Add new OID alias type regdatabase.
authorNathan Bossart <[email protected]>
Mon, 30 Jun 2025 20:38:54 +0000 (15:38 -0500)
committerNathan Bossart <[email protected]>
Mon, 30 Jun 2025 20:38:54 +0000 (15:38 -0500)
This provides a convenient way to look up a database's OID.  For
example, the query

    SELECT * FROM pg_shdepend
    WHERE dbid = (SELECT oid FROM pg_database
                  WHERE datname = current_database());

can now be simplified to

    SELECT * FROM pg_shdepend
    WHERE dbid = current_database()::regdatabase;

Like the regrole type, regdatabase has cluster-wide scope, so we
disallow regdatabase constants from appearing in stored
expressions.

Bumps catversion.

Author: Ian Lawrence Barwick <[email protected]>
Reviewed-by: Greg Sabino Mullane <[email protected]>
Reviewed-by: Jian He <[email protected]>
Reviewed-by: Fabrízio de Royes Mello <[email protected]>
Reviewed-by: Tom Lane <[email protected]>
Discussion: https://postgr.es/m/aBpjJhyHpM2LYcG0%40nathan

18 files changed:
contrib/postgres_fdw/deparse.c
doc/src/sgml/datatype.sgml
doc/src/sgml/func.sgml
doc/src/sgml/ref/pgupgrade.sgml
src/backend/bootstrap/bootstrap.c
src/backend/catalog/dependency.c
src/backend/utils/adt/regproc.c
src/backend/utils/adt/selfuncs.c
src/backend/utils/cache/catcache.c
src/bin/pg_upgrade/check.c
src/include/catalog/catversion.h
src/include/catalog/pg_cast.dat
src/include/catalog/pg_proc.dat
src/include/catalog/pg_type.dat
src/test/regress/expected/regproc.out
src/test/regress/expected/type_sanity.out
src/test/regress/sql/regproc.sql
src/test/regress/sql/type_sanity.sql

index d9970dd6753364c83db076a9deb874b91b68aa16..9351835b5e4f8038a5d8d8a4def6de4f89ab76b2 100644 (file)
@@ -39,6 +39,7 @@
 #include "catalog/pg_aggregate.h"
 #include "catalog/pg_authid.h"
 #include "catalog/pg_collation.h"
+#include "catalog/pg_database.h"
 #include "catalog/pg_namespace.h"
 #include "catalog/pg_operator.h"
 #include "catalog/pg_opfamily.h"
@@ -455,6 +456,11 @@ foreign_expr_walker(Node *node,
                                              AuthIdRelationId, fpinfo))
                                return false;
                            break;
+                       case REGDATABASEOID:
+                           if (!is_shippable(DatumGetObjectId(c->constvalue),
+                                             DatabaseRelationId, fpinfo))
+                               return false;
+                           break;
                    }
                }
 
index 09309ba0390b72cd20e3a47f315212bda364d428..49a7c180a803e71058433dd68692f21eaa8f0594 100644 (file)
@@ -4737,6 +4737,10 @@ INSERT INTO mytable VALUES(-1);  -- fails
     <primary>regconfig</primary>
    </indexterm>
 
+   <indexterm zone="datatype-oid">
+    <primary>regdatabase</primary>
+   </indexterm>
+
    <indexterm zone="datatype-oid">
     <primary>regdictionary</primary>
    </indexterm>
@@ -4878,6 +4882,13 @@ SELECT * FROM pg_attribute
         <entry><literal>english</literal></entry>
        </row>
 
+       <row>
+        <entry><type>regdatabase</type></entry>
+        <entry><structname>pg_database</structname></entry>
+        <entry>database name</entry>
+        <entry><literal>template1</literal></entry>
+       </row>
+
        <row>
         <entry><type>regdictionary</type></entry>
         <entry><structname>pg_ts_dict</structname></entry>
@@ -5049,8 +5060,8 @@ WHERE ...
     be dropped without first removing the default expression.  The
     alternative of <literal>nextval('my_seq'::text)</literal> does not
     create a dependency.
-    (<type>regrole</type> is an exception to this property. Constants of this
-    type are not allowed in stored expressions.)
+    (<type>regdatabase</type> and <type>regrole</type> are exceptions to this
+    property.  Constants of these types are not allowed in stored expressions.)
    </para>
 
    <para>
index 298791858be309ff0ea525b43bbee544f8569e71..126b8cfbad81ecce0c7284adfbb695ed42802e4c 100644 (file)
@@ -26750,6 +26750,23 @@ SELECT currval(pg_get_serial_sequence('sometable', 'id'));
        </para></entry>
       </row>
 
+      <row>
+       <entry role="func_table_entry"><para role="func_signature">
+        <indexterm>
+         <primary>to_regdatabase</primary>
+        </indexterm>
+        <function>to_regdatabase</function> ( <type>text</type> )
+        <returnvalue>regdatabase</returnvalue>
+       </para>
+       <para>
+        Translates a textual database name to its OID.  A similar result is
+        obtained by casting the string to type <type>regdatabase</type> (see
+        <xref linkend="datatype-oid"/>); however, this function will return
+        <literal>NULL</literal> rather than throwing an error if the name is
+        not found.
+       </para></entry>
+      </row>
+
       <row>
        <entry role="func_table_entry"><para role="func_signature">
         <indexterm>
index aeeed297437e692d20f9055f32f57a682b886a2f..5ddf3a8ae9257402e1b55146469dd495f159af9e 100644 (file)
@@ -1110,7 +1110,8 @@ psql --username=postgres --file=script.sql postgres
     <member><type>regproc</type></member>
     <member><type>regprocedure</type></member>
    </simplelist>
-   (<type>regclass</type>, <type>regrole</type>, and <type>regtype</type> can be upgraded.)
+   (<type>regclass</type>, <type>regdatabase</type>, <type>regrole</type>, and
+   <type>regtype</type> can be upgraded.)
   </para>
 
   <para>
index 6db864892d0ddeb282bf0f71a0f211b0b5566e61..fc8638c1b61b65e7c1a985e72ac2e419e439132a 100644 (file)
@@ -109,6 +109,8 @@ static const struct typinfo TypInfo[] = {
    F_REGROLEIN, F_REGROLEOUT},
    {"regnamespace", REGNAMESPACEOID, 0, 4, true, TYPALIGN_INT, TYPSTORAGE_PLAIN, InvalidOid,
    F_REGNAMESPACEIN, F_REGNAMESPACEOUT},
+   {"regdatabase", REGDATABASEOID, 0, 4, true, TYPALIGN_INT, TYPSTORAGE_PLAIN, InvalidOid,
+   F_REGDATABASEIN, F_REGDATABASEOUT},
    {"text", TEXTOID, 0, -1, false, TYPALIGN_INT, TYPSTORAGE_EXTENDED, DEFAULT_COLLATION_OID,
    F_TEXTIN, F_TEXTOUT},
    {"oid", OIDOID, 0, 4, true, TYPALIGN_INT, TYPSTORAGE_PLAIN, InvalidOid,
index 18316a3968bcf88e73d9879f983b75298460ea36..7dded634eb8100a4576a7bcfdb0334fa73559f77 100644 (file)
@@ -1850,6 +1850,17 @@ find_expr_references_walker(Node *node,
                             errmsg("constant of the type %s cannot be used here",
                                    "regrole")));
                    break;
+
+                   /*
+                    * Dependencies for regdatabase should be shared among all
+                    * databases, so explicitly inhibit to have dependencies.
+                    */
+               case REGDATABASEOID:
+                   ereport(ERROR,
+                           (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+                            errmsg("constant of the type %s cannot be used here",
+                                   "regdatabase")));
+                   break;
            }
        }
        return false;
index 5ee608a2b3921dfa4d113be6eb802d073910a37e..b8bbe95e82eb8e9bba50d9d73997820c9ef3a1e0 100644 (file)
@@ -30,6 +30,7 @@
 #include "catalog/pg_ts_config.h"
 #include "catalog/pg_ts_dict.h"
 #include "catalog/pg_type.h"
+#include "commands/dbcommands.h"
 #include "lib/stringinfo.h"
 #include "mb/pg_wchar.h"
 #include "miscadmin.h"
@@ -1763,6 +1764,123 @@ regnamespacesend(PG_FUNCTION_ARGS)
    return oidsend(fcinfo);
 }
 
+/*
+ * regdatabasein - converts database name to database OID
+ *
+ * We also accept a numeric OID, for symmetry with the output routine.
+ *
+ * '-' signifies unknown (OID 0).  In all other cases, the input must
+ * match an existing pg_database entry.
+ */
+Datum
+regdatabasein(PG_FUNCTION_ARGS)
+{
+   char       *db_name_or_oid = PG_GETARG_CSTRING(0);
+   Node       *escontext = fcinfo->context;
+   Oid         result;
+   List       *names;
+
+   /* Handle "-" or numeric OID */
+   if (parseDashOrOid(db_name_or_oid, &result, escontext))
+       PG_RETURN_OID(result);
+
+   /* The rest of this wouldn't work in bootstrap mode */
+   if (IsBootstrapProcessingMode())
+       elog(ERROR, "regdatabase values must be OIDs in bootstrap mode");
+
+   /* Normal case: see if the name matches any pg_database entry. */
+   names = stringToQualifiedNameList(db_name_or_oid, escontext);
+   if (names == NIL)
+       PG_RETURN_NULL();
+
+   if (list_length(names) != 1)
+       ereturn(escontext, (Datum) 0,
+               (errcode(ERRCODE_INVALID_NAME),
+                errmsg("invalid name syntax")));
+
+   result = get_database_oid(strVal(linitial(names)), true);
+
+   if (!OidIsValid(result))
+       ereturn(escontext, (Datum) 0,
+               (errcode(ERRCODE_UNDEFINED_OBJECT),
+                errmsg("database \"%s\" does not exist",
+                       strVal(linitial(names)))));
+
+   PG_RETURN_OID(result);
+}
+
+/*
+ * to_regdatabase - converts database name to database OID
+ *
+ * If the name is not found, we return NULL.
+ */
+Datum
+to_regdatabase(PG_FUNCTION_ARGS)
+{
+   char       *db_name = text_to_cstring(PG_GETARG_TEXT_PP(0));
+   Datum       result;
+   ErrorSaveContext escontext = {T_ErrorSaveContext};
+
+   if (!DirectInputFunctionCallSafe(regdatabasein, db_name,
+                                    InvalidOid, -1,
+                                    (Node *) &escontext,
+                                    &result))
+       PG_RETURN_NULL();
+   PG_RETURN_DATUM(result);
+}
+
+/*
+ * regdatabaseout - converts database OID to database name
+ */
+Datum
+regdatabaseout(PG_FUNCTION_ARGS)
+{
+   Oid         dboid = PG_GETARG_OID(0);
+   char       *result;
+
+   if (dboid == InvalidOid)
+   {
+       result = pstrdup("-");
+       PG_RETURN_CSTRING(result);
+   }
+
+   result = get_database_name(dboid);
+
+   if (result)
+   {
+       /* pstrdup is not really necessary, but it avoids a compiler warning */
+       result = pstrdup(quote_identifier(result));
+   }
+   else
+   {
+       /* If OID doesn't match any database, return it numerically */
+       result = (char *) palloc(NAMEDATALEN);
+       snprintf(result, NAMEDATALEN, "%u", dboid);
+   }
+
+   PG_RETURN_CSTRING(result);
+}
+
+/*
+ * regdatabaserecv - converts external binary format to regdatabase
+ */
+Datum
+regdatabaserecv(PG_FUNCTION_ARGS)
+{
+   /* Exactly the same as oidrecv, so share code */
+   return oidrecv(fcinfo);
+}
+
+/*
+ * regdatabasesend - converts regdatabase to binary format
+ */
+Datum
+regdatabasesend(PG_FUNCTION_ARGS)
+{
+   /* Exactly the same as oidsend, so share code */
+   return oidsend(fcinfo);
+}
+
 /*
  * text_regclass: convert text to regclass
  *
index 1e0f2de0336b00d1feabbb7aa8c85be81cc420cf..ce6a626eba2831c4430a6fe72d32613b7cca5ca6 100644 (file)
@@ -4619,6 +4619,7 @@ convert_to_scalar(Datum value, Oid valuetypid, Oid collid, double *scaledvalue,
        case REGDICTIONARYOID:
        case REGROLEOID:
        case REGNAMESPACEOID:
+       case REGDATABASEOID:
            *scaledvalue = convert_numeric_to_scalar(value, valuetypid,
                                                     &failure);
            *scaledlobound = convert_numeric_to_scalar(lobound, boundstypid,
@@ -4751,6 +4752,7 @@ convert_numeric_to_scalar(Datum value, Oid typid, bool *failure)
        case REGDICTIONARYOID:
        case REGROLEOID:
        case REGNAMESPACEOID:
+       case REGDATABASEOID:
            /* we can treat OIDs as integers... */
            return (double) DatumGetObjectId(value);
    }
index 657648996c235ef4002a926d1298e910efa3631f..d1b25214376ed5b74d6fd01ec3fcfd65b049a0d1 100644 (file)
@@ -317,6 +317,7 @@ GetCCHashEqFuncs(Oid keytype, CCHashFN *hashfunc, RegProcedure *eqfunc, CCFastEq
        case REGDICTIONARYOID:
        case REGROLEOID:
        case REGNAMESPACEOID:
+       case REGDATABASEOID:
            *hashfunc = int4hashfast;
            *fasteqfunc = int4eqfast;
            *eqfunc = F_OIDEQ;
index 81865cd3e4859cb5ca9121b391536b2d7f3d668f..fb063a2de428612b3b1c007d99f595b3f72f5fcf 100644 (file)
@@ -168,6 +168,7 @@ static DataTypesUsageChecks data_types_usage_checks[] =
        /* pg_class.oid is preserved, so 'regclass' is OK */
        "           'regcollation', "
        "           'regconfig', "
+       /* pg_database.oid is preserved, so 'regdatabase' is OK */
        "           'regdictionary', "
        "           'regnamespace', "
        "           'regoper', "
index 479629825f5b7683442c7e4c9bcc98a561d3949e..ff9ffd9d474988283d47b6f78b24b46619c3996b 100644 (file)
@@ -57,6 +57,6 @@
  */
 
 /*                         yyyymmddN */
-#define CATALOG_VERSION_NO 202506291
+#define CATALOG_VERSION_NO 202506301
 
 #endif
index ab46be606f03dc59aa7486b88d8ec8764bfb741f..fbfd669587f0797ccc62f0a65a0381b0c88eb6ae 100644 (file)
   castcontext => 'a', castmethod => 'f' },
 { castsource => 'regnamespace', casttarget => 'int4', castfunc => '0',
   castcontext => 'a', castmethod => 'b' },
+{ castsource => 'oid', casttarget => 'regdatabase', castfunc => '0',
+  castcontext => 'i', castmethod => 'b' },
+{ castsource => 'regdatabase', casttarget => 'oid', castfunc => '0',
+  castcontext => 'i', castmethod => 'b' },
+{ castsource => 'int8', casttarget => 'regdatabase', castfunc => 'oid',
+  castcontext => 'i', castmethod => 'f' },
+{ castsource => 'int2', casttarget => 'regdatabase', castfunc => 'int4(int2)',
+  castcontext => 'i', castmethod => 'f' },
+{ castsource => 'int4', casttarget => 'regdatabase', castfunc => '0',
+  castcontext => 'i', castmethod => 'b' },
+{ castsource => 'regdatabase', casttarget => 'int8', castfunc => 'int8(oid)',
+  castcontext => 'a', castmethod => 'f' },
+{ castsource => 'regdatabase', casttarget => 'int4', castfunc => '0',
+  castcontext => 'a', castmethod => 'b' },
 
 # String category
 { castsource => 'text', casttarget => 'bpchar', castfunc => '0',
index fb4f7f50350adb41c152982f67732c8b048fe610..d4650947c63a58aadc9f2bbba605b4472ee36319 100644 (file)
   prorettype => 'regnamespace', proargtypes => 'text',
   prosrc => 'to_regnamespace' },
 
+{ oid => '8321', descr => 'I/O',
+  proname => 'regdatabasein', provolatile => 's', prorettype => 'regdatabase',
+  proargtypes => 'cstring', prosrc => 'regdatabasein' },
+{ oid => '8322', descr => 'I/O',
+  proname => 'regdatabaseout', provolatile => 's', prorettype => 'cstring',
+  proargtypes => 'regdatabase', prosrc => 'regdatabaseout' },
+{ oid => '8323', descr => 'convert database name to regdatabase',
+  proname => 'to_regdatabase', provolatile => 's',
+  prorettype => 'regdatabase', proargtypes => 'text',
+  prosrc => 'to_regdatabase' },
+
 { oid => '6210', descr => 'test whether string is valid input for data type',
   proname => 'pg_input_is_valid', provolatile => 's', prorettype => 'bool',
   proargtypes => 'text text', prosrc => 'pg_input_is_valid' },
 { oid => '4088', descr => 'I/O',
   proname => 'regnamespacesend', prorettype => 'bytea',
   proargtypes => 'regnamespace', prosrc => 'regnamespacesend' },
+{ oid => '8324', descr => 'I/O',
+  proname => 'regdatabaserecv', prorettype => 'regdatabase',
+  proargtypes => 'internal', prosrc => 'regdatabaserecv' },
+{ oid => '8325', descr => 'I/O',
+  proname => 'regdatabasesend', prorettype => 'bytea',
+  proargtypes => 'regdatabase', prosrc => 'regdatabasesend' },
 { oid => '2456', descr => 'I/O',
   proname => 'bit_recv', prorettype => 'bit',
   proargtypes => 'internal oid int4', prosrc => 'bit_recv' },
index 6dca77e0a22f710094a76733d7e1d502453e7607..29e4ffffc98067b17b227e2e3a8d862b8ce49d1a 100644 (file)
   typinput => 'regnamespacein', typoutput => 'regnamespaceout',
   typreceive => 'regnamespacerecv', typsend => 'regnamespacesend',
   typalign => 'i' },
+{ oid => '8326', array_type_oid => '8327', descr => 'registered database',
+  typname => 'regdatabase', typlen => '4', typbyval => 't', typcategory => 'N',
+  typinput => 'regdatabasein', typoutput => 'regdatabaseout',
+  typreceive => 'regdatabaserecv', typsend => 'regdatabasesend',
+  typalign => 'i' },
 
 # uuid
 { oid => '2950', array_type_oid => '2951', descr => 'UUID',
index 97b917502cabbaeb20b5921ce952bf5fb28b57fb..84c84aef4207fdc95b0c37cd393071f6006d0937 100644 (file)
@@ -192,6 +192,18 @@ SELECT regnamespace('"pg_catalog"');
  pg_catalog
 (1 row)
 
+SELECT regdatabase('template1');
+ regdatabase 
+-------------
+ template1
+(1 row)
+
+SELECT regdatabase('"template1"');
+ regdatabase 
+-------------
+ template1
+(1 row)
+
 SELECT to_regrole('regress_regrole_test');
       to_regrole      
 ----------------------
@@ -216,6 +228,132 @@ SELECT to_regnamespace('"pg_catalog"');
  pg_catalog
 (1 row)
 
+SELECT to_regdatabase('template1');
+ to_regdatabase 
+----------------
+ template1
+(1 row)
+
+SELECT to_regdatabase('"template1"');
+ to_regdatabase 
+----------------
+ template1
+(1 row)
+
+-- special "single dash" case
+SELECT regproc('-')::oid;
+ regproc 
+---------
+       0
+(1 row)
+
+SELECT regprocedure('-')::oid;
+ regprocedure 
+--------------
+            0
+(1 row)
+
+SELECT regclass('-')::oid;
+ regclass 
+----------
+        0
+(1 row)
+
+SELECT regcollation('-')::oid;
+ regcollation 
+--------------
+            0
+(1 row)
+
+SELECT regtype('-')::oid;
+ regtype 
+---------
+       0
+(1 row)
+
+SELECT regconfig('-')::oid;
+ regconfig 
+-----------
+         0
+(1 row)
+
+SELECT regdictionary('-')::oid;
+ regdictionary 
+---------------
+             0
+(1 row)
+
+SELECT regrole('-')::oid;
+ regrole 
+---------
+       0
+(1 row)
+
+SELECT regnamespace('-')::oid;
+ regnamespace 
+--------------
+            0
+(1 row)
+
+SELECT regdatabase('-')::oid;
+ regdatabase 
+-------------
+           0
+(1 row)
+
+SELECT to_regproc('-')::oid;
+ to_regproc 
+------------
+          0
+(1 row)
+
+SELECT to_regprocedure('-')::oid;
+ to_regprocedure 
+-----------------
+               0
+(1 row)
+
+SELECT to_regclass('-')::oid;
+ to_regclass 
+-------------
+           0
+(1 row)
+
+SELECT to_regcollation('-')::oid;
+ to_regcollation 
+-----------------
+               0
+(1 row)
+
+SELECT to_regtype('-')::oid;
+ to_regtype 
+------------
+          0
+(1 row)
+
+SELECT to_regrole('-')::oid;
+ to_regrole 
+------------
+          0
+(1 row)
+
+SELECT to_regnamespace('-')::oid;
+ to_regnamespace 
+-----------------
+               0
+(1 row)
+
+SELECT to_regdatabase('-')::oid;
+ to_regdatabase 
+----------------
+              0
+(1 row)
+
+-- constant cannot be used here
+CREATE TABLE regrole_test (rolid OID DEFAULT 'regress_regrole_test'::regrole);
+ERROR:  constant of the type regrole cannot be used here
+CREATE TABLE regdatabase_test (datid OID DEFAULT 'template1'::regdatabase);
+ERROR:  constant of the type regdatabase cannot be used here
 /* If objects don't exist, raise errors. */
 DROP ROLE regress_regrole_test;
 -- without schemaname
@@ -305,6 +443,18 @@ SELECT regnamespace('foo.bar');
 ERROR:  invalid name syntax
 LINE 1: SELECT regnamespace('foo.bar');
                             ^
+SELECT regdatabase('Nonexistent');
+ERROR:  database "nonexistent" does not exist
+LINE 1: SELECT regdatabase('Nonexistent');
+                           ^
+SELECT regdatabase('"Nonexistent"');
+ERROR:  database "Nonexistent" does not exist
+LINE 1: SELECT regdatabase('"Nonexistent"');
+                           ^
+SELECT regdatabase('foo.bar');
+ERROR:  invalid name syntax
+LINE 1: SELECT regdatabase('foo.bar');
+                           ^
 /* If objects don't exist, return NULL with no error. */
 -- without schemaname
 SELECT to_regoper('||//');
@@ -447,6 +597,24 @@ SELECT to_regnamespace('foo.bar');
  
 (1 row)
 
+SELECT to_regdatabase('Nonexistent');
+ to_regdatabase 
+----------------
+(1 row)
+
+SELECT to_regdatabase('"Nonexistent"');
+ to_regdatabase 
+----------------
+(1 row)
+
+SELECT to_regdatabase('foo.bar');
+ to_regdatabase 
+----------------
+(1 row)
+
 -- Test to_regtypemod
 SELECT to_regtypemod('text');
  to_regtypemod 
@@ -569,6 +737,12 @@ SELECT * FROM pg_input_error_info('no_such_type', 'regtype');
  type "no_such_type" does not exist |        |      | 42704
 (1 row)
 
+SELECT * FROM pg_input_error_info('Nonexistent', 'regdatabase');
+                message                | detail | hint | sql_error_code 
+---------------------------------------+--------+------+----------------
+ database "nonexistent" does not exist |        |      | 42704
+(1 row)
+
 -- Some cases that should be soft errors, but are not yet
 SELECT * FROM pg_input_error_info('incorrect type name syntax', 'regtype');
 ERROR:  syntax error at or near "type"
index dd0c52ab08b5051cd4a3a63b44743a0f7a7b6356..943e56506bf1bec6bcdce8b634a16a75f5345863 100644 (file)
@@ -711,6 +711,7 @@ CREATE TABLE tab_core_types AS SELECT
   'regtype'::regtype type,
   'pg_monitor'::regrole,
   'pg_class'::regclass::oid,
+  'template1'::regdatabase,
   '(1,1)'::tid, '2'::xid, '3'::cid,
   '10:20:10,14,15'::txid_snapshot,
   '10:20:10,14,15'::pg_snapshot,
index 232289ac398234f0eef170b1d130df41fb463939..cfec8f8c754a26b5c04d2f23d15bcb358f91f672 100644 (file)
@@ -47,11 +47,42 @@ SELECT regrole('regress_regrole_test');
 SELECT regrole('"regress_regrole_test"');
 SELECT regnamespace('pg_catalog');
 SELECT regnamespace('"pg_catalog"');
+SELECT regdatabase('template1');
+SELECT regdatabase('"template1"');
 
 SELECT to_regrole('regress_regrole_test');
 SELECT to_regrole('"regress_regrole_test"');
 SELECT to_regnamespace('pg_catalog');
 SELECT to_regnamespace('"pg_catalog"');
+SELECT to_regdatabase('template1');
+SELECT to_regdatabase('"template1"');
+
+-- special "single dash" case
+
+SELECT regproc('-')::oid;
+SELECT regprocedure('-')::oid;
+SELECT regclass('-')::oid;
+SELECT regcollation('-')::oid;
+SELECT regtype('-')::oid;
+SELECT regconfig('-')::oid;
+SELECT regdictionary('-')::oid;
+SELECT regrole('-')::oid;
+SELECT regnamespace('-')::oid;
+SELECT regdatabase('-')::oid;
+
+SELECT to_regproc('-')::oid;
+SELECT to_regprocedure('-')::oid;
+SELECT to_regclass('-')::oid;
+SELECT to_regcollation('-')::oid;
+SELECT to_regtype('-')::oid;
+SELECT to_regrole('-')::oid;
+SELECT to_regnamespace('-')::oid;
+SELECT to_regdatabase('-')::oid;
+
+-- constant cannot be used here
+
+CREATE TABLE regrole_test (rolid OID DEFAULT 'regress_regrole_test'::regrole);
+CREATE TABLE regdatabase_test (datid OID DEFAULT 'template1'::regdatabase);
 
 /* If objects don't exist, raise errors. */
 
@@ -88,6 +119,9 @@ SELECT regrole('foo.bar');
 SELECT regnamespace('Nonexistent');
 SELECT regnamespace('"Nonexistent"');
 SELECT regnamespace('foo.bar');
+SELECT regdatabase('Nonexistent');
+SELECT regdatabase('"Nonexistent"');
+SELECT regdatabase('foo.bar');
 
 /* If objects don't exist, return NULL with no error. */
 
@@ -122,6 +156,9 @@ SELECT to_regrole('foo.bar');
 SELECT to_regnamespace('Nonexistent');
 SELECT to_regnamespace('"Nonexistent"');
 SELECT to_regnamespace('foo.bar');
+SELECT to_regdatabase('Nonexistent');
+SELECT to_regdatabase('"Nonexistent"');
+SELECT to_regdatabase('foo.bar');
 
 -- Test to_regtypemod
 SELECT to_regtypemod('text');
@@ -147,6 +184,7 @@ SELECT * FROM pg_input_error_info('ng_catalog.abs(numeric)', 'regprocedure');
 SELECT * FROM pg_input_error_info('ng_catalog.abs(numeric', 'regprocedure');
 SELECT * FROM pg_input_error_info('regress_regrole_test', 'regrole');
 SELECT * FROM pg_input_error_info('no_such_type', 'regtype');
+SELECT * FROM pg_input_error_info('Nonexistent', 'regdatabase');
 
 -- Some cases that should be soft errors, but are not yet
 SELECT * FROM pg_input_error_info('incorrect type name syntax', 'regtype');
index c94dd83d3061cad2f490ceef33f2ffb1a1ffb8d2..df795759bb4cbfa83748cc8f086b406d6e86bc03 100644 (file)
@@ -539,6 +539,7 @@ CREATE TABLE tab_core_types AS SELECT
   'regtype'::regtype type,
   'pg_monitor'::regrole,
   'pg_class'::regclass::oid,
+  'template1'::regdatabase,
   '(1,1)'::tid, '2'::xid, '3'::cid,
   '10:20:10,14,15'::txid_snapshot,
   '10:20:10,14,15'::pg_snapshot,