diff options
-rw-r--r-- | doc/src/sgml/catalogs.sgml | 3 | ||||
-rw-r--r-- | src/backend/catalog/heap.c | 75 | ||||
-rw-r--r-- | src/backend/catalog/toasting.c | 20 | ||||
-rw-r--r-- | src/backend/commands/tablecmds.c | 22 | ||||
-rw-r--r-- | src/backend/nodes/makefuncs.c | 6 | ||||
-rw-r--r-- | src/backend/utils/adt/pg_upgrade_support.c | 11 | ||||
-rw-r--r-- | src/backend/utils/cache/relcache.c | 13 | ||||
-rw-r--r-- | src/bin/pg_dump/pg_dump.c | 46 | ||||
-rw-r--r-- | src/include/catalog/binary_upgrade.h | 1 | ||||
-rw-r--r-- | src/include/catalog/catversion.h | 2 | ||||
-rw-r--r-- | src/include/catalog/pg_proc.dat | 4 | ||||
-rw-r--r-- | src/pl/plpgsql/src/pl_comp.c | 22 |
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><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 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)); } |