fix 'ERROR: unrecognized token' failures in _readWindowAgg()
authorTomas Vondra <[email protected]>
Fri, 20 Jan 2017 23:34:46 +0000 (00:34 +0100)
committerTomas Vondra <[email protected]>
Fri, 20 Jan 2017 23:53:36 +0000 (00:53 +0100)
The _outWindowAgg() and _readWindowAgg() were inconsistent, resulting
in failures in stringToNode(). In particular _outWindowAgg() was
producing output with tokens :partOperations and :ordOperations, while
_readWindowAgg() expected :partOperators and :ordOperators.

Perhaps more importantly, _readWindowAgg() used READ_OID_ARRAY marco
to parse :ordOperators, but the macro ignores portable_output flag.
So parsing the string failed.

Fixed mostly by reverting to the XL 9.5 code.

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

index 4769f17a8f5462e5ebbf2d8fd989f164e6309d9e..293da7f1c9d7817a92d6ae6e1e3548c67a86c361 100644 (file)
@@ -1112,7 +1112,7 @@ _outWindowAgg(StringInfo str, const WindowAgg *node)
        for (i = 0; i < node->partNumCols; i++)
                appendStringInfo(str, " %d", node->partColIdx[i]);
 
-       appendStringInfoString(str, " :partOperations");
+       appendStringInfoString(str, " :partOperators");
        for (i = 0; i < node->partNumCols; i++)
 #ifdef XCP
                if (portable_output)
@@ -1148,7 +1148,7 @@ _outWindowAgg(StringInfo str, const WindowAgg *node)
        for (i = 0; i < node->ordNumCols; i++)
                appendStringInfo(str, " %d", node->ordColIdx[i]);
 
-       appendStringInfoString(str, " :ordOperations");
+       appendStringInfoString(str, " :ordOperators");
        for (i = 0; i < node->ordNumCols; i++)
 #ifdef XCP
                if (portable_output)
index 63327aac745fb6035f84e9bdafb486fa7ae7c96c..023d409f9117e4f8d5f1e0a5ddc8bdc14b18daf6 100644 (file)
@@ -2940,17 +2940,123 @@ _readAgg(void)
 static WindowAgg *
 _readWindowAgg(void)
 {
-       READ_LOCALS(WindowAgg);
+       int i;
 
-       ReadCommonPlan(&local_node->plan);
+       READ_PLAN_FIELDS(WindowAgg);
 
        READ_UINT_FIELD(winref);
        READ_INT_FIELD(partNumCols);
-       READ_ATTRNUMBER_ARRAY(partColIdx, local_node->partNumCols);
-       READ_OID_ARRAY(partOperators, local_node->partNumCols);
+
+       token = pg_strtok(&length);             /* skip :partColIdx */
+       local_node->partColIdx = (AttrNumber *) palloc(local_node->partNumCols * sizeof(AttrNumber));
+       for (i = 0; i < local_node->partNumCols; i++)
+       {
+               token = pg_strtok(&length);
+               local_node->partColIdx[i] = atoi(token);
+       }
+
+       token = pg_strtok(&length);             /* skip :partOperators */
+       local_node->partOperators = (Oid *) palloc(local_node->partNumCols * sizeof(Oid));
+       for (i = 0; i < local_node->partNumCols; i++)
+       {
+               token = pg_strtok(&length);
+               if (portable_input)
+               {
+                       char       *nspname; /* namespace name */
+                       char       *oprname; /* operator name */
+                       char       *leftnspname; /* left type namespace */
+                       char       *leftname; /* left type name */
+                       Oid                     oprleft; /* left type */
+                       char       *rightnspname; /* right type namespace */
+                       char       *rightname; /* right type name */
+                       Oid                     oprright; /* right type */
+                       /* token is already set to nspname */
+                       nspname = nullable_string(token, length);
+                       token = pg_strtok(&length); /* get operator name */
+                       oprname = nullable_string(token, length);
+                       token = pg_strtok(&length); /* left type namespace */
+                       leftnspname = nullable_string(token, length);
+                       token = pg_strtok(&length); /* left type name */
+                       leftname = nullable_string(token, length);
+                       token = pg_strtok(&length); /* right type namespace */
+                       rightnspname = nullable_string(token, length);
+                       token = pg_strtok(&length); /* right type name */
+                       rightname = nullable_string(token, length);
+                       if (leftname)
+                               oprleft = get_typname_typid(leftname,
+                                                                                       NSP_OID(leftnspname));
+                       else
+                               oprleft = InvalidOid;
+                       if (rightname)
+                               oprright = get_typname_typid(rightname,
+                                                                                        NSP_OID(rightnspname));
+                       else
+                               oprright = InvalidOid;
+                       local_node->partOperators[i] = get_operid(oprname,
+                                                                                                         oprleft,
+                                                                                                         oprright,
+                                                                                                         NSP_OID(nspname));
+               }
+               else
+                       local_node->partOperators[i] = atooid(token);
+       }
+
        READ_INT_FIELD(ordNumCols);
-       READ_ATTRNUMBER_ARRAY(ordColIdx, local_node->ordNumCols);
-       READ_OID_ARRAY(ordOperators, local_node->ordNumCols);
+
+       token = pg_strtok(&length);             /* skip :ordColIdx */
+       local_node->ordColIdx = (AttrNumber *) palloc(local_node->ordNumCols * sizeof(AttrNumber));
+       for (i = 0; i < local_node->ordNumCols; i++)
+       {
+               token = pg_strtok(&length);
+               local_node->ordColIdx[i] = atoi(token);
+       }
+
+       token = pg_strtok(&length);             /* skip :ordOperators */
+       local_node->ordOperators = (Oid *) palloc(local_node->ordNumCols * sizeof(Oid));
+       for (i = 0; i < local_node->ordNumCols; i++)
+       {
+               token = pg_strtok(&length);
+               if (portable_input)
+               {
+                       char       *nspname; /* namespace name */
+                       char       *oprname; /* operator name */
+                       char       *leftnspname; /* left type namespace */
+                       char       *leftname; /* left type name */
+                       Oid                     oprleft; /* left type */
+                       char       *rightnspname; /* right type namespace */
+                       char       *rightname; /* right type name */
+                       Oid                     oprright; /* right type */
+                       /* token is already set to nspname */
+                       nspname = nullable_string(token, length);
+                       token = pg_strtok(&length); /* get operator name */
+                       oprname = nullable_string(token, length);
+                       token = pg_strtok(&length); /* left type namespace */
+                       leftnspname = nullable_string(token, length);
+                       token = pg_strtok(&length); /* left type name */
+                       leftname = nullable_string(token, length);
+                       token = pg_strtok(&length); /* right type namespace */
+                       rightnspname = nullable_string(token, length);
+                       token = pg_strtok(&length); /* right type name */
+                       rightname = nullable_string(token, length);
+                       if (leftname)
+                               oprleft = get_typname_typid(leftname,
+                                                                                       NSP_OID(leftnspname));
+                       else
+                               oprleft = InvalidOid;
+                       if (rightname)
+                               oprright = get_typname_typid(rightname,
+                                                                                        NSP_OID(rightnspname));
+                       else
+                               oprright = InvalidOid;
+                       local_node->ordOperators[i] = get_operid(oprname,
+                                                                                                        oprleft,
+                                                                                                        oprright,
+                                                                                                        NSP_OID(nspname));
+               }
+               else
+                       local_node->ordOperators[i] = atooid(token);
+       }
+
        READ_INT_FIELD(frameOptions);
        READ_NODE_FIELD(startOffset);
        READ_NODE_FIELD(endOffset);