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