Add pretty-printing variants of pg_get_viewdef and related functions.
authorTom Lane <[email protected]>
Wed, 30 Jul 2003 22:56:24 +0000 (22:56 +0000)
committerTom Lane <[email protected]>
Wed, 30 Jul 2003 22:56:24 +0000 (22:56 +0000)
Patch from Andreas Pflug.

doc/src/sgml/func.sgml
src/backend/utils/adt/ruleutils.c
src/include/catalog/catversion.h
src/include/catalog/pg_proc.h
src/include/utils/builtins.h

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