]> granicus.if.org Git - postgresql/blob - src/backend/nodes/outfuncs.c
Support expressions of the form 'scalar op ANY (array)' and
[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.211 2003/06/29 00:33:43 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 _outTargetEntry(StringInfo str, TargetEntry *node)
854 {
855         WRITE_NODE_TYPE("TARGETENTRY");
856
857         WRITE_NODE_FIELD(resdom);
858         WRITE_NODE_FIELD(expr);
859 }
860
861 static void
862 _outRangeTblRef(StringInfo str, RangeTblRef *node)
863 {
864         WRITE_NODE_TYPE("RANGETBLREF");
865
866         WRITE_INT_FIELD(rtindex);
867 }
868
869 static void
870 _outJoinExpr(StringInfo str, JoinExpr *node)
871 {
872         WRITE_NODE_TYPE("JOINEXPR");
873
874         WRITE_ENUM_FIELD(jointype, JoinType);
875         WRITE_BOOL_FIELD(isNatural);
876         WRITE_NODE_FIELD(larg);
877         WRITE_NODE_FIELD(rarg);
878         WRITE_NODE_FIELD(using);
879         WRITE_NODE_FIELD(quals);
880         WRITE_NODE_FIELD(alias);
881         WRITE_INT_FIELD(rtindex);
882 }
883
884 static void
885 _outFromExpr(StringInfo str, FromExpr *node)
886 {
887         WRITE_NODE_TYPE("FROMEXPR");
888
889         WRITE_NODE_FIELD(fromlist);
890         WRITE_NODE_FIELD(quals);
891 }
892
893 /*****************************************************************************
894  *
895  *      Stuff from relation.h.
896  *
897  *****************************************************************************/
898
899 /*
900  * print the basic stuff of all nodes that inherit from Path
901  *
902  * Note we do NOT print the parent, else we'd be in infinite recursion
903  */
904 static void
905 _outPathInfo(StringInfo str, Path *node)
906 {
907         WRITE_ENUM_FIELD(pathtype, NodeTag);
908         WRITE_FLOAT_FIELD(startup_cost, "%.2f");
909         WRITE_FLOAT_FIELD(total_cost, "%.2f");
910         WRITE_NODE_FIELD(pathkeys);
911 }
912
913 /*
914  * print the basic stuff of all nodes that inherit from JoinPath
915  */
916 static void
917 _outJoinPathInfo(StringInfo str, JoinPath *node)
918 {
919         _outPathInfo(str, (Path *) node);
920
921         WRITE_ENUM_FIELD(jointype, JoinType);
922         WRITE_NODE_FIELD(outerjoinpath);
923         WRITE_NODE_FIELD(innerjoinpath);
924         WRITE_NODE_FIELD(joinrestrictinfo);
925 }
926
927 static void
928 _outPath(StringInfo str, Path *node)
929 {
930         WRITE_NODE_TYPE("PATH");
931
932         _outPathInfo(str, (Path *) node);
933 }
934
935 /*
936  *      IndexPath is a subclass of Path.
937  */
938 static void
939 _outIndexPath(StringInfo str, IndexPath *node)
940 {
941         WRITE_NODE_TYPE("INDEXPATH");
942
943         _outPathInfo(str, (Path *) node);
944
945         WRITE_NODE_FIELD(indexinfo);
946         WRITE_NODE_FIELD(indexqual);
947         WRITE_NODE_FIELD(indexjoinclauses);
948         WRITE_ENUM_FIELD(indexscandir, ScanDirection);
949         WRITE_FLOAT_FIELD(rows, "%.2f");
950 }
951
952 static void
953 _outTidPath(StringInfo str, TidPath *node)
954 {
955         WRITE_NODE_TYPE("TIDPATH");
956
957         _outPathInfo(str, (Path *) node);
958
959         WRITE_NODE_FIELD(tideval);
960 }
961
962 static void
963 _outAppendPath(StringInfo str, AppendPath *node)
964 {
965         WRITE_NODE_TYPE("APPENDPATH");
966
967         _outPathInfo(str, (Path *) node);
968
969         WRITE_NODE_FIELD(subpaths);
970 }
971
972 static void
973 _outResultPath(StringInfo str, ResultPath *node)
974 {
975         WRITE_NODE_TYPE("RESULTPATH");
976
977         _outPathInfo(str, (Path *) node);
978
979         WRITE_NODE_FIELD(subpath);
980         WRITE_NODE_FIELD(constantqual);
981 }
982
983 static void
984 _outMaterialPath(StringInfo str, MaterialPath *node)
985 {
986         WRITE_NODE_TYPE("MATERIALPATH");
987
988         _outPathInfo(str, (Path *) node);
989
990         WRITE_NODE_FIELD(subpath);
991 }
992
993 static void
994 _outUniquePath(StringInfo str, UniquePath *node)
995 {
996         WRITE_NODE_TYPE("UNIQUEPATH");
997
998         _outPathInfo(str, (Path *) node);
999
1000         WRITE_NODE_FIELD(subpath);
1001         WRITE_BOOL_FIELD(use_hash);
1002         WRITE_FLOAT_FIELD(rows, "%.0f");
1003 }
1004
1005 static void
1006 _outNestPath(StringInfo str, NestPath *node)
1007 {
1008         WRITE_NODE_TYPE("NESTPATH");
1009
1010         _outJoinPathInfo(str, (JoinPath *) node);
1011 }
1012
1013 static void
1014 _outMergePath(StringInfo str, MergePath *node)
1015 {
1016         WRITE_NODE_TYPE("MERGEPATH");
1017
1018         _outJoinPathInfo(str, (JoinPath *) node);
1019
1020         WRITE_NODE_FIELD(path_mergeclauses);
1021         WRITE_NODE_FIELD(outersortkeys);
1022         WRITE_NODE_FIELD(innersortkeys);
1023 }
1024
1025 static void
1026 _outHashPath(StringInfo str, HashPath *node)
1027 {
1028         WRITE_NODE_TYPE("HASHPATH");
1029
1030         _outJoinPathInfo(str, (JoinPath *) node);
1031
1032         WRITE_NODE_FIELD(path_hashclauses);
1033 }
1034
1035 static void
1036 _outPathKeyItem(StringInfo str, PathKeyItem *node)
1037 {
1038         WRITE_NODE_TYPE("PATHKEYITEM");
1039
1040         WRITE_NODE_FIELD(key);
1041         WRITE_OID_FIELD(sortop);
1042 }
1043
1044 static void
1045 _outRestrictInfo(StringInfo str, RestrictInfo *node)
1046 {
1047         WRITE_NODE_TYPE("RESTRICTINFO");
1048
1049         /* NB: this isn't a complete set of fields */
1050         WRITE_NODE_FIELD(clause);
1051         WRITE_BOOL_FIELD(ispusheddown);
1052         WRITE_NODE_FIELD(subclauseindices);
1053         WRITE_BITMAPSET_FIELD(left_relids);
1054         WRITE_BITMAPSET_FIELD(right_relids);
1055         WRITE_OID_FIELD(mergejoinoperator);
1056         WRITE_OID_FIELD(left_sortop);
1057         WRITE_OID_FIELD(right_sortop);
1058         WRITE_NODE_FIELD(left_pathkey);
1059         WRITE_NODE_FIELD(right_pathkey);
1060         WRITE_OID_FIELD(hashjoinoperator);
1061 }
1062
1063 static void
1064 _outJoinInfo(StringInfo str, JoinInfo *node)
1065 {
1066         WRITE_NODE_TYPE("JOININFO");
1067
1068         WRITE_BITMAPSET_FIELD(unjoined_relids);
1069         WRITE_NODE_FIELD(jinfo_restrictinfo);
1070 }
1071
1072 static void
1073 _outInClauseInfo(StringInfo str, InClauseInfo *node)
1074 {
1075         WRITE_NODE_TYPE("INCLAUSEINFO");
1076
1077         WRITE_BITMAPSET_FIELD(lefthand);
1078         WRITE_BITMAPSET_FIELD(righthand);
1079         WRITE_NODE_FIELD(sub_targetlist);
1080 }
1081
1082 /*****************************************************************************
1083  *
1084  *      Stuff from parsenodes.h.
1085  *
1086  *****************************************************************************/
1087
1088 static void
1089 _outCreateStmt(StringInfo str, CreateStmt *node)
1090 {
1091         WRITE_NODE_TYPE("CREATE");
1092
1093         WRITE_NODE_FIELD(relation);
1094         WRITE_NODE_FIELD(tableElts);
1095         WRITE_NODE_FIELD(inhRelations);
1096         WRITE_NODE_FIELD(constraints);
1097         WRITE_BOOL_FIELD(hasoids);
1098         WRITE_ENUM_FIELD(oncommit, OnCommitAction);
1099 }
1100
1101 static void
1102 _outIndexStmt(StringInfo str, IndexStmt *node)
1103 {
1104         WRITE_NODE_TYPE("INDEX");
1105
1106         WRITE_STRING_FIELD(idxname);
1107         WRITE_NODE_FIELD(relation);
1108         WRITE_STRING_FIELD(accessMethod);
1109         WRITE_NODE_FIELD(indexParams);
1110         WRITE_NODE_FIELD(whereClause);
1111         WRITE_NODE_FIELD(rangetable);
1112         WRITE_BOOL_FIELD(unique);
1113         WRITE_BOOL_FIELD(primary);
1114         WRITE_BOOL_FIELD(isconstraint);
1115 }
1116
1117 static void
1118 _outNotifyStmt(StringInfo str, NotifyStmt *node)
1119 {
1120         WRITE_NODE_TYPE("NOTIFY");
1121
1122         WRITE_NODE_FIELD(relation);
1123 }
1124
1125 static void
1126 _outDeclareCursorStmt(StringInfo str, DeclareCursorStmt *node)
1127 {
1128         WRITE_NODE_TYPE("DECLARECURSOR");
1129
1130         WRITE_STRING_FIELD(portalname);
1131         WRITE_INT_FIELD(options);
1132         WRITE_NODE_FIELD(query);
1133 }
1134
1135 static void
1136 _outSelectStmt(StringInfo str, SelectStmt *node)
1137 {
1138         WRITE_NODE_TYPE("SELECT");
1139
1140         /* XXX this is pretty durn incomplete */
1141         WRITE_NODE_FIELD(whereClause);
1142 }
1143
1144 static void
1145 _outFuncCall(StringInfo str, FuncCall *node)
1146 {
1147         WRITE_NODE_TYPE("FUNCCALL");
1148
1149         WRITE_NODE_FIELD(funcname);
1150         WRITE_NODE_FIELD(args);
1151         WRITE_BOOL_FIELD(agg_star);
1152         WRITE_BOOL_FIELD(agg_distinct);
1153 }
1154
1155 static void
1156 _outColumnDef(StringInfo str, ColumnDef *node)
1157 {
1158         WRITE_NODE_TYPE("COLUMNDEF");
1159
1160         WRITE_STRING_FIELD(colname);
1161         WRITE_NODE_FIELD(typename);
1162         WRITE_INT_FIELD(inhcount);
1163         WRITE_BOOL_FIELD(is_local);
1164         WRITE_BOOL_FIELD(is_not_null);
1165         WRITE_NODE_FIELD(raw_default);
1166         WRITE_STRING_FIELD(cooked_default);
1167         WRITE_NODE_FIELD(constraints);
1168         WRITE_NODE_FIELD(support);
1169 }
1170
1171 static void
1172 _outTypeName(StringInfo str, TypeName *node)
1173 {
1174         WRITE_NODE_TYPE("TYPENAME");
1175
1176         WRITE_NODE_FIELD(names);
1177         WRITE_OID_FIELD(typeid);
1178         WRITE_BOOL_FIELD(timezone);
1179         WRITE_BOOL_FIELD(setof);
1180         WRITE_BOOL_FIELD(pct_type);
1181         WRITE_INT_FIELD(typmod);
1182         WRITE_NODE_FIELD(arrayBounds);
1183 }
1184
1185 static void
1186 _outTypeCast(StringInfo str, TypeCast *node)
1187 {
1188         WRITE_NODE_TYPE("TYPECAST");
1189
1190         WRITE_NODE_FIELD(arg);
1191         WRITE_NODE_FIELD(typename);
1192 }
1193
1194 static void
1195 _outIndexElem(StringInfo str, IndexElem *node)
1196 {
1197         WRITE_NODE_TYPE("INDEXELEM");
1198
1199         WRITE_STRING_FIELD(name);
1200         WRITE_NODE_FIELD(expr);
1201         WRITE_NODE_FIELD(opclass);
1202 }
1203
1204 static void
1205 _outQuery(StringInfo str, Query *node)
1206 {
1207         WRITE_NODE_TYPE("QUERY");
1208
1209         WRITE_ENUM_FIELD(commandType, CmdType);
1210         WRITE_ENUM_FIELD(querySource, QuerySource);
1211         WRITE_BOOL_FIELD(canSetTag);
1212
1213         /*
1214          * Hack to work around missing outfuncs routines for a lot of the
1215          * utility-statement node types.  (The only one we actually *need* for
1216          * rules support is NotifyStmt.)  Someday we ought to support 'em all,
1217          * but for the meantime do this to avoid getting lots of warnings when
1218          * running with debug_print_parse on.
1219          */
1220         if (node->utilityStmt)
1221         {
1222                 switch (nodeTag(node->utilityStmt))
1223                 {
1224                         case T_CreateStmt:
1225                         case T_IndexStmt:
1226                         case T_NotifyStmt:
1227                         case T_DeclareCursorStmt:
1228                                 WRITE_NODE_FIELD(utilityStmt);
1229                                 break;
1230                         default:
1231                                 appendStringInfo(str, " :utilityStmt ?");
1232                                 break;
1233                 }
1234         }
1235         else
1236                 appendStringInfo(str, " :utilityStmt <>");
1237
1238         WRITE_INT_FIELD(resultRelation);
1239         WRITE_NODE_FIELD(into);
1240         WRITE_BOOL_FIELD(hasAggs);
1241         WRITE_BOOL_FIELD(hasSubLinks);
1242         WRITE_NODE_FIELD(rtable);
1243         WRITE_NODE_FIELD(jointree);
1244         WRITE_INTLIST_FIELD(rowMarks);
1245         WRITE_NODE_FIELD(targetList);
1246         WRITE_NODE_FIELD(groupClause);
1247         WRITE_NODE_FIELD(havingQual);
1248         WRITE_NODE_FIELD(distinctClause);
1249         WRITE_NODE_FIELD(sortClause);
1250         WRITE_NODE_FIELD(limitOffset);
1251         WRITE_NODE_FIELD(limitCount);
1252         WRITE_NODE_FIELD(setOperations);
1253         WRITE_INTLIST_FIELD(resultRelations);
1254
1255         /* planner-internal fields are not written out */
1256 }
1257
1258 static void
1259 _outSortClause(StringInfo str, SortClause *node)
1260 {
1261         WRITE_NODE_TYPE("SORTCLAUSE");
1262
1263         WRITE_UINT_FIELD(tleSortGroupRef);
1264         WRITE_OID_FIELD(sortop);
1265 }
1266
1267 static void
1268 _outGroupClause(StringInfo str, GroupClause *node)
1269 {
1270         WRITE_NODE_TYPE("GROUPCLAUSE");
1271
1272         WRITE_UINT_FIELD(tleSortGroupRef);
1273         WRITE_OID_FIELD(sortop);
1274 }
1275
1276 static void
1277 _outSetOperationStmt(StringInfo str, SetOperationStmt *node)
1278 {
1279         WRITE_NODE_TYPE("SETOPERATIONSTMT");
1280
1281         WRITE_ENUM_FIELD(op, SetOperation);
1282         WRITE_BOOL_FIELD(all);
1283         WRITE_NODE_FIELD(larg);
1284         WRITE_NODE_FIELD(rarg);
1285         WRITE_OIDLIST_FIELD(colTypes);
1286 }
1287
1288 static void
1289 _outRangeTblEntry(StringInfo str, RangeTblEntry *node)
1290 {
1291         WRITE_NODE_TYPE("RTE");
1292
1293         /* put alias + eref first to make dump more legible */
1294         WRITE_NODE_FIELD(alias);
1295         WRITE_NODE_FIELD(eref);
1296         WRITE_ENUM_FIELD(rtekind, RTEKind);
1297
1298         switch (node->rtekind)
1299         {
1300                 case RTE_RELATION:
1301                 case RTE_SPECIAL:
1302                         WRITE_OID_FIELD(relid);
1303                         break;
1304                 case RTE_SUBQUERY:
1305                         WRITE_NODE_FIELD(subquery);
1306                         break;
1307                 case RTE_FUNCTION:
1308                         WRITE_NODE_FIELD(funcexpr);
1309                         WRITE_NODE_FIELD(coldeflist);
1310                         break;
1311                 case RTE_JOIN:
1312                         WRITE_ENUM_FIELD(jointype, JoinType);
1313                         WRITE_NODE_FIELD(joinaliasvars);
1314                         break;
1315                 default:
1316                         elog(ERROR, "bogus rte kind %d", (int) node->rtekind);
1317                         break;
1318         }
1319
1320         WRITE_BOOL_FIELD(inh);
1321         WRITE_BOOL_FIELD(inFromCl);
1322         WRITE_BOOL_FIELD(checkForRead);
1323         WRITE_BOOL_FIELD(checkForWrite);
1324         WRITE_OID_FIELD(checkAsUser);
1325 }
1326
1327 static void
1328 _outAExpr(StringInfo str, A_Expr *node)
1329 {
1330         WRITE_NODE_TYPE("AEXPR");
1331
1332         switch (node->kind)
1333         {
1334                 case AEXPR_OP:
1335                         appendStringInfo(str, " ");
1336                         WRITE_NODE_FIELD(name);
1337                         break;
1338                 case AEXPR_AND:
1339                         appendStringInfo(str, " AND");
1340                         break;
1341                 case AEXPR_OR:
1342                         appendStringInfo(str, " OR");
1343                         break;
1344                 case AEXPR_NOT:
1345                         appendStringInfo(str, " NOT");
1346                         break;
1347                 case AEXPR_OP_ANY:
1348                         appendStringInfo(str, " ");
1349                         WRITE_NODE_FIELD(name);
1350                         appendStringInfo(str, " ANY ");
1351                         break;
1352                 case AEXPR_OP_ALL:
1353                         appendStringInfo(str, " ");
1354                         WRITE_NODE_FIELD(name);
1355                         appendStringInfo(str, " ALL ");
1356                         break;
1357                 case AEXPR_DISTINCT:
1358                         appendStringInfo(str, " DISTINCT ");
1359                         WRITE_NODE_FIELD(name);
1360                         break;
1361                 case AEXPR_NULLIF:
1362                         appendStringInfo(str, " NULLIF ");
1363                         WRITE_NODE_FIELD(name);
1364                         break;
1365                 case AEXPR_OF:
1366                         appendStringInfo(str, " OF ");
1367                         WRITE_NODE_FIELD(name);
1368                         break;
1369                 default:
1370                         appendStringInfo(str, " ??");
1371                         break;
1372         }
1373
1374         WRITE_NODE_FIELD(lexpr);
1375         WRITE_NODE_FIELD(rexpr);
1376 }
1377
1378 static void
1379 _outValue(StringInfo str, Value *value)
1380 {
1381         switch (value->type)
1382         {
1383                 case T_Integer:
1384                         appendStringInfo(str, "%ld", value->val.ival);
1385                         break;
1386                 case T_Float:
1387
1388                         /*
1389                          * We assume the value is a valid numeric literal and so does
1390                          * not need quoting.
1391                          */
1392                         appendStringInfo(str, "%s", value->val.str);
1393                         break;
1394                 case T_String:
1395                         appendStringInfoChar(str, '"');
1396                         _outToken(str, value->val.str);
1397                         appendStringInfoChar(str, '"');
1398                         break;
1399                 case T_BitString:
1400                         /* internal representation already has leading 'b' */
1401                         appendStringInfo(str, "%s", value->val.str);
1402                         break;
1403                 default:
1404                         elog(WARNING, "_outValue: don't know how to print type %d",
1405                                  value->type);
1406                         break;
1407         }
1408 }
1409
1410 static void
1411 _outColumnRef(StringInfo str, ColumnRef *node)
1412 {
1413         WRITE_NODE_TYPE("COLUMNREF");
1414
1415         WRITE_NODE_FIELD(fields);
1416         WRITE_NODE_FIELD(indirection);
1417 }
1418
1419 static void
1420 _outParamRef(StringInfo str, ParamRef *node)
1421 {
1422         WRITE_NODE_TYPE("PARAMREF");
1423
1424         WRITE_INT_FIELD(number);
1425         WRITE_NODE_FIELD(fields);
1426         WRITE_NODE_FIELD(indirection);
1427 }
1428
1429 static void
1430 _outAConst(StringInfo str, A_Const *node)
1431 {
1432         WRITE_NODE_TYPE("CONST ");
1433
1434         _outValue(str, &(node->val));
1435         WRITE_NODE_FIELD(typename);
1436 }
1437
1438 static void
1439 _outExprFieldSelect(StringInfo str, ExprFieldSelect *node)
1440 {
1441         WRITE_NODE_TYPE("EXPRFIELDSELECT");
1442
1443         WRITE_NODE_FIELD(arg);
1444         WRITE_NODE_FIELD(fields);
1445         WRITE_NODE_FIELD(indirection);
1446 }
1447
1448 static void
1449 _outConstraint(StringInfo str, Constraint *node)
1450 {
1451         WRITE_NODE_TYPE("CONSTRAINT");
1452
1453         WRITE_STRING_FIELD(name);
1454
1455         appendStringInfo(str, " :contype ");
1456         switch (node->contype)
1457         {
1458                 case CONSTR_PRIMARY:
1459                         appendStringInfo(str, "PRIMARY_KEY");
1460                         WRITE_NODE_FIELD(keys);
1461                         break;
1462
1463                 case CONSTR_CHECK:
1464                         appendStringInfo(str, "CHECK");
1465                         WRITE_NODE_FIELD(raw_expr);
1466                         WRITE_STRING_FIELD(cooked_expr);
1467                         break;
1468
1469                 case CONSTR_DEFAULT:
1470                         appendStringInfo(str, "DEFAULT");
1471                         WRITE_NODE_FIELD(raw_expr);
1472                         WRITE_STRING_FIELD(cooked_expr);
1473                         break;
1474
1475                 case CONSTR_NOTNULL:
1476                         appendStringInfo(str, "NOT_NULL");
1477                         break;
1478
1479                 case CONSTR_UNIQUE:
1480                         appendStringInfo(str, "UNIQUE");
1481                         WRITE_NODE_FIELD(keys);
1482                         break;
1483
1484                 default:
1485                         appendStringInfo(str, "<unrecognized_constraint>");
1486                         break;
1487         }
1488 }
1489
1490 static void
1491 _outFkConstraint(StringInfo str, FkConstraint *node)
1492 {
1493         WRITE_NODE_TYPE("FKCONSTRAINT");
1494
1495         WRITE_STRING_FIELD(constr_name);
1496         WRITE_NODE_FIELD(pktable);
1497         WRITE_NODE_FIELD(fk_attrs);
1498         WRITE_NODE_FIELD(pk_attrs);
1499         WRITE_CHAR_FIELD(fk_matchtype);
1500         WRITE_CHAR_FIELD(fk_upd_action);
1501         WRITE_CHAR_FIELD(fk_del_action);
1502         WRITE_BOOL_FIELD(deferrable);
1503         WRITE_BOOL_FIELD(initdeferred);
1504         WRITE_BOOL_FIELD(skip_validation);
1505 }
1506
1507
1508 /*
1509  * _outNode -
1510  *        converts a Node into ascii string and append it to 'str'
1511  */
1512 static void
1513 _outNode(StringInfo str, void *obj)
1514 {
1515         if (obj == NULL)
1516         {
1517                 appendStringInfo(str, "<>");
1518                 return;
1519         }
1520
1521         if (IsA(obj, List))
1522         {
1523                 List       *l;
1524
1525                 appendStringInfoChar(str, '(');
1526                 foreach(l, (List *) obj)
1527                 {
1528                         _outNode(str, lfirst(l));
1529                         if (lnext(l))
1530                                 appendStringInfoChar(str, ' ');
1531                 }
1532                 appendStringInfoChar(str, ')');
1533         }
1534         else if (IsA(obj, Integer) ||
1535                          IsA(obj, Float) ||
1536                          IsA(obj, String) ||
1537                          IsA(obj, BitString))
1538         {
1539                 /* nodeRead does not want to see { } around these! */
1540                 _outValue(str, obj);
1541         }
1542         else
1543         {
1544                 appendStringInfoChar(str, '{');
1545                 switch (nodeTag(obj))
1546                 {
1547                         case T_Plan:
1548                                 _outPlan(str, obj);
1549                                 break;
1550                         case T_Result:
1551                                 _outResult(str, obj);
1552                                 break;
1553                         case T_Append:
1554                                 _outAppend(str, obj);
1555                                 break;
1556                         case T_Scan:
1557                                 _outScan(str, obj);
1558                                 break;
1559                         case T_SeqScan:
1560                                 _outSeqScan(str, obj);
1561                                 break;
1562                         case T_IndexScan:
1563                                 _outIndexScan(str, obj);
1564                                 break;
1565                         case T_TidScan:
1566                                 _outTidScan(str, obj);
1567                                 break;
1568                         case T_SubqueryScan:
1569                                 _outSubqueryScan(str, obj);
1570                                 break;
1571                         case T_FunctionScan:
1572                                 _outFunctionScan(str, obj);
1573                                 break;
1574                         case T_Join:
1575                                 _outJoin(str, obj);
1576                                 break;
1577                         case T_NestLoop:
1578                                 _outNestLoop(str, obj);
1579                                 break;
1580                         case T_MergeJoin:
1581                                 _outMergeJoin(str, obj);
1582                                 break;
1583                         case T_HashJoin:
1584                                 _outHashJoin(str, obj);
1585                                 break;
1586                         case T_Agg:
1587                                 _outAgg(str, obj);
1588                                 break;
1589                         case T_Group:
1590                                 _outGroup(str, obj);
1591                                 break;
1592                         case T_Material:
1593                                 _outMaterial(str, obj);
1594                                 break;
1595                         case T_Sort:
1596                                 _outSort(str, obj);
1597                                 break;
1598                         case T_Unique:
1599                                 _outUnique(str, obj);
1600                                 break;
1601                         case T_SetOp:
1602                                 _outSetOp(str, obj);
1603                                 break;
1604                         case T_Limit:
1605                                 _outLimit(str, obj);
1606                                 break;
1607                         case T_Hash:
1608                                 _outHash(str, obj);
1609                                 break;
1610                         case T_Resdom:
1611                                 _outResdom(str, obj);
1612                                 break;
1613                         case T_Alias:
1614                                 _outAlias(str, obj);
1615                                 break;
1616                         case T_RangeVar:
1617                                 _outRangeVar(str, obj);
1618                                 break;
1619                         case T_Var:
1620                                 _outVar(str, obj);
1621                                 break;
1622                         case T_Const:
1623                                 _outConst(str, obj);
1624                                 break;
1625                         case T_Param:
1626                                 _outParam(str, obj);
1627                                 break;
1628                         case T_Aggref:
1629                                 _outAggref(str, obj);
1630                                 break;
1631                         case T_ArrayRef:
1632                                 _outArrayRef(str, obj);
1633                                 break;
1634                         case T_FuncExpr:
1635                                 _outFuncExpr(str, obj);
1636                                 break;
1637                         case T_OpExpr:
1638                                 _outOpExpr(str, obj);
1639                                 break;
1640                         case T_DistinctExpr:
1641                                 _outDistinctExpr(str, obj);
1642                                 break;
1643                         case T_ScalarArrayOpExpr:
1644                                 _outScalarArrayOpExpr(str, obj);
1645                                 break;
1646                         case T_BoolExpr:
1647                                 _outBoolExpr(str, obj);
1648                                 break;
1649                         case T_SubLink:
1650                                 _outSubLink(str, obj);
1651                                 break;
1652                         case T_SubPlan:
1653                                 _outSubPlan(str, obj);
1654                                 break;
1655                         case T_FieldSelect:
1656                                 _outFieldSelect(str, obj);
1657                                 break;
1658                         case T_RelabelType:
1659                                 _outRelabelType(str, obj);
1660                                 break;
1661                         case T_CaseExpr:
1662                                 _outCaseExpr(str, obj);
1663                                 break;
1664                         case T_CaseWhen:
1665                                 _outCaseWhen(str, obj);
1666                                 break;
1667                         case T_ArrayExpr:
1668                                 _outArrayExpr(str, obj);
1669                                 break;
1670                         case T_CoalesceExpr:
1671                                 _outCoalesceExpr(str, obj);
1672                                 break;
1673                         case T_NullIfExpr:
1674                                 _outNullIfExpr(str, obj);
1675                                 break;
1676                         case T_NullTest:
1677                                 _outNullTest(str, obj);
1678                                 break;
1679                         case T_BooleanTest:
1680                                 _outBooleanTest(str, obj);
1681                                 break;
1682                         case T_CoerceToDomain:
1683                                 _outCoerceToDomain(str, obj);
1684                                 break;
1685                         case T_CoerceToDomainValue:
1686                                 _outCoerceToDomainValue(str, obj);
1687                                 break;
1688                         case T_TargetEntry:
1689                                 _outTargetEntry(str, obj);
1690                                 break;
1691                         case T_RangeTblRef:
1692                                 _outRangeTblRef(str, obj);
1693                                 break;
1694                         case T_JoinExpr:
1695                                 _outJoinExpr(str, obj);
1696                                 break;
1697                         case T_FromExpr:
1698                                 _outFromExpr(str, obj);
1699                                 break;
1700
1701                         case T_Path:
1702                                 _outPath(str, obj);
1703                                 break;
1704                         case T_IndexPath:
1705                                 _outIndexPath(str, obj);
1706                                 break;
1707                         case T_TidPath:
1708                                 _outTidPath(str, obj);
1709                                 break;
1710                         case T_AppendPath:
1711                                 _outAppendPath(str, obj);
1712                                 break;
1713                         case T_ResultPath:
1714                                 _outResultPath(str, obj);
1715                                 break;
1716                         case T_MaterialPath:
1717                                 _outMaterialPath(str, obj);
1718                                 break;
1719                         case T_UniquePath:
1720                                 _outUniquePath(str, obj);
1721                                 break;
1722                         case T_NestPath:
1723                                 _outNestPath(str, obj);
1724                                 break;
1725                         case T_MergePath:
1726                                 _outMergePath(str, obj);
1727                                 break;
1728                         case T_HashPath:
1729                                 _outHashPath(str, obj);
1730                                 break;
1731                         case T_PathKeyItem:
1732                                 _outPathKeyItem(str, obj);
1733                                 break;
1734                         case T_RestrictInfo:
1735                                 _outRestrictInfo(str, obj);
1736                                 break;
1737                         case T_JoinInfo:
1738                                 _outJoinInfo(str, obj);
1739                                 break;
1740                         case T_InClauseInfo:
1741                                 _outInClauseInfo(str, obj);
1742                                 break;
1743
1744                         case T_CreateStmt:
1745                                 _outCreateStmt(str, obj);
1746                                 break;
1747                         case T_IndexStmt:
1748                                 _outIndexStmt(str, obj);
1749                                 break;
1750                         case T_NotifyStmt:
1751                                 _outNotifyStmt(str, obj);
1752                                 break;
1753                         case T_DeclareCursorStmt:
1754                                 _outDeclareCursorStmt(str, obj);
1755                                 break;
1756                         case T_SelectStmt:
1757                                 _outSelectStmt(str, obj);
1758                                 break;
1759                         case T_ColumnDef:
1760                                 _outColumnDef(str, obj);
1761                                 break;
1762                         case T_TypeName:
1763                                 _outTypeName(str, obj);
1764                                 break;
1765                         case T_TypeCast:
1766                                 _outTypeCast(str, obj);
1767                                 break;
1768                         case T_IndexElem:
1769                                 _outIndexElem(str, obj);
1770                                 break;
1771                         case T_Query:
1772                                 _outQuery(str, obj);
1773                                 break;
1774                         case T_SortClause:
1775                                 _outSortClause(str, obj);
1776                                 break;
1777                         case T_GroupClause:
1778                                 _outGroupClause(str, obj);
1779                                 break;
1780                         case T_SetOperationStmt:
1781                                 _outSetOperationStmt(str, obj);
1782                                 break;
1783                         case T_RangeTblEntry:
1784                                 _outRangeTblEntry(str, obj);
1785                                 break;
1786                         case T_A_Expr:
1787                                 _outAExpr(str, obj);
1788                                 break;
1789                         case T_ColumnRef:
1790                                 _outColumnRef(str, obj);
1791                                 break;
1792                         case T_ParamRef:
1793                                 _outParamRef(str, obj);
1794                                 break;
1795                         case T_A_Const:
1796                                 _outAConst(str, obj);
1797                                 break;
1798                         case T_ExprFieldSelect:
1799                                 _outExprFieldSelect(str, obj);
1800                                 break;
1801                         case T_Constraint:
1802                                 _outConstraint(str, obj);
1803                                 break;
1804                         case T_FkConstraint:
1805                                 _outFkConstraint(str, obj);
1806                                 break;
1807                         case T_FuncCall:
1808                                 _outFuncCall(str, obj);
1809                                 break;
1810
1811                         default:
1812                                 elog(WARNING, "_outNode: don't know how to print type %d",
1813                                          nodeTag(obj));
1814                                 break;
1815                 }
1816                 appendStringInfoChar(str, '}');
1817         }
1818 }
1819
1820 /*
1821  * nodeToString -
1822  *         returns the ascii representation of the Node as a palloc'd string
1823  */
1824 char *
1825 nodeToString(void *obj)
1826 {
1827         StringInfoData str;
1828
1829         /* see stringinfo.h for an explanation of this maneuver */
1830         initStringInfo(&str);
1831         _outNode(&str, obj);
1832         return str.data;
1833 }