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

From Bruce Momjian
Subject Re: ruleutils with pretty-print option
Date
Msg-id 200307220352.h6M3qZx28876@candle.pha.pa.us
Whole thread Raw
In response to Re: ruleutils with pretty-print option  (Andreas Pflug <pgadmin@pse-consulting.de>)
Responses Re: ruleutils with pretty-print option  (Andreas Pflug <pgadmin@pse-consulting.de>)
List pgsql-patches
Andreas, looks good, but I need a diff -c, context diff.

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

Andreas Pflug wrote:
> Hi Bruce,
> so here's the complete patch against the current cvs.
>
> Description:
> The attached patches will add
>    pg_get_ruledef(oid, bool)
>    pg_get_viewdef(text, bool)
>    pg_get_viewdef(oid, bool)
>    pg_get_indexdef(oid, int4, bool)
>    pg_get_constraintdef(oid, bool)
>    pg_get_expr(text, oid, bool)
>
> If the last parameter "pretty-print" is false, these function will
> return the same result as their original counterparts without that
> parameter. The source is based on ruleutils.c 1.145 and pg_proc 1.309,
> and should return exactly the same result as before if no pretty-print
> is selected. My tests didn't show any differences for pg_dump output
> with old or new version.
>
> If the last parameter "pretty-print" is true, parentheses are checked;
> only necessary parentheses will be emitted. Additionally, line and
> indentation formatting is performed.
>
> pg_get_indexdef has one additional parameter. The second parameter
> (int4) selects the nth expression of an index (1..indnatts). If zero, a
> complete CREATE INDEX statement is generated to obtain the previous
> behaviour.
> The third is the pretty-print option as described.
>
> example:
> pg_get_indexdef(12345, 0, true)  -> CREATE INDEX foo ON bar (numcol,
> length(txtcol), intcol2, (8+length(txtcol2)))
> pg_get_indexdef(12345, 1, true)  -> numcol
> pg_get_indexdef(12345, 2, true)  -> length(txtcol)
> pg_get_indexdef(12345, 3, true)  -> intcol2
> pg_get_indexdef(12345, 4, true)  -> (8+length(txtcol2))
>
> Regards,
> Andreas
>

> Index: pg_proc.h
> ===================================================================
> RCS file: /projects/cvsroot/pgsql-server/src/include/catalog/pg_proc.h,v
> retrieving revision 1.309
> diff -r1.309 pg_proc.h
> 3407a3408,3421
> > /* 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");
> >

> Index: ruleutils.c
> ===================================================================
> RCS file: /projects/cvsroot/pgsql-server/src/backend/utils/adt/ruleutils.c,v
> retrieving revision 1.145
> diff -r1.145 ruleutils.c
> 73a74,92
> > /******************************
> >  * 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)
> >
> >
> 83a103,104
> >         int             prettyFlags;            /* enabling/disabling of pretty-print functions */
> >         int             indentLevel;            /* for prettyPrint, current space indents are counted */
> 126c147,153
> < static text *pg_do_getviewdef(Oid viewoid);
> ---
> > 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);
> 129,130c156,157
> < static void make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc);
> < static void make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc);
> ---
> > static void make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc, int prettyFlags);
> > static void make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc, int prettyFlags);
> 132c159
> <               TupleDesc resultDesc);
> ---
> >               TupleDesc resultDesc, int prettyFlags, int startIndent);
> 194a222
> >     int             prettyFlags = !PG_ARGISNULL(1) && PG_GETARG_BOOL(1) ? PRETTYFLAG_PAREN|PRETTYFLAG_INDENT : 0;
> 244c272
> <     make_ruledef(&buf, ruletup, rulettc);
> ---
> >     make_ruledef(&buf, ruletup, rulettc, prettyFlags);
> 274a303
> >     int             prettyFlags = !PG_ARGISNULL(1) && PG_GETARG_BOOL(1) ? PRETTYFLAG_PAREN|PRETTYFLAG_INDENT : 0;
> 276c305
> <     ruledef = pg_do_getviewdef(viewoid);
> ---
> >     ruledef = pg_do_getviewdef(viewoid, prettyFlags);
> 287a317
> >     int             prettyFlags = !PG_ARGISNULL(1) && PG_GETARG_BOOL(1) ? PRETTYFLAG_PAREN|PRETTYFLAG_INDENT : 0;
> 293c323
> <     ruledef = pg_do_getviewdef(viewoid);
> ---
> >     ruledef = pg_do_getviewdef(viewoid, prettyFlags);
> 301c331
> < pg_do_getviewdef(Oid viewoid)
> ---
> > pg_do_getviewdef(Oid viewoid, int prettyFlags)
> 356c386
> <         make_viewdef(&buf, ruletup, rulettc);
> ---
> >         make_viewdef(&buf, ruletup, rulettc, prettyFlags);
> 546a577,578
> >     int        colno = PG_ARGISNULL(1) ? 0 : PG_GETARG_INT32(1);
> >     int        prettyFlags = !PG_ARGISNULL(2) && PG_GETARG_BOOL(2) ? PRETTYFLAG_PAREN|PRETTYFLAG_INDENT : 0;
> 584a617,618
> >          * if colno == 0, we want a complete index definition.
> >          * if colno > 0, we only want the nth expression.
> 610c644,646
> <     appendStringInfo(&buf, "CREATE %sINDEX %s ON %s USING %s (",
> ---
> >
> >     if (!colno)
> >         appendStringInfo(&buf, "CREATE %sINDEX %s ON %s USING %s (",
> 624c660,661
> <         appendStringInfo(&buf, sep);
> ---
> >         if (!colno)
> >             appendStringInfo(&buf, sep);
> 633c670,671
> <             appendStringInfo(&buf, "%s", quote_identifier(attname));
> ---
> >             if (!colno || colno == keyno+1)
> >                 appendStringInfo(&buf, "%s", quote_identifier(attname));
> 646,648c684,688
> <             str = deparse_expression(indexkey, context, false, false);
> <             /* Need parens if it's not a bare function call */
> <             if (indexkey && IsA(indexkey, FuncExpr) &&
> ---
> >             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) &&
> 651c691
> <             else
> ---
> >                 else
> 652a693
> >             }
> 659c700,701
> <         get_opclass_name(idxrec->indclass[keyno], keycoltype,
> ---
> >         if (!colno)
> >             get_opclass_name(idxrec->indclass[keyno], keycoltype,
> 663,668c705
> <     appendStringInfoChar(&buf, ')');
> <
> <     /*
> <      * If it's a partial index, decompile and append the predicate
> <      */
> <     if (!heap_attisnull(ht_idx, Anum_pg_index_indpred))
> ---
> >     if (!colno)
> 669a707,713
> >         appendStringInfoChar(&buf, ')');
> >
> >         /*
> >          * If it's a partial index, decompile and append the predicate
> >          */
> >         if (!heap_attisnull(ht_idx, Anum_pg_index_indpred))
> >         {
> 692c736
> <         str = deparse_expression(node, context, false, false);
> ---
> >         str = deparse_expression_pretty(node, context, false, false, prettyFlags, 0);
> 693a738
> >         }
> 695d739
> <
> 731a776
> >     int      prettyFlags = !PG_ARGISNULL(1) && PG_GETARG_BOOL(1) ? PRETTYFLAG_PAREN|PRETTYFLAG_INDENT : 0;
> 937c982
> <                 consrc = deparse_expression(expr, context, false, false);
> ---
> >                 consrc = deparse_expression_pretty(expr, context, false, false, prettyFlags, 0);
> 1020a1066
> >     int      prettyFlags = !PG_ARGISNULL(2) && PG_GETARG_BOOL(2) ? PRETTYFLAG_PAREN|PRETTYFLAG_INDENT : 0;
> 1044c1090
> <     str = deparse_expression(node, context, false, false);
> ---
> >     str = deparse_expression_pretty(node, context, false, false, prettyFlags, 0);
> 1092a1139,1149
> >  * 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
> 1102a1160,1161
> >  *
> >  * tries to pretty up the output according to prettyFlags
> 1108,1109c1167,1168
> < 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)
> 1117a1177,1178
> >     context.prettyFlags = prettyFlags;
> >     context.indentLevel = startIndent;
> 1270c1331
> < make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc)
> ---
> > make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc, int prettyFlags)
> 1324c1385
> <     appendStringInfo(buf, "CREATE RULE %s AS ON ",
> ---
> >     appendStringInfo(buf, "CREATE RULE %s AS",
> 1326a1388,1392
> >     if (prettyFlags & PRETTYFLAG_INDENT)
> >         appendStringInfoString(buf, "\n    ON ");
> >     else
> >         appendStringInfoString(buf, "ON ");
> >
> 1368a1435,1436
> >         if (prettyFlags & PRETTYFLAG_INDENT)
> >             appendStringInfoString(buf, "\n  ");
> 1389a1458,1459
> >         context.prettyFlags = prettyFlags;
> >         context.indentLevel = PRETTYINDENT_STD;
> 1413,1414c1483,1487
> <             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, "; ");
> 1427c1500
> <         get_query_def(query, buf, NIL, NULL);
> ---
> >         get_query_def(query, buf, NIL, NULL, prettyFlags, 0);
> 1439c1512
> < make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc)
> ---
> > make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc, int prettyFlags)
> 1493c1566
> <     get_query_def(query, buf, NIL, RelationGetDescr(ev_relation));
> ---
> >     get_query_def(query, buf, NIL, RelationGetDescr(ev_relation), prettyFlags, 0);
> 1509c1582
> <               TupleDesc resultDesc)
> ---
> >               TupleDesc resultDesc, int prettyFlags, int startIndent)
> 1517a1591,1593
> >     context.prettyFlags = prettyFlags;
> >     context.indentLevel = startIndent;
> >
> 1589c1665
> <         appendStringInfo(buf, " ORDER BY ");
> ---
> >             appendContextKeyword(context, " ORDER BY ", -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
> 1618c1694
> <         appendStringInfo(buf, " OFFSET ");
> ---
> >         appendContextKeyword(context, " OFFSET ", -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
> 1623c1699
> <         appendStringInfo(buf, " LIMIT ");
> ---
> >         appendContextKeyword(context, " LIMIT ", -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
> 1643a1720,1724
> >     if (PRETTY_INDENT(context))
> >     {
> >         context->indentLevel += PRETTYINDENT_STD;
> >         appendStringInfoChar(buf, ' ');
> >     }
> 1723c1804
> <         appendStringInfo(buf, " WHERE ");
> ---
> >         appendContextKeyword(context, " WHERE ", -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
> 1730c1811
> <         appendStringInfo(buf, " GROUP BY ");
> ---
> >         appendContextKeyword(context, " GROUP BY ", -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
> 1746c1827
> <         appendStringInfo(buf, " HAVING ");
> ---
> >         appendContextKeyword(context, " HAVING ", -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
> 1764c1845
> <         get_query_def(subquery, buf, context->namespaces, resultDesc);
> ---
> >         get_query_def(subquery, buf, context->namespaces, resultDesc, context->prettyFlags, context->indentLevel);
> 1768a1850,1853
> >         bool need_paren=(PRETTY_PAREN(context) ? !IsA(op->rarg, RangeTblRef) : true);
> >
> >         if (!PRETTY_PAREN(context))
> >             appendStringInfoString(buf, "((");
> 1770d1854
> <         appendStringInfo(buf, "((");
> 1771a1856,1860
> >
> >         if (!PRETTY_PAREN(context))
> >             appendStringInfoChar(buf, ')');
> >         if (!PRETTY_INDENT(context))
> >             appendStringInfoChar(buf, ' ');
> 1775c1864
> <                 appendStringInfo(buf, ") UNION ");
> ---
> >                 appendContextKeyword(context, "UNION ", -PRETTYINDENT_STD, 0, 0);
> 1778c1867
> <                 appendStringInfo(buf, ") INTERSECT ");
> ---
> >                 appendContextKeyword(context, "INTERSECT ", -PRETTYINDENT_STD, 0, 0);
> 1781c1870
> <                 appendStringInfo(buf, ") EXCEPT ");
> ---
> >                 appendContextKeyword(context, "EXCEPT ", -PRETTYINDENT_STD, 0, 0);
> 1788c1877,1890
> <             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');
> >             }
> >         }
> 1790c1892,1893
> <             appendStringInfo(buf, "(");
> ---
> >             appendStringInfoChar(buf, '(');
> >
> 1792c1895,1902
> <         appendStringInfo(buf, "))");
> ---
> >
> >         if (PRETTY_PAREN(context))
> >         {
> >             if (need_paren)
> >             appendStringInfoChar(buf, ')');
> >         }
> >         else
> >             appendStringInfoString(buf, "))");
> 1864a1975,1980
> >
> >     if (PRETTY_INDENT(context))
> >     {
> >         context->indentLevel += PRETTYINDENT_STD;
> >         appendStringInfoChar(buf, ' ');
> >     }
> 1886c2002
> <         appendStringInfo(buf, "VALUES (");
> ---
> >         appendContextKeyword(context, "VALUES (", -PRETTYINDENT_STD, PRETTYINDENT_STD, 2);
> 1902c2018
> <         get_query_def(select_rte->subquery, buf, NIL, NULL);
> ---
> >         get_query_def(select_rte->subquery, buf, NIL, NULL, context->prettyFlags, context->indentLevel);
> 1922a2039,2043
> >     if (PRETTY_INDENT(context))
> >     {
> >         appendStringInfoChar(buf, ' ');
> >         context->indentLevel += PRETTYINDENT_STD;
> >     }
> 1956c2077
> <         appendStringInfo(buf, " WHERE ");
> ---
> >         appendContextKeyword(context, " WHERE ", -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
> 1976a2098,2102
> >     if (PRETTY_INDENT(context))
> >     {
> >         context->indentLevel += PRETTYINDENT_STD;
> >         appendStringInfoChar(buf, ' ');
> >     }
> 1984c2110
> <         appendStringInfo(buf, " WHERE ");
> ---
> >         appendContextKeyword(context, " WHERE ", -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
> 2002a2129
> >         appendContextKeyword(context, "", 0, PRETTYINDENT_STD, 1);
> 2142a2270,2505
> > /********************************************
> >  * 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, ')');
> > }
> >
> >
> 2297,2299c2660,2662
> <
> <                 appendStringInfoChar(buf, '(');
> <                 get_rule_expr(arg1, context, true);
> ---
> >                 if (!PRETTY_PAREN(context))
> >                     appendStringInfoChar(buf, '(');
> >                 get_rule_expr_paren(arg1, context, true, node);
> 2301,2302c2664,2666
> <                 get_rule_expr(arg2, context, true);
> <                 appendStringInfoChar(buf, ')');
> ---
> >                 get_rule_expr_paren(arg2, context, true, node);
> >                 if (!PRETTY_PAREN(context))
> >                     appendStringInfoChar(buf, ')');
> 2313,2314c2677,2679
> <                 appendStringInfoChar(buf, '(');
> <                 get_rule_expr(arg1, context, true);
> ---
> >                 if (!PRETTY_PAREN(context))
> >                     appendStringInfoChar(buf, '(');
> >                 get_rule_expr_paren(arg1, context, true, node);
> 2320,2321c2685,2689
> <                 get_rule_expr(arg2, context, true);
> <                 appendStringInfo(buf, "))");
> ---
> >                 get_rule_expr_paren(arg2, context, true, node);
> >                 appendStringInfoString(buf, ")");
> >
> >                 if (!PRETTY_PAREN(context))
> >                     appendStringInfoChar(buf, ')');
> 2333,2334c2701,2703
> <                         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);
> 2338,2339c2707,2708
> <                             get_rule_expr((Node *) lfirst(args), context,
> <                                           false);
> ---
> >                             get_rule_expr_paren((Node *) lfirst(args), context,
> >                                           false, node);
> 2341c2710,2711
> <                         appendStringInfoChar(buf, ')');
> ---
> >                             if (!PRETTY_PAREN(context))
> >                             appendStringInfoChar(buf, ')');
> 2345,2346c2715,2717
> <                         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);
> 2350,2351c2721,2722
> <                             get_rule_expr((Node *) lfirst(args), context,
> <                                           false);
> ---
> >                             get_rule_expr_paren((Node *) lfirst(args), context,
> >                                           false, node);
> 2353c2724,2725
> <                         appendStringInfoChar(buf, ')');
> ---
> >                             if (!PRETTY_PAREN(context))
> >                             appendStringInfoChar(buf, ')');
> 2357,2359c2729,2734
> <                         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, ')');
> 2407,2409c2782,2787
> <                 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));
> 2422c2800
> <                     get_rule_expr(arg, context, showimplicit);
> ---
> >                     get_rule_expr_paren(arg, context, showimplicit, node);
> 2434,2436c2812,2818
> <                     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",
> 2448c2830
> <                 appendStringInfo(buf, "CASE");
> ---
> >                 appendContextKeyword(context, "CASE", 0, PRETTYINDENT_VAR, 0);
> 2453c2835,2838
> <                     appendStringInfo(buf, " WHEN ");
> ---
> >                     if (!PRETTY_INDENT(context))
> >                         appendStringInfoChar(buf, ' ');
> >
> >                     appendContextKeyword(context, "WHEN ", 0, 0, 0);
> 2454a2840
> >
> 2458c2844,2846
> <                 appendStringInfo(buf, " ELSE ");
> ---
> >                 if (!PRETTY_INDENT(context))
> >                     appendStringInfoChar(buf, ' ');
> >                 appendContextKeyword(context, "ELSE ", 0, 0, 0);
> 2460c2848,2850
> <                 appendStringInfo(buf, " END");
> ---
> >                 if (!PRETTY_INDENT(context))
> >                     appendStringInfoChar(buf, ' ');
> >                 appendContextKeyword(context, "END", -PRETTYINDENT_VAR, 0, 0);
> 2528,2529c2918,2920
> <                 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);
> 2533c2924
> <                         appendStringInfo(buf, " IS NULL)");
> ---
> >                         appendStringInfo(buf, " IS NULL");
> 2536c2927
> <                         appendStringInfo(buf, " IS NOT NULL)");
> ---
> >                         appendStringInfo(buf, " IS NOT NULL");
> 2541a2933,2934
> >                 if (!PRETTY_PAREN(context))
> >                     appendStringInfoChar(buf, ')');
> 2549,2550c2942,2944
> <                 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);
> 2554c2948
> <                         appendStringInfo(buf, " IS TRUE)");
> ---
> >                         appendStringInfo(buf, " IS TRUE");
> 2557c2951
> <                         appendStringInfo(buf, " IS NOT TRUE)");
> ---
> >                         appendStringInfo(buf, " IS NOT TRUE");
> 2560c2954
> <                         appendStringInfo(buf, " IS FALSE)");
> ---
> >                         appendStringInfo(buf, " IS FALSE");
> 2563c2957
> <                         appendStringInfo(buf, " IS NOT FALSE)");
> ---
> >                         appendStringInfo(buf, " IS NOT FALSE");
> 2566c2960
> <                         appendStringInfo(buf, " IS UNKNOWN)");
> ---
> >                         appendStringInfo(buf, " IS UNKNOWN");
> 2569c2963
> <                         appendStringInfo(buf, " IS NOT UNKNOWN)");
> ---
> >                         appendStringInfo(buf, " IS NOT UNKNOWN");
> 2574a2969,2970
> >                 if (!PRETTY_PAREN(context))
> >                     appendStringInfoChar(buf, ')');
> 2596,2598c2992,2999
> <                     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",
> 2630c3031,3032
> <     appendStringInfoChar(buf, '(');
> ---
> >     if (!PRETTY_PAREN(context))
> >         appendStringInfoChar(buf, '(');
> 2636,2637c3038
> <
> <         get_rule_expr(arg1, context, true);
> ---
> >         get_rule_expr_paren(arg1, context, true, (Node*)expr);
> 2642c3043
> <         get_rule_expr(arg2, context, true);
> ---
> >         get_rule_expr_paren(arg2, context, true, (Node*)expr);
> 2664c3065
> <                 get_rule_expr(arg, context, true);
> ---
> >                 get_rule_expr_paren(arg, context, true, (Node*)expr);
> 2667c3068
> <                 get_rule_expr(arg, context, true);
> ---
> >                 get_rule_expr_paren(arg, context, true, (Node*)expr);
> 2678c3079,3080
> <     appendStringInfoChar(buf, ')');
> ---
> >     if (!PRETTY_PAREN(context))
> >         appendStringInfoChar(buf, ')');
> 2701c3103
> <         get_rule_expr((Node *) lfirst(expr->args), context, showimplicit);
> ---
> >         get_rule_expr_paren((Node *) lfirst(expr->args), context, showimplicit, (Node*)expr);
> 2727,2729c3129,3136
> <         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",
> 3050c3457
> <     get_query_def(query, buf, context->namespaces, NULL);
> ---
> >     get_query_def(query, buf, context->namespaces, NULL, context->prettyFlags, context->indentLevel);
> 3067c3474
> <     char       *sep;
> ---
> >     char       *sep=0;
> 3077d3483
> <     sep = " FROM ";
> 3096c3502,3506
> <         appendStringInfo(buf, sep);
> ---
> >         if (!sep)
> >             appendContextKeyword(context, " FROM ", -PRETTYINDENT_STD, PRETTYINDENT_STD, 2);
> >         else
> >             appendStringInfo(buf, sep);
> >
> 3125c3535,3536
> <                 get_query_def(rte->subquery, buf, context->namespaces, NULL);
> ---
> >                 get_query_def(rte->subquery, buf, context->namespaces, NULL,
> >                           context->prettyFlags, context->indentLevel);
> 3147c3558
> <                 appendStringInfo(buf, "(");
> ---
> >                 appendStringInfoChar(buf, '(');
> 3180a3592,3595
> >         bool need_paren_on_right = PRETTY_PAREN(context) && !IsA(j->rarg, RangeTblRef);
> >
> >         if (!PRETTY_PAREN(context) || j->alias != NULL)
> >             appendStringInfoChar(buf, '(');
> 3182d3596
> <         appendStringInfoChar(buf, '(');
> 3183a3598
> >
> 3185,3186d3599
> <             appendStringInfo(buf, " NATURAL");
> <         switch (j->jointype)
> 3187a3601,3631
> >             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)
> >             {
> 3190c3634
> <                     appendStringInfo(buf, " JOIN ");
> ---
> >                     appendContextKeyword(context, " JOIN ", -PRETTYINDENT_JOIN, PRETTYINDENT_JOIN, 2);
> 3192c3636
> <                     appendStringInfo(buf, " CROSS JOIN ");
> ---
> >                     appendContextKeyword(context, " CROSS JOIN ", -PRETTYINDENT_JOIN, PRETTYINDENT_JOIN, 1);
> 3195c3639
> <                 appendStringInfo(buf, " LEFT JOIN ");
> ---
> >                 appendContextKeyword(context, " LEFT JOIN ", -PRETTYINDENT_JOIN, PRETTYINDENT_JOIN, 2);
> 3198c3642
> <                 appendStringInfo(buf, " FULL JOIN ");
> ---
> >                 appendContextKeyword(context, " FULL JOIN ", -PRETTYINDENT_JOIN, PRETTYINDENT_JOIN, 2);
> 3201c3645
> <                 appendStringInfo(buf, " RIGHT JOIN ");
> ---
> >                 appendContextKeyword(context, " RIGHT JOIN ", -PRETTYINDENT_JOIN, PRETTYINDENT_JOIN, 2);
> 3204c3648
> <                 appendStringInfo(buf, " UNION JOIN ");
> ---
> >                 appendContextKeyword(context, " UNION JOIN ", -PRETTYINDENT_JOIN, PRETTYINDENT_JOIN, 2);
> 3208a3653
> >             }
> 3209a3655,3657
> >
> >         if (need_paren_on_right)
> >             appendStringInfoChar(buf, '(');
> 3210a3659,3663
> >         if (need_paren_on_right)
> >             appendStringInfoChar(buf, ')');
> >
> >             context->indentLevel -= PRETTYINDENT_JOIN_ON;
> >
> 3229c3682,3684
> <                 appendStringInfo(buf, " ON (");
> ---
> >                 appendStringInfo(buf, " ON ");
> >                 if (!PRETTY_PAREN(context))
> >                     appendStringInfoChar(buf, '(');
> 3231c3686,3687
> <                 appendStringInfoChar(buf, ')');
> ---
> >                 if (!PRETTY_PAREN(context))
> >                     appendStringInfoChar(buf, ')');
> 3234c3690,3692
> <         appendStringInfoChar(buf, ')');
> ---
> >         if (!PRETTY_PAREN(context) || j->alias != NULL)
> >             appendStringInfoChar(buf, ')');
> >
> 3244c3702
> <                 appendStringInfo(buf, "(");
> ---
> >                 appendStringInfoChar(buf, '(');

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

pgsql-patches by date:

Previous
From: Bruce Momjian
Date:
Subject: Re: Adding Rendezvous support to postmaster
Next
From: Böjthe Zoltán
Date:
Subject: Re: timetravel.c