Clarify error message and documentation related to typed tables.
authorTom Lane <[email protected]>
Fri, 26 Jul 2024 16:39:45 +0000 (12:39 -0400)
committerTom Lane <[email protected]>
Fri, 26 Jul 2024 16:39:45 +0000 (12:39 -0400)
We restrict typed tables (those declared as "OF composite_type")
to be based on stand-alone composite types, not composite types
that are the implicitly-created rowtypes of other tables.
But if you tried to do that, you got the very confusing error
message "type foo is not a composite type".  Provide a more specific
message for that case.  Also clarify related documentation in the
CREATE TABLE man page.

Erik Wienhold and David G. Johnston, per complaint from Hannu Krosing.

Discussion: https://postgr.es/m/CAMT0RQRysCb_Amy5CTENSc5GfsvXL1a4qX3mv_hx31_v74P==g@mail.gmail.com

doc/src/sgml/ref/create_table.sgml
src/backend/commands/tablecmds.c
src/test/regress/expected/typed_table.out
src/test/regress/sql/typed_table.sql

index f19306e7760cd9a5e8e9c502700f0d948f88962c..93b3f664f211208991134c2c1dcf194a7a2ada7e 100644 (file)
@@ -249,18 +249,18 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM
     <listitem>
      <para>
       Creates a <firstterm>typed table</firstterm>, which takes its
-      structure from the specified composite type (name optionally
-      schema-qualified).  A typed table is tied to its type; for
-      example the table will be dropped if the type is dropped
-      (with <literal>DROP TYPE ... CASCADE</literal>).
+      structure from the specified stand-alone composite type (that is,
+      one created using <xref linkend="sql-createtype"/>) though it still
+      produces a new composite type as well.  The table will have a
+      dependency on the referenced type, meaning that cascaded alter and
+      drop actions on that type will propagate to the table.
      </para>
 
      <para>
-      When a typed table is created, then the data types of the
-      columns are determined by the underlying composite type and are
-      not specified by the <literal>CREATE TABLE</literal> command.
+      A typed table always has the same column names and data types as the
+      type it is derived from, so you cannot specify additional columns.
       But the <literal>CREATE TABLE</literal> command can add defaults
-      and constraints to the table and can specify storage parameters.
+      and constraints to the table, as well as specify storage parameters.
      </para>
     </listitem>
    </varlistentry>
index 721d24783b4e38b472fee53dbce5bcd5ef9518be..0b2a52463f16b91da2d0ecaea05d04d629fa2d13 100644 (file)
@@ -6962,8 +6962,15 @@ check_of_type(HeapTuple typetuple)
         * the type before the typed table creation/conversion commits.
         */
        relation_close(typeRelation, NoLock);
+
+       if (!typeOk)
+           ereport(ERROR,
+                   (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+                    errmsg("type %s is the row type of another table",
+                           format_type_be(typ->oid)),
+                    errdetail("A typed table must use a stand-alone composite type created with CREATE TYPE.")));
    }
-   if (!typeOk)
+   else
        ereport(ERROR,
                (errcode(ERRCODE_WRONG_OBJECT_TYPE),
                 errmsg("type %s is not a composite type",
index 2e47ecbcf50838d4b5f3de23911622ac652c3bab..b6fbda3f217863815f2a44c765d7bf8d3a3d7cc8 100644 (file)
@@ -89,7 +89,12 @@ drop cascades to function get_all_persons()
 drop cascades to table persons2
 drop cascades to table persons3
 CREATE TABLE persons5 OF stuff; -- only CREATE TYPE AS types may be used
-ERROR:  type stuff is not a composite type
+ERROR:  type stuff is the row type of another table
+DETAIL:  A typed table must use a stand-alone composite type created with CREATE TYPE.
+CREATE TYPE tt_enum_type AS ENUM ('a');
+CREATE TABLE of_tt_enum_type OF tt_enum_type; -- not a composite type at all
+ERROR:  type tt_enum_type is not a composite type
+DROP TYPE tt_enum_type;
 DROP TABLE stuff;
 -- implicit casting
 CREATE TYPE person_type AS (id int, name text);
index 9ef0cdfcc7e468daafae7e6c8eeae69663f115ae..57ce12782b0ac49e419f359f0b0c02d9d0af0295 100644 (file)
@@ -48,6 +48,10 @@ DROP TYPE person_type CASCADE;
 
 CREATE TABLE persons5 OF stuff; -- only CREATE TYPE AS types may be used
 
+CREATE TYPE tt_enum_type AS ENUM ('a');
+CREATE TABLE of_tt_enum_type OF tt_enum_type; -- not a composite type at all
+DROP TYPE tt_enum_type;
+
 DROP TABLE stuff;