1 /*-------------------------------------------------------------------------
4 * Reader functions for Postgres tree nodes.
6 * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.131 2002/08/31 22:10:43 tgl Exp $
14 * Most of the read functions for plan nodes are tested. (In fact, they
15 * pass the regression test as of 11/8/94.) The rest (for path selection)
16 * are probably never used. No effort has been made to get them to work.
17 * The simplest way to test these functions is by doing the following in
18 * ProcessQuery (before executing the plan):
19 * plan = stringToNode(nodeToString(plan));
20 * Then, run the regression test. Let's just say you'll notice if either
21 * of the above function are not properly done.
24 *-------------------------------------------------------------------------
30 #include "nodes/plannodes.h"
31 #include "nodes/readfuncs.h"
32 #include "nodes/relation.h"
36 * NOTE: use atoi() to read values written with %d, or atoui() to read
37 * values written with %u in outfuncs.c. An exception is OID values,
38 * for which use atooid(). (As of 7.1, outfuncs.c writes OIDs as %u,
39 * but this will probably change in the future.)
41 #define atoui(x) ((unsigned int) strtoul((x), NULL, 10))
43 #define atooid(x) ((Oid) strtoul((x), NULL, 10))
45 #define strtobool(x) ((*(x) == 't') ? true : false)
47 #define nullable_string(token,length) \
48 ((length) == 0 ? (char *) NULL : debackslash(token, length))
51 static Datum readDatum(bool typbyval);
55 * node creator declarations
59 /* Convert Value list returned by nodeRead into list of integers */
67 Value *v = (Value *) lfirst(l);
70 elog(ERROR, "toIntList: unexpected datatype");
71 lfirsti(l) = intVal(v);
77 /* Convert Value list returned by nodeRead into list of OIDs */
85 Value *v = (Value *) lfirst(l);
88 * This is a bit tricky because OID is unsigned, and so nodeRead
89 * might have concluded the value doesn't fit in an integer. Must
90 * cope with T_Float as well.
94 lfirsti(l) = (Oid) intVal(v);
97 else if (IsA(v, Float))
99 lfirsti(l) = atooid(strVal(v));
104 elog(ERROR, "toOidList: unexpected datatype");
120 local_node = makeNode(Query);
122 token = pg_strtok(&length); /* skip :command */
123 token = pg_strtok(&length); /* get commandType */
124 local_node->commandType = atoi(token);
126 token = pg_strtok(&length); /* skip :utility */
127 local_node->utilityStmt = nodeRead(true);
129 token = pg_strtok(&length); /* skip :resultRelation */
130 token = pg_strtok(&length); /* get the resultRelation */
131 local_node->resultRelation = atoi(token);
133 token = pg_strtok(&length); /* skip :into */
134 local_node->into = nodeRead(true);
136 token = pg_strtok(&length); /* skip :isPortal */
137 token = pg_strtok(&length); /* get isPortal */
138 local_node->isPortal = strtobool(token);
140 token = pg_strtok(&length); /* skip :isBinary */
141 token = pg_strtok(&length); /* get isBinary */
142 local_node->isBinary = strtobool(token);
144 token = pg_strtok(&length); /* skip the :hasAggs */
145 token = pg_strtok(&length); /* get hasAggs */
146 local_node->hasAggs = strtobool(token);
148 token = pg_strtok(&length); /* skip the :hasSubLinks */
149 token = pg_strtok(&length); /* get hasSubLinks */
150 local_node->hasSubLinks = strtobool(token);
152 /* we always want originalQuery to be false in a read-in query */
153 local_node->originalQuery = false;
155 token = pg_strtok(&length); /* skip :rtable */
156 local_node->rtable = nodeRead(true);
158 token = pg_strtok(&length); /* skip :jointree */
159 local_node->jointree = nodeRead(true);
161 token = pg_strtok(&length); /* skip :rowMarks */
162 local_node->rowMarks = toIntList(nodeRead(true));
164 token = pg_strtok(&length); /* skip :targetlist */
165 local_node->targetList = nodeRead(true);
167 token = pg_strtok(&length); /* skip :groupClause */
168 local_node->groupClause = nodeRead(true);
170 token = pg_strtok(&length); /* skip :havingQual */
171 local_node->havingQual = nodeRead(true);
173 token = pg_strtok(&length); /* skip :distinctClause */
174 local_node->distinctClause = nodeRead(true);
176 token = pg_strtok(&length); /* skip :sortClause */
177 local_node->sortClause = nodeRead(true);
179 token = pg_strtok(&length); /* skip :limitOffset */
180 local_node->limitOffset = nodeRead(true);
182 token = pg_strtok(&length); /* skip :limitCount */
183 local_node->limitCount = nodeRead(true);
185 token = pg_strtok(&length); /* skip :setOperations */
186 local_node->setOperations = nodeRead(true);
188 token = pg_strtok(&length); /* skip :resultRelations */
189 local_node->resultRelations = toIntList(nodeRead(true));
199 _readNotifyStmt(void)
201 NotifyStmt *local_node;
205 local_node = makeNode(NotifyStmt);
207 token = pg_strtok(&length); /* skip :relation */
208 local_node->relation = nodeRead(true);
218 _readSortClause(void)
220 SortClause *local_node;
224 local_node = makeNode(SortClause);
226 token = pg_strtok(&length); /* skip :tleSortGroupRef */
227 token = pg_strtok(&length); /* get tleSortGroupRef */
228 local_node->tleSortGroupRef = atoui(token);
230 token = pg_strtok(&length); /* skip :sortop */
231 token = pg_strtok(&length); /* get sortop */
232 local_node->sortop = atooid(token);
242 _readGroupClause(void)
244 GroupClause *local_node;
248 local_node = makeNode(GroupClause);
250 token = pg_strtok(&length); /* skip :tleSortGroupRef */
251 token = pg_strtok(&length); /* get tleSortGroupRef */
252 local_node->tleSortGroupRef = atoui(token);
254 token = pg_strtok(&length); /* skip :sortop */
255 token = pg_strtok(&length); /* get sortop */
256 local_node->sortop = atooid(token);
262 * _readSetOperationStmt
265 static SetOperationStmt *
266 _readSetOperationStmt(void)
268 SetOperationStmt *local_node;
272 local_node = makeNode(SetOperationStmt);
274 token = pg_strtok(&length); /* eat :op */
275 token = pg_strtok(&length); /* get op */
276 local_node->op = (SetOperation) atoi(token);
278 token = pg_strtok(&length); /* eat :all */
279 token = pg_strtok(&length); /* get all */
280 local_node->all = strtobool(token);
282 token = pg_strtok(&length); /* eat :larg */
283 local_node->larg = nodeRead(true); /* get larg */
285 token = pg_strtok(&length); /* eat :rarg */
286 local_node->rarg = nodeRead(true); /* get rarg */
288 token = pg_strtok(&length); /* eat :colTypes */
289 local_node->colTypes = toOidList(nodeRead(true));
304 token = pg_strtok(&length); /* first token is :startup_cost */
305 token = pg_strtok(&length); /* next is the actual cost */
306 node->startup_cost = (Cost) atof(token);
308 token = pg_strtok(&length); /* skip the :total_cost */
309 token = pg_strtok(&length); /* next is the actual cost */
310 node->total_cost = (Cost) atof(token);
312 token = pg_strtok(&length); /* skip the :rows */
313 token = pg_strtok(&length); /* get the plan_rows */
314 node->plan_rows = atof(token);
316 token = pg_strtok(&length); /* skip the :width */
317 token = pg_strtok(&length); /* get the plan_width */
318 node->plan_width = atoi(token);
320 token = pg_strtok(&length); /* eat :qptargetlist */
321 node->targetlist = nodeRead(true);
323 token = pg_strtok(&length); /* eat :qpqual */
324 node->qual = nodeRead(true);
326 token = pg_strtok(&length); /* eat :lefttree */
327 node->lefttree = (Plan *) nodeRead(true);
329 token = pg_strtok(&length); /* eat :righttree */
330 node->righttree = (Plan *) nodeRead(true);
332 node->state = (EState *) NULL; /* never read in */
338 * Stuff from plannodes.h
350 local_node = makeNode(Plan);
352 _getPlan(local_node);
368 local_node = makeNode(Result);
370 _getPlan((Plan *) local_node);
372 token = pg_strtok(&length); /* eat :resconstantqual */
373 local_node->resconstantqual = nodeRead(true); /* now read it */
381 * Append is a subclass of Plan.
392 local_node = makeNode(Append);
394 _getPlan((Plan *) local_node);
396 token = pg_strtok(&length); /* eat :appendplans */
397 local_node->appendplans = nodeRead(true); /* now read it */
399 token = pg_strtok(&length); /* eat :isTarget */
400 token = pg_strtok(&length); /* get isTarget */
401 local_node->isTarget = strtobool(token);
416 _getPlan((Plan *) node);
418 token = pg_strtok(&length); /* skip the :jointype */
419 token = pg_strtok(&length); /* get the jointype */
420 node->jointype = (JoinType) atoi(token);
422 token = pg_strtok(&length); /* skip the :joinqual */
423 node->joinqual = nodeRead(true); /* get the joinqual */
430 * Join is a subclass of Plan
438 local_node = makeNode(Join);
440 _getJoin(local_node);
448 * NestLoop is a subclass of Join
455 NestLoop *local_node;
457 local_node = makeNode(NestLoop);
459 _getJoin((Join *) local_node);
467 * MergeJoin is a subclass of Join
473 MergeJoin *local_node;
477 local_node = makeNode(MergeJoin);
479 _getJoin((Join *) local_node);
481 token = pg_strtok(&length); /* eat :mergeclauses */
482 local_node->mergeclauses = nodeRead(true); /* now read it */
490 * HashJoin is a subclass of Join.
496 HashJoin *local_node;
500 local_node = makeNode(HashJoin);
502 _getJoin((Join *) local_node);
504 token = pg_strtok(&length); /* eat :hashclauses */
505 local_node->hashclauses = nodeRead(true); /* now read it */
507 token = pg_strtok(&length); /* eat :hashjoinop */
508 token = pg_strtok(&length); /* get hashjoinop */
509 local_node->hashjoinop = atooid(token);
517 * Scan is a subclass of Plan.
519 * Scan gets its own get function since stuff inherits it.
528 _getPlan((Plan *) node);
530 token = pg_strtok(&length); /* eat :scanrelid */
531 token = pg_strtok(&length); /* get scanrelid */
532 node->scanrelid = atoui(token);
538 * Scan is a subclass of Plan.
546 local_node = makeNode(Scan);
548 _getScan(local_node);
556 * SeqScan is a subclass of Scan
564 local_node = makeNode(SeqScan);
566 _getScan((Scan *) local_node);
574 * IndexScan is a subclass of Scan
580 IndexScan *local_node;
584 local_node = makeNode(IndexScan);
586 _getScan((Scan *) local_node);
588 token = pg_strtok(&length); /* eat :indxid */
589 local_node->indxid = toOidList(nodeRead(true)); /* now read it */
591 token = pg_strtok(&length); /* eat :indxqual */
592 local_node->indxqual = nodeRead(true); /* now read it */
594 token = pg_strtok(&length); /* eat :indxqualorig */
595 local_node->indxqualorig = nodeRead(true); /* now read it */
597 token = pg_strtok(&length); /* eat :indxorderdir */
598 token = pg_strtok(&length); /* get indxorderdir */
599 local_node->indxorderdir = atoi(token);
607 * TidScan is a subclass of Scan
617 local_node = makeNode(TidScan);
619 _getScan((Scan *) local_node);
621 token = pg_strtok(&length); /* eat :needrescan */
622 token = pg_strtok(&length); /* get needrescan */
623 local_node->needRescan = atoi(token);
625 token = pg_strtok(&length); /* eat :tideval */
626 local_node->tideval = nodeRead(true); /* now read it */
634 * SubqueryScan is a subclass of Scan
637 static SubqueryScan *
638 _readSubqueryScan(void)
640 SubqueryScan *local_node;
644 local_node = makeNode(SubqueryScan);
646 _getScan((Scan *) local_node);
648 token = pg_strtok(&length); /* eat :subplan */
649 local_node->subplan = nodeRead(true); /* now read it */
657 * FunctionScan is a subclass of Scan
660 static FunctionScan *
661 _readFunctionScan(void)
663 FunctionScan *local_node;
665 local_node = makeNode(FunctionScan);
667 _getScan((Scan *) local_node);
675 * Sort is a subclass of Plan
685 local_node = makeNode(Sort);
687 _getPlan((Plan *) local_node);
689 token = pg_strtok(&length); /* eat :keycount */
690 token = pg_strtok(&length); /* get keycount */
691 local_node->keycount = atoi(token);
701 local_node = makeNode(Agg);
702 _getPlan((Plan *) local_node);
710 * Hash is a subclass of Plan
720 local_node = makeNode(Hash);
722 _getPlan((Plan *) local_node);
724 token = pg_strtok(&length); /* eat :hashkey */
725 local_node->hashkey = nodeRead(true);
731 * Stuff from primnodes.h.
737 * Resdom is a subclass of Node
747 local_node = makeNode(Resdom);
749 token = pg_strtok(&length); /* eat :resno */
750 token = pg_strtok(&length); /* get resno */
751 local_node->resno = atoi(token);
753 token = pg_strtok(&length); /* eat :restype */
754 token = pg_strtok(&length); /* get restype */
755 local_node->restype = atooid(token);
757 token = pg_strtok(&length); /* eat :restypmod */
758 token = pg_strtok(&length); /* get restypmod */
759 local_node->restypmod = atoi(token);
761 token = pg_strtok(&length); /* eat :resname */
762 token = pg_strtok(&length); /* get the name */
763 local_node->resname = nullable_string(token, length);
765 token = pg_strtok(&length); /* eat :reskey */
766 token = pg_strtok(&length); /* get reskey */
767 local_node->reskey = atoui(token);
769 token = pg_strtok(&length); /* eat :reskeyop */
770 token = pg_strtok(&length); /* get reskeyop */
771 local_node->reskeyop = atooid(token);
773 token = pg_strtok(&length); /* eat :ressortgroupref */
774 token = pg_strtok(&length); /* get ressortgroupref */
775 local_node->ressortgroupref = atoui(token);
777 token = pg_strtok(&length); /* eat :resjunk */
778 token = pg_strtok(&length); /* get resjunk */
779 local_node->resjunk = strtobool(token);
787 * Expr is a subclass of Node
797 local_node = makeNode(Expr);
799 token = pg_strtok(&length); /* eat :typeOid */
800 token = pg_strtok(&length); /* get typeOid */
801 local_node->typeOid = atooid(token);
803 token = pg_strtok(&length); /* eat :opType */
804 token = pg_strtok(&length); /* get opType */
805 if (strncmp(token, "op", 2) == 0)
806 local_node->opType = OP_EXPR;
807 else if (strncmp(token, "distinct", 8) == 0)
808 local_node->opType = DISTINCT_EXPR;
809 else if (strncmp(token, "func", 4) == 0)
810 local_node->opType = FUNC_EXPR;
811 else if (strncmp(token, "or", 2) == 0)
812 local_node->opType = OR_EXPR;
813 else if (strncmp(token, "and", 3) == 0)
814 local_node->opType = AND_EXPR;
815 else if (strncmp(token, "not", 3) == 0)
816 local_node->opType = NOT_EXPR;
817 else if (strncmp(token, "subp", 4) == 0)
818 local_node->opType = SUBPLAN_EXPR;
820 elog(ERROR, "_readExpr: unknown opType \"%.*s\"", length, token);
822 token = pg_strtok(&length); /* eat :oper */
823 local_node->oper = nodeRead(true);
825 token = pg_strtok(&length); /* eat :args */
826 local_node->args = nodeRead(true); /* now read it */
834 * CaseExpr is a subclass of Node
840 CaseExpr *local_node;
844 local_node = makeNode(CaseExpr);
846 token = pg_strtok(&length); /* eat :casetype */
847 token = pg_strtok(&length); /* get casetype */
848 local_node->casetype = atooid(token);
850 token = pg_strtok(&length); /* eat :arg */
851 local_node->arg = nodeRead(true);
853 token = pg_strtok(&length); /* eat :args */
854 local_node->args = nodeRead(true);
856 token = pg_strtok(&length); /* eat :defresult */
857 local_node->defresult = nodeRead(true);
865 * CaseWhen is a subclass of Node
871 CaseWhen *local_node;
875 local_node = makeNode(CaseWhen);
877 local_node->expr = nodeRead(true);
878 token = pg_strtok(&length); /* eat :then */
879 local_node->result = nodeRead(true);
887 * NullTest is a subclass of Node
893 NullTest *local_node;
897 local_node = makeNode(NullTest);
899 token = pg_strtok(&length); /* eat :arg */
900 local_node->arg = nodeRead(true); /* now read it */
902 token = pg_strtok(&length); /* eat :nulltesttype */
903 token = pg_strtok(&length); /* get nulltesttype */
904 local_node->nulltesttype = (NullTestType) atoi(token);
912 * BooleanTest is a subclass of Node
916 _readBooleanTest(void)
918 BooleanTest *local_node;
922 local_node = makeNode(BooleanTest);
924 token = pg_strtok(&length); /* eat :arg */
925 local_node->arg = nodeRead(true); /* now read it */
927 token = pg_strtok(&length); /* eat :booltesttype */
928 token = pg_strtok(&length); /* get booltesttype */
929 local_node->booltesttype = (BoolTestType) atoi(token);
935 * _readConstraintTest
937 * ConstraintTest is a subclass of Node
940 static ConstraintTest *
941 _readConstraintTest(void)
943 ConstraintTest *local_node;
947 local_node = makeNode(ConstraintTest);
949 token = pg_strtok(&length); /* eat :arg */
950 local_node->arg = nodeRead(true); /* now read it */
952 token = pg_strtok(&length); /* eat :testtype */
953 token = pg_strtok(&length); /* get testtype */
954 local_node->testtype = (ConstraintTestType) atoi(token);
956 token = pg_strtok(&length); /* get :name */
957 token = pg_strtok(&length); /* now read it */
958 local_node->name = nullable_string(token, length);
960 token = pg_strtok(&length); /* eat :check_expr */
961 local_node->check_expr = nodeRead(true); /* now read it */
969 * Var is a subclass of Expr
979 local_node = makeNode(Var);
981 token = pg_strtok(&length); /* eat :varno */
982 token = pg_strtok(&length); /* get varno */
983 local_node->varno = atoui(token);
985 token = pg_strtok(&length); /* eat :varattno */
986 token = pg_strtok(&length); /* get varattno */
987 local_node->varattno = atoi(token);
989 token = pg_strtok(&length); /* eat :vartype */
990 token = pg_strtok(&length); /* get vartype */
991 local_node->vartype = atooid(token);
993 token = pg_strtok(&length); /* eat :vartypmod */
994 token = pg_strtok(&length); /* get vartypmod */
995 local_node->vartypmod = atoi(token);
997 token = pg_strtok(&length); /* eat :varlevelsup */
998 token = pg_strtok(&length); /* get varlevelsup */
999 local_node->varlevelsup = atoui(token);
1001 token = pg_strtok(&length); /* eat :varnoold */
1002 token = pg_strtok(&length); /* get varnoold */
1003 local_node->varnoold = atoui(token);
1005 token = pg_strtok(&length); /* eat :varoattno */
1006 token = pg_strtok(&length); /* eat :varoattno */
1007 local_node->varoattno = atoi(token);
1015 * ArrayRef is a subclass of Expr
1021 ArrayRef *local_node;
1025 local_node = makeNode(ArrayRef);
1027 token = pg_strtok(&length); /* eat :refrestype */
1028 token = pg_strtok(&length); /* get refrestype */
1029 local_node->refrestype = atooid(token);
1031 token = pg_strtok(&length); /* eat :refattrlength */
1032 token = pg_strtok(&length); /* get refattrlength */
1033 local_node->refattrlength = atoi(token);
1035 token = pg_strtok(&length); /* eat :refelemlength */
1036 token = pg_strtok(&length); /* get refelemlength */
1037 local_node->refelemlength = atoi(token);
1039 token = pg_strtok(&length); /* eat :refelembyval */
1040 token = pg_strtok(&length); /* get refelembyval */
1041 local_node->refelembyval = strtobool(token);
1043 token = pg_strtok(&length); /* eat :refelemalign */
1044 token = pg_strtok(&length); /* get refelemalign */
1045 local_node->refelemalign = token[0];
1047 token = pg_strtok(&length); /* eat :refupperindexpr */
1048 local_node->refupperindexpr = nodeRead(true);
1050 token = pg_strtok(&length); /* eat :reflowerindexpr */
1051 local_node->reflowerindexpr = nodeRead(true);
1053 token = pg_strtok(&length); /* eat :refexpr */
1054 local_node->refexpr = nodeRead(true);
1056 token = pg_strtok(&length); /* eat :refassgnexpr */
1057 local_node->refassgnexpr = nodeRead(true);
1065 * Const is a subclass of Expr
1075 local_node = makeNode(Const);
1077 token = pg_strtok(&length); /* get :consttype */
1078 token = pg_strtok(&length); /* now read it */
1079 local_node->consttype = atooid(token);
1081 token = pg_strtok(&length); /* get :constlen */
1082 token = pg_strtok(&length); /* now read it */
1083 local_node->constlen = atoi(token);
1085 token = pg_strtok(&length); /* get :constbyval */
1086 token = pg_strtok(&length); /* now read it */
1087 local_node->constbyval = strtobool(token);
1089 token = pg_strtok(&length); /* get :constisnull */
1090 token = pg_strtok(&length); /* now read it */
1091 local_node->constisnull = strtobool(token);
1093 token = pg_strtok(&length); /* get :constvalue */
1095 if (local_node->constisnull)
1097 token = pg_strtok(&length); /* skip "NIL" */
1100 local_node->constvalue = readDatum(local_node->constbyval);
1108 * Func is a subclass of Expr
1118 local_node = makeNode(Func);
1120 token = pg_strtok(&length); /* get :funcid */
1121 token = pg_strtok(&length); /* now read it */
1122 local_node->funcid = atooid(token);
1124 token = pg_strtok(&length); /* get :funcresulttype */
1125 token = pg_strtok(&length); /* now read it */
1126 local_node->funcresulttype = atooid(token);
1128 token = pg_strtok(&length); /* get :funcretset */
1129 token = pg_strtok(&length); /* now read it */
1130 local_node->funcretset = strtobool(token);
1132 local_node->func_fcache = NULL;
1140 * Oper is a subclass of Expr
1150 local_node = makeNode(Oper);
1152 token = pg_strtok(&length); /* get :opno */
1153 token = pg_strtok(&length); /* now read it */
1154 local_node->opno = atooid(token);
1156 token = pg_strtok(&length); /* get :opid */
1157 token = pg_strtok(&length); /* now read it */
1158 local_node->opid = atooid(token);
1160 token = pg_strtok(&length); /* get :opresulttype */
1161 token = pg_strtok(&length); /* now read it */
1162 local_node->opresulttype = atooid(token);
1164 token = pg_strtok(&length); /* get :opretset */
1165 token = pg_strtok(&length); /* now read it */
1166 local_node->opretset = strtobool(token);
1168 local_node->op_fcache = NULL;
1176 * Param is a subclass of Expr
1186 local_node = makeNode(Param);
1188 token = pg_strtok(&length); /* get :paramkind */
1189 token = pg_strtok(&length); /* now read it */
1190 local_node->paramkind = atoi(token);
1192 token = pg_strtok(&length); /* get :paramid */
1193 token = pg_strtok(&length); /* now read it */
1194 local_node->paramid = atoi(token);
1196 token = pg_strtok(&length); /* get :paramname */
1197 token = pg_strtok(&length); /* now read it */
1198 local_node->paramname = nullable_string(token, length);
1200 token = pg_strtok(&length); /* get :paramtype */
1201 token = pg_strtok(&length); /* now read it */
1202 local_node->paramtype = atooid(token);
1210 * Aggref is a subclass of Node
1220 local_node = makeNode(Aggref);
1222 token = pg_strtok(&length); /* eat :aggfnoid */
1223 token = pg_strtok(&length); /* get aggfnoid */
1224 local_node->aggfnoid = atooid(token);
1226 token = pg_strtok(&length); /* eat :aggtype */
1227 token = pg_strtok(&length); /* get aggtype */
1228 local_node->aggtype = atooid(token);
1230 token = pg_strtok(&length); /* eat :target */
1231 local_node->target = nodeRead(true); /* now read it */
1233 token = pg_strtok(&length); /* eat :aggstar */
1234 token = pg_strtok(&length); /* get aggstar */
1235 local_node->aggstar = strtobool(token);
1237 token = pg_strtok(&length); /* eat :aggdistinct */
1238 token = pg_strtok(&length); /* get aggdistinct */
1239 local_node->aggdistinct = strtobool(token);
1247 * SubLink is a subclass of Node
1253 SubLink *local_node;
1257 local_node = makeNode(SubLink);
1259 token = pg_strtok(&length); /* eat :subLinkType */
1260 token = pg_strtok(&length); /* get subLinkType */
1261 local_node->subLinkType = atoi(token);
1263 token = pg_strtok(&length); /* eat :useor */
1264 token = pg_strtok(&length); /* get useor */
1265 local_node->useor = strtobool(token);
1267 token = pg_strtok(&length); /* eat :lefthand */
1268 local_node->lefthand = nodeRead(true); /* now read it */
1270 token = pg_strtok(&length); /* eat :oper */
1271 local_node->oper = nodeRead(true); /* now read it */
1273 token = pg_strtok(&length); /* eat :subselect */
1274 local_node->subselect = nodeRead(true); /* now read it */
1282 * FieldSelect is a subclass of Node
1285 static FieldSelect *
1286 _readFieldSelect(void)
1288 FieldSelect *local_node;
1292 local_node = makeNode(FieldSelect);
1294 token = pg_strtok(&length); /* eat :arg */
1295 local_node->arg = nodeRead(true); /* now read it */
1297 token = pg_strtok(&length); /* eat :fieldnum */
1298 token = pg_strtok(&length); /* get fieldnum */
1299 local_node->fieldnum = (AttrNumber) atoi(token);
1301 token = pg_strtok(&length); /* eat :resulttype */
1302 token = pg_strtok(&length); /* get resulttype */
1303 local_node->resulttype = atooid(token);
1305 token = pg_strtok(&length); /* eat :resulttypmod */
1306 token = pg_strtok(&length); /* get resulttypmod */
1307 local_node->resulttypmod = atoi(token);
1315 * RelabelType is a subclass of Node
1318 static RelabelType *
1319 _readRelabelType(void)
1321 RelabelType *local_node;
1325 local_node = makeNode(RelabelType);
1327 token = pg_strtok(&length); /* eat :arg */
1328 local_node->arg = nodeRead(true); /* now read it */
1330 token = pg_strtok(&length); /* eat :resulttype */
1331 token = pg_strtok(&length); /* get resulttype */
1332 local_node->resulttype = atooid(token);
1334 token = pg_strtok(&length); /* eat :resulttypmod */
1335 token = pg_strtok(&length); /* get resulttypmod */
1336 local_node->resulttypmod = atoi(token);
1344 * RangeTblRef is a subclass of Node
1347 static RangeTblRef *
1348 _readRangeTblRef(void)
1350 RangeTblRef *local_node;
1354 local_node = makeNode(RangeTblRef);
1356 token = pg_strtok(&length); /* get rtindex */
1357 local_node->rtindex = atoi(token);
1365 * FromExpr is a subclass of Node
1371 FromExpr *local_node;
1375 local_node = makeNode(FromExpr);
1377 token = pg_strtok(&length); /* eat :fromlist */
1378 local_node->fromlist = nodeRead(true); /* now read it */
1380 token = pg_strtok(&length); /* eat :quals */
1381 local_node->quals = nodeRead(true); /* now read it */
1389 * JoinExpr is a subclass of Node
1395 JoinExpr *local_node;
1399 local_node = makeNode(JoinExpr);
1401 token = pg_strtok(&length); /* eat :jointype */
1402 token = pg_strtok(&length); /* get jointype */
1403 local_node->jointype = (JoinType) atoi(token);
1405 token = pg_strtok(&length); /* eat :isNatural */
1406 token = pg_strtok(&length); /* get isNatural */
1407 local_node->isNatural = strtobool(token);
1409 token = pg_strtok(&length); /* eat :larg */
1410 local_node->larg = nodeRead(true); /* now read it */
1412 token = pg_strtok(&length); /* eat :rarg */
1413 local_node->rarg = nodeRead(true); /* now read it */
1415 token = pg_strtok(&length); /* eat :using */
1416 local_node->using = nodeRead(true); /* now read it */
1418 token = pg_strtok(&length); /* eat :quals */
1419 local_node->quals = nodeRead(true); /* now read it */
1421 token = pg_strtok(&length); /* eat :alias */
1422 local_node->alias = nodeRead(true); /* now read it */
1424 token = pg_strtok(&length); /* eat :rtindex */
1425 token = pg_strtok(&length); /* get rtindex */
1426 local_node->rtindex = atoi(token);
1435 static TargetEntry *
1436 _readTargetEntry(void)
1438 TargetEntry *local_node;
1442 local_node = makeNode(TargetEntry);
1444 token = pg_strtok(&length); /* get :resdom */
1445 local_node->resdom = nodeRead(true); /* now read it */
1447 token = pg_strtok(&length); /* get :expr */
1448 local_node->expr = nodeRead(true); /* now read it */
1456 RangeVar *local_node;
1460 local_node = makeNode(RangeVar);
1462 local_node->catalogname = NULL; /* not currently saved in output format */
1464 token = pg_strtok(&length); /* eat :relation */
1465 token = pg_strtok(&length); /* get schemaname */
1466 local_node->schemaname = nullable_string(token, length);
1468 token = pg_strtok(&length); /* eat "." */
1469 token = pg_strtok(&length); /* get relname */
1470 local_node->relname = nullable_string(token, length);
1472 token = pg_strtok(&length); /* eat :inhopt */
1473 token = pg_strtok(&length); /* get inhopt */
1474 local_node->inhOpt = (InhOption) atoi(token);
1476 token = pg_strtok(&length); /* eat :istemp */
1477 token = pg_strtok(&length); /* get istemp */
1478 local_node->istemp = strtobool(token);
1480 token = pg_strtok(&length); /* eat :alias */
1481 local_node->alias = nodeRead(true); /* now read it */
1487 _readColumnRef(void)
1489 ColumnRef *local_node;
1493 local_node = makeNode(ColumnRef);
1495 token = pg_strtok(&length); /* eat :fields */
1496 local_node->fields = nodeRead(true); /* now read it */
1498 token = pg_strtok(&length); /* eat :indirection */
1499 local_node->indirection = nodeRead(true); /* now read it */
1505 _readColumnDef(void)
1507 ColumnDef *local_node;
1511 local_node = makeNode(ColumnDef);
1513 token = pg_strtok(&length); /* eat :colname */
1514 token = pg_strtok(&length); /* now read it */
1515 local_node->colname = nullable_string(token, length);
1517 token = pg_strtok(&length); /* eat :typename */
1518 local_node->typename = nodeRead(true); /* now read it */
1520 token = pg_strtok(&length); /* eat :is_inherited */
1521 token = pg_strtok(&length); /* get :is_inherited */
1522 local_node->is_inherited = strtobool(token);
1524 token = pg_strtok(&length); /* eat :is_not_null */
1525 token = pg_strtok(&length); /* get :is_not_null */
1526 local_node->is_not_null = strtobool(token);
1528 token = pg_strtok(&length); /* eat :raw_default */
1529 local_node->raw_default = nodeRead(true); /* now read it */
1531 token = pg_strtok(&length); /* eat :cooked_default */
1532 token = pg_strtok(&length); /* now read it */
1533 local_node->cooked_default = nullable_string(token, length);
1535 token = pg_strtok(&length); /* eat :constraints */
1536 local_node->constraints = nodeRead(true); /* now read it */
1538 token = pg_strtok(&length); /* eat :support */
1539 local_node->support = nodeRead(true); /* now read it */
1547 TypeName *local_node;
1551 local_node = makeNode(TypeName);
1553 token = pg_strtok(&length); /* eat :names */
1554 local_node->names = nodeRead(true); /* now read it */
1556 token = pg_strtok(&length); /* eat :typeid */
1557 token = pg_strtok(&length); /* get typeid */
1558 local_node->typeid = atooid(token);
1560 token = pg_strtok(&length); /* eat :timezone */
1561 token = pg_strtok(&length); /* get timezone */
1562 local_node->timezone = strtobool(token);
1564 token = pg_strtok(&length); /* eat :setof */
1565 token = pg_strtok(&length); /* get setof */
1566 local_node->setof = strtobool(token);
1568 token = pg_strtok(&length); /* eat :pct_type */
1569 token = pg_strtok(&length); /* get pct_type */
1570 local_node->pct_type = strtobool(token);
1572 token = pg_strtok(&length); /* eat :typmod */
1573 token = pg_strtok(&length); /* get typmod */
1574 local_node->typmod = atoi(token);
1576 token = pg_strtok(&length); /* eat :arrayBounds */
1577 local_node->arrayBounds = nodeRead(true); /* now read it */
1582 static ExprFieldSelect *
1583 _readExprFieldSelect(void)
1585 ExprFieldSelect *local_node;
1589 local_node = makeNode(ExprFieldSelect);
1591 token = pg_strtok(&length); /* eat :arg */
1592 local_node->arg = nodeRead(true); /* now read it */
1594 token = pg_strtok(&length); /* eat :fields */
1595 local_node->fields = nodeRead(true); /* now read it */
1597 token = pg_strtok(&length); /* eat :indirection */
1598 local_node->indirection = nodeRead(true); /* now read it */
1610 local_node = makeNode(Alias);
1612 token = pg_strtok(&length); /* eat :aliasname */
1613 token = pg_strtok(&length); /* get aliasname */
1614 local_node->aliasname = debackslash(token, length);
1616 token = pg_strtok(&length); /* eat :colnames */
1617 local_node->colnames = nodeRead(true); /* now read it */
1623 * _readRangeTblEntry
1626 static RangeTblEntry *
1627 _readRangeTblEntry(void)
1629 RangeTblEntry *local_node;
1633 local_node = makeNode(RangeTblEntry);
1635 token = pg_strtok(&length); /* eat :alias */
1636 local_node->alias = nodeRead(true); /* now read it */
1638 token = pg_strtok(&length); /* eat :eref */
1639 local_node->eref = nodeRead(true); /* now read it */
1641 token = pg_strtok(&length); /* eat :rtekind */
1642 token = pg_strtok(&length); /* get rtekind */
1643 local_node->rtekind = (RTEKind) atoi(token);
1645 switch (local_node->rtekind)
1649 token = pg_strtok(&length); /* eat :relid */
1650 token = pg_strtok(&length); /* get :relid */
1651 local_node->relid = atooid(token);
1655 token = pg_strtok(&length); /* eat :subquery */
1656 local_node->subquery = nodeRead(true); /* now read it */
1660 token = pg_strtok(&length); /* eat :funcexpr */
1661 local_node->funcexpr = nodeRead(true); /* now read it */
1663 token = pg_strtok(&length); /* eat :coldeflist */
1664 local_node->coldeflist = nodeRead(true); /* now read it */
1669 token = pg_strtok(&length); /* eat :jointype */
1670 token = pg_strtok(&length); /* get jointype */
1671 local_node->jointype = (JoinType) atoi(token);
1673 token = pg_strtok(&length); /* eat :joinaliasvars */
1674 local_node->joinaliasvars = nodeRead(true); /* now read it */
1678 elog(ERROR, "bogus rte kind %d", (int) local_node->rtekind);
1682 token = pg_strtok(&length); /* eat :inh */
1683 token = pg_strtok(&length); /* get :inh */
1684 local_node->inh = strtobool(token);
1686 token = pg_strtok(&length); /* eat :inFromCl */
1687 token = pg_strtok(&length); /* get :inFromCl */
1688 local_node->inFromCl = strtobool(token);
1690 token = pg_strtok(&length); /* eat :checkForRead */
1691 token = pg_strtok(&length); /* get :checkForRead */
1692 local_node->checkForRead = strtobool(token);
1694 token = pg_strtok(&length); /* eat :checkForWrite */
1695 token = pg_strtok(&length); /* get :checkForWrite */
1696 local_node->checkForWrite = strtobool(token);
1698 token = pg_strtok(&length); /* eat :checkAsUser */
1699 token = pg_strtok(&length); /* get :checkAsUser */
1700 local_node->checkAsUser = atooid(token);
1708 * Path is a subclass of Node.
1718 local_node = makeNode(Path);
1720 token = pg_strtok(&length); /* get :pathtype */
1721 token = pg_strtok(&length); /* now read it */
1722 local_node->pathtype = atoi(token);
1724 token = pg_strtok(&length); /* get :startup_cost */
1725 token = pg_strtok(&length); /* now read it */
1726 local_node->startup_cost = (Cost) atof(token);
1728 token = pg_strtok(&length); /* get :total_cost */
1729 token = pg_strtok(&length); /* now read it */
1730 local_node->total_cost = (Cost) atof(token);
1732 token = pg_strtok(&length); /* get :pathkeys */
1733 local_node->pathkeys = nodeRead(true); /* now read it */
1741 * IndexPath is a subclass of Path.
1745 _readIndexPath(void)
1747 IndexPath *local_node;
1751 local_node = makeNode(IndexPath);
1753 token = pg_strtok(&length); /* get :pathtype */
1754 token = pg_strtok(&length); /* now read it */
1755 local_node->path.pathtype = atoi(token);
1757 token = pg_strtok(&length); /* get :startup_cost */
1758 token = pg_strtok(&length); /* now read it */
1759 local_node->path.startup_cost = (Cost) atof(token);
1761 token = pg_strtok(&length); /* get :total_cost */
1762 token = pg_strtok(&length); /* now read it */
1763 local_node->path.total_cost = (Cost) atof(token);
1765 token = pg_strtok(&length); /* get :pathkeys */
1766 local_node->path.pathkeys = nodeRead(true); /* now read it */
1768 token = pg_strtok(&length); /* get :indexinfo */
1769 local_node->indexinfo = nodeRead(true); /* now read it */
1771 token = pg_strtok(&length); /* get :indexqual */
1772 local_node->indexqual = nodeRead(true); /* now read it */
1774 token = pg_strtok(&length); /* get :indexscandir */
1775 token = pg_strtok(&length); /* now read it */
1776 local_node->indexscandir = (ScanDirection) atoi(token);
1778 token = pg_strtok(&length); /* get :joinrelids */
1779 local_node->joinrelids = toIntList(nodeRead(true));
1781 token = pg_strtok(&length); /* get :alljoinquals */
1782 token = pg_strtok(&length); /* now read it */
1783 local_node->alljoinquals = strtobool(token);
1785 token = pg_strtok(&length); /* get :rows */
1786 token = pg_strtok(&length); /* now read it */
1787 local_node->rows = atof(token);
1795 * TidPath is a subclass of Path.
1801 TidPath *local_node;
1805 local_node = makeNode(TidPath);
1807 token = pg_strtok(&length); /* get :pathtype */
1808 token = pg_strtok(&length); /* now read it */
1809 local_node->path.pathtype = atoi(token);
1811 token = pg_strtok(&length); /* get :startup_cost */
1812 token = pg_strtok(&length); /* now read it */
1813 local_node->path.startup_cost = (Cost) atof(token);
1815 token = pg_strtok(&length); /* get :total_cost */
1816 token = pg_strtok(&length); /* now read it */
1817 local_node->path.total_cost = (Cost) atof(token);
1819 token = pg_strtok(&length); /* get :pathkeys */
1820 local_node->path.pathkeys = nodeRead(true); /* now read it */
1822 token = pg_strtok(&length); /* get :tideval */
1823 local_node->tideval = nodeRead(true); /* now read it */
1825 token = pg_strtok(&length); /* get :unjoined_relids */
1826 local_node->unjoined_relids = toIntList(nodeRead(true));
1834 * AppendPath is a subclass of Path.
1838 _readAppendPath(void)
1840 AppendPath *local_node;
1844 local_node = makeNode(AppendPath);
1846 token = pg_strtok(&length); /* get :pathtype */
1847 token = pg_strtok(&length); /* now read it */
1848 local_node->path.pathtype = atoi(token);
1850 token = pg_strtok(&length); /* get :startup_cost */
1851 token = pg_strtok(&length); /* now read it */
1852 local_node->path.startup_cost = (Cost) atof(token);
1854 token = pg_strtok(&length); /* get :total_cost */
1855 token = pg_strtok(&length); /* now read it */
1856 local_node->path.total_cost = (Cost) atof(token);
1858 token = pg_strtok(&length); /* get :pathkeys */
1859 local_node->path.pathkeys = nodeRead(true); /* now read it */
1861 token = pg_strtok(&length); /* get :subpaths */
1862 local_node->subpaths = nodeRead(true); /* now read it */
1870 * NestPath is a subclass of Path
1876 NestPath *local_node;
1880 local_node = makeNode(NestPath);
1882 token = pg_strtok(&length); /* get :pathtype */
1883 token = pg_strtok(&length); /* now read it */
1884 local_node->path.pathtype = atoi(token);
1886 token = pg_strtok(&length); /* get :startup_cost */
1887 token = pg_strtok(&length); /* now read it */
1888 local_node->path.startup_cost = (Cost) atof(token);
1890 token = pg_strtok(&length); /* get :total_cost */
1891 token = pg_strtok(&length); /* now read it */
1892 local_node->path.total_cost = (Cost) atof(token);
1894 token = pg_strtok(&length); /* get :pathkeys */
1895 local_node->path.pathkeys = nodeRead(true); /* now read it */
1897 token = pg_strtok(&length); /* get :jointype */
1898 token = pg_strtok(&length); /* now read it */
1899 local_node->jointype = (JoinType) atoi(token);
1901 token = pg_strtok(&length); /* get :outerjoinpath */
1902 local_node->outerjoinpath = nodeRead(true); /* now read it */
1904 token = pg_strtok(&length); /* get :innerjoinpath */
1905 local_node->innerjoinpath = nodeRead(true); /* now read it */
1907 token = pg_strtok(&length); /* get :joinrestrictinfo */
1908 local_node->joinrestrictinfo = nodeRead(true); /* now read it */
1916 * MergePath is a subclass of NestPath.
1920 _readMergePath(void)
1922 MergePath *local_node;
1926 local_node = makeNode(MergePath);
1928 token = pg_strtok(&length); /* get :pathtype */
1929 token = pg_strtok(&length); /* now read it */
1930 local_node->jpath.path.pathtype = atoi(token);
1932 token = pg_strtok(&length); /* get :startup_cost */
1933 token = pg_strtok(&length); /* now read it */
1934 local_node->jpath.path.startup_cost = (Cost) atof(token);
1936 token = pg_strtok(&length); /* get :total_cost */
1937 token = pg_strtok(&length); /* now read it */
1938 local_node->jpath.path.total_cost = (Cost) atof(token);
1940 token = pg_strtok(&length); /* get :pathkeys */
1941 local_node->jpath.path.pathkeys = nodeRead(true); /* now read it */
1943 token = pg_strtok(&length); /* get :jointype */
1944 token = pg_strtok(&length); /* now read it */
1945 local_node->jpath.jointype = (JoinType) atoi(token);
1947 token = pg_strtok(&length); /* get :outerjoinpath */
1948 local_node->jpath.outerjoinpath = nodeRead(true); /* now read it */
1950 token = pg_strtok(&length); /* get :innerjoinpath */
1951 local_node->jpath.innerjoinpath = nodeRead(true); /* now read it */
1953 token = pg_strtok(&length); /* get :joinrestrictinfo */
1954 local_node->jpath.joinrestrictinfo = nodeRead(true); /* now read it */
1956 token = pg_strtok(&length); /* get :path_mergeclauses */
1957 local_node->path_mergeclauses = nodeRead(true); /* now read it */
1959 token = pg_strtok(&length); /* get :outersortkeys */
1960 local_node->outersortkeys = nodeRead(true); /* now read it */
1962 token = pg_strtok(&length); /* get :innersortkeys */
1963 local_node->innersortkeys = nodeRead(true); /* now read it */
1971 * HashPath is a subclass of NestPath.
1977 HashPath *local_node;
1981 local_node = makeNode(HashPath);
1983 token = pg_strtok(&length); /* get :pathtype */
1984 token = pg_strtok(&length); /* now read it */
1985 local_node->jpath.path.pathtype = atoi(token);
1987 token = pg_strtok(&length); /* get :startup_cost */
1988 token = pg_strtok(&length); /* now read it */
1989 local_node->jpath.path.startup_cost = (Cost) atof(token);
1991 token = pg_strtok(&length); /* get :total_cost */
1992 token = pg_strtok(&length); /* now read it */
1993 local_node->jpath.path.total_cost = (Cost) atof(token);
1995 token = pg_strtok(&length); /* get :pathkeys */
1996 local_node->jpath.path.pathkeys = nodeRead(true); /* now read it */
1998 token = pg_strtok(&length); /* get :jointype */
1999 token = pg_strtok(&length); /* now read it */
2000 local_node->jpath.jointype = (JoinType) atoi(token);
2002 token = pg_strtok(&length); /* get :outerjoinpath */
2003 local_node->jpath.outerjoinpath = nodeRead(true); /* now read it */
2005 token = pg_strtok(&length); /* get :innerjoinpath */
2006 local_node->jpath.innerjoinpath = nodeRead(true); /* now read it */
2008 token = pg_strtok(&length); /* get :joinrestrictinfo */
2009 local_node->jpath.joinrestrictinfo = nodeRead(true); /* now read it */
2011 token = pg_strtok(&length); /* get :path_hashclauses */
2012 local_node->path_hashclauses = nodeRead(true); /* now read it */
2020 * PathKeyItem is a subclass of Node.
2023 static PathKeyItem *
2024 _readPathKeyItem(void)
2026 PathKeyItem *local_node;
2030 local_node = makeNode(PathKeyItem);
2032 token = pg_strtok(&length); /* get :sortop */
2033 token = pg_strtok(&length); /* now read it */
2034 local_node->sortop = atooid(token);
2036 token = pg_strtok(&length); /* get :key */
2037 local_node->key = nodeRead(true); /* now read it */
2045 * RestrictInfo is a subclass of Node.
2048 static RestrictInfo *
2049 _readRestrictInfo(void)
2051 RestrictInfo *local_node;
2055 local_node = makeNode(RestrictInfo);
2057 token = pg_strtok(&length); /* get :clause */
2058 local_node->clause = nodeRead(true); /* now read it */
2060 token = pg_strtok(&length); /* get :ispusheddown */
2061 token = pg_strtok(&length); /* now read it */
2062 local_node->ispusheddown = strtobool(token);
2064 token = pg_strtok(&length); /* get :subclauseindices */
2065 local_node->subclauseindices = nodeRead(true); /* now read it */
2067 token = pg_strtok(&length); /* get :mergejoinoperator */
2068 token = pg_strtok(&length); /* now read it */
2069 local_node->mergejoinoperator = atooid(token);
2071 token = pg_strtok(&length); /* get :left_sortop */
2072 token = pg_strtok(&length); /* now read it */
2073 local_node->left_sortop = atooid(token);
2075 token = pg_strtok(&length); /* get :right_sortop */
2076 token = pg_strtok(&length); /* now read it */
2077 local_node->right_sortop = atooid(token);
2079 token = pg_strtok(&length); /* get :hashjoinoperator */
2080 token = pg_strtok(&length); /* now read it */
2081 local_node->hashjoinoperator = atooid(token);
2083 /* eval_cost is not part of saved representation; compute on first use */
2084 local_node->eval_cost = -1;
2085 /* ditto for this_selec */
2086 local_node->this_selec = -1;
2087 /* ditto for cached pathkeys, selectivity, bucketsize */
2088 local_node->left_pathkey = NIL;
2089 local_node->right_pathkey = NIL;
2090 local_node->left_mergescansel = -1;
2091 local_node->right_mergescansel = -1;
2092 local_node->left_bucketsize = -1;
2093 local_node->right_bucketsize = -1;
2101 * JoinInfo is a subclass of Node.
2107 JoinInfo *local_node;
2111 local_node = makeNode(JoinInfo);
2113 token = pg_strtok(&length); /* get :unjoined_relids */
2114 local_node->unjoined_relids = toIntList(nodeRead(true)); /* now read it */
2116 token = pg_strtok(&length); /* get :jinfo_restrictinfo */
2117 local_node->jinfo_restrictinfo = nodeRead(true); /* now read it */
2126 * Given a character string containing a plan, parsePlanString sets up the
2127 * plan structure representing that plan.
2129 * The string to be read must already have been loaded into pg_strtok().
2133 parsePlanString(void)
2137 void *return_value = NULL;
2139 token = pg_strtok(&length);
2141 if (length == 4 && strncmp(token, "PLAN", length) == 0)
2142 return_value = _readPlan();
2143 else if (length == 6 && strncmp(token, "RESULT", length) == 0)
2144 return_value = _readResult();
2145 else if (length == 6 && strncmp(token, "APPEND", length) == 0)
2146 return_value = _readAppend();
2147 else if (length == 4 && strncmp(token, "JOIN", length) == 0)
2148 return_value = _readJoin();
2149 else if (length == 8 && strncmp(token, "NESTLOOP", length) == 0)
2150 return_value = _readNestLoop();
2151 else if (length == 9 && strncmp(token, "MERGEJOIN", length) == 0)
2152 return_value = _readMergeJoin();
2153 else if (length == 8 && strncmp(token, "HASHJOIN", length) == 0)
2154 return_value = _readHashJoin();
2155 else if (length == 4 && strncmp(token, "SCAN", length) == 0)
2156 return_value = _readScan();
2157 else if (length == 7 && strncmp(token, "SEQSCAN", length) == 0)
2158 return_value = _readSeqScan();
2159 else if (length == 9 && strncmp(token, "INDEXSCAN", length) == 0)
2160 return_value = _readIndexScan();
2161 else if (length == 7 && strncmp(token, "TIDSCAN", length) == 0)
2162 return_value = _readTidScan();
2163 else if (length == 12 && strncmp(token, "SUBQUERYSCAN", length) == 0)
2164 return_value = _readSubqueryScan();
2165 else if (length == 12 && strncmp(token, "FUNCTIONSCAN", length) == 0)
2166 return_value = _readFunctionScan();
2167 else if (length == 4 && strncmp(token, "SORT", length) == 0)
2168 return_value = _readSort();
2169 else if (length == 6 && strncmp(token, "AGGREG", length) == 0)
2170 return_value = _readAggref();
2171 else if (length == 7 && strncmp(token, "SUBLINK", length) == 0)
2172 return_value = _readSubLink();
2173 else if (length == 11 && strncmp(token, "FIELDSELECT", length) == 0)
2174 return_value = _readFieldSelect();
2175 else if (length == 11 && strncmp(token, "RELABELTYPE", length) == 0)
2176 return_value = _readRelabelType();
2177 else if (length == 11 && strncmp(token, "RANGETBLREF", length) == 0)
2178 return_value = _readRangeTblRef();
2179 else if (length == 8 && strncmp(token, "FROMEXPR", length) == 0)
2180 return_value = _readFromExpr();
2181 else if (length == 8 && strncmp(token, "JOINEXPR", length) == 0)
2182 return_value = _readJoinExpr();
2183 else if (length == 3 && strncmp(token, "AGG", length) == 0)
2184 return_value = _readAgg();
2185 else if (length == 4 && strncmp(token, "HASH", length) == 0)
2186 return_value = _readHash();
2187 else if (length == 6 && strncmp(token, "RESDOM", length) == 0)
2188 return_value = _readResdom();
2189 else if (length == 4 && strncmp(token, "EXPR", length) == 0)
2190 return_value = _readExpr();
2191 else if (length == 8 && strncmp(token, "ARRAYREF", length) == 0)
2192 return_value = _readArrayRef();
2193 else if (length == 3 && strncmp(token, "VAR", length) == 0)
2194 return_value = _readVar();
2195 else if (length == 5 && strncmp(token, "CONST", length) == 0)
2196 return_value = _readConst();
2197 else if (length == 4 && strncmp(token, "FUNC", length) == 0)
2198 return_value = _readFunc();
2199 else if (length == 4 && strncmp(token, "OPER", length) == 0)
2200 return_value = _readOper();
2201 else if (length == 5 && strncmp(token, "PARAM", length) == 0)
2202 return_value = _readParam();
2203 else if (length == 11 && strncmp(token, "TARGETENTRY", length) == 0)
2204 return_value = _readTargetEntry();
2205 else if (length == 8 && strncmp(token, "RANGEVAR", length) == 0)
2206 return_value = _readRangeVar();
2207 else if (length == 9 && strncmp(token, "COLUMNREF", length) == 0)
2208 return_value = _readColumnRef();
2209 else if (length == 9 && strncmp(token, "COLUMNDEF", length) == 0)
2210 return_value = _readColumnDef();
2211 else if (length == 8 && strncmp(token, "TYPENAME", length) == 0)
2212 return_value = _readTypeName();
2213 else if (length == 15 && strncmp(token, "EXPRFIELDSELECT", length) == 0)
2214 return_value = _readExprFieldSelect();
2215 else if (length == 5 && strncmp(token, "ALIAS", length) == 0)
2216 return_value = _readAlias();
2217 else if (length == 3 && strncmp(token, "RTE", length) == 0)
2218 return_value = _readRangeTblEntry();
2219 else if (length == 4 && strncmp(token, "PATH", length) == 0)
2220 return_value = _readPath();
2221 else if (length == 9 && strncmp(token, "INDEXPATH", length) == 0)
2222 return_value = _readIndexPath();
2223 else if (length == 7 && strncmp(token, "TIDPATH", length) == 0)
2224 return_value = _readTidPath();
2225 else if (length == 10 && strncmp(token, "APPENDPATH", length) == 0)
2226 return_value = _readAppendPath();
2227 else if (length == 8 && strncmp(token, "NESTPATH", length) == 0)
2228 return_value = _readNestPath();
2229 else if (length == 9 && strncmp(token, "MERGEPATH", length) == 0)
2230 return_value = _readMergePath();
2231 else if (length == 8 && strncmp(token, "HASHPATH", length) == 0)
2232 return_value = _readHashPath();
2233 else if (length == 11 && strncmp(token, "PATHKEYITEM", length) == 0)
2234 return_value = _readPathKeyItem();
2235 else if (length == 12 && strncmp(token, "RESTRICTINFO", length) == 0)
2236 return_value = _readRestrictInfo();
2237 else if (length == 8 && strncmp(token, "JOININFO", length) == 0)
2238 return_value = _readJoinInfo();
2239 else if (length == 5 && strncmp(token, "QUERY", length) == 0)
2240 return_value = _readQuery();
2241 else if (length == 6 && strncmp(token, "NOTIFY", length) == 0)
2242 return_value = _readNotifyStmt();
2243 else if (length == 10 && strncmp(token, "SORTCLAUSE", length) == 0)
2244 return_value = _readSortClause();
2245 else if (length == 11 && strncmp(token, "GROUPCLAUSE", length) == 0)
2246 return_value = _readGroupClause();
2247 else if (length == 16 && strncmp(token, "SETOPERATIONSTMT", length) == 0)
2248 return_value = _readSetOperationStmt();
2249 else if (length == 4 && strncmp(token, "CASE", length) == 0)
2250 return_value = _readCaseExpr();
2251 else if (length == 4 && strncmp(token, "WHEN", length) == 0)
2252 return_value = _readCaseWhen();
2253 else if (length == 8 && strncmp(token, "NULLTEST", length) == 0)
2254 return_value = _readNullTest();
2255 else if (length == 11 && strncmp(token, "BOOLEANTEST", length) == 0)
2256 return_value = _readBooleanTest();
2257 else if (length == 14 && strncmp(token, "CONSTRAINTTEST", length) == 0)
2258 return_value = _readConstraintTest();
2260 elog(ERROR, "badly formatted planstring \"%.10s\"...", token);
2262 return (Node *) return_value;
2265 /*------------------------------------------------------------*/
2270 * Given a string representation of a constant, recreate the appropriate
2271 * Datum. The string representation embeds length info, but not byValue,
2272 * so we must be told that.
2276 readDatum(bool typbyval)
2286 * read the actual length of the value
2288 token = pg_strtok(&tokenLength);
2289 length = atoui(token);
2291 token = pg_strtok(&tokenLength); /* read the '[' */
2292 if (token == NULL || token[0] != '[')
2293 elog(ERROR, "readDatum: expected '%s', got '%s'; length = %lu",
2294 "[", token ? (const char *) token : "[NULL]",
2295 (unsigned long) length);
2299 if (length > (Size) sizeof(Datum))
2300 elog(ERROR, "readDatum: byval & length = %lu",
2301 (unsigned long) length);
2303 s = (char *) (&res);
2304 for (i = 0; i < (Size) sizeof(Datum); i++)
2306 token = pg_strtok(&tokenLength);
2307 s[i] = (char) atoi(token);
2310 else if (length <= 0)
2314 s = (char *) palloc(length);
2315 for (i = 0; i < length; i++)
2317 token = pg_strtok(&tokenLength);
2318 s[i] = (char) atoi(token);
2320 res = PointerGetDatum(s);
2323 token = pg_strtok(&tokenLength); /* read the ']' */
2324 if (token == NULL || token[0] != ']')
2325 elog(ERROR, "readDatum: expected '%s', got '%s'; length = %lu",
2326 "]", token ? (const char *) token : "[NULL]",
2327 (unsigned long) length);