OSDN Git Service

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