]> granicus.if.org Git - postgresql/commitdiff
Add castNode(type, ptr) for safe casting between NodeTag based types.
authorAndres Freund <andres@anarazel.de>
Fri, 27 Jan 2017 00:47:03 +0000 (16:47 -0800)
committerAndres Freund <andres@anarazel.de>
Fri, 27 Jan 2017 00:47:03 +0000 (16:47 -0800)
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-

src/backend/tcop/postgres.c
src/include/nodes/nodes.h

index a7558255a5006d015fdc4116dbf30ac680c19301..6bb8701aa99dd7eb398dfd4b040545a703ed5040 100644 (file)
@@ -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)
index 6b850e4bc4ecbd4aded4db991168900144fea02f..f7fd8ec6bec2b6dd5ec7a9ee2fac1afc13bdde21 100644 (file)
@@ -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
  * ----------------------------------------------------------------