OSDN Git Service

Phase 1 of read-only-plans project: cause executor state nodes to point
[pg-rex/syncrep.git] / src / backend / nodes / outfuncs.c
1 /*-------------------------------------------------------------------------
2  *
3  * outfuncs.c
4  *        Output functions for Postgres tree nodes.
5  *
6  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.186 2002/12/05 15:50:35 tgl Exp $
12  *
13  * NOTES
14  *        Every node type that can appear in stored rules' parsetrees *must*
15  *        have an output function defined here (as well as an input function
16  *        in readfuncs.c).  For use in debugging, we also provide output
17  *        functions for nodes that appear in raw parsetrees, path, and plan trees.
18  *        These nodes however need not have input functions.
19  *
20  *-------------------------------------------------------------------------
21  */
22 #include "postgres.h"
23
24 #include <ctype.h>
25
26 #include "lib/stringinfo.h"
27 #include "nodes/parsenodes.h"
28 #include "nodes/plannodes.h"
29 #include "nodes/relation.h"
30 #include "parser/parse.h"
31 #include "utils/datum.h"
32
33
34 /*
35  * Macros to simplify output of different kinds of fields.  Use these
36  * wherever possible to reduce the chance for silly typos.  Note that these
37  * hard-wire conventions about the names of the local variables in an Out
38  * routine.
39  */
40
41 /* Write the label for the node type */
42 #define WRITE_NODE_TYPE(nodelabel) \
43         appendStringInfo(str, nodelabel)
44
45 /* Write an integer field (anything written as ":fldname %d") */
46 #define WRITE_INT_FIELD(fldname) \
47         appendStringInfo(str, " :" CppAsString(fldname) " %d", node->fldname)
48
49 /* Write an unsigned integer field (anything written as ":fldname %u") */
50 #define WRITE_UINT_FIELD(fldname) \
51         appendStringInfo(str, " :" CppAsString(fldname) " %u", node->fldname)
52
53 /* Write an OID field (don't hard-wire assumption that OID is same as uint) */
54 #define WRITE_OID_FIELD(fldname) \
55         appendStringInfo(str, " :" CppAsString(fldname) " %u", node->fldname)
56
57 /* Write a long-integer field */
58 #define WRITE_LONG_FIELD(fldname) \
59         appendStringInfo(str, " :" CppAsString(fldname) " %ld", node->fldname)
60
61 /* Write a char field (ie, one ascii character) */
62 #define WRITE_CHAR_FIELD(fldname) \
63         appendStringInfo(str, " :" CppAsString(fldname) " %c", node->fldname)
64
65 /* Write an enumerated-type field as an integer code */
66 #define WRITE_ENUM_FIELD(fldname, enumtype) \
67         appendStringInfo(str, " :" CppAsString(fldname) " %d", \
68                                          (int) node->fldname)
69
70 /* Write a float field --- caller must give format to define precision */
71 #define WRITE_FLOAT_FIELD(fldname,format) \
72         appendStringInfo(str, " :" CppAsString(fldname) " " format, node->fldname)
73
74 /* Write a boolean field */
75 #define WRITE_BOOL_FIELD(fldname) \
76         appendStringInfo(str, " :" CppAsString(fldname) " %s", \
77                                          booltostr(node->fldname))
78
79 /* Write a character-string (possibly NULL) field */
80 #define WRITE_STRING_FIELD(fldname) \
81         (appendStringInfo(str, " :" CppAsString(fldname) " "), \
82          _outToken(str, node->fldname))
83
84 /* Write a Node field */
85 #define WRITE_NODE_FIELD(fldname) \
86         (appendStringInfo(str, " :" CppAsString(fldname) " "), \
87          _outNode(str, node->fldname))
88
89 /* Write an integer-list field */
90 #define WRITE_INTLIST_FIELD(fldname) \
91         (appendStringInfo(str, " :" CppAsString(fldname) " "), \
92          _outIntList(str, node->fldname))
93
94 /* Write an OID-list field */
95 #define WRITE_OIDLIST_FIELD(fldname) \
96         (appendStringInfo(str, " :" CppAsString(fldname) " "), \
97          _outOidList(str, node->fldname))
98
99
100 #define booltostr(x)  ((x) ? "true" : "false")
101
102 static void _outDatum(StringInfo str, Datum value, int typlen, bool typbyval);
103 static void _outNode(StringInfo str, void *obj);
104
105 /*
106  * _outToken
107  *        Convert an ordinary string (eg, an identifier) into a form that
108  *        will be decoded back to a plain token by read.c's functions.
109  *
110  *        If a null or empty string is given, it is encoded as "<>".
111  */
112 static void
113 _outToken(StringInfo str, char *s)
114 {
115         if (s == NULL || *s == '\0')
116         {
117                 appendStringInfo(str, "<>");
118                 return;
119         }
120
121         /*
122          * Look for characters or patterns that are treated specially by
123          * read.c (either in pg_strtok() or in nodeRead()), and therefore need
124          * a protective backslash.
125          */
126         /* These characters only need to be quoted at the start of the string */
127         if (*s == '<' ||
128                 *s == '\"' ||
129                 *s == '@' ||
130                 isdigit((unsigned char) *s) ||
131                 ((*s == '+' || *s == '-') &&
132                  (isdigit((unsigned char) s[1]) || s[1] == '.')))
133                 appendStringInfoChar(str, '\\');
134         while (*s)
135         {
136                 /* These chars must be backslashed anywhere in the string */
137                 if (*s == ' ' || *s == '\n' || *s == '\t' ||
138                         *s == '(' || *s == ')' || *s == '{' || *s == '}' ||
139                         *s == '\\')
140                         appendStringInfoChar(str, '\\');
141                 appendStringInfoChar(str, *s++);
142         }
143 }
144
145 /*
146  * _outIntList -
147  *         converts a List of integers
148  */
149 static void
150 _outIntList(StringInfo str, List *list)
151 {
152         List       *l;
153
154         appendStringInfoChar(str, '(');
155         foreach(l, list)
156                 appendStringInfo(str, " %d", lfirsti(l));
157         appendStringInfoChar(str, ')');
158 }
159
160 /*
161  * _outOidList -
162  *         converts a List of OIDs
163  */
164 static void
165 _outOidList(StringInfo str, List *list)
166 {
167         List       *l;
168
169         appendStringInfoChar(str, '(');
170         foreach(l, list)
171                 appendStringInfo(str, " %u", (Oid) lfirsti(l));
172         appendStringInfoChar(str, ')');
173 }
174
175 static void
176 _outCreateStmt(StringInfo str, CreateStmt *node)
177 {
178         WRITE_NODE_TYPE("CREATE");
179
180         WRITE_NODE_FIELD(relation);
181         WRITE_NODE_FIELD(tableElts);
182         WRITE_NODE_FIELD(inhRelations);
183         WRITE_NODE_FIELD(constraints);
184         WRITE_BOOL_FIELD(hasoids);
185         WRITE_ENUM_FIELD(oncommit, OnCommitAction);
186 }
187
188 static void
189 _outIndexStmt(StringInfo str, IndexStmt *node)
190 {
191         WRITE_NODE_TYPE("INDEX");
192
193         WRITE_STRING_FIELD(idxname);
194         WRITE_NODE_FIELD(relation);
195         WRITE_STRING_FIELD(accessMethod);
196         WRITE_NODE_FIELD(indexParams);
197         WRITE_NODE_FIELD(whereClause);
198         WRITE_NODE_FIELD(rangetable);
199         WRITE_BOOL_FIELD(unique);
200         WRITE_BOOL_FIELD(primary);
201         WRITE_BOOL_FIELD(isconstraint);
202 }
203
204 static void
205 _outNotifyStmt(StringInfo str, NotifyStmt *node)
206 {
207         WRITE_NODE_TYPE("NOTIFY");
208
209         WRITE_NODE_FIELD(relation);
210 }
211
212 static void
213 _outSelectStmt(StringInfo str, SelectStmt *node)
214 {
215         WRITE_NODE_TYPE("SELECT");
216
217         /* XXX this is pretty durn incomplete */
218         WRITE_NODE_FIELD(whereClause);
219 }
220
221 static void
222 _outFuncCall(StringInfo str, FuncCall *node)
223 {
224         WRITE_NODE_TYPE("FUNCCALL");
225
226         WRITE_NODE_FIELD(funcname);
227         WRITE_NODE_FIELD(args);
228         WRITE_BOOL_FIELD(agg_star);
229         WRITE_BOOL_FIELD(agg_distinct);
230 }
231
232 static void
233 _outColumnDef(StringInfo str, ColumnDef *node)
234 {
235         WRITE_NODE_TYPE("COLUMNDEF");
236
237         WRITE_STRING_FIELD(colname);
238         WRITE_NODE_FIELD(typename);
239         WRITE_INT_FIELD(inhcount);
240         WRITE_BOOL_FIELD(is_local);
241         WRITE_BOOL_FIELD(is_not_null);
242         WRITE_NODE_FIELD(raw_default);
243         WRITE_STRING_FIELD(cooked_default);
244         WRITE_NODE_FIELD(constraints);
245         WRITE_NODE_FIELD(support);
246 }
247
248 static void
249 _outTypeName(StringInfo str, TypeName *node)
250 {
251         WRITE_NODE_TYPE("TYPENAME");
252
253         WRITE_NODE_FIELD(names);
254         WRITE_OID_FIELD(typeid);
255         WRITE_BOOL_FIELD(timezone);
256         WRITE_BOOL_FIELD(setof);
257         WRITE_BOOL_FIELD(pct_type);
258         WRITE_INT_FIELD(typmod);
259         WRITE_NODE_FIELD(arrayBounds);
260 }
261
262 static void
263 _outTypeCast(StringInfo str, TypeCast *node)
264 {
265         WRITE_NODE_TYPE("TYPECAST");
266
267         WRITE_NODE_FIELD(arg);
268         WRITE_NODE_FIELD(typename);
269 }
270
271 static void
272 _outIndexElem(StringInfo str, IndexElem *node)
273 {
274         WRITE_NODE_TYPE("INDEXELEM");
275
276         WRITE_STRING_FIELD(name);
277         WRITE_NODE_FIELD(funcname);
278         WRITE_NODE_FIELD(args);
279         WRITE_NODE_FIELD(opclass);
280 }
281
282 static void
283 _outQuery(StringInfo str, Query *node)
284 {
285         WRITE_NODE_TYPE("QUERY");
286
287         WRITE_ENUM_FIELD(commandType, CmdType);
288         WRITE_ENUM_FIELD(querySource, QuerySource);
289
290         /*
291          * Hack to work around missing outfuncs routines for a lot of the
292          * utility-statement node types.  (The only one we actually *need* for
293          * rules support is NotifyStmt.)  Someday we ought to support 'em all,
294          * but for the meantime do this to avoid getting lots of warnings when
295          * running with debug_print_parse on.
296          */
297         if (node->utilityStmt)
298         {
299                 switch (nodeTag(node->utilityStmt))
300                 {
301                         case T_CreateStmt:
302                         case T_IndexStmt:
303                         case T_NotifyStmt:
304                                 WRITE_NODE_FIELD(utilityStmt);
305                                 break;
306                         default:
307                                 appendStringInfo(str, " :utilityStmt ?");
308                                 break;
309                 }
310         }
311         else
312                 appendStringInfo(str, " :utilityStmt <>");
313
314         WRITE_INT_FIELD(resultRelation);
315         WRITE_NODE_FIELD(into);
316         WRITE_BOOL_FIELD(isPortal);
317         WRITE_BOOL_FIELD(isBinary);
318         WRITE_BOOL_FIELD(hasAggs);
319         WRITE_BOOL_FIELD(hasSubLinks);
320         WRITE_NODE_FIELD(rtable);
321         WRITE_NODE_FIELD(jointree);
322         WRITE_INTLIST_FIELD(rowMarks);
323         WRITE_NODE_FIELD(targetList);
324         WRITE_NODE_FIELD(groupClause);
325         WRITE_NODE_FIELD(havingQual);
326         WRITE_NODE_FIELD(distinctClause);
327         WRITE_NODE_FIELD(sortClause);
328         WRITE_NODE_FIELD(limitOffset);
329         WRITE_NODE_FIELD(limitCount);
330         WRITE_NODE_FIELD(setOperations);
331         WRITE_INTLIST_FIELD(resultRelations);
332
333         /* planner-internal fields are not written out */
334 }
335
336 static void
337 _outSortClause(StringInfo str, SortClause *node)
338 {
339         WRITE_NODE_TYPE("SORTCLAUSE");
340
341         WRITE_UINT_FIELD(tleSortGroupRef);
342         WRITE_OID_FIELD(sortop);
343 }
344
345 static void
346 _outGroupClause(StringInfo str, GroupClause *node)
347 {
348         WRITE_NODE_TYPE("GROUPCLAUSE");
349
350         WRITE_UINT_FIELD(tleSortGroupRef);
351         WRITE_OID_FIELD(sortop);
352 }
353
354 static void
355 _outSetOperationStmt(StringInfo str, SetOperationStmt *node)
356 {
357         WRITE_NODE_TYPE("SETOPERATIONSTMT");
358
359         WRITE_ENUM_FIELD(op, SetOperation);
360         WRITE_BOOL_FIELD(all);
361         WRITE_NODE_FIELD(larg);
362         WRITE_NODE_FIELD(rarg);
363         WRITE_OIDLIST_FIELD(colTypes);
364 }
365
366 /*
367  *      Stuff from plannodes.h
368  */
369
370 /*
371  * print the basic stuff of all nodes that inherit from Plan
372  *
373  * NOTE: we deliberately omit the execution state (EState)
374  */
375 static void
376 _outPlanInfo(StringInfo str, Plan *node)
377 {
378         WRITE_FLOAT_FIELD(startup_cost, "%.2f");
379         WRITE_FLOAT_FIELD(total_cost, "%.2f");
380         WRITE_FLOAT_FIELD(plan_rows, "%.0f");
381         WRITE_INT_FIELD(plan_width);
382         WRITE_NODE_FIELD(targetlist);
383         WRITE_NODE_FIELD(qual);
384         WRITE_NODE_FIELD(lefttree);
385         WRITE_NODE_FIELD(righttree);
386         WRITE_NODE_FIELD(initPlan);
387         WRITE_INTLIST_FIELD(extParam);
388         WRITE_INTLIST_FIELD(locParam);
389         WRITE_INT_FIELD(nParamExec);
390 }
391
392 /*
393  * print the basic stuff of all nodes that inherit from Scan
394  */
395 static void
396 _outScanInfo(StringInfo str, Scan *node)
397 {
398         _outPlanInfo(str, (Plan *) node);
399
400         WRITE_UINT_FIELD(scanrelid);
401 }
402
403 /*
404  * print the basic stuff of all nodes that inherit from Join
405  */
406 static void
407 _outJoinPlanInfo(StringInfo str, Join *node)
408 {
409         _outPlanInfo(str, (Plan *) node);
410
411         WRITE_ENUM_FIELD(jointype, JoinType);
412         WRITE_NODE_FIELD(joinqual);
413 }
414
415
416 static void
417 _outPlan(StringInfo str, Plan *node)
418 {
419         WRITE_NODE_TYPE("PLAN");
420
421         _outPlanInfo(str, (Plan *) node);
422 }
423
424 static void
425 _outResult(StringInfo str, Result *node)
426 {
427         WRITE_NODE_TYPE("RESULT");
428
429         _outPlanInfo(str, (Plan *) node);
430
431         WRITE_NODE_FIELD(resconstantqual);
432 }
433
434 static void
435 _outAppend(StringInfo str, Append *node)
436 {
437         WRITE_NODE_TYPE("APPEND");
438
439         _outPlanInfo(str, (Plan *) node);
440
441         WRITE_NODE_FIELD(appendplans);
442         WRITE_BOOL_FIELD(isTarget);
443 }
444
445 static void
446 _outScan(StringInfo str, Scan *node)
447 {
448         WRITE_NODE_TYPE("SCAN");
449
450         _outScanInfo(str, (Scan *) node);
451 }
452
453 static void
454 _outSeqScan(StringInfo str, SeqScan *node)
455 {
456         WRITE_NODE_TYPE("SEQSCAN");
457
458         _outScanInfo(str, (Scan *) node);
459 }
460
461 static void
462 _outIndexScan(StringInfo str, IndexScan *node)
463 {
464         WRITE_NODE_TYPE("INDEXSCAN");
465
466         _outScanInfo(str, (Scan *) node);
467
468         WRITE_OIDLIST_FIELD(indxid);
469         WRITE_NODE_FIELD(indxqual);
470         WRITE_NODE_FIELD(indxqualorig);
471         WRITE_ENUM_FIELD(indxorderdir, ScanDirection);
472 }
473
474 static void
475 _outTidScan(StringInfo str, TidScan *node)
476 {
477         WRITE_NODE_TYPE("TIDSCAN");
478
479         _outScanInfo(str, (Scan *) node);
480
481         WRITE_NODE_FIELD(tideval);
482 }
483
484 static void
485 _outSubqueryScan(StringInfo str, SubqueryScan *node)
486 {
487         WRITE_NODE_TYPE("SUBQUERYSCAN");
488
489         _outScanInfo(str, (Scan *) node);
490
491         WRITE_NODE_FIELD(subplan);
492 }
493
494 static void
495 _outFunctionScan(StringInfo str, FunctionScan *node)
496 {
497         WRITE_NODE_TYPE("FUNCTIONSCAN");
498
499         _outScanInfo(str, (Scan *) node);
500 }
501
502 static void
503 _outJoin(StringInfo str, Join *node)
504 {
505         WRITE_NODE_TYPE("JOIN");
506
507         _outJoinPlanInfo(str, (Join *) node);
508 }
509
510 static void
511 _outNestLoop(StringInfo str, NestLoop *node)
512 {
513         WRITE_NODE_TYPE("NESTLOOP");
514
515         _outJoinPlanInfo(str, (Join *) node);
516 }
517
518 static void
519 _outMergeJoin(StringInfo str, MergeJoin *node)
520 {
521         WRITE_NODE_TYPE("MERGEJOIN");
522
523         _outJoinPlanInfo(str, (Join *) node);
524
525         WRITE_NODE_FIELD(mergeclauses);
526 }
527
528 static void
529 _outHashJoin(StringInfo str, HashJoin *node)
530 {
531         WRITE_NODE_TYPE("HASHJOIN");
532
533         _outJoinPlanInfo(str, (Join *) node);
534
535         WRITE_NODE_FIELD(hashclauses);
536 }
537
538 static void
539 _outAgg(StringInfo str, Agg *node)
540 {
541         WRITE_NODE_TYPE("AGG");
542
543         _outPlanInfo(str, (Plan *) node);
544
545         WRITE_ENUM_FIELD(aggstrategy, AggStrategy);
546         WRITE_INT_FIELD(numCols);
547         WRITE_LONG_FIELD(numGroups);
548 }
549
550 static void
551 _outGroup(StringInfo str, Group *node)
552 {
553         WRITE_NODE_TYPE("GRP");
554
555         _outPlanInfo(str, (Plan *) node);
556
557         WRITE_INT_FIELD(numCols);
558 }
559
560 static void
561 _outMaterial(StringInfo str, Material *node)
562 {
563         WRITE_NODE_TYPE("MATERIAL");
564
565         _outPlanInfo(str, (Plan *) node);
566 }
567
568 static void
569 _outSort(StringInfo str, Sort *node)
570 {
571         WRITE_NODE_TYPE("SORT");
572
573         _outPlanInfo(str, (Plan *) node);
574
575         WRITE_INT_FIELD(keycount);
576 }
577
578 static void
579 _outUnique(StringInfo str, Unique *node)
580 {
581         int                     i;
582
583         WRITE_NODE_TYPE("UNIQUE");
584
585         _outPlanInfo(str, (Plan *) node);
586
587         WRITE_INT_FIELD(numCols);
588
589         appendStringInfo(str, " :uniqColIdx");
590         for (i = 0; i < node->numCols; i++)
591                 appendStringInfo(str, " %d", node->uniqColIdx[i]);
592 }
593
594 static void
595 _outSetOp(StringInfo str, SetOp *node)
596 {
597         int                     i;
598
599         WRITE_NODE_TYPE("SETOP");
600
601         _outPlanInfo(str, (Plan *) node);
602
603         WRITE_ENUM_FIELD(cmd, SetOpCmd);
604         WRITE_INT_FIELD(numCols);
605
606         appendStringInfo(str, " :dupColIdx");
607         for (i = 0; i < node->numCols; i++)
608                 appendStringInfo(str, " %d", node->dupColIdx[i]);
609
610         WRITE_INT_FIELD(flagColIdx);
611 }
612
613 static void
614 _outLimit(StringInfo str, Limit *node)
615 {
616         WRITE_NODE_TYPE("LIMIT");
617
618         _outPlanInfo(str, (Plan *) node);
619
620         WRITE_NODE_FIELD(limitOffset);
621         WRITE_NODE_FIELD(limitCount);
622 }
623
624 static void
625 _outHash(StringInfo str, Hash *node)
626 {
627         WRITE_NODE_TYPE("HASH");
628
629         _outPlanInfo(str, (Plan *) node);
630
631         WRITE_NODE_FIELD(hashkeys);
632 }
633
634 static void
635 _outSubPlan(StringInfo str, SubPlan *node)
636 {
637         WRITE_NODE_TYPE("SUBPLAN");
638
639         WRITE_NODE_FIELD(plan);
640         WRITE_INT_FIELD(plan_id);
641         WRITE_NODE_FIELD(rtable);
642         WRITE_INTLIST_FIELD(setParam);
643         WRITE_INTLIST_FIELD(parParam);
644         WRITE_NODE_FIELD(sublink);
645 }
646
647 /*****************************************************************************
648  *
649  *      Stuff from primnodes.h.
650  *
651  *****************************************************************************/
652
653 static void
654 _outResdom(StringInfo str, Resdom *node)
655 {
656         WRITE_NODE_TYPE("RESDOM");
657
658         WRITE_INT_FIELD(resno);
659         WRITE_OID_FIELD(restype);
660         WRITE_INT_FIELD(restypmod);
661         WRITE_STRING_FIELD(resname);
662         WRITE_UINT_FIELD(ressortgroupref);
663         WRITE_UINT_FIELD(reskey);
664         WRITE_OID_FIELD(reskeyop);
665         WRITE_BOOL_FIELD(resjunk);
666 }
667
668 static void
669 _outExpr(StringInfo str, Expr *node)
670 {
671         char       *opstr = NULL;
672
673         WRITE_NODE_TYPE("EXPR");
674
675         WRITE_OID_FIELD(typeOid);
676
677         /* do-it-yourself enum representation */
678         switch (node->opType)
679         {
680                 case OP_EXPR:
681                         opstr = "op";
682                         break;
683                 case DISTINCT_EXPR:
684                         opstr = "distinct";
685                         break;
686                 case FUNC_EXPR:
687                         opstr = "func";
688                         break;
689                 case OR_EXPR:
690                         opstr = "or";
691                         break;
692                 case AND_EXPR:
693                         opstr = "and";
694                         break;
695                 case NOT_EXPR:
696                         opstr = "not";
697                         break;
698                 case SUBPLAN_EXPR:
699                         opstr = "subp";
700                         break;
701         }
702         appendStringInfo(str, " :opType ");
703         _outToken(str, opstr);
704
705         WRITE_NODE_FIELD(oper);
706         WRITE_NODE_FIELD(args);
707 }
708
709 static void
710 _outVar(StringInfo str, Var *node)
711 {
712         WRITE_NODE_TYPE("VAR");
713
714         WRITE_UINT_FIELD(varno);
715         WRITE_INT_FIELD(varattno);
716         WRITE_OID_FIELD(vartype);
717         WRITE_INT_FIELD(vartypmod);
718         WRITE_UINT_FIELD(varlevelsup);
719         WRITE_UINT_FIELD(varnoold);
720         WRITE_INT_FIELD(varoattno);
721 }
722
723 static void
724 _outConst(StringInfo str, Const *node)
725 {
726         WRITE_NODE_TYPE("CONST");
727
728         WRITE_OID_FIELD(consttype);
729         WRITE_INT_FIELD(constlen);
730         WRITE_BOOL_FIELD(constbyval);
731         WRITE_BOOL_FIELD(constisnull);
732
733         appendStringInfo(str, " :constvalue ");
734         if (node->constisnull)
735                 appendStringInfo(str, "<>");
736         else
737                 _outDatum(str, node->constvalue, node->constlen, node->constbyval);
738 }
739
740 static void
741 _outAggref(StringInfo str, Aggref *node)
742 {
743         WRITE_NODE_TYPE("AGGREF");
744
745         WRITE_OID_FIELD(aggfnoid);
746         WRITE_OID_FIELD(aggtype);
747         WRITE_NODE_FIELD(target);
748         WRITE_BOOL_FIELD(aggstar);
749         WRITE_BOOL_FIELD(aggdistinct);
750         /* aggno is not saved since it is just executor state */
751 }
752
753 static void
754 _outSubLink(StringInfo str, SubLink *node)
755 {
756         WRITE_NODE_TYPE("SUBLINK");
757
758         WRITE_ENUM_FIELD(subLinkType, SubLinkType);
759         WRITE_BOOL_FIELD(useor);
760         WRITE_NODE_FIELD(lefthand);
761         WRITE_NODE_FIELD(oper);
762         WRITE_NODE_FIELD(subselect);
763 }
764
765 static void
766 _outArrayRef(StringInfo str, ArrayRef *node)
767 {
768         WRITE_NODE_TYPE("ARRAYREF");
769
770         WRITE_OID_FIELD(refrestype);
771         WRITE_INT_FIELD(refattrlength);
772         WRITE_INT_FIELD(refelemlength);
773         WRITE_BOOL_FIELD(refelembyval);
774         WRITE_CHAR_FIELD(refelemalign);
775         WRITE_NODE_FIELD(refupperindexpr);
776         WRITE_NODE_FIELD(reflowerindexpr);
777         WRITE_NODE_FIELD(refexpr);
778         WRITE_NODE_FIELD(refassgnexpr);
779 }
780
781 static void
782 _outFunc(StringInfo str, Func *node)
783 {
784         WRITE_NODE_TYPE("FUNC");
785
786         WRITE_OID_FIELD(funcid);
787         WRITE_OID_FIELD(funcresulttype);
788         WRITE_BOOL_FIELD(funcretset);
789         WRITE_ENUM_FIELD(funcformat, CoercionForm);
790 }
791
792 static void
793 _outOper(StringInfo str, Oper *node)
794 {
795         WRITE_NODE_TYPE("OPER");
796
797         WRITE_OID_FIELD(opno);
798         WRITE_OID_FIELD(opid);
799         WRITE_OID_FIELD(opresulttype);
800         WRITE_BOOL_FIELD(opretset);
801 }
802
803 static void
804 _outParam(StringInfo str, Param *node)
805 {
806         WRITE_NODE_TYPE("PARAM");
807
808         WRITE_INT_FIELD(paramkind);
809         WRITE_INT_FIELD(paramid);
810         WRITE_STRING_FIELD(paramname);
811         WRITE_OID_FIELD(paramtype);
812 }
813
814 static void
815 _outFieldSelect(StringInfo str, FieldSelect *node)
816 {
817         WRITE_NODE_TYPE("FIELDSELECT");
818
819         WRITE_NODE_FIELD(arg);
820         WRITE_INT_FIELD(fieldnum);
821         WRITE_OID_FIELD(resulttype);
822         WRITE_INT_FIELD(resulttypmod);
823 }
824
825 static void
826 _outRelabelType(StringInfo str, RelabelType *node)
827 {
828         WRITE_NODE_TYPE("RELABELTYPE");
829
830         WRITE_NODE_FIELD(arg);
831         WRITE_OID_FIELD(resulttype);
832         WRITE_INT_FIELD(resulttypmod);
833         WRITE_ENUM_FIELD(relabelformat, CoercionForm);
834 }
835
836 static void
837 _outRangeTblRef(StringInfo str, RangeTblRef *node)
838 {
839         WRITE_NODE_TYPE("RANGETBLREF");
840
841         WRITE_INT_FIELD(rtindex);
842 }
843
844 static void
845 _outJoinExpr(StringInfo str, JoinExpr *node)
846 {
847         WRITE_NODE_TYPE("JOINEXPR");
848
849         WRITE_ENUM_FIELD(jointype, JoinType);
850         WRITE_BOOL_FIELD(isNatural);
851         WRITE_NODE_FIELD(larg);
852         WRITE_NODE_FIELD(rarg);
853         WRITE_NODE_FIELD(using);
854         WRITE_NODE_FIELD(quals);
855         WRITE_NODE_FIELD(alias);
856         WRITE_INT_FIELD(rtindex);
857 }
858
859 static void
860 _outFromExpr(StringInfo str, FromExpr *node)
861 {
862         WRITE_NODE_TYPE("FROMEXPR");
863
864         WRITE_NODE_FIELD(fromlist);
865         WRITE_NODE_FIELD(quals);
866 }
867
868 static void
869 _outTargetEntry(StringInfo str, TargetEntry *node)
870 {
871         WRITE_NODE_TYPE("TARGETENTRY");
872
873         WRITE_NODE_FIELD(resdom);
874         /* fjoin not supported ... */
875         WRITE_NODE_FIELD(expr);
876 }
877
878 static void
879 _outAlias(StringInfo str, Alias *node)
880 {
881         WRITE_NODE_TYPE("ALIAS");
882
883         WRITE_STRING_FIELD(aliasname);
884         WRITE_NODE_FIELD(colnames);
885 }
886
887 static void
888 _outRangeTblEntry(StringInfo str, RangeTblEntry *node)
889 {
890         WRITE_NODE_TYPE("RTE");
891
892         /* put alias + eref first to make dump more legible */
893         WRITE_NODE_FIELD(alias);
894         WRITE_NODE_FIELD(eref);
895         WRITE_ENUM_FIELD(rtekind, RTEKind);
896
897         switch (node->rtekind)
898         {
899                 case RTE_RELATION:
900                 case RTE_SPECIAL:
901                         WRITE_OID_FIELD(relid);
902                         break;
903                 case RTE_SUBQUERY:
904                         WRITE_NODE_FIELD(subquery);
905                         break;
906                 case RTE_FUNCTION:
907                         WRITE_NODE_FIELD(funcexpr);
908                         WRITE_NODE_FIELD(coldeflist);
909                         break;
910                 case RTE_JOIN:
911                         WRITE_ENUM_FIELD(jointype, JoinType);
912                         WRITE_NODE_FIELD(joinaliasvars);
913                         break;
914                 default:
915                         elog(ERROR, "bogus rte kind %d", (int) node->rtekind);
916                         break;
917         }
918
919         WRITE_BOOL_FIELD(inh);
920         WRITE_BOOL_FIELD(inFromCl);
921         WRITE_BOOL_FIELD(checkForRead);
922         WRITE_BOOL_FIELD(checkForWrite);
923         WRITE_OID_FIELD(checkAsUser);
924 }
925
926 /*
927  * print the basic stuff of all nodes that inherit from Path
928  *
929  * Note we do NOT print the parent, else we'd be in infinite recursion
930  */
931 static void
932 _outPathInfo(StringInfo str, Path *node)
933 {
934         WRITE_ENUM_FIELD(pathtype, NodeTag);
935         WRITE_FLOAT_FIELD(startup_cost, "%.2f");
936         WRITE_FLOAT_FIELD(total_cost, "%.2f");
937         WRITE_NODE_FIELD(pathkeys);
938 }
939
940 /*
941  * print the basic stuff of all nodes that inherit from JoinPath
942  */
943 static void
944 _outJoinPathInfo(StringInfo str, JoinPath *node)
945 {
946         _outPathInfo(str, (Path *) node);
947
948         WRITE_ENUM_FIELD(jointype, JoinType);
949         WRITE_NODE_FIELD(outerjoinpath);
950         WRITE_NODE_FIELD(innerjoinpath);
951         WRITE_NODE_FIELD(joinrestrictinfo);
952 }
953
954 static void
955 _outPath(StringInfo str, Path *node)
956 {
957         WRITE_NODE_TYPE("PATH");
958
959         _outPathInfo(str, (Path *) node);
960 }
961
962 /*
963  *      IndexPath is a subclass of Path.
964  */
965 static void
966 _outIndexPath(StringInfo str, IndexPath *node)
967 {
968         WRITE_NODE_TYPE("INDEXPATH");
969
970         _outPathInfo(str, (Path *) node);
971
972         WRITE_NODE_FIELD(indexinfo);
973         WRITE_NODE_FIELD(indexqual);
974         WRITE_ENUM_FIELD(indexscandir, ScanDirection);
975         WRITE_FLOAT_FIELD(rows, "%.2f");
976 }
977
978 static void
979 _outTidPath(StringInfo str, TidPath *node)
980 {
981         WRITE_NODE_TYPE("TIDPATH");
982
983         _outPathInfo(str, (Path *) node);
984
985         WRITE_NODE_FIELD(tideval);
986 }
987
988 static void
989 _outAppendPath(StringInfo str, AppendPath *node)
990 {
991         WRITE_NODE_TYPE("APPENDPATH");
992
993         _outPathInfo(str, (Path *) node);
994
995         WRITE_NODE_FIELD(subpaths);
996 }
997
998 static void
999 _outResultPath(StringInfo str, ResultPath *node)
1000 {
1001         WRITE_NODE_TYPE("RESULTPATH");
1002
1003         _outPathInfo(str, (Path *) node);
1004
1005         WRITE_NODE_FIELD(subpath);
1006         WRITE_NODE_FIELD(constantqual);
1007 }
1008
1009 static void
1010 _outMaterialPath(StringInfo str, MaterialPath *node)
1011 {
1012         WRITE_NODE_TYPE("MATERIALPATH");
1013
1014         _outPathInfo(str, (Path *) node);
1015
1016         WRITE_NODE_FIELD(subpath);
1017 }
1018
1019 static void
1020 _outNestPath(StringInfo str, NestPath *node)
1021 {
1022         WRITE_NODE_TYPE("NESTPATH");
1023
1024         _outJoinPathInfo(str, (JoinPath *) node);
1025 }
1026
1027 static void
1028 _outMergePath(StringInfo str, MergePath *node)
1029 {
1030         WRITE_NODE_TYPE("MERGEPATH");
1031
1032         _outJoinPathInfo(str, (JoinPath *) node);
1033
1034         WRITE_NODE_FIELD(path_mergeclauses);
1035         WRITE_NODE_FIELD(outersortkeys);
1036         WRITE_NODE_FIELD(innersortkeys);
1037 }
1038
1039 static void
1040 _outHashPath(StringInfo str, HashPath *node)
1041 {
1042         WRITE_NODE_TYPE("HASHPATH");
1043
1044         _outJoinPathInfo(str, (JoinPath *) node);
1045
1046         WRITE_NODE_FIELD(path_hashclauses);
1047 }
1048
1049 static void
1050 _outPathKeyItem(StringInfo str, PathKeyItem *node)
1051 {
1052         WRITE_NODE_TYPE("PATHKEYITEM");
1053
1054         WRITE_NODE_FIELD(key);
1055         WRITE_OID_FIELD(sortop);
1056 }
1057
1058 static void
1059 _outRestrictInfo(StringInfo str, RestrictInfo *node)
1060 {
1061         WRITE_NODE_TYPE("RESTRICTINFO");
1062
1063         WRITE_NODE_FIELD(clause);
1064         WRITE_BOOL_FIELD(ispusheddown);
1065         WRITE_NODE_FIELD(subclauseindices);
1066         WRITE_OID_FIELD(mergejoinoperator);
1067         WRITE_OID_FIELD(left_sortop);
1068         WRITE_OID_FIELD(right_sortop);
1069         WRITE_OID_FIELD(hashjoinoperator);
1070 }
1071
1072 static void
1073 _outJoinInfo(StringInfo str, JoinInfo *node)
1074 {
1075         WRITE_NODE_TYPE("JOININFO");
1076
1077         WRITE_INTLIST_FIELD(unjoined_relids);
1078         WRITE_NODE_FIELD(jinfo_restrictinfo);
1079 }
1080
1081 /*
1082  * Print the value of a Datum given its type.
1083  */
1084 static void
1085 _outDatum(StringInfo str, Datum value, int typlen, bool typbyval)
1086 {
1087         Size            length,
1088                                 i;
1089         char       *s;
1090
1091         length = datumGetSize(value, typbyval, typlen);
1092
1093         if (typbyval)
1094         {
1095                 s = (char *) (&value);
1096                 appendStringInfo(str, "%u [ ", (unsigned int) length);
1097                 for (i = 0; i < (Size) sizeof(Datum); i++)
1098                         appendStringInfo(str, "%d ", (int) (s[i]));
1099                 appendStringInfo(str, "]");
1100         }
1101         else
1102         {
1103                 s = (char *) DatumGetPointer(value);
1104                 if (!PointerIsValid(s))
1105                         appendStringInfo(str, "0 [ ]");
1106                 else
1107                 {
1108                         appendStringInfo(str, "%u [ ", (unsigned int) length);
1109                         for (i = 0; i < length; i++)
1110                                 appendStringInfo(str, "%d ", (int) (s[i]));
1111                         appendStringInfo(str, "]");
1112                 }
1113         }
1114 }
1115
1116 static void
1117 _outAExpr(StringInfo str, A_Expr *node)
1118 {
1119         WRITE_NODE_TYPE("AEXPR");
1120
1121         switch (node->oper)
1122         {
1123                 case AND:
1124                         appendStringInfo(str, " AND");
1125                         break;
1126                 case OR:
1127                         appendStringInfo(str, " OR");
1128                         break;
1129                 case NOT:
1130                         appendStringInfo(str, " NOT");
1131                         break;
1132                 case OP:
1133                         appendStringInfo(str, " ");
1134                         WRITE_NODE_FIELD(name);
1135                         break;
1136                 default:
1137                         appendStringInfo(str, " ??");
1138                         break;
1139         }
1140
1141         WRITE_NODE_FIELD(lexpr);
1142         WRITE_NODE_FIELD(rexpr);
1143 }
1144
1145 static void
1146 _outValue(StringInfo str, Value *value)
1147 {
1148         switch (value->type)
1149         {
1150                 case T_Integer:
1151                         appendStringInfo(str, "%ld", value->val.ival);
1152                         break;
1153                 case T_Float:
1154
1155                         /*
1156                          * We assume the value is a valid numeric literal and so does
1157                          * not need quoting.
1158                          */
1159                         appendStringInfo(str, "%s", value->val.str);
1160                         break;
1161                 case T_String:
1162                         appendStringInfoChar(str, '"');
1163                         _outToken(str, value->val.str);
1164                         appendStringInfoChar(str, '"');
1165                         break;
1166                 case T_BitString:
1167                         /* internal representation already has leading 'b' */
1168                         appendStringInfo(str, "%s", value->val.str);
1169                         break;
1170                 default:
1171                         elog(WARNING, "_outValue: don't know how to print type %d",
1172                                  value->type);
1173                         break;
1174         }
1175 }
1176
1177 static void
1178 _outRangeVar(StringInfo str, RangeVar *node)
1179 {
1180         WRITE_NODE_TYPE("RANGEVAR");
1181
1182         /*
1183          * we deliberately ignore catalogname here, since it is presently not
1184          * semantically meaningful
1185          */
1186         WRITE_STRING_FIELD(schemaname);
1187         WRITE_STRING_FIELD(relname);
1188         WRITE_ENUM_FIELD(inhOpt, InhOption);
1189         WRITE_BOOL_FIELD(istemp);
1190         WRITE_NODE_FIELD(alias);
1191 }
1192
1193 static void
1194 _outColumnRef(StringInfo str, ColumnRef *node)
1195 {
1196         WRITE_NODE_TYPE("COLUMNREF");
1197
1198         WRITE_NODE_FIELD(fields);
1199         WRITE_NODE_FIELD(indirection);
1200 }
1201
1202 static void
1203 _outParamRef(StringInfo str, ParamRef *node)
1204 {
1205         WRITE_NODE_TYPE("PARAMREF");
1206
1207         WRITE_INT_FIELD(number);
1208         WRITE_NODE_FIELD(fields);
1209         WRITE_NODE_FIELD(indirection);
1210 }
1211
1212 static void
1213 _outAConst(StringInfo str, A_Const *node)
1214 {
1215         WRITE_NODE_TYPE("CONST ");
1216
1217         _outValue(str, &(node->val));
1218         WRITE_NODE_FIELD(typename);
1219 }
1220
1221 static void
1222 _outExprFieldSelect(StringInfo str, ExprFieldSelect *node)
1223 {
1224         WRITE_NODE_TYPE("EXPRFIELDSELECT");
1225
1226         WRITE_NODE_FIELD(arg);
1227         WRITE_NODE_FIELD(fields);
1228         WRITE_NODE_FIELD(indirection);
1229 }
1230
1231 static void
1232 _outConstraint(StringInfo str, Constraint *node)
1233 {
1234         WRITE_NODE_TYPE("CONSTRAINT");
1235
1236         WRITE_STRING_FIELD(name);
1237
1238         appendStringInfo(str, " :contype ");
1239         switch (node->contype)
1240         {
1241                 case CONSTR_PRIMARY:
1242                         appendStringInfo(str, "PRIMARY_KEY");
1243                         WRITE_NODE_FIELD(keys);
1244                         break;
1245
1246                 case CONSTR_CHECK:
1247                         appendStringInfo(str, "CHECK");
1248                         WRITE_NODE_FIELD(raw_expr);
1249                         WRITE_STRING_FIELD(cooked_expr);
1250                         break;
1251
1252                 case CONSTR_DEFAULT:
1253                         appendStringInfo(str, "DEFAULT");
1254                         WRITE_NODE_FIELD(raw_expr);
1255                         WRITE_STRING_FIELD(cooked_expr);
1256                         break;
1257
1258                 case CONSTR_NOTNULL:
1259                         appendStringInfo(str, "NOT_NULL");
1260                         break;
1261
1262                 case CONSTR_UNIQUE:
1263                         appendStringInfo(str, "UNIQUE");
1264                         WRITE_NODE_FIELD(keys);
1265                         break;
1266
1267                 default:
1268                         appendStringInfo(str, "<unrecognized_constraint>");
1269                         break;
1270         }
1271 }
1272
1273 static void
1274 _outFkConstraint(StringInfo str, FkConstraint *node)
1275 {
1276         WRITE_NODE_TYPE("FKCONSTRAINT");
1277
1278         WRITE_STRING_FIELD(constr_name);
1279         WRITE_NODE_FIELD(pktable);
1280         WRITE_NODE_FIELD(fk_attrs);
1281         WRITE_NODE_FIELD(pk_attrs);
1282         WRITE_CHAR_FIELD(fk_matchtype);
1283         WRITE_CHAR_FIELD(fk_upd_action);
1284         WRITE_CHAR_FIELD(fk_del_action);
1285         WRITE_BOOL_FIELD(deferrable);
1286         WRITE_BOOL_FIELD(initdeferred);
1287         WRITE_BOOL_FIELD(skip_validation);
1288 }
1289
1290 static void
1291 _outCaseExpr(StringInfo str, CaseExpr *node)
1292 {
1293         WRITE_NODE_TYPE("CASE");
1294
1295         WRITE_OID_FIELD(casetype);
1296         WRITE_NODE_FIELD(arg);
1297         WRITE_NODE_FIELD(args);
1298         WRITE_NODE_FIELD(defresult);
1299 }
1300
1301 static void
1302 _outCaseWhen(StringInfo str, CaseWhen *node)
1303 {
1304         WRITE_NODE_TYPE("WHEN");
1305
1306         WRITE_NODE_FIELD(expr);
1307         WRITE_NODE_FIELD(result);
1308 }
1309
1310 static void
1311 _outNullTest(StringInfo str, NullTest *node)
1312 {
1313         WRITE_NODE_TYPE("NULLTEST");
1314
1315         WRITE_NODE_FIELD(arg);
1316         WRITE_ENUM_FIELD(nulltesttype, NullTestType);
1317 }
1318
1319 static void
1320 _outBooleanTest(StringInfo str, BooleanTest *node)
1321 {
1322         WRITE_NODE_TYPE("BOOLEANTEST");
1323
1324         WRITE_NODE_FIELD(arg);
1325         WRITE_ENUM_FIELD(booltesttype, BoolTestType);
1326 }
1327
1328 static void
1329 _outConstraintTest(StringInfo str, ConstraintTest *node)
1330 {
1331         WRITE_NODE_TYPE("CONSTRAINTTEST");
1332
1333         WRITE_NODE_FIELD(arg);
1334         WRITE_ENUM_FIELD(testtype, ConstraintTestType);
1335         WRITE_STRING_FIELD(name);
1336         WRITE_STRING_FIELD(domname);
1337         WRITE_NODE_FIELD(check_expr);
1338 }
1339
1340 static void
1341 _outDomainConstraintValue(StringInfo str, DomainConstraintValue *node)
1342 {
1343         WRITE_NODE_TYPE("DOMAINCONSTRAINTVALUE");
1344 }
1345
1346 static void
1347 _outConstraintTestValue(StringInfo str, ConstraintTestValue *node)
1348 {
1349         WRITE_NODE_TYPE("CONSTRAINTTESTVALUE");
1350
1351         WRITE_OID_FIELD(typeId);
1352         WRITE_INT_FIELD(typeMod);
1353 }
1354
1355
1356 /*
1357  * _outNode -
1358  *        converts a Node into ascii string and append it to 'str'
1359  */
1360 static void
1361 _outNode(StringInfo str, void *obj)
1362 {
1363         if (obj == NULL)
1364         {
1365                 appendStringInfo(str, "<>");
1366                 return;
1367         }
1368
1369         if (IsA(obj, List))
1370         {
1371                 List       *l;
1372
1373                 appendStringInfoChar(str, '(');
1374                 foreach(l, (List *) obj)
1375                 {
1376                         _outNode(str, lfirst(l));
1377                         if (lnext(l))
1378                                 appendStringInfoChar(str, ' ');
1379                 }
1380                 appendStringInfoChar(str, ')');
1381         }
1382         else if (IsA(obj, Integer) ||
1383                          IsA(obj, Float) ||
1384                          IsA(obj, String) ||
1385                          IsA(obj, BitString))
1386         {
1387                 /* nodeRead does not want to see { } around these! */
1388                 _outValue(str, obj);
1389         }
1390         else
1391         {
1392                 appendStringInfoChar(str, '{');
1393                 switch (nodeTag(obj))
1394                 {
1395                         case T_CreateStmt:
1396                                 _outCreateStmt(str, obj);
1397                                 break;
1398                         case T_IndexStmt:
1399                                 _outIndexStmt(str, obj);
1400                                 break;
1401                         case T_NotifyStmt:
1402                                 _outNotifyStmt(str, obj);
1403                                 break;
1404                         case T_SelectStmt:
1405                                 _outSelectStmt(str, obj);
1406                                 break;
1407                         case T_ColumnDef:
1408                                 _outColumnDef(str, obj);
1409                                 break;
1410                         case T_TypeName:
1411                                 _outTypeName(str, obj);
1412                                 break;
1413                         case T_TypeCast:
1414                                 _outTypeCast(str, obj);
1415                                 break;
1416                         case T_IndexElem:
1417                                 _outIndexElem(str, obj);
1418                                 break;
1419                         case T_Query:
1420                                 _outQuery(str, obj);
1421                                 break;
1422                         case T_SortClause:
1423                                 _outSortClause(str, obj);
1424                                 break;
1425                         case T_GroupClause:
1426                                 _outGroupClause(str, obj);
1427                                 break;
1428                         case T_SetOperationStmt:
1429                                 _outSetOperationStmt(str, obj);
1430                                 break;
1431                         case T_Plan:
1432                                 _outPlan(str, obj);
1433                                 break;
1434                         case T_Result:
1435                                 _outResult(str, obj);
1436                                 break;
1437                         case T_Append:
1438                                 _outAppend(str, obj);
1439                                 break;
1440                         case T_Join:
1441                                 _outJoin(str, obj);
1442                                 break;
1443                         case T_NestLoop:
1444                                 _outNestLoop(str, obj);
1445                                 break;
1446                         case T_MergeJoin:
1447                                 _outMergeJoin(str, obj);
1448                                 break;
1449                         case T_HashJoin:
1450                                 _outHashJoin(str, obj);
1451                                 break;
1452                         case T_Scan:
1453                                 _outScan(str, obj);
1454                                 break;
1455                         case T_SeqScan:
1456                                 _outSeqScan(str, obj);
1457                                 break;
1458                         case T_IndexScan:
1459                                 _outIndexScan(str, obj);
1460                                 break;
1461                         case T_TidScan:
1462                                 _outTidScan(str, obj);
1463                                 break;
1464                         case T_SubqueryScan:
1465                                 _outSubqueryScan(str, obj);
1466                                 break;
1467                         case T_FunctionScan:
1468                                 _outFunctionScan(str, obj);
1469                                 break;
1470                         case T_Material:
1471                                 _outMaterial(str, obj);
1472                                 break;
1473                         case T_Sort:
1474                                 _outSort(str, obj);
1475                                 break;
1476                         case T_Agg:
1477                                 _outAgg(str, obj);
1478                                 break;
1479                         case T_Group:
1480                                 _outGroup(str, obj);
1481                                 break;
1482                         case T_Unique:
1483                                 _outUnique(str, obj);
1484                                 break;
1485                         case T_SetOp:
1486                                 _outSetOp(str, obj);
1487                                 break;
1488                         case T_Limit:
1489                                 _outLimit(str, obj);
1490                                 break;
1491                         case T_Hash:
1492                                 _outHash(str, obj);
1493                                 break;
1494                         case T_SubPlan:
1495                                 _outSubPlan(str, obj);
1496                                 break;
1497                         case T_Resdom:
1498                                 _outResdom(str, obj);
1499                                 break;
1500                         case T_Expr:
1501                                 _outExpr(str, obj);
1502                                 break;
1503                         case T_Var:
1504                                 _outVar(str, obj);
1505                                 break;
1506                         case T_Const:
1507                                 _outConst(str, obj);
1508                                 break;
1509                         case T_Aggref:
1510                                 _outAggref(str, obj);
1511                                 break;
1512                         case T_SubLink:
1513                                 _outSubLink(str, obj);
1514                                 break;
1515                         case T_ArrayRef:
1516                                 _outArrayRef(str, obj);
1517                                 break;
1518                         case T_Func:
1519                                 _outFunc(str, obj);
1520                                 break;
1521                         case T_Oper:
1522                                 _outOper(str, obj);
1523                                 break;
1524                         case T_Param:
1525                                 _outParam(str, obj);
1526                                 break;
1527                         case T_FieldSelect:
1528                                 _outFieldSelect(str, obj);
1529                                 break;
1530                         case T_RelabelType:
1531                                 _outRelabelType(str, obj);
1532                                 break;
1533                         case T_RangeTblRef:
1534                                 _outRangeTblRef(str, obj);
1535                                 break;
1536                         case T_FromExpr:
1537                                 _outFromExpr(str, obj);
1538                                 break;
1539                         case T_JoinExpr:
1540                                 _outJoinExpr(str, obj);
1541                                 break;
1542                         case T_TargetEntry:
1543                                 _outTargetEntry(str, obj);
1544                                 break;
1545                         case T_Alias:
1546                                 _outAlias(str, obj);
1547                                 break;
1548                         case T_RangeTblEntry:
1549                                 _outRangeTblEntry(str, obj);
1550                                 break;
1551                         case T_Path:
1552                                 _outPath(str, obj);
1553                                 break;
1554                         case T_IndexPath:
1555                                 _outIndexPath(str, obj);
1556                                 break;
1557                         case T_TidPath:
1558                                 _outTidPath(str, obj);
1559                                 break;
1560                         case T_AppendPath:
1561                                 _outAppendPath(str, obj);
1562                                 break;
1563                         case T_ResultPath:
1564                                 _outResultPath(str, obj);
1565                                 break;
1566                         case T_MaterialPath:
1567                                 _outMaterialPath(str, obj);
1568                                 break;
1569                         case T_NestPath:
1570                                 _outNestPath(str, obj);
1571                                 break;
1572                         case T_MergePath:
1573                                 _outMergePath(str, obj);
1574                                 break;
1575                         case T_HashPath:
1576                                 _outHashPath(str, obj);
1577                                 break;
1578                         case T_PathKeyItem:
1579                                 _outPathKeyItem(str, obj);
1580                                 break;
1581                         case T_RestrictInfo:
1582                                 _outRestrictInfo(str, obj);
1583                                 break;
1584                         case T_JoinInfo:
1585                                 _outJoinInfo(str, obj);
1586                                 break;
1587                         case T_A_Expr:
1588                                 _outAExpr(str, obj);
1589                                 break;
1590                         case T_RangeVar:
1591                                 _outRangeVar(str, obj);
1592                                 break;
1593                         case T_ColumnRef:
1594                                 _outColumnRef(str, obj);
1595                                 break;
1596                         case T_ParamRef:
1597                                 _outParamRef(str, obj);
1598                                 break;
1599                         case T_A_Const:
1600                                 _outAConst(str, obj);
1601                                 break;
1602                         case T_ExprFieldSelect:
1603                                 _outExprFieldSelect(str, obj);
1604                                 break;
1605                         case T_Constraint:
1606                                 _outConstraint(str, obj);
1607                                 break;
1608                         case T_FkConstraint:
1609                                 _outFkConstraint(str, obj);
1610                                 break;
1611                         case T_CaseExpr:
1612                                 _outCaseExpr(str, obj);
1613                                 break;
1614                         case T_CaseWhen:
1615                                 _outCaseWhen(str, obj);
1616                                 break;
1617                         case T_NullTest:
1618                                 _outNullTest(str, obj);
1619                                 break;
1620                         case T_BooleanTest:
1621                                 _outBooleanTest(str, obj);
1622                                 break;
1623                         case T_ConstraintTest:
1624                                 _outConstraintTest(str, obj);
1625                                 break;
1626                         case T_ConstraintTestValue:
1627                                 _outConstraintTestValue(str, obj);
1628                                 break;
1629                         case T_FuncCall:
1630                                 _outFuncCall(str, obj);
1631                                 break;
1632                         case T_DomainConstraintValue:
1633                                 _outDomainConstraintValue(str, obj);
1634                                 break;
1635
1636                         default:
1637                                 elog(WARNING, "_outNode: don't know how to print type %d",
1638                                          nodeTag(obj));
1639                                 break;
1640                 }
1641                 appendStringInfoChar(str, '}');
1642         }
1643 }
1644
1645 /*
1646  * nodeToString -
1647  *         returns the ascii representation of the Node as a palloc'd string
1648  */
1649 char *
1650 nodeToString(void *obj)
1651 {
1652         StringInfoData str;
1653
1654         /* see stringinfo.h for an explanation of this maneuver */
1655         initStringInfo(&str);
1656         _outNode(&str, obj);
1657         return str.data;
1658 }