Handle Aggref->aggargtypes in out/readfuncs.c
authorTomas Vondra <[email protected]>
Tue, 19 Sep 2017 21:06:46 +0000 (23:06 +0200)
committerTomas Vondra <[email protected]>
Tue, 19 Sep 2017 21:06:46 +0000 (23:06 +0200)
When communicating with other nodes, we send names of objects instead
of OIDs as those are assigned on each node independently. We failed to
do this for Aggref->aggargtypes, which worked fine for built-in data
types (those have the same OID on all nodes), but resulted in failures
for custom data types (like for example FIXEDDECIMAL).

   ERROR:  cache lookup failed for type 16731

This fixes it by implementing READ/WRITE_TYPID_LIST_FIELD, similarly
to what we had for RELID.

Note: Turns out the WRITE_RELID_LIST_FIELD was broken, but apparently
we never call it in XL as it's only used for arbiterIndexes field. So
fix that too, in case we enable the feature in the future.

src/backend/nodes/outfuncs.c
src/backend/nodes/readfuncs.c

index cf05a613428e52eb586b6dd4314d003f460e3902..99b70b717fe08fa3ee5997c02eb78c8b46ce643e 100644 (file)
@@ -173,18 +173,42 @@ static void outChar(StringInfo str, char c);
                                Oid relid = lfirst_oid(lc); \
                                appendStringInfoString(str, sep); \
                                WRITE_RELID_INTERNAL(relid); \
-                               sep = ","; \
+                               sep = " , "; \
                        } \
-                       appendStringInfoChar(str, ')'); \
+                       appendStringInfoString(str, " )"); \
                } \
        }  while (0)
 
+#define WRITE_TYPID_INTERNAL(typid) \
+       (outToken(str, OidIsValid(typid) ? NSP_NAME(get_typ_namespace(typid)) : NULL), \
+        appendStringInfoChar(str, ' '), \
+        outToken(str, OidIsValid(typid) ? get_typ_name(typid) : NULL))
+
 /* write an OID which is a data type OID */
 #define WRITE_TYPID_FIELD(fldname) \
        (appendStringInfo(str, " :" CppAsString(fldname) " "), \
-        outToken(str, OidIsValid(node->fldname) ? NSP_NAME(get_typ_namespace(node->fldname)) : NULL), \
-        appendStringInfoChar(str, ' '), \
-        outToken(str, OidIsValid(node->fldname) ? get_typ_name(node->fldname) : NULL))
+        WRITE_TYPID_INTERNAL(node->fldname))
+
+#define WRITE_TYPID_LIST_FIELD(fldname) \
+       do { \
+               ListCell *lc; \
+               char *sep = ""; \
+               appendStringInfo(str, " :" CppAsString(fldname) " "); \
+               if (node->fldname == NIL || list_length(node->fldname) == 0) \
+                       appendStringInfoString(str, "<>"); \
+               else \
+               { \
+                       appendStringInfoChar(str, '('); \
+                       foreach (lc, node->fldname) \
+                       { \
+                               Oid typid = lfirst_oid(lc); \
+                               appendStringInfoString(str, sep); \
+                               WRITE_TYPID_INTERNAL(typid); \
+                               sep = " , "; \
+                       } \
+                       appendStringInfoString(str, " )"); \
+               } \
+       }  while (0)
 
 /* write an OID which is a function OID */
 #define WRITE_FUNCID_FIELD(fldname) \
@@ -1868,6 +1892,11 @@ _outAggref(StringInfo str, const Aggref *node)
        else
 #endif
        WRITE_OID_FIELD(aggtranstype);
+#ifdef XCP
+       if (portable_output)
+               WRITE_TYPID_LIST_FIELD(aggargtypes);
+       else
+#endif
        WRITE_NODE_FIELD(aggargtypes);
        WRITE_NODE_FIELD(aggdirectargs);
        WRITE_NODE_FIELD(args);
index dd47b2698cb405b07aafe6526db200b8f574759d..a3bfe81afd2ca0a420b0c41ba9f88d5b0e33e5f4 100644 (file)
@@ -243,20 +243,53 @@ set_portable_input(bool value)
        } while (0)
 
 /* Read data type identifier and lookup the OID */
-#define READ_TYPID_FIELD(fldname) \
+#define READ_TYPID_INTERNAL(typid) \
        do { \
                char       *nspname; /* namespace name */ \
                char       *typname; /* data type name */ \
-               token = pg_strtok(&length);             /* skip :fldname */ \
                token = pg_strtok(&length); /* get nspname */ \
                nspname = nullable_string(token, length); \
                token = pg_strtok(&length); /* get typname */ \
                typname = nullable_string(token, length); \
                if (typname) \
-                       local_node->fldname = get_typname_typid(typname, \
-                                                                                                       NSP_OID(nspname)); \
+               { \
+                       typid = get_typname_typid(typname, \
+                                                                               NSP_OID(nspname)); \
+                       if (!OidIsValid((typid))) \
+                               elog(WARNING, "could not find OID for type %s.%s", nspname,\
+                                               typname); \
+               } \
                else \
-                       local_node->fldname = InvalidOid; \
+                       typid = InvalidOid; \
+       } while (0)
+
+#define READ_TYPID_FIELD(fldname) \
+       do { \
+               Oid typid; \
+               token = pg_strtok(&length);             /* skip :fldname */ \
+               READ_TYPID_INTERNAL(typid); \
+               local_node->fldname = typid; \
+       } while (0)
+
+#define READ_TYPID_LIST_FIELD(fldname) \
+       do { \
+               token = pg_strtok(&length);             /* skip :fldname */ \
+               token = pg_strtok(&length);     /* skip '(' */ \
+               if (length > 0 ) \
+               { \
+                       Assert(token[0] == '('); \
+                       for (;;) \
+                       { \
+                               Oid typid; \
+                               READ_TYPID_INTERNAL(typid); \
+                               local_node->fldname = lappend_oid(local_node->fldname, typid); \
+                               token = pg_strtok(&length); \
+                               if (token[0] == ')') \
+                               break; \
+                       } \
+               } \
+               else \
+                       local_node->fldname = NIL; \
        } while (0)
 
 /* Read function identifier and lookup the OID */
@@ -882,6 +915,11 @@ _readAggref(void)
        else
 #endif
        READ_OID_FIELD(aggtranstype);
+#ifdef XCP
+       if (portable_input)
+               READ_TYPID_LIST_FIELD(aggargtypes);
+       else
+#endif
        READ_NODE_FIELD(aggargtypes);
        READ_NODE_FIELD(aggdirectargs);
        READ_NODE_FIELD(args);