]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Fix CREATE DATABASE so we can pg_upgrade DBs with OIDs above 2^31.
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 4 Nov 2022 14:39:52 +0000 (10:39 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 4 Nov 2022 14:39:52 +0000 (10:39 -0400)
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
src/backend/commands/define.c
src/backend/parser/gram.y
src/include/commands/defrem.h

index 034d14f39daa2752b3316bc4c95b4c2b88fc849a..5f342478296666f8829689c47bd9cece26a7aa0c 100644 (file)
@@ -815,7 +815,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
index 0755ab1eae539cb27a737a1617ae3282620de6e5..1e07fa97bb9588ad04f4f820282c1733af8acb6b 100644 (file)
@@ -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.
  */
index f5bb30c505510f3e2f7ef881709119caa995ff16..0b9cd62bf0c7d31cd3725d8d5a3d22e8832fe280 100644 (file)
@@ -11067,9 +11067,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
                                {
index 56d2bb661612530235249191be86f3ef05e63243..1d3ce246c92703a1bc25915fdab0bf09ee5b402e 100644 (file)
@@ -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);