Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
Postgres FD Implementation
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Abuhujair Javed
Postgres FD Implementation
Commits
52347b66
Commit
52347b66
authored
Jul 30, 2003
by
Tom Lane
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add pretty-printing variants of pg_get_viewdef and related functions.
Patch from Andreas Pflug.
parent
12911ea2
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
951 additions
and
193 deletions
+951
-193
doc/src/sgml/func.sgml
doc/src/sgml/func.sgml
+57
-6
src/backend/utils/adt/ruleutils.c
src/backend/utils/adt/ruleutils.c
+870
-183
src/include/catalog/catversion.h
src/include/catalog/catversion.h
+2
-2
src/include/catalog/pg_proc.h
src/include/catalog/pg_proc.h
+15
-1
src/include/utils/builtins.h
src/include/utils/builtins.h
+7
-1
No files found.
doc/src/sgml/func.sgml
View file @
52347b66
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/func.sgml,v 1.16
1 2003/07/29 00:03:17
tgl Exp $
$Header: /cvsroot/pgsql/doc/src/sgml/func.sgml,v 1.16
2 2003/07/30 22:56:23
tgl Exp $
PostgreSQL documentation
-->
...
...
@@ -6494,10 +6494,9 @@ SET search_path TO <replaceable>schema</> <optional>, <replaceable>schema</>, ..
<para>
The function <function>current_setting</function> yields the
current value of the setting <parameter>setting_name</parameter>,
as part of a query result. It corresponds to the
<acronym>SQL</acronym> command <command>SHOW</command>. An
example:
current value of the setting <parameter>setting_name</parameter>.
It corresponds to the <acronym>SQL</acronym> command
<command>SHOW</command>. An example:
<programlisting>
SELECT current_setting('datestyle');
...
...
@@ -6832,6 +6831,10 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
<primary>pg_get_constraintdef</primary>
</indexterm>
<indexterm zone="functions-misc">
<primary>pg_get_expr</primary>
</indexterm>
<indexterm zone="functions-misc">
<primary>pg_get_userbyid</primary>
</indexterm>
...
...
@@ -6846,7 +6849,16 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
<function>pg_get_constraintdef</function> respectively
reconstruct the creating command for a view, rule, index, or
constraint. (Note that this is a decompiled reconstruction, not
the verbatim text of the command.)
the original text of the command.) Most of these come in two
variants, one of which can optionally <quote>pretty-print</> the result.
The pretty-printed form is more readable but is less likely to be
interpreted the same way by future versions of <productname>PostgreSQL</>;
avoid using pretty-printed output for dump purposes.
Passing <literal>false</> for the pretty-print parameter yields the
same result as the variant that does not have the parameter at all.
<function>pg_get_expr</function> decompiles the internal form of an
individual expression, such as the default value for a column. It
may be useful when examining the contents of system catalogs.
<function>pg_get_userbyid</function>
extracts a user's name given a user ID number.
</para>
...
...
@@ -6864,21 +6876,43 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
<entry><type>text</type></entry>
<entry>get <command>CREATE VIEW</> command for view (<emphasis>deprecated</emphasis>)</entry>
</row>
<row>
<entry><literal><function>pg_get_viewdef</function>(<parameter>view_name</parameter>, <parameter>pretty_bool</>)</literal></entry>
<entry><type>text</type></entry>
<entry>get <command>CREATE VIEW</> command for view (<emphasis>deprecated</emphasis>)</entry>
</row>
<row>
<entry><literal><function>pg_get_viewdef</function>(<parameter>view_oid</parameter>)</literal></entry>
<entry><type>text</type></entry>
<entry>get <command>CREATE VIEW</> command for view</entry>
</row>
<row>
<entry><literal><function>pg_get_viewdef</function>(<parameter>view_oid</parameter>, <parameter>pretty_bool</>)</literal></entry>
<entry><type>text</type></entry>
<entry>get <command>CREATE VIEW</> command for view</entry>
</row>
<row>
<entry><literal><function>pg_get_ruledef</function>(<parameter>rule_oid</parameter>)</literal></entry>
<entry><type>text</type></entry>
<entry>get <command>CREATE RULE</> command for rule</entry>
</row>
<row>
<entry><literal><function>pg_get_ruledef</function>(<parameter>rule_oid</parameter>, <parameter>pretty_bool</>)</literal></entry>
<entry><type>text</type></entry>
<entry>get <command>CREATE RULE</> command for rule</entry>
</row>
<row>
<entry><literal><function>pg_get_indexdef</function>(<parameter>index_oid</parameter>)</literal></entry>
<entry><type>text</type></entry>
<entry>get <command>CREATE INDEX</> command for index</entry>
</row>
<row>
<entry><literal><function>pg_get_indexdef</function>(<parameter>index_oid</parameter>, <parameter>column_no</>, <parameter>pretty_bool</>)</literal></entry>
<entry><type>text</type></entry>
<entry>get <command>CREATE INDEX</> command for index,
or definition of just one index column when
<parameter>column_no</> is not zero</entry>
</row>
<row>
<entry><function>pg_get_triggerdef</function>(<parameter>trigger_oid</parameter>)</entry>
<entry><type>text</type></entry>
...
...
@@ -6889,6 +6923,23 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
<entry><type>text</type></entry>
<entry>get definition of a constraint</entry>
</row>
<row>
<entry><literal><function>pg_get_constraintdef</function>(<parameter>constraint_oid</parameter>, <parameter>pretty_bool</>)</literal></entry>
<entry><type>text</type></entry>
<entry>get definition of a constraint</entry>
</row>
<row>
<entry><literal><function>pg_get_expr</function>(<parameter>expr_text</parameter>, <parameter>relation_oid</>)</literal></entry>
<entry><type>text</type></entry>
<entry>decompile internal form of an expression, assuming that any Vars
in it refer to the relation indicated by the second parameter</entry>
</row>
<row>
<entry><literal><function>pg_get_expr</function>(<parameter>expr_text</parameter>, <parameter>relation_oid</>, <parameter>pretty_bool</>)</literal></entry>
<entry><type>text</type></entry>
<entry>decompile internal form of an expression, assuming that any Vars
in it refer to the relation indicated by the second parameter</entry>
</row>
<row>
<entry><literal><function>pg_get_userbyid</function>(<parameter>userid</parameter>)</literal></entry>
<entry><type>name</type></entry>
...
...
src/backend/utils/adt/ruleutils.c
View file @
52347b66
...
...
@@ -3,7 +3,7 @@
* back to source text
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.14
6 2003/07/27 04:53:09
tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.14
7 2003/07/30 22:56:23
tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
...
...
@@ -71,6 +71,26 @@
#include "utils/lsyscache.h"
/* ----------
* Pretty formatting constants
* ----------
*/
/* Indent counts */
#define PRETTYINDENT_STD 8
#define PRETTYINDENT_JOIN 13
#define PRETTYINDENT_JOIN_ON (PRETTYINDENT_JOIN-PRETTYINDENT_STD)
#define PRETTYINDENT_VAR 4
/* Pretty flags */
#define PRETTYFLAG_PAREN 1
#define PRETTYFLAG_INDENT 2
/* macro to test if pretty action needed */
#define PRETTY_PAREN(context) ((context)->prettyFlags & PRETTYFLAG_PAREN)
#define PRETTY_INDENT(context) ((context)->prettyFlags & PRETTYFLAG_INDENT)
/* ----------
* Local data types
* ----------
...
...
@@ -81,6 +101,8 @@ typedef struct
{
StringInfo
buf
;
/* output buffer to append to */
List
*
namespaces
;
/* List of deparse_namespace nodes */
int
prettyFlags
;
/* enabling of pretty-print functions */
int
indentLevel
;
/* current indent level for prettyprint */
bool
varprefix
;
/* TRUE to print prefixes on Vars */
}
deparse_context
;
...
...
@@ -123,13 +145,24 @@ static char *query_getviewrule = "SELECT * FROM pg_catalog.pg_rewrite WHERE ev_c
* as a parameter, and append their text output to its contents.
* ----------
*/
static
text
*
pg_do_getviewdef
(
Oid
viewoid
);
static
char
*
deparse_expression_pretty
(
Node
*
expr
,
List
*
dpcontext
,
bool
forceprefix
,
bool
showimplicit
,
int
prettyFlags
,
int
startIndent
);
static
text
*
pg_do_getviewdef
(
Oid
viewoid
,
int
prettyFlags
);
static
void
decompile_column_index_array
(
Datum
column_index_array
,
Oid
relId
,
StringInfo
buf
);
static
void
make_ruledef
(
StringInfo
buf
,
HeapTuple
ruletup
,
TupleDesc
rulettc
);
static
void
make_viewdef
(
StringInfo
buf
,
HeapTuple
ruletup
,
TupleDesc
rulettc
);
static
Datum
pg_get_ruledef_worker
(
Oid
ruleoid
,
int
prettyFlags
);
static
Datum
pg_get_indexdef_worker
(
Oid
indexrelid
,
int
colno
,
int
prettyFlags
);
static
Datum
pg_get_constraintdef_worker
(
Oid
constraintId
,
int
prettyFlags
);
static
Datum
pg_get_expr_worker
(
text
*
expr
,
Oid
relid
,
char
*
relname
,
int
prettyFlags
);
static
void
make_ruledef
(
StringInfo
buf
,
HeapTuple
ruletup
,
TupleDesc
rulettc
,
int
prettyFlags
);
static
void
make_viewdef
(
StringInfo
buf
,
HeapTuple
ruletup
,
TupleDesc
rulettc
,
int
prettyFlags
);
static
void
get_query_def
(
Query
*
query
,
StringInfo
buf
,
List
*
parentnamespace
,
TupleDesc
resultDesc
);
TupleDesc
resultDesc
,
int
prettyFlags
,
int
startIndent
);
static
void
get_select_query_def
(
Query
*
query
,
deparse_context
*
context
,
TupleDesc
resultDesc
);
static
void
get_insert_query_def
(
Query
*
query
,
deparse_context
*
context
);
...
...
@@ -148,6 +181,11 @@ static void get_names_for_var(Var *var, deparse_context *context,
char
**
schemaname
,
char
**
refname
,
char
**
attname
);
static
RangeTblEntry
*
find_rte_by_refname
(
const
char
*
refname
,
deparse_context
*
context
);
static
const
char
*
get_simple_binary_op_name
(
OpExpr
*
expr
);
static
bool
isSimpleNode
(
Node
*
node
,
Node
*
parentNode
,
int
prettyFlags
);
static
void
appendStringInfoSpaces
(
StringInfo
buf
,
int
count
);
static
void
appendContextKeyword
(
deparse_context
*
context
,
const
char
*
str
,
int
indentBefore
,
int
indentAfter
,
int
indentPlus
);
static
void
get_rule_expr
(
Node
*
node
,
deparse_context
*
context
,
bool
showimplicit
);
static
void
get_oper_expr
(
OpExpr
*
expr
,
deparse_context
*
context
);
...
...
@@ -184,6 +222,26 @@ Datum
pg_get_ruledef
(
PG_FUNCTION_ARGS
)
{
Oid
ruleoid
=
PG_GETARG_OID
(
0
);
return
pg_get_ruledef_worker
(
ruleoid
,
0
);
}
Datum
pg_get_ruledef_ext
(
PG_FUNCTION_ARGS
)
{
Oid
ruleoid
=
PG_GETARG_OID
(
0
);
bool
pretty
=
PG_GETARG_BOOL
(
1
);
int
prettyFlags
;
prettyFlags
=
pretty
?
PRETTYFLAG_PAREN
|
PRETTYFLAG_INDENT
:
0
;
return
pg_get_ruledef_worker
(
ruleoid
,
prettyFlags
);
}
static
Datum
pg_get_ruledef_worker
(
Oid
ruleoid
,
int
prettyFlags
)
{
text
*
ruledef
;
Datum
args
[
1
];
char
nulls
[
1
];
...
...
@@ -241,7 +299,7 @@ pg_get_ruledef(PG_FUNCTION_ARGS)
* Get the rules definition and put it into executors memory
*/
initStringInfo
(
&
buf
);
make_ruledef
(
&
buf
,
ruletup
,
rulettc
);
make_ruledef
(
&
buf
,
ruletup
,
rulettc
,
prettyFlags
);
len
=
buf
.
len
+
VARHDRSZ
;
ruledef
=
SPI_palloc
(
len
);
VARATT_SIZEP
(
ruledef
)
=
len
;
...
...
@@ -273,7 +331,22 @@ pg_get_viewdef(PG_FUNCTION_ARGS)
Oid
viewoid
=
PG_GETARG_OID
(
0
);
text
*
ruledef
;
ruledef
=
pg_do_getviewdef
(
viewoid
);
ruledef
=
pg_do_getviewdef
(
viewoid
,
0
);
PG_RETURN_TEXT_P
(
ruledef
);
}
Datum
pg_get_viewdef_ext
(
PG_FUNCTION_ARGS
)
{
/* By OID */
Oid
viewoid
=
PG_GETARG_OID
(
0
);
bool
pretty
=
PG_GETARG_BOOL
(
1
);
text
*
ruledef
;
int
prettyFlags
;
prettyFlags
=
pretty
?
PRETTYFLAG_PAREN
|
PRETTYFLAG_INDENT
:
0
;
ruledef
=
pg_do_getviewdef
(
viewoid
,
prettyFlags
);
PG_RETURN_TEXT_P
(
ruledef
);
}
...
...
@@ -290,7 +363,28 @@ pg_get_viewdef_name(PG_FUNCTION_ARGS)
"get_viewdef"
));
viewoid
=
RangeVarGetRelid
(
viewrel
,
false
);
ruledef
=
pg_do_getviewdef
(
viewoid
);
ruledef
=
pg_do_getviewdef
(
viewoid
,
0
);
PG_RETURN_TEXT_P
(
ruledef
);
}
Datum
pg_get_viewdef_name_ext
(
PG_FUNCTION_ARGS
)
{
/* By qualified name */
text
*
viewname
=
PG_GETARG_TEXT_P
(
0
);
bool
pretty
=
PG_GETARG_BOOL
(
1
);
int
prettyFlags
;
RangeVar
*
viewrel
;
Oid
viewoid
;
text
*
ruledef
;
prettyFlags
=
pretty
?
PRETTYFLAG_PAREN
|
PRETTYFLAG_INDENT
:
0
;
viewrel
=
makeRangeVarFromNameList
(
textToQualifiedNameList
(
viewname
,
"get_viewdef"
));
viewoid
=
RangeVarGetRelid
(
viewrel
,
false
);
ruledef
=
pg_do_getviewdef
(
viewoid
,
prettyFlags
);
PG_RETURN_TEXT_P
(
ruledef
);
}
...
...
@@ -298,7 +392,7 @@ pg_get_viewdef_name(PG_FUNCTION_ARGS)
* Common code for by-OID and by-name variants of pg_get_viewdef
*/
static
text
*
pg_do_getviewdef
(
Oid
viewoid
)
pg_do_getviewdef
(
Oid
viewoid
,
int
prettyFlags
)
{
text
*
ruledef
;
Datum
args
[
2
];
...
...
@@ -353,7 +447,7 @@ pg_do_getviewdef(Oid viewoid)
*/
ruletup
=
SPI_tuptable
->
vals
[
0
];
rulettc
=
SPI_tuptable
->
tupdesc
;
make_viewdef
(
&
buf
,
ruletup
,
rulettc
);
make_viewdef
(
&
buf
,
ruletup
,
rulettc
,
prettyFlags
);
}
len
=
buf
.
len
+
VARHDRSZ
;
ruledef
=
SPI_palloc
(
len
);
...
...
@@ -521,12 +615,35 @@ pg_get_triggerdef(PG_FUNCTION_ARGS)
/* ----------
* get_indexdef - Get the definition of an index
*
* In the extended version, there is a colno argument as well as pretty bool.
* if colno == 0, we want a complete index definition.
* if colno > 0, we only want the Nth index key's variable or expression.
* ----------
*/
Datum
pg_get_indexdef
(
PG_FUNCTION_ARGS
)
{
Oid
indexrelid
=
PG_GETARG_OID
(
0
);
return
pg_get_indexdef_worker
(
indexrelid
,
0
,
0
);
}
Datum
pg_get_indexdef_ext
(
PG_FUNCTION_ARGS
)
{
Oid
indexrelid
=
PG_GETARG_OID
(
0
);
int32
colno
=
PG_GETARG_INT32
(
1
);
bool
pretty
=
PG_GETARG_BOOL
(
2
);
int
prettyFlags
;
prettyFlags
=
pretty
?
PRETTYFLAG_PAREN
|
PRETTYFLAG_INDENT
:
0
;
return
pg_get_indexdef_worker
(
indexrelid
,
colno
,
prettyFlags
);
}
static
Datum
pg_get_indexdef_worker
(
Oid
indexrelid
,
int
colno
,
int
prettyFlags
)
{
text
*
indexdef
;
HeapTuple
ht_idx
;
HeapTuple
ht_idxrel
;
...
...
@@ -607,7 +724,9 @@ pg_get_indexdef(PG_FUNCTION_ARGS)
* never be schema-qualified, but the indexed rel's name may be.
*/
initStringInfo
(
&
buf
);
appendStringInfo
(
&
buf
,
"CREATE %sINDEX %s ON %s USING %s ("
,
if
(
!
colno
)
appendStringInfo
(
&
buf
,
"CREATE %sINDEX %s ON %s USING %s ("
,
idxrec
->
indisunique
?
"UNIQUE "
:
""
,
quote_identifier
(
NameStr
(
idxrelrec
->
relname
)),
generate_relation_name
(
indrelid
),
...
...
@@ -621,7 +740,8 @@ pg_get_indexdef(PG_FUNCTION_ARGS)
{
AttrNumber
attnum
=
idxrec
->
indkey
[
keyno
];
appendStringInfo
(
&
buf
,
sep
);
if
(
!
colno
)
appendStringInfo
(
&
buf
,
sep
);
sep
=
", "
;
if
(
attnum
!=
0
)
...
...
@@ -630,7 +750,8 @@ pg_get_indexdef(PG_FUNCTION_ARGS)
char
*
attname
;
attname
=
get_relid_attribute_name
(
indrelid
,
attnum
);
appendStringInfo
(
&
buf
,
"%s"
,
quote_identifier
(
attname
));
if
(
!
colno
||
colno
==
keyno
+
1
)
appendStringInfo
(
&
buf
,
"%s"
,
quote_identifier
(
attname
));
keycoltype
=
get_atttype
(
indrelid
,
attnum
);
}
else
...
...
@@ -643,54 +764,63 @@ pg_get_indexdef(PG_FUNCTION_ARGS)
indexkey
=
(
Node
*
)
lfirst
(
indexprs
);
indexprs
=
lnext
(
indexprs
);
/* Deparse */
str
=
deparse_expression
(
indexkey
,
context
,
false
,
false
);
/* Need parens if it's not a bare function call */
if
(
indexkey
&&
IsA
(
indexkey
,
FuncExpr
)
&&
((
FuncExpr
*
)
indexkey
)
->
funcformat
==
COERCE_EXPLICIT_CALL
)
appendStringInfo
(
&
buf
,
"%s"
,
str
);
else
appendStringInfo
(
&
buf
,
"(%s)"
,
str
);
str
=
deparse_expression_pretty
(
indexkey
,
context
,
false
,
false
,
prettyFlags
,
0
);
if
(
!
colno
||
colno
==
keyno
+
1
)
{
/* Need parens if it's not a bare function call */
if
(
indexkey
&&
IsA
(
indexkey
,
FuncExpr
)
&&
((
FuncExpr
*
)
indexkey
)
->
funcformat
==
COERCE_EXPLICIT_CALL
)
appendStringInfo
(
&
buf
,
"%s"
,
str
);
else
appendStringInfo
(
&
buf
,
"(%s)"
,
str
);
}
keycoltype
=
exprType
(
indexkey
);
}
/*
* Add the operator class name
*/
get_opclass_name
(
idxrec
->
indclass
[
keyno
],
keycoltype
,
if
(
!
colno
)
get_opclass_name
(
idxrec
->
indclass
[
keyno
],
keycoltype
,
&
buf
);
}
appendStringInfoChar
(
&
buf
,
')'
);
/*
* If it's a partial index, decompile and append the predicate
*/
if
(
!
heap_attisnull
(
ht_idx
,
Anum_pg_index_indpred
))
if
(
!
colno
)
{
Node
*
node
;
Datum
predDatum
;
bool
isnull
;
char
*
predString
;
appendStringInfoChar
(
&
buf
,
')'
);
/*
* If it's a partial index, decompile and append the predicate
*/
if
(
!
heap_attisnull
(
ht_idx
,
Anum_pg_index_indpred
))
{
Node
*
node
;
Datum
predDatum
;
bool
isnull
;
char
*
predString
;
/* Convert text string to node tree */
predDatum
=
SysCacheGetAttr
(
INDEXRELID
,
ht_idx
,
Anum_pg_index_indpred
,
&
isnull
);
Assert
(
!
isnull
);
predString
=
DatumGetCString
(
DirectFunctionCall1
(
textout
,
predDatum
));
node
=
(
Node
*
)
stringToNode
(
predString
);
pfree
(
predString
);
/* Convert text string to node tree */
predDatum
=
SysCacheGetAttr
(
INDEXRELID
,
ht_idx
,
Anum_pg_index_indpred
,
&
isnull
);
Assert
(
!
isnull
);
predString
=
DatumGetCString
(
DirectFunctionCall1
(
textout
,
predDatum
));
node
=
(
Node
*
)
stringToNode
(
predString
);
pfree
(
predString
);
/*
* If top level is a List, assume it is an implicit-AND structure,
* and convert to explicit AND. This is needed for partial index
* predicates.
*/
if
(
node
&&
IsA
(
node
,
List
))
node
=
(
Node
*
)
make_ands_explicit
((
List
*
)
node
);
/* Deparse */
str
=
deparse_expression
(
node
,
context
,
false
,
false
);
appendStringInfo
(
&
buf
,
" WHERE %s"
,
str
);
/*
* If top level is a List, assume it is an implicit-AND structure,
* and convert to explicit AND. This is needed for partial index
* predicates.
*/
if
(
node
&&
IsA
(
node
,
List
))
node
=
(
Node
*
)
make_ands_explicit
((
List
*
)
node
);
/* Deparse */
str
=
deparse_expression_pretty
(
node
,
context
,
false
,
false
,
prettyFlags
,
0
);
appendStringInfo
(
&
buf
,
" WHERE %s"
,
str
);
}
}
/*
...
...
@@ -721,6 +851,25 @@ Datum
pg_get_constraintdef
(
PG_FUNCTION_ARGS
)
{
Oid
constraintId
=
PG_GETARG_OID
(
0
);
return
pg_get_constraintdef_worker
(
constraintId
,
0
);
}
Datum
pg_get_constraintdef_ext
(
PG_FUNCTION_ARGS
)
{
Oid
constraintId
=
PG_GETARG_OID
(
0
);
bool
pretty
=
PG_GETARG_BOOL
(
1
);
int
prettyFlags
;
prettyFlags
=
pretty
?
PRETTYFLAG_PAREN
|
PRETTYFLAG_INDENT
:
0
;
return
pg_get_constraintdef_worker
(
constraintId
,
prettyFlags
);
}
static
Datum
pg_get_constraintdef_worker
(
Oid
constraintId
,
int
prettyFlags
)
{
text
*
result
;
StringInfoData
buf
;
int
len
;
...
...
@@ -934,7 +1083,8 @@ pg_get_constraintdef(PG_FUNCTION_ARGS)
context
=
deparse_context_for
(
get_typname
(
conForm
->
contypid
),
InvalidOid
);
consrc
=
deparse_expression
(
expr
,
context
,
false
,
false
);
consrc
=
deparse_expression_pretty
(
expr
,
context
,
false
,
false
,
prettyFlags
,
0
);
/* Append the constraint source */
appendStringInfoString
(
&
buf
,
consrc
);
...
...
@@ -1012,20 +1162,46 @@ decompile_column_index_array(Datum column_index_array, Oid relId,
Datum
pg_get_expr
(
PG_FUNCTION_ARGS
)
{
text
*
expr
=
PG_GETARG_TEXT_P
(
0
);
Oid
relid
=
PG_GETARG_OID
(
1
);
text
*
result
;
Node
*
node
;
List
*
context
;
char
*
exprstr
;
text
*
expr
=
PG_GETARG_TEXT_P
(
0
);
Oid
relid
=
PG_GETARG_OID
(
1
);
char
*
relname
;
char
*
str
;
/* Get the name for the relation */
relname
=
get_rel_name
(
relid
);
if
(
relname
==
NULL
)
PG_RETURN_NULL
();
/* should we raise an error? */
return
pg_get_expr_worker
(
expr
,
relid
,
relname
,
0
);
}
Datum
pg_get_expr_ext
(
PG_FUNCTION_ARGS
)
{
text
*
expr
=
PG_GETARG_TEXT_P
(
0
);
Oid
relid
=
PG_GETARG_OID
(
1
);
bool
pretty
=
PG_GETARG_BOOL
(
2
);
int
prettyFlags
;
char
*
relname
;
prettyFlags
=
pretty
?
PRETTYFLAG_PAREN
|
PRETTYFLAG_INDENT
:
0
;
/* Get the name for the relation */
relname
=
get_rel_name
(
relid
);
if
(
relname
==
NULL
)
PG_RETURN_NULL
();
/* should we raise an error? */
return
pg_get_expr_worker
(
expr
,
relid
,
relname
,
prettyFlags
);
}
static
Datum
pg_get_expr_worker
(
text
*
expr
,
Oid
relid
,
char
*
relname
,
int
prettyFlags
)
{
text
*
result
;
Node
*
node
;
List
*
context
;
char
*
exprstr
;
char
*
str
;
/* Convert input TEXT object to C string */
exprstr
=
DatumGetCString
(
DirectFunctionCall1
(
textout
,
PointerGetDatum
(
expr
)));
...
...
@@ -1043,7 +1219,8 @@ pg_get_expr(PG_FUNCTION_ARGS)
/* Deparse */
context
=
deparse_context_for
(
relname
,
relid
);
str
=
deparse_expression
(
node
,
context
,
false
,
false
);
str
=
deparse_expression_pretty
(
node
,
context
,
false
,
false
,
prettyFlags
,
0
);
/* Pass the result back as TEXT */
result
=
DatumGetTextP
(
DirectFunctionCall1
(
textin
,
...
...
@@ -1093,6 +1270,19 @@ pg_get_userbyid(PG_FUNCTION_ARGS)
/* ----------
* deparse_expression - General utility for deparsing expressions
*
* calls deparse_expression_pretty with all prettyPrinting disabled
*/
char
*
deparse_expression
(
Node
*
expr
,
List
*
dpcontext
,
bool
forceprefix
,
bool
showimplicit
)
{
return
deparse_expression_pretty
(
expr
,
dpcontext
,
forceprefix
,
showimplicit
,
0
,
0
);
}
/* ----------
* deparse_expression_pretty - General utility for deparsing expressions
*
* expr is the node tree to be deparsed. It must be a transformed expression
* tree (ie, not the raw output of gram.y).
*
...
...
@@ -1102,13 +1292,16 @@ pg_get_userbyid(PG_FUNCTION_ARGS)
* forceprefix is TRUE to force all Vars to be prefixed with their table names.
*
* showimplicit is TRUE to force all implicit casts to be shown explicitly.
*
* tries to pretty up the output according to prettyFlags and startIndent.
*
* The result is a palloc'd string.
* ----------
*/
char
*
deparse_expression
(
Node
*
expr
,
List
*
dpcontext
,
bool
forceprefix
,
bool
showimplicit
)
deparse_expression_pretty
(
Node
*
expr
,
List
*
dpcontext
,
bool
forceprefix
,
bool
showimplicit
,
int
prettyFlags
,
int
startIndent
)
{
StringInfoData
buf
;
deparse_context
context
;
...
...
@@ -1117,6 +1310,8 @@ deparse_expression(Node *expr, List *dpcontext,
context
.
buf
=
&
buf
;
context
.
namespaces
=
dpcontext
;
context
.
varprefix
=
forceprefix
;
context
.
prettyFlags
=
prettyFlags
;
context
.
indentLevel
=
startIndent
;
get_rule_expr
(
expr
,
&
context
,
showimplicit
);
...
...
@@ -1269,7 +1464,8 @@ deparse_context_for_subplan(const char *name, List *tlist,
* ----------
*/
static
void
make_ruledef
(
StringInfo
buf
,
HeapTuple
ruletup
,
TupleDesc
rulettc
)
make_ruledef
(
StringInfo
buf
,
HeapTuple
ruletup
,
TupleDesc
rulettc
,
int
prettyFlags
)
{
char
*
rulename
;
char
ev_type
;
...
...
@@ -1323,9 +1519,14 @@ make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc)
/*
* Build the rules definition text
*/
appendStringInfo
(
buf
,
"CREATE RULE %s AS
ON
"
,
appendStringInfo
(
buf
,
"CREATE RULE %s AS"
,
quote_identifier
(
rulename
));
if
(
prettyFlags
&
PRETTYFLAG_INDENT
)
appendStringInfoString
(
buf
,
"
\n
ON "
);
else
appendStringInfoString
(
buf
,
" ON "
);
/* The event the rule is fired for */
switch
(
ev_type
)
{
...
...
@@ -1370,6 +1571,8 @@ make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc)
deparse_context
context
;
deparse_namespace
dpns
;
if
(
prettyFlags
&
PRETTYFLAG_INDENT
)
appendStringInfoString
(
buf
,
"
\n
"
);
appendStringInfo
(
buf
,
" WHERE "
);
qual
=
stringToNode
(
ev_qual
);
...
...
@@ -1391,6 +1594,8 @@ make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc)
context
.
buf
=
buf
;
context
.
namespaces
=
makeList1
(
&
dpns
);
context
.
varprefix
=
(
length
(
query
->
rtable
)
!=
1
);
context
.
prettyFlags
=
prettyFlags
;
context
.
indentLevel
=
PRETTYINDENT_STD
;
dpns
.
rtable
=
query
->
rtable
;
dpns
.
outer_varno
=
dpns
.
inner_varno
=
0
;
dpns
.
outer_rte
=
dpns
.
inner_rte
=
NULL
;
...
...
@@ -1414,8 +1619,11 @@ make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc)
foreach
(
action
,
actions
)
{
query
=
(
Query
*
)
lfirst
(
action
);
get_query_def
(
query
,
buf
,
NIL
,
NULL
);
appendStringInfo
(
buf
,
"; "
);
get_query_def
(
query
,
buf
,
NIL
,
NULL
,
prettyFlags
,
0
);
if
(
prettyFlags
)
appendStringInfo
(
buf
,
";
\n
"
);
else
appendStringInfo
(
buf
,
"; "
);
}
appendStringInfo
(
buf
,
");"
);
}
...
...
@@ -1428,7 +1636,7 @@ make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc)
Query
*
query
;
query
=
(
Query
*
)
lfirst
(
actions
);
get_query_def
(
query
,
buf
,
NIL
,
NULL
);
get_query_def
(
query
,
buf
,
NIL
,
NULL
,
prettyFlags
,
0
);
appendStringInfo
(
buf
,
";"
);
}
}
...
...
@@ -1440,7 +1648,8 @@ make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc)
* ----------
*/
static
void
make_viewdef
(
StringInfo
buf
,
HeapTuple
ruletup
,
TupleDesc
rulettc
)
make_viewdef
(
StringInfo
buf
,
HeapTuple
ruletup
,
TupleDesc
rulettc
,
int
prettyFlags
)
{
Query
*
query
;
char
ev_type
;
...
...
@@ -1494,7 +1703,8 @@ make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc)
ev_relation
=
heap_open
(
ev_class
,
AccessShareLock
);
get_query_def
(
query
,
buf
,
NIL
,
RelationGetDescr
(
ev_relation
));
get_query_def
(
query
,
buf
,
NIL
,
RelationGetDescr
(
ev_relation
),
prettyFlags
,
0
);
appendStringInfo
(
buf
,
";"
);
heap_close
(
ev_relation
,
AccessShareLock
);
...
...
@@ -1510,7 +1720,7 @@ make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc)
*/
static
void
get_query_def
(
Query
*
query
,
StringInfo
buf
,
List
*
parentnamespace
,
TupleDesc
resultDesc
)
TupleDesc
resultDesc
,
int
prettyFlags
,
int
startIndent
)
{
deparse_context
context
;
deparse_namespace
dpns
;
...
...
@@ -1519,6 +1729,9 @@ get_query_def(Query *query, StringInfo buf, List *parentnamespace,
context
.
namespaces
=
lcons
(
&
dpns
,
parentnamespace
);
context
.
varprefix
=
(
parentnamespace
!=
NIL
||
length
(
query
->
rtable
)
!=
1
);
context
.
prettyFlags
=
prettyFlags
;
context
.
indentLevel
=
startIndent
;
dpns
.
rtable
=
query
->
rtable
;
dpns
.
outer_varno
=
dpns
.
inner_varno
=
0
;
dpns
.
outer_rte
=
dpns
.
inner_rte
=
NULL
;
...
...
@@ -1590,7 +1803,8 @@ get_select_query_def(Query *query, deparse_context *context,
/* Add the ORDER BY clause if given */
if
(
query
->
sortClause
!=
NIL
)
{
appendStringInfo
(
buf
,
" ORDER BY "
);
appendContextKeyword
(
context
,
" ORDER BY "
,
-
PRETTYINDENT_STD
,
PRETTYINDENT_STD
,
1
);
sep
=
""
;
foreach
(
l
,
query
->
sortClause
)
{
...
...
@@ -1619,12 +1833,14 @@ get_select_query_def(Query *query, deparse_context *context,
/* Add the LIMIT clause if given */
if
(
query
->
limitOffset
!=
NULL
)
{
appendStringInfo
(
buf
,
" OFFSET "
);
appendContextKeyword
(
context
,
" OFFSET "
,
-
PRETTYINDENT_STD
,
PRETTYINDENT_STD
,
0
);
get_rule_expr
(
query
->
limitOffset
,
context
,
false
);
}
if
(
query
->
limitCount
!=
NULL
)
{
appendStringInfo
(
buf
,
" LIMIT "
);
appendContextKeyword
(
context
,
" LIMIT "
,
-
PRETTYINDENT_STD
,
PRETTYINDENT_STD
,
0
);
if
(
IsA
(
query
->
limitCount
,
Const
)
&&
((
Const
*
)
query
->
limitCount
)
->
constisnull
)
appendStringInfo
(
buf
,
"ALL"
);
...
...
@@ -1645,6 +1861,11 @@ get_basic_select_query(Query *query, deparse_context *context,
/*
* Build up the query string - first we say SELECT
*/
if
(
PRETTY_INDENT
(
context
))
{
context
->
indentLevel
+=
PRETTYINDENT_STD
;
appendStringInfoChar
(
buf
,
' '
);
}
appendStringInfo
(
buf
,
"SELECT"
);
/* Add the DISTINCT clause if given */
...
...
@@ -1724,14 +1945,16 @@ get_basic_select_query(Query *query, deparse_context *context,
/* Add the WHERE clause if given */
if
(
query
->
jointree
->
quals
!=
NULL
)
{
appendStringInfo
(
buf
,
" WHERE "
);
appendContextKeyword
(
context
,
" WHERE "
,
-
PRETTYINDENT_STD
,
PRETTYINDENT_STD
,
1
);
get_rule_expr
(
query
->
jointree
->
quals
,
context
,
false
);
}
/* Add the GROUP BY clause if given */
if
(
query
->
groupClause
!=
NULL
)
{
appendStringInfo
(
buf
,
" GROUP BY "
);
appendContextKeyword
(
context
,
" GROUP BY "
,
-
PRETTYINDENT_STD
,
PRETTYINDENT_STD
,
1
);
sep
=
""
;
foreach
(
l
,
query
->
groupClause
)
{
...
...
@@ -1747,7 +1970,8 @@ get_basic_select_query(Query *query, deparse_context *context,
/* Add the HAVING clause if given */
if
(
query
->
havingQual
!=
NULL
)
{
appendStringInfo
(
buf
,
" HAVING "
);
appendContextKeyword
(
context
,
" HAVING "
,
-
PRETTYINDENT_STD
,
PRETTYINDENT_STD
,
0
);
get_rule_expr
(
query
->
havingQual
,
context
,
false
);
}
}
...
...
@@ -1765,35 +1989,71 @@ get_setop_query(Node *setOp, Query *query, deparse_context *context,
Query
*
subquery
=
rte
->
subquery
;
Assert
(
subquery
!=
NULL
);
get_query_def
(
subquery
,
buf
,
context
->
namespaces
,
resultDesc
);
get_query_def
(
subquery
,
buf
,
context
->
namespaces
,
resultDesc
,
context
->
prettyFlags
,
context
->
indentLevel
);
}
else
if
(
IsA
(
setOp
,
SetOperationStmt
))
{
SetOperationStmt
*
op
=
(
SetOperationStmt
*
)
setOp
;
bool
need_paren
;
need_paren
=
(
PRETTY_PAREN
(
context
)
?
!
IsA
(
op
->
rarg
,
RangeTblRef
)
:
true
);
if
(
!
PRETTY_PAREN
(
context
))
appendStringInfoString
(
buf
,
"(("
);
appendStringInfo
(
buf
,
"(("
);
get_setop_query
(
op
->
larg
,
query
,
context
,
resultDesc
);
if
(
!
PRETTY_PAREN
(
context
))
appendStringInfoChar
(
buf
,
')'
);
if
(
!
PRETTY_INDENT
(
context
))
appendStringInfoChar
(
buf
,
' '
);
switch
(
op
->
op
)
{
case
SETOP_UNION
:
appendStringInfo
(
buf
,
") UNION "
);
appendContextKeyword
(
context
,
"UNION "
,
-
PRETTYINDENT_STD
,
0
,
0
);
break
;
case
SETOP_INTERSECT
:
appendStringInfo
(
buf
,
") INTERSECT "
);
appendContextKeyword
(
context
,
"INTERSECT "
,
-
PRETTYINDENT_STD
,
0
,
0
);
break
;
case
SETOP_EXCEPT
:
appendStringInfo
(
buf
,
") EXCEPT "
);
appendContextKeyword
(
context
,
"EXCEPT "
,
-
PRETTYINDENT_STD
,
0
,
0
);
break
;
default:
elog
(
ERROR
,
"unrecognized set op: %d"
,
(
int
)
op
->
op
);
}
if
(
op
->
all
)
appendStringInfo
(
buf
,
"ALL ("
);
appendStringInfo
(
buf
,
"ALL "
);
if
(
PRETTY_INDENT
(
context
))
appendStringInfoChar
(
buf
,
'\n'
);
if
(
PRETTY_PAREN
(
context
))
{
if
(
need_paren
)
{
appendStringInfoChar
(
buf
,
'('
);
if
(
PRETTY_INDENT
(
context
))
appendStringInfoChar
(
buf
,
'\n'
);
}
}
else
appendStringInfo
(
buf
,
"("
);
appendStringInfoChar
(
buf
,
'('
);
get_setop_query
(
op
->
rarg
,
query
,
context
,
resultDesc
);
appendStringInfo
(
buf
,
"))"
);
if
(
PRETTY_PAREN
(
context
))
{
if
(
need_paren
)
appendStringInfoChar
(
buf
,
')'
);
}
else
appendStringInfoString
(
buf
,
"))"
);
}
else
{
...
...
@@ -1866,6 +2126,12 @@ get_insert_query_def(Query *query, deparse_context *context)
*/
rte
=
rt_fetch
(
query
->
resultRelation
,
query
->
rtable
);
Assert
(
rte
->
rtekind
==
RTE_RELATION
);
if
(
PRETTY_INDENT
(
context
))
{
context
->
indentLevel
+=
PRETTYINDENT_STD
;
appendStringInfoChar
(
buf
,
' '
);
}
appendStringInfo
(
buf
,
"INSERT INTO %s"
,
generate_relation_name
(
rte
->
relid
));
...
...
@@ -1887,7 +2153,8 @@ get_insert_query_def(Query *query, deparse_context *context)
/* Add the VALUES or the SELECT */
if
(
select_rte
==
NULL
)
{
appendStringInfo
(
buf
,
"VALUES ("
);
appendContextKeyword
(
context
,
"VALUES ("
,
-
PRETTYINDENT_STD
,
PRETTYINDENT_STD
,
2
);
sep
=
""
;
foreach
(
l
,
query
->
targetList
)
{
...
...
@@ -1903,7 +2170,8 @@ get_insert_query_def(Query *query, deparse_context *context)
appendStringInfoChar
(
buf
,
')'
);
}
else
get_query_def
(
select_rte
->
subquery
,
buf
,
NIL
,
NULL
);
get_query_def
(
select_rte
->
subquery
,
buf
,
NIL
,
NULL
,
context
->
prettyFlags
,
context
->
indentLevel
);
}
...
...
@@ -1924,6 +2192,11 @@ get_update_query_def(Query *query, deparse_context *context)
*/
rte
=
rt_fetch
(
query
->
resultRelation
,
query
->
rtable
);
Assert
(
rte
->
rtekind
==
RTE_RELATION
);
if
(
PRETTY_INDENT
(
context
))
{
appendStringInfoChar
(
buf
,
' '
);
context
->
indentLevel
+=
PRETTYINDENT_STD
;
}
appendStringInfo
(
buf
,
"UPDATE %s%s SET "
,
only_marker
(
rte
),
generate_relation_name
(
rte
->
relid
));
...
...
@@ -1957,7 +2230,8 @@ get_update_query_def(Query *query, deparse_context *context)
/* Finally add a WHERE clause if given */
if
(
query
->
jointree
->
quals
!=
NULL
)
{
appendStringInfo
(
buf
,
" WHERE "
);
appendContextKeyword
(
context
,
" WHERE "
,
-
PRETTYINDENT_STD
,
PRETTYINDENT_STD
,
1
);
get_rule_expr
(
query
->
jointree
->
quals
,
context
,
false
);
}
}
...
...
@@ -1978,6 +2252,11 @@ get_delete_query_def(Query *query, deparse_context *context)
*/
rte
=
rt_fetch
(
query
->
resultRelation
,
query
->
rtable
);
Assert
(
rte
->
rtekind
==
RTE_RELATION
);
if
(
PRETTY_INDENT
(
context
))
{
context
->
indentLevel
+=
PRETTYINDENT_STD
;
appendStringInfoChar
(
buf
,
' '
);
}
appendStringInfo
(
buf
,
"DELETE FROM %s%s"
,
only_marker
(
rte
),
generate_relation_name
(
rte
->
relid
));
...
...
@@ -1985,7 +2264,8 @@ get_delete_query_def(Query *query, deparse_context *context)
/* Add a WHERE clause if given */
if
(
query
->
jointree
->
quals
!=
NULL
)
{
appendStringInfo
(
buf
,
" WHERE "
);
appendContextKeyword
(
context
,
" WHERE "
,
-
PRETTYINDENT_STD
,
PRETTYINDENT_STD
,
1
);
get_rule_expr
(
query
->
jointree
->
quals
,
context
,
false
);
}
}
...
...
@@ -2004,6 +2284,8 @@ get_utility_query_def(Query *query, deparse_context *context)
{
NotifyStmt
*
stmt
=
(
NotifyStmt
*
)
query
->
utilityStmt
;
appendContextKeyword
(
context
,
""
,
0
,
PRETTYINDENT_STD
,
1
);
appendStringInfo
(
buf
,
"NOTIFY %s"
,
quote_qualified_identifier
(
stmt
->
relation
->
schemaname
,
stmt
->
relation
->
relname
));
...
...
@@ -2145,6 +2427,285 @@ find_rte_by_refname(const char *refname, deparse_context *context)
}
/*
* get_simple_binary_op_name
*
* helper function for isSimpleNode
* will return single char binary operator name, or NULL if it's not
*/
static
const
char
*
get_simple_binary_op_name
(
OpExpr
*
expr
)
{
List
*
args
=
expr
->
args
;
if
(
length
(
args
)
==
2
)
{
/* binary operator */
Node
*
arg1
=
(
Node
*
)
lfirst
(
args
);
Node
*
arg2
=
(
Node
*
)
lsecond
(
args
);
const
char
*
op
;
op
=
generate_operator_name
(
expr
->
opno
,
exprType
(
arg1
),
exprType
(
arg2
));
if
(
strlen
(
op
)
==
1
)
return
op
;
}
return
NULL
;
}
/*
* isSimpleNode - check if given node is simple (doesn't need parenthesizing)
*
* true : simple in the context of parent node's type
* false : not simple
*/
static
bool
isSimpleNode
(
Node
*
node
,
Node
*
parentNode
,
int
prettyFlags
)
{
if
(
!
node
)
return
false
;
switch
(
nodeTag
(
node
))
{
case
T_Var
:
case
T_Const
:
case
T_Param
:
case
T_CoerceToDomainValue
:
case
T_SetToDefault
:
/* single words: always simple */
return
true
;
case
T_ArrayRef
:
case
T_ArrayExpr
:
case
T_CoalesceExpr
:
case
T_NullIfExpr
:
case
T_Aggref
:
case
T_FuncExpr
:
/* function-like: name(..) or name[..] */
return
true
;
/* CASE keywords act as parentheses */
case
T_CaseExpr
:
return
true
;
case
T_FieldSelect
:
/*
* appears simple since . has top precedence, unless parent is
* T_FieldSelect itself!
*/
return
(
IsA
(
parentNode
,
FieldSelect
)
?
false
:
true
);
case
T_CoerceToDomain
:
/* maybe simple, check args */
return
isSimpleNode
((
Node
*
)
((
CoerceToDomain
*
)
node
)
->
arg
,
node
,
prettyFlags
);
case
T_RelabelType
:
return
isSimpleNode
((
Node
*
)
((
RelabelType
*
)
node
)
->
arg
,
node
,
prettyFlags
);
case
T_OpExpr
:
{
/* depends on parent node type; needs further checking */
if
(
prettyFlags
&
PRETTYFLAG_PAREN
&&
IsA
(
parentNode
,
OpExpr
))
{
const
char
*
op
;
const
char
*
parentOp
;
bool
is_lopriop
;
bool
is_hipriop
;
bool
is_lopriparent
;
bool
is_hipriparent
;
op
=
get_simple_binary_op_name
((
OpExpr
*
)
node
);
if
(
!
op
)
return
false
;
/* We know only the basic operators + - and * / % */
is_lopriop
=
(
strchr
(
"+-"
,
*
op
)
!=
NULL
);
is_hipriop
=
(
strchr
(
"*/%"
,
*
op
)
!=
NULL
);
if
(
!
(
is_lopriop
||
is_hipriop
))
return
false
;
parentOp
=
get_simple_binary_op_name
((
OpExpr
*
)
parentNode
);
if
(
!
parentOp
)
return
false
;
is_lopriparent
=
(
strchr
(
"+-"
,
*
parentOp
)
!=
NULL
);
is_hipriparent
=
(
strchr
(
"*/%"
,
*
parentOp
)
!=
NULL
);
if
(
!
(
is_lopriparent
||
is_hipriparent
))
return
false
;
if
(
is_hipriop
&&
is_lopriparent
)
return
true
;
/* op binds tighter than parent */
if
(
is_lopriop
&&
is_hipriparent
)
return
false
;
/*
* Operators are same priority --- can skip parens only
* if we have (a - b) - c, not a - (b - c).
*/
if
(
node
==
(
Node
*
)
lfirst
(((
OpExpr
*
)
parentNode
)
->
args
))
return
true
;
return
false
;
}
/* else do the same stuff as for T_SubLink et al. */
/* FALL THROUGH */
}
case
T_SubLink
:
case
T_NullTest
:
case
T_BooleanTest
:
case
T_DistinctExpr
:
switch
(
nodeTag
(
parentNode
))
{
case
T_FuncExpr
:
{
/* special handling for casts */
CoercionForm
type
=
((
FuncExpr
*
)
parentNode
)
->
funcformat
;
if
(
type
==
COERCE_EXPLICIT_CAST
||
type
==
COERCE_IMPLICIT_CAST
)
return
false
;
return
true
;
/* own parentheses */
}
case
T_BoolExpr
:
/* lower precedence */
case
T_ArrayRef
:
/* other separators */
case
T_ArrayExpr
:
/* other separators */
case
T_CoalesceExpr
:
/* own parentheses */
case
T_NullIfExpr
:
/* other separators */
case
T_Aggref
:
/* own parentheses */
case
T_CaseExpr
:
/* other separators */
return
true
;
default:
return
false
;
}
case
T_BoolExpr
:
switch
(
nodeTag
(
parentNode
))
{
case
T_BoolExpr
:
if
(
prettyFlags
&
PRETTYFLAG_PAREN
)
{
BoolExprType
type
;
BoolExprType
parentType
;
type
=
((
BoolExpr
*
)
node
)
->
boolop
;
parentType
=
((
BoolExpr
*
)
parentNode
)
->
boolop
;
switch
(
type
)
{
case
NOT_EXPR
:
case
AND_EXPR
:
if
(
parentType
==
AND_EXPR
||
parentType
==
OR_EXPR
)
return
true
;
break
;
case
OR_EXPR
:
if
(
parentType
==
OR_EXPR
)
return
true
;
break
;
}
}
return
false
;
case
T_FuncExpr
:
{
/* special handling for casts */
CoercionForm
type
=
((
FuncExpr
*
)
parentNode
)
->
funcformat
;
if
(
type
==
COERCE_EXPLICIT_CAST
||
type
==
COERCE_IMPLICIT_CAST
)
return
false
;
return
true
;
/* own parentheses */
}
case
T_ArrayRef
:
/* other separators */
case
T_ArrayExpr
:
/* other separators */
case
T_CoalesceExpr
:
/* own parentheses */
case
T_NullIfExpr
:
/* other separators */
case
T_Aggref
:
/* own parentheses */
case
T_CaseExpr
:
/* other separators */
return
true
;
default:
return
false
;
}
default:
break
;
}
/* those we don't know: in dubio complexo */
return
false
;
}
/*
* appendStringInfoSpaces - append spaces to buffer
*/
static
void
appendStringInfoSpaces
(
StringInfo
buf
,
int
count
)
{
while
(
count
--
>
0
)
appendStringInfoChar
(
buf
,
' '
);
}
/*
* appendContextKeyword - append a keyword to buffer
*
* If prettyPrint is enabled, perform a line break, and adjust indentation.
* Otherwise, just append the keyword.
*/
static
void
appendContextKeyword
(
deparse_context
*
context
,
const
char
*
str
,
int
indentBefore
,
int
indentAfter
,
int
indentPlus
)
{
if
(
PRETTY_INDENT
(
context
))
{
context
->
indentLevel
+=
indentBefore
;
if
(
context
->
indentLevel
<
0
)
context
->
indentLevel
=
0
;
appendStringInfoChar
(
context
->
buf
,
'\n'
);
appendStringInfoSpaces
(
context
->
buf
,
context
->
indentLevel
+
indentPlus
);
}
appendStringInfoString
(
context
->
buf
,
str
);
if
(
PRETTY_INDENT
(
context
))
{
context
->
indentLevel
+=
indentAfter
;
if
(
context
->
indentLevel
<
0
)
context
->
indentLevel
=
0
;
}
}
/*
* get_rule_expr_paren - deparse expr using get_rule_expr,
* embracing the string with parentheses if necessary for prettyPrint.
*
* Never embrace if prettyFlags=0, because it's done in the calling node.
*
* Any node that does *not* embrace its argument node by sql syntax (with
* parentheses, non-operator keywords like CASE/WHEN/ON, or comma etc) should
* use get_rule_expr_paren instead of get_rule_expr so parentheses can be
* added.
*/
static
void
get_rule_expr_paren
(
Node
*
node
,
deparse_context
*
context
,
bool
showimplicit
,
Node
*
parentNode
)
{
bool
need_paren
;
need_paren
=
PRETTY_PAREN
(
context
)
&&
!
isSimpleNode
(
node
,
parentNode
,
context
->
prettyFlags
);
if
(
need_paren
)
appendStringInfoChar
(
context
->
buf
,
'('
);
get_rule_expr
(
node
,
context
,
showimplicit
);
if
(
need_paren
)
appendStringInfoChar
(
context
->
buf
,
')'
);
}
/* ----------
* get_rule_expr - Parse back an expression
*
...
...
@@ -2300,11 +2861,13 @@ get_rule_expr(Node *node, deparse_context *context,
Node
*
arg1
=
(
Node
*
)
lfirst
(
args
);
Node
*
arg2
=
(
Node
*
)
lsecond
(
args
);
appendStringInfoChar
(
buf
,
'('
);
get_rule_expr
(
arg1
,
context
,
true
);
if
(
!
PRETTY_PAREN
(
context
))
appendStringInfoChar
(
buf
,
'('
);
get_rule_expr_paren
(
arg1
,
context
,
true
,
node
);
appendStringInfo
(
buf
,
" IS DISTINCT FROM "
);
get_rule_expr
(
arg2
,
context
,
true
);
appendStringInfoChar
(
buf
,
')'
);
get_rule_expr_paren
(
arg2
,
context
,
true
,
node
);
if
(
!
PRETTY_PAREN
(
context
))
appendStringInfoChar
(
buf
,
')'
);
}
break
;
...
...
@@ -2315,15 +2878,18 @@ get_rule_expr(Node *node, deparse_context *context,
Node
*
arg1
=
(
Node
*
)
lfirst
(
args
);
Node
*
arg2
=
(
Node
*
)
lsecond
(
args
);
appendStringInfoChar
(
buf
,
'('
);
get_rule_expr
(
arg1
,
context
,
true
);
if
(
!
PRETTY_PAREN
(
context
))
appendStringInfoChar
(
buf
,
'('
);
get_rule_expr_paren
(
arg1
,
context
,
true
,
node
);
appendStringInfo
(
buf
,
" %s %s ("
,
generate_operator_name
(
expr
->
opno
,
exprType
(
arg1
),
get_element_type
(
exprType
(
arg2
))),
expr
->
useOr
?
"ANY"
:
"ALL"
);
get_rule_expr
(
arg2
,
context
,
true
);
appendStringInfo
(
buf
,
"))"
);
get_rule_expr_paren
(
arg2
,
context
,
true
,
node
);
appendStringInfoChar
(
buf
,
')'
);
if
(
!
PRETTY_PAREN
(
context
))
appendStringInfoChar
(
buf
,
')'
);
}
break
;
...
...
@@ -2335,33 +2901,43 @@ get_rule_expr(Node *node, deparse_context *context,
switch
(
expr
->
boolop
)
{
case
AND_EXPR
:
appendStringInfoChar
(
buf
,
'('
);
get_rule_expr
((
Node
*
)
lfirst
(
args
),
context
,
false
);
if
(
!
PRETTY_PAREN
(
context
))
appendStringInfoChar
(
buf
,
'('
);
get_rule_expr_paren
((
Node
*
)
lfirst
(
args
),
context
,
false
,
node
);
while
((
args
=
lnext
(
args
))
!=
NIL
)
{
appendStringInfo
(
buf
,
" AND "
);
get_rule_expr
((
Node
*
)
lfirst
(
args
),
context
,
fals
e
);
get_rule_expr
_paren
((
Node
*
)
lfirst
(
args
),
context
,
false
,
nod
e
);
}
appendStringInfoChar
(
buf
,
')'
);
if
(
!
PRETTY_PAREN
(
context
))
appendStringInfoChar
(
buf
,
')'
);
break
;
case
OR_EXPR
:
appendStringInfoChar
(
buf
,
'('
);
get_rule_expr
((
Node
*
)
lfirst
(
args
),
context
,
false
);
if
(
!
PRETTY_PAREN
(
context
))
appendStringInfoChar
(
buf
,
'('
);
get_rule_expr_paren
((
Node
*
)
lfirst
(
args
),
context
,
false
,
node
);
while
((
args
=
lnext
(
args
))
!=
NIL
)
{
appendStringInfo
(
buf
,
" OR "
);
get_rule_expr
((
Node
*
)
lfirst
(
args
),
context
,
fals
e
);
get_rule_expr
_paren
((
Node
*
)
lfirst
(
args
),
context
,
false
,
nod
e
);
}
appendStringInfoChar
(
buf
,
')'
);
if
(
!
PRETTY_PAREN
(
context
))
appendStringInfoChar
(
buf
,
')'
);
break
;
case
NOT_EXPR
:
appendStringInfo
(
buf
,
"(NOT "
);
get_rule_expr
((
Node
*
)
lfirst
(
args
),
context
,
false
);
appendStringInfoChar
(
buf
,
')'
);
if
(
!
PRETTY_PAREN
(
context
))
appendStringInfoChar
(
buf
,
'('
);
appendStringInfo
(
buf
,
"NOT "
);
get_rule_expr_paren
((
Node
*
)
lfirst
(
args
),
context
,
false
,
node
);
if
(
!
PRETTY_PAREN
(
context
))
appendStringInfoChar
(
buf
,
')'
);
break
;
default:
...
...
@@ -2409,9 +2985,12 @@ get_rule_expr(Node *node, deparse_context *context,
* arg.fieldname, but most cases where FieldSelect is used
* are *not* simple. So, always use parenthesized syntax.
*/
appendStringInfoChar
(
buf
,
'('
);
get_rule_expr
((
Node
*
)
fselect
->
arg
,
context
,
true
);
appendStringInfo
(
buf
,
").%s"
,
quote_identifier
(
fieldname
));
if
(
!
PRETTY_PAREN
(
context
))
appendStringInfoChar
(
buf
,
'('
);
get_rule_expr_paren
((
Node
*
)
fselect
->
arg
,
context
,
true
,
node
);
if
(
!
PRETTY_PAREN
(
context
))
appendStringInfoChar
(
buf
,
')'
);
appendStringInfo
(
buf
,
".%s"
,
quote_identifier
(
fieldname
));
}
break
;
...
...
@@ -2424,7 +3003,7 @@ get_rule_expr(Node *node, deparse_context *context,
!
showimplicit
)
{
/* don't show the implicit cast */
get_rule_expr
(
arg
,
context
,
showimplicit
);
get_rule_expr
_paren
(
arg
,
context
,
showimplicit
,
node
);
}
else
{
...
...
@@ -2436,9 +3015,12 @@ get_rule_expr(Node *node, deparse_context *context,
*/
arg
=
strip_type_coercion
(
arg
,
relabel
->
resulttype
);
appendStringInfoChar
(
buf
,
'('
);
get_rule_expr
(
arg
,
context
,
showimplicit
);
appendStringInfo
(
buf
,
")::%s"
,
if
(
!
PRETTY_PAREN
(
context
))
appendStringInfoChar
(
buf
,
'('
);
get_rule_expr_paren
(
arg
,
context
,
showimplicit
,
node
);
if
(
!
PRETTY_PAREN
(
context
))
appendStringInfoChar
(
buf
,
')'
);
appendStringInfo
(
buf
,
"::%s"
,
format_type_with_typemod
(
relabel
->
resulttype
,
relabel
->
resulttypmod
));
}
...
...
@@ -2450,19 +3032,29 @@ get_rule_expr(Node *node, deparse_context *context,
CaseExpr
*
caseexpr
=
(
CaseExpr
*
)
node
;
List
*
temp
;
appendStringInfo
(
buf
,
"CASE"
);
appendContextKeyword
(
context
,
"CASE"
,
0
,
PRETTYINDENT_VAR
,
0
);
foreach
(
temp
,
caseexpr
->
args
)
{
CaseWhen
*
when
=
(
CaseWhen
*
)
lfirst
(
temp
);
appendStringInfo
(
buf
,
" WHEN "
);
if
(
!
PRETTY_INDENT
(
context
))
appendStringInfoChar
(
buf
,
' '
);
appendContextKeyword
(
context
,
"WHEN "
,
0
,
0
,
0
);
get_rule_expr
((
Node
*
)
when
->
expr
,
context
,
false
);
appendStringInfo
(
buf
,
" THEN "
);
get_rule_expr
((
Node
*
)
when
->
result
,
context
,
true
);
}
appendStringInfo
(
buf
,
" ELSE "
);
if
(
!
PRETTY_INDENT
(
context
))
appendStringInfoChar
(
buf
,
' '
);
appendContextKeyword
(
context
,
"ELSE "
,
0
,
0
,
0
);
get_rule_expr
((
Node
*
)
caseexpr
->
defresult
,
context
,
true
);
appendStringInfo
(
buf
,
" END"
);
if
(
!
PRETTY_INDENT
(
context
))
appendStringInfoChar
(
buf
,
' '
);
appendContextKeyword
(
context
,
"END"
,
-
PRETTYINDENT_VAR
,
0
,
0
);
}
break
;
...
...
@@ -2530,20 +3122,23 @@ get_rule_expr(Node *node, deparse_context *context,
{
NullTest
*
ntest
=
(
NullTest
*
)
node
;
appendStringInfo
(
buf
,
"("
);
get_rule_expr
((
Node
*
)
ntest
->
arg
,
context
,
true
);
if
(
!
PRETTY_PAREN
(
context
))
appendStringInfoChar
(
buf
,
'('
);
get_rule_expr_paren
((
Node
*
)
ntest
->
arg
,
context
,
true
,
node
);
switch
(
ntest
->
nulltesttype
)
{
case
IS_NULL
:
appendStringInfo
(
buf
,
" IS NULL
)
"
);
appendStringInfo
(
buf
,
" IS NULL"
);
break
;
case
IS_NOT_NULL
:
appendStringInfo
(
buf
,
" IS NOT NULL
)
"
);
appendStringInfo
(
buf
,
" IS NOT NULL"
);
break
;
default:
elog
(
ERROR
,
"unrecognized nulltesttype: %d"
,
(
int
)
ntest
->
nulltesttype
);
}
if
(
!
PRETTY_PAREN
(
context
))
appendStringInfoChar
(
buf
,
')'
);
}
break
;
...
...
@@ -2551,32 +3146,35 @@ get_rule_expr(Node *node, deparse_context *context,
{
BooleanTest
*
btest
=
(
BooleanTest
*
)
node
;
appendStringInfo
(
buf
,
"("
);
get_rule_expr
((
Node
*
)
btest
->
arg
,
context
,
false
);
if
(
!
PRETTY_PAREN
(
context
))
appendStringInfoChar
(
buf
,
'('
);
get_rule_expr_paren
((
Node
*
)
btest
->
arg
,
context
,
false
,
node
);
switch
(
btest
->
booltesttype
)
{
case
IS_TRUE
:
appendStringInfo
(
buf
,
" IS TRUE
)
"
);
appendStringInfo
(
buf
,
" IS TRUE"
);
break
;
case
IS_NOT_TRUE
:
appendStringInfo
(
buf
,
" IS NOT TRUE
)
"
);
appendStringInfo
(
buf
,
" IS NOT TRUE"
);
break
;
case
IS_FALSE
:
appendStringInfo
(
buf
,
" IS FALSE
)
"
);
appendStringInfo
(
buf
,
" IS FALSE"
);
break
;
case
IS_NOT_FALSE
:
appendStringInfo
(
buf
,
" IS NOT FALSE
)
"
);
appendStringInfo
(
buf
,
" IS NOT FALSE"
);
break
;
case
IS_UNKNOWN
:
appendStringInfo
(
buf
,
" IS UNKNOWN
)
"
);
appendStringInfo
(
buf
,
" IS UNKNOWN"
);
break
;
case
IS_NOT_UNKNOWN
:
appendStringInfo
(
buf
,
" IS NOT UNKNOWN
)
"
);
appendStringInfo
(
buf
,
" IS NOT UNKNOWN"
);
break
;
default:
elog
(
ERROR
,
"unrecognized booltesttype: %d"
,
(
int
)
btest
->
booltesttype
);
}
if
(
!
PRETTY_PAREN
(
context
))
appendStringInfoChar
(
buf
,
')'
);
}
break
;
...
...
@@ -2598,9 +3196,12 @@ get_rule_expr(Node *node, deparse_context *context,
}
else
{
appendStringInfoChar
(
buf
,
'('
);
get_rule_expr
(
arg
,
context
,
false
);
appendStringInfo
(
buf
,
")::%s"
,
if
(
!
PRETTY_PAREN
(
context
))
appendStringInfoChar
(
buf
,
'('
);
get_rule_expr_paren
(
arg
,
context
,
false
,
node
);
if
(
!
PRETTY_PAREN
(
context
))
appendStringInfoChar
(
buf
,
')'
);
appendStringInfo
(
buf
,
"::%s"
,
format_type_with_typemod
(
ctest
->
resulttype
,
ctest
->
resulttypmod
));
}
...
...
@@ -2632,19 +3233,19 @@ get_oper_expr(OpExpr *expr, deparse_context *context)
Oid
opno
=
expr
->
opno
;
List
*
args
=
expr
->
args
;
appendStringInfoChar
(
buf
,
'('
);
if
(
!
PRETTY_PAREN
(
context
))
appendStringInfoChar
(
buf
,
'('
);
if
(
length
(
args
)
==
2
)
{
/* binary operator */
Node
*
arg1
=
(
Node
*
)
lfirst
(
args
);
Node
*
arg2
=
(
Node
*
)
lsecond
(
args
);
get_rule_expr
(
arg1
,
context
,
true
);
get_rule_expr_paren
(
arg1
,
context
,
true
,
(
Node
*
)
expr
);
appendStringInfo
(
buf
,
" %s "
,
generate_operator_name
(
opno
,
exprType
(
arg1
),
exprType
(
arg2
)));
get_rule_expr
(
arg2
,
context
,
true
);
get_rule_expr
_paren
(
arg2
,
context
,
true
,
(
Node
*
)
expr
);
}
else
{
...
...
@@ -2666,10 +3267,10 @@ get_oper_expr(OpExpr *expr, deparse_context *context)
generate_operator_name
(
opno
,
InvalidOid
,
exprType
(
arg
)));
get_rule_expr
(
arg
,
context
,
true
);
get_rule_expr
_paren
(
arg
,
context
,
true
,
(
Node
*
)
expr
);
break
;
case
'r'
:
get_rule_expr
(
arg
,
context
,
true
);
get_rule_expr
_paren
(
arg
,
context
,
true
,
(
Node
*
)
expr
);
appendStringInfo
(
buf
,
" %s"
,
generate_operator_name
(
opno
,
exprType
(
arg
),
...
...
@@ -2680,7 +3281,8 @@ get_oper_expr(OpExpr *expr, deparse_context *context)
}
ReleaseSysCache
(
tp
);
}
appendStringInfoChar
(
buf
,
')'
);
if
(
!
PRETTY_PAREN
(
context
))
appendStringInfoChar
(
buf
,
')'
);
}
/*
...
...
@@ -2703,7 +3305,8 @@ get_func_expr(FuncExpr *expr, deparse_context *context,
*/
if
(
expr
->
funcformat
==
COERCE_IMPLICIT_CAST
&&
!
showimplicit
)
{
get_rule_expr
((
Node
*
)
lfirst
(
expr
->
args
),
context
,
showimplicit
);
get_rule_expr_paren
((
Node
*
)
lfirst
(
expr
->
args
),
context
,
showimplicit
,
(
Node
*
)
expr
);
return
;
}
...
...
@@ -2729,9 +3332,12 @@ get_func_expr(FuncExpr *expr, deparse_context *context,
*/
arg
=
strip_type_coercion
(
arg
,
rettype
);
appendStringInfoChar
(
buf
,
'('
);
get_rule_expr
(
arg
,
context
,
showimplicit
);
appendStringInfo
(
buf
,
")::%s"
,
if
(
!
PRETTY_PAREN
(
context
))
appendStringInfoChar
(
buf
,
'('
);
get_rule_expr_paren
(
arg
,
context
,
showimplicit
,
(
Node
*
)
expr
);
if
(
!
PRETTY_PAREN
(
context
))
appendStringInfoChar
(
buf
,
')'
);
appendStringInfo
(
buf
,
"::%s"
,
format_type_with_typemod
(
rettype
,
coercedTypmod
));
return
;
...
...
@@ -3052,7 +3658,8 @@ get_sublink_expr(SubLink *sublink, deparse_context *context)
if
(
need_paren
)
appendStringInfoChar
(
buf
,
'('
);
get_query_def
(
query
,
buf
,
context
->
namespaces
,
NULL
);
get_query_def
(
query
,
buf
,
context
->
namespaces
,
NULL
,
context
->
prettyFlags
,
context
->
indentLevel
);
if
(
need_paren
)
appendStringInfo
(
buf
,
"))"
);
...
...
@@ -3069,7 +3676,7 @@ static void
get_from_clause
(
Query
*
query
,
deparse_context
*
context
)
{
StringInfo
buf
=
context
->
buf
;
char
*
sep
;
bool
first
=
true
;
List
*
l
;
/*
...
...
@@ -3079,8 +3686,6 @@ get_from_clause(Query *query, deparse_context *context)
* sufficient to check here.) Also ignore the rule pseudo-RTEs for NEW
* and OLD.
*/
sep
=
" FROM "
;
foreach
(
l
,
query
->
jointree
->
fromlist
)
{
Node
*
jtnode
=
(
Node
*
)
lfirst
(
l
);
...
...
@@ -3098,9 +3703,16 @@ get_from_clause(Query *query, deparse_context *context)
continue
;
}
appendStringInfo
(
buf
,
sep
);
if
(
first
)
{
appendContextKeyword
(
context
,
" FROM "
,
-
PRETTYINDENT_STD
,
PRETTYINDENT_STD
,
2
);
first
=
false
;
}
else
appendStringInfoString
(
buf
,
", "
);
get_from_clause_item
(
jtnode
,
query
,
context
);
sep
=
", "
;
}
}
...
...
@@ -3127,7 +3739,8 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
case
RTE_SUBQUERY
:
/* Subquery RTE */
appendStringInfoChar
(
buf
,
'('
);
get_query_def
(
rte
->
subquery
,
buf
,
context
->
namespaces
,
NULL
);
get_query_def
(
rte
->
subquery
,
buf
,
context
->
namespaces
,
NULL
,
context
->
prettyFlags
,
context
->
indentLevel
);
appendStringInfoChar
(
buf
,
')'
);
break
;
case
RTE_FUNCTION
:
...
...
@@ -3149,7 +3762,7 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
{
List
*
col
;
appendStringInfo
(
buf
,
"("
);
appendStringInfo
Char
(
buf
,
'('
);
foreach
(
col
,
rte
->
alias
->
colnames
)
{
if
(
col
!=
rte
->
alias
->
colnames
)
...
...
@@ -3183,36 +3796,105 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
else
if
(
IsA
(
jtnode
,
JoinExpr
))
{
JoinExpr
*
j
=
(
JoinExpr
*
)
jtnode
;
bool
need_paren_on_right
;
need_paren_on_right
=
PRETTY_PAREN
(
context
)
&&
!
IsA
(
j
->
rarg
,
RangeTblRef
);
if
(
!
PRETTY_PAREN
(
context
)
||
j
->
alias
!=
NULL
)
appendStringInfoChar
(
buf
,
'('
);
appendStringInfoChar
(
buf
,
'('
);
get_from_clause_item
(
j
->
larg
,
query
,
context
);
if
(
j
->
isNatural
)
appendStringInfo
(
buf
,
" NATURAL"
);
switch
(
j
->
jointype
)
{
case
JOIN_INNER
:
if
(
j
->
quals
)
appendStringInfo
(
buf
,
" JOIN "
);
else
appendStringInfo
(
buf
,
" CROSS JOIN "
);
break
;
case
JOIN_LEFT
:
appendStringInfo
(
buf
,
" LEFT JOIN "
);
break
;
case
JOIN_FULL
:
appendStringInfo
(
buf
,
" FULL JOIN "
);
break
;
case
JOIN_RIGHT
:
appendStringInfo
(
buf
,
" RIGHT JOIN "
);
break
;
case
JOIN_UNION
:
appendStringInfo
(
buf
,
" UNION JOIN "
);
break
;
default:
elog
(
ERROR
,
"unrecognized join type: %d"
,
(
int
)
j
->
jointype
);
if
(
!
PRETTY_INDENT
(
context
))
appendStringInfoChar
(
buf
,
' '
);
switch
(
j
->
jointype
)
{
case
JOIN_INNER
:
if
(
j
->
quals
)
appendContextKeyword
(
context
,
"NATURAL JOIN "
,
-
PRETTYINDENT_JOIN
,
PRETTYINDENT_JOIN
,
0
);
else
appendContextKeyword
(
context
,
"NATURAL CROSS JOIN "
,
-
PRETTYINDENT_JOIN
,
PRETTYINDENT_JOIN
,
0
);
break
;
case
JOIN_LEFT
:
appendContextKeyword
(
context
,
"NATURAL LEFT JOIN "
,
-
PRETTYINDENT_JOIN
,
PRETTYINDENT_JOIN
,
0
);
break
;
case
JOIN_FULL
:
appendContextKeyword
(
context
,
"NATURAL FULL JOIN "
,
-
PRETTYINDENT_JOIN
,
PRETTYINDENT_JOIN
,
0
);
break
;
case
JOIN_RIGHT
:
appendContextKeyword
(
context
,
"NATURAL RIGHT JOIN "
,
-
PRETTYINDENT_JOIN
,
PRETTYINDENT_JOIN
,
0
);
break
;
case
JOIN_UNION
:
appendContextKeyword
(
context
,
"NATURAL UNION JOIN "
,
-
PRETTYINDENT_JOIN
,
PRETTYINDENT_JOIN
,
0
);
break
;
default:
elog
(
ERROR
,
"unrecognized join type: %d"
,
(
int
)
j
->
jointype
);
}
}
else
{
switch
(
j
->
jointype
)
{
case
JOIN_INNER
:
if
(
j
->
quals
)
appendContextKeyword
(
context
,
" JOIN "
,
-
PRETTYINDENT_JOIN
,
PRETTYINDENT_JOIN
,
2
);
else
appendContextKeyword
(
context
,
" CROSS JOIN "
,
-
PRETTYINDENT_JOIN
,
PRETTYINDENT_JOIN
,
1
);
break
;
case
JOIN_LEFT
:
appendContextKeyword
(
context
,
" LEFT JOIN "
,
-
PRETTYINDENT_JOIN
,
PRETTYINDENT_JOIN
,
2
);
break
;
case
JOIN_FULL
:
appendContextKeyword
(
context
,
" FULL JOIN "
,
-
PRETTYINDENT_JOIN
,
PRETTYINDENT_JOIN
,
2
);
break
;
case
JOIN_RIGHT
:
appendContextKeyword
(
context
,
" RIGHT JOIN "
,
-
PRETTYINDENT_JOIN
,
PRETTYINDENT_JOIN
,
2
);
break
;
case
JOIN_UNION
:
appendContextKeyword
(
context
,
" UNION JOIN "
,
-
PRETTYINDENT_JOIN
,
PRETTYINDENT_JOIN
,
2
);
break
;
default:
elog
(
ERROR
,
"unrecognized join type: %d"
,
(
int
)
j
->
jointype
);
}
}
if
(
need_paren_on_right
)
appendStringInfoChar
(
buf
,
'('
);
get_from_clause_item
(
j
->
rarg
,
query
,
context
);
if
(
need_paren_on_right
)
appendStringInfoChar
(
buf
,
')'
);
context
->
indentLevel
-=
PRETTYINDENT_JOIN_ON
;
if
(
!
j
->
isNatural
)
{
if
(
j
->
using
)
...
...
@@ -3225,18 +3907,23 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
if
(
col
!=
j
->
using
)
appendStringInfo
(
buf
,
", "
);
appendStringInfo
(
buf
,
"%s"
,
quote_identifier
(
strVal
(
lfirst
(
col
))));
quote_identifier
(
strVal
(
lfirst
(
col
))));
}
appendStringInfoChar
(
buf
,
')'
);
}
else
if
(
j
->
quals
)
{
appendStringInfo
(
buf
,
" ON ("
);
appendStringInfo
(
buf
,
" ON "
);
if
(
!
PRETTY_PAREN
(
context
))
appendStringInfoChar
(
buf
,
'('
);
get_rule_expr
(
j
->
quals
,
context
,
false
);
appendStringInfoChar
(
buf
,
')'
);
if
(
!
PRETTY_PAREN
(
context
))
appendStringInfoChar
(
buf
,
')'
);
}
}
appendStringInfoChar
(
buf
,
')'
);
if
(
!
PRETTY_PAREN
(
context
)
||
j
->
alias
!=
NULL
)
appendStringInfoChar
(
buf
,
')'
);
/* Yes, it's correct to put alias after the right paren ... */
if
(
j
->
alias
!=
NULL
)
{
...
...
@@ -3246,13 +3933,13 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
{
List
*
col
;
appendStringInfo
(
buf
,
"("
);
appendStringInfo
Char
(
buf
,
'('
);
foreach
(
col
,
j
->
alias
->
colnames
)
{
if
(
col
!=
j
->
alias
->
colnames
)
appendStringInfo
(
buf
,
", "
);
appendStringInfo
(
buf
,
"%s"
,
quote_identifier
(
strVal
(
lfirst
(
col
))));
quote_identifier
(
strVal
(
lfirst
(
col
))));
}
appendStringInfoChar
(
buf
,
')'
);
}
...
...
src/include/catalog/catversion.h
View file @
52347b66
...
...
@@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: catversion.h,v 1.20
3 2003/07/29 17:21:27
tgl Exp $
* $Id: catversion.h,v 1.20
4 2003/07/30 22:56:24
tgl Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
#define CATALOG_VERSION_NO 200307
29
1
#define CATALOG_VERSION_NO 200307
30
1
#endif
src/include/catalog/pg_proc.h
View file @
52347b66
...
...
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: pg_proc.h,v 1.3
09 2003/07/01 00:04:38
tgl Exp $
* $Id: pg_proc.h,v 1.3
10 2003/07/30 22:56:24
tgl Exp $
*
* NOTES
* The script catalog/genbki.sh reads this file and generates .bki
...
...
@@ -3405,6 +3405,20 @@ DESCR("I/O");
DATA
(
insert
OID
=
2503
(
anyarray_send
PGNSP
PGUID
12
f
f
t
f
s
1
17
"2277"
anyarray_send
-
_null_
));
DESCR
(
"I/O"
);
/* System-view support functions with pretty-print option */
DATA
(
insert
OID
=
2504
(
pg_get_ruledef
PGNSP
PGUID
12
f
f
t
f
s
2
25
"26 16"
pg_get_ruledef_ext
-
_null_
));
DESCR
(
"source text of a rule with pretty-print option"
);
DATA
(
insert
OID
=
2505
(
pg_get_viewdef
PGNSP
PGUID
12
f
f
t
f
s
2
25
"25 16"
pg_get_viewdef_name_ext
-
_null_
));
DESCR
(
"select statement of a view with pretty-print option"
);
DATA
(
insert
OID
=
2506
(
pg_get_viewdef
PGNSP
PGUID
12
f
f
t
f
s
2
25
"26 16"
pg_get_viewdef_ext
-
_null_
));
DESCR
(
"select statement of a view with pretty-print option"
);
DATA
(
insert
OID
=
2507
(
pg_get_indexdef
PGNSP
PGUID
12
f
f
t
f
s
3
25
"26 23 16"
pg_get_indexdef_ext
-
_null_
));
DESCR
(
"index description (full create statement or single expression) with pretty-print option"
);
DATA
(
insert
OID
=
2508
(
pg_get_constraintdef
PGNSP
PGUID
12
f
f
t
f
s
2
25
"26 16"
pg_get_constraintdef_ext
-
_null_
));
DESCR
(
"constraint description with pretty-print option"
);
DATA
(
insert
OID
=
2509
(
pg_get_expr
PGNSP
PGUID
12
f
f
t
f
s
3
25
"25 26 16"
pg_get_expr_ext
-
_null_
));
DESCR
(
"deparse an encoded expression with pretty-print option"
);
/*
* Symbolic values for provolatile column: these indicate whether the result
...
...
src/include/utils/builtins.h
View file @
52347b66
...
...
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: builtins.h,v 1.22
3 2003/06/27 00:33:26
tgl Exp $
* $Id: builtins.h,v 1.22
4 2003/07/30 22:56:24
tgl Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -441,13 +441,19 @@ extern char *format_operator(Oid operator_oid);
/* ruleutils.c */
extern
Datum
pg_get_ruledef
(
PG_FUNCTION_ARGS
);
extern
Datum
pg_get_ruledef_ext
(
PG_FUNCTION_ARGS
);
extern
Datum
pg_get_viewdef
(
PG_FUNCTION_ARGS
);
extern
Datum
pg_get_viewdef_ext
(
PG_FUNCTION_ARGS
);
extern
Datum
pg_get_viewdef_name
(
PG_FUNCTION_ARGS
);
extern
Datum
pg_get_viewdef_name_ext
(
PG_FUNCTION_ARGS
);
extern
Datum
pg_get_indexdef
(
PG_FUNCTION_ARGS
);
extern
Datum
pg_get_indexdef_ext
(
PG_FUNCTION_ARGS
);
extern
Datum
pg_get_triggerdef
(
PG_FUNCTION_ARGS
);
extern
Datum
pg_get_constraintdef
(
PG_FUNCTION_ARGS
);
extern
Datum
pg_get_constraintdef_ext
(
PG_FUNCTION_ARGS
);
extern
Datum
pg_get_userbyid
(
PG_FUNCTION_ARGS
);
extern
Datum
pg_get_expr
(
PG_FUNCTION_ARGS
);
extern
Datum
pg_get_expr_ext
(
PG_FUNCTION_ARGS
);
extern
char
*
deparse_expression
(
Node
*
expr
,
List
*
dpcontext
,
bool
forceprefix
,
bool
showimplicit
);
extern
List
*
deparse_context_for
(
const
char
*
aliasname
,
Oid
relid
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment