Re: ruleutils with pretty-print option - Mailing list pgsql-patches
From | Bruce Momjian |
---|---|
Subject | Re: ruleutils with pretty-print option |
Date | |
Msg-id | 200307221556.h6MFusZ20863@candle.pha.pa.us Whole thread Raw |
In response to | Re: ruleutils with pretty-print option (Andreas Pflug <pgadmin@pse-consulting.de>) |
List | pgsql-patches |
Your patch has been added to the PostgreSQL unapplied patches list at: http://momjian.postgresql.org/cgi-bin/pgpatches I will try to apply it within the next 48 hours. --------------------------------------------------------------------------- Andreas Pflug wrote: > Bruce Momjian wrote: > > >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) -- Bruce Momjian | http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 359-1001 + If your life is a hard drive, | 13 Roberts Road + Christ can be your backup. | Newtown Square, Pennsylvania 19073
pgsql-patches by date: