Re: [bug] Table not have typarray when created by single user mode - Mailing list pgsql-bugs
| From | Tom Lane |
|---|---|
| Subject | Re: [bug] Table not have typarray when created by single user mode |
| Date | |
| Msg-id | 1468768.1594066959@sss.pgh.pa.us 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>) |
| Responses |
Re: [bug] Table not have typarray when created by single user mode
|
| List | pgsql-bugs |
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: