Thread: Re: anonymous composite types

Re: anonymous composite types

From
Joe Conway
Date:
Neil Conway wrote:
 > This does not:
 >
 > create view pg_locks as select l.relation, l.database, l.backendpid,
 > l.mode, l.isgranted from pg_lock_info() as l(relation oid, database oid,
 > backendpid int4, mode text, isgranted bool);
 > ERROR:  badly formatted planstring "COLUMNDEF "...
 >

Reported by Neil Conway -- I never implemented readfuncs.c support for
ColumnDef or TypeName, which is needed so that views can be created on
functions returning type RECORD. Here's a patch.

If there are no objections, please apply.

Thanks,

Joe

Index: src/backend/nodes/outfuncs.c
===================================================================
RCS file: /opt/src/cvs/pgsql-server/src/backend/nodes/outfuncs.c,v
retrieving revision 1.166
diff -c -r1.166 outfuncs.c
*** src/backend/nodes/outfuncs.c    4 Aug 2002 19:48:09 -0000    1.166
--- src/backend/nodes/outfuncs.c    7 Aug 2002 01:26:01 -0000
***************
*** 193,199 ****
      appendStringInfo(str, " TYPENAME :names ");
      _outNode(str, node->names);
      appendStringInfo(str, " :typeid %u :timezone %s :setof %s"
!                      " :pct_type %s typmod %d :arrayBounds ",
                       node->typeid,
                       booltostr(node->timezone),
                       booltostr(node->setof),
--- 193,199 ----
      appendStringInfo(str, " TYPENAME :names ");
      _outNode(str, node->names);
      appendStringInfo(str, " :typeid %u :timezone %s :setof %s"
!                      " :pct_type %s :typmod %d :arrayBounds ",
                       node->typeid,
                       booltostr(node->timezone),
                       booltostr(node->setof),
Index: src/backend/nodes/readfuncs.c
===================================================================
RCS file: /opt/src/cvs/pgsql-server/src/backend/nodes/readfuncs.c,v
retrieving revision 1.127
diff -c -r1.127 readfuncs.c
*** src/backend/nodes/readfuncs.c    4 Aug 2002 19:48:09 -0000    1.127
--- src/backend/nodes/readfuncs.c    7 Aug 2002 01:38:41 -0000
***************
*** 1465,1470 ****
--- 1465,1544 ----
      return local_node;
  }

+ static ColumnDef *
+ _readColumnDef(void)
+ {
+     ColumnDef  *local_node;
+     char       *token;
+     int            length;
+
+     local_node = makeNode(ColumnDef);
+
+     token = pg_strtok(&length); /* eat :colname */
+     token = pg_strtok(&length); /* now read it */
+     local_node->colname = nullable_string(token, length);
+
+     token = pg_strtok(&length); /* eat :typename */
+     local_node->typename = nodeRead(true); /* now read it */
+
+     token = pg_strtok(&length); /* eat :is_not_null */
+     token = pg_strtok(&length); /* get :is_not_null */
+     local_node->is_not_null = strtobool(token);
+
+     token = pg_strtok(&length); /* eat :raw_default */
+     local_node->raw_default = nodeRead(true); /* now read it */
+
+     token = pg_strtok(&length); /* eat :cooked_default */
+     token = pg_strtok(&length); /* now read it */
+     local_node->cooked_default = nullable_string(token, length);
+
+     token = pg_strtok(&length); /* eat :constraints */
+     local_node->constraints = nodeRead(true);    /* now read it */
+
+     token = pg_strtok(&length); /* eat :support */
+     local_node->support = nodeRead(true); /* now read it */
+
+     return local_node;
+ }
+
+ static TypeName *
+ _readTypeName(void)
+ {
+     TypeName  *local_node;
+     char       *token;
+     int            length;
+
+     local_node = makeNode(TypeName);
+
+     token = pg_strtok(&length); /* eat :names */
+     local_node->names = nodeRead(true); /* now read it */
+
+     token = pg_strtok(&length); /* eat :typeid */
+     token = pg_strtok(&length); /* get typeid */
+     local_node->typeid = atooid(token);
+
+     token = pg_strtok(&length); /* eat :timezone */
+     token = pg_strtok(&length); /* get timezone */
+     local_node->timezone = strtobool(token);
+
+     token = pg_strtok(&length); /* eat :setof */
+     token = pg_strtok(&length); /* get setof */
+     local_node->setof = strtobool(token);
+
+     token = pg_strtok(&length); /* eat :pct_type */
+     token = pg_strtok(&length); /* get pct_type */
+     local_node->pct_type = strtobool(token);
+
+     token = pg_strtok(&length); /* eat :typmod */
+     token = pg_strtok(&length); /* get typmod */
+     local_node->typmod = atoi(token);
+
+     token = pg_strtok(&length); /* eat :arrayBounds */
+     local_node->arrayBounds = nodeRead(true); /* now read it */
+
+     return local_node;
+ }
+
  static ExprFieldSelect *
  _readExprFieldSelect(void)
  {
***************
*** 2092,2097 ****
--- 2166,2175 ----
          return_value = _readRangeVar();
      else if (length == 9 && strncmp(token, "COLUMNREF", length) == 0)
          return_value = _readColumnRef();
+     else if (length == 9 && strncmp(token, "COLUMNDEF", length) == 0)
+         return_value = _readColumnDef();
+     else if (length == 8 && strncmp(token, "TYPENAME", length) == 0)
+         return_value = _readTypeName();
      else if (length == 15 && strncmp(token, "EXPRFIELDSELECT", length) == 0)
          return_value = _readExprFieldSelect();
      else if (length == 5 && strncmp(token, "ALIAS", length) == 0)


Re: anonymous composite types

From
Bruce Momjian
Date:
Your patch has been added to the PostgreSQL unapplied patches list at:

    http://candle.pha.pa.us/cgi-bin/pgpatches

I will try to apply it within the next 48 hours.

---------------------------------------------------------------------------


Joe Conway wrote:
> Neil Conway wrote:
>  > This does not:
>  >
>  > create view pg_locks as select l.relation, l.database, l.backendpid,
>  > l.mode, l.isgranted from pg_lock_info() as l(relation oid, database oid,
>  > backendpid int4, mode text, isgranted bool);
>  > ERROR:  badly formatted planstring "COLUMNDEF "...
>  >
>
> Reported by Neil Conway -- I never implemented readfuncs.c support for
> ColumnDef or TypeName, which is needed so that views can be created on
> functions returning type RECORD. Here's a patch.
>
> If there are no objections, please apply.
>
> Thanks,
>
> Joe
>

> Index: src/backend/nodes/outfuncs.c
> ===================================================================
> RCS file: /opt/src/cvs/pgsql-server/src/backend/nodes/outfuncs.c,v
> retrieving revision 1.166
> diff -c -r1.166 outfuncs.c
> *** src/backend/nodes/outfuncs.c    4 Aug 2002 19:48:09 -0000    1.166
> --- src/backend/nodes/outfuncs.c    7 Aug 2002 01:26:01 -0000
> ***************
> *** 193,199 ****
>       appendStringInfo(str, " TYPENAME :names ");
>       _outNode(str, node->names);
>       appendStringInfo(str, " :typeid %u :timezone %s :setof %s"
> !                      " :pct_type %s typmod %d :arrayBounds ",
>                        node->typeid,
>                        booltostr(node->timezone),
>                        booltostr(node->setof),
> --- 193,199 ----
>       appendStringInfo(str, " TYPENAME :names ");
>       _outNode(str, node->names);
>       appendStringInfo(str, " :typeid %u :timezone %s :setof %s"
> !                      " :pct_type %s :typmod %d :arrayBounds ",
>                        node->typeid,
>                        booltostr(node->timezone),
>                        booltostr(node->setof),
> Index: src/backend/nodes/readfuncs.c
> ===================================================================
> RCS file: /opt/src/cvs/pgsql-server/src/backend/nodes/readfuncs.c,v
> retrieving revision 1.127
> diff -c -r1.127 readfuncs.c
> *** src/backend/nodes/readfuncs.c    4 Aug 2002 19:48:09 -0000    1.127
> --- src/backend/nodes/readfuncs.c    7 Aug 2002 01:38:41 -0000
> ***************
> *** 1465,1470 ****
> --- 1465,1544 ----
>       return local_node;
>   }
>
> + static ColumnDef *
> + _readColumnDef(void)
> + {
> +     ColumnDef  *local_node;
> +     char       *token;
> +     int            length;
> +
> +     local_node = makeNode(ColumnDef);
> +
> +     token = pg_strtok(&length); /* eat :colname */
> +     token = pg_strtok(&length); /* now read it */
> +     local_node->colname = nullable_string(token, length);
> +
> +     token = pg_strtok(&length); /* eat :typename */
> +     local_node->typename = nodeRead(true); /* now read it */
> +
> +     token = pg_strtok(&length); /* eat :is_not_null */
> +     token = pg_strtok(&length); /* get :is_not_null */
> +     local_node->is_not_null = strtobool(token);
> +
> +     token = pg_strtok(&length); /* eat :raw_default */
> +     local_node->raw_default = nodeRead(true); /* now read it */
> +
> +     token = pg_strtok(&length); /* eat :cooked_default */
> +     token = pg_strtok(&length); /* now read it */
> +     local_node->cooked_default = nullable_string(token, length);
> +
> +     token = pg_strtok(&length); /* eat :constraints */
> +     local_node->constraints = nodeRead(true);    /* now read it */
> +
> +     token = pg_strtok(&length); /* eat :support */
> +     local_node->support = nodeRead(true); /* now read it */
> +
> +     return local_node;
> + }
> +
> + static TypeName *
> + _readTypeName(void)
> + {
> +     TypeName  *local_node;
> +     char       *token;
> +     int            length;
> +
> +     local_node = makeNode(TypeName);
> +
> +     token = pg_strtok(&length); /* eat :names */
> +     local_node->names = nodeRead(true); /* now read it */
> +
> +     token = pg_strtok(&length); /* eat :typeid */
> +     token = pg_strtok(&length); /* get typeid */
> +     local_node->typeid = atooid(token);
> +
> +     token = pg_strtok(&length); /* eat :timezone */
> +     token = pg_strtok(&length); /* get timezone */
> +     local_node->timezone = strtobool(token);
> +
> +     token = pg_strtok(&length); /* eat :setof */
> +     token = pg_strtok(&length); /* get setof */
> +     local_node->setof = strtobool(token);
> +
> +     token = pg_strtok(&length); /* eat :pct_type */
> +     token = pg_strtok(&length); /* get pct_type */
> +     local_node->pct_type = strtobool(token);
> +
> +     token = pg_strtok(&length); /* eat :typmod */
> +     token = pg_strtok(&length); /* get typmod */
> +     local_node->typmod = atoi(token);
> +
> +     token = pg_strtok(&length); /* eat :arrayBounds */
> +     local_node->arrayBounds = nodeRead(true); /* now read it */
> +
> +     return local_node;
> + }
> +
>   static ExprFieldSelect *
>   _readExprFieldSelect(void)
>   {
> ***************
> *** 2092,2097 ****
> --- 2166,2175 ----
>           return_value = _readRangeVar();
>       else if (length == 9 && strncmp(token, "COLUMNREF", length) == 0)
>           return_value = _readColumnRef();
> +     else if (length == 9 && strncmp(token, "COLUMNDEF", length) == 0)
> +         return_value = _readColumnDef();
> +     else if (length == 8 && strncmp(token, "TYPENAME", length) == 0)
> +         return_value = _readTypeName();
>       else if (length == 15 && strncmp(token, "EXPRFIELDSELECT", length) == 0)
>           return_value = _readExprFieldSelect();
>       else if (length == 5 && strncmp(token, "ALIAS", length) == 0)
>

>
> ---------------------------(end of broadcast)---------------------------
> TIP 2: you can get off all lists at once with the unregister command
>     (send "unregister YourEmailAddressHere" to majordomo@postgresql.org)

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026

Re: anonymous composite types

From
Bruce Momjian
Date:
Patch applied.  Thanks.

---------------------------------------------------------------------------



Joe Conway wrote:
> Neil Conway wrote:
>  > This does not:
>  >
>  > create view pg_locks as select l.relation, l.database, l.backendpid,
>  > l.mode, l.isgranted from pg_lock_info() as l(relation oid, database oid,
>  > backendpid int4, mode text, isgranted bool);
>  > ERROR:  badly formatted planstring "COLUMNDEF "...
>  >
>
> Reported by Neil Conway -- I never implemented readfuncs.c support for
> ColumnDef or TypeName, which is needed so that views can be created on
> functions returning type RECORD. Here's a patch.
>
> If there are no objections, please apply.
>
> Thanks,
>
> Joe
>

> Index: src/backend/nodes/outfuncs.c
> ===================================================================
> RCS file: /opt/src/cvs/pgsql-server/src/backend/nodes/outfuncs.c,v
> retrieving revision 1.166
> diff -c -r1.166 outfuncs.c
> *** src/backend/nodes/outfuncs.c    4 Aug 2002 19:48:09 -0000    1.166
> --- src/backend/nodes/outfuncs.c    7 Aug 2002 01:26:01 -0000
> ***************
> *** 193,199 ****
>       appendStringInfo(str, " TYPENAME :names ");
>       _outNode(str, node->names);
>       appendStringInfo(str, " :typeid %u :timezone %s :setof %s"
> !                      " :pct_type %s typmod %d :arrayBounds ",
>                        node->typeid,
>                        booltostr(node->timezone),
>                        booltostr(node->setof),
> --- 193,199 ----
>       appendStringInfo(str, " TYPENAME :names ");
>       _outNode(str, node->names);
>       appendStringInfo(str, " :typeid %u :timezone %s :setof %s"
> !                      " :pct_type %s :typmod %d :arrayBounds ",
>                        node->typeid,
>                        booltostr(node->timezone),
>                        booltostr(node->setof),
> Index: src/backend/nodes/readfuncs.c
> ===================================================================
> RCS file: /opt/src/cvs/pgsql-server/src/backend/nodes/readfuncs.c,v
> retrieving revision 1.127
> diff -c -r1.127 readfuncs.c
> *** src/backend/nodes/readfuncs.c    4 Aug 2002 19:48:09 -0000    1.127
> --- src/backend/nodes/readfuncs.c    7 Aug 2002 01:38:41 -0000
> ***************
> *** 1465,1470 ****
> --- 1465,1544 ----
>       return local_node;
>   }
>
> + static ColumnDef *
> + _readColumnDef(void)
> + {
> +     ColumnDef  *local_node;
> +     char       *token;
> +     int            length;
> +
> +     local_node = makeNode(ColumnDef);
> +
> +     token = pg_strtok(&length); /* eat :colname */
> +     token = pg_strtok(&length); /* now read it */
> +     local_node->colname = nullable_string(token, length);
> +
> +     token = pg_strtok(&length); /* eat :typename */
> +     local_node->typename = nodeRead(true); /* now read it */
> +
> +     token = pg_strtok(&length); /* eat :is_not_null */
> +     token = pg_strtok(&length); /* get :is_not_null */
> +     local_node->is_not_null = strtobool(token);
> +
> +     token = pg_strtok(&length); /* eat :raw_default */
> +     local_node->raw_default = nodeRead(true); /* now read it */
> +
> +     token = pg_strtok(&length); /* eat :cooked_default */
> +     token = pg_strtok(&length); /* now read it */
> +     local_node->cooked_default = nullable_string(token, length);
> +
> +     token = pg_strtok(&length); /* eat :constraints */
> +     local_node->constraints = nodeRead(true);    /* now read it */
> +
> +     token = pg_strtok(&length); /* eat :support */
> +     local_node->support = nodeRead(true); /* now read it */
> +
> +     return local_node;
> + }
> +
> + static TypeName *
> + _readTypeName(void)
> + {
> +     TypeName  *local_node;
> +     char       *token;
> +     int            length;
> +
> +     local_node = makeNode(TypeName);
> +
> +     token = pg_strtok(&length); /* eat :names */
> +     local_node->names = nodeRead(true); /* now read it */
> +
> +     token = pg_strtok(&length); /* eat :typeid */
> +     token = pg_strtok(&length); /* get typeid */
> +     local_node->typeid = atooid(token);
> +
> +     token = pg_strtok(&length); /* eat :timezone */
> +     token = pg_strtok(&length); /* get timezone */
> +     local_node->timezone = strtobool(token);
> +
> +     token = pg_strtok(&length); /* eat :setof */
> +     token = pg_strtok(&length); /* get setof */
> +     local_node->setof = strtobool(token);
> +
> +     token = pg_strtok(&length); /* eat :pct_type */
> +     token = pg_strtok(&length); /* get pct_type */
> +     local_node->pct_type = strtobool(token);
> +
> +     token = pg_strtok(&length); /* eat :typmod */
> +     token = pg_strtok(&length); /* get typmod */
> +     local_node->typmod = atoi(token);
> +
> +     token = pg_strtok(&length); /* eat :arrayBounds */
> +     local_node->arrayBounds = nodeRead(true); /* now read it */
> +
> +     return local_node;
> + }
> +
>   static ExprFieldSelect *
>   _readExprFieldSelect(void)
>   {
> ***************
> *** 2092,2097 ****
> --- 2166,2175 ----
>           return_value = _readRangeVar();
>       else if (length == 9 && strncmp(token, "COLUMNREF", length) == 0)
>           return_value = _readColumnRef();
> +     else if (length == 9 && strncmp(token, "COLUMNDEF", length) == 0)
> +         return_value = _readColumnDef();
> +     else if (length == 8 && strncmp(token, "TYPENAME", length) == 0)
> +         return_value = _readTypeName();
>       else if (length == 15 && strncmp(token, "EXPRFIELDSELECT", length) == 0)
>           return_value = _readExprFieldSelect();
>       else if (length == 5 && strncmp(token, "ALIAS", length) == 0)
>

>
> ---------------------------(end of broadcast)---------------------------
> TIP 2: you can get off all lists at once with the unregister command
>     (send "unregister YourEmailAddressHere" to majordomo@postgresql.org)

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073