]> granicus.if.org Git - postgresql/blob - src/backend/nodes/outfuncs.c
Instead of supposing (wrongly, in the general case) that the rowtype
[postgresql] / src / backend / nodes / outfuncs.c
1 /*-------------------------------------------------------------------------
2  *
3  * outfuncs.c
4  *        Output functions for Postgres tree nodes.
5  *
6  * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.244 2004/12/11 23:26:33 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 "utils/datum.h"
31
32
33 /*
34  * Macros to simplify output of different kinds of fields.      Use these
35  * wherever possible to reduce the chance for silly typos.      Note that these
36  * hard-wire conventions about the names of the local variables in an Out
37  * routine.
38  */
39
40 /* Write the label for the node type */
41 #define WRITE_NODE_TYPE(nodelabel) \
42         appendStringInfoString(str, nodelabel)
43
44 /* Write an integer field (anything written as ":fldname %d") */
45 #define WRITE_INT_FIELD(fldname) \
46         appendStringInfo(str, " :" CppAsString(fldname) " %d", node->fldname)
47
48 /* Write an unsigned integer field (anything written as ":fldname %u") */
49 #define WRITE_UINT_FIELD(fldname) \
50         appendStringInfo(str, " :" CppAsString(fldname) " %u", node->fldname)
51
52 /* Write an OID field (don't hard-wire assumption that OID is same as uint) */
53 #define WRITE_OID_FIELD(fldname) \
54         appendStringInfo(str, " :" CppAsString(fldname) " %u", node->fldname)
55
56 /* Write a long-integer field */
57 #define WRITE_LONG_FIELD(fldname) \
58         appendStringInfo(str, " :" CppAsString(fldname) " %ld", node->fldname)
59
60 /* Write a char field (ie, one ascii character) */
61 #define WRITE_CHAR_FIELD(fldname) \
62         appendStringInfo(str, " :" CppAsString(fldname) " %c", node->fldname)
63
64 /* Write an enumerated-type field as an integer code */
65 #define WRITE_ENUM_FIELD(fldname, enumtype) \
66         appendStringInfo(str, " :" CppAsString(fldname) " %d", \
67                                          (int) node->fldname)
68
69 /* Write a float field --- caller must give format to define precision */
70 #define WRITE_FLOAT_FIELD(fldname,format) \
71         appendStringInfo(str, " :" CppAsString(fldname) " " format, node->fldname)
72
73 /* Write a boolean field */
74 #define WRITE_BOOL_FIELD(fldname) \
75         appendStringInfo(str, " :" CppAsString(fldname) " %s", \
76                                          booltostr(node->fldname))
77
78 /* Write a character-string (possibly NULL) field */
79 #define WRITE_STRING_FIELD(fldname) \
80         (appendStringInfo(str, " :" CppAsString(fldname) " "), \
81          _outToken(str, node->fldname))
82
83 /* Write a Node field */
84 #define WRITE_NODE_FIELD(fldname) \
85         (appendStringInfo(str, " :" CppAsString(fldname) " "), \
86          _outNode(str, node->fldname))
87
88 /* Write a bitmapset field */
89 #define WRITE_BITMAPSET_FIELD(fldname) \
90         (appendStringInfo(str, " :" CppAsString(fldname) " "), \
91          _outBitmapset(str, node->fldname))
92
93
94 #define booltostr(x)  ((x) ? "true" : "false")
95
96 static void _outNode(StringInfo str, void *obj);
97
98
99 /*
100  * _outToken
101  *        Convert an ordinary string (eg, an identifier) into a form that
102  *        will be decoded back to a plain token by read.c's functions.
103  *
104  *        If a null or empty string is given, it is encoded as "<>".
105  */
106 static void
107 _outToken(StringInfo str, char *s)
108 {
109         if (s == NULL || *s == '\0')
110         {
111                 appendStringInfo(str, "<>");
112                 return;
113         }
114
115         /*
116          * Look for characters or patterns that are treated specially by
117          * read.c (either in pg_strtok() or in nodeRead()), and therefore need
118          * a protective backslash.
119          */
120         /* These characters only need to be quoted at the start of the string */
121         if (*s == '<' ||
122                 *s == '\"' ||
123                 isdigit((unsigned char) *s) ||
124                 ((*s == '+' || *s == '-') &&
125                  (isdigit((unsigned char) s[1]) || s[1] == '.')))
126                 appendStringInfoChar(str, '\\');
127         while (*s)
128         {
129                 /* These chars must be backslashed anywhere in the string */
130                 if (*s == ' ' || *s == '\n' || *s == '\t' ||
131                         *s == '(' || *s == ')' || *s == '{' || *s == '}' ||
132                         *s == '\\')
133                         appendStringInfoChar(str, '\\');
134                 appendStringInfoChar(str, *s++);
135         }
136 }
137
138 static void
139 _outList(StringInfo str, List *node)
140 {
141         ListCell   *lc;
142
143         appendStringInfoChar(str, '(');
144
145         if (IsA(node, IntList))
146                 appendStringInfoChar(str, 'i');
147         else if (IsA(node, OidList))
148                 appendStringInfoChar(str, 'o');
149
150         foreach(lc, node)
151         {
152                 /*
153                  * For the sake of backward compatibility, we emit a slightly
154                  * different whitespace format for lists of nodes vs. other types
155                  * of lists. XXX: is this necessary?
156                  */
157                 if (IsA(node, List))
158                 {
159                         _outNode(str, lfirst(lc));
160                         if (lnext(lc))
161                                 appendStringInfoChar(str, ' ');
162                 }
163                 else if (IsA(node, IntList))
164                         appendStringInfo(str, " %d", lfirst_int(lc));
165                 else if (IsA(node, OidList))
166                         appendStringInfo(str, " %u", lfirst_oid(lc));
167                 else
168                         elog(ERROR, "unrecognized list node type: %d",
169                                  (int) node->type);
170         }
171
172         appendStringInfoChar(str, ')');
173 }
174
175 /*
176  * _outBitmapset -
177  *         converts a bitmap set of integers
178  *
179  * Note: the output format is "(b int int ...)", similar to an integer List.
180  * Currently bitmapsets do not appear in any node type that is stored in
181  * rules, so there is no support in readfuncs.c for reading this format.
182  */
183 static void
184 _outBitmapset(StringInfo str, Bitmapset *bms)
185 {
186         Bitmapset  *tmpset;
187         int                     x;
188
189         appendStringInfoChar(str, '(');
190         appendStringInfoChar(str, 'b');
191         tmpset = bms_copy(bms);
192         while ((x = bms_first_member(tmpset)) >= 0)
193                 appendStringInfo(str, " %d", x);
194         bms_free(tmpset);
195         appendStringInfoChar(str, ')');
196 }
197
198 /*
199  * Print the value of a Datum given its type.
200  */
201 static void
202 _outDatum(StringInfo str, Datum value, int typlen, bool typbyval)
203 {
204         Size            length,
205                                 i;
206         char       *s;
207
208         length = datumGetSize(value, typbyval, typlen);
209
210         if (typbyval)
211         {
212                 s = (char *) (&value);
213                 appendStringInfo(str, "%u [ ", (unsigned int) length);
214                 for (i = 0; i < (Size) sizeof(Datum); i++)
215                         appendStringInfo(str, "%d ", (int) (s[i]));
216                 appendStringInfo(str, "]");
217         }
218         else
219         {
220                 s = (char *) DatumGetPointer(value);
221                 if (!PointerIsValid(s))
222                         appendStringInfo(str, "0 [ ]");
223                 else
224                 {
225                         appendStringInfo(str, "%u [ ", (unsigned int) length);
226                         for (i = 0; i < length; i++)
227                                 appendStringInfo(str, "%d ", (int) (s[i]));
228                         appendStringInfo(str, "]");
229                 }
230         }
231 }
232
233
234 /*
235  *      Stuff from plannodes.h
236  */
237
238 /*
239  * print the basic stuff of all nodes that inherit from Plan
240  */
241 static void
242 _outPlanInfo(StringInfo str, Plan *node)
243 {
244         WRITE_FLOAT_FIELD(startup_cost, "%.2f");
245         WRITE_FLOAT_FIELD(total_cost, "%.2f");
246         WRITE_FLOAT_FIELD(plan_rows, "%.0f");
247         WRITE_INT_FIELD(plan_width);
248         WRITE_NODE_FIELD(targetlist);
249         WRITE_NODE_FIELD(qual);
250         WRITE_NODE_FIELD(lefttree);
251         WRITE_NODE_FIELD(righttree);
252         WRITE_NODE_FIELD(initPlan);
253         WRITE_BITMAPSET_FIELD(extParam);
254         WRITE_BITMAPSET_FIELD(allParam);
255         WRITE_INT_FIELD(nParamExec);
256 }
257
258 /*
259  * print the basic stuff of all nodes that inherit from Scan
260  */
261 static void
262 _outScanInfo(StringInfo str, Scan *node)
263 {
264         _outPlanInfo(str, (Plan *) node);
265
266         WRITE_UINT_FIELD(scanrelid);
267 }
268
269 /*
270  * print the basic stuff of all nodes that inherit from Join
271  */
272 static void
273 _outJoinPlanInfo(StringInfo str, Join *node)
274 {
275         _outPlanInfo(str, (Plan *) node);
276
277         WRITE_ENUM_FIELD(jointype, JoinType);
278         WRITE_NODE_FIELD(joinqual);
279 }
280
281
282 static void
283 _outPlan(StringInfo str, Plan *node)
284 {
285         WRITE_NODE_TYPE("PLAN");
286
287         _outPlanInfo(str, (Plan *) node);
288 }
289
290 static void
291 _outResult(StringInfo str, Result *node)
292 {
293         WRITE_NODE_TYPE("RESULT");
294
295         _outPlanInfo(str, (Plan *) node);
296
297         WRITE_NODE_FIELD(resconstantqual);
298 }
299
300 static void
301 _outAppend(StringInfo str, Append *node)
302 {
303         WRITE_NODE_TYPE("APPEND");
304
305         _outPlanInfo(str, (Plan *) node);
306
307         WRITE_NODE_FIELD(appendplans);
308         WRITE_BOOL_FIELD(isTarget);
309 }
310
311 static void
312 _outScan(StringInfo str, Scan *node)
313 {
314         WRITE_NODE_TYPE("SCAN");
315
316         _outScanInfo(str, (Scan *) node);
317 }
318
319 static void
320 _outSeqScan(StringInfo str, SeqScan *node)
321 {
322         WRITE_NODE_TYPE("SEQSCAN");
323
324         _outScanInfo(str, (Scan *) node);
325 }
326
327 static void
328 _outIndexScan(StringInfo str, IndexScan *node)
329 {
330         WRITE_NODE_TYPE("INDEXSCAN");
331
332         _outScanInfo(str, (Scan *) node);
333
334         WRITE_NODE_FIELD(indxid);
335         WRITE_NODE_FIELD(indxqual);
336         WRITE_NODE_FIELD(indxqualorig);
337         WRITE_NODE_FIELD(indxstrategy);
338         WRITE_NODE_FIELD(indxsubtype);
339         WRITE_NODE_FIELD(indxlossy);
340         WRITE_ENUM_FIELD(indxorderdir, ScanDirection);
341 }
342
343 static void
344 _outTidScan(StringInfo str, TidScan *node)
345 {
346         WRITE_NODE_TYPE("TIDSCAN");
347
348         _outScanInfo(str, (Scan *) node);
349
350         WRITE_NODE_FIELD(tideval);
351 }
352
353 static void
354 _outSubqueryScan(StringInfo str, SubqueryScan *node)
355 {
356         WRITE_NODE_TYPE("SUBQUERYSCAN");
357
358         _outScanInfo(str, (Scan *) node);
359
360         WRITE_NODE_FIELD(subplan);
361 }
362
363 static void
364 _outFunctionScan(StringInfo str, FunctionScan *node)
365 {
366         WRITE_NODE_TYPE("FUNCTIONSCAN");
367
368         _outScanInfo(str, (Scan *) node);
369 }
370
371 static void
372 _outJoin(StringInfo str, Join *node)
373 {
374         WRITE_NODE_TYPE("JOIN");
375
376         _outJoinPlanInfo(str, (Join *) node);
377 }
378
379 static void
380 _outNestLoop(StringInfo str, NestLoop *node)
381 {
382         WRITE_NODE_TYPE("NESTLOOP");
383
384         _outJoinPlanInfo(str, (Join *) node);
385 }
386
387 static void
388 _outMergeJoin(StringInfo str, MergeJoin *node)
389 {
390         WRITE_NODE_TYPE("MERGEJOIN");
391
392         _outJoinPlanInfo(str, (Join *) node);
393
394         WRITE_NODE_FIELD(mergeclauses);
395 }
396
397 static void
398 _outHashJoin(StringInfo str, HashJoin *node)
399 {
400         WRITE_NODE_TYPE("HASHJOIN");
401
402         _outJoinPlanInfo(str, (Join *) node);
403
404         WRITE_NODE_FIELD(hashclauses);
405 }
406
407 static void
408 _outAgg(StringInfo str, Agg *node)
409 {
410         WRITE_NODE_TYPE("AGG");
411
412         _outPlanInfo(str, (Plan *) node);
413
414         WRITE_ENUM_FIELD(aggstrategy, AggStrategy);
415         WRITE_INT_FIELD(numCols);
416         WRITE_LONG_FIELD(numGroups);
417 }
418
419 static void
420 _outGroup(StringInfo str, Group *node)
421 {
422         int                     i;
423
424         WRITE_NODE_TYPE("GROUP");
425
426         _outPlanInfo(str, (Plan *) node);
427
428         WRITE_INT_FIELD(numCols);
429
430         appendStringInfo(str, " :grpColIdx");
431         for (i = 0; i < node->numCols; i++)
432                 appendStringInfo(str, " %d", node->grpColIdx[i]);
433 }
434
435 static void
436 _outMaterial(StringInfo str, Material *node)
437 {
438         WRITE_NODE_TYPE("MATERIAL");
439
440         _outPlanInfo(str, (Plan *) node);
441 }
442
443 static void
444 _outSort(StringInfo str, Sort *node)
445 {
446         int                     i;
447
448         WRITE_NODE_TYPE("SORT");
449
450         _outPlanInfo(str, (Plan *) node);
451
452         WRITE_INT_FIELD(numCols);
453
454         appendStringInfo(str, " :sortColIdx");
455         for (i = 0; i < node->numCols; i++)
456                 appendStringInfo(str, " %d", node->sortColIdx[i]);
457
458         appendStringInfo(str, " :sortOperators");
459         for (i = 0; i < node->numCols; i++)
460                 appendStringInfo(str, " %u", node->sortOperators[i]);
461 }
462
463 static void
464 _outUnique(StringInfo str, Unique *node)
465 {
466         int                     i;
467
468         WRITE_NODE_TYPE("UNIQUE");
469
470         _outPlanInfo(str, (Plan *) node);
471
472         WRITE_INT_FIELD(numCols);
473
474         appendStringInfo(str, " :uniqColIdx");
475         for (i = 0; i < node->numCols; i++)
476                 appendStringInfo(str, " %d", node->uniqColIdx[i]);
477 }
478
479 static void
480 _outSetOp(StringInfo str, SetOp *node)
481 {
482         int                     i;
483
484         WRITE_NODE_TYPE("SETOP");
485
486         _outPlanInfo(str, (Plan *) node);
487
488         WRITE_ENUM_FIELD(cmd, SetOpCmd);
489         WRITE_INT_FIELD(numCols);
490
491         appendStringInfo(str, " :dupColIdx");
492         for (i = 0; i < node->numCols; i++)
493                 appendStringInfo(str, " %d", node->dupColIdx[i]);
494
495         WRITE_INT_FIELD(flagColIdx);
496 }
497
498 static void
499 _outLimit(StringInfo str, Limit *node)
500 {
501         WRITE_NODE_TYPE("LIMIT");
502
503         _outPlanInfo(str, (Plan *) node);
504
505         WRITE_NODE_FIELD(limitOffset);
506         WRITE_NODE_FIELD(limitCount);
507 }
508
509 static void
510 _outHash(StringInfo str, Hash *node)
511 {
512         WRITE_NODE_TYPE("HASH");
513
514         _outPlanInfo(str, (Plan *) node);
515 }
516
517 /*****************************************************************************
518  *
519  *      Stuff from primnodes.h.
520  *
521  *****************************************************************************/
522
523 static void
524 _outResdom(StringInfo str, Resdom *node)
525 {
526         WRITE_NODE_TYPE("RESDOM");
527
528         WRITE_INT_FIELD(resno);
529         WRITE_OID_FIELD(restype);
530         WRITE_INT_FIELD(restypmod);
531         WRITE_STRING_FIELD(resname);
532         WRITE_UINT_FIELD(ressortgroupref);
533         WRITE_OID_FIELD(resorigtbl);
534         WRITE_INT_FIELD(resorigcol);
535         WRITE_BOOL_FIELD(resjunk);
536 }
537
538 static void
539 _outAlias(StringInfo str, Alias *node)
540 {
541         WRITE_NODE_TYPE("ALIAS");
542
543         WRITE_STRING_FIELD(aliasname);
544         WRITE_NODE_FIELD(colnames);
545 }
546
547 static void
548 _outRangeVar(StringInfo str, RangeVar *node)
549 {
550         WRITE_NODE_TYPE("RANGEVAR");
551
552         /*
553          * we deliberately ignore catalogname here, since it is presently not
554          * semantically meaningful
555          */
556         WRITE_STRING_FIELD(schemaname);
557         WRITE_STRING_FIELD(relname);
558         WRITE_ENUM_FIELD(inhOpt, InhOption);
559         WRITE_BOOL_FIELD(istemp);
560         WRITE_NODE_FIELD(alias);
561 }
562
563 static void
564 _outVar(StringInfo str, Var *node)
565 {
566         WRITE_NODE_TYPE("VAR");
567
568         WRITE_UINT_FIELD(varno);
569         WRITE_INT_FIELD(varattno);
570         WRITE_OID_FIELD(vartype);
571         WRITE_INT_FIELD(vartypmod);
572         WRITE_UINT_FIELD(varlevelsup);
573         WRITE_UINT_FIELD(varnoold);
574         WRITE_INT_FIELD(varoattno);
575 }
576
577 static void
578 _outConst(StringInfo str, Const *node)
579 {
580         WRITE_NODE_TYPE("CONST");
581
582         WRITE_OID_FIELD(consttype);
583         WRITE_INT_FIELD(constlen);
584         WRITE_BOOL_FIELD(constbyval);
585         WRITE_BOOL_FIELD(constisnull);
586
587         appendStringInfo(str, " :constvalue ");
588         if (node->constisnull)
589                 appendStringInfo(str, "<>");
590         else
591                 _outDatum(str, node->constvalue, node->constlen, node->constbyval);
592 }
593
594 static void
595 _outParam(StringInfo str, Param *node)
596 {
597         WRITE_NODE_TYPE("PARAM");
598
599         WRITE_INT_FIELD(paramkind);
600         WRITE_INT_FIELD(paramid);
601         WRITE_STRING_FIELD(paramname);
602         WRITE_OID_FIELD(paramtype);
603 }
604
605 static void
606 _outAggref(StringInfo str, Aggref *node)
607 {
608         WRITE_NODE_TYPE("AGGREF");
609
610         WRITE_OID_FIELD(aggfnoid);
611         WRITE_OID_FIELD(aggtype);
612         WRITE_NODE_FIELD(target);
613         WRITE_UINT_FIELD(agglevelsup);
614         WRITE_BOOL_FIELD(aggstar);
615         WRITE_BOOL_FIELD(aggdistinct);
616 }
617
618 static void
619 _outArrayRef(StringInfo str, ArrayRef *node)
620 {
621         WRITE_NODE_TYPE("ARRAYREF");
622
623         WRITE_OID_FIELD(refrestype);
624         WRITE_OID_FIELD(refarraytype);
625         WRITE_OID_FIELD(refelemtype);
626         WRITE_NODE_FIELD(refupperindexpr);
627         WRITE_NODE_FIELD(reflowerindexpr);
628         WRITE_NODE_FIELD(refexpr);
629         WRITE_NODE_FIELD(refassgnexpr);
630 }
631
632 static void
633 _outFuncExpr(StringInfo str, FuncExpr *node)
634 {
635         WRITE_NODE_TYPE("FUNCEXPR");
636
637         WRITE_OID_FIELD(funcid);
638         WRITE_OID_FIELD(funcresulttype);
639         WRITE_BOOL_FIELD(funcretset);
640         WRITE_ENUM_FIELD(funcformat, CoercionForm);
641         WRITE_NODE_FIELD(args);
642 }
643
644 static void
645 _outOpExpr(StringInfo str, OpExpr *node)
646 {
647         WRITE_NODE_TYPE("OPEXPR");
648
649         WRITE_OID_FIELD(opno);
650         WRITE_OID_FIELD(opfuncid);
651         WRITE_OID_FIELD(opresulttype);
652         WRITE_BOOL_FIELD(opretset);
653         WRITE_NODE_FIELD(args);
654 }
655
656 static void
657 _outDistinctExpr(StringInfo str, DistinctExpr *node)
658 {
659         WRITE_NODE_TYPE("DISTINCTEXPR");
660
661         WRITE_OID_FIELD(opno);
662         WRITE_OID_FIELD(opfuncid);
663         WRITE_OID_FIELD(opresulttype);
664         WRITE_BOOL_FIELD(opretset);
665         WRITE_NODE_FIELD(args);
666 }
667
668 static void
669 _outScalarArrayOpExpr(StringInfo str, ScalarArrayOpExpr *node)
670 {
671         WRITE_NODE_TYPE("SCALARARRAYOPEXPR");
672
673         WRITE_OID_FIELD(opno);
674         WRITE_OID_FIELD(opfuncid);
675         WRITE_BOOL_FIELD(useOr);
676         WRITE_NODE_FIELD(args);
677 }
678
679 static void
680 _outBoolExpr(StringInfo str, BoolExpr *node)
681 {
682         char       *opstr = NULL;
683
684         WRITE_NODE_TYPE("BOOLEXPR");
685
686         /* do-it-yourself enum representation */
687         switch (node->boolop)
688         {
689                 case AND_EXPR:
690                         opstr = "and";
691                         break;
692                 case OR_EXPR:
693                         opstr = "or";
694                         break;
695                 case NOT_EXPR:
696                         opstr = "not";
697                         break;
698         }
699         appendStringInfo(str, " :boolop ");
700         _outToken(str, opstr);
701
702         WRITE_NODE_FIELD(args);
703 }
704
705 static void
706 _outSubLink(StringInfo str, SubLink *node)
707 {
708         WRITE_NODE_TYPE("SUBLINK");
709
710         WRITE_ENUM_FIELD(subLinkType, SubLinkType);
711         WRITE_BOOL_FIELD(useOr);
712         WRITE_NODE_FIELD(lefthand);
713         WRITE_NODE_FIELD(operName);
714         WRITE_NODE_FIELD(operOids);
715         WRITE_NODE_FIELD(subselect);
716 }
717
718 static void
719 _outSubPlan(StringInfo str, SubPlan *node)
720 {
721         WRITE_NODE_TYPE("SUBPLAN");
722
723         WRITE_ENUM_FIELD(subLinkType, SubLinkType);
724         WRITE_BOOL_FIELD(useOr);
725         WRITE_NODE_FIELD(exprs);
726         WRITE_NODE_FIELD(paramIds);
727         WRITE_NODE_FIELD(plan);
728         WRITE_INT_FIELD(plan_id);
729         WRITE_NODE_FIELD(rtable);
730         WRITE_BOOL_FIELD(useHashTable);
731         WRITE_BOOL_FIELD(unknownEqFalse);
732         WRITE_NODE_FIELD(setParam);
733         WRITE_NODE_FIELD(parParam);
734         WRITE_NODE_FIELD(args);
735 }
736
737 static void
738 _outFieldSelect(StringInfo str, FieldSelect *node)
739 {
740         WRITE_NODE_TYPE("FIELDSELECT");
741
742         WRITE_NODE_FIELD(arg);
743         WRITE_INT_FIELD(fieldnum);
744         WRITE_OID_FIELD(resulttype);
745         WRITE_INT_FIELD(resulttypmod);
746 }
747
748 static void
749 _outFieldStore(StringInfo str, FieldStore *node)
750 {
751         WRITE_NODE_TYPE("FIELDSTORE");
752
753         WRITE_NODE_FIELD(arg);
754         WRITE_NODE_FIELD(newvals);
755         WRITE_NODE_FIELD(fieldnums);
756         WRITE_OID_FIELD(resulttype);
757 }
758
759 static void
760 _outRelabelType(StringInfo str, RelabelType *node)
761 {
762         WRITE_NODE_TYPE("RELABELTYPE");
763
764         WRITE_NODE_FIELD(arg);
765         WRITE_OID_FIELD(resulttype);
766         WRITE_INT_FIELD(resulttypmod);
767         WRITE_ENUM_FIELD(relabelformat, CoercionForm);
768 }
769
770 static void
771 _outConvertRowtypeExpr(StringInfo str, ConvertRowtypeExpr *node)
772 {
773         WRITE_NODE_TYPE("CONVERTROWTYPEEXPR");
774
775         WRITE_NODE_FIELD(arg);
776         WRITE_OID_FIELD(resulttype);
777         WRITE_ENUM_FIELD(convertformat, CoercionForm);
778 }
779
780 static void
781 _outCaseExpr(StringInfo str, CaseExpr *node)
782 {
783         WRITE_NODE_TYPE("CASE");
784
785         WRITE_OID_FIELD(casetype);
786         WRITE_NODE_FIELD(arg);
787         WRITE_NODE_FIELD(args);
788         WRITE_NODE_FIELD(defresult);
789 }
790
791 static void
792 _outCaseWhen(StringInfo str, CaseWhen *node)
793 {
794         WRITE_NODE_TYPE("WHEN");
795
796         WRITE_NODE_FIELD(expr);
797         WRITE_NODE_FIELD(result);
798 }
799
800 static void
801 _outCaseTestExpr(StringInfo str, CaseTestExpr *node)
802 {
803         WRITE_NODE_TYPE("CASETESTEXPR");
804
805         WRITE_OID_FIELD(typeId);
806         WRITE_INT_FIELD(typeMod);
807 }
808
809 static void
810 _outArrayExpr(StringInfo str, ArrayExpr *node)
811 {
812         WRITE_NODE_TYPE("ARRAY");
813
814         WRITE_OID_FIELD(array_typeid);
815         WRITE_OID_FIELD(element_typeid);
816         WRITE_NODE_FIELD(elements);
817         WRITE_BOOL_FIELD(multidims);
818 }
819
820 static void
821 _outRowExpr(StringInfo str, RowExpr *node)
822 {
823         WRITE_NODE_TYPE("ROW");
824
825         WRITE_NODE_FIELD(args);
826         WRITE_OID_FIELD(row_typeid);
827         WRITE_ENUM_FIELD(row_format, CoercionForm);
828 }
829
830 static void
831 _outCoalesceExpr(StringInfo str, CoalesceExpr *node)
832 {
833         WRITE_NODE_TYPE("COALESCE");
834
835         WRITE_OID_FIELD(coalescetype);
836         WRITE_NODE_FIELD(args);
837 }
838
839 static void
840 _outNullIfExpr(StringInfo str, NullIfExpr *node)
841 {
842         WRITE_NODE_TYPE("NULLIFEXPR");
843
844         WRITE_OID_FIELD(opno);
845         WRITE_OID_FIELD(opfuncid);
846         WRITE_OID_FIELD(opresulttype);
847         WRITE_BOOL_FIELD(opretset);
848         WRITE_NODE_FIELD(args);
849 }
850
851 static void
852 _outNullTest(StringInfo str, NullTest *node)
853 {
854         WRITE_NODE_TYPE("NULLTEST");
855
856         WRITE_NODE_FIELD(arg);
857         WRITE_ENUM_FIELD(nulltesttype, NullTestType);
858 }
859
860 static void
861 _outBooleanTest(StringInfo str, BooleanTest *node)
862 {
863         WRITE_NODE_TYPE("BOOLEANTEST");
864
865         WRITE_NODE_FIELD(arg);
866         WRITE_ENUM_FIELD(booltesttype, BoolTestType);
867 }
868
869 static void
870 _outCoerceToDomain(StringInfo str, CoerceToDomain *node)
871 {
872         WRITE_NODE_TYPE("COERCETODOMAIN");
873
874         WRITE_NODE_FIELD(arg);
875         WRITE_OID_FIELD(resulttype);
876         WRITE_INT_FIELD(resulttypmod);
877         WRITE_ENUM_FIELD(coercionformat, CoercionForm);
878 }
879
880 static void
881 _outCoerceToDomainValue(StringInfo str, CoerceToDomainValue *node)
882 {
883         WRITE_NODE_TYPE("COERCETODOMAINVALUE");
884
885         WRITE_OID_FIELD(typeId);
886         WRITE_INT_FIELD(typeMod);
887 }
888
889 static void
890 _outSetToDefault(StringInfo str, SetToDefault *node)
891 {
892         WRITE_NODE_TYPE("SETTODEFAULT");
893
894         WRITE_OID_FIELD(typeId);
895         WRITE_INT_FIELD(typeMod);
896 }
897
898 static void
899 _outTargetEntry(StringInfo str, TargetEntry *node)
900 {
901         WRITE_NODE_TYPE("TARGETENTRY");
902
903         WRITE_NODE_FIELD(resdom);
904         WRITE_NODE_FIELD(expr);
905 }
906
907 static void
908 _outRangeTblRef(StringInfo str, RangeTblRef *node)
909 {
910         WRITE_NODE_TYPE("RANGETBLREF");
911
912         WRITE_INT_FIELD(rtindex);
913 }
914
915 static void
916 _outJoinExpr(StringInfo str, JoinExpr *node)
917 {
918         WRITE_NODE_TYPE("JOINEXPR");
919
920         WRITE_ENUM_FIELD(jointype, JoinType);
921         WRITE_BOOL_FIELD(isNatural);
922         WRITE_NODE_FIELD(larg);
923         WRITE_NODE_FIELD(rarg);
924         WRITE_NODE_FIELD(using);
925         WRITE_NODE_FIELD(quals);
926         WRITE_NODE_FIELD(alias);
927         WRITE_INT_FIELD(rtindex);
928 }
929
930 static void
931 _outFromExpr(StringInfo str, FromExpr *node)
932 {
933         WRITE_NODE_TYPE("FROMEXPR");
934
935         WRITE_NODE_FIELD(fromlist);
936         WRITE_NODE_FIELD(quals);
937 }
938
939 /*****************************************************************************
940  *
941  *      Stuff from relation.h.
942  *
943  *****************************************************************************/
944
945 /*
946  * print the basic stuff of all nodes that inherit from Path
947  *
948  * Note we do NOT print the parent, else we'd be in infinite recursion
949  */
950 static void
951 _outPathInfo(StringInfo str, Path *node)
952 {
953         WRITE_ENUM_FIELD(pathtype, NodeTag);
954         WRITE_FLOAT_FIELD(startup_cost, "%.2f");
955         WRITE_FLOAT_FIELD(total_cost, "%.2f");
956         WRITE_NODE_FIELD(pathkeys);
957 }
958
959 /*
960  * print the basic stuff of all nodes that inherit from JoinPath
961  */
962 static void
963 _outJoinPathInfo(StringInfo str, JoinPath *node)
964 {
965         _outPathInfo(str, (Path *) node);
966
967         WRITE_ENUM_FIELD(jointype, JoinType);
968         WRITE_NODE_FIELD(outerjoinpath);
969         WRITE_NODE_FIELD(innerjoinpath);
970         WRITE_NODE_FIELD(joinrestrictinfo);
971 }
972
973 static void
974 _outPath(StringInfo str, Path *node)
975 {
976         WRITE_NODE_TYPE("PATH");
977
978         _outPathInfo(str, (Path *) node);
979 }
980
981 /*
982  *      IndexPath is a subclass of Path.
983  */
984 static void
985 _outIndexPath(StringInfo str, IndexPath *node)
986 {
987         WRITE_NODE_TYPE("INDEXPATH");
988
989         _outPathInfo(str, (Path *) node);
990
991         WRITE_NODE_FIELD(indexinfo);
992         WRITE_NODE_FIELD(indexclauses);
993         WRITE_NODE_FIELD(indexquals);
994         WRITE_BOOL_FIELD(isjoininner);
995         WRITE_ENUM_FIELD(indexscandir, ScanDirection);
996         WRITE_FLOAT_FIELD(rows, "%.0f");
997 }
998
999 static void
1000 _outTidPath(StringInfo str, TidPath *node)
1001 {
1002         WRITE_NODE_TYPE("TIDPATH");
1003
1004         _outPathInfo(str, (Path *) node);
1005
1006         WRITE_NODE_FIELD(tideval);
1007 }
1008
1009 static void
1010 _outAppendPath(StringInfo str, AppendPath *node)
1011 {
1012         WRITE_NODE_TYPE("APPENDPATH");
1013
1014         _outPathInfo(str, (Path *) node);
1015
1016         WRITE_NODE_FIELD(subpaths);
1017 }
1018
1019 static void
1020 _outResultPath(StringInfo str, ResultPath *node)
1021 {
1022         WRITE_NODE_TYPE("RESULTPATH");
1023
1024         _outPathInfo(str, (Path *) node);
1025
1026         WRITE_NODE_FIELD(subpath);
1027         WRITE_NODE_FIELD(constantqual);
1028 }
1029
1030 static void
1031 _outMaterialPath(StringInfo str, MaterialPath *node)
1032 {
1033         WRITE_NODE_TYPE("MATERIALPATH");
1034
1035         _outPathInfo(str, (Path *) node);
1036
1037         WRITE_NODE_FIELD(subpath);
1038 }
1039
1040 static void
1041 _outUniquePath(StringInfo str, UniquePath *node)
1042 {
1043         WRITE_NODE_TYPE("UNIQUEPATH");
1044
1045         _outPathInfo(str, (Path *) node);
1046
1047         WRITE_NODE_FIELD(subpath);
1048         WRITE_ENUM_FIELD(umethod, UniquePathMethod);
1049         WRITE_FLOAT_FIELD(rows, "%.0f");
1050 }
1051
1052 static void
1053 _outNestPath(StringInfo str, NestPath *node)
1054 {
1055         WRITE_NODE_TYPE("NESTPATH");
1056
1057         _outJoinPathInfo(str, (JoinPath *) node);
1058 }
1059
1060 static void
1061 _outMergePath(StringInfo str, MergePath *node)
1062 {
1063         WRITE_NODE_TYPE("MERGEPATH");
1064
1065         _outJoinPathInfo(str, (JoinPath *) node);
1066
1067         WRITE_NODE_FIELD(path_mergeclauses);
1068         WRITE_NODE_FIELD(outersortkeys);
1069         WRITE_NODE_FIELD(innersortkeys);
1070 }
1071
1072 static void
1073 _outHashPath(StringInfo str, HashPath *node)
1074 {
1075         WRITE_NODE_TYPE("HASHPATH");
1076
1077         _outJoinPathInfo(str, (JoinPath *) node);
1078
1079         WRITE_NODE_FIELD(path_hashclauses);
1080 }
1081
1082 static void
1083 _outPathKeyItem(StringInfo str, PathKeyItem *node)
1084 {
1085         WRITE_NODE_TYPE("PATHKEYITEM");
1086
1087         WRITE_NODE_FIELD(key);
1088         WRITE_OID_FIELD(sortop);
1089 }
1090
1091 static void
1092 _outRestrictInfo(StringInfo str, RestrictInfo *node)
1093 {
1094         WRITE_NODE_TYPE("RESTRICTINFO");
1095
1096         /* NB: this isn't a complete set of fields */
1097         WRITE_NODE_FIELD(clause);
1098         WRITE_BOOL_FIELD(is_pushed_down);
1099         WRITE_BOOL_FIELD(valid_everywhere);
1100         WRITE_BOOL_FIELD(can_join);
1101         WRITE_BITMAPSET_FIELD(clause_relids);
1102         WRITE_BITMAPSET_FIELD(left_relids);
1103         WRITE_BITMAPSET_FIELD(right_relids);
1104         WRITE_NODE_FIELD(orclause);
1105         WRITE_OID_FIELD(mergejoinoperator);
1106         WRITE_OID_FIELD(left_sortop);
1107         WRITE_OID_FIELD(right_sortop);
1108         WRITE_NODE_FIELD(left_pathkey);
1109         WRITE_NODE_FIELD(right_pathkey);
1110         WRITE_OID_FIELD(hashjoinoperator);
1111 }
1112
1113 static void
1114 _outJoinInfo(StringInfo str, JoinInfo *node)
1115 {
1116         WRITE_NODE_TYPE("JOININFO");
1117
1118         WRITE_BITMAPSET_FIELD(unjoined_relids);
1119         WRITE_NODE_FIELD(jinfo_restrictinfo);
1120 }
1121
1122 static void
1123 _outInClauseInfo(StringInfo str, InClauseInfo *node)
1124 {
1125         WRITE_NODE_TYPE("INCLAUSEINFO");
1126
1127         WRITE_BITMAPSET_FIELD(lefthand);
1128         WRITE_BITMAPSET_FIELD(righthand);
1129         WRITE_NODE_FIELD(sub_targetlist);
1130 }
1131
1132 /*****************************************************************************
1133  *
1134  *      Stuff from parsenodes.h.
1135  *
1136  *****************************************************************************/
1137
1138 static void
1139 _outCreateStmt(StringInfo str, CreateStmt *node)
1140 {
1141         WRITE_NODE_TYPE("CREATESTMT");
1142
1143         WRITE_NODE_FIELD(relation);
1144         WRITE_NODE_FIELD(tableElts);
1145         WRITE_NODE_FIELD(inhRelations);
1146         WRITE_NODE_FIELD(constraints);
1147         WRITE_ENUM_FIELD(hasoids, ContainsOids);
1148         WRITE_ENUM_FIELD(oncommit, OnCommitAction);
1149         WRITE_STRING_FIELD(tablespacename);
1150 }
1151
1152 static void
1153 _outIndexStmt(StringInfo str, IndexStmt *node)
1154 {
1155         WRITE_NODE_TYPE("INDEXSTMT");
1156
1157         WRITE_STRING_FIELD(idxname);
1158         WRITE_NODE_FIELD(relation);
1159         WRITE_STRING_FIELD(accessMethod);
1160         WRITE_STRING_FIELD(tableSpace);
1161         WRITE_NODE_FIELD(indexParams);
1162         WRITE_NODE_FIELD(whereClause);
1163         WRITE_NODE_FIELD(rangetable);
1164         WRITE_BOOL_FIELD(unique);
1165         WRITE_BOOL_FIELD(primary);
1166         WRITE_BOOL_FIELD(isconstraint);
1167 }
1168
1169 static void
1170 _outNotifyStmt(StringInfo str, NotifyStmt *node)
1171 {
1172         WRITE_NODE_TYPE("NOTIFY");
1173
1174         WRITE_NODE_FIELD(relation);
1175 }
1176
1177 static void
1178 _outDeclareCursorStmt(StringInfo str, DeclareCursorStmt *node)
1179 {
1180         WRITE_NODE_TYPE("DECLARECURSOR");
1181
1182         WRITE_STRING_FIELD(portalname);
1183         WRITE_INT_FIELD(options);
1184         WRITE_NODE_FIELD(query);
1185 }
1186
1187 static void
1188 _outSelectStmt(StringInfo str, SelectStmt *node)
1189 {
1190         WRITE_NODE_TYPE("SELECT");
1191
1192         WRITE_NODE_FIELD(whereClause);
1193         WRITE_NODE_FIELD(distinctClause);
1194         WRITE_NODE_FIELD(into);
1195         WRITE_NODE_FIELD(intoColNames);
1196         WRITE_ENUM_FIELD(intoHasOids, ContainsOids);
1197         WRITE_NODE_FIELD(targetList);
1198         WRITE_NODE_FIELD(fromClause);
1199         WRITE_NODE_FIELD(whereClause);
1200         WRITE_NODE_FIELD(groupClause);
1201         WRITE_NODE_FIELD(havingClause);
1202         WRITE_NODE_FIELD(sortClause);
1203         WRITE_NODE_FIELD(limitOffset);
1204         WRITE_NODE_FIELD(limitCount);
1205         WRITE_NODE_FIELD(forUpdate);
1206         WRITE_ENUM_FIELD(op, SetOperation);
1207         WRITE_BOOL_FIELD(all);
1208         WRITE_NODE_FIELD(larg);
1209         WRITE_NODE_FIELD(rarg);
1210 }
1211
1212 static void
1213 _outFuncCall(StringInfo str, FuncCall *node)
1214 {
1215         WRITE_NODE_TYPE("FUNCCALL");
1216
1217         WRITE_NODE_FIELD(funcname);
1218         WRITE_NODE_FIELD(args);
1219         WRITE_BOOL_FIELD(agg_star);
1220         WRITE_BOOL_FIELD(agg_distinct);
1221 }
1222
1223 static void
1224 _outDefElem(StringInfo str, DefElem *node)
1225 {
1226         WRITE_NODE_TYPE("DEFELEM");
1227
1228         WRITE_STRING_FIELD(defname);
1229         WRITE_NODE_FIELD(arg);
1230 }
1231
1232 static void
1233 _outColumnDef(StringInfo str, ColumnDef *node)
1234 {
1235         WRITE_NODE_TYPE("COLUMNDEF");
1236
1237         WRITE_STRING_FIELD(colname);
1238         WRITE_NODE_FIELD(typename);
1239         WRITE_INT_FIELD(inhcount);
1240         WRITE_BOOL_FIELD(is_local);
1241         WRITE_BOOL_FIELD(is_not_null);
1242         WRITE_NODE_FIELD(raw_default);
1243         WRITE_STRING_FIELD(cooked_default);
1244         WRITE_NODE_FIELD(constraints);
1245         WRITE_NODE_FIELD(support);
1246 }
1247
1248 static void
1249 _outTypeName(StringInfo str, TypeName *node)
1250 {
1251         WRITE_NODE_TYPE("TYPENAME");
1252
1253         WRITE_NODE_FIELD(names);
1254         WRITE_OID_FIELD(typeid);
1255         WRITE_BOOL_FIELD(timezone);
1256         WRITE_BOOL_FIELD(setof);
1257         WRITE_BOOL_FIELD(pct_type);
1258         WRITE_INT_FIELD(typmod);
1259         WRITE_NODE_FIELD(arrayBounds);
1260 }
1261
1262 static void
1263 _outTypeCast(StringInfo str, TypeCast *node)
1264 {
1265         WRITE_NODE_TYPE("TYPECAST");
1266
1267         WRITE_NODE_FIELD(arg);
1268         WRITE_NODE_FIELD(typename);
1269 }
1270
1271 static void
1272 _outIndexElem(StringInfo str, IndexElem *node)
1273 {
1274         WRITE_NODE_TYPE("INDEXELEM");
1275
1276         WRITE_STRING_FIELD(name);
1277         WRITE_NODE_FIELD(expr);
1278         WRITE_NODE_FIELD(opclass);
1279 }
1280
1281 static void
1282 _outQuery(StringInfo str, Query *node)
1283 {
1284         WRITE_NODE_TYPE("QUERY");
1285
1286         WRITE_ENUM_FIELD(commandType, CmdType);
1287         WRITE_ENUM_FIELD(querySource, QuerySource);
1288         WRITE_BOOL_FIELD(canSetTag);
1289
1290         /*
1291          * Hack to work around missing outfuncs routines for a lot of the
1292          * utility-statement node types.  (The only one we actually *need* for
1293          * rules support is NotifyStmt.)  Someday we ought to support 'em all,
1294          * but for the meantime do this to avoid getting lots of warnings when
1295          * running with debug_print_parse on.
1296          */
1297         if (node->utilityStmt)
1298         {
1299                 switch (nodeTag(node->utilityStmt))
1300                 {
1301                         case T_CreateStmt:
1302                         case T_IndexStmt:
1303                         case T_NotifyStmt:
1304                         case T_DeclareCursorStmt:
1305                                 WRITE_NODE_FIELD(utilityStmt);
1306                                 break;
1307                         default:
1308                                 appendStringInfo(str, " :utilityStmt ?");
1309                                 break;
1310                 }
1311         }
1312         else
1313                 appendStringInfo(str, " :utilityStmt <>");
1314
1315         WRITE_INT_FIELD(resultRelation);
1316         WRITE_NODE_FIELD(into);
1317         WRITE_BOOL_FIELD(hasAggs);
1318         WRITE_BOOL_FIELD(hasSubLinks);
1319         WRITE_NODE_FIELD(rtable);
1320         WRITE_NODE_FIELD(jointree);
1321         WRITE_NODE_FIELD(rowMarks);
1322         WRITE_NODE_FIELD(targetList);
1323         WRITE_NODE_FIELD(groupClause);
1324         WRITE_NODE_FIELD(havingQual);
1325         WRITE_NODE_FIELD(distinctClause);
1326         WRITE_NODE_FIELD(sortClause);
1327         WRITE_NODE_FIELD(limitOffset);
1328         WRITE_NODE_FIELD(limitCount);
1329         WRITE_NODE_FIELD(setOperations);
1330         WRITE_NODE_FIELD(resultRelations);
1331
1332         /* planner-internal fields are not written out */
1333 }
1334
1335 static void
1336 _outSortClause(StringInfo str, SortClause *node)
1337 {
1338         WRITE_NODE_TYPE("SORTCLAUSE");
1339
1340         WRITE_UINT_FIELD(tleSortGroupRef);
1341         WRITE_OID_FIELD(sortop);
1342 }
1343
1344 static void
1345 _outGroupClause(StringInfo str, GroupClause *node)
1346 {
1347         WRITE_NODE_TYPE("GROUPCLAUSE");
1348
1349         WRITE_UINT_FIELD(tleSortGroupRef);
1350         WRITE_OID_FIELD(sortop);
1351 }
1352
1353 static void
1354 _outSetOperationStmt(StringInfo str, SetOperationStmt *node)
1355 {
1356         WRITE_NODE_TYPE("SETOPERATIONSTMT");
1357
1358         WRITE_ENUM_FIELD(op, SetOperation);
1359         WRITE_BOOL_FIELD(all);
1360         WRITE_NODE_FIELD(larg);
1361         WRITE_NODE_FIELD(rarg);
1362         WRITE_NODE_FIELD(colTypes);
1363 }
1364
1365 static void
1366 _outRangeTblEntry(StringInfo str, RangeTblEntry *node)
1367 {
1368         WRITE_NODE_TYPE("RTE");
1369
1370         /* put alias + eref first to make dump more legible */
1371         WRITE_NODE_FIELD(alias);
1372         WRITE_NODE_FIELD(eref);
1373         WRITE_ENUM_FIELD(rtekind, RTEKind);
1374
1375         switch (node->rtekind)
1376         {
1377                 case RTE_RELATION:
1378                 case RTE_SPECIAL:
1379                         WRITE_OID_FIELD(relid);
1380                         break;
1381                 case RTE_SUBQUERY:
1382                         WRITE_NODE_FIELD(subquery);
1383                         break;
1384                 case RTE_FUNCTION:
1385                         WRITE_NODE_FIELD(funcexpr);
1386                         WRITE_NODE_FIELD(coldeflist);
1387                         break;
1388                 case RTE_JOIN:
1389                         WRITE_ENUM_FIELD(jointype, JoinType);
1390                         WRITE_NODE_FIELD(joinaliasvars);
1391                         break;
1392                 default:
1393                         elog(ERROR, "unrecognized RTE kind: %d", (int) node->rtekind);
1394                         break;
1395         }
1396
1397         WRITE_BOOL_FIELD(inh);
1398         WRITE_BOOL_FIELD(inFromCl);
1399         WRITE_UINT_FIELD(requiredPerms);
1400         WRITE_UINT_FIELD(checkAsUser);
1401 }
1402
1403 static void
1404 _outAExpr(StringInfo str, A_Expr *node)
1405 {
1406         WRITE_NODE_TYPE("AEXPR");
1407
1408         switch (node->kind)
1409         {
1410                 case AEXPR_OP:
1411                         appendStringInfo(str, " ");
1412                         WRITE_NODE_FIELD(name);
1413                         break;
1414                 case AEXPR_AND:
1415                         appendStringInfo(str, " AND");
1416                         break;
1417                 case AEXPR_OR:
1418                         appendStringInfo(str, " OR");
1419                         break;
1420                 case AEXPR_NOT:
1421                         appendStringInfo(str, " NOT");
1422                         break;
1423                 case AEXPR_OP_ANY:
1424                         appendStringInfo(str, " ");
1425                         WRITE_NODE_FIELD(name);
1426                         appendStringInfo(str, " ANY ");
1427                         break;
1428                 case AEXPR_OP_ALL:
1429                         appendStringInfo(str, " ");
1430                         WRITE_NODE_FIELD(name);
1431                         appendStringInfo(str, " ALL ");
1432                         break;
1433                 case AEXPR_DISTINCT:
1434                         appendStringInfo(str, " DISTINCT ");
1435                         WRITE_NODE_FIELD(name);
1436                         break;
1437                 case AEXPR_NULLIF:
1438                         appendStringInfo(str, " NULLIF ");
1439                         WRITE_NODE_FIELD(name);
1440                         break;
1441                 case AEXPR_OF:
1442                         appendStringInfo(str, " OF ");
1443                         WRITE_NODE_FIELD(name);
1444                         break;
1445                 default:
1446                         appendStringInfo(str, " ??");
1447                         break;
1448         }
1449
1450         WRITE_NODE_FIELD(lexpr);
1451         WRITE_NODE_FIELD(rexpr);
1452 }
1453
1454 static void
1455 _outValue(StringInfo str, Value *value)
1456 {
1457         switch (value->type)
1458         {
1459                 case T_Integer:
1460                         appendStringInfo(str, "%ld", value->val.ival);
1461                         break;
1462                 case T_Float:
1463
1464                         /*
1465                          * We assume the value is a valid numeric literal and so does
1466                          * not need quoting.
1467                          */
1468                         appendStringInfoString(str, value->val.str);
1469                         break;
1470                 case T_String:
1471                         appendStringInfoChar(str, '"');
1472                         _outToken(str, value->val.str);
1473                         appendStringInfoChar(str, '"');
1474                         break;
1475                 case T_BitString:
1476                         /* internal representation already has leading 'b' */
1477                         appendStringInfoString(str, value->val.str);
1478                         break;
1479                 default:
1480                         elog(ERROR, "unrecognized node type: %d", (int) value->type);
1481                         break;
1482         }
1483 }
1484
1485 static void
1486 _outColumnRef(StringInfo str, ColumnRef *node)
1487 {
1488         WRITE_NODE_TYPE("COLUMNREF");
1489
1490         WRITE_NODE_FIELD(fields);
1491 }
1492
1493 static void
1494 _outParamRef(StringInfo str, ParamRef *node)
1495 {
1496         WRITE_NODE_TYPE("PARAMREF");
1497
1498         WRITE_INT_FIELD(number);
1499 }
1500
1501 static void
1502 _outAConst(StringInfo str, A_Const *node)
1503 {
1504         WRITE_NODE_TYPE("A_CONST");
1505
1506         _outValue(str, &(node->val));
1507         WRITE_NODE_FIELD(typename);
1508 }
1509
1510 static void
1511 _outA_Indices(StringInfo str, A_Indices *node)
1512 {
1513         WRITE_NODE_TYPE("A_INDICES");
1514
1515         WRITE_NODE_FIELD(lidx);
1516         WRITE_NODE_FIELD(uidx);
1517 }
1518
1519 static void
1520 _outA_Indirection(StringInfo str, A_Indirection *node)
1521 {
1522         WRITE_NODE_TYPE("A_INDIRECTION");
1523
1524         WRITE_NODE_FIELD(arg);
1525         WRITE_NODE_FIELD(indirection);
1526 }
1527
1528 static void
1529 _outResTarget(StringInfo str, ResTarget *node)
1530 {
1531         WRITE_NODE_TYPE("RESTARGET");
1532
1533         WRITE_STRING_FIELD(name);
1534         WRITE_NODE_FIELD(indirection);
1535         WRITE_NODE_FIELD(val);
1536 }
1537
1538 static void
1539 _outConstraint(StringInfo str, Constraint *node)
1540 {
1541         WRITE_NODE_TYPE("CONSTRAINT");
1542
1543         WRITE_STRING_FIELD(name);
1544
1545         appendStringInfo(str, " :contype ");
1546         switch (node->contype)
1547         {
1548                 case CONSTR_PRIMARY:
1549                         appendStringInfo(str, "PRIMARY_KEY");
1550                         WRITE_NODE_FIELD(keys);
1551                         WRITE_STRING_FIELD(indexspace);
1552                         break;
1553
1554                 case CONSTR_UNIQUE:
1555                         appendStringInfo(str, "UNIQUE");
1556                         WRITE_NODE_FIELD(keys);
1557                         WRITE_STRING_FIELD(indexspace);
1558                         break;
1559
1560                 case CONSTR_CHECK:
1561                         appendStringInfo(str, "CHECK");
1562                         WRITE_NODE_FIELD(raw_expr);
1563                         WRITE_STRING_FIELD(cooked_expr);
1564                         break;
1565
1566                 case CONSTR_DEFAULT:
1567                         appendStringInfo(str, "DEFAULT");
1568                         WRITE_NODE_FIELD(raw_expr);
1569                         WRITE_STRING_FIELD(cooked_expr);
1570                         break;
1571
1572                 case CONSTR_NOTNULL:
1573                         appendStringInfo(str, "NOT_NULL");
1574                         break;
1575
1576                 default:
1577                         appendStringInfo(str, "<unrecognized_constraint>");
1578                         break;
1579         }
1580 }
1581
1582 static void
1583 _outFkConstraint(StringInfo str, FkConstraint *node)
1584 {
1585         WRITE_NODE_TYPE("FKCONSTRAINT");
1586
1587         WRITE_STRING_FIELD(constr_name);
1588         WRITE_NODE_FIELD(pktable);
1589         WRITE_NODE_FIELD(fk_attrs);
1590         WRITE_NODE_FIELD(pk_attrs);
1591         WRITE_CHAR_FIELD(fk_matchtype);
1592         WRITE_CHAR_FIELD(fk_upd_action);
1593         WRITE_CHAR_FIELD(fk_del_action);
1594         WRITE_BOOL_FIELD(deferrable);
1595         WRITE_BOOL_FIELD(initdeferred);
1596         WRITE_BOOL_FIELD(skip_validation);
1597 }
1598
1599
1600 /*
1601  * _outNode -
1602  *        converts a Node into ascii string and append it to 'str'
1603  */
1604 static void
1605 _outNode(StringInfo str, void *obj)
1606 {
1607         if (obj == NULL)
1608                 appendStringInfo(str, "<>");
1609         else if (IsA(obj, List) ||IsA(obj, IntList) || IsA(obj, OidList))
1610                 _outList(str, obj);
1611         else if (IsA(obj, Integer) ||
1612                          IsA(obj, Float) ||
1613                          IsA(obj, String) ||
1614                          IsA(obj, BitString))
1615         {
1616                 /* nodeRead does not want to see { } around these! */
1617                 _outValue(str, obj);
1618         }
1619         else
1620         {
1621                 appendStringInfoChar(str, '{');
1622                 switch (nodeTag(obj))
1623                 {
1624                         case T_Plan:
1625                                 _outPlan(str, obj);
1626                                 break;
1627                         case T_Result:
1628                                 _outResult(str, obj);
1629                                 break;
1630                         case T_Append:
1631                                 _outAppend(str, obj);
1632                                 break;
1633                         case T_Scan:
1634                                 _outScan(str, obj);
1635                                 break;
1636                         case T_SeqScan:
1637                                 _outSeqScan(str, obj);
1638                                 break;
1639                         case T_IndexScan:
1640                                 _outIndexScan(str, obj);
1641                                 break;
1642                         case T_TidScan:
1643                                 _outTidScan(str, obj);
1644                                 break;
1645                         case T_SubqueryScan:
1646                                 _outSubqueryScan(str, obj);
1647                                 break;
1648                         case T_FunctionScan:
1649                                 _outFunctionScan(str, obj);
1650                                 break;
1651                         case T_Join:
1652                                 _outJoin(str, obj);
1653                                 break;
1654                         case T_NestLoop:
1655                                 _outNestLoop(str, obj);
1656                                 break;
1657                         case T_MergeJoin:
1658                                 _outMergeJoin(str, obj);
1659                                 break;
1660                         case T_HashJoin:
1661                                 _outHashJoin(str, obj);
1662                                 break;
1663                         case T_Agg:
1664                                 _outAgg(str, obj);
1665                                 break;
1666                         case T_Group:
1667                                 _outGroup(str, obj);
1668                                 break;
1669                         case T_Material:
1670                                 _outMaterial(str, obj);
1671                                 break;
1672                         case T_Sort:
1673                                 _outSort(str, obj);
1674                                 break;
1675                         case T_Unique:
1676                                 _outUnique(str, obj);
1677                                 break;
1678                         case T_SetOp:
1679                                 _outSetOp(str, obj);
1680                                 break;
1681                         case T_Limit:
1682                                 _outLimit(str, obj);
1683                                 break;
1684                         case T_Hash:
1685                                 _outHash(str, obj);
1686                                 break;
1687                         case T_Resdom:
1688                                 _outResdom(str, obj);
1689                                 break;
1690                         case T_Alias:
1691                                 _outAlias(str, obj);
1692                                 break;
1693                         case T_RangeVar:
1694                                 _outRangeVar(str, obj);
1695                                 break;
1696                         case T_Var:
1697                                 _outVar(str, obj);
1698                                 break;
1699                         case T_Const:
1700                                 _outConst(str, obj);
1701                                 break;
1702                         case T_Param:
1703                                 _outParam(str, obj);
1704                                 break;
1705                         case T_Aggref:
1706                                 _outAggref(str, obj);
1707                                 break;
1708                         case T_ArrayRef:
1709                                 _outArrayRef(str, obj);
1710                                 break;
1711                         case T_FuncExpr:
1712                                 _outFuncExpr(str, obj);
1713                                 break;
1714                         case T_OpExpr:
1715                                 _outOpExpr(str, obj);
1716                                 break;
1717                         case T_DistinctExpr:
1718                                 _outDistinctExpr(str, obj);
1719                                 break;
1720                         case T_ScalarArrayOpExpr:
1721                                 _outScalarArrayOpExpr(str, obj);
1722                                 break;
1723                         case T_BoolExpr:
1724                                 _outBoolExpr(str, obj);
1725                                 break;
1726                         case T_SubLink:
1727                                 _outSubLink(str, obj);
1728                                 break;
1729                         case T_SubPlan:
1730                                 _outSubPlan(str, obj);
1731                                 break;
1732                         case T_FieldSelect:
1733                                 _outFieldSelect(str, obj);
1734                                 break;
1735                         case T_FieldStore:
1736                                 _outFieldStore(str, obj);
1737                                 break;
1738                         case T_RelabelType:
1739                                 _outRelabelType(str, obj);
1740                                 break;
1741                         case T_ConvertRowtypeExpr:
1742                                 _outConvertRowtypeExpr(str, obj);
1743                                 break;
1744                         case T_CaseExpr:
1745                                 _outCaseExpr(str, obj);
1746                                 break;
1747                         case T_CaseWhen:
1748                                 _outCaseWhen(str, obj);
1749                                 break;
1750                         case T_CaseTestExpr:
1751                                 _outCaseTestExpr(str, obj);
1752                                 break;
1753                         case T_ArrayExpr:
1754                                 _outArrayExpr(str, obj);
1755                                 break;
1756                         case T_RowExpr:
1757                                 _outRowExpr(str, obj);
1758                                 break;
1759                         case T_CoalesceExpr:
1760                                 _outCoalesceExpr(str, obj);
1761                                 break;
1762                         case T_NullIfExpr:
1763                                 _outNullIfExpr(str, obj);
1764                                 break;
1765                         case T_NullTest:
1766                                 _outNullTest(str, obj);
1767                                 break;
1768                         case T_BooleanTest:
1769                                 _outBooleanTest(str, obj);
1770                                 break;
1771                         case T_CoerceToDomain:
1772                                 _outCoerceToDomain(str, obj);
1773                                 break;
1774                         case T_CoerceToDomainValue:
1775                                 _outCoerceToDomainValue(str, obj);
1776                                 break;
1777                         case T_SetToDefault:
1778                                 _outSetToDefault(str, obj);
1779                                 break;
1780                         case T_TargetEntry:
1781                                 _outTargetEntry(str, obj);
1782                                 break;
1783                         case T_RangeTblRef:
1784                                 _outRangeTblRef(str, obj);
1785                                 break;
1786                         case T_JoinExpr:
1787                                 _outJoinExpr(str, obj);
1788                                 break;
1789                         case T_FromExpr:
1790                                 _outFromExpr(str, obj);
1791                                 break;
1792
1793                         case T_Path:
1794                                 _outPath(str, obj);
1795                                 break;
1796                         case T_IndexPath:
1797                                 _outIndexPath(str, obj);
1798                                 break;
1799                         case T_TidPath:
1800                                 _outTidPath(str, obj);
1801                                 break;
1802                         case T_AppendPath:
1803                                 _outAppendPath(str, obj);
1804                                 break;
1805                         case T_ResultPath:
1806                                 _outResultPath(str, obj);
1807                                 break;
1808                         case T_MaterialPath:
1809                                 _outMaterialPath(str, obj);
1810                                 break;
1811                         case T_UniquePath:
1812                                 _outUniquePath(str, obj);
1813                                 break;
1814                         case T_NestPath:
1815                                 _outNestPath(str, obj);
1816                                 break;
1817                         case T_MergePath:
1818                                 _outMergePath(str, obj);
1819                                 break;
1820                         case T_HashPath:
1821                                 _outHashPath(str, obj);
1822                                 break;
1823                         case T_PathKeyItem:
1824                                 _outPathKeyItem(str, obj);
1825                                 break;
1826                         case T_RestrictInfo:
1827                                 _outRestrictInfo(str, obj);
1828                                 break;
1829                         case T_JoinInfo:
1830                                 _outJoinInfo(str, obj);
1831                                 break;
1832                         case T_InClauseInfo:
1833                                 _outInClauseInfo(str, obj);
1834                                 break;
1835
1836                         case T_CreateStmt:
1837                                 _outCreateStmt(str, obj);
1838                                 break;
1839                         case T_IndexStmt:
1840                                 _outIndexStmt(str, obj);
1841                                 break;
1842                         case T_NotifyStmt:
1843                                 _outNotifyStmt(str, obj);
1844                                 break;
1845                         case T_DeclareCursorStmt:
1846                                 _outDeclareCursorStmt(str, obj);
1847                                 break;
1848                         case T_SelectStmt:
1849                                 _outSelectStmt(str, obj);
1850                                 break;
1851                         case T_ColumnDef:
1852                                 _outColumnDef(str, obj);
1853                                 break;
1854                         case T_TypeName:
1855                                 _outTypeName(str, obj);
1856                                 break;
1857                         case T_TypeCast:
1858                                 _outTypeCast(str, obj);
1859                                 break;
1860                         case T_IndexElem:
1861                                 _outIndexElem(str, obj);
1862                                 break;
1863                         case T_Query:
1864                                 _outQuery(str, obj);
1865                                 break;
1866                         case T_SortClause:
1867                                 _outSortClause(str, obj);
1868                                 break;
1869                         case T_GroupClause:
1870                                 _outGroupClause(str, obj);
1871                                 break;
1872                         case T_SetOperationStmt:
1873                                 _outSetOperationStmt(str, obj);
1874                                 break;
1875                         case T_RangeTblEntry:
1876                                 _outRangeTblEntry(str, obj);
1877                                 break;
1878                         case T_A_Expr:
1879                                 _outAExpr(str, obj);
1880                                 break;
1881                         case T_ColumnRef:
1882                                 _outColumnRef(str, obj);
1883                                 break;
1884                         case T_ParamRef:
1885                                 _outParamRef(str, obj);
1886                                 break;
1887                         case T_A_Const:
1888                                 _outAConst(str, obj);
1889                                 break;
1890                         case T_A_Indices:
1891                                 _outA_Indices(str, obj);
1892                                 break;
1893                         case T_A_Indirection:
1894                                 _outA_Indirection(str, obj);
1895                                 break;
1896                         case T_ResTarget:
1897                                 _outResTarget(str, obj);
1898                                 break;
1899                         case T_Constraint:
1900                                 _outConstraint(str, obj);
1901                                 break;
1902                         case T_FkConstraint:
1903                                 _outFkConstraint(str, obj);
1904                                 break;
1905                         case T_FuncCall:
1906                                 _outFuncCall(str, obj);
1907                                 break;
1908                         case T_DefElem:
1909                                 _outDefElem(str, obj);
1910                                 break;
1911
1912                         default:
1913
1914                                 /*
1915                                  * This should be an ERROR, but it's too useful to be able
1916                                  * to dump structures that _outNode only understands part
1917                                  * of.
1918                                  */
1919                                 elog(WARNING, "could not dump unrecognized node type: %d",
1920                                          (int) nodeTag(obj));
1921                                 break;
1922                 }
1923                 appendStringInfoChar(str, '}');
1924         }
1925 }
1926
1927 /*
1928  * nodeToString -
1929  *         returns the ascii representation of the Node as a palloc'd string
1930  */
1931 char *
1932 nodeToString(void *obj)
1933 {
1934         StringInfoData str;
1935
1936         /* see stringinfo.h for an explanation of this maneuver */
1937         initStringInfo(&str);
1938         _outNode(&str, obj);
1939         return str.data;
1940 }