]> granicus.if.org Git - postgresql/blob - src/backend/nodes/readfuncs.c
Create a new expression node type RelabelType, which exists solely to
[postgresql] / src / backend / nodes / readfuncs.c
1 /*-------------------------------------------------------------------------
2  *
3  * readfuncs.c
4  *        Reader functions for Postgres tree nodes.
5  *
6  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.85 2000/02/20 21:32:05 tgl Exp $
12  *
13  * NOTES
14  *        Most of the read functions for plan nodes are tested. (In fact, they
15  *        pass the regression test as of 11/8/94.) The rest (for path selection)
16  *        are probably never used. No effort has been made to get them to work.
17  *        The simplest way to test these functions is by doing the following in
18  *        ProcessQuery (before executing the plan):
19  *                              plan = stringToNode(nodeToString(plan));
20  *        Then, run the regression test. Let's just say you'll notice if either
21  *        of the above function are not properly done.
22  *                                                                                                              - ay 11/94
23  *
24  *-------------------------------------------------------------------------
25  */
26 #include <math.h>
27
28 #include "postgres.h"
29
30 #include "catalog/pg_index.h"
31 #include "nodes/plannodes.h"
32 #include "nodes/readfuncs.h"
33 #include "nodes/relation.h"
34 #include "utils/lsyscache.h"
35
36 /* ----------------
37  *              node creator declarations
38  * ----------------
39  */
40
41 static Datum readDatum(Oid type);
42
43 static List *
44 toIntList(List *list)
45 {
46         List       *l;
47
48         foreach(l, list)
49         {
50                 /* ugly manipulation, should probably free the Value node too */
51                 lfirst(l) = (void *) intVal(lfirst(l));
52         }
53         return list;
54 }
55
56 /* ----------------
57  *              _readQuery
58  * ----------------
59  */
60 static Query *
61 _readQuery()
62 {
63         Query      *local_node;
64         char       *token;
65         int                     length;
66
67         local_node = makeNode(Query);
68
69         token = lsptok(NULL, &length);          /* skip the :command */
70         token = lsptok(NULL, &length);          /* get the commandType */
71         local_node->commandType = atoi(token);
72
73         token = lsptok(NULL, &length);          /* skip :utility */
74         /* we can't get create or index here, can we? */
75
76         token = lsptok(NULL, &length);          /* get the notify name if any */
77         if (length == 0)
78                 local_node->utilityStmt = NULL;
79         else
80         {
81                 NotifyStmt *n = makeNode(NotifyStmt);
82
83                 n->relname = debackslash(token, length);
84                 local_node->utilityStmt = (Node *) n;
85         }
86
87         token = lsptok(NULL, &length);          /* skip the :resultRelation */
88         token = lsptok(NULL, &length);          /* get the resultRelation */
89         local_node->resultRelation = atoi(token);
90
91         token = lsptok(NULL, &length);          /* skip :into */
92         token = lsptok(NULL, &length);          /* get into */
93         if (length == 0)
94                 local_node->into = NULL;
95         else
96                 local_node->into = debackslash(token, length);
97
98         token = lsptok(NULL, &length);          /* skip :isPortal */
99         token = lsptok(NULL, &length);          /* get isPortal */
100         local_node->isPortal = (token[0] == 't') ? true : false;
101
102         token = lsptok(NULL, &length);          /* skip :isBinary */
103         token = lsptok(NULL, &length);          /* get isBinary */
104         local_node->isBinary = (token[0] == 't') ? true : false;
105
106         token = lsptok(NULL, &length);          /* skip :isTemp */
107         token = lsptok(NULL, &length);          /* get isTemp */
108         local_node->isTemp = (token[0] == 't') ? true : false;
109
110         token = lsptok(NULL, &length);          /* skip :unionall */
111         token = lsptok(NULL, &length);          /* get unionall */
112         local_node->unionall = (token[0] == 't') ? true : false;
113
114         token = lsptok(NULL, &length);          /* skip :distinctClause */
115         local_node->distinctClause = nodeRead(true);
116
117         token = lsptok(NULL, &length);          /* skip :sortClause */
118         local_node->sortClause = nodeRead(true);
119
120         token = lsptok(NULL, &length);          /* skip :rtable */
121         local_node->rtable = nodeRead(true);
122
123         token = lsptok(NULL, &length);          /* skip :targetlist */
124         local_node->targetList = nodeRead(true);
125
126         token = lsptok(NULL, &length);          /* skip :qual */
127         local_node->qual = nodeRead(true);
128
129         token = lsptok(NULL, &length);          /* skip :groupClause */
130         local_node->groupClause = nodeRead(true);
131
132         token = lsptok(NULL, &length);          /* skip :havingQual */
133         local_node->havingQual = nodeRead(true);
134
135         token = lsptok(NULL, &length);          /* skip the :hasAggs */
136         token = lsptok(NULL, &length);          /* get hasAggs */
137         local_node->hasAggs = (token[0] == 't') ? true : false;
138
139         token = lsptok(NULL, &length);          /* skip the :hasSubLinks */
140         token = lsptok(NULL, &length);          /* get hasSubLinks */
141         local_node->hasSubLinks = (token[0] == 't') ? true : false;
142
143         token = lsptok(NULL, &length);          /* skip :unionClause */
144         local_node->unionClause = nodeRead(true);
145
146         token = lsptok(NULL, &length);          /* skip :intersectClause */
147         local_node->intersectClause = nodeRead(true);
148
149
150         token = lsptok(NULL, &length);          /* skip :limitOffset */
151         local_node->limitOffset = nodeRead(true);
152
153         token = lsptok(NULL, &length);          /* skip :limitCount */
154         local_node->limitCount = nodeRead(true);
155
156         token = lsptok(NULL, &length);          /* skip :rowMark */
157         local_node->rowMark = nodeRead(true);
158
159         return local_node;
160 }
161
162 /* ----------------
163  *              _readSortClause
164  * ----------------
165  */
166 static SortClause *
167 _readSortClause()
168 {
169         SortClause *local_node;
170         char       *token;
171         int                     length;
172
173         local_node = makeNode(SortClause);
174
175         token = lsptok(NULL, &length);          /* skip :tleSortGroupRef */
176         token = lsptok(NULL, &length);          /* get tleSortGroupRef */
177         local_node->tleSortGroupRef = strtoul(token, NULL, 10);
178
179         token = lsptok(NULL, &length);          /* skip :sortop */
180         token = lsptok(NULL, &length);          /* get sortop */
181         local_node->sortop = strtoul(token, NULL, 10);
182
183         return local_node;
184 }
185
186 /* ----------------
187  *              _readGroupClause
188  * ----------------
189  */
190 static GroupClause *
191 _readGroupClause()
192 {
193         GroupClause *local_node;
194         char       *token;
195         int                     length;
196
197         local_node = makeNode(GroupClause);
198
199         token = lsptok(NULL, &length);          /* skip :tleSortGroupRef */
200         token = lsptok(NULL, &length);          /* get tleSortGroupRef */
201         local_node->tleSortGroupRef = strtoul(token, NULL, 10);
202
203         token = lsptok(NULL, &length);          /* skip :sortop */
204         token = lsptok(NULL, &length);          /* get sortop */
205         local_node->sortop = strtoul(token, NULL, 10);
206
207         return local_node;
208 }
209
210 /* ----------------
211  *              _getPlan
212  * ----------------
213  */
214 static void
215 _getPlan(Plan *node)
216 {
217         char       *token;
218         int                     length;
219
220         token = lsptok(NULL, &length);          /* first token is :startup_cost */
221         token = lsptok(NULL, &length);          /* next is the actual cost */
222         node->startup_cost = (Cost) atof(token);
223
224         token = lsptok(NULL, &length);          /* skip the :total_cost */
225         token = lsptok(NULL, &length);          /* next is the actual cost */
226         node->total_cost = (Cost) atof(token);
227
228         token = lsptok(NULL, &length);          /* skip the :rows */
229         token = lsptok(NULL, &length);          /* get the plan_rows */
230         node->plan_rows = atof(token);
231
232         token = lsptok(NULL, &length);          /* skip the :width */
233         token = lsptok(NULL, &length);          /* get the plan_width */
234         node->plan_width = atoi(token);
235
236         token = lsptok(NULL, &length);          /* eat the :state stuff */
237         token = lsptok(NULL, &length);          /* now get the state */
238
239         if (length == 0)
240                 node->state = (EState *) NULL;
241         else
242         {                                                       /* Disgusting hack until I figure out what
243                                                                  * to do here */
244                 node->state = (EState *) !NULL;
245         }
246
247         token = lsptok(NULL, &length);          /* eat :qptargetlist */
248         node->targetlist = nodeRead(true);
249
250         token = lsptok(NULL, &length);          /* eat :qpqual */
251         node->qual = nodeRead(true);
252
253         token = lsptok(NULL, &length);          /* eat :lefttree */
254         node->lefttree = (Plan *) nodeRead(true);
255
256         token = lsptok(NULL, &length);          /* eat :righttree */
257         node->righttree = (Plan *) nodeRead(true);
258
259         return;
260 }
261
262 /*
263  *      Stuff from plannodes.h
264  */
265
266 /* ----------------
267  *              _readPlan
268  * ----------------
269  */
270 static Plan *
271 _readPlan()
272 {
273         Plan       *local_node;
274
275         local_node = makeNode(Plan);
276
277         _getPlan(local_node);
278
279         return local_node;
280 }
281
282 /* ----------------
283  *              _readResult
284  * ----------------
285  */
286 static Result *
287 _readResult()
288 {
289         Result     *local_node;
290         char       *token;
291         int                     length;
292
293         local_node = makeNode(Result);
294
295         _getPlan((Plan *) local_node);
296
297         token = lsptok(NULL, &length);          /* eat :resconstantqual */
298         local_node->resconstantqual = nodeRead(true);           /* now read it */
299
300         return local_node;
301 }
302
303 /* ----------------
304  *              _readAppend
305  *
306  *      Append is a subclass of Plan.
307  * ----------------
308  */
309
310 static Append *
311 _readAppend()
312 {
313         Append     *local_node;
314         char       *token;
315         int                     length;
316
317         local_node = makeNode(Append);
318
319         _getPlan((Plan *) local_node);
320
321         token = lsptok(NULL, &length);          /* eat :appendplans */
322         local_node->appendplans = nodeRead(true);       /* now read it */
323
324         token = lsptok(NULL, &length);          /* eat :unionrtables */
325         local_node->unionrtables = nodeRead(true);      /* now read it */
326
327         token = lsptok(NULL, &length);          /* eat :inheritrelid */
328         token = lsptok(NULL, &length);          /* get inheritrelid */
329         local_node->inheritrelid = strtoul(token, NULL, 10);
330
331         token = lsptok(NULL, &length);          /* eat :inheritrtable */
332         local_node->inheritrtable = nodeRead(true); /* now read it */
333
334         return local_node;
335 }
336
337 /* ----------------
338  *              _getJoin
339  *
340  * In case Join is not the same structure as Plan someday.
341  * ----------------
342  */
343 static void
344 _getJoin(Join *node)
345 {
346         _getPlan((Plan *) node);
347 }
348
349
350 /* ----------------
351  *              _readJoin
352  *
353  *      Join is a subclass of Plan
354  * ----------------
355  */
356 static Join *
357 _readJoin()
358 {
359         Join       *local_node;
360
361         local_node = makeNode(Join);
362
363         _getJoin(local_node);
364
365         return local_node;
366 }
367
368 /* ----------------
369  *              _readNestLoop
370  *
371  *      NestLoop is a subclass of Join
372  * ----------------
373  */
374
375 static NestLoop *
376 _readNestLoop()
377 {
378         NestLoop   *local_node;
379
380         local_node = makeNode(NestLoop);
381
382         _getJoin((Join *) local_node);
383
384         return local_node;
385 }
386
387 /* ----------------
388  *              _readMergeJoin
389  *
390  *      MergeJoin is a subclass of Join
391  * ----------------
392  */
393 static MergeJoin *
394 _readMergeJoin()
395 {
396         MergeJoin  *local_node;
397         char       *token;
398         int                     length;
399
400         local_node = makeNode(MergeJoin);
401
402         _getJoin((Join *) local_node);
403         token = lsptok(NULL, &length);          /* eat :mergeclauses */
404         local_node->mergeclauses = nodeRead(true);      /* now read it */
405
406         return local_node;
407 }
408
409 /* ----------------
410  *              _readHashJoin
411  *
412  *      HashJoin is a subclass of Join.
413  * ----------------
414  */
415 static HashJoin *
416 _readHashJoin()
417 {
418         HashJoin   *local_node;
419         char       *token;
420         int                     length;
421
422         local_node = makeNode(HashJoin);
423
424         _getJoin((Join *) local_node);
425
426         token = lsptok(NULL, &length);          /* eat :hashclauses */
427         local_node->hashclauses = nodeRead(true);       /* now read it */
428
429         token = lsptok(NULL, &length);          /* eat :hashjoinop */
430         token = lsptok(NULL, &length);          /* get hashjoinop */
431         local_node->hashjoinop = strtoul(token, NULL, 10);
432
433         token = lsptok(NULL, &length);          /* eat :hashdone */
434         token = lsptok(NULL, &length);          /* eat hashdone */
435         local_node->hashdone = false;
436
437         return local_node;
438 }
439
440 /* ----------------
441  *              _getScan
442  *
443  *      Scan is a subclass of Node
444  *      (Actually, according to the plannodes.h include file, it is a
445  *      subclass of Plan.  This is why _getPlan is used here.)
446  *
447  *      Scan gets its own get function since stuff inherits it.
448  * ----------------
449  */
450 static void
451 _getScan(Scan *node)
452 {
453         char       *token;
454         int                     length;
455
456         _getPlan((Plan *) node);
457
458         token = lsptok(NULL, &length);          /* eat :scanrelid */
459         token = lsptok(NULL, &length);          /* get scanrelid */
460         node->scanrelid = strtoul(token, NULL, 10);
461 }
462
463 /* ----------------
464  *              _readScan
465  *
466  * Scan is a subclass of Plan (Not Node, see above).
467  * ----------------
468  */
469 static Scan *
470 _readScan()
471 {
472         Scan       *local_node;
473
474         local_node = makeNode(Scan);
475
476         _getScan(local_node);
477
478         return local_node;
479 }
480
481 /* ----------------
482  *              _readSeqScan
483  *
484  *      SeqScan is a subclass of Scan
485  * ----------------
486  */
487 static SeqScan *
488 _readSeqScan()
489 {
490         SeqScan    *local_node;
491
492         local_node = makeNode(SeqScan);
493
494         _getScan((Scan *) local_node);
495
496         return local_node;
497 }
498
499 /* ----------------
500  *              _readIndexScan
501  *
502  *      IndexScan is a subclass of Scan
503  * ----------------
504  */
505 static IndexScan *
506 _readIndexScan()
507 {
508         IndexScan  *local_node;
509         char       *token;
510         int                     length;
511
512         local_node = makeNode(IndexScan);
513
514         _getScan((Scan *) local_node);
515
516         token = lsptok(NULL, &length);          /* eat :indxid */
517         local_node->indxid = toIntList(nodeRead(true));         /* now read it */
518
519         token = lsptok(NULL, &length);          /* eat :indxqual */
520         local_node->indxqual = nodeRead(true);          /* now read it */
521
522         token = lsptok(NULL, &length);          /* eat :indxqualorig */
523         local_node->indxqualorig = nodeRead(true);      /* now read it */
524
525         token = lsptok(NULL, &length);          /* eat :indxorderdir */
526         token = lsptok(NULL, &length);          /* get indxorderdir */
527         local_node->indxorderdir = atoi(token);
528
529         return local_node;
530 }
531
532 /* ----------------
533  *              _readTidScan
534  *
535  *      TidScan is a subclass of Scan
536  * ----------------
537  */
538 static TidScan *
539 _readTidScan()
540 {
541         TidScan  *local_node;
542         char       *token;
543         int                     length;
544
545         local_node = makeNode(TidScan);
546
547         _getScan((Scan *) local_node);
548
549         token = lsptok(NULL, &length);          /* eat :needrescan */
550         token = lsptok(NULL, &length);          /* get needrescan */
551         local_node->needRescan = atoi(token);
552
553         token = lsptok(NULL, &length);          /* eat :tideval */
554         local_node->tideval = nodeRead(true);   /* now read it */
555
556         return local_node;
557 }
558
559 /* ----------------
560  *              _readNoname
561  *
562  *      Noname is a subclass of Plan
563  * ----------------
564  */
565 static Noname *
566 _readNoname()
567 {
568         Noname     *local_node;
569         char       *token;
570         int                     length;
571
572         local_node = makeNode(Noname);
573
574         _getPlan((Plan *) local_node);
575
576         token = lsptok(NULL, &length);          /* eat :nonameid */
577         token = lsptok(NULL, &length);          /* get nonameid */
578         local_node->nonameid = atol(token);
579
580         token = lsptok(NULL, &length);          /* eat :keycount */
581         token = lsptok(NULL, &length);          /* get keycount */
582         local_node->keycount = atoi(token);
583
584         return local_node;
585 }
586
587 /* ----------------
588  *              _readSort
589  *
590  *      Sort is a subclass of Noname
591  * ----------------
592  */
593 static Sort *
594 _readSort()
595 {
596         Sort       *local_node;
597         char       *token;
598         int                     length;
599
600         local_node = makeNode(Sort);
601
602         _getPlan((Plan *) local_node);
603
604         token = lsptok(NULL, &length);          /* eat :nonameid */
605         token = lsptok(NULL, &length);          /* get nonameid */
606         local_node->nonameid = atol(token);
607
608         token = lsptok(NULL, &length);          /* eat :keycount */
609         token = lsptok(NULL, &length);          /* get keycount */
610         local_node->keycount = atoi(token);
611
612         return local_node;
613 }
614
615 static Agg *
616 _readAgg()
617 {
618         Agg                *local_node;
619
620         local_node = makeNode(Agg);
621         _getPlan((Plan *) local_node);
622
623         return local_node;
624 }
625
626 /* ----------------
627  *              _readHash
628  *
629  *      Hash is a subclass of Noname
630  * ----------------
631  */
632 static Hash *
633 _readHash()
634 {
635         Hash       *local_node;
636         char       *token;
637         int                     length;
638
639         local_node = makeNode(Hash);
640
641         _getPlan((Plan *) local_node);
642
643         token = lsptok(NULL, &length);          /* eat :hashkey */
644         local_node->hashkey = (Var *) nodeRead(true);
645
646         return local_node;
647 }
648
649 /*
650  *      Stuff from primnodes.h.
651  */
652
653 /* ----------------
654  *              _readResdom
655  *
656  *      Resdom is a subclass of Node
657  * ----------------
658  */
659 static Resdom *
660 _readResdom()
661 {
662         Resdom     *local_node;
663         char       *token;
664         int                     length;
665
666         local_node = makeNode(Resdom);
667
668         token = lsptok(NULL, &length);          /* eat :resno */
669         token = lsptok(NULL, &length);          /* get resno */
670         local_node->resno = atoi(token);
671
672         token = lsptok(NULL, &length);          /* eat :restype */
673         token = lsptok(NULL, &length);          /* get restype */
674         local_node->restype = atol(token);
675
676         token = lsptok(NULL, &length);          /* eat :restypmod */
677         token = lsptok(NULL, &length);          /* get restypmod */
678         local_node->restypmod = atoi(token);
679
680         token = lsptok(NULL, &length);          /* eat :resname */
681         token = lsptok(NULL, &length);          /* get the name */
682         if (length == 0)
683                 local_node->resname = NULL;
684         else
685                 local_node->resname = debackslash(token, length);
686
687         token = lsptok(NULL, &length);          /* eat :reskey */
688         token = lsptok(NULL, &length);          /* get reskey */
689         local_node->reskey = strtoul(token, NULL, 10);
690
691         token = lsptok(NULL, &length);          /* eat :reskeyop */
692         token = lsptok(NULL, &length);          /* get reskeyop */
693         local_node->reskeyop = (Oid) atol(token);
694
695         token = lsptok(NULL, &length);          /* eat :ressortgroupref */
696         token = lsptok(NULL, &length);          /* get ressortgroupref */
697         local_node->ressortgroupref = strtoul(token, NULL, 10);
698
699         token = lsptok(NULL, &length);          /* eat :resjunk */
700         token = lsptok(NULL, &length);          /* get resjunk */
701         local_node->resjunk = (token[0] == 't') ? true : false;
702
703         return local_node;
704 }
705
706 /* ----------------
707  *              _readExpr
708  *
709  *      Expr is a subclass of Node
710  * ----------------
711  */
712 static Expr *
713 _readExpr()
714 {
715         Expr       *local_node;
716         char       *token;
717         int                     length;
718
719         local_node = makeNode(Expr);
720
721         token = lsptok(NULL, &length);          /* eat :typeOid */
722         token = lsptok(NULL, &length);          /* get typeOid */
723         local_node->typeOid = (Oid) atol(token);
724
725         token = lsptok(NULL, &length);          /* eat :opType */
726         token = lsptok(NULL, &length);          /* get opType */
727         if (!strncmp(token, "op", 2))
728                 local_node->opType = OP_EXPR;
729         else if (!strncmp(token, "func", 4))
730                 local_node->opType = FUNC_EXPR;
731         else if (!strncmp(token, "or", 2))
732                 local_node->opType = OR_EXPR;
733         else if (!strncmp(token, "and", 3))
734                 local_node->opType = AND_EXPR;
735         else if (!strncmp(token, "not", 3))
736                 local_node->opType = NOT_EXPR;
737         else if (!strncmp(token, "subp", 4))
738                 local_node->opType = SUBPLAN_EXPR;
739         else
740                 elog(ERROR, "_readExpr: unknown opType \"%.10s\"", token);
741
742         token = lsptok(NULL, &length);          /* eat :oper */
743         local_node->oper = nodeRead(true);
744
745         token = lsptok(NULL, &length);          /* eat :args */
746         local_node->args = nodeRead(true);      /* now read it */
747
748         return local_node;
749 }
750
751 /* ----------------
752  *              _readCaseExpr
753  *
754  *      CaseExpr is a subclass of Node
755  * ----------------
756  */
757 static CaseExpr *
758 _readCaseExpr()
759 {
760         CaseExpr   *local_node;
761         char       *token;
762         int                     length;
763
764         local_node = makeNode(CaseExpr);
765
766         local_node->args = nodeRead(true);
767         token = lsptok(NULL, &length);          /* eat :default */
768         local_node->defresult = nodeRead(true);
769
770         return local_node;
771 }
772
773 /* ----------------
774  *              _readCaseWhen
775  *
776  *      CaseWhen is a subclass of Node
777  * ----------------
778  */
779 static CaseWhen *
780 _readCaseWhen()
781 {
782         CaseWhen   *local_node;
783         char       *token;
784         int                     length;
785
786         local_node = makeNode(CaseWhen);
787
788         local_node->expr = nodeRead(true);
789         token = lsptok(NULL, &length);          /* eat :then */
790         local_node->result = nodeRead(true);
791
792         return local_node;
793 }
794
795 /* ----------------
796  *              _readVar
797  *
798  *      Var is a subclass of Expr
799  * ----------------
800  */
801 static Var *
802 _readVar()
803 {
804         Var                *local_node;
805         char       *token;
806         int                     length;
807
808         local_node = makeNode(Var);
809
810         token = lsptok(NULL, &length);          /* eat :varno */
811         token = lsptok(NULL, &length);          /* get varno */
812         local_node->varno = strtoul(token, NULL, 10);
813
814         token = lsptok(NULL, &length);          /* eat :varattno */
815         token = lsptok(NULL, &length);          /* get varattno */
816         local_node->varattno = atoi(token);
817
818         token = lsptok(NULL, &length);          /* eat :vartype */
819         token = lsptok(NULL, &length);          /* get vartype */
820         local_node->vartype = (Oid) atol(token);
821
822         token = lsptok(NULL, &length);          /* eat :vartypmod */
823         token = lsptok(NULL, &length);          /* get vartypmod */
824         local_node->vartypmod = atoi(token);
825
826         token = lsptok(NULL, &length);          /* eat :varlevelsup */
827         token = lsptok(NULL, &length);          /* get varlevelsup */
828         local_node->varlevelsup = (Oid) atol(token);
829
830         token = lsptok(NULL, &length);          /* eat :varnoold */
831         token = lsptok(NULL, &length);          /* get varnoold */
832         local_node->varnoold = (Oid) atol(token);
833
834         token = lsptok(NULL, &length);          /* eat :varoattno */
835         token = lsptok(NULL, &length);          /* eat :varoattno */
836         local_node->varoattno = (int) atol(token);
837
838         return local_node;
839 }
840
841 /* ----------------
842  * _readArray
843  *
844  * Array is a subclass of Expr
845  * ----------------
846  */
847 static Array *
848 _readArray()
849 {
850         Array      *local_node;
851         char       *token;
852         int                     length;
853
854         local_node = makeNode(Array);
855
856         token = lsptok(NULL, &length);          /* eat :arrayelemtype */
857         token = lsptok(NULL, &length);          /* get arrayelemtype */
858         local_node->arrayelemtype = strtoul(token, NULL, 10);
859
860         token = lsptok(NULL, &length);          /* eat :arrayelemlength */
861         token = lsptok(NULL, &length);          /* get arrayelemlength */
862         local_node->arrayelemlength = atoi(token);
863
864         token = lsptok(NULL, &length);          /* eat :arrayelembyval */
865         token = lsptok(NULL, &length);          /* get arrayelembyval */
866         local_node->arrayelembyval = (token[0] == 't') ? true : false;
867
868         token = lsptok(NULL, &length);          /* eat :arraylow */
869         token = lsptok(NULL, &length);          /* get arraylow */
870         local_node->arraylow.indx[0] = atoi(token);
871
872         token = lsptok(NULL, &length);          /* eat :arrayhigh */
873         token = lsptok(NULL, &length);          /* get arrayhigh */
874         local_node->arrayhigh.indx[0] = atoi(token);
875
876         token = lsptok(NULL, &length);          /* eat :arraylen */
877         token = lsptok(NULL, &length);          /* get arraylen */
878         local_node->arraylen = atoi(token);
879
880         return local_node;
881 }
882
883 /* ----------------
884  * _readArrayRef
885  *
886  * ArrayRef is a subclass of Expr
887  * ----------------
888  */
889 static ArrayRef *
890 _readArrayRef()
891 {
892         ArrayRef   *local_node;
893         char       *token;
894         int                     length;
895
896         local_node = makeNode(ArrayRef);
897
898         token = lsptok(NULL, &length);          /* eat :refelemtype */
899         token = lsptok(NULL, &length);          /* get refelemtype */
900         local_node->refelemtype = strtoul(token, NULL, 10);
901
902         token = lsptok(NULL, &length);          /* eat :refattrlength */
903         token = lsptok(NULL, &length);          /* get refattrlength */
904         local_node->refattrlength = atoi(token);
905
906         token = lsptok(NULL, &length);          /* eat :refelemlength */
907         token = lsptok(NULL, &length);          /* get refelemlength */
908         local_node->refelemlength = atoi(token);
909
910         token = lsptok(NULL, &length);          /* eat :refelembyval */
911         token = lsptok(NULL, &length);          /* get refelembyval */
912         local_node->refelembyval = (token[0] == 't') ? true : false;
913
914         token = lsptok(NULL, &length);          /* eat :refupperindex */
915         local_node->refupperindexpr = nodeRead(true);
916
917         token = lsptok(NULL, &length);          /* eat :reflowerindex */
918         local_node->reflowerindexpr = nodeRead(true);
919
920         token = lsptok(NULL, &length);          /* eat :refexpr */
921         local_node->refexpr = nodeRead(true);
922
923         token = lsptok(NULL, &length);          /* eat :refassgnexpr */
924         local_node->refassgnexpr = nodeRead(true);
925
926         return local_node;
927 }
928
929 /* ----------------
930  *              _readConst
931  *
932  *      Const is a subclass of Expr
933  * ----------------
934  */
935 static Const *
936 _readConst()
937 {
938         Const      *local_node;
939         char       *token;
940         int                     length;
941
942         local_node = makeNode(Const);
943
944         token = lsptok(NULL, &length);          /* get :consttype */
945         token = lsptok(NULL, &length);          /* now read it */
946         local_node->consttype = atol(token);
947
948
949         token = lsptok(NULL, &length);          /* get :constlen */
950         token = lsptok(NULL, &length);          /* now read it */
951         local_node->constlen = strtol(token, NULL, 10);
952
953         token = lsptok(NULL, &length);          /* get :constisnull */
954         token = lsptok(NULL, &length);          /* now read it */
955
956         if (!strncmp(token, "true", 4))
957                 local_node->constisnull = true;
958         else
959                 local_node->constisnull = false;
960
961
962         token = lsptok(NULL, &length);          /* get :constvalue */
963
964         if (local_node->constisnull)
965         {
966                 token = lsptok(NULL, &length);  /* skip "NIL" */
967         }
968         else
969         {
970
971                 /*
972                  * read the value
973                  */
974                 local_node->constvalue = readDatum(local_node->consttype);
975         }
976
977         token = lsptok(NULL, &length);          /* get :constbyval */
978         token = lsptok(NULL, &length);          /* now read it */
979
980         if (!strncmp(token, "true", 4))
981                 local_node->constbyval = true;
982         else
983                 local_node->constbyval = false;
984
985         return local_node;
986 }
987
988 /* ----------------
989  *              _readFunc
990  *
991  *      Func is a subclass of Expr
992  * ----------------
993  */
994 static Func *
995 _readFunc()
996 {
997         Func       *local_node;
998         char       *token;
999         int                     length;
1000
1001         local_node = makeNode(Func);
1002
1003         token = lsptok(NULL, &length);          /* get :funcid */
1004         token = lsptok(NULL, &length);          /* now read it */
1005         local_node->funcid = atol(token);
1006
1007         token = lsptok(NULL, &length);          /* get :functype */
1008         token = lsptok(NULL, &length);          /* now read it */
1009         local_node->functype = atol(token);
1010
1011         token = lsptok(NULL, &length);          /* get :funcisindex */
1012         token = lsptok(NULL, &length);          /* now read it */
1013
1014         if (!strncmp(token, "true", 4))
1015                 local_node->funcisindex = true;
1016         else
1017                 local_node->funcisindex = false;
1018
1019         token = lsptok(NULL, &length);          /* get :funcsize */
1020         token = lsptok(NULL, &length);          /* now read it */
1021         local_node->funcsize = atol(token);
1022
1023         token = lsptok(NULL, &length);          /* get :func_fcache */
1024         token = lsptok(NULL, &length);          /* get @ */
1025         token = lsptok(NULL, &length);          /* now read it */
1026
1027         local_node->func_fcache = (FunctionCache *) NULL;
1028
1029         token = lsptok(NULL, &length);          /* get :func_tlist */
1030         local_node->func_tlist = nodeRead(true);        /* now read it */
1031
1032         token = lsptok(NULL, &length);          /* get :func_planlist */
1033         local_node->func_planlist = nodeRead(true); /* now read it */
1034
1035         return local_node;
1036 }
1037
1038 /* ----------------
1039  *              _readOper
1040  *
1041  *      Oper is a subclass of Expr
1042  * ----------------
1043  */
1044 static Oper *
1045 _readOper()
1046 {
1047         Oper       *local_node;
1048         char       *token;
1049         int                     length;
1050
1051         local_node = makeNode(Oper);
1052
1053         token = lsptok(NULL, &length);          /* get :opno */
1054         token = lsptok(NULL, &length);          /* now read it */
1055         local_node->opno = atol(token);
1056
1057         token = lsptok(NULL, &length);          /* get :opid */
1058         token = lsptok(NULL, &length);          /* now read it */
1059         local_node->opid = atol(token);
1060
1061         token = lsptok(NULL, &length);          /* get :opresulttype */
1062         token = lsptok(NULL, &length);          /* now read it */
1063         local_node->opresulttype = atol(token);
1064
1065         /*
1066          * NOTE: Alternatively we can call 'replace_opid' which initializes
1067          * both 'opid' and 'op_fcache'.
1068          */
1069         local_node->op_fcache = (FunctionCache *) NULL;
1070
1071         return local_node;
1072 }
1073
1074 /* ----------------
1075  *              _readParam
1076  *
1077  *      Param is a subclass of Expr
1078  * ----------------
1079  */
1080 static Param *
1081 _readParam()
1082 {
1083         Param      *local_node;
1084         char       *token;
1085         int                     length;
1086
1087         local_node = makeNode(Param);
1088
1089         token = lsptok(NULL, &length);          /* get :paramkind */
1090         token = lsptok(NULL, &length);          /* now read it */
1091         local_node->paramkind = atoi(token);
1092
1093         token = lsptok(NULL, &length);          /* get :paramid */
1094         token = lsptok(NULL, &length);          /* now read it */
1095         local_node->paramid = atol(token);
1096
1097         token = lsptok(NULL, &length);          /* get :paramname */
1098         token = lsptok(NULL, &length);          /* now read it */
1099         if (length == 0)
1100                 local_node->paramname = NULL;
1101         else
1102                 local_node->paramname = debackslash(token, length);
1103
1104         token = lsptok(NULL, &length);          /* get :paramtype */
1105         token = lsptok(NULL, &length);          /* now read it */
1106
1107         local_node->paramtype = atol(token);
1108         token = lsptok(NULL, &length);          /* get :param_tlist */
1109         local_node->param_tlist = nodeRead(true);       /* now read it */
1110
1111         return local_node;
1112 }
1113
1114 /* ----------------
1115  *              _readAggref
1116  *
1117  *      Aggref is a subclass of Node
1118  * ----------------
1119  */
1120 static Aggref *
1121 _readAggref()
1122 {
1123         Aggref     *local_node;
1124         char       *token;
1125         int                     length;
1126
1127         local_node = makeNode(Aggref);
1128
1129         token = lsptok(NULL, &length);          /* eat :aggname */
1130         token = lsptok(NULL, &length);          /* get aggname */
1131         local_node->aggname = debackslash(token, length);
1132
1133         token = lsptok(NULL, &length);          /* eat :basetype */
1134         token = lsptok(NULL, &length);          /* get basetype */
1135         local_node->basetype = (Oid) atol(token);
1136
1137         token = lsptok(NULL, &length);          /* eat :aggtype */
1138         token = lsptok(NULL, &length);          /* get aggtype */
1139         local_node->aggtype = (Oid) atol(token);
1140
1141         token = lsptok(NULL, &length);          /* eat :target */
1142         local_node->target = nodeRead(true);            /* now read it */
1143
1144         token = lsptok(NULL, &length);          /* eat :usenulls */
1145         token = lsptok(NULL, &length);          /* get usenulls */
1146         local_node->usenulls = (token[0] == 't') ? true : false;
1147
1148         token = lsptok(NULL, &length);          /* eat :aggstar */
1149         token = lsptok(NULL, &length);          /* get aggstar */
1150         local_node->aggstar = (token[0] == 't') ? true : false;
1151
1152         token = lsptok(NULL, &length);          /* eat :aggdistinct */
1153         token = lsptok(NULL, &length);          /* get aggdistinct */
1154         local_node->aggdistinct = (token[0] == 't') ? true : false;
1155
1156         return local_node;
1157 }
1158
1159 /* ----------------
1160  *              _readSubLink
1161  *
1162  *      SubLink is a subclass of Node
1163  * ----------------
1164  */
1165 static SubLink *
1166 _readSubLink()
1167 {
1168         SubLink    *local_node;
1169         char       *token;
1170         int                     length;
1171
1172         local_node = makeNode(SubLink);
1173
1174         token = lsptok(NULL, &length);          /* eat :subLinkType */
1175         token = lsptok(NULL, &length);          /* get subLinkType */
1176         local_node->subLinkType = atoi(token);
1177
1178         token = lsptok(NULL, &length);          /* eat :useor */
1179         token = lsptok(NULL, &length);          /* get useor */
1180         local_node->useor = (token[0] == 't') ? true : false;
1181
1182         token = lsptok(NULL, &length);          /* eat :lefthand */
1183         local_node->lefthand = nodeRead(true);          /* now read it */
1184
1185         token = lsptok(NULL, &length);          /* eat :oper */
1186         local_node->oper = nodeRead(true);      /* now read it */
1187
1188         token = lsptok(NULL, &length);          /* eat :subselect */
1189         local_node->subselect = nodeRead(true);         /* now read it */
1190
1191         return local_node;
1192 }
1193
1194 /* ----------------
1195  *              _readRelabelType
1196  *
1197  *      RelabelType is a subclass of Node
1198  * ----------------
1199  */
1200 static RelabelType *
1201 _readRelabelType()
1202 {
1203         RelabelType *local_node;
1204         char       *token;
1205         int                     length;
1206
1207         local_node = makeNode(RelabelType);
1208
1209         token = lsptok(NULL, &length);          /* eat :arg */
1210         local_node->arg = nodeRead(true);       /* now read it */
1211
1212         token = lsptok(NULL, &length);          /* eat :resulttype */
1213         token = lsptok(NULL, &length);          /* get resulttype */
1214         local_node->resulttype = (Oid) atol(token);
1215
1216         token = lsptok(NULL, &length);          /* eat :resulttypmod */
1217         token = lsptok(NULL, &length);          /* get resulttypmod */
1218         local_node->resulttypmod = atoi(token);
1219
1220         return local_node;
1221 }
1222
1223 /*
1224  *      Stuff from execnodes.h
1225  */
1226
1227 /* ----------------
1228  *              _readEState
1229  *
1230  *      EState is a subclass of Node.
1231  * ----------------
1232  */
1233 static EState *
1234 _readEState()
1235 {
1236         EState     *local_node;
1237         char       *token;
1238         int                     length;
1239
1240         local_node = makeNode(EState);
1241
1242         token = lsptok(NULL, &length);          /* get :direction */
1243         token = lsptok(NULL, &length);          /* now read it */
1244
1245         local_node->es_direction = atoi(token);
1246
1247         token = lsptok(NULL, &length);          /* get :range_table */
1248
1249         local_node->es_range_table = nodeRead(true);            /* now read it */
1250
1251         token = lsptok(NULL, &length);          /* get :result_relation_info */
1252         token = lsptok(NULL, &length);          /* get @ */
1253         token = lsptok(NULL, &length);          /* now read it */
1254
1255         sscanf(token, "%x", (unsigned int *) &local_node->es_result_relation_info);
1256
1257         return local_node;
1258 }
1259
1260 /*
1261  *      Stuff from relation.h
1262  */
1263
1264 /* ----------------
1265  *              _readRelOptInfo
1266  * ----------------
1267  */
1268 static RelOptInfo *
1269 _readRelOptInfo()
1270 {
1271         RelOptInfo *local_node;
1272         char       *token;
1273         int                     length;
1274
1275         local_node = makeNode(RelOptInfo);
1276
1277         token = lsptok(NULL, &length);          /* get :relids */
1278         local_node->relids = toIntList(nodeRead(true));         /* now read it */
1279
1280         token = lsptok(NULL, &length);          /* get :rows */
1281         token = lsptok(NULL, &length);          /* now read it */
1282         local_node->rows = atof(token);
1283
1284         token = lsptok(NULL, &length);          /* get :width */
1285         token = lsptok(NULL, &length);          /* now read it */
1286         local_node->width = atoi(token);
1287
1288         token = lsptok(NULL, &length);          /* get :indexed */
1289         token = lsptok(NULL, &length);          /* now read it */
1290
1291         if (!strncmp(token, "true", 4))
1292                 local_node->indexed = true;
1293         else
1294                 local_node->indexed = false;
1295
1296         token = lsptok(NULL, &length);          /* get :pages */
1297         token = lsptok(NULL, &length);          /* now read it */
1298         local_node->pages = atol(token);
1299
1300         token = lsptok(NULL, &length);          /* get :tuples */
1301         token = lsptok(NULL, &length);          /* now read it */
1302         local_node->tuples = atof(token);
1303
1304         token = lsptok(NULL, &length);          /* get :targetlist */
1305         local_node->targetlist = nodeRead(true);        /* now read it */
1306
1307         token = lsptok(NULL, &length);          /* get :pathlist */
1308         local_node->pathlist = nodeRead(true);          /* now read it */
1309
1310         token = lsptok(NULL, &length);          /* get :cheapest_startup_path */
1311         local_node->cheapest_startup_path = nodeRead(true);             /* now read it */
1312
1313         token = lsptok(NULL, &length);          /* get :cheapest_total_path */
1314         local_node->cheapest_total_path = nodeRead(true);               /* now read it */
1315
1316         token = lsptok(NULL, &length);          /* eat :pruneable */
1317         token = lsptok(NULL, &length);          /* get :pruneable */
1318         local_node->pruneable = (token[0] == 't') ? true : false;
1319
1320         token = lsptok(NULL, &length);          /* get :baserestrictinfo */
1321         local_node->baserestrictinfo = nodeRead(true);  /* now read it */
1322
1323         token = lsptok(NULL, &length);          /* get :joininfo */
1324         local_node->joininfo = nodeRead(true);          /* now read it */
1325
1326         token = lsptok(NULL, &length);          /* get :innerjoin */
1327         local_node->innerjoin = nodeRead(true);         /* now read it */
1328
1329         return local_node;
1330 }
1331
1332 /* ----------------
1333  *              _readTargetEntry
1334  * ----------------
1335  */
1336 static TargetEntry *
1337 _readTargetEntry()
1338 {
1339         TargetEntry *local_node;
1340         char       *token;
1341         int                     length;
1342
1343         local_node = makeNode(TargetEntry);
1344
1345         token = lsptok(NULL, &length);          /* get :resdom */
1346         local_node->resdom = nodeRead(true);            /* now read it */
1347
1348         token = lsptok(NULL, &length);          /* get :expr */
1349         local_node->expr = nodeRead(true);      /* now read it */
1350
1351         return local_node;
1352 }
1353
1354 static Attr *
1355 _readAttr()
1356 {
1357         Attr       *local_node;
1358         char       *token;
1359         int                     length;
1360
1361         local_node = makeNode(Attr);
1362
1363         token = lsptok(NULL, &length);          /* eat :relname */
1364         token = lsptok(NULL, &length);          /* get relname */
1365         local_node->relname = debackslash(token, length);
1366
1367         token = lsptok(NULL, &length);          /* eat :attrs */
1368         local_node->attrs = nodeRead(true);     /* now read it */
1369
1370         return local_node;
1371 }
1372
1373 /* ----------------
1374  *              _readRangeTblEntry
1375  * ----------------
1376  */
1377 static RangeTblEntry *
1378 _readRangeTblEntry()
1379 {
1380         RangeTblEntry *local_node;
1381         char       *token;
1382         int                     length;
1383
1384         local_node = makeNode(RangeTblEntry);
1385
1386         token = lsptok(NULL, &length);          /* eat :relname */
1387         token = lsptok(NULL, &length);          /* get :relname */
1388         if (length == 0)
1389                 local_node->relname = NULL;
1390         else
1391                 local_node->relname = debackslash(token, length);
1392
1393         token = lsptok(NULL, &length);          /* eat :ref */
1394         local_node->ref = nodeRead(true);       /* now read it */
1395
1396         token = lsptok(NULL, &length);          /* eat :relid */
1397         token = lsptok(NULL, &length);          /* get :relid */
1398         local_node->relid = strtoul(token, NULL, 10);
1399
1400         token = lsptok(NULL, &length);          /* eat :inh */
1401         token = lsptok(NULL, &length);          /* get :inh */
1402         local_node->inh = (token[0] == 't') ? true : false;
1403
1404         token = lsptok(NULL, &length);          /* eat :inFromCl */
1405         token = lsptok(NULL, &length);          /* get :inFromCl */
1406         local_node->inFromCl = (token[0] == 't') ? true : false;
1407
1408         token = lsptok(NULL, &length);          /* eat :inJoinSet */
1409         token = lsptok(NULL, &length);          /* get :inJoinSet */
1410         local_node->inJoinSet = (token[0] == 't') ? true : false;
1411
1412         token = lsptok(NULL, &length);          /* eat :skipAcl */
1413         token = lsptok(NULL, &length);          /* get :skipAcl */
1414         local_node->skipAcl = (token[0] == 't') ? true : false;
1415
1416         return local_node;
1417 }
1418
1419 static RowMark *
1420 _readRowMark()
1421 {
1422         RowMark    *local_node = makeNode(RowMark);
1423         char       *token;
1424         int                     length;
1425
1426         token = lsptok(NULL, &length);          /* eat :rti */
1427         token = lsptok(NULL, &length);          /* get :rti */
1428         local_node->rti = strtoul(token, NULL, 10);
1429
1430         token = lsptok(NULL, &length);          /* eat :info */
1431         token = lsptok(NULL, &length);          /* get :info */
1432         local_node->info = strtoul(token, NULL, 10);
1433
1434         return local_node;
1435 }
1436
1437 /* ----------------
1438  *              _readPath
1439  *
1440  *      Path is a subclass of Node.
1441  * ----------------
1442  */
1443 static Path *
1444 _readPath()
1445 {
1446         Path       *local_node;
1447         char       *token;
1448         int                     length;
1449
1450         local_node = makeNode(Path);
1451
1452         token = lsptok(NULL, &length);          /* get :pathtype */
1453         token = lsptok(NULL, &length);          /* now read it */
1454         local_node->pathtype = atol(token);
1455
1456         token = lsptok(NULL, &length);          /* get :startup_cost */
1457         token = lsptok(NULL, &length);          /* now read it */
1458         local_node->startup_cost = (Cost) atof(token);
1459
1460         token = lsptok(NULL, &length);          /* get :total_cost */
1461         token = lsptok(NULL, &length);          /* now read it */
1462         local_node->total_cost = (Cost) atof(token);
1463
1464         token = lsptok(NULL, &length);          /* get :pathkeys */
1465         local_node->pathkeys = nodeRead(true);          /* now read it */
1466
1467         return local_node;
1468 }
1469
1470 /* ----------------
1471  *              _readIndexPath
1472  *
1473  *      IndexPath is a subclass of Path.
1474  * ----------------
1475  */
1476 static IndexPath *
1477 _readIndexPath()
1478 {
1479         IndexPath  *local_node;
1480         char       *token;
1481         int                     length;
1482
1483         local_node = makeNode(IndexPath);
1484
1485         token = lsptok(NULL, &length);          /* get :pathtype */
1486         token = lsptok(NULL, &length);          /* now read it */
1487         local_node->path.pathtype = atol(token);
1488
1489         token = lsptok(NULL, &length);          /* get :startup_cost */
1490         token = lsptok(NULL, &length);          /* now read it */
1491         local_node->path.startup_cost = (Cost) atof(token);
1492
1493         token = lsptok(NULL, &length);          /* get :total_cost */
1494         token = lsptok(NULL, &length);          /* now read it */
1495         local_node->path.total_cost = (Cost) atof(token);
1496
1497         token = lsptok(NULL, &length);          /* get :pathkeys */
1498         local_node->path.pathkeys = nodeRead(true); /* now read it */
1499
1500         token = lsptok(NULL, &length);          /* get :indexid */
1501         local_node->indexid = toIntList(nodeRead(true));
1502
1503         token = lsptok(NULL, &length);          /* get :indexqual */
1504         local_node->indexqual = nodeRead(true);         /* now read it */
1505
1506         token = lsptok(NULL, &length);          /* get :indexscandir */
1507         token = lsptok(NULL, &length);          /* now read it */
1508         local_node->indexscandir = (ScanDirection) atoi(token);
1509
1510         token = lsptok(NULL, &length);          /* get :joinrelids */
1511         local_node->joinrelids = toIntList(nodeRead(true));
1512
1513         return local_node;
1514 }
1515
1516 /* ----------------
1517  *              _readTidPath
1518  *
1519  *      TidPath is a subclass of Path.
1520  * ----------------
1521  */
1522 static TidPath *
1523 _readTidPath()
1524 {
1525         TidPath  *local_node;
1526         char       *token;
1527         int                     length;
1528
1529         local_node = makeNode(TidPath);
1530
1531         token = lsptok(NULL, &length);          /* get :pathtype */
1532         token = lsptok(NULL, &length);          /* now read it */
1533         local_node->path.pathtype = atol(token);
1534
1535         token = lsptok(NULL, &length);          /* get :startup_cost */
1536         token = lsptok(NULL, &length);          /* now read it */
1537         local_node->path.startup_cost = (Cost) atof(token);
1538
1539         token = lsptok(NULL, &length);          /* get :total_cost */
1540         token = lsptok(NULL, &length);          /* now read it */
1541         local_node->path.total_cost = (Cost) atof(token);
1542
1543         token = lsptok(NULL, &length);          /* get :pathkeys */
1544         local_node->path.pathkeys = nodeRead(true); /* now read it */
1545
1546         token = lsptok(NULL, &length);          /* get :tideval */
1547         local_node->tideval = nodeRead(true);   /* now read it */
1548
1549         token = lsptok(NULL, &length);          /* get :unjoined_relids */
1550         local_node->unjoined_relids = toIntList(nodeRead(true));
1551
1552         return local_node;
1553 }
1554
1555 /* ----------------
1556  *              _readNestPath
1557  *
1558  *      NestPath is a subclass of Path
1559  * ----------------
1560  */
1561 static NestPath *
1562 _readNestPath()
1563 {
1564         NestPath   *local_node;
1565         char       *token;
1566         int                     length;
1567
1568         local_node = makeNode(NestPath);
1569
1570         token = lsptok(NULL, &length);          /* get :pathtype */
1571         token = lsptok(NULL, &length);          /* now read it */
1572         local_node->path.pathtype = atol(token);
1573
1574         token = lsptok(NULL, &length);          /* get :startup_cost */
1575         token = lsptok(NULL, &length);          /* now read it */
1576         local_node->path.startup_cost = (Cost) atof(token);
1577
1578         token = lsptok(NULL, &length);          /* get :total_cost */
1579         token = lsptok(NULL, &length);          /* now read it */
1580         local_node->path.total_cost = (Cost) atof(token);
1581
1582         token = lsptok(NULL, &length);          /* get :pathkeys */
1583         local_node->path.pathkeys = nodeRead(true); /* now read it */
1584
1585         token = lsptok(NULL, &length);          /* get :outerjoinpath */
1586         local_node->outerjoinpath = nodeRead(true); /* now read it */
1587
1588         token = lsptok(NULL, &length);          /* get :innerjoinpath */
1589         local_node->innerjoinpath = nodeRead(true); /* now read it */
1590
1591         token = lsptok(NULL, &length);          /* get :joinrestrictinfo */
1592         local_node->joinrestrictinfo = nodeRead(true); /* now read it */
1593
1594         return local_node;
1595 }
1596
1597 /* ----------------
1598  *              _readMergePath
1599  *
1600  *      MergePath is a subclass of NestPath.
1601  * ----------------
1602  */
1603 static MergePath *
1604 _readMergePath()
1605 {
1606         MergePath  *local_node;
1607         char       *token;
1608         int                     length;
1609
1610         local_node = makeNode(MergePath);
1611
1612         token = lsptok(NULL, &length);          /* get :pathtype */
1613         token = lsptok(NULL, &length);          /* now read it */
1614         local_node->jpath.path.pathtype = atol(token);
1615
1616         token = lsptok(NULL, &length);          /* get :startup_cost */
1617         token = lsptok(NULL, &length);          /* now read it */
1618         local_node->jpath.path.startup_cost = (Cost) atof(token);
1619
1620         token = lsptok(NULL, &length);          /* get :total_cost */
1621         token = lsptok(NULL, &length);          /* now read it */
1622         local_node->jpath.path.total_cost = (Cost) atof(token);
1623
1624         token = lsptok(NULL, &length);          /* get :pathkeys */
1625         local_node->jpath.path.pathkeys = nodeRead(true);       /* now read it */
1626
1627         token = lsptok(NULL, &length);          /* get :outerjoinpath */
1628         local_node->jpath.outerjoinpath = nodeRead(true); /* now read it */
1629
1630         token = lsptok(NULL, &length);          /* get :innerjoinpath */
1631         local_node->jpath.innerjoinpath = nodeRead(true); /* now read it */
1632
1633         token = lsptok(NULL, &length);          /* get :joinrestrictinfo */
1634         local_node->jpath.joinrestrictinfo = nodeRead(true); /* now read it */
1635
1636         token = lsptok(NULL, &length);          /* get :path_mergeclauses */
1637         local_node->path_mergeclauses = nodeRead(true);         /* now read it */
1638
1639         token = lsptok(NULL, &length);          /* get :outersortkeys */
1640         local_node->outersortkeys = nodeRead(true); /* now read it */
1641
1642         token = lsptok(NULL, &length);          /* get :innersortkeys */
1643         local_node->innersortkeys = nodeRead(true); /* now read it */
1644
1645         return local_node;
1646 }
1647
1648 /* ----------------
1649  *              _readHashPath
1650  *
1651  *      HashPath is a subclass of NestPath.
1652  * ----------------
1653  */
1654 static HashPath *
1655 _readHashPath()
1656 {
1657         HashPath   *local_node;
1658         char       *token;
1659         int                     length;
1660
1661         local_node = makeNode(HashPath);
1662
1663         token = lsptok(NULL, &length);          /* get :pathtype */
1664         token = lsptok(NULL, &length);          /* now read it */
1665         local_node->jpath.path.pathtype = atol(token);
1666
1667         token = lsptok(NULL, &length);          /* get :startup_cost */
1668         token = lsptok(NULL, &length);          /* now read it */
1669         local_node->jpath.path.startup_cost = (Cost) atof(token);
1670
1671         token = lsptok(NULL, &length);          /* get :total_cost */
1672         token = lsptok(NULL, &length);          /* now read it */
1673         local_node->jpath.path.total_cost = (Cost) atof(token);
1674
1675         token = lsptok(NULL, &length);          /* get :pathkeys */
1676         local_node->jpath.path.pathkeys = nodeRead(true);       /* now read it */
1677
1678         token = lsptok(NULL, &length);          /* get :outerjoinpath */
1679         local_node->jpath.outerjoinpath = nodeRead(true); /* now read it */
1680
1681         token = lsptok(NULL, &length);          /* get :innerjoinpath */
1682         local_node->jpath.innerjoinpath = nodeRead(true); /* now read it */
1683
1684         token = lsptok(NULL, &length);          /* get :joinrestrictinfo */
1685         local_node->jpath.joinrestrictinfo = nodeRead(true); /* now read it */
1686
1687         token = lsptok(NULL, &length);          /* get :path_hashclauses */
1688         local_node->path_hashclauses = nodeRead(true);          /* now read it */
1689
1690         return local_node;
1691 }
1692
1693 /* ----------------
1694  *              _readPathKeyItem
1695  *
1696  *      PathKeyItem is a subclass of Node.
1697  * ----------------
1698  */
1699 static PathKeyItem *
1700 _readPathKeyItem()
1701 {
1702         PathKeyItem *local_node;
1703         char       *token;
1704         int                     length;
1705
1706         local_node = makeNode(PathKeyItem);
1707
1708         token = lsptok(NULL, &length);          /* get :sortop */
1709         token = lsptok(NULL, &length);          /* now read it */
1710
1711         local_node->sortop = atol(token);
1712
1713         token = lsptok(NULL, &length);          /* get :key */
1714         local_node->key = nodeRead(true);       /* now read it */
1715
1716         return local_node;
1717 }
1718
1719 /* ----------------
1720  *              _readRestrictInfo
1721  *
1722  *      RestrictInfo is a subclass of Node.
1723  * ----------------
1724  */
1725 static RestrictInfo *
1726 _readRestrictInfo()
1727 {
1728         RestrictInfo *local_node;
1729         char       *token;
1730         int                     length;
1731
1732         local_node = makeNode(RestrictInfo);
1733
1734         token = lsptok(NULL, &length);          /* get :clause */
1735         local_node->clause = nodeRead(true);            /* now read it */
1736
1737         token = lsptok(NULL, &length);          /* get :subclauseindices */
1738         local_node->subclauseindices = nodeRead(true);          /* now read it */
1739
1740         token = lsptok(NULL, &length);          /* get :mergejoinoperator */
1741         token = lsptok(NULL, &length);          /* now read it */
1742         local_node->mergejoinoperator = atol(token);
1743
1744         token = lsptok(NULL, &length);          /* get :left_sortop */
1745         token = lsptok(NULL, &length);          /* now read it */
1746         local_node->left_sortop = atol(token);
1747
1748         token = lsptok(NULL, &length);          /* get :right_sortop */
1749         token = lsptok(NULL, &length);          /* now read it */
1750         local_node->right_sortop = atol(token);
1751
1752         token = lsptok(NULL, &length);          /* get :hashjoinoperator */
1753         token = lsptok(NULL, &length);          /* now read it */
1754         local_node->hashjoinoperator = atol(token);
1755
1756         return local_node;
1757 }
1758
1759 /* ----------------
1760  *              _readJoinInfo()
1761  *
1762  *      JoinInfo is a subclass of Node.
1763  * ----------------
1764  */
1765 static JoinInfo *
1766 _readJoinInfo()
1767 {
1768         JoinInfo   *local_node;
1769         char       *token;
1770         int                     length;
1771
1772         local_node = makeNode(JoinInfo);
1773
1774         token = lsptok(NULL, &length);          /* get :unjoined_relids */
1775         local_node->unjoined_relids = toIntList(nodeRead(true));        /* now read it */
1776
1777         token = lsptok(NULL, &length);          /* get :jinfo_restrictinfo */
1778         local_node->jinfo_restrictinfo = nodeRead(true);        /* now read it */
1779
1780         return local_node;
1781 }
1782
1783 /* ----------------
1784  *              _readIter()
1785  *
1786  * ----------------
1787  */
1788 static Iter *
1789 _readIter()
1790 {
1791         Iter       *local_node;
1792         char       *token;
1793         int                     length;
1794
1795         local_node = makeNode(Iter);
1796
1797         token = lsptok(NULL, &length);          /* eat :iterexpr */
1798         local_node->iterexpr = nodeRead(true);          /* now read it */
1799
1800         return local_node;
1801 }
1802
1803
1804 /* ----------------
1805  *              parsePlanString
1806  *
1807  * Given a character string containing a plan, parsePlanString sets up the
1808  * plan structure representing that plan.
1809  *
1810  * The string to be read must already have been loaded into lsptok().
1811  * ----------------
1812  */
1813 Node *
1814 parsePlanString(void)
1815 {
1816         char       *token;
1817         int                     length;
1818         void       *return_value = NULL;
1819
1820         token = lsptok(NULL, &length);
1821
1822         if (length == 4 && strncmp(token, "PLAN", length) == 0)
1823                 return_value = _readPlan();
1824         else if (length == 6 && strncmp(token, "RESULT", length) == 0)
1825                 return_value = _readResult();
1826         else if (length == 6 && strncmp(token, "APPEND", length) == 0)
1827                 return_value = _readAppend();
1828         else if (length == 4 && strncmp(token, "JOIN", length) == 0)
1829                 return_value = _readJoin();
1830         else if (length == 8 && strncmp(token, "NESTLOOP", length) == 0)
1831                 return_value = _readNestLoop();
1832         else if (length == 9 && strncmp(token, "MERGEJOIN", length) == 0)
1833                 return_value = _readMergeJoin();
1834         else if (length == 8 && strncmp(token, "HASHJOIN", length) == 0)
1835                 return_value = _readHashJoin();
1836         else if (length == 4 && strncmp(token, "SCAN", length) == 0)
1837                 return_value = _readScan();
1838         else if (length == 7 && strncmp(token, "SEQSCAN", length) == 0)
1839                 return_value = _readSeqScan();
1840         else if (length == 9 && strncmp(token, "INDEXSCAN", length) == 0)
1841                 return_value = _readIndexScan();
1842         else if (length == 7 && strncmp(token, "TIDSCAN", length) == 0)
1843                 return_value = _readTidScan();
1844         else if (length == 6 && strncmp(token, "NONAME", length) == 0)
1845                 return_value = _readNoname();
1846         else if (length == 4 && strncmp(token, "SORT", length) == 0)
1847                 return_value = _readSort();
1848         else if (length == 6 && strncmp(token, "AGGREG", length) == 0)
1849                 return_value = _readAggref();
1850         else if (length == 7 && strncmp(token, "SUBLINK", length) == 0)
1851                 return_value = _readSubLink();
1852         else if (length == 11 && strncmp(token, "RELABELTYPE", length) == 0)
1853                 return_value = _readRelabelType();
1854         else if (length == 3 && strncmp(token, "AGG", length) == 0)
1855                 return_value = _readAgg();
1856         else if (length == 4 && strncmp(token, "HASH", length) == 0)
1857                 return_value = _readHash();
1858         else if (length == 6 && strncmp(token, "RESDOM", length) == 0)
1859                 return_value = _readResdom();
1860         else if (length == 4 && strncmp(token, "EXPR", length) == 0)
1861                 return_value = _readExpr();
1862         else if (length == 8 && strncmp(token, "ARRAYREF", length) == 0)
1863                 return_value = _readArrayRef();
1864         else if (length == 5 && strncmp(token, "ARRAY", length) == 0)
1865                 return_value = _readArray();
1866         else if (length == 3 && strncmp(token, "VAR", length) == 0)
1867                 return_value = _readVar();
1868         else if (length == 4 && strncmp(token, "ATTR", length) == 0)
1869                 return_value = _readAttr();
1870         else if (length == 5 && strncmp(token, "CONST", length) == 0)
1871                 return_value = _readConst();
1872         else if (length == 4 && strncmp(token, "FUNC", length) == 0)
1873                 return_value = _readFunc();
1874         else if (length == 4 && strncmp(token, "OPER", length) == 0)
1875                 return_value = _readOper();
1876         else if (length == 5 && strncmp(token, "PARAM", length) == 0)
1877                 return_value = _readParam();
1878         else if (length == 6 && strncmp(token, "ESTATE", length) == 0)
1879                 return_value = _readEState();
1880         else if (length == 10 && strncmp(token, "RELOPTINFO", length) == 0)
1881                 return_value = _readRelOptInfo();
1882         else if (length == 11 && strncmp(token, "TARGETENTRY", length) == 0)
1883                 return_value = _readTargetEntry();
1884         else if (length == 3 && strncmp(token, "RTE", length) == 0)
1885                 return_value = _readRangeTblEntry();
1886         else if (length == 4 && strncmp(token, "PATH", length) == 0)
1887                 return_value = _readPath();
1888         else if (length == 9 && strncmp(token, "INDEXPATH", length) == 0)
1889                 return_value = _readIndexPath();
1890         else if (length == 7 && strncmp(token, "TIDPATH", length) == 0)
1891                 return_value = _readTidPath();
1892         else if (length == 8 && strncmp(token, "NESTPATH", length) == 0)
1893                 return_value = _readNestPath();
1894         else if (length == 9 && strncmp(token, "MERGEPATH", length) == 0)
1895                 return_value = _readMergePath();
1896         else if (length == 8 && strncmp(token, "HASHPATH", length) == 0)
1897                 return_value = _readHashPath();
1898         else if (length == 11 && strncmp(token, "PATHKEYITEM", length) == 0)
1899                 return_value = _readPathKeyItem();
1900         else if (length == 12 && strncmp(token, "RESTRICTINFO", length) == 0)
1901                 return_value = _readRestrictInfo();
1902         else if (length == 8 && strncmp(token, "JOININFO", length) == 0)
1903                 return_value = _readJoinInfo();
1904         else if (length == 4 && strncmp(token, "ITER", length) == 0)
1905                 return_value = _readIter();
1906         else if (length == 5 && strncmp(token, "QUERY", length) == 0)
1907                 return_value = _readQuery();
1908         else if (length == 10 && strncmp(token, "SORTCLAUSE", length) == 0)
1909                 return_value = _readSortClause();
1910         else if (length == 11 && strncmp(token, "GROUPCLAUSE", length) == 0)
1911                 return_value = _readGroupClause();
1912         else if (length == 4 && strncmp(token, "CASE", length) == 0)
1913                 return_value = _readCaseExpr();
1914         else if (length == 4 && strncmp(token, "WHEN", length) == 0)
1915                 return_value = _readCaseWhen();
1916         else if (length == 7 && strncmp(token, "ROWMARK", length) == 0)
1917                 return_value = _readRowMark();
1918         else
1919                 elog(ERROR, "badly formatted planstring \"%.10s\"...\n", token);
1920
1921         return (Node *) return_value;
1922 }
1923
1924 /*------------------------------------------------------------*/
1925
1926 /* ----------------
1927  *              readDatum
1928  *
1929  * given a string representation of the value of the given type,
1930  * create the appropriate Datum
1931  * ----------------
1932  */
1933 static Datum
1934 readDatum(Oid type)
1935 {
1936         int                     length;
1937         int                     tokenLength;
1938         char       *token;
1939         bool            byValue;
1940         Datum           res;
1941         char       *s;
1942         int                     i;
1943
1944         byValue = get_typbyval(type);
1945
1946         /*
1947          * read the actual length of the value
1948          */
1949         token = lsptok(NULL, &tokenLength);
1950         length = atoi(token);
1951         token = lsptok(NULL, &tokenLength); /* skip the '[' */
1952
1953         if (byValue)
1954         {
1955                 if (length > sizeof(Datum))
1956                         elog(ERROR, "readValue: byval & length = %d", length);
1957                 res = (Datum) 0;
1958                 s = (char *) (&res);
1959                 for (i = 0; i < sizeof(Datum); i++)
1960                 {
1961                         token = lsptok(NULL, &tokenLength);
1962                         s[i] = (char) atoi(token);
1963                 }
1964         }
1965         else if (length <= 0)
1966                 res = (Datum) NULL;
1967         else
1968         {
1969                 s = (char *) palloc(length);
1970                 for (i = 0; i < length; i++)
1971                 {
1972                         token = lsptok(NULL, &tokenLength);
1973                         s[i] = (char) atoi(token);
1974                 }
1975                 res = PointerGetDatum(s);
1976         }
1977
1978         token = lsptok(NULL, &tokenLength); /* skip the ']' */
1979         if (token[0] != ']')
1980                 elog(ERROR, "readValue: ']' expected, length =%d", length);
1981
1982         return res;
1983 }