aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/src/sgml/catalogs.sgml3
-rw-r--r--src/backend/catalog/heap.c75
-rw-r--r--src/backend/catalog/toasting.c20
-rw-r--r--src/backend/commands/tablecmds.c22
-rw-r--r--src/backend/nodes/makefuncs.c6
-rw-r--r--src/backend/utils/adt/pg_upgrade_support.c11
-rw-r--r--src/backend/utils/cache/relcache.c13
-rw-r--r--src/bin/pg_dump/pg_dump.c46
-rw-r--r--src/include/catalog/binary_upgrade.h1
-rw-r--r--src/include/catalog/catversion.h2
-rw-r--r--src/include/catalog/pg_proc.dat4
-rw-r--r--src/pl/plpgsql/src/pl_comp.c22
12 files changed, 102 insertions, 123 deletions
diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index 361793b337a..e9cdff48641 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -1895,7 +1895,8 @@ SCRAM-SHA-256$<replaceable>&lt;iteration count&gt;</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 fd04e82b20e..3985326df62 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -1000,7 +1000,9 @@ AddNewRelationTuple(Relation pg_class_desc,
/* relispartition is always set by updating this tuple later */
new_rel_reltup->relispartition = false;
- new_rel_desc->rd_att->tdtypeid = new_type_oid;
+ /* fill rd_att's type ID with something sane even if reltype is zero */
+ new_rel_desc->rd_att->tdtypeid = new_type_oid ? new_type_oid : RECORDOID;
+ new_rel_desc->rd_att->tdtypmod = -1;
/* Now build and insert the tuple */
InsertPgClassTuple(pg_class_desc, new_rel_desc, new_rel_oid,
@@ -1085,6 +1087,7 @@ AddNewRelationType(const char *typeName,
*
* Output parameters:
* typaddress: if not null, gets the object address of the new pg_type entry
+ * (this must be null if the relkind is one that doesn't get a pg_type entry)
*
* Returns the OID of the new relation
* --------------------------------
@@ -1118,8 +1121,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 +1263,46 @@ 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();
+
+ /*
+ * Make the pg_type entry for the composite type. 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 +1339,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 3f7ab8d389b..8b8888af5ed 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 f79044f39fc..42330692e76 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -11001,8 +11001,8 @@ ATPrepAlterColumnType(List **wqueue,
tab->relkind == RELKIND_FOREIGN_TABLE)
{
/*
- * For composite types, do this check now. Tables will check it later
- * when the table is being rewritten.
+ * For composite types and foreign tables, do this check now. Regular
+ * tables will check it later when the table is being rewritten.
*/
find_composite_type_dependencies(rel->rd_rel->reltype, rel, NULL);
}
@@ -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 b442b5a29ef..49de285f01e 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 18f2ee8226c..14d9eb2b5b3 100644
--- a/src/backend/utils/adt/pg_upgrade_support.c
+++ b/src/backend/utils/adt/pg_upgrade_support.c
@@ -52,17 +52,6 @@ binary_upgrade_set_next_array_pg_type_oid(PG_FUNCTION_ARGS)
}
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)
{
Oid reloid = PG_GETARG_OID(0);
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 0b9eb00d2de..a2453cf1f42 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -506,9 +506,10 @@ RelationBuildTupleDesc(Relation relation)
AttrMissing *attrmiss = NULL;
int ndef = 0;
- /* copy some fields from pg_class row to rd_att */
- relation->rd_att->tdtypeid = relation->rd_rel->reltype;
- relation->rd_att->tdtypmod = -1; /* unnecessary, but... */
+ /* fill rd_att's type ID fields (compare heap.c's AddNewRelationTuple) */
+ relation->rd_att->tdtypeid =
+ relation->rd_rel->reltype ? relation->rd_rel->reltype : RECORDOID;
+ relation->rd_att->tdtypmod = -1; /* just to be sure */
constr = (TupleConstr *) MemoryContextAlloc(CacheMemoryContext,
sizeof(TupleConstr));
@@ -1886,7 +1887,7 @@ formrdesc(const char *relationName, Oid relationReltype,
relation->rd_att->tdrefcount = 1; /* mark as refcounted */
relation->rd_att->tdtypeid = relationReltype;
- relation->rd_att->tdtypmod = -1; /* unnecessary, but... */
+ relation->rd_att->tdtypmod = -1; /* just to be sure */
/*
* initialize tuple desc info
@@ -5692,8 +5693,8 @@ load_relcache_init_file(bool shared)
rel->rd_att = CreateTemplateTupleDesc(relform->relnatts);
rel->rd_att->tdrefcount = 1; /* mark as refcounted */
- rel->rd_att->tdtypeid = relform->reltype;
- rel->rd_att->tdtypmod = -1; /* unnecessary, but... */
+ rel->rd_att->tdtypeid = relform->reltype ? relform->reltype : RECORDOID;
+ rel->rd_att->tdtypmod = -1; /* just to be sure */
/* next read all the attribute tuple form data entries */
has_not_null = false;
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index a41a3db876c..fd7b3e09203 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
@@ -17209,8 +17184,11 @@ dumpSequence(Archive *fout, TableInfo *tbinfo)
{
binary_upgrade_set_pg_class_oids(fout, query,
tbinfo->dobj.catId.oid, false);
- binary_upgrade_set_type_oids_by_rel_oid(fout, query,
- tbinfo->dobj.catId.oid);
+
+ /*
+ * In older PG versions a sequence will have a pg_type entry, but v14
+ * and up don't use that, so don't attempt to preserve the type OID.
+ */
}
if (tbinfo->is_identity_sequence)
diff --git a/src/include/catalog/binary_upgrade.h b/src/include/catalog/binary_upgrade.h
index 12d94fe1b3c..02fecb90f79 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/catversion.h b/src/include/catalog/catversion.h
index 1b35510d46d..60e5361af66 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 202007071
+#define CATALOG_VERSION_NO 202007072
#endif
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 3c89c53aa28..d951b4a36f2 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 828ff5a288f..e7f4a5f291d 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));
}