/*------------------------------------------------------------------------- * * readfuncs.c * Reader functions for Postgres tree nodes. * * Portions Copyright (c) 1996-2015, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION * src/backend/nodes/readfuncs.c * * NOTES * Path and Plan nodes do not have any readfuncs support, because we * never have occasion to read them in. (There was once code here that * claimed to read them, but it was broken as well as unused.) We * never read executor state trees, either. * * Parse location fields are written out by outfuncs.c, but only for * possible debugging use. When reading a location field, we discard * the stored value and set the location field to -1 (ie, "unknown"). * This is because nodes coming from a stored rule should not be thought * to have a known location in the current query's text. * *------------------------------------------------------------------------- */ #include "postgres.h" #include #include "nodes/parsenodes.h" #include "nodes/readfuncs.h" /* * Macros to simplify reading of different kinds of fields. Use these * wherever possible to reduce the chance for silly typos. Note that these * hard-wire conventions about the names of the local variables in a Read * routine. */ /* Macros for declaring appropriate local variables */ /* A few guys need only local_node */ #define READ_LOCALS_NO_FIELDS(nodeTypeName) \ nodeTypeName *local_node = makeNode(nodeTypeName) /* And a few guys need only the pg_strtok support fields */ #define READ_TEMP_LOCALS() \ char *token; \ int length /* ... but most need both */ #define READ_LOCALS(nodeTypeName) \ READ_LOCALS_NO_FIELDS(nodeTypeName); \ READ_TEMP_LOCALS() /* Read an integer field (anything written as ":fldname %d") */ #define READ_INT_FIELD(fldname) \ token = pg_strtok(&length); /* skip :fldname */ \ token = pg_strtok(&length); /* get field value */ \ local_node->fldname = atoi(token) /* Read an unsigned integer field (anything written as ":fldname %u") */ #define READ_UINT_FIELD(fldname) \ token = pg_strtok(&length); /* skip :fldname */ \ token = pg_strtok(&length); /* get field value */ \ local_node->fldname = atoui(token) /* Read an OID field (don't hard-wire assumption that OID is same as uint) */ #define READ_OID_FIELD(fldname) \ token = pg_strtok(&length); /* skip :fldname */ \ token = pg_strtok(&length); /* get field value */ \ local_node->fldname = atooid(token) /* Read a char field (ie, one ascii character) */ #define READ_CHAR_FIELD(fldname) \ token = pg_strtok(&length); /* skip :fldname */ \ token = pg_strtok(&length); /* get field value */ \ local_node->fldname = token[0] /* Read an enumerated-type field that was written as an integer code */ #define READ_ENUM_FIELD(fldname, enumtype) \ token = pg_strtok(&length); /* skip :fldname */ \ token = pg_strtok(&length); /* get field value */ \ local_node->fldname = (enumtype) atoi(token) /* Read a float field */ #define READ_FLOAT_FIELD(fldname) \ token = pg_strtok(&length); /* skip :fldname */ \ token = pg_strtok(&length); /* get field value */ \ local_node->fldname = atof(token) /* Read a boolean field */ #define READ_BOOL_FIELD(fldname) \ token = pg_strtok(&length); /* skip :fldname */ \ token = pg_strtok(&length); /* get field value */ \ local_node->fldname = strtobool(token) /* Read a character-string field */ #define READ_STRING_FIELD(fldname) \ token = pg_strtok(&length); /* skip :fldname */ \ token = pg_strtok(&length); /* get field value */ \ local_node->fldname = nullable_string(token, length) /* Read a parse location field (and throw away the value, per notes above) */ #define READ_LOCATION_FIELD(fldname) \ token = pg_strtok(&length); /* skip :fldname */ \ token = pg_strtok(&length); /* get field value */ \ (void) token; /* in case not used elsewhere */ \ local_node->fldname = -1 /* set field to "unknown" */ /* Read a Node field */ #define READ_NODE_FIELD(fldname) \ token = pg_strtok(&length); /* skip :fldname */ \ (void) token; /* in case not used elsewhere */ \ local_node->fldname = nodeRead(NULL, 0) /* Read a bitmapset field */ #define READ_BITMAPSET_FIELD(fldname) \ token = pg_strtok(&length); /* skip :fldname */ \ (void) token; /* in case not used elsewhere */ \ local_node->fldname = _readBitmapset() /* Routine exit */ #define READ_DONE() \ return local_node /* * NOTE: use atoi() to read values written with %d, or atoui() to read * values written with %u in outfuncs.c. An exception is OID values, * for which use atooid(). (As of 7.1, outfuncs.c writes OIDs as %u, * but this will probably change in the future.) */ #define atoui(x) ((unsigned int) strtoul((x), NULL, 10)) #define atooid(x) ((Oid) strtoul((x), NULL, 10)) #define strtobool(x) ((*(x) == 't') ? true : false) #define nullable_string(token,length) \ ((length) == 0 ? NULL : debackslash(token, length)) static Datum readDatum(bool typbyval); /* * _readBitmapset */ static Bitmapset * _readBitmapset(void) { Bitmapset *result = NULL; READ_TEMP_LOCALS(); token = pg_strtok(&length); if (token == NULL) elog(ERROR, "incomplete Bitmapset structure"); if (length != 1 || token[0] != '(') elog(ERROR, "unrecognized token: \"%.*s\"", length, token); token = pg_strtok(&length); if (token == NULL) elog(ERROR, "incomplete Bitmapset structure"); if (length != 1 || token[0] != 'b') elog(ERROR, "unrecognized token: \"%.*s\"", length, token); for (;;) { int val; char *endptr; token = pg_strtok(&length); if (token == NULL) elog(ERROR, "unterminated Bitmapset structure"); if (length == 1 && token[0] == ')') break; val = (int) strtol(token, &endptr, 10); if (endptr != token + length) elog(ERROR, "unrecognized integer: \"%.*s\"", length, token); result = bms_add_member(result, val); } return result; } /* * _readQuery */ static Query * _readQuery(void) { READ_LOCALS(Query); READ_ENUM_FIELD(commandType, CmdType); READ_ENUM_FIELD(querySource, QuerySource); local_node->queryId = 0; /* not saved in output format */ READ_BOOL_FIELD(canSetTag); READ_NODE_FIELD(utilityStmt); READ_INT_FIELD(resultRelation); READ_BOOL_FIELD(hasAggs); READ_BOOL_FIELD(hasWindowFuncs); READ_BOOL_FIELD(hasSubLinks); READ_BOOL_FIELD(hasDistinctOn); READ_BOOL_FIELD(hasRecursive); READ_BOOL_FIELD(hasModifyingCTE); READ_BOOL_FIELD(hasForUpdate); READ_BOOL_FIELD(hasRowSecurity); READ_NODE_FIELD(cteList); READ_NODE_FIELD(rtable); READ_NODE_FIELD(jointree); READ_NODE_FIELD(targetList); READ_NODE_FIELD(withCheckOptions); READ_NODE_FIELD(onConflict); READ_NODE_FIELD(returningList); READ_NODE_FIELD(groupClause); READ_NODE_FIELD(havingQual); READ_NODE_FIELD(windowClause); READ_NODE_FIELD(distinctClause); READ_NODE_FIELD(sortClause); READ_NODE_FIELD(limitOffset); READ_NODE_FIELD(limitCount); READ_NODE_FIELD(rowMarks); READ_NODE_FIELD(setOperations); READ_NODE_FIELD(constraintDeps); READ_DONE(); } /* * _readNotifyStmt */ static NotifyStmt * _readNotifyStmt(void) { READ_LOCALS(NotifyStmt); READ_STRING_FIELD(conditionname); READ_STRING_FIELD(payload); READ_DONE(); } /* * _readDeclareCursorStmt */ static DeclareCursorStmt * _readDeclareCursorStmt(void) { READ_LOCALS(DeclareCursorStmt); READ_STRING_FIELD(portalname); READ_INT_FIELD(options); READ_NODE_FIELD(query); READ_DONE(); } /* * _readWithCheckOption */ static WithCheckOption * _readWithCheckOption(void) { READ_LOCALS(WithCheckOption); READ_ENUM_FIELD(kind, WCOKind); READ_STRING_FIELD(relname); READ_NODE_FIELD(qual); READ_BOOL_FIELD(cascaded); READ_DONE(); } /* * _readSortGroupClause */ static SortGroupClause * _readSortGroupClause(void) { READ_LOCALS(SortGroupClause); READ_UINT_FIELD(tleSortGroupRef); READ_OID_FIELD(eqop); READ_OID_FIELD(sortop); READ_BOOL_FIELD(nulls_first); READ_BOOL_FIELD(hashable); READ_DONE(); } /* * _readWindowClause */ static WindowClause * _readWindowClause(void) { READ_LOCALS(WindowClause); READ_STRING_FIELD(name); READ_STRING_FIELD(refname); READ_NODE_FIELD(partitionClause); READ_NODE_FIELD(orderClause); READ_INT_FIELD(frameOptions); READ_NODE_FIELD(startOffset); READ_NODE_FIELD(endOffset); READ_UINT_FIELD(winref); READ_BOOL_FIELD(copiedOrder); READ_DONE(); } /* * _readRowMarkClause */ static RowMarkClause * _readRowMarkClause(void) { READ_LOCALS(RowMarkClause); READ_UINT_FIELD(rti); READ_ENUM_FIELD(strength, LockClauseStrength); READ_ENUM_FIELD(waitPolicy, LockWaitPolicy); READ_BOOL_FIELD(pushedDown); READ_DONE(); } /* * _readCommonTableExpr */ static CommonTableExpr * _readCommonTableExpr(void) { READ_LOCALS(CommonTableExpr); READ_STRING_FIELD(ctename); READ_NODE_FIELD(aliascolnames); READ_NODE_FIELD(ctequery); READ_LOCATION_FIELD(location); READ_BOOL_FIELD(cterecursive); READ_INT_FIELD(cterefcount); READ_NODE_FIELD(ctecolnames); READ_NODE_FIELD(ctecoltypes); READ_NODE_FIELD(ctecoltypmods); READ_NODE_FIELD(ctecolcollations); READ_DONE(); } /* * _readRangeTableSample */ static RangeTableSample * _readRangeTableSample(void) { READ_LOCALS(RangeTableSample); READ_NODE_FIELD(relation); READ_STRING_FIELD(method); READ_NODE_FIELD(repeatable); READ_NODE_FIELD(args); READ_DONE(); } /* * _readTableSampleClause */ static TableSampleClause * _readTableSampleClause(void) { READ_LOCALS(TableSampleClause); READ_OID_FIELD(tsmid); READ_BOOL_FIELD(tsmseqscan); READ_BOOL_FIELD(tsmpagemode); READ_OID_FIELD(tsminit); READ_OID_FIELD(tsmnextblock); READ_OID_FIELD(tsmnexttuple); READ_OID_FIELD(tsmexaminetuple); READ_OID_FIELD(tsmend); READ_OID_FIELD(tsmreset); READ_OID_FIELD(tsmcost); READ_NODE_FIELD(repeatable); READ_NODE_FIELD(args); READ_DONE(); } /* * _readSetOperationStmt */ static SetOperationStmt * _readSetOperationStmt(void) { READ_LOCALS(SetOperationStmt); READ_ENUM_FIELD(op, SetOperation); READ_BOOL_FIELD(all); READ_NODE_FIELD(larg); READ_NODE_FIELD(rarg); READ_NODE_FIELD(colTypes); READ_NODE_FIELD(colTypmods); READ_NODE_FIELD(colCollations); READ_NODE_FIELD(groupClauses); READ_DONE(); } /* * Stuff from primnodes.h. */ static Alias * _readAlias(void) { READ_LOCALS(Alias); READ_STRING_FIELD(aliasname); READ_NODE_FIELD(colnames); READ_DONE(); } static RangeVar * _readRangeVar(void) { READ_LOCALS(RangeVar); local_node->catalogname = NULL; /* not currently saved in output * format */ READ_STRING_FIELD(schemaname); READ_STRING_FIELD(relname); READ_ENUM_FIELD(inhOpt, InhOption); READ_CHAR_FIELD(relpersistence); READ_NODE_FIELD(alias); READ_LOCATION_FIELD(location); READ_DONE(); } static IntoClause * _readIntoClause(void) { READ_LOCALS(IntoClause); READ_NODE_FIELD(rel); READ_NODE_FIELD(colNames); READ_NODE_FIELD(options); READ_ENUM_FIELD(onCommit, OnCommitAction); READ_STRING_FIELD(tableSpaceName); READ_NODE_FIELD(viewQuery); READ_BOOL_FIELD(skipData); READ_DONE(); } /* * _readVar */ static Var * _readVar(void) { READ_LOCALS(Var); READ_UINT_FIELD(varno); READ_INT_FIELD(varattno); READ_OID_FIELD(vartype); READ_INT_FIELD(vartypmod); READ_OID_FIELD(varcollid); READ_UINT_FIELD(varlevelsup); READ_UINT_FIELD(varnoold); READ_INT_FIELD(varoattno); READ_LOCATION_FIELD(location); READ_DONE(); } /* * _readConst */ static Const * _readConst(void) { READ_LOCALS(Const); READ_OID_FIELD(consttype); READ_INT_FIELD(consttypmod); READ_OID_FIELD(constcollid); READ_INT_FIELD(constlen); READ_BOOL_FIELD(constbyval); READ_BOOL_FIELD(constisnull); READ_LOCATION_FIELD(location); token = pg_strtok(&length); /* skip :constvalue */ if (local_node->constisnull) token = pg_strtok(&length); /* skip "<>" */ else local_node->constvalue = readDatum(local_node->constbyval); READ_DONE(); } /* * _readParam */ static Param * _readParam(void) { READ_LOCALS(Param); READ_ENUM_FIELD(paramkind, ParamKind); READ_INT_FIELD(paramid); READ_OID_FIELD(paramtype); READ_INT_FIELD(paramtypmod); READ_OID_FIELD(paramcollid); READ_LOCATION_FIELD(location); READ_DONE(); } /* * _readAggref */ static Aggref * _readAggref(void) { READ_LOCALS(Aggref); READ_OID_FIELD(aggfnoid); READ_OID_FIELD(aggtype); READ_OID_FIELD(aggcollid); READ_OID_FIELD(inputcollid); READ_NODE_FIELD(aggdirectargs); READ_NODE_FIELD(args); READ_NODE_FIELD(aggorder); READ_NODE_FIELD(aggdistinct); READ_NODE_FIELD(aggfilter); READ_BOOL_FIELD(aggstar); READ_BOOL_FIELD(aggvariadic); READ_CHAR_FIELD(aggkind); READ_UINT_FIELD(agglevelsup); READ_LOCATION_FIELD(location); READ_DONE(); } /* * _readWindowFunc */ static WindowFunc * _readWindowFunc(void) { READ_LOCALS(WindowFunc); READ_OID_FIELD(winfnoid); READ_OID_FIELD(wintype); READ_OID_FIELD(wincollid); READ_OID_FIELD(inputcollid); READ_NODE_FIELD(args); READ_NODE_FIELD(aggfilter); READ_UINT_FIELD(winref); READ_BOOL_FIELD(winstar); READ_BOOL_FIELD(winagg); READ_LOCATION_FIELD(location); READ_DONE(); } /* * _readArrayRef */ static ArrayRef * _readArrayRef(void) { READ_LOCALS(ArrayRef); READ_OID_FIELD(refarraytype); READ_OID_FIELD(refelemtype); READ_INT_FIELD(reftypmod); READ_OID_FIELD(refcollid); READ_NODE_FIELD(refupperindexpr); READ_NODE_FIELD(reflowerindexpr); READ_NODE_FIELD(refexpr); READ_NODE_FIELD(refassgnexpr); READ_DONE(); } /* * _readFuncExpr */ static FuncExpr * _readFuncExpr(void) { READ_LOCALS(FuncExpr); READ_OID_FIELD(funcid); READ_OID_FIELD(funcresulttype); READ_BOOL_FIELD(funcretset); READ_BOOL_FIELD(funcvariadic); READ_ENUM_FIELD(funcformat, CoercionForm); READ_OID_FIELD(funccollid); READ_OID_FIELD(inputcollid); READ_NODE_FIELD(args); READ_LOCATION_FIELD(location); READ_DONE(); } /* * _readNamedArgExpr */ static NamedArgExpr * _readNamedArgExpr(void) { READ_LOCALS(NamedArgExpr); READ_NODE_FIELD(arg); READ_STRING_FIELD(name); READ_INT_FIELD(argnumber); READ_LOCATION_FIELD(location); READ_DONE(); } /* * _readOpExpr */ static OpExpr * _readOpExpr(void) { READ_LOCALS(OpExpr); READ_OID_FIELD(opno); READ_OID_FIELD(opfuncid); /* * The opfuncid is stored in the textual format primarily for debugging * and documentation reasons. We want to always read it as zero to force * it to be re-looked-up in the pg_operator entry. This ensures that * stored rules don't have hidden dependencies on operators' functions. * (We don't currently support an ALTER OPERATOR command, but might * someday.) */ local_node->opfuncid = InvalidOid; READ_OID_FIELD(opresulttype); READ_BOOL_FIELD(opretset); READ_OID_FIELD(opcollid); READ_OID_FIELD(inputcollid); READ_NODE_FIELD(args); READ_LOCATION_FIELD(location); READ_DONE(); } /* * _readDistinctExpr */ static DistinctExpr * _readDistinctExpr(void) { READ_LOCALS(DistinctExpr); READ_OID_FIELD(opno); READ_OID_FIELD(opfuncid); /* * The opfuncid is stored in the textual format primarily for debugging * and documentation reasons. We want to always read it as zero to force * it to be re-looked-up in the pg_operator entry. This ensures that * stored rules don't have hidden dependencies on operators' functions. * (We don't currently support an ALTER OPERATOR command, but might * someday.) */ local_node->opfuncid = InvalidOid; READ_OID_FIELD(opresulttype); READ_BOOL_FIELD(opretset); READ_OID_FIELD(opcollid); READ_OID_FIELD(inputcollid); READ_NODE_FIELD(args); READ_LOCATION_FIELD(location); READ_DONE(); } /* * _readNullIfExpr */ static NullIfExpr * _readNullIfExpr(void) { READ_LOCALS(NullIfExpr); READ_OID_FIELD(opno); READ_OID_FIELD(opfuncid); /* * The opfuncid is stored in the textual format primarily for debugging * and documentation reasons. We want to always read it as zero to force * it to be re-looked-up in the pg_operator entry. This ensures that * stored rules don't have hidden dependencies on operators' functions. * (We don't currently support an ALTER OPERATOR command, but might * someday.) */ local_node->opfuncid = InvalidOid; READ_OID_FIELD(opresulttype); READ_BOOL_FIELD(opretset); READ_OID_FIELD(opcollid); READ_OID_FIELD(inputcollid); READ_NODE_FIELD(args); READ_LOCATION_FIELD(location); READ_DONE(); } /* * _readScalarArrayOpExpr */ static ScalarArrayOpExpr * _readScalarArrayOpExpr(void) { READ_LOCALS(ScalarArrayOpExpr); READ_OID_FIELD(opno); READ_OID_FIELD(opfuncid); /* * The opfuncid is stored in the textual format primarily for debugging * and documentation reasons. We want to always read it as zero to force * it to be re-looked-up in the pg_operator entry. This ensures that * stored rules don't have hidden dependencies on operators' functions. * (We don't currently support an ALTER OPERATOR command, but might * someday.) */ local_node->opfuncid = InvalidOid; READ_BOOL_FIELD(useOr); READ_OID_FIELD(inputcollid); READ_NODE_FIELD(args); READ_LOCATION_FIELD(location); READ_DONE(); } /* * _readBoolExpr */ static BoolExpr * _readBoolExpr(void) { READ_LOCALS(BoolExpr); /* do-it-yourself enum representation */ token = pg_strtok(&length); /* skip :boolop */ token = pg_strtok(&length); /* get field value */ if (strncmp(token, "and", 3) == 0) local_node->boolop = AND_EXPR; else if (strncmp(token, "or", 2) == 0) local_node->boolop = OR_EXPR; else if (strncmp(token, "not", 3) == 0) local_node->boolop = NOT_EXPR; else elog(ERROR, "unrecognized boolop \"%.*s\"", length, token); READ_NODE_FIELD(args); READ_LOCATION_FIELD(location); READ_DONE(); } /* * _readSubLink */ static SubLink * _readSubLink(void) { READ_LOCALS(SubLink); READ_ENUM_FIELD(subLinkType, SubLinkType); READ_INT_FIELD(subLinkId); READ_NODE_FIELD(testexpr); READ_NODE_FIELD(operName); READ_NODE_FIELD(subselect); READ_LOCATION_FIELD(location); READ_DONE(); } /* * _readSubPlan is not needed since it doesn't appear in stored rules. */ /* * _readFieldSelect */ static FieldSelect * _readFieldSelect(void) { READ_LOCALS(FieldSelect); READ_NODE_FIELD(arg); READ_INT_FIELD(fieldnum); READ_OID_FIELD(resulttype); READ_INT_FIELD(resulttypmod); READ_OID_FIELD(resultcollid); READ_DONE(); } /* * _readFieldStore */ static FieldStore * _readFieldStore(void) { READ_LOCALS(FieldStore); READ_NODE_FIELD(arg); READ_NODE_FIELD(newvals); READ_NODE_FIELD(fieldnums); READ_OID_FIELD(resulttype); READ_DONE(); } /* * _readRelabelType */ static RelabelType * _readRelabelType(void) { READ_LOCALS(RelabelType); READ_NODE_FIELD(arg); READ_OID_FIELD(resulttype); READ_INT_FIELD(resulttypmod); READ_OID_FIELD(resultcollid); READ_ENUM_FIELD(relabelformat, CoercionForm); READ_LOCATION_FIELD(location); READ_DONE(); } /* * _readCoerceViaIO */ static CoerceViaIO * _readCoerceViaIO(void) { READ_LOCALS(CoerceViaIO); READ_NODE_FIELD(arg); READ_OID_FIELD(resulttype); READ_OID_FIELD(resultcollid); READ_ENUM_FIELD(coerceformat, CoercionForm); READ_LOCATION_FIELD(location); READ_DONE(); } /* * _readArrayCoerceExpr */ static ArrayCoerceExpr * _readArrayCoerceExpr(void) { READ_LOCALS(ArrayCoerceExpr); READ_NODE_FIELD(arg); READ_OID_FIELD(elemfuncid); READ_OID_FIELD(resulttype); READ_INT_FIELD(resulttypmod); READ_OID_FIELD(resultcollid); READ_BOOL_FIELD(isExplicit); READ_ENUM_FIELD(coerceformat, CoercionForm); READ_LOCATION_FIELD(location); READ_DONE(); } /* * _readConvertRowtypeExpr */ static ConvertRowtypeExpr * _readConvertRowtypeExpr(void) { READ_LOCALS(ConvertRowtypeExpr); READ_NODE_FIELD(arg); READ_OID_FIELD(resulttype); READ_ENUM_FIELD(convertformat, CoercionForm); READ_LOCATION_FIELD(location); READ_DONE(); } /* * _readCollateExpr */ static CollateExpr * _readCollateExpr(void) { READ_LOCALS(CollateExpr); READ_NODE_FIELD(arg); READ_OID_FIELD(collOid); READ_LOCATION_FIELD(location); READ_DONE(); } /* * _readCaseExpr */ static CaseExpr * _readCaseExpr(void) { READ_LOCALS(CaseExpr); READ_OID_FIELD(casetype); READ_OID_FIELD(casecollid); READ_NODE_FIELD(arg); READ_NODE_FIELD(args); READ_NODE_FIELD(defresult); READ_LOCATION_FIELD(location); READ_DONE(); } /* * _readCaseWhen */ static CaseWhen * _readCaseWhen(void) { READ_LOCALS(CaseWhen); READ_NODE_FIELD(expr); READ_NODE_FIELD(result); READ_LOCATION_FIELD(location); READ_DONE(); } /* * _readCaseTestExpr */ static CaseTestExpr * _readCaseTestExpr(void) { READ_LOCALS(CaseTestExpr); READ_OID_FIELD(typeId); READ_INT_FIELD(typeMod); READ_OID_FIELD(collation); READ_DONE(); } /* * _readArrayExpr */ static ArrayExpr * _readArrayExpr(void) { READ_LOCALS(ArrayExpr); READ_OID_FIELD(array_typeid); READ_OID_FIELD(array_collid); READ_OID_FIELD(element_typeid); READ_NODE_FIELD(elements); READ_BOOL_FIELD(multidims); READ_LOCATION_FIELD(location); READ_DONE(); } /* * _readRowExpr */ static RowExpr * _readRowExpr(void) { READ_LOCALS(RowExpr); READ_NODE_FIELD(args); READ_OID_FIELD(row_typeid); READ_ENUM_FIELD(row_format, CoercionForm); READ_NODE_FIELD(colnames); READ_LOCATION_FIELD(location); READ_DONE(); } /* * _readRowCompareExpr */ static RowCompareExpr * _readRowCompareExpr(void) { READ_LOCALS(RowCompareExpr); READ_ENUM_FIELD(rctype, RowCompareType); READ_NODE_FIELD(opnos); READ_NODE_FIELD(opfamilies); READ_NODE_FIELD(inputcollids); READ_NODE_FIELD(largs); READ_NODE_FIELD(rargs); READ_DONE(); } /* * _readCoalesceExpr */ static CoalesceExpr * _readCoalesceExpr(void) { READ_LOCALS(CoalesceExpr); READ_OID_FIELD(coalescetype); READ_OID_FIELD(coalescecollid); READ_NODE_FIELD(args); READ_LOCATION_FIELD(location); READ_DONE(); } /* * _readMinMaxExpr */ static MinMaxExpr * _readMinMaxExpr(void) { READ_LOCALS(MinMaxExpr); READ_OID_FIELD(minmaxtype); READ_OID_FIELD(minmaxcollid); READ_OID_FIELD(inputcollid); READ_ENUM_FIELD(op, MinMaxOp); READ_NODE_FIELD(args); READ_LOCATION_FIELD(location); READ_DONE(); } /* * _readXmlExpr */ static XmlExpr * _readXmlExpr(void) { READ_LOCALS(XmlExpr); READ_ENUM_FIELD(op, XmlExprOp); READ_STRING_FIELD(name); READ_NODE_FIELD(named_args); READ_NODE_FIELD(arg_names); READ_NODE_FIELD(args); READ_ENUM_FIELD(xmloption, XmlOptionType); READ_OID_FIELD(type); READ_INT_FIELD(typmod); READ_LOCATION_FIELD(location); READ_DONE(); } /* * _readNullTest */ static NullTest * _readNullTest(void) { READ_LOCALS(NullTest); READ_NODE_FIELD(arg); READ_ENUM_FIELD(nulltesttype, NullTestType); READ_BOOL_FIELD(argisrow); READ_LOCATION_FIELD(location); READ_DONE(); } /* * _readBooleanTest */ static BooleanTest * _readBooleanTest(void) { READ_LOCALS(BooleanTest); READ_NODE_FIELD(arg); READ_ENUM_FIELD(booltesttype, BoolTestType); READ_LOCATION_FIELD(location); READ_DONE(); } /* * _readCoerceToDomain */ static CoerceToDomain * _readCoerceToDomain(void) { READ_LOCALS(CoerceToDomain); READ_NODE_FIELD(arg); READ_OID_FIELD(resulttype); READ_INT_FIELD(resulttypmod); READ_OID_FIELD(resultcollid); READ_ENUM_FIELD(coercionformat, CoercionForm); READ_LOCATION_FIELD(location); READ_DONE(); } /* * _readCoerceToDomainValue */ static CoerceToDomainValue * _readCoerceToDomainValue(void) { READ_LOCALS(CoerceToDomainValue); READ_OID_FIELD(typeId); READ_INT_FIELD(typeMod); READ_OID_FIELD(collation); READ_LOCATION_FIELD(location); READ_DONE(); } /* * _readSetToDefault */ static SetToDefault * _readSetToDefault(void) { READ_LOCALS(SetToDefault); READ_OID_FIELD(typeId); READ_INT_FIELD(typeMod); READ_OID_FIELD(collation); READ_LOCATION_FIELD(location); READ_DONE(); } /* * _readCurrentOfExpr */ static CurrentOfExpr * _readCurrentOfExpr(void) { READ_LOCALS(CurrentOfExpr); READ_UINT_FIELD(cvarno); READ_STRING_FIELD(cursor_name); READ_INT_FIELD(cursor_param); READ_DONE(); } /* * _readInferenceElem */ static InferenceElem * _readInferenceElem(void) { READ_LOCALS(InferenceElem); READ_NODE_FIELD(expr); READ_OID_FIELD(infercollid); READ_OID_FIELD(inferopfamily); READ_OID_FIELD(inferopcinputtype); READ_DONE(); } /* * _readTargetEntry */ static TargetEntry * _readTargetEntry(void) { READ_LOCALS(TargetEntry); READ_NODE_FIELD(expr); READ_INT_FIELD(resno); READ_STRING_FIELD(resname); READ_UINT_FIELD(ressortgroupref); READ_OID_FIELD(resorigtbl); READ_INT_FIELD(resorigcol); READ_BOOL_FIELD(resjunk); READ_DONE(); } /* * _readRangeTblRef */ static RangeTblRef * _readRangeTblRef(void) { READ_LOCALS(RangeTblRef); READ_INT_FIELD(rtindex); READ_DONE(); } /* * _readJoinExpr */ static JoinExpr * _readJoinExpr(void) { READ_LOCALS(JoinExpr); READ_ENUM_FIELD(jointype, JoinType); READ_BOOL_FIELD(isNatural); READ_NODE_FIELD(larg); READ_NODE_FIELD(rarg); READ_NODE_FIELD(usingClause); READ_NODE_FIELD(quals); READ_NODE_FIELD(alias); READ_INT_FIELD(rtindex); READ_DONE(); } /* * _readFromExpr */ static FromExpr * _readFromExpr(void) { READ_LOCALS(FromExpr); READ_NODE_FIELD(fromlist); READ_NODE_FIELD(quals); READ_DONE(); } /* * _readOnConflictExpr */ static OnConflictExpr * _readOnConflictExpr(void) { READ_LOCALS(OnConflictExpr); READ_ENUM_FIELD(action, OnConflictAction); READ_NODE_FIELD(arbiterElems); READ_NODE_FIELD(arbiterWhere); READ_NODE_FIELD(onConflictSet); READ_NODE_FIELD(onConflictWhere); READ_OID_FIELD(constraint); READ_INT_FIELD(exclRelIndex); READ_NODE_FIELD(exclRelTlist); READ_DONE(); } /* * Stuff from parsenodes.h. */ /* * _readRangeTblEntry */ static RangeTblEntry * _readRangeTblEntry(void) { READ_LOCALS(RangeTblEntry); /* put alias + eref first to make dump more legible */ READ_NODE_FIELD(alias); READ_NODE_FIELD(eref); READ_ENUM_FIELD(rtekind, RTEKind); switch (local_node->rtekind) { case RTE_RELATION: READ_OID_FIELD(relid); READ_CHAR_FIELD(relkind); READ_NODE_FIELD(tablesample); break; case RTE_SUBQUERY: READ_NODE_FIELD(subquery); READ_BOOL_FIELD(security_barrier); break; case RTE_JOIN: READ_ENUM_FIELD(jointype, JoinType); READ_NODE_FIELD(joinaliasvars); break; case RTE_FUNCTION: READ_NODE_FIELD(functions); READ_BOOL_FIELD(funcordinality); break; case RTE_VALUES: READ_NODE_FIELD(values_lists); READ_NODE_FIELD(values_collations); break; case RTE_CTE: READ_STRING_FIELD(ctename); READ_UINT_FIELD(ctelevelsup); READ_BOOL_FIELD(self_reference); READ_NODE_FIELD(ctecoltypes); READ_NODE_FIELD(ctecoltypmods); READ_NODE_FIELD(ctecolcollations); break; default: elog(ERROR, "unrecognized RTE kind: %d", (int) local_node->rtekind); break; } READ_BOOL_FIELD(lateral); READ_BOOL_FIELD(inh); READ_BOOL_FIELD(inFromCl); READ_UINT_FIELD(requiredPerms); READ_OID_FIELD(checkAsUser); READ_BITMAPSET_FIELD(selectedCols); READ_BITMAPSET_FIELD(insertedCols); READ_BITMAPSET_FIELD(updatedCols); READ_NODE_FIELD(securityQuals); READ_DONE(); } /* * _readRangeTblFunction */ static RangeTblFunction * _readRangeTblFunction(void) { READ_LOCALS(RangeTblFunction); READ_NODE_FIELD(funcexpr); READ_INT_FIELD(funccolcount); READ_NODE_FIELD(funccolnames); READ_NODE_FIELD(funccoltypes); READ_NODE_FIELD(funccoltypmods); READ_NODE_FIELD(funccolcollations); READ_BITMAPSET_FIELD(funcparams); READ_DONE(); } /* * parseNodeString * * Given a character string representing a node tree, parseNodeString creates * the internal node structure. * * The string to be read must already have been loaded into pg_strtok(). */ Node * parseNodeString(void) { void *return_value; READ_TEMP_LOCALS(); token = pg_strtok(&length); #define MATCH(tokname, namelen) \ (length == namelen && memcmp(token, tokname, namelen) == 0) if (MATCH("QUERY", 5)) return_value = _readQuery(); else if (MATCH("WITHCHECKOPTION", 15)) return_value = _readWithCheckOption(); else if (MATCH("SORTGROUPCLAUSE", 15)) return_value = _readSortGroupClause(); else if (MATCH("WINDOWCLAUSE", 12)) return_value = _readWindowClause(); else if (MATCH("ROWMARKCLAUSE", 13)) return_value = _readRowMarkClause(); else if (MATCH("COMMONTABLEEXPR", 15)) return_value = _readCommonTableExpr(); else if (MATCH("RANGETABLESAMPLE", 16)) return_value = _readRangeTableSample(); else if (MATCH("TABLESAMPLECLAUSE", 17)) return_value = _readTableSampleClause(); else if (MATCH("SETOPERATIONSTMT", 16)) return_value = _readSetOperationStmt(); else if (MATCH("ALIAS", 5)) return_value = _readAlias(); else if (MATCH("RANGEVAR", 8)) return_value = _readRangeVar(); else if (MATCH("INTOCLAUSE", 10)) return_value = _readIntoClause(); else if (MATCH("VAR", 3)) return_value = _readVar(); else if (MATCH("CONST", 5)) return_value = _readConst(); else if (MATCH("PARAM", 5)) return_value = _readParam(); else if (MATCH("AGGREF", 6)) return_value = _readAggref(); else if (MATCH("WINDOWFUNC", 10)) return_value = _readWindowFunc(); else if (MATCH("ARRAYREF", 8)) return_value = _readArrayRef(); else if (MATCH("FUNCEXPR", 8)) return_value = _readFuncExpr(); else if (MATCH("NAMEDARGEXPR", 12)) return_value = _readNamedArgExpr(); else if (MATCH("OPEXPR", 6)) return_value = _readOpExpr(); else if (MATCH("DISTINCTEXPR", 12)) return_value = _readDistinctExpr(); else if (MATCH("NULLIFEXPR", 10)) return_value = _readNullIfExpr(); else if (MATCH("SCALARARRAYOPEXPR", 17)) return_value = _readScalarArrayOpExpr(); else if (MATCH("BOOLEXPR", 8)) return_value = _readBoolExpr(); else if (MATCH("SUBLINK", 7)) return_value = _readSubLink(); else if (MATCH("FIELDSELECT", 11)) return_value = _readFieldSelect(); else if (MATCH("FIELDSTORE", 10)) return_value = _readFieldStore(); else if (MATCH("RELABELTYPE", 11)) return_value = _readRelabelType(); else if (MATCH("COERCEVIAIO", 11)) return_value = _readCoerceViaIO(); else if (MATCH("ARRAYCOERCEEXPR", 15)) return_value = _readArrayCoerceExpr(); else if (MATCH("CONVERTROWTYPEEXPR", 18)) return_value = _readConvertRowtypeExpr(); else if (MATCH("COLLATE", 7)) return_value = _readCollateExpr(); else if (MATCH("CASE", 4)) return_value = _readCaseExpr(); else if (MATCH("WHEN", 4)) return_value = _readCaseWhen(); else if (MATCH("CASETESTEXPR", 12)) return_value = _readCaseTestExpr(); else if (MATCH("ARRAY", 5)) return_value = _readArrayExpr(); else if (MATCH("ROW", 3)) return_value = _readRowExpr(); else if (MATCH("ROWCOMPARE", 10)) return_value = _readRowCompareExpr(); else if (MATCH("COALESCE", 8)) return_value = _readCoalesceExpr(); else if (MATCH("MINMAX", 6)) return_value = _readMinMaxExpr(); else if (MATCH("XMLEXPR", 7)) return_value = _readXmlExpr(); else if (MATCH("NULLTEST", 8)) return_value = _readNullTest(); else if (MATCH("BOOLEANTEST", 11)) return_value = _readBooleanTest(); else if (MATCH("COERCETODOMAIN", 14)) return_value = _readCoerceToDomain(); else if (MATCH("COERCETODOMAINVALUE", 19)) return_value = _readCoerceToDomainValue(); else if (MATCH("SETTODEFAULT", 12)) return_value = _readSetToDefault(); else if (MATCH("CURRENTOFEXPR", 13)) return_value = _readCurrentOfExpr(); else if (MATCH("INFERENCEELEM", 13)) return_value = _readInferenceElem(); else if (MATCH("TARGETENTRY", 11)) return_value = _readTargetEntry(); else if (MATCH("RANGETBLREF", 11)) return_value = _readRangeTblRef(); else if (MATCH("JOINEXPR", 8)) return_value = _readJoinExpr(); else if (MATCH("FROMEXPR", 8)) return_value = _readFromExpr(); else if (MATCH("ONCONFLICTEXPR", 14)) return_value = _readOnConflictExpr(); else if (MATCH("RTE", 3)) return_value = _readRangeTblEntry(); else if (MATCH("RANGETBLFUNCTION", 16)) return_value = _readRangeTblFunction(); else if (MATCH("NOTIFY", 6)) return_value = _readNotifyStmt(); else if (MATCH("DECLARECURSOR", 13)) return_value = _readDeclareCursorStmt(); else { elog(ERROR, "badly formatted node string \"%.32s\"...", token); return_value = NULL; /* keep compiler quiet */ } return (Node *) return_value; } /* * readDatum * * Given a string representation of a constant, recreate the appropriate * Datum. The string representation embeds length info, but not byValue, * so we must be told that. */ static Datum readDatum(bool typbyval) { Size length, i; int tokenLength; char *token; Datum res; char *s; /* * read the actual length of the value */ token = pg_strtok(&tokenLength); length = atoui(token); token = pg_strtok(&tokenLength); /* read the '[' */ if (token == NULL || token[0] != '[') elog(ERROR, "expected \"[\" to start datum, but got \"%s\"; length = %zu", token ? (const char *) token : "[NULL]", length); if (typbyval) { if (length > (Size) sizeof(Datum)) elog(ERROR, "byval datum but length = %zu", length); res = (Datum) 0; s = (char *) (&res); for (i = 0; i < (Size) sizeof(Datum); i++) { token = pg_strtok(&tokenLength); s[i] = (char) atoi(token); } } else if (length <= 0) res = (Datum) NULL; else { s = (char *) palloc(length); for (i = 0; i < length; i++) { token = pg_strtok(&tokenLength); s[i] = (char) atoi(token); } res = PointerGetDatum(s); } token = pg_strtok(&tokenLength); /* read the ']' */ if (token == NULL || token[0] != ']') elog(ERROR, "expected \"]\" to end datum, but got \"%s\"; length = %zu", token ? (const char *) token : "[NULL]", length); return res; }