Re: ruleutils with pretty-print option

From: Bruce Momjian <pgman(at)candle(dot)pha(dot)pa(dot)us>
To: Andreas Pflug <pgadmin(at)pse-consulting(dot)de>
Cc: pgsql-patches(at)postgresql(dot)org
Subject: Re: ruleutils with pretty-print option
Date: 2003-07-31 04:57:00
Message-ID: 200307310457.h6V4v1m13511@candle.pha.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-patches


Patch applied, modified by Tom and myself.

---------------------------------------------------------------------------

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(at)candle(dot)pha(dot)pa(dot)us | (610) 359-1001
+ If your life is a hard drive, | 13 Roberts Road
+ Christ can be your backup. | Newtown Square, Pennsylvania 19073

In response to

Browse pgsql-patches by date

  From Date Subject
Next Message Christopher Kings-Lynne 2003-07-31 05:15:04 Re: ruleutils with pretty-print option
Previous Message Bruce Momjian 2003-07-31 04:52:19 Re: ruleutils with pretty-print option