From c3ad77375062cfbeee7d4ce7e0fe274a5db76453 Mon Sep 17 00:00:00 2001 From: Daniel Farina Date: Fri, 24 Feb 2012 01:31:54 -0800 Subject: [PATCH] Introduce NodeKey as a service to extensions in the backend Signed-off-by: Daniel Farina --- src/backend/nodes/copyfuncs.c | 4 ++-- src/backend/nodes/outfuncs.c | 6 ------ src/backend/nodes/readfuncs.c | 7 +++---- src/backend/optimizer/plan/planner.c | 2 +- src/backend/parser/analyze.c | 2 +- src/include/nodes/parsenodes.h | 4 ++-- src/include/nodes/plannodes.h | 4 +++- src/include/nodes/primnodes.h | 14 ++++++++++++++ 8 files changed, 26 insertions(+), 17 deletions(-) *** a/src/backend/nodes/copyfuncs.c --- b/src/backend/nodes/copyfuncs.c *************** *** 91,97 **** _copyPlannedStmt(const PlannedStmt *from) COPY_NODE_FIELD(relationOids); COPY_NODE_FIELD(invalItems); COPY_SCALAR_FIELD(nParamExec); ! COPY_SCALAR_FIELD(queryId); return newnode; } --- 91,97 ---- COPY_NODE_FIELD(relationOids); COPY_NODE_FIELD(invalItems); COPY_SCALAR_FIELD(nParamExec); ! COPY_SCALAR_FIELD(nodeKey); return newnode; } *************** *** 2415,2421 **** _copyQuery(const Query *from) COPY_SCALAR_FIELD(commandType); COPY_SCALAR_FIELD(querySource); ! COPY_SCALAR_FIELD(queryId); COPY_SCALAR_FIELD(canSetTag); COPY_NODE_FIELD(utilityStmt); COPY_SCALAR_FIELD(resultRelation); --- 2415,2421 ---- COPY_SCALAR_FIELD(commandType); COPY_SCALAR_FIELD(querySource); ! COPY_SCALAR_FIELD(nodeKey); COPY_SCALAR_FIELD(canSetTag); COPY_NODE_FIELD(utilityStmt); COPY_SCALAR_FIELD(resultRelation); *** a/src/backend/nodes/outfuncs.c --- b/src/backend/nodes/outfuncs.c *************** *** 81,90 **** #define WRITE_LOCATION_FIELD(fldname) \ appendStringInfo(str, " :" CppAsString(fldname) " %d", node->fldname) - /* Write a query id field */ - #define WRITE_QUERYID_FIELD(fldname) \ - ((void) 0) - /* Write a Node field */ #define WRITE_NODE_FIELD(fldname) \ (appendStringInfo(str, " :" CppAsString(fldname) " "), \ --- 81,86 ---- *************** *** 259,265 **** _outPlannedStmt(StringInfo str, const PlannedStmt *node) WRITE_NODE_FIELD(relationOids); WRITE_NODE_FIELD(invalItems); WRITE_INT_FIELD(nParamExec); - WRITE_QUERYID_FIELD(queryId); } /* --- 255,260 ---- *************** *** 2164,2170 **** _outQuery(StringInfo str, const Query *node) WRITE_ENUM_FIELD(commandType, CmdType); WRITE_ENUM_FIELD(querySource, QuerySource); - WRITE_QUERYID_FIELD(query_id); WRITE_BOOL_FIELD(canSetTag); /* --- 2159,2164 ---- *** a/src/backend/nodes/readfuncs.c --- b/src/backend/nodes/readfuncs.c *************** *** 116,124 **** token = pg_strtok(&length); /* get field value */ \ local_node->fldname = -1 /* set field to "unknown" */ - /* NOOP */ - #define READ_QUERYID_FIELD(fldname) \ - ((void) 0) /* Read a Node field */ #define READ_NODE_FIELD(fldname) \ token = pg_strtok(&length); /* skip :fldname */ \ --- 116,121 ---- *************** *** 206,212 **** _readQuery(void) READ_ENUM_FIELD(commandType, CmdType); READ_ENUM_FIELD(querySource, QuerySource); - READ_QUERYID_FIELD(query_id); READ_BOOL_FIELD(canSetTag); READ_NODE_FIELD(utilityStmt); READ_INT_FIELD(resultRelation); --- 203,208 ---- *************** *** 234,239 **** _readQuery(void) --- 230,238 ---- READ_NODE_FIELD(setOperations); READ_NODE_FIELD(constraintDeps); + /* Set up the unique but arbitrary nodeKey */ + local_node->nodeKey = (NodeKey) local_node; + READ_DONE(); } *** a/src/backend/optimizer/plan/planner.c --- b/src/backend/optimizer/plan/planner.c *************** *** 240,246 **** standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams) result->relationOids = glob->relationOids; result->invalItems = glob->invalItems; result->nParamExec = list_length(glob->paramlist); ! result->queryId = parse->queryId; return result; } --- 240,246 ---- result->relationOids = glob->relationOids; result->invalItems = glob->invalItems; result->nParamExec = list_length(glob->paramlist); ! result->nodeKey = parse->nodeKey; return result; } *** a/src/backend/parser/analyze.c --- b/src/backend/parser/analyze.c *************** *** 245,250 **** transformStmt(ParseState *pstate, Node *parseTree) --- 245,251 ---- /* Mark as original query until we learn differently */ result->querySource = QSRC_ORIGINAL; result->canSetTag = true; + result->nodeKey = (NodeKey) result; return result; } *************** *** 905,911 **** transformSelectStmt(ParseState *pstate, SelectStmt *stmt) ListCell *l; qry->commandType = CMD_SELECT; - qry->queryId = 0; /* process the WITH clause independently of all else */ if (stmt->withClause) --- 906,911 ---- *** a/src/include/nodes/parsenodes.h --- b/src/include/nodes/parsenodes.h *************** *** 103,110 **** typedef struct Query QuerySource querySource; /* where did I come from? */ ! uint32 queryId; /* query identifier that can be set by plugins. ! * Will be copied to resulting PlannedStmt. */ bool canSetTag; /* do I set the command result tag? */ --- 103,110 ---- QuerySource querySource; /* where did I come from? */ ! NodeKey nodeKey; /* query identifier so hooks can associate ! * queries to plans */ bool canSetTag; /* do I set the command result tag? */ *** a/src/include/nodes/plannodes.h --- b/src/include/nodes/plannodes.h *************** *** 68,74 **** typedef struct PlannedStmt int nParamExec; /* number of PARAM_EXEC Params used */ ! uint32 queryId; /* query identifier carried from query tree */ } PlannedStmt; /* macro for fetching the Plan associated with a SubPlan node */ --- 68,76 ---- int nParamExec; /* number of PARAM_EXEC Params used */ ! NodeKey nodeKey; /* Possesses a value that can be used to ! * uniquely identify the source of this plan ! * within one backend. */ } PlannedStmt; /* macro for fetching the Plan associated with a SubPlan node */ *** a/src/include/nodes/primnodes.h --- b/src/include/nodes/primnodes.h *************** *** 1266,1269 **** typedef struct FromExpr --- 1266,1283 ---- Node *quals; /* qualifiers on join, if any */ } FromExpr; + /* + * NodeKey - Associate nodes together throughout query parse and planning + * + * This is currently implemented as intptr_t to piggyback on memory allocation + * as a way to derive unique, unambiguous keys within a backend with low + * overhead. This means that given this implementation of NodeKey that the + * target of the pointer deriving the NodeKey *must* remain allocated, or it + * risks being reused. + * + */ + typedef uintptr_t NodeKey; + + #define NodeKeyDefined(nk) ((nk) != (NodeKey) NULL) + #endif /* PRIMNODES_H */