summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndres Freund <andres@anarazel.de>2017-01-26 16:47:04 -0800
committerAndres Freund <andres@anarazel.de>2017-01-26 16:47:04 -0800
commit14d0e290cbe72aac7911c159f40406dd7242353e (patch)
tree3a5ec612fb93eb80e9376d37012bc63d04119e86
parentfe6120f9b359d3ac20f235fbf9938bcd850b1598 (diff)
downloadpostgresql-14d0e290cbe72aac7911c159f40406dd7242353e.tar.gz
Add castNode(type, ptr) for safe casting between NodeTag based types.
The new function allows to cast from one NodeTag based type to another, while asserting that the conversion is valid. This replaces the common pattern of doing a cast and a Assert(IsA(ptr, type)) close-by. As this seems likely to be used pervasively, we decided to backpatch this change the addition of this macro. Otherwise backpatched fixes are more likely not to work on back-branches. On branches before 9.6, where we do not yet rely on inline functions being available, the type assertion is only performed if PG_USE_INLINE support is detected. The cast obviously is performed regardless. For the benefit of verifying the macro compiles in the back-branches, this commit contains a single use of the new macro. On master, a somewhat larger conversion will be committed separately. Author: Peter Eisentraut and Andres Freund Reviewed-By: Tom Lane Discussion: https://postgr.es/m/c5d387d9-3440-f5e0-f9d4-71d53b9fbe52@2ndquadrant.com Backpatch: 9.2-
-rw-r--r--src/backend/tcop/postgres.c2
-rw-r--r--src/include/nodes/nodes.h22
2 files changed, 23 insertions, 1 deletions
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 12861ac454..83281a09aa 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -824,7 +824,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 54bf6895f9..26d0f42d12 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -480,6 +480,28 @@ 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). If
+ * inline functions are not available - only a small number of platforms -
+ * don't Assert, but use the non-checking version.
+ */
+#if defined(USE_ASSERT_CHECKING) && defined(PG_USE_INLINE)
+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
* ----------------------------------------------------------------