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