Re: ruleutils with pretty-print option - Mailing list pgsql-patches

From Andreas Pflug
Subject Re: ruleutils with pretty-print option
Date
Msg-id 3F1D3A73.7010108@pse-consulting.de
Whole thread Raw
In response to Re: ruleutils with pretty-print option  (Bruce Momjian <pgman@candle.pha.pa.us>)
Responses Re: ruleutils with pretty-print option
Re: ruleutils with pretty-print option
Re: ruleutils with pretty-print option
Re: ruleutils with pretty-print option
List pgsql-patches
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)

pgsql-patches by date:

Previous
From: Lee Kindness
Date:
Subject: PATCH: Memory leaks on start-up
Next
From: Karel Zak
Date:
Subject: Czech NLS