From: Antonin Houska Date: Fri, 5 Jul 2019 16:24:02 +0200 Subject: [PATCH 13/17] Make database OID constant for postgres database. Later in the patch series we teach pg_upgrade to preserve OIDs of relfilenodes, tablespaces and databases. To ensure the last, we need to make the OID of the "postgres" database constant because pg_upgrade can drop it in the new cluster and create it again. --- src/backend/commands/dbcommands.c | 21 +++++++++++++++++---- src/include/catalog/pg_database.h | 14 ++++++++++++++ 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c index 7ea783d096..4ffb6dccf4 100644 --- a/src/backend/commands/dbcommands.c +++ b/src/backend/commands/dbcommands.c @@ -513,11 +513,24 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt) */ pg_database_rel = table_open(DatabaseRelationId, RowExclusiveLock); - do + /* The "postgres" database has fixed OID. */ + if (strcmp(dbname, "postgres") == 0) { - dboid = GetNewOidWithIndex(pg_database_rel, DatabaseOidIndexId, - Anum_pg_database_oid); - } while (check_db_file_conflict(dboid)); + dboid = PostgresDbOid; + + if (check_db_file_conflict(dboid)) + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_DATABASE), + errmsg("database \"%s\" already exists", dbname))); + } + else + { + do + { + dboid = GetNewOidWithIndex(pg_database_rel, DatabaseOidIndexId, + Anum_pg_database_oid); + } while (check_db_file_conflict(dboid)); + } /* * Insert a new tuple into pg_database. This establishes our ownership of diff --git a/src/include/catalog/pg_database.h b/src/include/catalog/pg_database.h index 06fea45f53..ebb17e3051 100644 --- a/src/include/catalog/pg_database.h +++ b/src/include/catalog/pg_database.h @@ -80,4 +80,18 @@ CATALOG(pg_database,1262,DatabaseRelationId) BKI_SHARED_RELATION BKI_ROWTYPE_OID */ typedef FormData_pg_database *Form_pg_database; +/* + * The "postgres" database has reserved pg_database(oid) because initially + * it's below FirstNormalObjectId, and thus pg_upgrade cannot guarantee that + * the same OID will be assigned in the new cluster (unlike TemplateDbOid, + * which has always OID=1). Since database OID is used to construct encryption + * initialization vector (tweak), different OID would break data decryption in + * the new cluster. + * + * The easiest way to avoid collision with any system OID is to use the + * maximum system OID. initdb won't reach this value and GetNewObjectId() will + * always skip that. + */ +#define PostgresDbOid (FirstNormalObjectId - 1) + #endif /* PG_DATABASE_H */ -- 2.13.7 --=-=-= Content-Type: text/x-diff Content-Disposition: attachment; filename=v04-0014-Teach-pg_upgrade-to-preserve-OIDs-of-relfilenode-dat.patch