]> granicus.if.org Git - postgresql/blob - src/backend/nodes/outfuncs.c
Reimplement parsing and storage of default expressions and constraint
[postgresql] / src / backend / nodes / outfuncs.c
1 /*
2  *
3  * outfuncs.c
4  *        routines to convert a node to ascii representation
5  *
6  * Copyright (c) 1994, Regents of the University of California
7  *
8  *      $Id: outfuncs.c,v 1.96 1999/10/03 23:55:29 tgl Exp $
9  *
10  * NOTES
11  *        Every (plan) node in POSTGRES has an associated "out" routine which
12  *        knows how to create its ascii representation. These functions are
13  *        useful for debugging as well as for storing plans in the system
14  *        catalogs (eg. indexes). This is also the plan string sent out in
15  *        Mariposa.
16  *
17  *        These functions update the in/out argument of type StringInfo
18  *        passed to them. This argument contains the string holding the ASCII
19  *        representation plus some other information (string length, etc.)
20  *
21  */
22
23 #include "postgres.h"
24 #include "access/heapam.h"
25 #include "access/htup.h"
26 #include "catalog/pg_type.h"
27 #include "fmgr.h"
28 #include "lib/stringinfo.h"
29 #include "nodes/execnodes.h"
30 #include "nodes/nodes.h"
31 #include "nodes/parsenodes.h"
32 #include "nodes/pg_list.h"
33 #include "nodes/plannodes.h"
34 #include "nodes/primnodes.h"
35 #include "nodes/relation.h"
36 #include "utils/datum.h"
37 #include "utils/lsyscache.h"
38 #include "utils/syscache.h"
39
40 #include "../parse.h"
41
42 static void _outDatum(StringInfo str, Datum value, Oid type);
43 static void _outNode(StringInfo str, void *obj);
44
45 /* Convert a null string pointer into "<>" */
46 #define stringStringInfo(s) (((s) == NULL) ? "<>" : (s))
47
48
49 /*
50  * _outIntList -
51  *         converts a List of integers
52  */
53 static void
54 _outIntList(StringInfo str, List *list)
55 {
56         List       *l;
57
58         appendStringInfo(str, "(");
59         foreach(l, list)
60                 appendStringInfo(str, " %d ", lfirsti(l));
61         appendStringInfo(str, ")");
62 }
63
64 static void
65 _outCreateStmt(StringInfo str, CreateStmt *node)
66 {
67         appendStringInfo(str, " CREATE :relname %s ",
68                                          stringStringInfo(node->relname));
69
70         appendStringInfo(str, " :istemp %s ",
71                                          node->istemp ? "true" : "false");
72
73         appendStringInfo(str, " :columns ");
74         _outNode(str, node->tableElts);
75
76         appendStringInfo(str, " :inhRelnames ");
77         _outNode(str, node->inhRelnames);
78
79         appendStringInfo(str, " :constraints ");
80         _outNode(str, node->constraints);
81 }
82
83 static void
84 _outIndexStmt(StringInfo str, IndexStmt *node)
85 {
86         appendStringInfo(str,
87                  " INDEX :idxname %s :relname %s :accessMethod %s :indexParams ",
88                                          stringStringInfo(node->idxname),
89                                          stringStringInfo(node->relname),
90                                          stringStringInfo(node->accessMethod));
91         _outNode(str, node->indexParams);
92
93         appendStringInfo(str, " :withClause ");
94         _outNode(str, node->withClause);
95
96         appendStringInfo(str, " :whereClause ");
97         _outNode(str, node->whereClause);
98
99         appendStringInfo(str, " :rangetable ");
100         _outNode(str, node->rangetable);
101
102         appendStringInfo(str, " :lossy %s :unique %s ",
103                                          node->lossy ? "true" : "false",
104                                          node->unique ? "true" : "false");
105 }
106
107 static void
108 _outSelectStmt(StringInfo str, SelectStmt *node)
109 {
110         appendStringInfo(str, "SELECT :where ");
111         _outNode(str, node->whereClause);
112 }
113
114 static void
115 _outFuncCall(StringInfo str, FuncCall *node)
116 {
117         appendStringInfo(str, "FUNCTION %s :args ", stringStringInfo(node->funcname));
118         _outNode(str, node->args);
119 }
120
121 static void
122 _outColumnDef(StringInfo str, ColumnDef *node)
123 {
124         appendStringInfo(str, " COLUMNDEF :colname %s :typename ",
125                                          stringStringInfo(node->colname));
126         _outNode(str, node->typename);
127         appendStringInfo(str, " :is_not_null %s :is_sequence %s :raw_default ",
128                                          node->is_not_null ? "true" : "false",
129                                          node->is_sequence ? "true" : "false");
130         _outNode(str, node->raw_default);
131         appendStringInfo(str, " :cooked_default %s :constraints ",
132                                          stringStringInfo(node->cooked_default));
133         _outNode(str, node->constraints);
134 }
135
136 static void
137 _outTypeName(StringInfo str, TypeName *node)
138 {
139         appendStringInfo(str,
140          " TYPENAME :name %s :timezone %s :setof %s typmod %d :arrayBounds ",
141                                          stringStringInfo(node->name),
142                                          node->timezone ? "true" : "false",
143                                          node->setof ? "true" : "false",
144                                          node->typmod);
145
146         appendStringInfo(str, " :arrayBounds ");
147         _outNode(str, node->arrayBounds);
148 }
149
150 static void
151 _outIndexElem(StringInfo str, IndexElem *node)
152 {
153         appendStringInfo(str, " INDEXELEM :name %s :args ",
154                                          stringStringInfo(node->name));
155         _outNode(str, node->args);
156
157         appendStringInfo(str, " :class %s :typename ", stringStringInfo(node->class));
158         _outNode(str, node->typename);
159 }
160
161 static void
162 _outQuery(StringInfo str, Query *node)
163 {
164
165         appendStringInfo(str, " QUERY :command %d ", node->commandType);
166
167         if (node->utilityStmt)
168         {
169                 switch (nodeTag(node->utilityStmt))
170                 {
171                         case T_CreateStmt:
172                                 appendStringInfo(str, " :create %s ",
173                                                                  stringStringInfo(((CreateStmt *) (node->utilityStmt))->relname));
174                                 _outNode(str, node->utilityStmt);
175                                 break;
176
177                         case T_IndexStmt:
178                                 appendStringInfo(str, " :index %s on %s ",
179                                                                  stringStringInfo(((IndexStmt *) (node->utilityStmt))->idxname),
180                                                                  stringStringInfo(((IndexStmt *) (node->utilityStmt))->relname));
181                                 _outNode(str, node->utilityStmt);
182                                 break;
183
184                         case T_NotifyStmt:
185                                 appendStringInfo(str, " :utility %s ",
186                                                                  stringStringInfo(((NotifyStmt *) (node->utilityStmt))->relname));
187                                 break;
188
189                         default:
190                                 appendStringInfo(str, " :utility ? ");
191                 }
192         }
193         else
194                 appendStringInfo(str, " :utility <>");
195
196         appendStringInfo(str,
197                                          " :resultRelation %u :into %s :isPortal %s :isBinary %s :isTemp %s :unionall %s ",
198                                          node->resultRelation,
199                                          stringStringInfo(node->into),
200                                          node->isPortal ? "true" : "false",
201                                          node->isBinary ? "true" : "false",
202                                          node->isTemp ? "true" : "false",
203                                          node->unionall ? "true" : "false");
204
205         appendStringInfo(str, " :unique %s :sortClause ",
206                                          stringStringInfo(node->uniqueFlag));
207         _outNode(str, node->sortClause);
208
209         appendStringInfo(str, " :rtable ");
210         _outNode(str, node->rtable);
211
212         appendStringInfo(str, " :targetlist ");
213         _outNode(str, node->targetList);
214
215         appendStringInfo(str, " :qual ");
216         _outNode(str, node->qual);
217
218         appendStringInfo(str, " :groupClause ");
219         _outNode(str, node->groupClause);
220
221         appendStringInfo(str, " :havingQual ");
222         _outNode(str, node->havingQual);
223
224         appendStringInfo(str, " :hasAggs %s :hasSubLinks %s :unionClause ",
225                                          node->hasAggs ? "true" : "false",
226                                          node->hasSubLinks ? "true" : "false");
227         _outNode(str, node->unionClause);
228
229         appendStringInfo(str, " :intersectClause ");
230         _outNode(str, node->intersectClause);
231
232         appendStringInfo(str, " :limitOffset ");
233         _outNode(str, node->limitOffset);
234
235         appendStringInfo(str, " :limitCount ");
236         _outNode(str, node->limitCount);
237
238         appendStringInfo(str, " :rowMark ");
239         _outNode(str, node->rowMark);
240
241 }
242
243 static void
244 _outSortClause(StringInfo str, SortClause *node)
245 {
246         appendStringInfo(str, " SORTCLAUSE :tleSortGroupRef %d :sortop %u ",
247                                          node->tleSortGroupRef, node->sortop);
248 }
249
250 static void
251 _outGroupClause(StringInfo str, GroupClause *node)
252 {
253         appendStringInfo(str, " GROUPCLAUSE :tleSortGroupRef %d :sortop %u ",
254                                          node->tleSortGroupRef, node->sortop);
255 }
256
257 /*
258  * print the basic stuff of all nodes that inherit from Plan
259  */
260 static void
261 _outPlanInfo(StringInfo str, Plan *node)
262 {
263         appendStringInfo(str,
264                                   ":cost %g :size %d :width %d :state %s :qptargetlist ",
265                                          node->cost,
266                                          node->plan_size,
267                                          node->plan_width,
268                                          node->state ? "not-NULL" : "<>");
269         _outNode(str, node->targetlist);
270
271         appendStringInfo(str, " :qpqual ");
272         _outNode(str, node->qual);
273
274         appendStringInfo(str, " :lefttree ");
275         _outNode(str, node->lefttree);
276
277         appendStringInfo(str, " :righttree ");
278         _outNode(str, node->righttree);
279
280         appendStringInfo(str, " :extprm ");
281         _outIntList(str, node->extParam);
282
283         appendStringInfo(str, " :locprm ");
284         _outIntList(str, node->locParam);
285
286         appendStringInfo(str, " :initplan ");
287         _outNode(str, node->initPlan);
288
289         appendStringInfo(str, " :nprm %d ", node->nParamExec);
290 }
291
292 /*
293  *      Stuff from plannodes.h
294  */
295 static void
296 _outPlan(StringInfo str, Plan *node)
297 {
298         appendStringInfo(str, " PLAN ");
299         _outPlanInfo(str, (Plan *) node);
300 }
301
302 static void
303 _outResult(StringInfo str, Result *node)
304 {
305         appendStringInfo(str, " RESULT ");
306         _outPlanInfo(str, (Plan *) node);
307
308         appendStringInfo(str, " :resconstantqual ");
309         _outNode(str, node->resconstantqual);
310
311 }
312
313 /*
314  *      Append is a subclass of Plan.
315  */
316 static void
317 _outAppend(StringInfo str, Append *node)
318 {
319         appendStringInfo(str, " APPEND ");
320         _outPlanInfo(str, (Plan *) node);
321
322         appendStringInfo(str, " :appendplans ");
323         _outNode(str, node->appendplans);
324
325         appendStringInfo(str, " :unionrtables ");
326         _outNode(str, node->unionrtables);
327
328         appendStringInfo(str,
329                                          " :inheritrelid %u :inheritrtable ",
330                                          node->inheritrelid);
331         _outNode(str, node->inheritrtable);
332
333 }
334
335 /*
336  *      Join is a subclass of Plan
337  */
338 static void
339 _outJoin(StringInfo str, Join *node)
340 {
341         appendStringInfo(str, " JOIN ");
342         _outPlanInfo(str, (Plan *) node);
343
344 }
345
346 /*
347  *      NestLoop is a subclass of Join
348  */
349 static void
350 _outNestLoop(StringInfo str, NestLoop *node)
351 {
352         appendStringInfo(str, " NESTLOOP ");
353         _outPlanInfo(str, (Plan *) node);
354 }
355
356 /*
357  *      MergeJoin is a subclass of Join
358  */
359 static void
360 _outMergeJoin(StringInfo str, MergeJoin *node)
361 {
362         appendStringInfo(str, " MERGEJOIN ");
363         _outPlanInfo(str, (Plan *) node);
364
365         appendStringInfo(str, " :mergeclauses ");
366         _outNode(str, node->mergeclauses);
367 }
368
369 /*
370  *      HashJoin is a subclass of Join.
371  */
372 static void
373 _outHashJoin(StringInfo str, HashJoin *node)
374 {
375         appendStringInfo(str, " HASHJOIN ");
376         _outPlanInfo(str, (Plan *) node);
377
378         appendStringInfo(str, " :hashclauses ");
379         _outNode(str, node->hashclauses);
380
381         appendStringInfo(str,
382                                          " :hashjoinop %u ",
383                                          node->hashjoinop);
384
385         appendStringInfo(str,
386                                          " :hashdone %d ",
387                                          node->hashdone);
388 }
389
390 static void
391 _outSubPlan(StringInfo str, SubPlan *node)
392 {
393         appendStringInfo(str, " SUBPLAN :plan ");
394         _outNode(str, node->plan);
395
396         appendStringInfo(str, " :planid %u :rtable ", node->plan_id);
397         _outNode(str, node->rtable);
398
399         appendStringInfo(str, " :setprm ");
400         _outIntList(str, node->setParam);
401
402         appendStringInfo(str, " :parprm ");
403         _outIntList(str, node->parParam);
404
405         appendStringInfo(str, " :slink ");
406         _outNode(str, node->sublink);
407 }
408
409 /*
410  *      Scan is a subclass of Node
411  */
412 static void
413 _outScan(StringInfo str, Scan *node)
414 {
415         appendStringInfo(str, " SCAN ");
416         _outPlanInfo(str, (Plan *) node);
417
418         appendStringInfo(str, " :scanrelid %u ", node->scanrelid);
419 }
420
421 /*
422  *      SeqScan is a subclass of Scan
423  */
424 static void
425 _outSeqScan(StringInfo str, SeqScan *node)
426 {
427         appendStringInfo(str, " SEQSCAN ");
428         _outPlanInfo(str, (Plan *) node);
429
430         appendStringInfo(str, " :scanrelid %u ", node->scanrelid);
431 }
432
433 /*
434  *      IndexScan is a subclass of Scan
435  */
436 static void
437 _outIndexScan(StringInfo str, IndexScan *node)
438 {
439         appendStringInfo(str, " INDEXSCAN ");
440         _outPlanInfo(str, (Plan *) node);
441
442         appendStringInfo(str, " :scanrelid %u :indxid ", node->scan.scanrelid);
443         _outIntList(str, node->indxid);
444
445         appendStringInfo(str, " :indxqual ");
446         _outNode(str, node->indxqual);
447
448         appendStringInfo(str, " :indxqualorig ");
449         _outNode(str, node->indxqualorig);
450
451         appendStringInfo(str, " :indxorderdir %d ", node->indxorderdir);
452 }
453
454 /*
455  *      Noname is a subclass of Plan
456  */
457 static void
458 _outNoname(StringInfo str, Noname *node)
459 {
460         appendStringInfo(str, " NONAME ");
461         _outPlanInfo(str, (Plan *) node);
462
463         appendStringInfo(str, " :nonameid %u :keycount %d ",
464                                          node->nonameid,
465                                          node->keycount);
466 }
467
468 /*
469  *      Sort is a subclass of Noname
470  */
471 static void
472 _outSort(StringInfo str, Sort *node)
473 {
474         appendStringInfo(str, " SORT ");
475         _outPlanInfo(str, (Plan *) node);
476
477         appendStringInfo(str, " :nonameid %u :keycount %d ",
478                                          node->nonameid,
479                                          node->keycount);
480 }
481
482 static void
483 _outAgg(StringInfo str, Agg *node)
484 {
485
486         appendStringInfo(str, " AGG ");
487         _outPlanInfo(str, (Plan *) node);
488 }
489
490 static void
491 _outGroup(StringInfo str, Group *node)
492 {
493         appendStringInfo(str, " GRP ");
494         _outPlanInfo(str, (Plan *) node);
495
496         /* the actual Group fields */
497         appendStringInfo(str, " :numCols %d :tuplePerGroup %s ",
498                                          node->numCols,
499                                          node->tuplePerGroup ? "true" : "false");
500 }
501
502 /*
503  *      For some reason, unique is a subclass of Noname.
504  */
505 static void
506 _outUnique(StringInfo str, Unique *node)
507 {
508         appendStringInfo(str, " UNIQUE ");
509         _outPlanInfo(str, (Plan *) node);
510
511         appendStringInfo(str, " :nonameid %u :keycount %d ",
512                                          node->nonameid,
513                                          node->keycount);
514 }
515
516
517 /*
518  *      Hash is a subclass of Noname
519  */
520 static void
521 _outHash(StringInfo str, Hash *node)
522 {
523         appendStringInfo(str, " HASH ");
524         _outPlanInfo(str, (Plan *) node);
525
526         appendStringInfo(str, " :hashkey ");
527         _outNode(str, node->hashkey);
528 }
529
530 /*****************************************************************************
531  *
532  *      Stuff from primnodes.h.
533  *
534  *****************************************************************************/
535
536 /*
537  *      Resdom is a subclass of Node
538  */
539 static void
540 _outResdom(StringInfo str, Resdom *node)
541 {
542         appendStringInfo(str, " RESDOM :resno %d :restype %u :restypmod %d",
543                                          node->resno,
544                                          node->restype,
545                                          node->restypmod);
546
547         appendStringInfo(str, " :resname \"%s\" :reskey %d :reskeyop %u",
548                                          stringStringInfo(node->resname),
549                                          node->reskey,
550                                          node->reskeyop);
551
552         appendStringInfo(str, " :ressortgroupref %d :resjunk %s ",
553                                          node->ressortgroupref,
554                                          node->resjunk ? "true" : "false");
555 }
556
557 static void
558 _outFjoin(StringInfo str, Fjoin *node)
559 {
560         int                     i;
561
562         appendStringInfo(str, " FJOIN :initialized %s :nNodes %d ",
563                                          node->fj_initialized ? "true" : "false",
564                                          node->fj_nNodes);
565
566         appendStringInfo(str, " :innerNode ");
567         _outNode(str, node->fj_innerNode);
568
569         appendStringInfo(str, " :results @ 0x%x :alwaysdone",
570                                          (int) node->fj_results);
571
572         for (i = 0; i < node->fj_nNodes; i++)
573                 appendStringInfo(str, (node->fj_alwaysDone[i]) ? "true" : "false");
574 }
575
576 /*
577  *      Expr is a subclass of Node
578  */
579 static void
580 _outExpr(StringInfo str, Expr *node)
581 {
582         char       *opstr = NULL;
583
584         appendStringInfo(str, " EXPR :typeOid %u ",
585                                          node->typeOid);
586
587         switch (node->opType)
588         {
589                 case OP_EXPR:
590                         opstr = "op";
591                         break;
592                 case FUNC_EXPR:
593                         opstr = "func";
594                         break;
595                 case OR_EXPR:
596                         opstr = "or";
597                         break;
598                 case AND_EXPR:
599                         opstr = "and";
600                         break;
601                 case NOT_EXPR:
602                         opstr = "not";
603                         break;
604                 case SUBPLAN_EXPR:
605                         opstr = "subp";
606                         break;
607         }
608         appendStringInfo(str, " :opType %s :oper ", stringStringInfo(opstr));
609         _outNode(str, node->oper);
610
611         appendStringInfo(str, " :args ");
612         _outNode(str, node->args);
613 }
614
615 /*
616  *      Var is a subclass of Expr
617  */
618 static void
619 _outVar(StringInfo str, Var *node)
620 {
621         appendStringInfo(str,
622                                 " VAR :varno %d :varattno %d :vartype %u :vartypmod %d ",
623                                          node->varno,
624                                          node->varattno,
625                                          node->vartype,
626                                          node->vartypmod);
627
628         appendStringInfo(str, " :varlevelsup %u :varnoold %d :varoattno %d",
629                                          node->varlevelsup,
630                                          node->varnoold,
631                                          node->varoattno);
632 }
633
634 /*
635  *      Const is a subclass of Expr
636  */
637 static void
638 _outConst(StringInfo str, Const *node)
639 {
640         appendStringInfo(str,
641                 " CONST :consttype %u :constlen %d :constisnull %s :constvalue ",
642                                          node->consttype,
643                                          node->constlen,
644                                          node->constisnull ? "true" : "false");
645
646         if (node->constisnull)
647                 appendStringInfo(str, "<>");
648         else
649                 _outDatum(str, node->constvalue, node->consttype);
650
651         appendStringInfo(str, " :constbyval %s ",
652                                          node->constbyval ? "true" : "false");
653 }
654
655 /*
656  *      Aggref
657  */
658 static void
659 _outAggref(StringInfo str, Aggref *node)
660 {
661         appendStringInfo(str,
662                                  " AGGREG :aggname %s :basetype %u :aggtype %u :target ",
663                                          stringStringInfo(node->aggname),
664                                          node->basetype,
665                                          node->aggtype);
666         _outNode(str, node->target);
667
668         appendStringInfo(str, " :usenulls %s ",
669                                          node->usenulls ? "true" : "false");
670 }
671
672 /*
673  *      SubLink
674  */
675 static void
676 _outSubLink(StringInfo str, SubLink *node)
677 {
678         appendStringInfo(str,
679                                          " SUBLINK :subLinkType %d :useor %s :lefthand ",
680                                          node->subLinkType,
681                                          node->useor ? "true" : "false");
682         _outNode(str, node->lefthand);
683
684         appendStringInfo(str, " :oper ");
685         _outNode(str, node->oper);
686
687         appendStringInfo(str, " :subselect ");
688         _outNode(str, node->subselect);
689 }
690
691 /*
692  *      Array is a subclass of Expr
693  */
694 static void
695 _outArray(StringInfo str, Array *node)
696 {
697         int                     i;
698
699         appendStringInfo(str,
700           " ARRAY :arrayelemtype %u :arrayelemlength %d :arrayelembyval %c ",
701                                          node->arrayelemtype,
702                                          node->arrayelemlength,
703                                          node->arrayelembyval ? 't' : 'f');
704
705         appendStringInfo(str, " :arrayndim %d :arraylow ", node->arrayndim);
706         for (i = 0; i < node->arrayndim; i++)
707                 appendStringInfo(str, " %d ", node->arraylow.indx[i]);
708         appendStringInfo(str, " :arrayhigh ");
709         for (i = 0; i < node->arrayndim; i++)
710                 appendStringInfo(str, " %d ", node->arrayhigh.indx[i]);
711         appendStringInfo(str, " :arraylen %d ", node->arraylen);
712 }
713
714 /*
715  *      ArrayRef is a subclass of Expr
716  */
717 static void
718 _outArrayRef(StringInfo str, ArrayRef *node)
719 {
720         appendStringInfo(str,
721                 " ARRAYREF :refelemtype %u :refattrlength %d :refelemlength %d ",
722                                          node->refelemtype,
723                                          node->refattrlength,
724                                          node->refelemlength);
725
726         appendStringInfo(str, " :refelembyval %c :refupperindex ",
727                                          node->refelembyval ? 't' : 'f');
728         _outNode(str, node->refupperindexpr);
729
730         appendStringInfo(str, " :reflowerindex ");
731         _outNode(str, node->reflowerindexpr);
732
733         appendStringInfo(str, " :refexpr ");
734         _outNode(str, node->refexpr);
735
736         appendStringInfo(str, " :refassgnexpr ");
737         _outNode(str, node->refassgnexpr);
738 }
739
740 /*
741  *      Func is a subclass of Expr
742  */
743 static void
744 _outFunc(StringInfo str, Func *node)
745 {
746         appendStringInfo(str,
747                    " FUNC :funcid %u :functype %u :funcisindex %s :funcsize %d ",
748                                          node->funcid,
749                                          node->functype,
750                                          node->funcisindex ? "true" : "false",
751                                          node->funcsize);
752
753         appendStringInfo(str, " :func_fcache @ 0x%x :func_tlist ",
754                                          (int) node->func_fcache);
755         _outNode(str, node->func_tlist);
756
757         appendStringInfo(str, " :func_planlist ");
758         _outNode(str, node->func_planlist);
759 }
760
761 /*
762  *      Oper is a subclass of Expr
763  */
764 static void
765 _outOper(StringInfo str, Oper *node)
766 {
767         appendStringInfo(str,
768                                          " OPER :opno %u :opid %u :opresulttype %u ",
769                                          node->opno,
770                                          node->opid,
771                                          node->opresulttype);
772 }
773
774 /*
775  *      Param is a subclass of Expr
776  */
777 static void
778 _outParam(StringInfo str, Param *node)
779 {
780         appendStringInfo(str,
781                  " PARAM :paramkind %d :paramid %d :paramname %s :paramtype %u ",
782                                          node->paramkind,
783                                          node->paramid,
784                                          stringStringInfo(node->paramname),
785                                          node->paramtype);
786
787         appendStringInfo(str, " :param_tlist ");
788         _outNode(str, node->param_tlist);
789 }
790
791 /*
792  *      Stuff from execnodes.h
793  */
794
795 /*
796  *      EState is a subclass of Node.
797  */
798 static void
799 _outEState(StringInfo str, EState *node)
800 {
801         appendStringInfo(str,
802                                          " ESTATE :direction %d :range_table ",
803                                          node->es_direction);
804         _outNode(str, node->es_range_table);
805
806         appendStringInfo(str, " :result_relation_info @ 0x%x ",
807                                          (int) (node->es_result_relation_info));
808 }
809
810 /*
811  *      Stuff from relation.h
812  */
813 static void
814 _outRelOptInfo(StringInfo str, RelOptInfo *node)
815 {
816         appendStringInfo(str, " RELOPTINFO :relids ");
817         _outIntList(str, node->relids);
818
819         appendStringInfo(str,
820          " :indexed %s :pages %u :tuples %u :size %u :width %u :targetlist ",
821                                          node->indexed ? "true" : "false",
822                                          node->pages,
823                                          node->tuples,
824                                          node->size,
825                                          node->width);
826         _outNode(str, node->targetlist);
827
828         appendStringInfo(str, " :pathlist ");
829         _outNode(str, node->pathlist);
830
831         /*
832          * Not sure if these are nodes or not.  They're declared as struct
833          * Path *.      Since i don't know, i'll just print the addresses for now.
834          * This can be changed later, if necessary.
835          */
836
837         appendStringInfo(str,
838                                          " :cheapestpath @ 0x%x :pruneable %s :restrictinfo ",
839                                          (int) node->cheapestpath,
840                                          node->pruneable ? "true" : "false");
841         _outNode(str, node->restrictinfo);
842
843         appendStringInfo(str, " :joininfo ");
844         _outNode(str, node->joininfo);
845
846         appendStringInfo(str, " :innerjoin ");
847         _outNode(str, node->innerjoin);
848 }
849
850 /*
851  *      TargetEntry is a subclass of Node.
852  */
853 static void
854 _outTargetEntry(StringInfo str, TargetEntry *node)
855 {
856         appendStringInfo(str, " TARGETENTRY :resdom ");
857         _outNode(str, node->resdom);
858
859         appendStringInfo(str, " :expr ");
860         _outNode(str, node->expr);
861 }
862
863 static void
864 _outRangeTblEntry(StringInfo str, RangeTblEntry *node)
865 {
866         appendStringInfo(str,
867                                          " RTE :relname %s :refname %s :relid %u :inh %s :inFromCl %s :skipAcl %s",
868                                          stringStringInfo(node->relname),
869                                          stringStringInfo(node->refname),
870                                          node->relid,
871                                          node->inh ? "true" : "false",
872                                          node->inFromCl ? "true" : "false",
873                                          node->skipAcl ? "true" : "false");
874 }
875
876 static void
877 _outRowMark(StringInfo str, RowMark *node)
878 {
879         appendStringInfo(str, " ROWMARK :rti %u :info %u", node->rti, node->info);
880 }
881
882 /*
883  *      Path is a subclass of Node.
884  */
885 static void
886 _outPath(StringInfo str, Path *node)
887 {
888         appendStringInfo(str, " PATH :pathtype %d :cost %f :pathkeys ",
889                                          node->pathtype,
890                                          node->path_cost);
891         _outNode(str, node->pathkeys);
892 }
893
894 /*
895  *      IndexPath is a subclass of Path.
896  */
897 static void
898 _outIndexPath(StringInfo str, IndexPath *node)
899 {
900         appendStringInfo(str,
901                                          " INDEXPATH :pathtype %d :cost %f :pathkeys ",
902                                          node->path.pathtype,
903                                          node->path.path_cost);
904         _outNode(str, node->path.pathkeys);
905
906         appendStringInfo(str, " :indexid ");
907         _outIntList(str, node->indexid);
908
909         appendStringInfo(str, " :indexqual ");
910         _outNode(str, node->indexqual);
911
912         appendStringInfo(str, " :joinrelids ");
913         _outIntList(str, node->joinrelids);
914 }
915
916 /*
917  *      NestPath is a subclass of Path
918  */
919 static void
920 _outNestPath(StringInfo str, NestPath *node)
921 {
922         appendStringInfo(str,
923                                          " NESTPATH :pathtype %d :cost %f :pathkeys ",
924                                          node->path.pathtype,
925                                          node->path.path_cost);
926         _outNode(str, node->path.pathkeys);
927
928         appendStringInfo(str, " :pathinfo ");
929         _outNode(str, node->pathinfo);
930
931         /*
932          * Not sure if these are nodes; they're declared as "struct path *".
933          * For now, i'll just print the addresses.
934          */
935
936         appendStringInfo(str,
937                                          " :outerjoinpath @ 0x%x :innerjoinpath @ 0x%x ",
938                                          (int) node->outerjoinpath,
939                                          (int) node->innerjoinpath);
940 }
941
942 /*
943  *      MergePath is a subclass of NestPath.
944  */
945 static void
946 _outMergePath(StringInfo str, MergePath *node)
947 {
948         appendStringInfo(str,
949                                          " MERGEPATH :pathtype %d :cost %f :pathkeys ",
950                                          node->jpath.path.pathtype,
951                                          node->jpath.path.path_cost);
952         _outNode(str, node->jpath.path.pathkeys);
953
954         appendStringInfo(str, " :pathinfo ");
955         _outNode(str, node->jpath.pathinfo);
956
957         /*
958          * Not sure if these are nodes; they're declared as "struct path *".
959          * For now, i'll just print the addresses.
960          */
961
962         appendStringInfo(str,
963                                          " :outerjoinpath @ 0x%x :innerjoinpath @ 0x%x ",
964                                          (int) node->jpath.outerjoinpath,
965                                          (int) node->jpath.innerjoinpath);
966
967         appendStringInfo(str, " :path_mergeclauses ");
968         _outNode(str, node->path_mergeclauses);
969
970         appendStringInfo(str, " :outersortkeys ");
971         _outNode(str, node->outersortkeys);
972
973         appendStringInfo(str, " :innersortkeys ");
974         _outNode(str, node->innersortkeys);
975 }
976
977 /*
978  *      HashPath is a subclass of NestPath.
979  */
980 static void
981 _outHashPath(StringInfo str, HashPath *node)
982 {
983         appendStringInfo(str,
984                                          " HASHPATH :pathtype %d :cost %f :pathkeys ",
985                                          node->jpath.path.pathtype,
986                                          node->jpath.path.path_cost);
987         _outNode(str, node->jpath.path.pathkeys);
988
989         appendStringInfo(str, " :pathinfo ");
990         _outNode(str, node->jpath.pathinfo);
991
992         /*
993          * Not sure if these are nodes; they're declared as "struct path *".
994          * For now, i'll just print the addresses.
995          */
996
997         appendStringInfo(str,
998                                          " :outerjoinpath @ 0x%x :innerjoinpath @ 0x%x ",
999                                          (int) node->jpath.outerjoinpath,
1000                                          (int) node->jpath.innerjoinpath);
1001
1002         appendStringInfo(str, " :path_hashclauses ");
1003         _outNode(str, node->path_hashclauses);
1004 }
1005
1006 /*
1007  *      PathKeyItem is a subclass of Node.
1008  */
1009 static void
1010 _outPathKeyItem(StringInfo str, PathKeyItem *node)
1011 {
1012         appendStringInfo(str, " PATHKEYITEM :sortop %u :key ",
1013                                          node->sortop);
1014         _outNode(str, node->key);
1015 }
1016
1017 /*
1018  *      RestrictInfo is a subclass of Node.
1019  */
1020 static void
1021 _outRestrictInfo(StringInfo str, RestrictInfo *node)
1022 {
1023         appendStringInfo(str, " RESTRICTINFO :clause ");
1024         _outNode(str, node->clause);
1025
1026         appendStringInfo(str,
1027                                          " :selectivity %f :subclauseindices ",
1028                                          node->selectivity);
1029         _outNode(str, node->subclauseindices);
1030
1031         appendStringInfo(str, " :mergejoinoperator %u ", node->mergejoinoperator);
1032         appendStringInfo(str, " :left_sortop %u ", node->left_sortop);
1033         appendStringInfo(str, " :right_sortop %u ", node->right_sortop);
1034         appendStringInfo(str, " :hashjoinoperator %u ", node->hashjoinoperator);
1035 }
1036
1037 /*
1038  *      JoinInfo is a subclass of Node.
1039  */
1040 static void
1041 _outJoinInfo(StringInfo str, JoinInfo *node)
1042 {
1043         appendStringInfo(str, " JINFO :unjoined_relids ");
1044         _outIntList(str, node->unjoined_relids);
1045
1046         appendStringInfo(str, " :jinfo_restrictinfo ");
1047         _outNode(str, node->jinfo_restrictinfo);
1048 }
1049
1050 /*
1051  * Print the value of a Datum given its type.
1052  */
1053 static void
1054 _outDatum(StringInfo str, Datum value, Oid type)
1055 {
1056         char       *s;
1057         Size            length,
1058                                 typeLength;
1059         bool            byValue;
1060         int                     i;
1061
1062         /*
1063          * find some information about the type and the "real" length of the
1064          * datum.
1065          */
1066         byValue = get_typbyval(type);
1067         typeLength = get_typlen(type);
1068         length = datumGetSize(value, type, byValue, typeLength);
1069
1070         if (byValue)
1071         {
1072                 s = (char *) (&value);
1073                 appendStringInfo(str, " %d [ ", length);
1074                 for (i = 0; i < sizeof(Datum); i++)
1075                         appendStringInfo(str, " %d ", (int) (s[i]));
1076                 appendStringInfo(str, "] ");
1077         }
1078         else
1079         {                                                       /* !byValue */
1080                 s = (char *) DatumGetPointer(value);
1081                 if (!PointerIsValid(s))
1082                         appendStringInfo(str, " 0 [ ] ");
1083                 else
1084                 {
1085
1086                         /*
1087                          * length is unsigned - very bad to do < comparison to -1
1088                          * without casting it to int first!! -mer 8 Jan 1991
1089                          */
1090                         if (((int) length) <= -1)
1091                                 length = VARSIZE(s);
1092                         appendStringInfo(str, " %d [ ", length);
1093                         for (i = 0; i < length; i++)
1094                                 appendStringInfo(str, " %d ", (int) (s[i]));
1095                         appendStringInfo(str, "] ");
1096                 }
1097         }
1098 }
1099
1100 static void
1101 _outIter(StringInfo str, Iter *node)
1102 {
1103         appendStringInfo(str, " ITER :iterexpr ");
1104         _outNode(str, node->iterexpr);
1105 }
1106
1107 static void
1108 _outStream(StringInfo str, Stream *node)
1109 {
1110         appendStringInfo(str,
1111                                          " STREAM :pathptr @ 0x%x :cinfo @ 0x%x :clausetype %d :upstream @ 0x%x ",
1112                                          (int) node->pathptr,
1113                                          (int) node->cinfo,
1114                                          (int) node->clausetype,
1115                                          (int) node->upstream);
1116
1117         appendStringInfo(str,
1118                    " :downstream @ 0x%x :groupup %d :groupcost %f :groupsel %f ",
1119                                          (int) node->downstream,
1120                                          node->groupup,
1121                                          node->groupcost,
1122                                          node->groupsel);
1123 }
1124
1125 static void
1126 _outAExpr(StringInfo str, A_Expr *node)
1127 {
1128         appendStringInfo(str, "EXPR ");
1129         switch (node->oper)
1130         {
1131                 case AND:
1132                         appendStringInfo(str, "AND");
1133                         break;
1134                 case OR:
1135                         appendStringInfo(str, "OR");
1136                         break;
1137                 case NOT:
1138                         appendStringInfo(str, "NOT");
1139                         break;
1140                 case ISNULL:
1141                         appendStringInfo(str, "ISNULL");
1142                         break;
1143                 case NOTNULL:
1144                         appendStringInfo(str, "NOTNULL");
1145                         break;
1146                 default:
1147                         appendStringInfo(str, stringStringInfo(node->opname));
1148                         break;
1149         }
1150         _outNode(str, node->lexpr);
1151         _outNode(str, node->rexpr);
1152         return;
1153 }
1154
1155 static void
1156 _outValue(StringInfo str, Value *value)
1157 {
1158         switch (value->type)
1159         {
1160                         case T_String:
1161                         appendStringInfo(str, " \"%s\" ", stringStringInfo(value->val.str));
1162                         break;
1163                 case T_Integer:
1164                         appendStringInfo(str, " %ld ", value->val.ival);
1165                         break;
1166                 case T_Float:
1167                         appendStringInfo(str, " %f ", value->val.dval);
1168                         break;
1169                 default:
1170                         break;
1171         }
1172         return;
1173 }
1174
1175 static void
1176 _outIdent(StringInfo str, Ident *node)
1177 {
1178         appendStringInfo(str, " IDENT \"%s\" ", stringStringInfo(node->name));
1179         return;
1180 }
1181
1182 static void
1183 _outAttr(StringInfo str, Attr *node)
1184 {
1185         List       *l;
1186
1187         appendStringInfo(str, " ATTR \"%s\" ", stringStringInfo(node->relname));
1188
1189         appendStringInfo(str, "(");
1190         foreach(l, node->attrs)
1191         {
1192                 _outNode(str, lfirst(l));
1193                 if (lnext(l))
1194                         appendStringInfo(str, ",");
1195         }
1196         appendStringInfo(str, ")");
1197         return;
1198 }
1199
1200 static void
1201 _outAConst(StringInfo str, A_Const *node)
1202 {
1203         appendStringInfo(str, "CONST ");
1204         _outValue(str, &(node->val));
1205         return;
1206 }
1207
1208 static void
1209 _outConstraint(StringInfo str, Constraint *node)
1210 {
1211         appendStringInfo(str, " %s :type", stringStringInfo(node->name));
1212
1213         switch (node->contype)
1214         {
1215                 case CONSTR_PRIMARY:
1216                         appendStringInfo(str, " PRIMARY KEY ");
1217                         _outNode(str, node->keys);
1218                         break;
1219
1220                 case CONSTR_CHECK:
1221                         appendStringInfo(str, " CHECK :raw ");
1222                         _outNode(str, node->raw_expr);
1223                         appendStringInfo(str, " :cooked %s ",
1224                                                          stringStringInfo(node->cooked_expr));
1225                         break;
1226
1227                 case CONSTR_DEFAULT:
1228                         appendStringInfo(str, " DEFAULT :raw ");
1229                         _outNode(str, node->raw_expr);
1230                         appendStringInfo(str, " :cooked %s ",
1231                                                          stringStringInfo(node->cooked_expr));
1232                         break;
1233
1234                 case CONSTR_NOTNULL:
1235                         appendStringInfo(str, " NOT NULL ");
1236                         break;
1237
1238                 case CONSTR_UNIQUE:
1239                         appendStringInfo(str, " UNIQUE ");
1240                         _outNode(str, node->keys);
1241                         break;
1242
1243                 default:
1244                         appendStringInfo(str, "<unrecognized constraint>");
1245                         break;
1246         }
1247 }
1248
1249 static void
1250 _outCaseExpr(StringInfo str, CaseExpr *node)
1251 {
1252         appendStringInfo(str, "CASE ");
1253         _outNode(str, node->args);
1254
1255         appendStringInfo(str, " :default ");
1256         _outNode(str, node->defresult);
1257
1258         return;
1259 }
1260
1261 static void
1262 _outCaseWhen(StringInfo str, CaseWhen *node)
1263 {
1264         appendStringInfo(str, " WHEN ");
1265         _outNode(str, node->expr);
1266
1267         appendStringInfo(str, " :then ");
1268         _outNode(str, node->result);
1269
1270         return;
1271 }
1272
1273 /*
1274  * _outNode -
1275  *        converts a Node into ascii string and append it to 'str'
1276  */
1277 static void
1278 _outNode(StringInfo str, void *obj)
1279 {
1280         if (obj == NULL)
1281         {
1282                 appendStringInfo(str, "<>");
1283                 return;
1284         }
1285
1286         if (nodeTag(obj) == T_List)
1287         {
1288                 List       *l;
1289
1290                 appendStringInfo(str, "(");
1291                 foreach(l, (List *) obj)
1292                 {
1293                         _outNode(str, lfirst(l));
1294                         if (lnext(l))
1295                                 appendStringInfo(str, " ");
1296                 }
1297                 appendStringInfo(str, ")");
1298         }
1299         else
1300         {
1301                 appendStringInfo(str, "{");
1302                 switch (nodeTag(obj))
1303                 {
1304                         case T_CreateStmt:
1305                                 _outCreateStmt(str, obj);
1306                                 break;
1307                         case T_IndexStmt:
1308                                 _outIndexStmt(str, obj);
1309                                 break;
1310
1311                         case T_ColumnDef:
1312                                 _outColumnDef(str, obj);
1313                                 break;
1314                         case T_TypeName:
1315                                 _outTypeName(str, obj);
1316                                 break;
1317                         case T_IndexElem:
1318                                 _outIndexElem(str, obj);
1319                                 break;
1320                         case T_Query:
1321                                 _outQuery(str, obj);
1322                                 break;
1323                         case T_SortClause:
1324                                 _outSortClause(str, obj);
1325                                 break;
1326                         case T_GroupClause:
1327                                 _outGroupClause(str, obj);
1328                                 break;
1329                         case T_Plan:
1330                                 _outPlan(str, obj);
1331                                 break;
1332                         case T_Result:
1333                                 _outResult(str, obj);
1334                                 break;
1335                         case T_Append:
1336                                 _outAppend(str, obj);
1337                                 break;
1338                         case T_Join:
1339                                 _outJoin(str, obj);
1340                                 break;
1341                         case T_NestLoop:
1342                                 _outNestLoop(str, obj);
1343                                 break;
1344                         case T_MergeJoin:
1345                                 _outMergeJoin(str, obj);
1346                                 break;
1347                         case T_HashJoin:
1348                                 _outHashJoin(str, obj);
1349                                 break;
1350                         case T_Scan:
1351                                 _outScan(str, obj);
1352                                 break;
1353                         case T_SeqScan:
1354                                 _outSeqScan(str, obj);
1355                                 break;
1356                         case T_IndexScan:
1357                                 _outIndexScan(str, obj);
1358                                 break;
1359                         case T_Noname:
1360                                 _outNoname(str, obj);
1361                                 break;
1362                         case T_Sort:
1363                                 _outSort(str, obj);
1364                                 break;
1365                         case T_Agg:
1366                                 _outAgg(str, obj);
1367                                 break;
1368                         case T_Group:
1369                                 _outGroup(str, obj);
1370                                 break;
1371                         case T_Unique:
1372                                 _outUnique(str, obj);
1373                                 break;
1374                         case T_Hash:
1375                                 _outHash(str, obj);
1376                                 break;
1377                         case T_SubPlan:
1378                                 _outSubPlan(str, obj);
1379                                 break;
1380                         case T_Resdom:
1381                                 _outResdom(str, obj);
1382                                 break;
1383                         case T_Fjoin:
1384                                 _outFjoin(str, obj);
1385                                 break;
1386                         case T_Expr:
1387                                 _outExpr(str, obj);
1388                                 break;
1389                         case T_Var:
1390                                 _outVar(str, obj);
1391                                 break;
1392                         case T_Const:
1393                                 _outConst(str, obj);
1394                                 break;
1395                         case T_Aggref:
1396                                 _outAggref(str, obj);
1397                                 break;
1398                         case T_SubLink:
1399                                 _outSubLink(str, obj);
1400                                 break;
1401                         case T_Array:
1402                                 _outArray(str, obj);
1403                                 break;
1404                         case T_ArrayRef:
1405                                 _outArrayRef(str, obj);
1406                                 break;
1407                         case T_Func:
1408                                 _outFunc(str, obj);
1409                                 break;
1410                         case T_Oper:
1411                                 _outOper(str, obj);
1412                                 break;
1413                         case T_Param:
1414                                 _outParam(str, obj);
1415                                 break;
1416                         case T_EState:
1417                                 _outEState(str, obj);
1418                                 break;
1419                         case T_RelOptInfo:
1420                                 _outRelOptInfo(str, obj);
1421                                 break;
1422                         case T_TargetEntry:
1423                                 _outTargetEntry(str, obj);
1424                                 break;
1425                         case T_RangeTblEntry:
1426                                 _outRangeTblEntry(str, obj);
1427                                 break;
1428                         case T_RowMark:
1429                                 _outRowMark(str, obj);
1430                                 break;
1431                         case T_Path:
1432                                 _outPath(str, obj);
1433                                 break;
1434                         case T_IndexPath:
1435                                 _outIndexPath(str, obj);
1436                                 break;
1437                         case T_NestPath:
1438                                 _outNestPath(str, obj);
1439                                 break;
1440                         case T_MergePath:
1441                                 _outMergePath(str, obj);
1442                                 break;
1443                         case T_HashPath:
1444                                 _outHashPath(str, obj);
1445                                 break;
1446                         case T_PathKeyItem:
1447                                 _outPathKeyItem(str, obj);
1448                                 break;
1449                         case T_RestrictInfo:
1450                                 _outRestrictInfo(str, obj);
1451                                 break;
1452                         case T_JoinInfo:
1453                                 _outJoinInfo(str, obj);
1454                                 break;
1455                         case T_Iter:
1456                                 _outIter(str, obj);
1457                                 break;
1458                         case T_Stream:
1459                                 _outStream(str, obj);
1460                                 break;
1461                         case T_Integer:
1462                         case T_String:
1463                         case T_Float:
1464                                 _outValue(str, obj);
1465                                 break;
1466                         case T_A_Expr:
1467                                 _outAExpr(str, obj);
1468                                 break;
1469                         case T_Ident:
1470                                 _outIdent(str, obj);
1471                                 break;
1472                         case T_A_Const:
1473                                 _outAConst(str, obj);
1474                                 break;
1475                         case T_Constraint:
1476                                 _outConstraint(str, obj);
1477                                 break;
1478                         case T_CaseExpr:
1479                                 _outCaseExpr(str, obj);
1480                                 break;
1481                         case T_CaseWhen:
1482                                 _outCaseWhen(str, obj);
1483                                 break;
1484
1485                         case T_VariableSetStmt:
1486                                 break;
1487                         case T_SelectStmt:
1488                                 _outSelectStmt(str, obj);
1489                                 break;
1490                         case T_FuncCall:
1491                                 _outFuncCall(str, obj);
1492                                 break;
1493                         case T_Attr:
1494                                 _outAttr(str, obj);
1495                                 break;
1496
1497                         default:
1498                                 elog(NOTICE, "_outNode: don't know how to print type %d ",
1499                                          nodeTag(obj));
1500                                 break;
1501                 }
1502                 appendStringInfo(str, "}");
1503         }
1504         return;
1505 }
1506
1507 /*
1508  * nodeToString -
1509  *         returns the ascii representation of the Node as a palloc'd string
1510  */
1511 char *
1512 nodeToString(void *obj)
1513 {
1514         StringInfoData str;
1515
1516         /* see stringinfo.h for an explanation of this maneuver */
1517         initStringInfo(&str);
1518         _outNode(&str, obj);
1519         return str.data;
1520 }