regdatabase.v1.patch
text/x-patch
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
Series: patch v1
| File | + | − |
|---|---|---|
| doc/src/sgml/datatype.sgml | 13 | 2 |
| doc/src/sgml/func.sgml | 18 | 0 |
| doc/src/sgml/ref/pgupgrade.sgml | 1 | 0 |
| src/backend/bootstrap/bootstrap.c | 2 | 0 |
| src/backend/catalog/dependency.c | 8 | 2 |
| src/backend/utils/adt/regproc.c | 128 | 0 |
| src/backend/utils/adt/selfuncs.c | 1 | 0 |
| src/backend/utils/cache/catcache.c | 1 | 0 |
| src/bin/pg_upgrade/check.c | 1 | 0 |
| src/include/catalog/pg_cast.dat | 14 | 0 |
| src/include/catalog/pg_proc.dat | 17 | 1 |
| src/include/catalog/pg_type.dat | 5 | 0 |
| src/test/regress/expected/regproc.out | 29 | 0 |
| src/test/regress/sql/regproc.sql | 12 | 0 |
commit aea262f0fe6917fbad7edb7db9c0e33a5e3c7941
Author: Ian Barwick <barwick@gmail.com>
Date: Mon May 25 23:44:17 2020 +0900
Implement regdatabase datatype
diff --git a/doc/src/sgml/datatype.sgml b/doc/src/sgml/datatype.sgml
index 7027758d28..cc54c3ffa7 100644
--- a/doc/src/sgml/datatype.sgml
+++ b/doc/src/sgml/datatype.sgml
@@ -4514,6 +4514,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>
@@ -4654,6 +4658,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>
@@ -4738,8 +4749,8 @@ SELECT * FROM pg_attribute
understands that the default expression depends on the sequence
<literal>my_seq</literal>; the system will not let the sequence be dropped
without first removing the default expression.
- <type>regrole</type> is the only exception for the property. Constants of this
- type are not allowed in such expressions.
+ <type>regrole</type> and <type>regdatabase</type> are the only exceptions for the property.
+ Constants of this type are not allowed in such expressions.
</para>
<note>
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index f065856535..fb8d685486 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -22517,6 +22517,24 @@ SELECT collation for ('foo' COLLATE "de_DE");
</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. Also unlike the cast, this does not accept
+ a numeric OID as input.
+ </para></entry>
+ </row>
+
<row>
<entry role="func_table_entry"><para role="func_signature">
<indexterm>
diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml
index 6779a5bddc..9781ab3933 100644
--- a/doc/src/sgml/ref/pgupgrade.sgml
+++ b/doc/src/sgml/ref/pgupgrade.sgml
@@ -777,6 +777,7 @@ psql --username=postgres --file=script.sql postgres
<simplelist>
<member><type>regcollation</type></member>
<member><type>regconfig</type></member>
+ <member><type>regdatabase</type></member>
<member><type>regdictionary</type></member>
<member><type>regnamespace</type></member>
<member><type>regoper</type></member>
diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c
index 5480a024e0..7953b116e9 100644
--- a/src/backend/bootstrap/bootstrap.c
+++ b/src/backend/bootstrap/bootstrap.c
@@ -125,6 +125,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,
diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c
index b33a2f94af..41e28a49f8 100644
--- a/src/backend/catalog/dependency.c
+++ b/src/backend/catalog/dependency.c
@@ -1858,9 +1858,15 @@ find_expr_references_walker(Node *node,
break;
/*
- * Dependencies for regrole should be shared among all
- * databases, so explicitly inhibit to have dependencies.
+ * Explicitly prohibit dependencies for cluster-wide shared objects
*/
+ case REGDATABASEOID:
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("constant of the type %s cannot be used here",
+ "regdatabase")));
+ break;
+
case REGROLEOID:
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
diff --git a/src/backend/utils/adt/regproc.c b/src/backend/utils/adt/regproc.c
index c800d797ac..447286ae6b 100644
--- a/src/backend/utils/adt/regproc.c
+++ b/src/backend/utils/adt/regproc.c
@@ -41,6 +41,8 @@
#include "utils/syscache.h"
#include "utils/varlena.h"
+#include "commands/dbcommands.h"
+
static char *format_operator_internal(Oid operator_oid, bool force_qualify);
static char *format_procedure_internal(Oid procedure_oid, bool force_qualify);
static void parseNameAndArgTypes(const char *string, bool allowNone,
@@ -1810,6 +1812,132 @@ regnamespacesend(PG_FUNCTION_ARGS)
return oidsend(fcinfo);
}
+
+/*
+ * regdatabasein - converts "datname" 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 *dat_name_or_oid = PG_GETARG_CSTRING(0);
+ Oid result;
+ List *names;
+
+ /* '-' ? */
+ if (strcmp(dat_name_or_oid, "-") == 0)
+ PG_RETURN_OID(InvalidOid);
+
+ /* Numeric OID? */
+ if (dat_name_or_oid[0] >= '0' &&
+ dat_name_or_oid[0] <= '9' &&
+ strspn(dat_name_or_oid, "0123456789") == strlen(dat_name_or_oid))
+ {
+ result = DatumGetObjectId(DirectFunctionCall1(oidin,
+ CStringGetDatum(dat_name_or_oid)));
+ 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(dat_name_or_oid);
+
+ if (list_length(names) != 1)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_NAME),
+ errmsg("invalid name syntax")));
+
+ result = get_database_oid(strVal(linitial(names)), false);
+
+ PG_RETURN_OID(result);
+}
+
+/*
+ * to_regdatabase - converts "datname" to database OID
+ *
+ * If the name is not found, we return NULL.
+ */
+Datum
+to_regdatabase(PG_FUNCTION_ARGS)
+{
+ char *dat_name = text_to_cstring(PG_GETARG_TEXT_PP(0));
+ Oid result;
+ List *names;
+
+ names = stringToQualifiedNameList(dat_name);
+
+ if (list_length(names) != 1)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_NAME),
+ errmsg("invalid name syntax")));
+
+ result = get_database_oid(strVal(linitial(names)), true);
+
+ if (OidIsValid(result))
+ PG_RETURN_OID(result);
+ else
+ PG_RETURN_NULL();
+}
+
+/*
+ * regdatabaseout - converts database OID to "dat_name"
+ */
+Datum
+regdatabaseout(PG_FUNCTION_ARGS)
+{
+ Oid datid = PG_GETARG_OID(0);
+ char *result;
+
+ if (datid == InvalidOid)
+ {
+ result = pstrdup("-");
+ PG_RETURN_CSTRING(result);
+ }
+
+ result = get_database_name(datid);
+
+ 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", datid);
+ }
+
+ 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
*
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index be08eb4814..01050f7708 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -4074,6 +4074,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,
diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c
index 3613ae5f44..a533728469 100644
--- a/src/backend/utils/cache/catcache.c
+++ b/src/backend/utils/cache/catcache.c
@@ -243,6 +243,7 @@ GetCCHashEqFuncs(Oid keytype, CCHashFN *hashfunc, RegProcedure *eqfunc, CCFastEq
case REGDICTIONARYOID:
case REGROLEOID:
case REGNAMESPACEOID:
+ case REGDATABASEOID:
*hashfunc = int4hashfast;
*fasteqfunc = int4eqfast;
*eqfunc = F_OIDEQ;
diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c
index 00aef855dc..1c754bbeb5 100644
--- a/src/bin/pg_upgrade/check.c
+++ b/src/bin/pg_upgrade/check.c
@@ -1030,6 +1030,7 @@ check_for_reg_data_type_usage(ClusterInfo *cluster)
/* regclass.oid is preserved, so 'regclass' is OK */
" 'regcollation', "
" 'regconfig', "
+ " 'regdatabase', "
" 'regdictionary', "
" 'regnamespace', "
" 'regoper', "
diff --git a/src/include/catalog/pg_cast.dat b/src/include/catalog/pg_cast.dat
index 5a58f50fbb..d74e89f1e2 100644
--- a/src/include/catalog/pg_cast.dat
+++ b/src/include/catalog/pg_cast.dat
@@ -281,6 +281,20 @@
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',
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 38295aca48..def8908252 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -6767,6 +6767,17 @@
prorettype => 'regnamespace', proargtypes => 'text',
prosrc => 'to_regnamespace' },
+{ oid => '8802', descr => 'I/O',
+ proname => 'regdatabasein', provolatile => 's', prorettype => 'regdatabase',
+ proargtypes => 'cstring', prosrc => 'regdatabasein' },
+{ oid => '8803', descr => 'I/O',
+ proname => 'regdatabaseout', provolatile => 's', prorettype => 'cstring',
+ proargtypes => 'regdatabase', prosrc => 'regdatabaseout' },
+{ oid => '8804', descr => 'convert database name to regdatabase',
+ proname => 'to_regdatabase', provolatile => 's',
+ prorettype => 'regdatabase', proargtypes => 'text',
+ prosrc => 'to_regdatabase' },
+
{ oid => '1268',
descr => 'parse qualified identifier to array of identifiers',
proname => 'parse_ident', prorettype => '_text', proargtypes => 'text bool',
@@ -7561,7 +7572,6 @@
{ oid => '2455', descr => 'I/O',
proname => 'regtypesend', prorettype => 'bytea', proargtypes => 'regtype',
prosrc => 'regtypesend' },
-
{ oid => '4094', descr => 'I/O',
proname => 'regrolerecv', prorettype => 'regrole', proargtypes => 'internal',
prosrc => 'regrolerecv' },
@@ -7574,6 +7584,12 @@
{ oid => '4088', descr => 'I/O',
proname => 'regnamespacesend', prorettype => 'bytea',
proargtypes => 'regnamespace', prosrc => 'regnamespacesend' },
+{ oid => '8805', descr => 'I/O',
+ proname => 'regdatabaserecv', prorettype => 'regdatabase',
+ proargtypes => 'internal', prosrc => 'regdatabaserecv' },
+{ oid => '8806', 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' },
diff --git a/src/include/catalog/pg_type.dat b/src/include/catalog/pg_type.dat
index e8be000835..5e104a740c 100644
--- a/src/include/catalog/pg_type.dat
+++ b/src/include/catalog/pg_type.dat
@@ -401,6 +401,11 @@
typinput => 'regnamespacein', typoutput => 'regnamespaceout',
typreceive => 'regnamespacerecv', typsend => 'regnamespacesend',
typalign => 'i' },
+{ oid => '8800', array_type_oid => '8801', 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 datatype',
diff --git a/src/test/regress/expected/regproc.out b/src/test/regress/expected/regproc.out
index e45ff5483f..a7d75187fd 100644
--- a/src/test/regress/expected/regproc.out
+++ b/src/test/regress/expected/regproc.out
@@ -46,6 +46,12 @@ SELECT regcollation('"POSIX"');
"POSIX"
(1 row)
+SELECT regdatabase('template1');
+ regdatabase
+-------------
+ template1
+(1 row)
+
SELECT to_regoper('||/');
to_regoper
------------
@@ -88,6 +94,12 @@ SELECT to_regcollation('"POSIX"');
"POSIX"
(1 row)
+SELECT to_regdatabase('template1');
+ to_regdatabase
+----------------
+ template1
+(1 row)
+
-- with schemaname
SELECT regoper('pg_catalog.||/');
regoper
@@ -243,6 +255,10 @@ SELECT regtype('int3');
ERROR: type "int3" does not exist
LINE 1: SELECT regtype('int3');
^
+SELECT regdatabase('notadatabase');
+ERROR: database "notadatabase" does not exist
+LINE 1: SELECT regdatabase('notadatabase');
+ ^
-- with schemaname
SELECT regoper('ng_catalog.||/');
ERROR: schema "ng_catalog" does not exist
@@ -349,6 +365,12 @@ SELECT to_regcollation('notacollation');
(1 row)
+SELECT to_regdatabase('notadatabase');
+ to_regdatabase
+----------------
+
+(1 row)
+
-- with schemaname
SELECT to_regoper('ng_catalog.||/');
to_regoper
@@ -435,3 +457,10 @@ SELECT to_regnamespace('"Nonexistent"');
SELECT to_regnamespace('foo.bar');
ERROR: invalid name syntax
+-- constant cannot be used here
+CREATE ROLE regress_regrole_test;
+CREATE TABLE regrole_test (rolid OID DEFAULT 'regress_regrole_test'::regrole);
+ERROR: constant of the type regrole cannot be used here
+DROP ROLE regress_regrole_test;
+CREATE TABLE regdatabase_test (datid OID DEFAULT 'template1'::regdatabase);
+ERROR: constant of the type regdatabase cannot be used here
diff --git a/src/test/regress/sql/regproc.sql b/src/test/regress/sql/regproc.sql
index faab0c15ce..c684886a15 100644
--- a/src/test/regress/sql/regproc.sql
+++ b/src/test/regress/sql/regproc.sql
@@ -15,6 +15,7 @@ SELECT regprocedure('abs(numeric)');
SELECT regclass('pg_class');
SELECT regtype('int4');
SELECT regcollation('"POSIX"');
+SELECT regdatabase('template1');
SELECT to_regoper('||/');
SELECT to_regoperator('+(int4,int4)');
@@ -23,6 +24,7 @@ SELECT to_regprocedure('abs(numeric)');
SELECT to_regclass('pg_class');
SELECT to_regtype('int4');
SELECT to_regcollation('"POSIX"');
+SELECT to_regdatabase('template1');
-- with schemaname
@@ -65,6 +67,7 @@ SELECT regproc('know');
SELECT regprocedure('absinthe(numeric)');
SELECT regclass('pg_classes');
SELECT regtype('int3');
+SELECT regdatabase('notadatabase');
-- with schemaname
@@ -98,6 +101,7 @@ SELECT to_regprocedure('absinthe(numeric)');
SELECT to_regclass('pg_classes');
SELECT to_regtype('int3');
SELECT to_regcollation('notacollation');
+SELECT to_regdatabase('notadatabase');
-- with schemaname
@@ -120,3 +124,11 @@ SELECT to_regrole('foo.bar');
SELECT to_regnamespace('Nonexistent');
SELECT to_regnamespace('"Nonexistent"');
SELECT to_regnamespace('foo.bar');
+
+-- constant cannot be used here
+
+CREATE ROLE regress_regrole_test;
+CREATE TABLE regrole_test (rolid OID DEFAULT 'regress_regrole_test'::regrole);
+DROP ROLE regress_regrole_test;
+
+CREATE TABLE regdatabase_test (datid OID DEFAULT 'template1'::regdatabase);