diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index a7558255a5..6bb8701aa9 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -844,7 +844,7 @@ pg_plan_queries(List *querytrees, int cursorOptions, ParamListInfo boundParams) foreach(query_list, querytrees) { - Query *query = (Query *) lfirst(query_list); + Query *query = castNode(Query, lfirst(query_list)); Node *stmt; if (query->commandType == CMD_UTILITY) diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h index 6b850e4bc4..f7fd8ec6be 100644 --- a/src/include/nodes/nodes.h +++ b/src/include/nodes/nodes.h @@ -542,6 +542,26 @@ extern PGDLLIMPORT Node *newNodeMacroHolder; #define IsA(nodeptr,_type_) (nodeTag(nodeptr) == T_##_type_) +/* + * castNode(type, ptr) casts ptr to type and, if cassert is enabled, verifies + * that the the c actually has the appropriate type (using it's nodeTag()). + * + * Use an inline function when assertions are enabled, to avoid multiple + * evaluations of the ptr argument (which could e.g. be a function call). + */ +#ifdef USE_ASSERT_CHECKING +static inline Node* +castNodeImpl(enum NodeTag type, void *ptr) +{ + Assert(ptr == NULL || nodeTag(ptr) == type); + return ptr; +} +#define castNode(_type_, nodeptr) ((_type_ *) castNodeImpl(T_##_type_, nodeptr)) +#else +#define castNode(_type_,nodeptr) ((_type_ *)(nodeptr)) +#endif + + /* ---------------------------------------------------------------- * extern declarations follow * ----------------------------------------------------------------