OSDN Git Service

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