diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index c15303c7bb..62d49c8625 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -846,7 +846,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)); PlannedStmt *stmt; if (query->commandType == CMD_UTILITY) diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h index fa4932a902..b462a5ffde 100644 --- a/src/include/nodes/nodes.h +++ b/src/include/nodes/nodes.h @@ -558,6 +558,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 * ----------------------------------------------------------------