Re: [bug] Table not have typarray when created by single user mode - Mailing list pgsql-bugs

From wenjing zeng
Subject Re: [bug] Table not have typarray when created by single user mode
Date
Msg-id 758C3780-2911-43F4-94CE-DFF772A61D2C@gmail.com
Whole thread Raw
In response to Re: [bug] Table not have typarray when created by single user mode  (Tom Lane <tgl@sss.pgh.pa.us>)
List pgsql-bugs
Thank you very much Tom. It looks perfect.
 I don't have any more questions.


Wenjing


> 2020年7月7日 上午4:22,Tom Lane <tgl@sss.pgh.pa.us> 写道:
>
> I wrote:
>> However, if we're going to go this far, I think there's a good
>> case to be made for going all the way and eliminating the policy
>> of not making array types for system catalogs.  That was never
>> anything but a wart justified by space savings in pg_type, and
>> this patch already kills most of the space savings.  If we
>> drop the system-state test in heap_create_with_catalog altogether,
>> we end up with 601 initial pg_type entries.  That still leaves
>> the four bootstrap catalogs without array types, because they are
>> not created by heap_create_with_catalog; but we can manually add
>> those too for a total of 605 initial entries.  (That brings initial
>> pg_type to 14 pages as I show above; I think it was 13 with the
>> original version of the patch.)
>> In short, if we're gonna do this, I think we should do it like
>> the attached.  Or we could do nothing, but there is some appeal
>> to removing this old inconsistency.
>
> I pushed that, but while working on it I had a further thought:
> why is it that we create composite types but not arrays over those
> types for *any* relkinds?  That is, we could create even more
> consistency, as well as buying back some of the pg_type bloat added
> here, by not creating pg_type entries at all for toast tables or
> sequences.  A little bit of hacking later, I have the attached.
>
> One could argue it either way as to whether sequences should have
> composite types.  It's possible to demonstrate queries that will
> fail without one:
>
> regression=# create sequence seq1;
> CREATE SEQUENCE
> regression=# select s from seq1 s;
> ERROR:  relation "seq1" does not have a composite type
>
> but it's pretty hard to believe anyone's using that in practice.
> Also, we've talked more than once about changing the implementation
> of sequences to not have a relation per sequence, in which case the
> ability to do something like the above would go away anyway.
>
> Comments?
>
>             regards, tom lane
>
> diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
> index 003d278370..7471ba53f2 100644
> --- a/doc/src/sgml/catalogs.sgml
> +++ b/doc/src/sgml/catalogs.sgml
> @@ -1895,7 +1895,8 @@ SCRAM-SHA-256$<replaceable><iteration count></replaceable>:<replaceable>&l
>       </para>
>       <para>
>        The OID of the data type that corresponds to this table's row type,
> -       if any (zero for indexes, which have no <structname>pg_type</structname> entry)
> +       if any (zero for indexes, sequences, and toast tables, which have
> +       no <structname>pg_type</structname> entry)
>       </para></entry>
>      </row>
>
> diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
> index fd04e82b20..ae509d9d49 100644
> --- a/src/backend/catalog/heap.c
> +++ b/src/backend/catalog/heap.c
> @@ -1118,8 +1118,6 @@ heap_create_with_catalog(const char *relname,
>     Oid            existing_relid;
>     Oid            old_type_oid;
>     Oid            new_type_oid;
> -    ObjectAddress new_type_addr;
> -    Oid            new_array_oid = InvalidOid;
>     TransactionId relfrozenxid;
>     MultiXactId relminmxid;
>
> @@ -1262,44 +1260,45 @@ heap_create_with_catalog(const char *relname,
>     new_rel_desc->rd_rel->relrewrite = relrewrite;
>
>     /*
> -     * Decide whether to create an array type over the relation's rowtype.
> -     * Array types are made except where the use of a relation as such is an
> +     * Decide whether to create a pg_type entry for the relation's rowtype.
> +     * These types are made except where the use of a relation as such is an
>      * implementation detail: toast tables, sequences and indexes.
>      */
>     if (!(relkind == RELKIND_SEQUENCE ||
>           relkind == RELKIND_TOASTVALUE ||
>           relkind == RELKIND_INDEX ||
>           relkind == RELKIND_PARTITIONED_INDEX))
> -        new_array_oid = AssignTypeArrayOid();
> -
> -    /*
> -     * Since defining a relation also defines a complex type, we add a new
> -     * system type corresponding to the new relation.  The OID of the type can
> -     * be preselected by the caller, but if reltypeid is InvalidOid, we'll
> -     * generate a new OID for it.
> -     *
> -     * NOTE: we could get a unique-index failure here, in case someone else is
> -     * creating the same type name in parallel but hadn't committed yet when
> -     * we checked for a duplicate name above.
> -     */
> -    new_type_addr = AddNewRelationType(relname,
> -                                       relnamespace,
> -                                       relid,
> -                                       relkind,
> -                                       ownerid,
> -                                       reltypeid,
> -                                       new_array_oid);
> -    new_type_oid = new_type_addr.objectId;
> -    if (typaddress)
> -        *typaddress = new_type_addr;
> -
> -    /*
> -     * Now make the array type if wanted.
> -     */
> -    if (OidIsValid(new_array_oid))
>     {
> +        Oid            new_array_oid;
> +        ObjectAddress new_type_addr;
>         char       *relarrayname;
>
> +        /*
> +         * We'll make an array over the composite type, too.  For largely
> +         * historical reasons, the array type's OID is assigned first.
> +         */
> +        new_array_oid = AssignTypeArrayOid();
> +
> +        /*
> +         * The OID of the composite type can be preselected by the caller, but
> +         * if reltypeid is InvalidOid, we'll generate a new OID for it.
> +         *
> +         * NOTE: we could get a unique-index failure here, in case someone
> +         * else is creating the same type name in parallel but hadn't
> +         * committed yet when we checked for a duplicate name above.
> +         */
> +        new_type_addr = AddNewRelationType(relname,
> +                                           relnamespace,
> +                                           relid,
> +                                           relkind,
> +                                           ownerid,
> +                                           reltypeid,
> +                                           new_array_oid);
> +        new_type_oid = new_type_addr.objectId;
> +        if (typaddress)
> +            *typaddress = new_type_addr;
> +
> +        /* Now create the array type. */
>         relarrayname = makeArrayTypeName(relname, relnamespace);
>
>         TypeCreate(new_array_oid,    /* force the type's OID to this */
> @@ -1336,6 +1335,14 @@ heap_create_with_catalog(const char *relname,
>
>         pfree(relarrayname);
>     }
> +    else
> +    {
> +        /* Caller should not be expecting a type to be created. */
> +        Assert(reltypeid == InvalidOid);
> +        Assert(typaddress == NULL);
> +
> +        new_type_oid = InvalidOid;
> +    }
>
>     /*
>      * now create an entry in pg_class for the relation.
> diff --git a/src/backend/catalog/toasting.c b/src/backend/catalog/toasting.c
> index 3f7ab8d389..8b8888af5e 100644
> --- a/src/backend/catalog/toasting.c
> +++ b/src/backend/catalog/toasting.c
> @@ -34,9 +34,6 @@
> #include "utils/rel.h"
> #include "utils/syscache.h"
>
> -/* Potentially set by pg_upgrade_support functions */
> -Oid            binary_upgrade_next_toast_pg_type_oid = InvalidOid;
> -
> static void CheckAndCreateToastTable(Oid relOid, Datum reloptions,
>                                      LOCKMODE lockmode, bool check);
> static bool create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid,
> @@ -135,7 +132,6 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid,
>     Relation    toast_rel;
>     Relation    class_rel;
>     Oid            toast_relid;
> -    Oid            toast_typid = InvalidOid;
>     Oid            namespaceid;
>     char        toast_relname[NAMEDATALEN];
>     char        toast_idxname[NAMEDATALEN];
> @@ -181,8 +177,7 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid,
>          * problem that it might take up an OID that will conflict with some
>          * old-cluster table we haven't seen yet.
>          */
> -        if (!OidIsValid(binary_upgrade_next_toast_pg_class_oid) ||
> -            !OidIsValid(binary_upgrade_next_toast_pg_type_oid))
> +        if (!OidIsValid(binary_upgrade_next_toast_pg_class_oid))
>             return false;
>     }
>
> @@ -234,17 +229,6 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid,
>     else
>         namespaceid = PG_TOAST_NAMESPACE;
>
> -    /*
> -     * Use binary-upgrade override for pg_type.oid, if supplied.  We might be
> -     * in the post-schema-restore phase where we are doing ALTER TABLE to
> -     * create TOAST tables that didn't exist in the old cluster.
> -     */
> -    if (IsBinaryUpgrade && OidIsValid(binary_upgrade_next_toast_pg_type_oid))
> -    {
> -        toast_typid = binary_upgrade_next_toast_pg_type_oid;
> -        binary_upgrade_next_toast_pg_type_oid = InvalidOid;
> -    }
> -
>     /* Toast table is shared if and only if its parent is. */
>     shared_relation = rel->rd_rel->relisshared;
>
> @@ -255,7 +239,7 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid,
>                                            namespaceid,
>                                            rel->rd_rel->reltablespace,
>                                            toastOid,
> -                                           toast_typid,
> +                                           InvalidOid,
>                                            InvalidOid,
>                                            rel->rd_rel->relowner,
>                                            table_relation_toast_am(rel),
> diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
> index f79044f39f..4b2548f33f 100644
> --- a/src/backend/commands/tablecmds.c
> +++ b/src/backend/commands/tablecmds.c
> @@ -12564,8 +12564,7 @@ ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing, LOCKMODE lock
>         /*
>          * Also change the ownership of the table's row type, if it has one
>          */
> -        if (tuple_class->relkind != RELKIND_INDEX &&
> -            tuple_class->relkind != RELKIND_PARTITIONED_INDEX)
> +        if (OidIsValid(tuple_class->reltype))
>             AlterTypeOwnerInternal(tuple_class->reltype, newOwnerId);
>
>         /*
> @@ -15009,9 +15008,10 @@ AlterTableNamespaceInternal(Relation rel, Oid oldNspOid, Oid nspOid,
>     AlterRelationNamespaceInternal(classRel, RelationGetRelid(rel), oldNspOid,
>                                    nspOid, true, objsMoved);
>
> -    /* Fix the table's row type too */
> -    AlterTypeNamespaceInternal(rel->rd_rel->reltype,
> -                               nspOid, false, false, objsMoved);
> +    /* Fix the table's row type too, if it has one */
> +    if (OidIsValid(rel->rd_rel->reltype))
> +        AlterTypeNamespaceInternal(rel->rd_rel->reltype,
> +                                   nspOid, false, false, objsMoved);
>
>     /* Fix other dependent stuff */
>     if (rel->rd_rel->relkind == RELKIND_RELATION ||
> @@ -15206,11 +15206,11 @@ AlterSeqNamespaces(Relation classRel, Relation rel,
>                                        true, objsMoved);
>
>         /*
> -         * Sequences have entries in pg_type. We need to be careful to move
> -         * them to the new namespace, too.
> +         * Sequences used to have entries in pg_type, but no longer do.  If we
> +         * ever re-instate that, we'll need to move the pg_type entry to the
> +         * new namespace, too (using AlterTypeNamespaceInternal).
>          */
> -        AlterTypeNamespaceInternal(RelationGetForm(seqRel)->reltype,
> -                                   newNspOid, false, false, objsMoved);
> +        Assert(RelationGetForm(seqRel)->reltype == InvalidOid);
>
>         /* Now we can close it.  Keep the lock till end of transaction. */
>         relation_close(seqRel, NoLock);
> diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c
> index b442b5a29e..49de285f01 100644
> --- a/src/backend/nodes/makefuncs.c
> +++ b/src/backend/nodes/makefuncs.c
> @@ -145,8 +145,10 @@ makeWholeRowVar(RangeTblEntry *rte,
>             /* relation: the rowtype is a named composite type */
>             toid = get_rel_type_id(rte->relid);
>             if (!OidIsValid(toid))
> -                elog(ERROR, "could not find type OID for relation %u",
> -                     rte->relid);
> +                ereport(ERROR,
> +                        (errcode(ERRCODE_WRONG_OBJECT_TYPE),
> +                         errmsg("relation \"%s\" does not have a composite type",
> +                                get_rel_name(rte->relid))));
>             result = makeVar(varno,
>                              InvalidAttrNumber,
>                              toid,
> diff --git a/src/backend/utils/adt/pg_upgrade_support.c b/src/backend/utils/adt/pg_upgrade_support.c
> index 18f2ee8226..14d9eb2b5b 100644
> --- a/src/backend/utils/adt/pg_upgrade_support.c
> +++ b/src/backend/utils/adt/pg_upgrade_support.c
> @@ -51,17 +51,6 @@ binary_upgrade_set_next_array_pg_type_oid(PG_FUNCTION_ARGS)
>     PG_RETURN_VOID();
> }
>
> -Datum
> -binary_upgrade_set_next_toast_pg_type_oid(PG_FUNCTION_ARGS)
> -{
> -    Oid            typoid = PG_GETARG_OID(0);
> -
> -    CHECK_IS_BINARY_UPGRADE;
> -    binary_upgrade_next_toast_pg_type_oid = typoid;
> -
> -    PG_RETURN_VOID();
> -}
> -
> Datum
> binary_upgrade_set_next_heap_pg_class_oid(PG_FUNCTION_ARGS)
> {
> diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
> index a41a3db876..ee0947dda7 100644
> --- a/src/bin/pg_dump/pg_dump.c
> +++ b/src/bin/pg_dump/pg_dump.c
> @@ -272,7 +272,7 @@ static void binary_upgrade_set_type_oids_by_type_oid(Archive *fout,
>                                                      PQExpBuffer upgrade_buffer,
>                                                      Oid pg_type_oid,
>                                                      bool force_array_type);
> -static bool binary_upgrade_set_type_oids_by_rel_oid(Archive *fout,
> +static void binary_upgrade_set_type_oids_by_rel_oid(Archive *fout,
>                                                     PQExpBuffer upgrade_buffer, Oid pg_rel_oid);
> static void binary_upgrade_set_pg_class_oids(Archive *fout,
>                                              PQExpBuffer upgrade_buffer,
> @@ -4493,7 +4493,7 @@ binary_upgrade_set_type_oids_by_type_oid(Archive *fout,
>     destroyPQExpBuffer(upgrade_query);
> }
>
> -static bool
> +static void
> binary_upgrade_set_type_oids_by_rel_oid(Archive *fout,
>                                         PQExpBuffer upgrade_buffer,
>                                         Oid pg_rel_oid)
> @@ -4501,48 +4501,23 @@ binary_upgrade_set_type_oids_by_rel_oid(Archive *fout,
>     PQExpBuffer upgrade_query = createPQExpBuffer();
>     PGresult   *upgrade_res;
>     Oid            pg_type_oid;
> -    bool        toast_set = false;
>
> -    /*
> -     * We only support old >= 8.3 for binary upgrades.
> -     *
> -     * We purposefully ignore toast OIDs for partitioned tables; the reason is
> -     * that versions 10 and 11 have them, but 12 does not, so emitting them
> -     * causes the upgrade to fail.
> -     */
>     appendPQExpBuffer(upgrade_query,
> -                      "SELECT c.reltype AS crel, t.reltype AS trel "
> +                      "SELECT c.reltype AS crel "
>                       "FROM pg_catalog.pg_class c "
> -                      "LEFT JOIN pg_catalog.pg_class t ON "
> -                      "  (c.reltoastrelid = t.oid AND c.relkind <> '%c') "
>                       "WHERE c.oid = '%u'::pg_catalog.oid;",
> -                      RELKIND_PARTITIONED_TABLE, pg_rel_oid);
> +                      pg_rel_oid);
>
>     upgrade_res = ExecuteSqlQueryForSingleRow(fout, upgrade_query->data);
>
>     pg_type_oid = atooid(PQgetvalue(upgrade_res, 0, PQfnumber(upgrade_res, "crel")));
>
> -    binary_upgrade_set_type_oids_by_type_oid(fout, upgrade_buffer,
> -                                             pg_type_oid, false);
> -
> -    if (!PQgetisnull(upgrade_res, 0, PQfnumber(upgrade_res, "trel")))
> -    {
> -        /* Toast tables do not have pg_type array rows */
> -        Oid            pg_type_toast_oid = atooid(PQgetvalue(upgrade_res, 0,
> -                                                          PQfnumber(upgrade_res, "trel")));
> -
> -        appendPQExpBufferStr(upgrade_buffer, "\n-- For binary upgrade, must preserve pg_type toast oid\n");
> -        appendPQExpBuffer(upgrade_buffer,
> -                          "SELECT pg_catalog.binary_upgrade_set_next_toast_pg_type_oid('%u'::pg_catalog.oid);\n\n",
> -                          pg_type_toast_oid);
> -
> -        toast_set = true;
> -    }
> +    if (OidIsValid(pg_type_oid))
> +        binary_upgrade_set_type_oids_by_type_oid(fout, upgrade_buffer,
> +                                                 pg_type_oid, false);
>
>     PQclear(upgrade_res);
>     destroyPQExpBuffer(upgrade_query);
> -
> -    return toast_set;
> }
>
> static void
> diff --git a/src/include/catalog/binary_upgrade.h b/src/include/catalog/binary_upgrade.h
> index 12d94fe1b3..02fecb90f7 100644
> --- a/src/include/catalog/binary_upgrade.h
> +++ b/src/include/catalog/binary_upgrade.h
> @@ -16,7 +16,6 @@
>
> extern PGDLLIMPORT Oid binary_upgrade_next_pg_type_oid;
> extern PGDLLIMPORT Oid binary_upgrade_next_array_pg_type_oid;
> -extern PGDLLIMPORT Oid binary_upgrade_next_toast_pg_type_oid;
>
> extern PGDLLIMPORT Oid binary_upgrade_next_heap_pg_class_oid;
> extern PGDLLIMPORT Oid binary_upgrade_next_index_pg_class_oid;
> diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
> index 38295aca48..a995a104b6 100644
> --- a/src/include/catalog/pg_proc.dat
> +++ b/src/include/catalog/pg_proc.dat
> @@ -10306,10 +10306,6 @@
>   proname => 'binary_upgrade_set_next_array_pg_type_oid', provolatile => 'v',
>   proparallel => 'r', prorettype => 'void', proargtypes => 'oid',
>   prosrc => 'binary_upgrade_set_next_array_pg_type_oid' },
> -{ oid => '3585', descr => 'for use by pg_upgrade',
> -  proname => 'binary_upgrade_set_next_toast_pg_type_oid', provolatile => 'v',
> -  proparallel => 'r', prorettype => 'void', proargtypes => 'oid',
> -  prosrc => 'binary_upgrade_set_next_toast_pg_type_oid' },
> { oid => '3586', descr => 'for use by pg_upgrade',
>   proname => 'binary_upgrade_set_next_heap_pg_class_oid', provolatile => 'v',
>   proparallel => 'r', prorettype => 'void', proargtypes => 'oid',
> diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c
> index 828ff5a288..e7f4a5f291 100644
> --- a/src/pl/plpgsql/src/pl_comp.c
> +++ b/src/pl/plpgsql/src/pl_comp.c
> @@ -1778,6 +1778,7 @@ PLpgSQL_type *
> plpgsql_parse_wordrowtype(char *ident)
> {
>     Oid            classOid;
> +    Oid            typOid;
>
>     /*
>      * Look up the relation.  Note that because relation rowtypes have the
> @@ -1792,8 +1793,16 @@ plpgsql_parse_wordrowtype(char *ident)
>                 (errcode(ERRCODE_UNDEFINED_TABLE),
>                  errmsg("relation \"%s\" does not exist", ident)));
>
> +    /* Some relkinds lack type OIDs */
> +    typOid = get_rel_type_id(classOid);
> +    if (!OidIsValid(typOid))
> +        ereport(ERROR,
> +                (errcode(ERRCODE_WRONG_OBJECT_TYPE),
> +                 errmsg("relation \"%s\" does not have a composite type",
> +                        ident)));
> +
>     /* Build and return the row type struct */
> -    return plpgsql_build_datatype(get_rel_type_id(classOid), -1, InvalidOid,
> +    return plpgsql_build_datatype(typOid, -1, InvalidOid,
>                                   makeTypeName(ident));
> }
>
> @@ -1806,6 +1815,7 @@ PLpgSQL_type *
> plpgsql_parse_cwordrowtype(List *idents)
> {
>     Oid            classOid;
> +    Oid            typOid;
>     RangeVar   *relvar;
>     MemoryContext oldCxt;
>
> @@ -1825,10 +1835,18 @@ plpgsql_parse_cwordrowtype(List *idents)
>                           -1);
>     classOid = RangeVarGetRelid(relvar, NoLock, false);
>
> +    /* Some relkinds lack type OIDs */
> +    typOid = get_rel_type_id(classOid);
> +    if (!OidIsValid(typOid))
> +        ereport(ERROR,
> +                (errcode(ERRCODE_WRONG_OBJECT_TYPE),
> +                 errmsg("relation \"%s\" does not have a composite type",
> +                        strVal(lsecond(idents)))));
> +
>     MemoryContextSwitchTo(oldCxt);
>
>     /* Build and return the row type struct */
> -    return plpgsql_build_datatype(get_rel_type_id(classOid), -1, InvalidOid,
> +    return plpgsql_build_datatype(typOid, -1, InvalidOid,
>                                   makeTypeNameFromNameList(idents));
> }
>




pgsql-bugs by date:

Previous
From: PG Bug reporting form
Date:
Subject: BUG #16530: pgAdmin 4 Query Tool not loading/visualizing the data
Next
From: PG Bug reporting form
Date:
Subject: BUG #16531: listen_addresses wide open?