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