Andreas, looks good, but I need a diff -c, context diff.Hi Bruce,
I intentionally only attached only non-context diffs because the patch is about 50 % size of the original file. Now, here's the same as context diff.
Regards, Andreas
Index: pg_proc.h
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/include/catalog/pg_proc.h,v
retrieving revision 1.309
diff -c -r1.309 pg_proc.h
*** pg_proc.h 1 Jul 2003 00:04:38 -0000 1.309
--- pg_proc.h 22 Jul 2003 12:52:07 -0000
***************
*** 3405,3410 ****
--- 3405,3424 ----
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 - _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 - _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 - _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 - _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 - _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 - _null_ ));
+ DESCR("deparse an encoded expression with pretty-print option");
+
/*
* Symbolic values for provolatile column: these indicate whether the result
Index: ruleutils.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/backend/utils/adt/ruleutils.c,v
retrieving revision 1.145
diff -c -r1.145 ruleutils.c
*** ruleutils.c 4 Jul 2003 02:51:34 -0000 1.145
--- ruleutils.c 22 Jul 2003 12:54:10 -0000
***************
*** 71,76 ****
--- 71,95 ----
#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,86 ****
--- 100,107 ----
{
StringInfo buf; /* output buffer to append to */
List *namespaces; /* List of deparse_namespace nodes */
+ int prettyFlags; /* enabling/disabling of
pretty-print functions */
+ int indentLevel; /* for prettyPrint, current space
indents are counted */
bool varprefix; /* TRUE to print prefixes on Vars */
} deparse_context;
***************
*** 123,135 ****
* as a parameter, and append their text output to its contents.
* ----------
*/
! static text *pg_do_getviewdef(Oid viewoid);
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 void get_query_def(Query *query, StringInfo buf, List *parentnamespace,
! TupleDesc resultDesc);
static void get_select_query_def(Query *query, deparse_context *context,
TupleDesc resultDesc);
static void get_insert_query_def(Query *query, deparse_context *context);
--- 144,162 ----
* as a parameter, and append their text output to its contents.
* ----------
*/
! static char *get_simple_binary_op_name(OpExpr *expr);
! static void appendStringInfoSpace(StringInfo buf, int count);
! static void appendContextKeyword(deparse_context *context, char *str, int
indentBefore, int indentAfter, int indentPlus);
! static char *deparse_expression_pretty(Node *expr, List *dpcontext,
! bool forceprefix, bool showimplicit, int prettyFlags, int
startIndent);
! static bool isSimpleNode(Node *node, Node *parentNode, int prettyFlags);
! 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, 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, 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);
***************
*** 192,197 ****
--- 219,225 ----
TupleDesc rulettc;
StringInfoData buf;
int len;
+ int prettyFlags = !PG_ARGISNULL(1) && PG_GETARG_BOOL(1) ?
PRETTYFLAG_PAREN|PRETTYFLAG_INDENT : 0;
/*
* Connect to SPI manager
***************
*** 241,247 ****
* Get the rules definition and put it into executors memory
*/
initStringInfo(&buf);
! make_ruledef(&buf, ruletup, rulettc);
len = buf.len + VARHDRSZ;
ruledef = SPI_palloc(len);
VARATT_SIZEP(ruledef) = len;
--- 269,275 ----
* Get the rules definition and put it into executors memory
*/
initStringInfo(&buf);
! make_ruledef(&buf, ruletup, rulettc, prettyFlags);
len = buf.len + VARHDRSZ;
ruledef = SPI_palloc(len);
VARATT_SIZEP(ruledef) = len;
***************
*** 272,279 ****
/* By OID */
Oid viewoid = PG_GETARG_OID(0);
text *ruledef;
! ruledef = pg_do_getviewdef(viewoid);
PG_RETURN_TEXT_P(ruledef);
}
--- 300,308 ----
/* By OID */
Oid viewoid = PG_GETARG_OID(0);
text *ruledef;
+ int prettyFlags = !PG_ARGISNULL(1) && PG_GETARG_BOOL(1) ?
PRETTYFLAG_PAREN|PRETTYFLAG_INDENT : 0;
! ruledef = pg_do_getviewdef(viewoid, prettyFlags);
PG_RETURN_TEXT_P(ruledef);
}
***************
*** 285,296 ****
RangeVar *viewrel;
Oid viewoid;
text *ruledef;
viewrel = makeRangeVarFromNameList(textToQualifiedNameList(viewname,
"get_viewdef"));
viewoid = RangeVarGetRelid(viewrel, false);
! ruledef = pg_do_getviewdef(viewoid);
PG_RETURN_TEXT_P(ruledef);
}
--- 314,326 ----
RangeVar *viewrel;
Oid viewoid;
text *ruledef;
+ int prettyFlags = !PG_ARGISNULL(1) && PG_GETARG_BOOL(1) ?
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,304 ****
* Common code for by-OID and by-name variants of pg_get_viewdef
*/
static text *
! pg_do_getviewdef(Oid viewoid)
{
text *ruledef;
Datum args[2];
--- 328,334 ----
* Common code for by-OID and by-name variants of pg_get_viewdef
*/
static text *
! pg_do_getviewdef(Oid viewoid, int prettyFlags)
{
text *ruledef;
Datum args[2];
***************
*** 353,359 ****
*/
ruletup = SPI_tuptable->vals[0];
rulettc = SPI_tuptable->tupdesc;
! make_viewdef(&buf, ruletup, rulettc);
}
len = buf.len + VARHDRSZ;
ruledef = SPI_palloc(len);
--- 383,389 ----
*/
ruletup = SPI_tuptable->vals[0];
rulettc = SPI_tuptable->tupdesc;
! make_viewdef(&buf, ruletup, rulettc, prettyFlags);
}
len = buf.len + VARHDRSZ;
ruledef = SPI_palloc(len);
***************
*** 544,549 ****
--- 574,581 ----
StringInfoData buf;
char *str;
char *sep;
+ int colno = PG_ARGISNULL(1) ? 0 : PG_GETARG_INT32(1);
+ int prettyFlags = !PG_ARGISNULL(2) && PG_GETARG_BOOL(2) ?
PRETTYFLAG_PAREN|PRETTYFLAG_INDENT : 0;
/*
* Fetch the pg_index tuple by the Oid of the index
***************
*** 582,587 ****
--- 614,621 ----
* Get the index expressions, if any. (NOTE: we do not use the relcache
* versions of the expressions and predicate, because we want to display
* non-const-folded expressions.)
+ * if colno == 0, we want a complete index definition.
+ * if colno > 0, we only want the nth expression.
*/
if (!heap_attisnull(ht_idx, Anum_pg_index_indexprs))
{
***************
*** 607,613 ****
* never be schema-qualified, but the indexed rel's name may be.
*/
initStringInfo(&buf);
! appendStringInfo(&buf, "CREATE %sINDEX %s ON %s USING %s (",
idxrec->indisunique ? "UNIQUE " : "",
quote_identifier(NameStr(idxrelrec->relname)),
generate_relation_name(indrelid),
--- 641,649 ----
* never be schema-qualified, but the indexed rel's name may be.
*/
initStringInfo(&buf);
!
! if (!colno)
! appendStringInfo(&buf, "CREATE %sINDEX %s ON %s USING %s (",
idxrec->indisunique ? "UNIQUE " : "",
quote_identifier(NameStr(idxrelrec->relname)),
generate_relation_name(indrelid),
***************
*** 621,627 ****
{
AttrNumber attnum = idxrec->indkey[keyno];
! appendStringInfo(&buf, sep);
sep = ", ";
if (attnum != 0)
--- 657,664 ----
{
AttrNumber attnum = idxrec->indkey[keyno];
! if (!colno)
! appendStringInfo(&buf, sep);
sep = ", ";
if (attnum != 0)
***************
*** 630,636 ****
char *attname;
attname = get_relid_attribute_name(indrelid, attnum);
! appendStringInfo(&buf, "%s", quote_identifier(attname));
keycoltype = get_atttype(indrelid, attnum);
}
else
--- 667,674 ----
char *attname;
attname = get_relid_attribute_name(indrelid, attnum);
! if (!colno || colno == keyno+1)
! appendStringInfo(&buf, "%s", quote_identifier(attname));
keycoltype = get_atttype(indrelid, attnum);
}
else
***************
*** 643,672 ****
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);
keycoltype = exprType(indexkey);
}
/*
* Add the operator class name
*/
! 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))
{
Node *node;
Datum predDatum;
bool isnull;
--- 681,716 ----
indexkey = (Node *) lfirst(indexprs);
indexprs = lnext(indexprs);
/* Deparse */
! 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
*/
! if (!colno)
! get_opclass_name(idxrec->indclass[keyno], keycoltype,
&buf);
}
! if (!colno)
{
+ 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;
***************
*** 689,698 ****
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);
}
-
/*
* Create the result as a TEXT datum, and free working data
*/
--- 733,742 ----
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);
+ }
}
/*
* Create the result as a TEXT datum, and free working data
*/
***************
*** 729,734 ****
--- 773,779 ----
ScanKeyData skey[1];
HeapTuple tup;
Form_pg_constraint conForm;
+ int prettyFlags = !PG_ARGISNULL(1) && PG_GETARG_BOOL(1) ?
PRETTYFLAG_PAREN|PRETTYFLAG_INDENT : 0;
/*
* Fetch the pg_constraint row. There's no syscache for pg_constraint
***************
*** 934,940 ****
context =
deparse_context_for(get_typname(conForm->contypid),
InvalidOid);
! consrc = deparse_expression(expr, context, false,
false);
/* Append the constraint source */
appendStringInfoString(&buf, consrc);
--- 979,985 ----
context =
deparse_context_for(get_typname(conForm->contypid),
InvalidOid);
! consrc = deparse_expression_pretty(expr, context,
false, false, prettyFlags, 0);
/* Append the constraint source */
appendStringInfoString(&buf, consrc);
***************
*** 1018,1023 ****
--- 1063,1069 ----
char *exprstr;
char *relname;
char *str;
+ int prettyFlags = !PG_ARGISNULL(2) && PG_GETARG_BOOL(2) ?
PRETTYFLAG_PAREN|PRETTYFLAG_INDENT : 0;
/* Get the name for the relation */
relname = get_rel_name(relid);
***************
*** 1041,1047 ****
/* Deparse */
context = deparse_context_for(relname, relid);
! str = deparse_expression(node, context, false, false);
/* Pass the result back as TEXT */
result = DatumGetTextP(DirectFunctionCall1(textin,
--- 1087,1093 ----
/* Deparse */
context = deparse_context_for(relname, relid);
! str = deparse_expression_pretty(node, context, false, false, prettyFlags, 0);
/* Pass the result back as TEXT */
result = DatumGetTextP(DirectFunctionCall1(textin,
***************
*** 1090,1095 ****
--- 1136,1152 ----
/* ----------
* 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).
***************
*** 1100,1112 ****
* 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.
*
* The result is a palloc'd string.
* ----------
*/
char *
! deparse_expression(Node *expr, List *dpcontext,
! bool forceprefix, bool showimplicit)
{
StringInfoData buf;
deparse_context context;
--- 1157,1171 ----
* 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
*
* The result is a palloc'd string.
* ----------
*/
char *
! deparse_expression_pretty(Node *expr, List *dpcontext,
! bool forceprefix, bool showimplicit, int
prettyFlags, int startIndent)
{
StringInfoData buf;
deparse_context context;
***************
*** 1115,1120 ****
--- 1174,1181 ----
context.buf = &buf;
context.namespaces = dpcontext;
context.varprefix = forceprefix;
+ context.prettyFlags = prettyFlags;
+ context.indentLevel = startIndent;
get_rule_expr(expr, &context, showimplicit);
***************
*** 1267,1273 ****
* ----------
*/
static void
! make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc)
{
char *rulename;
char ev_type;
--- 1328,1334 ----
* ----------
*/
static void
! make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc, int prettyFlags)
{
char *rulename;
char ev_type;
***************
*** 1321,1329 ****
/*
* Build the rules definition text
*/
! appendStringInfo(buf, "CREATE RULE %s AS ON ",
quote_identifier(rulename));
/* The event the rule is fired for */
switch (ev_type)
{
--- 1382,1395 ----
/*
* Build the rules definition text
*/
! 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)
{
***************
*** 1366,1371 ****
--- 1432,1439 ----
deparse_context context;
deparse_namespace dpns;
+ if (prettyFlags & PRETTYFLAG_INDENT)
+ appendStringInfoString(buf, "\n ");
appendStringInfo(buf, " WHERE ");
qual = stringToNode(ev_qual);
***************
*** 1387,1392 ****
--- 1455,1462 ----
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;
***************
*** 1410,1417 ****
foreach(action, actions)
{
query = (Query *) lfirst(action);
! get_query_def(query, buf, NIL, NULL);
! appendStringInfo(buf, "; ");
}
appendStringInfo(buf, ");");
}
--- 1480,1490 ----
foreach(action, actions)
{
query = (Query *) lfirst(action);
! get_query_def(query, buf, NIL, NULL, prettyFlags, 0);
! if (prettyFlags)
! appendStringInfo(buf, ";\n");
! else
! appendStringInfo(buf, "; ");
}
appendStringInfo(buf, ");");
}
***************
*** 1424,1430 ****
Query *query;
query = (Query *) lfirst(actions);
! get_query_def(query, buf, NIL, NULL);
appendStringInfo(buf, ";");
}
}
--- 1497,1503 ----
Query *query;
query = (Query *) lfirst(actions);
! get_query_def(query, buf, NIL, NULL, prettyFlags, 0);
appendStringInfo(buf, ";");
}
}
***************
*** 1436,1442 ****
* ----------
*/
static void
! make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc)
{
Query *query;
char ev_type;
--- 1509,1515 ----
* ----------
*/
static void
! make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc, int prettyFlags)
{
Query *query;
char ev_type;
***************
*** 1490,1496 ****
ev_relation = heap_open(ev_class, AccessShareLock);
! get_query_def(query, buf, NIL, RelationGetDescr(ev_relation));
appendStringInfo(buf, ";");
heap_close(ev_relation, AccessShareLock);
--- 1563,1569 ----
ev_relation = heap_open(ev_class, AccessShareLock);
! get_query_def(query, buf, NIL, RelationGetDescr(ev_relation), prettyFlags, 0);
appendStringInfo(buf, ";");
heap_close(ev_relation, AccessShareLock);
***************
*** 1506,1512 ****
*/
static void
get_query_def(Query *query, StringInfo buf, List *parentnamespace,
! TupleDesc resultDesc)
{
deparse_context context;
deparse_namespace dpns;
--- 1579,1585 ----
*/
static void
get_query_def(Query *query, StringInfo buf, List *parentnamespace,
! TupleDesc resultDesc, int prettyFlags, int startIndent)
{
deparse_context context;
deparse_namespace dpns;
***************
*** 1515,1520 ****
--- 1588,1596 ----
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;
***************
*** 1586,1592 ****
/* Add the ORDER BY clause if given */
if (query->sortClause != NIL)
{
! appendStringInfo(buf, " ORDER BY ");
sep = "";
foreach(l, query->sortClause)
{
--- 1662,1668 ----
/* Add the ORDER BY clause if given */
if (query->sortClause != NIL)
{
! appendContextKeyword(context, " ORDER BY ", -PRETTYINDENT_STD,
PRETTYINDENT_STD, 1);
sep = "";
foreach(l, query->sortClause)
{
***************
*** 1615,1626 ****
/* Add the LIMIT clause if given */
if (query->limitOffset != NULL)
{
! appendStringInfo(buf, " OFFSET ");
get_rule_expr(query->limitOffset, context, false);
}
if (query->limitCount != NULL)
{
! appendStringInfo(buf, " LIMIT ");
if (IsA(query->limitCount, Const) &&
((Const *) query->limitCount)->constisnull)
appendStringInfo(buf, "ALL");
--- 1691,1702 ----
/* Add the LIMIT clause if given */
if (query->limitOffset != NULL)
{
! appendContextKeyword(context, " OFFSET ", -PRETTYINDENT_STD,
PRETTYINDENT_STD, 0);
get_rule_expr(query->limitOffset, context, false);
}
if (query->limitCount != NULL)
{
! appendContextKeyword(context, " LIMIT ", -PRETTYINDENT_STD,
PRETTYINDENT_STD, 0);
if (IsA(query->limitCount, Const) &&
((Const *) query->limitCount)->constisnull)
appendStringInfo(buf, "ALL");
***************
*** 1641,1646 ****
--- 1717,1727 ----
/*
* 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 */
***************
*** 1720,1733 ****
/* Add the WHERE clause if given */
if (query->jointree->quals != NULL)
{
! appendStringInfo(buf, " WHERE ");
get_rule_expr(query->jointree->quals, context, false);
}
/* Add the GROUP BY clause if given */
if (query->groupClause != NULL)
{
! appendStringInfo(buf, " GROUP BY ");
sep = "";
foreach(l, query->groupClause)
{
--- 1801,1814 ----
/* Add the WHERE clause if given */
if (query->jointree->quals != NULL)
{
! 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)
{
! appendContextKeyword(context, " GROUP BY ", -PRETTYINDENT_STD,
PRETTYINDENT_STD, 1);
sep = "";
foreach(l, query->groupClause)
{
***************
*** 1743,1749 ****
/* Add the HAVING clause if given */
if (query->havingQual != NULL)
{
! appendStringInfo(buf, " HAVING ");
get_rule_expr(query->havingQual, context, false);
}
}
--- 1824,1830 ----
/* Add the HAVING clause if given */
if (query->havingQual != NULL)
{
! appendContextKeyword(context, " HAVING ", -PRETTYINDENT_STD,
PRETTYINDENT_STD, 0);
get_rule_expr(query->havingQual, context, false);
}
}
***************
*** 1761,1795 ****
Query *subquery = rte->subquery;
Assert(subquery != NULL);
! get_query_def(subquery, buf, context->namespaces, resultDesc);
}
else if (IsA(setOp, SetOperationStmt))
{
SetOperationStmt *op = (SetOperationStmt *) setOp;
- appendStringInfo(buf, "((");
get_setop_query(op->larg, query, context, resultDesc);
switch (op->op)
{
case SETOP_UNION:
! appendStringInfo(buf, ") UNION ");
break;
case SETOP_INTERSECT:
! appendStringInfo(buf, ") INTERSECT ");
break;
case SETOP_EXCEPT:
! appendStringInfo(buf, ") EXCEPT ");
break;
default:
elog(ERROR, "get_setop_query: unexpected set op %d",
(int) op->op);
}
if (op->all)
! appendStringInfo(buf, "ALL (");
else
! appendStringInfo(buf, "(");
get_setop_query(op->rarg, query, context, resultDesc);
! appendStringInfo(buf, "))");
}
else
{
--- 1842,1905 ----
Query *subquery = rte->subquery;
Assert(subquery != NULL);
! get_query_def(subquery, buf, context->namespaces, resultDesc,
context->prettyFlags, context->indentLevel);
}
else if (IsA(setOp, SetOperationStmt))
{
SetOperationStmt *op = (SetOperationStmt *) setOp;
+ bool need_paren=(PRETTY_PAREN(context) ? !IsA(op->rarg, RangeTblRef) :
true);
+
+ if (!PRETTY_PAREN(context))
+ appendStringInfoString(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:
! appendContextKeyword(context, "UNION ",
-PRETTYINDENT_STD, 0, 0);
break;
case SETOP_INTERSECT:
! appendContextKeyword(context, "INTERSECT ",
-PRETTYINDENT_STD, 0, 0);
break;
case SETOP_EXCEPT:
! appendContextKeyword(context, "EXCEPT ",
-PRETTYINDENT_STD, 0, 0);
break;
default:
elog(ERROR, "get_setop_query: unexpected set op %d",
(int) op->op);
}
if (op->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
! appendStringInfoChar(buf, '(');
!
get_setop_query(op->rarg, query, context, resultDesc);
!
! if (PRETTY_PAREN(context))
! {
! if (need_paren)
! appendStringInfoChar(buf, ')');
! }
! else
! appendStringInfoString(buf, "))");
}
else
{
***************
*** 1862,1867 ****
--- 1972,1983 ----
*/
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));
***************
*** 1883,1889 ****
/* Add the VALUES or the SELECT */
if (select_rte == NULL)
{
! appendStringInfo(buf, "VALUES (");
sep = "";
foreach(l, query->targetList)
{
--- 1999,2005 ----
/* Add the VALUES or the SELECT */
if (select_rte == NULL)
{
! appendContextKeyword(context, "VALUES (", -PRETTYINDENT_STD,
PRETTYINDENT_STD, 2);
sep = "";
foreach(l, query->targetList)
{
***************
*** 1899,1905 ****
appendStringInfoChar(buf, ')');
}
else
! get_query_def(select_rte->subquery, buf, NIL, NULL);
}
--- 2015,2021 ----
appendStringInfoChar(buf, ')');
}
else
! get_query_def(select_rte->subquery, buf, NIL, NULL,
context->prettyFlags, context->indentLevel);
}
***************
*** 1920,1925 ****
--- 2036,2046 ----
*/
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));
***************
*** 1953,1959 ****
/* Finally add a WHERE clause if given */
if (query->jointree->quals != NULL)
{
! appendStringInfo(buf, " WHERE ");
get_rule_expr(query->jointree->quals, context, false);
}
}
--- 2074,2080 ----
/* Finally add a WHERE clause if given */
if (query->jointree->quals != NULL)
{
! appendContextKeyword(context, " WHERE ", -PRETTYINDENT_STD,
PRETTYINDENT_STD, 1);
get_rule_expr(query->jointree->quals, context, false);
}
}
***************
*** 1974,1979 ****
--- 2095,2105 ----
*/
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));
***************
*** 1981,1987 ****
/* Add a WHERE clause if given */
if (query->jointree->quals != NULL)
{
! appendStringInfo(buf, " WHERE ");
get_rule_expr(query->jointree->quals, context, false);
}
}
--- 2107,2113 ----
/* Add a WHERE clause if given */
if (query->jointree->quals != NULL)
{
! appendContextKeyword(context, " WHERE ", -PRETTYINDENT_STD,
PRETTYINDENT_STD, 1);
get_rule_expr(query->jointree->quals, context, false);
}
}
***************
*** 2000,2005 ****
--- 2126,2132 ----
{
NotifyStmt *stmt = (NotifyStmt *) query->utilityStmt;
+ appendContextKeyword(context, "", 0, PRETTYINDENT_STD, 1);
appendStringInfo(buf, "NOTIFY %s",
quote_qualified_identifier(stmt->relation->schemaname,
stmt->relation->relname));
***************
*** 2140,2145 ****
--- 2267,2508 ----
}
+ /********************************************
+ * get_simple_binary_op_name
+ * helper function for isSimpleNode
+ * will return single char binary operator
+ *******************************************/
+
+ static 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);
+ char *op = generate_operator_name(expr->opno, exprType(arg1),
exprType(arg2));
+
+ if (strlen(op) == 1)
+ return op;
+ }
+ return 0;
+ }
+
+
+ /***************************************
+ * check if given node is simple.
+ * false : not simple
+ * true : simple in the context of parent node's type
+ ***************************************/
+
+ static bool isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
+ {
+ if (!node)
+ return true;
+
+ switch (nodeTag(node))
+ {
+ // single words: always simple
+ case T_Var:
+ case T_Const:
+ case T_Param:
+
+ // function-like: name(..) or name[..]
+ case T_ArrayRef:
+ case T_ArrayExpr:
+ case T_CoalesceExpr:
+ case T_NullIfExpr:
+ case T_Aggref:
+ case T_FuncExpr:
+
+ // CASE keywords act as parentheses
+ case T_CaseExpr:
+ return true;
+
+ // appears simple since . has top precedence, unless parent is T_FieldSelect
itself!
+ case T_FieldSelect:
+ return (nodeTag(parentNode) == T_FieldSelect ? false : true);
+
+
+ // maybe simple, check args
+ case T_CoerceToDomain:
+ return isSimpleNode((Node*) ((CoerceToDomain*)node)->arg, node,
prettyFlags);
+ case T_RelabelType:
+ return isSimpleNode((Node*) ((RelabelType*)node)->arg, node, prettyFlags);
+
+
+ // depends on parent node type; needs further checking
+ case T_OpExpr:
+ {
+ if (prettyFlags & PRETTYFLAG_PAREN && nodeTag(parentNode) == T_OpExpr)
+ {
+ char *op=get_simple_binary_op_name((OpExpr*)node);
+ char *parentOp=get_simple_binary_op_name((OpExpr*)parentNode);
+ if (!op || !parentOp)
+ return false;
+
+ // we know only these basic operators
+ if (!strchr("+-*/%", *op) || !strchr("+-*/%", *parentOp))
+ return false;
+
+ // natural operator precedence, so we don't need parentheses
+ if (strchr("*/%", *op) || strchr("+-", *parentOp))
+ return true;
+
+ return false;
+ }
+ // else do the same stuff as for T_SubLink et al.
+ }
+ 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=((BoolExpr*)node)->boolop;
+ BoolExprType 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;
+ }
+ // these are not completely implemented; so far, they're simple
+ case T_SubPlan:
+ case T_CoerceToDomainValue:
+ return true;
+
+ case T_ScalarArrayOpExpr:
+ // need to check
+ default:
+ break;
+ }
+ // those we don't know: in dubio complexo
+ return false;
+ }
+
+
+ /******************************************
+ * appendContextKeyword
+ * append spaces to buffer
+ ******************************************/
+ static void appendStringInfoSpace(StringInfo buf, int count)
+ {
+ while (count-- > 0)
+ appendStringInfoChar(buf, ' ');
+ }
+
+ /******************************************
+ * appendContextKeyword
+ * performing a line break, and indentation
+ * if prettyPrint is enabled.
+ * Otherwise, only the keyword is appended
+ *****************************************/
+
+ static void appendContextKeyword(deparse_context *context, 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');
+ appendStringInfoSpace(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 - parsing expr using get_rule_expr,
+ * embracing the string with parentheses if necessary for prettyPrint.
+ * never embracing 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 = 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
*
***************
*** 2294,2305 ****
List *args = expr->args;
Node *arg1 = (Node *) lfirst(args);
Node *arg2 = (Node *) lsecond(args);
!
! appendStringInfoChar(buf, '(');
! get_rule_expr(arg1, context, true);
appendStringInfo(buf, " IS DISTINCT FROM ");
! get_rule_expr(arg2, context, true);
! appendStringInfoChar(buf, ')');
}
break;
--- 2657,2669 ----
List *args = expr->args;
Node *arg1 = (Node *) lfirst(args);
Node *arg2 = (Node *) lsecond(args);
! if (!PRETTY_PAREN(context))
! appendStringInfoChar(buf, '(');
! get_rule_expr_paren(arg1, context, true, node);
appendStringInfo(buf, " IS DISTINCT FROM ");
! get_rule_expr_paren(arg2, context, true, node);
! if (!PRETTY_PAREN(context))
! appendStringInfoChar(buf, ')');
}
break;
***************
*** 2310,2324 ****
Node *arg1 = (Node *) lfirst(args);
Node *arg2 = (Node *) lsecond(args);
! appendStringInfoChar(buf, '(');
! get_rule_expr(arg1, context, true);
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, "))");
}
break;
--- 2674,2692 ----
Node *arg1 = (Node *) lfirst(args);
Node *arg2 = (Node *) lsecond(args);
! 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_paren(arg2, context, true, node);
! appendStringInfoString(buf, ")");
!
! if (!PRETTY_PAREN(context))
! appendStringInfoChar(buf, ')');
}
break;
***************
*** 2330,2362 ****
switch (expr->boolop)
{
case AND_EXPR:
! appendStringInfoChar(buf, '(');
! get_rule_expr((Node *) lfirst(args),
context, false);
while ((args = lnext(args)) != NIL)
{
appendStringInfo(buf, " AND ");
! get_rule_expr((Node *)
lfirst(args), context,
!
false);
}
! appendStringInfoChar(buf, ')');
break;
case OR_EXPR:
! appendStringInfoChar(buf, '(');
! get_rule_expr((Node *) lfirst(args),
context, false);
while ((args = lnext(args)) != NIL)
{
appendStringInfo(buf, " OR ");
! get_rule_expr((Node *)
lfirst(args), context,
!
false);
}
! appendStringInfoChar(buf, ')');
break;
case NOT_EXPR:
! appendStringInfo(buf, "(NOT ");
! get_rule_expr((Node *) lfirst(args),
context, false);
! appendStringInfoChar(buf, ')');
break;
default:
--- 2698,2737 ----
switch (expr->boolop)
{
case AND_EXPR:
! 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_paren((Node *)
lfirst(args), context,
!
false, node);
}
! if (!PRETTY_PAREN(context))
! appendStringInfoChar(buf, ')');
break;
case OR_EXPR:
! 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_paren((Node *)
lfirst(args), context,
!
false, node);
}
! if (!PRETTY_PAREN(context))
! appendStringInfoChar(buf, ')');
break;
case NOT_EXPR:
! 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:
***************
*** 2404,2412 ****
* 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));
}
break;
--- 2779,2790 ----
* arg.fieldname, but most cases where FieldSelect is
used
* are *not* simple. So, always use parenthesized
syntax.
*/
! 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;
***************
*** 2419,2425 ****
!showimplicit)
{
/* don't show the implicit cast */
! get_rule_expr(arg, context, showimplicit);
}
else
{
--- 2797,2803 ----
!showimplicit)
{
/* don't show the implicit cast */
! get_rule_expr_paren(arg, context,
showimplicit, node);
}
else
{
***************
*** 2431,2439 ****
*/
arg = strip_type_coercion(arg,
relabel->resulttype);
! appendStringInfoChar(buf, '(');
! get_rule_expr(arg, context, showimplicit);
! appendStringInfo(buf, ")::%s",
format_type_with_typemod(relabel->resulttype,
relabel->resulttypmod));
}
--- 2809,2821 ----
*/
arg = strip_type_coercion(arg,
relabel->resulttype);
! 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));
}
***************
*** 2445,2463 ****
CaseExpr *caseexpr = (CaseExpr *) node;
List *temp;
! appendStringInfo(buf, "CASE");
foreach(temp, caseexpr->args)
{
CaseWhen *when = (CaseWhen *) lfirst(temp);
! appendStringInfo(buf, " WHEN ");
get_rule_expr((Node *) when->expr, context,
false);
appendStringInfo(buf, " THEN ");
get_rule_expr((Node *) when->result, context,
true);
}
! appendStringInfo(buf, " ELSE ");
get_rule_expr((Node *) caseexpr->defresult, context,
true);
! appendStringInfo(buf, " END");
}
break;
--- 2827,2853 ----
CaseExpr *caseexpr = (CaseExpr *) node;
List *temp;
! appendContextKeyword(context, "CASE", 0,
PRETTYINDENT_VAR, 0);
foreach(temp, caseexpr->args)
{
CaseWhen *when = (CaseWhen *) lfirst(temp);
! 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);
}
! if (!PRETTY_INDENT(context))
! appendStringInfoChar(buf, ' ');
! appendContextKeyword(context, "ELSE ", 0, 0, 0);
get_rule_expr((Node *) caseexpr->defresult, context,
true);
! if (!PRETTY_INDENT(context))
! appendStringInfoChar(buf, ' ');
! appendContextKeyword(context, "END",
-PRETTYINDENT_VAR, 0, 0);
}
break;
***************
*** 2525,2544 ****
{
NullTest *ntest = (NullTest *) node;
! appendStringInfo(buf, "(");
! get_rule_expr((Node *) ntest->arg, context, true);
switch (ntest->nulltesttype)
{
case IS_NULL:
! appendStringInfo(buf, " IS NULL)");
break;
case IS_NOT_NULL:
! appendStringInfo(buf, " IS NOT NULL)");
break;
default:
elog(ERROR, "get_rule_expr: unexpected
nulltesttype %d",
(int) ntest->nulltesttype);
}
}
break;
--- 2915,2937 ----
{
NullTest *ntest = (NullTest *) node;
! 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");
break;
case IS_NOT_NULL:
! appendStringInfo(buf, " IS NOT NULL");
break;
default:
elog(ERROR, "get_rule_expr: unexpected
nulltesttype %d",
(int) ntest->nulltesttype);
}
+ if (!PRETTY_PAREN(context))
+ appendStringInfoChar(buf, ')');
}
break;
***************
*** 2546,2577 ****
{
BooleanTest *btest = (BooleanTest *) node;
! appendStringInfo(buf, "(");
! get_rule_expr((Node *) btest->arg, context, false);
switch (btest->booltesttype)
{
case IS_TRUE:
! appendStringInfo(buf, " IS TRUE)");
break;
case IS_NOT_TRUE:
! appendStringInfo(buf, " IS NOT TRUE)");
break;
case IS_FALSE:
! appendStringInfo(buf, " IS FALSE)");
break;
case IS_NOT_FALSE:
! appendStringInfo(buf, " IS NOT
FALSE)");
break;
case IS_UNKNOWN:
! appendStringInfo(buf, " IS UNKNOWN)");
break;
case IS_NOT_UNKNOWN:
! appendStringInfo(buf, " IS NOT
UNKNOWN)");
break;
default:
elog(ERROR, "get_rule_expr: unexpected
booltesttype %d",
(int) btest->booltesttype);
}
}
break;
--- 2939,2973 ----
{
BooleanTest *btest = (BooleanTest *) node;
! 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");
break;
case IS_NOT_TRUE:
! appendStringInfo(buf, " IS NOT TRUE");
break;
case IS_FALSE:
! appendStringInfo(buf, " IS FALSE");
break;
case IS_NOT_FALSE:
! appendStringInfo(buf, " IS NOT FALSE");
break;
case IS_UNKNOWN:
! appendStringInfo(buf, " IS UNKNOWN");
break;
case IS_NOT_UNKNOWN:
! appendStringInfo(buf, " IS NOT
UNKNOWN");
break;
default:
elog(ERROR, "get_rule_expr: unexpected
booltesttype %d",
(int) btest->booltesttype);
}
+ if (!PRETTY_PAREN(context))
+ appendStringInfoChar(buf, ')');
}
break;
***************
*** 2593,2601 ****
}
else
{
! appendStringInfoChar(buf, '(');
! get_rule_expr(arg, context, false);
! appendStringInfo(buf, ")::%s",
format_type_with_typemod(ctest->resulttype,
ctest->resulttypmod));
}
--- 2989,3002 ----
}
else
{
! 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));
}
***************
*** 2627,2645 ****
Oid opno = expr->opno;
List *args = expr->args;
! appendStringInfoChar(buf, '(');
if (length(args) == 2)
{
/* binary operator */
Node *arg1 = (Node *) lfirst(args);
Node *arg2 = (Node *) lsecond(args);
!
! get_rule_expr(arg1, context, true);
appendStringInfo(buf, " %s ",
generate_operator_name(opno,
exprType(arg1),
exprType(arg2)));
! get_rule_expr(arg2, context, true);
}
else
{
--- 3028,3046 ----
Oid opno = expr->opno;
List *args = expr->args;
! 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_paren(arg1, context, true, (Node*)expr);
appendStringInfo(buf, " %s ",
generate_operator_name(opno,
exprType(arg1),
exprType(arg2)));
! get_rule_expr_paren(arg2, context, true, (Node*)expr);
}
else
{
***************
*** 2661,2670 ****
generate_operator_name(opno,
InvalidOid,
exprType(arg)));
! get_rule_expr(arg, context, true);
break;
case 'r':
! get_rule_expr(arg, context, true);
appendStringInfo(buf, " %s",
generate_operator_name(opno,
exprType(arg),
--- 3062,3071 ----
generate_operator_name(opno,
InvalidOid,
exprType(arg)));
! get_rule_expr_paren(arg, context, true, (Node*)expr);
break;
case 'r':
! get_rule_expr_paren(arg, context, true, (Node*)expr);
appendStringInfo(buf, " %s",
generate_operator_name(opno,
exprType(arg),
***************
*** 2675,2681 ****
}
ReleaseSysCache(tp);
}
! appendStringInfoChar(buf, ')');
}
/*
--- 3076,3083 ----
}
ReleaseSysCache(tp);
}
! if (!PRETTY_PAREN(context))
! appendStringInfoChar(buf, ')');
}
/*
***************
*** 2698,2704 ****
*/
if (expr->funcformat == COERCE_IMPLICIT_CAST && !showimplicit)
{
! get_rule_expr((Node *) lfirst(expr->args), context, showimplicit);
return;
}
--- 3100,3106 ----
*/
if (expr->funcformat == COERCE_IMPLICIT_CAST && !showimplicit)
{
! get_rule_expr_paren((Node *) lfirst(expr->args), context,
showimplicit, (Node*)expr);
return;
}
***************
*** 2724,2732 ****
*/
arg = strip_type_coercion(arg, rettype);
! appendStringInfoChar(buf, '(');
! get_rule_expr(arg, context, showimplicit);
! appendStringInfo(buf, ")::%s",
format_type_with_typemod(rettype,
coercedTypmod));
return;
--- 3126,3139 ----
*/
arg = strip_type_coercion(arg, rettype);
! 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;
***************
*** 3047,3053 ****
if (need_paren)
appendStringInfoChar(buf, '(');
! get_query_def(query, buf, context->namespaces, NULL);
if (need_paren)
appendStringInfo(buf, "))");
--- 3454,3460 ----
if (need_paren)
appendStringInfoChar(buf, '(');
! get_query_def(query, buf, context->namespaces, NULL, context->prettyFlags,
context->indentLevel);
if (need_paren)
appendStringInfo(buf, "))");
***************
*** 3064,3070 ****
get_from_clause(Query *query, deparse_context *context)
{
StringInfo buf = context->buf;
! char *sep;
List *l;
/*
--- 3471,3477 ----
get_from_clause(Query *query, deparse_context *context)
{
StringInfo buf = context->buf;
! char *sep=0;
List *l;
/*
***************
*** 3074,3080 ****
* sufficient to check here.) Also ignore the rule pseudo-RTEs for NEW
* and OLD.
*/
- sep = " FROM ";
foreach(l, query->jointree->fromlist)
{
--- 3481,3486 ----
***************
*** 3093,3099 ****
continue;
}
! appendStringInfo(buf, sep);
get_from_clause_item(jtnode, query, context);
sep = ", ";
}
--- 3499,3509 ----
continue;
}
! if (!sep)
! appendContextKeyword(context, " FROM ", -PRETTYINDENT_STD,
PRETTYINDENT_STD, 2);
! else
! appendStringInfo(buf, sep);
!
get_from_clause_item(jtnode, query, context);
sep = ", ";
}
***************
*** 3122,3128 ****
case RTE_SUBQUERY:
/* Subquery RTE */
appendStringInfoChar(buf, '(');
! get_query_def(rte->subquery, buf, context->namespaces,
NULL);
appendStringInfoChar(buf, ')');
break;
case RTE_FUNCTION:
--- 3532,3539 ----
case RTE_SUBQUERY:
/* Subquery RTE */
appendStringInfoChar(buf, '(');
! get_query_def(rte->subquery, buf, context->namespaces,
NULL,
! context->prettyFlags,
context->indentLevel);
appendStringInfoChar(buf, ')');
break;
case RTE_FUNCTION:
***************
*** 3144,3150 ****
{
List *col;
! appendStringInfo(buf, "(");
foreach(col, rte->alias->colnames)
{
if (col != rte->alias->colnames)
--- 3555,3561 ----
{
List *col;
! appendStringInfoChar(buf, '(');
foreach(col, rte->alias->colnames)
{
if (col != rte->alias->colnames)
***************
*** 3178,3213 ****
else if (IsA(jtnode, JoinExpr))
{
JoinExpr *j = (JoinExpr *) jtnode;
- 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, "get_from_clause_item: unknown join type
%d",
(int) j->jointype);
}
get_from_clause_item(j->rarg, query, context);
if (!j->isNatural)
{
if (j->using)
--- 3589,3666 ----
else if (IsA(jtnode, JoinExpr))
{
JoinExpr *j = (JoinExpr *) jtnode;
+ bool need_paren_on_right = PRETTY_PAREN(context) && !IsA(j->rarg,
RangeTblRef);
+
+ if (!PRETTY_PAREN(context) || j->alias != NULL)
+ appendStringInfoChar(buf, '(');
get_from_clause_item(j->larg, query, context);
+
if (j->isNatural)
{
+ 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, "get_from_clause_item: unknown 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, "get_from_clause_item: unknown 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)
***************
*** 3226,3237 ****
}
else if (j->quals)
{
! appendStringInfo(buf, " ON (");
get_rule_expr(j->quals, context, false);
! appendStringInfoChar(buf, ')');
}
}
! appendStringInfoChar(buf, ')');
/* Yes, it's correct to put alias after the right paren ... */
if (j->alias != NULL)
{
--- 3679,3695 ----
}
else if (j->quals)
{
! appendStringInfo(buf, " ON ");
! if (!PRETTY_PAREN(context))
! appendStringInfoChar(buf, '(');
get_rule_expr(j->quals, context, false);
! if (!PRETTY_PAREN(context))
! 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)
{
***************
*** 3241,3247 ****
{
List *col;
! appendStringInfo(buf, "(");
foreach(col, j->alias->colnames)
{
if (col != j->alias->colnames)
--- 3699,3705 ----
{
List *col;
! appendStringInfoChar(buf, '(');
foreach(col, j->alias->colnames)
{
if (col != j->alias->colnames)
---------------------------(end of broadcast)--------------------------- TIP 7: don't forget to increase your free space map settings
