postgres.git / summary / log / commit / refs

commit    34fa0ddae5cf27dd93a5855b30083185d4bb5a5b
Author:   Tom Lane <tgl@sss.pgh.pa.us>
Date:     Fri Nov 04 14:39:52 2022 +0000
First released in: 16.0, 15.1

    Fix CREATE DATABASE so we can pg_upgrade DBs with OIDs above 2^31.
    
    Commit aa0105141 repeated one of the oldest mistakes in our book:
    thinking that OID is the same as int32.  It isn't of course, and
    unsurprisingly the first person who came along with a database
    OID above 2 billion broke it.  Repair.
    
    Per bug #17677 from Sergey Pankov.  Back-patch to v15.
    
    Discussion: https://postgr.es/m/17677-a99fa067d7ed71c9@postgresql.org


src/backend/commands/dbcommands.c | 2 +- src/backend/commands/define.c | 33 +++++++++++++++++++++++++++++++++ src/backend/parser/gram.y | 4 ++-- src/include/commands/defrem.h | 1 + 4 files changed, 37 insertions(+), 3 deletions(-) diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c index 16e422138bb..8abc2c3e0b0 100644 --- a/src/backend/commands/dbcommands.c +++ b/src/backend/commands/dbcommands.c @@ -816,7 +816,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt) } else if (strcmp(defel->defname, "oid") == 0) { - dboid = defGetInt32(defel); + dboid = defGetObjectId(defel); /* * We don't normally permit new databases to be created with diff --git a/src/backend/commands/define.c b/src/backend/commands/define.c index 86b89071eed..090e5d38d24 100644 --- a/src/backend/commands/define.c +++ b/src/backend/commands/define.c @@ -213,6 +213,39 @@ defGetInt64(DefElem *def) return 0; /* keep compiler quiet */ } +/* + * Extract an OID value from a DefElem. + */ +Oid +defGetObjectId(DefElem *def) +{ + if (def->arg == NULL) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("%s requires a numeric value", + def->defname))); + switch (nodeTag(def->arg)) + { + case T_Integer: + return (Oid) intVal(def->arg); + case T_Float: + + /* + * Values too large for int4 will be represented as Float + * constants by the lexer. Accept these if they are valid OID + * strings. + */ + return DatumGetObjectId(DirectFunctionCall1(oidin, + CStringGetDatum(castNode(Float, def->arg)->fval))); + default: + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("%s requires a numeric value", + def->defname))); + } + return 0; /* keep compiler quiet */ +} + /* * Extract a possibly-qualified name (as a List of Strings) from a DefElem. */ diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 6ca23f88c4f..deb101710e4 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11105,9 +11105,9 @@ createdb_opt_items: ; createdb_opt_item: - createdb_opt_name opt_equal SignedIconst + createdb_opt_name opt_equal NumericOnly { - $$ = makeDefElem($1, (Node *) makeInteger($3), @1); + $$ = makeDefElem($1, $3, @1); } | createdb_opt_name opt_equal opt_boolean_or_string { diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h index 56d2bb66161..1d3ce246c92 100644 --- a/src/include/commands/defrem.h +++ b/src/include/commands/defrem.h @@ -150,6 +150,7 @@ extern double defGetNumeric(DefElem *def); extern bool defGetBoolean(DefElem *def); extern int32 defGetInt32(DefElem *def); extern int64 defGetInt64(DefElem *def); +extern Oid defGetObjectId(DefElem *def); extern List *defGetQualifiedName(DefElem *def); extern TypeName *defGetTypeName(DefElem *def); extern int defGetTypeLength(DefElem *def); [parent: 8c7146790811]