1 /*-------------------------------------------------------------------------
4 * Reader functions for Postgres tree nodes.
6 * Copyright (c) 1994, Regents of the University of California
10 * $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.75 1999/11/23 20:06:53 momjian Exp $
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.
23 *-------------------------------------------------------------------------
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"
38 * node creator declarations
42 static Datum readDatum(Oid type);
51 /* ugly manipulation, should probably free the Value node too */
52 lfirst(l) = (void *) intVal(lfirst(l));
68 local_node = makeNode(Query);
70 token = lsptok(NULL, &length); /* skip the :command */
71 token = lsptok(NULL, &length); /* get the commandType */
72 local_node->commandType = atoi(token);
74 token = lsptok(NULL, &length); /* skip :utility */
75 /* we can't get create or index here, can we? */
77 token = lsptok(NULL, &length); /* get the notify name if any */
79 local_node->utilityStmt = NULL;
82 NotifyStmt *n = makeNode(NotifyStmt);
84 n->relname = palloc(length + 1);
85 StrNCpy(n->relname, token, length + 1);
86 local_node->utilityStmt = (Node *) n;
89 token = lsptok(NULL, &length); /* skip the :resultRelation */
90 token = lsptok(NULL, &length); /* get the resultRelation */
91 local_node->resultRelation = atoi(token);
93 token = lsptok(NULL, &length); /* skip :into */
94 token = lsptok(NULL, &length); /* get into */
96 local_node->into = NULL;
99 local_node->into = palloc(length + 1);
100 StrNCpy(local_node->into, token, length + 1);
103 token = lsptok(NULL, &length); /* skip :isPortal */
104 token = lsptok(NULL, &length); /* get isPortal */
105 local_node->isPortal = (token[0] == 't') ? true : false;
107 token = lsptok(NULL, &length); /* skip :isBinary */
108 token = lsptok(NULL, &length); /* get isBinary */
109 local_node->isBinary = (token[0] == 't') ? true : false;
111 token = lsptok(NULL, &length); /* skip :isTemp */
112 token = lsptok(NULL, &length); /* get isTemp */
113 local_node->isTemp = (token[0] == 't') ? true : false;
115 token = lsptok(NULL, &length); /* skip :unionall */
116 token = lsptok(NULL, &length); /* get unionall */
117 local_node->unionall = (token[0] == 't') ? true : false;
119 token = lsptok(NULL, &length); /* skip :uniqueFlag */
120 token = lsptok(NULL, &length); /* get uniqueFlag */
122 local_node->uniqueFlag = NULL;
125 local_node->uniqueFlag = palloc(length + 1);
126 StrNCpy(local_node->uniqueFlag, token, length + 1);
129 token = lsptok(NULL, &length); /* skip :sortClause */
130 local_node->sortClause = nodeRead(true);
132 token = lsptok(NULL, &length); /* skip :rtable */
133 local_node->rtable = nodeRead(true);
135 token = lsptok(NULL, &length); /* skip :targetlist */
136 local_node->targetList = nodeRead(true);
138 token = lsptok(NULL, &length); /* skip :qual */
139 local_node->qual = nodeRead(true);
141 token = lsptok(NULL, &length); /* skip :groupClause */
142 local_node->groupClause = nodeRead(true);
144 token = lsptok(NULL, &length); /* skip :havingQual */
145 local_node->havingQual = nodeRead(true);
147 token = lsptok(NULL, &length); /* skip the :hasAggs */
148 token = lsptok(NULL, &length); /* get hasAggs */
149 local_node->hasAggs = (token[0] == 't') ? true : false;
151 token = lsptok(NULL, &length); /* skip the :hasSubLinks */
152 token = lsptok(NULL, &length); /* get hasSubLinks */
153 local_node->hasSubLinks = (token[0] == 't') ? true : false;
155 token = lsptok(NULL, &length); /* skip :unionClause */
156 local_node->unionClause = nodeRead(true);
158 token = lsptok(NULL, &length); /* skip :intersectClause */
159 local_node->intersectClause = nodeRead(true);
162 token = lsptok(NULL, &length); /* skip :limitOffset */
163 local_node->limitOffset = nodeRead(true);
165 token = lsptok(NULL, &length); /* skip :limitCount */
166 local_node->limitCount = nodeRead(true);
168 token = lsptok(NULL, &length); /* skip :rowMark */
169 local_node->rowMark = nodeRead(true);
181 SortClause *local_node;
185 local_node = makeNode(SortClause);
187 token = lsptok(NULL, &length); /* skip :tleSortGroupRef */
188 token = lsptok(NULL, &length); /* get tleSortGroupRef */
189 local_node->tleSortGroupRef = strtoul(token, NULL, 10);
191 token = lsptok(NULL, &length); /* skip :sortop */
192 token = lsptok(NULL, &length); /* get sortop */
193 local_node->sortop = strtoul(token, NULL, 10);
205 GroupClause *local_node;
209 local_node = makeNode(GroupClause);
211 token = lsptok(NULL, &length); /* skip :tleSortGroupRef */
212 token = lsptok(NULL, &length); /* get tleSortGroupRef */
213 local_node->tleSortGroupRef = strtoul(token, NULL, 10);
215 token = lsptok(NULL, &length); /* skip :sortop */
216 token = lsptok(NULL, &length); /* get sortop */
217 local_node->sortop = strtoul(token, NULL, 10);
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);
236 token = lsptok(NULL, &length); /* skip the :size */
237 token = lsptok(NULL, &length); /* get the plan_size */
238 node->plan_size = atoi(token);
240 token = lsptok(NULL, &length); /* skip the :width */
241 token = lsptok(NULL, &length); /* get the plan_width */
242 node->plan_width = atoi(token);
244 token = lsptok(NULL, &length); /* eat the :state stuff */
245 token = lsptok(NULL, &length); /* now get the state */
248 node->state = (EState *) NULL;
250 { /* Disgusting hack until I figure out what
252 node->state = (EState *) !NULL;
255 token = lsptok(NULL, &length); /* eat :qptargetlist */
256 node->targetlist = nodeRead(true);
258 token = lsptok(NULL, &length); /* eat :qpqual */
259 node->qual = nodeRead(true);
261 token = lsptok(NULL, &length); /* eat :lefttree */
262 node->lefttree = (Plan *) nodeRead(true);
264 token = lsptok(NULL, &length); /* eat :righttree */
265 node->righttree = (Plan *) nodeRead(true);
271 * Stuff from plannodes.h
283 local_node = makeNode(Plan);
285 _getPlan(local_node);
293 * Does some obscene, possibly unportable, magic with
304 local_node = makeNode(Result);
306 _getPlan((Plan *) local_node);
308 token = lsptok(NULL, &length); /* eat :resconstantqual */
309 local_node->resconstantqual = nodeRead(true); /* now read it */
317 * Append is a subclass of Plan.
328 local_node = makeNode(Append);
330 _getPlan((Plan *) local_node);
332 token = lsptok(NULL, &length); /* eat :appendplans */
333 local_node->appendplans = nodeRead(true); /* now read it */
335 token = lsptok(NULL, &length); /* eat :unionrtables */
336 local_node->unionrtables = nodeRead(true); /* now read it */
338 token = lsptok(NULL, &length); /* eat :inheritrelid */
339 token = lsptok(NULL, &length); /* get inheritrelid */
340 local_node->inheritrelid = strtoul(token, NULL, 10);
342 token = lsptok(NULL, &length); /* eat :inheritrtable */
343 local_node->inheritrtable = nodeRead(true); /* now read it */
351 * In case Join is not the same structure as Plan someday.
357 _getPlan((Plan *) node);
364 * Join is a subclass of Plan
372 local_node = makeNode(Join);
374 _getJoin(local_node);
382 * NestLoop is a subclass of Join
389 NestLoop *local_node;
391 local_node = makeNode(NestLoop);
393 _getJoin((Join *) local_node);
401 * MergeJoin is a subclass of Join
407 MergeJoin *local_node;
411 local_node = makeNode(MergeJoin);
413 _getJoin((Join *) local_node);
414 token = lsptok(NULL, &length); /* eat :mergeclauses */
415 local_node->mergeclauses = nodeRead(true); /* now read it */
423 * HashJoin is a subclass of Join.
429 HashJoin *local_node;
433 local_node = makeNode(HashJoin);
435 _getJoin((Join *) local_node);
437 token = lsptok(NULL, &length); /* eat :hashclauses */
438 local_node->hashclauses = nodeRead(true); /* now read it */
440 token = lsptok(NULL, &length); /* eat :hashjoinop */
441 token = lsptok(NULL, &length); /* get hashjoinop */
442 local_node->hashjoinop = strtoul(token, NULL, 10);
444 token = lsptok(NULL, &length); /* eat :hashdone */
445 token = lsptok(NULL, &length); /* eat hashdone */
446 local_node->hashdone = false;
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.)
458 * Scan gets its own get function since stuff inherits it.
467 _getPlan((Plan *) node);
469 token = lsptok(NULL, &length); /* eat :scanrelid */
470 token = lsptok(NULL, &length); /* get scanrelid */
471 node->scanrelid = strtoul(token, NULL, 10);
477 * Scan is a subclass of Plan (Not Node, see above).
485 local_node = makeNode(Scan);
487 _getScan(local_node);
495 * SeqScan is a subclass of Scan
503 local_node = makeNode(SeqScan);
505 _getScan((Scan *) local_node);
513 * IndexScan is a subclass of Scan
519 IndexScan *local_node;
523 local_node = makeNode(IndexScan);
525 _getScan((Scan *) local_node);
527 token = lsptok(NULL, &length); /* eat :indxid */
528 local_node->indxid = toIntList(nodeRead(true)); /* now read it */
530 token = lsptok(NULL, &length); /* eat :indxqual */
531 local_node->indxqual = nodeRead(true); /* now read it */
533 token = lsptok(NULL, &length); /* eat :indxqualorig */
534 local_node->indxqualorig = nodeRead(true); /* now read it */
536 token = lsptok(NULL, &length); /* eat :indxorderdir */
537 token = lsptok(NULL, &length); /* get indxorderdir */
539 local_node->indxorderdir = atoi(token);
547 * TidScan is a subclass of Scan
557 local_node = makeNode(TidScan);
559 _getScan((Scan *) local_node);
561 token = lsptok(NULL, &length); /* eat :needrescan */
562 token = lsptok(NULL, &length); /* get needrescan */
563 local_node->needRescan = atoi(token);
565 token = lsptok(NULL, &length); /* eat :tideval */
566 local_node->tideval = nodeRead(true); /* now read it */
574 * Noname is a subclass of Plan
584 local_node = makeNode(Noname);
586 _getPlan((Plan *) local_node);
588 token = lsptok(NULL, &length); /* eat :nonameid */
589 token = lsptok(NULL, &length); /* get nonameid */
590 local_node->nonameid = atol(token);
592 token = lsptok(NULL, &length); /* eat :keycount */
593 token = lsptok(NULL, &length); /* get keycount */
594 local_node->keycount = atoi(token);
602 * Sort is a subclass of Noname
612 local_node = makeNode(Sort);
614 _getPlan((Plan *) local_node);
616 token = lsptok(NULL, &length); /* eat :nonameid */
617 token = lsptok(NULL, &length); /* get nonameid */
618 local_node->nonameid = atol(token);
620 token = lsptok(NULL, &length); /* eat :keycount */
621 token = lsptok(NULL, &length); /* get keycount */
622 local_node->keycount = atoi(token);
632 local_node = makeNode(Agg);
633 _getPlan((Plan *) local_node);
641 * For some reason, unique is a subclass of Noname.
650 local_node = makeNode(Unique);
652 _getPlan((Plan *) local_node);
654 token = lsptok(NULL, &length); /* eat :nonameid */
655 token = lsptok(NULL, &length); /* get :nonameid */
656 local_node->nonameid = atol(token);
658 token = lsptok(NULL, &length); /* eat :keycount */
659 token = lsptok(NULL, &length); /* get :keycount */
660 local_node->keycount = atoi(token);
668 * Hash is a subclass of Noname
678 local_node = makeNode(Hash);
680 _getPlan((Plan *) local_node);
682 token = lsptok(NULL, &length); /* eat :hashkey */
683 local_node->hashkey = (Var *) nodeRead(true);
689 * Stuff from primnodes.h.
695 * Resdom is a subclass of Node
705 local_node = makeNode(Resdom);
707 token = lsptok(NULL, &length); /* eat :resno */
708 token = lsptok(NULL, &length); /* get resno */
709 local_node->resno = atoi(token);
711 token = lsptok(NULL, &length); /* eat :restype */
712 token = lsptok(NULL, &length); /* get restype */
713 local_node->restype = atol(token);
715 token = lsptok(NULL, &length); /* eat :restypmod */
716 token = lsptok(NULL, &length); /* get restypmod */
717 local_node->restypmod = atoi(token);
719 token = lsptok(NULL, &length); /* eat :resname */
720 token = lsptok(NULL, &length); /* get the name */
723 local_node->resname = NULL;
726 local_node->resname = (char *) palloc(length + 1);
727 StrNCpy(local_node->resname, token + 1, length + 1 - 2); /* strip quotes */
730 token = lsptok(NULL, &length); /* eat :reskey */
731 token = lsptok(NULL, &length); /* get reskey */
732 local_node->reskey = strtoul(token, NULL, 10);
734 token = lsptok(NULL, &length); /* eat :reskeyop */
735 token = lsptok(NULL, &length); /* get reskeyop */
736 local_node->reskeyop = (Oid) atol(token);
738 token = lsptok(NULL, &length); /* eat :ressortgroupref */
739 token = lsptok(NULL, &length); /* get ressortgroupref */
740 local_node->ressortgroupref = strtoul(token, NULL, 10);
742 token = lsptok(NULL, &length); /* eat :resjunk */
743 token = lsptok(NULL, &length); /* get resjunk */
744 local_node->resjunk = (token[0] == 't') ? true : false;
752 * Expr is a subclass of Node
762 local_node = makeNode(Expr);
764 token = lsptok(NULL, &length); /* eat :typeOid */
765 token = lsptok(NULL, &length); /* get typeOid */
766 local_node->typeOid = (Oid) atol(token);
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;
783 token = lsptok(NULL, &length); /* eat :oper */
784 local_node->oper = nodeRead(true);
786 token = lsptok(NULL, &length); /* eat :args */
787 local_node->args = nodeRead(true); /* now read it */
795 * CaseExpr is a subclass of Node
801 CaseExpr *local_node;
805 local_node = makeNode(CaseExpr);
807 local_node->args = nodeRead(true);
808 token = lsptok(NULL, &length); /* eat :default */
809 local_node->defresult = nodeRead(true);
817 * CaseWhen is a subclass of Node
823 CaseWhen *local_node;
827 local_node = makeNode(CaseWhen);
829 local_node->expr = nodeRead(true);
830 token = lsptok(NULL, &length); /* eat :then */
831 local_node->result = nodeRead(true);
839 * Var is a subclass of Expr
849 local_node = makeNode(Var);
851 token = lsptok(NULL, &length); /* eat :varno */
852 token = lsptok(NULL, &length); /* get varno */
853 local_node->varno = strtoul(token, NULL, 10);
855 token = lsptok(NULL, &length); /* eat :varattno */
856 token = lsptok(NULL, &length); /* get varattno */
857 local_node->varattno = atoi(token);
859 token = lsptok(NULL, &length); /* eat :vartype */
860 token = lsptok(NULL, &length); /* get vartype */
861 local_node->vartype = (Oid) atol(token);
863 token = lsptok(NULL, &length); /* eat :vartypmod */
864 token = lsptok(NULL, &length); /* get vartypmod */
865 local_node->vartypmod = atoi(token);
867 token = lsptok(NULL, &length); /* eat :varlevelsup */
868 token = lsptok(NULL, &length); /* get varlevelsup */
869 local_node->varlevelsup = (Oid) atol(token);
871 token = lsptok(NULL, &length); /* eat :varnoold */
872 token = lsptok(NULL, &length); /* get varnoold */
873 local_node->varnoold = (Oid) atol(token);
875 token = lsptok(NULL, &length); /* eat :varoattno */
876 token = lsptok(NULL, &length); /* eat :varoattno */
877 local_node->varoattno = (int) atol(token);
885 * Array is a subclass of Expr
895 local_node = makeNode(Array);
897 token = lsptok(NULL, &length); /* eat :arrayelemtype */
898 token = lsptok(NULL, &length); /* get arrayelemtype */
899 local_node->arrayelemtype = strtoul(token, NULL, 10);
901 token = lsptok(NULL, &length); /* eat :arrayelemlength */
902 token = lsptok(NULL, &length); /* get arrayelemlength */
903 local_node->arrayelemlength = atoi(token);
905 token = lsptok(NULL, &length); /* eat :arrayelembyval */
906 token = lsptok(NULL, &length); /* get arrayelembyval */
907 local_node->arrayelembyval = (token[0] == 't') ? true : false;
909 token = lsptok(NULL, &length); /* eat :arraylow */
910 token = lsptok(NULL, &length); /* get arraylow */
911 local_node->arraylow.indx[0] = atoi(token);
913 token = lsptok(NULL, &length); /* eat :arrayhigh */
914 token = lsptok(NULL, &length); /* get arrayhigh */
915 local_node->arrayhigh.indx[0] = atoi(token);
917 token = lsptok(NULL, &length); /* eat :arraylen */
918 token = lsptok(NULL, &length); /* get arraylen */
919 local_node->arraylen = atoi(token);
927 * ArrayRef is a subclass of Expr
933 ArrayRef *local_node;
937 local_node = makeNode(ArrayRef);
939 token = lsptok(NULL, &length); /* eat :refelemtype */
940 token = lsptok(NULL, &length); /* get refelemtype */
941 local_node->refelemtype = strtoul(token, NULL, 10);
943 token = lsptok(NULL, &length); /* eat :refattrlength */
944 token = lsptok(NULL, &length); /* get refattrlength */
945 local_node->refattrlength = atoi(token);
947 token = lsptok(NULL, &length); /* eat :refelemlength */
948 token = lsptok(NULL, &length); /* get refelemlength */
949 local_node->refelemlength = atoi(token);
951 token = lsptok(NULL, &length); /* eat :refelembyval */
952 token = lsptok(NULL, &length); /* get refelembyval */
953 local_node->refelembyval = (token[0] == 't') ? true : false;
955 token = lsptok(NULL, &length); /* eat :refupperindex */
956 local_node->refupperindexpr = nodeRead(true);
958 token = lsptok(NULL, &length); /* eat :reflowerindex */
959 local_node->reflowerindexpr = nodeRead(true);
961 token = lsptok(NULL, &length); /* eat :refexpr */
962 local_node->refexpr = nodeRead(true);
964 token = lsptok(NULL, &length); /* eat :refassgnexpr */
965 local_node->refassgnexpr = nodeRead(true);
973 * Const is a subclass of Expr
983 local_node = makeNode(Const);
985 token = lsptok(NULL, &length); /* get :consttype */
986 token = lsptok(NULL, &length); /* now read it */
987 local_node->consttype = atol(token);
990 token = lsptok(NULL, &length); /* get :constlen */
991 token = lsptok(NULL, &length); /* now read it */
992 local_node->constlen = strtol(token, NULL, 10);
994 token = lsptok(NULL, &length); /* get :constisnull */
995 token = lsptok(NULL, &length); /* now read it */
997 if (!strncmp(token, "true", 4))
998 local_node->constisnull = true;
1000 local_node->constisnull = false;
1003 token = lsptok(NULL, &length); /* get :constvalue */
1005 if (local_node->constisnull)
1007 token = lsptok(NULL, &length); /* skip "NIL" */
1015 local_node->constvalue = readDatum(local_node->consttype);
1018 token = lsptok(NULL, &length); /* get :constbyval */
1019 token = lsptok(NULL, &length); /* now read it */
1021 if (!strncmp(token, "true", 4))
1022 local_node->constbyval = true;
1024 local_node->constbyval = false;
1032 * Func is a subclass of Expr
1042 local_node = makeNode(Func);
1044 token = lsptok(NULL, &length); /* get :funcid */
1045 token = lsptok(NULL, &length); /* now read it */
1046 local_node->funcid = atol(token);
1048 token = lsptok(NULL, &length); /* get :functype */
1049 token = lsptok(NULL, &length); /* now read it */
1050 local_node->functype = atol(token);
1052 token = lsptok(NULL, &length); /* get :funcisindex */
1053 token = lsptok(NULL, &length); /* now read it */
1055 if (!strncmp(token, "true", 4))
1056 local_node->funcisindex = true;
1058 local_node->funcisindex = false;
1060 token = lsptok(NULL, &length); /* get :funcsize */
1061 token = lsptok(NULL, &length); /* now read it */
1062 local_node->funcsize = atol(token);
1064 token = lsptok(NULL, &length); /* get :func_fcache */
1065 token = lsptok(NULL, &length); /* get @ */
1066 token = lsptok(NULL, &length); /* now read it */
1068 local_node->func_fcache = (FunctionCache *) NULL;
1070 token = lsptok(NULL, &length); /* get :func_tlist */
1071 local_node->func_tlist = nodeRead(true); /* now read it */
1073 token = lsptok(NULL, &length); /* get :func_planlist */
1074 local_node->func_planlist = nodeRead(true); /* now read it */
1082 * Oper is a subclass of Expr
1092 local_node = makeNode(Oper);
1094 token = lsptok(NULL, &length); /* get :opno */
1095 token = lsptok(NULL, &length); /* now read it */
1096 local_node->opno = atol(token);
1098 token = lsptok(NULL, &length); /* get :opid */
1099 token = lsptok(NULL, &length); /* now read it */
1100 local_node->opid = atol(token);
1102 token = lsptok(NULL, &length); /* get :opresulttype */
1103 token = lsptok(NULL, &length); /* now read it */
1104 local_node->opresulttype = atol(token);
1107 * NOTE: Alternatively we can call 'replace_opid' which initializes
1108 * both 'opid' and 'op_fcache'.
1110 local_node->op_fcache = (FunctionCache *) NULL;
1118 * Param is a subclass of Expr
1128 local_node = makeNode(Param);
1130 token = lsptok(NULL, &length); /* get :paramkind */
1131 token = lsptok(NULL, &length); /* now read it */
1132 local_node->paramkind = atoi(token);
1134 token = lsptok(NULL, &length); /* get :paramid */
1135 token = lsptok(NULL, &length); /* now read it */
1136 local_node->paramid = atol(token);
1138 token = lsptok(NULL, &length); /* get :paramname */
1139 token = lsptok(NULL, &length); /* now read it */
1141 local_node->paramname = NULL;
1144 local_node->paramname = (char *) palloc(length + 1);
1145 StrNCpy(local_node->paramname, token, length + 1);
1148 token = lsptok(NULL, &length); /* get :paramtype */
1149 token = lsptok(NULL, &length); /* now read it */
1151 local_node->paramtype = atol(token);
1152 token = lsptok(NULL, &length); /* get :param_tlist */
1153 local_node->param_tlist = nodeRead(true); /* now read it */
1161 * Aggref is a subclass of Node
1171 local_node = makeNode(Aggref);
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);
1178 token = lsptok(NULL, &length); /* eat :basetype */
1179 token = lsptok(NULL, &length); /* get basetype */
1180 local_node->basetype = (Oid) atol(token);
1182 token = lsptok(NULL, &length); /* eat :aggtype */
1183 token = lsptok(NULL, &length); /* get aggtype */
1184 local_node->aggtype = (Oid) atol(token);
1186 token = lsptok(NULL, &length); /* eat :target */
1187 local_node->target = nodeRead(true); /* now read it */
1189 token = lsptok(NULL, &length); /* eat :usenulls */
1190 token = lsptok(NULL, &length); /* get usenulls */
1191 local_node->usenulls = (token[0] == 't') ? true : false;
1199 * SubLink is a subclass of Node
1205 SubLink *local_node;
1209 local_node = makeNode(SubLink);
1211 token = lsptok(NULL, &length); /* eat :subLinkType */
1212 token = lsptok(NULL, &length); /* get subLinkType */
1213 local_node->subLinkType = atoi(token);
1215 token = lsptok(NULL, &length); /* eat :useor */
1216 token = lsptok(NULL, &length); /* get useor */
1217 local_node->useor = (token[0] == 't') ? true : false;
1219 token = lsptok(NULL, &length); /* eat :lefthand */
1220 local_node->lefthand = nodeRead(true); /* now read it */
1222 token = lsptok(NULL, &length); /* eat :oper */
1223 local_node->oper = nodeRead(true); /* now read it */
1225 token = lsptok(NULL, &length); /* eat :subselect */
1226 local_node->subselect = nodeRead(true); /* now read it */
1232 * Stuff from execnodes.h
1238 * EState is a subclass of Node.
1248 local_node = makeNode(EState);
1250 token = lsptok(NULL, &length); /* get :direction */
1251 token = lsptok(NULL, &length); /* now read it */
1253 local_node->es_direction = atoi(token);
1255 token = lsptok(NULL, &length); /* get :range_table */
1257 local_node->es_range_table = nodeRead(true); /* now read it */
1259 token = lsptok(NULL, &length); /* get :result_relation_info */
1260 token = lsptok(NULL, &length); /* get @ */
1261 token = lsptok(NULL, &length); /* now read it */
1263 sscanf(token, "%x", (unsigned int *) &local_node->es_result_relation_info);
1269 * Stuff from relation.h
1279 RelOptInfo *local_node;
1283 local_node = makeNode(RelOptInfo);
1285 token = lsptok(NULL, &length); /* get :relids */
1286 local_node->relids = toIntList(nodeRead(true)); /* now read it */
1288 token = lsptok(NULL, &length); /* get :indexed */
1289 token = lsptok(NULL, &length); /* now read it */
1291 if (!strncmp(token, "true", 4))
1292 local_node->indexed = true;
1294 local_node->indexed = false;
1296 token = lsptok(NULL, &length); /* get :pages */
1297 token = lsptok(NULL, &length); /* now read it */
1298 local_node->pages = (unsigned int) atoi(token);
1300 token = lsptok(NULL, &length); /* get :tuples */
1301 token = lsptok(NULL, &length); /* now read it */
1302 local_node->tuples = (unsigned int) atoi(token);
1304 token = lsptok(NULL, &length); /* get :size */
1305 token = lsptok(NULL, &length); /* now read it */
1306 local_node->size = (unsigned int) atoi(token);
1308 token = lsptok(NULL, &length); /* get :width */
1309 token = lsptok(NULL, &length); /* now read it */
1310 local_node->width = (unsigned int) atoi(token);
1312 token = lsptok(NULL, &length); /* get :targetlist */
1313 local_node->targetlist = nodeRead(true); /* now read it */
1315 token = lsptok(NULL, &length); /* get :pathlist */
1316 local_node->pathlist = nodeRead(true); /* now read it */
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.
1324 token = lsptok(NULL, &length); /* get :cheapestpath */
1325 token = lsptok(NULL, &length); /* get @ */
1326 token = lsptok(NULL, &length); /* now read it */
1328 sscanf(token, "%x", (unsigned int *) &local_node->cheapestpath);
1331 token = lsptok(NULL, &length); /* get :restrictinfo */
1332 local_node->restrictinfo = nodeRead(true); /* now read it */
1334 token = lsptok(NULL, &length); /* get :joininfo */
1335 local_node->joininfo = nodeRead(true); /* now read it */
1337 token = lsptok(NULL, &length); /* get :innerjoin */
1338 local_node->innerjoin = nodeRead(true); /* now read it */
1347 static TargetEntry *
1350 TargetEntry *local_node;
1354 local_node = makeNode(TargetEntry);
1356 token = lsptok(NULL, &length); /* get :resdom */
1357 local_node->resdom = nodeRead(true); /* now read it */
1359 token = lsptok(NULL, &length); /* get :expr */
1360 local_node->expr = nodeRead(true); /* now read it */
1366 * _readRangeTblEntry
1369 static RangeTblEntry *
1370 _readRangeTblEntry()
1372 RangeTblEntry *local_node;
1376 local_node = makeNode(RangeTblEntry);
1378 token = lsptok(NULL, &length); /* eat :relname */
1379 token = lsptok(NULL, &length); /* get :relname */
1381 local_node->relname = NULL;
1384 local_node->relname = (char *) palloc(length + 1);
1385 StrNCpy(local_node->relname, token, length + 1);
1388 token = lsptok(NULL, &length); /* eat :refname */
1389 token = lsptok(NULL, &length); /* get :refname */
1391 local_node->refname = NULL;
1394 local_node->refname = (char *) palloc(length + 1);
1395 StrNCpy(local_node->refname, token, length + 1);
1398 token = lsptok(NULL, &length); /* eat :relid */
1399 token = lsptok(NULL, &length); /* get :relid */
1400 local_node->relid = strtoul(token, NULL, 10);
1402 token = lsptok(NULL, &length); /* eat :inh */
1403 token = lsptok(NULL, &length); /* get :inh */
1404 local_node->inh = (token[0] == 't') ? true : false;
1406 token = lsptok(NULL, &length); /* eat :inFromCl */
1407 token = lsptok(NULL, &length); /* get :inFromCl */
1408 local_node->inFromCl = (token[0] == 't') ? true : false;
1410 token = lsptok(NULL, &length); /* eat :inJoinSet */
1411 token = lsptok(NULL, &length); /* get :inJoinSet */
1412 local_node->inJoinSet = (token[0] == 't') ? true : false;
1414 token = lsptok(NULL, &length); /* eat :skipAcl */
1415 token = lsptok(NULL, &length); /* get :skipAcl */
1416 local_node->skipAcl = (token[0] == 't') ? true : false;
1424 RowMark *local_node = makeNode(RowMark);
1428 token = lsptok(NULL, &length); /* eat :rti */
1429 token = lsptok(NULL, &length); /* get :rti */
1430 local_node->rti = strtoul(token, NULL, 10);
1432 token = lsptok(NULL, &length); /* eat :info */
1433 token = lsptok(NULL, &length); /* get :info */
1434 local_node->info = strtoul(token, NULL, 10);
1442 * Path is a subclass of Node.
1452 local_node = makeNode(Path);
1454 token = lsptok(NULL, &length); /* get :pathtype */
1455 token = lsptok(NULL, &length); /* now read it */
1456 local_node->pathtype = atol(token);
1458 token = lsptok(NULL, &length); /* get :cost */
1459 token = lsptok(NULL, &length); /* now read it */
1460 local_node->path_cost = (Cost) atof(token);
1462 token = lsptok(NULL, &length); /* get :pathkeys */
1463 local_node->pathkeys = nodeRead(true); /* now read it */
1471 * IndexPath is a subclass of Path.
1477 IndexPath *local_node;
1481 local_node = makeNode(IndexPath);
1483 token = lsptok(NULL, &length); /* get :pathtype */
1484 token = lsptok(NULL, &length); /* now read it */
1485 local_node->path.pathtype = atol(token);
1487 token = lsptok(NULL, &length); /* get :cost */
1488 token = lsptok(NULL, &length); /* now read it */
1489 local_node->path.path_cost = (Cost) atof(token);
1491 token = lsptok(NULL, &length); /* get :pathkeys */
1492 local_node->path.pathkeys = nodeRead(true); /* now read it */
1494 token = lsptok(NULL, &length); /* get :indexid */
1495 local_node->indexid = toIntList(nodeRead(true));
1497 token = lsptok(NULL, &length); /* get :indexqual */
1498 local_node->indexqual = nodeRead(true); /* now read it */
1500 token = lsptok(NULL, &length); /* get :joinrelids */
1501 local_node->joinrelids = toIntList(nodeRead(true));
1509 * TidPath is a subclass of Path.
1515 TidPath *local_node;
1519 local_node = makeNode(TidPath);
1521 token = lsptok(NULL, &length); /* get :pathtype */
1522 token = lsptok(NULL, &length); /* now read it */
1523 local_node->path.pathtype = atol(token);
1525 token = lsptok(NULL, &length); /* get :cost */
1526 token = lsptok(NULL, &length); /* now read it */
1527 local_node->path.path_cost = (Cost) atof(token);
1529 token = lsptok(NULL, &length); /* get :pathkeys */
1530 local_node->path.pathkeys = nodeRead(true); /* now read it */
1532 token = lsptok(NULL, &length); /* get :tideval */
1533 local_node->tideval = nodeRead(true); /* now read it */
1535 token = lsptok(NULL, &length); /* get :unjoined_relids */
1536 local_node->unjoined_relids = toIntList(nodeRead(true));
1544 * NestPath is a subclass of Path
1550 NestPath *local_node;
1554 local_node = makeNode(NestPath);
1556 token = lsptok(NULL, &length); /* get :pathtype */
1557 token = lsptok(NULL, &length); /* now read it */
1558 local_node->path.pathtype = atol(token);
1560 token = lsptok(NULL, &length); /* get :cost */
1561 token = lsptok(NULL, &length); /* now read it */
1562 local_node->path.path_cost = (Cost) atof(token);
1564 token = lsptok(NULL, &length); /* get :pathkeys */
1565 local_node->path.pathkeys = nodeRead(true); /* now read it */
1567 token = lsptok(NULL, &length); /* get :pathinfo */
1568 local_node->pathinfo = nodeRead(true); /* now read it */
1571 * Not sure if these are nodes; they're declared as "struct path *".
1572 * For now, i'll just print the addresses.
1574 * GJK: Since I am parsing this stuff, I'll just ignore the addresses,
1575 * and initialize these pointers to NULL.
1578 token = lsptok(NULL, &length); /* get :outerjoinpath */
1579 token = lsptok(NULL, &length); /* get @ */
1580 token = lsptok(NULL, &length); /* now read it */
1582 local_node->outerjoinpath = NULL;
1584 token = lsptok(NULL, &length); /* get :innerjoinpath */
1585 token = lsptok(NULL, &length); /* get @ */
1586 token = lsptok(NULL, &length); /* now read it */
1588 local_node->innerjoinpath = NULL;
1596 * MergePath is a subclass of NestPath.
1602 MergePath *local_node;
1606 local_node = makeNode(MergePath);
1608 token = lsptok(NULL, &length); /* get :pathtype */
1609 token = lsptok(NULL, &length); /* now read it */
1611 local_node->jpath.path.pathtype = atol(token);
1613 token = lsptok(NULL, &length); /* get :cost */
1614 token = lsptok(NULL, &length); /* now read it */
1616 local_node->jpath.path.path_cost = (Cost) atof(token);
1618 token = lsptok(NULL, &length); /* get :pathkeys */
1619 local_node->jpath.path.pathkeys = nodeRead(true); /* now read it */
1621 token = lsptok(NULL, &length); /* get :pathinfo */
1622 local_node->jpath.pathinfo = nodeRead(true); /* now read it */
1625 * Not sure if these are nodes; they're declared as "struct path *".
1626 * For now, i'll just print the addresses.
1628 * GJK: Since I am parsing this stuff, I'll just ignore the addresses,
1629 * and initialize these pointers to NULL.
1632 token = lsptok(NULL, &length); /* get :outerjoinpath */
1633 token = lsptok(NULL, &length); /* get @ */
1634 token = lsptok(NULL, &length); /* now read it */
1636 local_node->jpath.outerjoinpath = NULL;
1638 token = lsptok(NULL, &length); /* get :innerjoinpath */
1639 token = lsptok(NULL, &length); /* get @ */
1640 token = lsptok(NULL, &length); /* now read it */
1642 local_node->jpath.innerjoinpath = NULL;
1644 token = lsptok(NULL, &length); /* get :path_mergeclauses */
1645 local_node->path_mergeclauses = nodeRead(true); /* now read it */
1647 token = lsptok(NULL, &length); /* get :outersortkeys */
1648 local_node->outersortkeys = nodeRead(true); /* now read it */
1650 token = lsptok(NULL, &length); /* get :innersortkeys */
1651 local_node->innersortkeys = nodeRead(true); /* now read it */
1659 * HashPath is a subclass of NestPath.
1665 HashPath *local_node;
1669 local_node = makeNode(HashPath);
1671 token = lsptok(NULL, &length); /* get :pathtype */
1672 token = lsptok(NULL, &length); /* now read it */
1674 local_node->jpath.path.pathtype = atol(token);
1676 token = lsptok(NULL, &length); /* get :cost */
1677 token = lsptok(NULL, &length); /* now read it */
1679 local_node->jpath.path.path_cost = (Cost) atof(token);
1681 token = lsptok(NULL, &length); /* get :pathkeys */
1682 local_node->jpath.path.pathkeys = nodeRead(true); /* now read it */
1684 token = lsptok(NULL, &length); /* get :pathinfo */
1685 local_node->jpath.pathinfo = nodeRead(true); /* now read it */
1688 * Not sure if these are nodes; they're declared as "struct path *".
1689 * For now, i'll just print the addresses.
1691 * GJK: Since I am parsing this stuff, I'll just ignore the addresses,
1692 * and initialize these pointers to NULL.
1695 token = lsptok(NULL, &length); /* get :outerjoinpath */
1696 token = lsptok(NULL, &length); /* get @ */
1697 token = lsptok(NULL, &length); /* now read it */
1699 local_node->jpath.outerjoinpath = NULL;
1701 token = lsptok(NULL, &length); /* get :innerjoinpath */
1702 token = lsptok(NULL, &length); /* get @ */
1703 token = lsptok(NULL, &length); /* now read it */
1705 local_node->jpath.innerjoinpath = NULL;
1707 token = lsptok(NULL, &length); /* get :path_hashclauses */
1708 local_node->path_hashclauses = nodeRead(true); /* now read it */
1716 * PathKeyItem is a subclass of Node.
1719 static PathKeyItem *
1722 PathKeyItem *local_node;
1726 local_node = makeNode(PathKeyItem);
1728 token = lsptok(NULL, &length); /* get :sortop */
1729 token = lsptok(NULL, &length); /* now read it */
1731 local_node->sortop = atol(token);
1733 token = lsptok(NULL, &length); /* get :key */
1734 local_node->key = nodeRead(true); /* now read it */
1742 * RestrictInfo is a subclass of Node.
1745 static RestrictInfo *
1748 RestrictInfo *local_node;
1752 local_node = makeNode(RestrictInfo);
1754 token = lsptok(NULL, &length); /* get :clause */
1755 local_node->clause = nodeRead(true); /* now read it */
1757 token = lsptok(NULL, &length); /* get :selectivity */
1758 token = lsptok(NULL, &length); /* now read it */
1759 local_node->selectivity = atof(token);
1761 token = lsptok(NULL, &length); /* get :subclauseindices */
1762 local_node->subclauseindices = nodeRead(true); /* now read it */
1764 token = lsptok(NULL, &length); /* get :mergejoinoperator */
1765 token = lsptok(NULL, &length); /* now read it */
1766 local_node->mergejoinoperator = atol(token);
1768 token = lsptok(NULL, &length); /* get :left_sortop */
1769 token = lsptok(NULL, &length); /* now read it */
1770 local_node->left_sortop = atol(token);
1772 token = lsptok(NULL, &length); /* get :right_sortop */
1773 token = lsptok(NULL, &length); /* now read it */
1774 local_node->right_sortop = atol(token);
1776 token = lsptok(NULL, &length); /* get :hashjoinoperator */
1777 token = lsptok(NULL, &length); /* now read it */
1778 local_node->hashjoinoperator = atol(token);
1786 * JoinInfo is a subclass of Node.
1792 JoinInfo *local_node;
1796 local_node = makeNode(JoinInfo);
1798 token = lsptok(NULL, &length); /* get :unjoined_relids */
1799 local_node->unjoined_relids = toIntList(nodeRead(true)); /* now read it */
1801 token = lsptok(NULL, &length); /* get :jinfo_restrictinfo */
1802 local_node->jinfo_restrictinfo = nodeRead(true); /* now read it */
1819 local_node = makeNode(Iter);
1821 token = lsptok(NULL, &length); /* eat :iterexpr */
1822 local_node->iterexpr = nodeRead(true); /* now read it */
1831 * Given a character string containing a plan, parsePlanString sets up the
1832 * plan structure representing that plan.
1834 * The string passed to parsePlanString must be null-terminated.
1838 parsePlanString(void)
1842 void *return_value = NULL;
1844 token = lsptok(NULL, &length);
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();
1941 elog(ERROR, "badly formatted planstring \"%.10s\"...\n", token);
1943 return (Node *) return_value;
1946 /*------------------------------------------------------------*/
1951 * given a string representation of the value of the given type,
1952 * create the appropriate Datum
1966 byValue = get_typbyval(type);
1969 * read the actual length of the value
1971 token = lsptok(NULL, &tokenLength);
1972 length = atoi(token);
1973 token = lsptok(NULL, &tokenLength); /* skip the '[' */
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++)
1982 token = lsptok(NULL, &tokenLength);
1983 s[i] = (char) atoi(token);
1986 else if (length <= 0)
1988 else if (length >= 1)
1990 s = (char *) palloc(length);
1992 for (i = 0; i < length; i++)
1994 token = lsptok(NULL, &tokenLength);
1995 s[i] = (char) atoi(token);
1997 res = PointerGetDatum(s);
2000 token = lsptok(NULL, &tokenLength); /* skip the ']' */
2001 if (token[0] != ']')
2002 elog(ERROR, "readValue: ']' expected, length =%d", length);