aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPeter Eisentraut <peter@eisentraut.org>2020-03-18 21:20:01 +0100
committerPeter Eisentraut <peter@eisentraut.org>2020-03-18 21:21:00 +0100
commita2b1faa0f279f18517adc1dd969e5f026eb51d33 (patch)
treefdaad46a4934875be4e420c4990759663368802d /src
parentc31132d87c6315bbbe4b4aa383705aaae2348c0e (diff)
downloadpostgresql-a2b1faa0f279f18517adc1dd969e5f026eb51d33.tar.gz
postgresql-a2b1faa0f279f18517adc1dd969e5f026eb51d33.zip
Implement type regcollation
This will be helpful for a following commit and it's also just generally useful, like the other reg* types. Author: Julien Rouhaud Reviewed-by: Thomas Munro and Michael Paquier Discussion: https://postgr.es/m/CAEepm%3D0uEQCpfq_%2BLYFBdArCe4Ot98t1aR4eYiYTe%3DyavQygiQ%40mail.gmail.com
Diffstat (limited to 'src')
-rw-r--r--src/backend/utils/adt/regproc.c152
-rw-r--r--src/bin/pg_upgrade/check.c1
-rw-r--r--src/include/catalog/catversion.h2
-rw-r--r--src/include/catalog/pg_cast.dat14
-rw-r--r--src/include/catalog/pg_proc.dat15
-rw-r--r--src/include/catalog/pg_type.dat4
-rw-r--r--src/test/regress/expected/regproc.out40
-rw-r--r--src/test/regress/sql/regproc.sql7
8 files changed, 234 insertions, 1 deletions
diff --git a/src/backend/utils/adt/regproc.c b/src/backend/utils/adt/regproc.c
index f0fa52bc27e..da8cc0cf6b2 100644
--- a/src/backend/utils/adt/regproc.c
+++ b/src/backend/utils/adt/regproc.c
@@ -24,6 +24,7 @@
#include "access/htup_details.h"
#include "catalog/namespace.h"
#include "catalog/pg_class.h"
+#include "catalog/pg_collation.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_ts_config.h"
@@ -1044,6 +1045,157 @@ regclasssend(PG_FUNCTION_ARGS)
/*
+ * regcollationin - converts "collationname" to collation 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_collation entry.
+ */
+Datum
+regcollationin(PG_FUNCTION_ARGS)
+{
+ char *collation_name_or_oid = PG_GETARG_CSTRING(0);
+ Oid result = InvalidOid;
+ List *names;
+
+ /* '-' ? */
+ if (strcmp(collation_name_or_oid, "-") == 0)
+ PG_RETURN_OID(InvalidOid);
+
+ /* Numeric OID? */
+ if (collation_name_or_oid[0] >= '0' &&
+ collation_name_or_oid[0] <= '9' &&
+ strspn(collation_name_or_oid, "0123456789") == strlen(collation_name_or_oid))
+ {
+ result = DatumGetObjectId(DirectFunctionCall1(oidin,
+ CStringGetDatum(collation_name_or_oid)));
+ PG_RETURN_OID(result);
+ }
+
+ /* Else it's a name, possibly schema-qualified */
+
+ /* The rest of this wouldn't work in bootstrap mode */
+ if (IsBootstrapProcessingMode())
+ elog(ERROR, "regcollation values must be OIDs in bootstrap mode");
+
+ /*
+ * Normal case: parse the name into components and see if it matches any
+ * pg_collation entries in the current search path.
+ */
+ names = stringToQualifiedNameList(collation_name_or_oid);
+
+ result = get_collation_oid(names, false);
+
+ PG_RETURN_OID(result);
+}
+
+/*
+ * to_regcollation - converts "collationname" to collation OID
+ *
+ * If the name is not found, we return NULL.
+ */
+Datum
+to_regcollation(PG_FUNCTION_ARGS)
+{
+ char *collation_name = text_to_cstring(PG_GETARG_TEXT_PP(0));
+ Oid result;
+ List *names;
+
+ /*
+ * Parse the name into components and see if it matches any pg_collation
+ * entries in the current search path.
+ */
+ names = stringToQualifiedNameList(collation_name);
+
+ /* We might not even have permissions on this relation; don't lock it. */
+ result = get_collation_oid(names, true);
+
+ if (OidIsValid(result))
+ PG_RETURN_OID(result);
+ else
+ PG_RETURN_NULL();
+}
+
+/*
+ * regcollationout - converts collation OID to "collation_name"
+ */
+Datum
+regcollationout(PG_FUNCTION_ARGS)
+{
+ Oid collationid = PG_GETARG_OID(0);
+ char *result;
+ HeapTuple collationtup;
+
+ if (collationid == InvalidOid)
+ {
+ result = pstrdup("-");
+ PG_RETURN_CSTRING(result);
+ }
+
+ collationtup = SearchSysCache1(COLLOID, ObjectIdGetDatum(collationid));
+
+ if (HeapTupleIsValid(collationtup))
+ {
+ Form_pg_collation collationform = (Form_pg_collation) GETSTRUCT(collationtup);
+ char *collationname = NameStr(collationform->collname);
+
+ /*
+ * In bootstrap mode, skip the fancy namespace stuff and just return
+ * the collation name. (This path is only needed for debugging output
+ * anyway.)
+ */
+ if (IsBootstrapProcessingMode())
+ result = pstrdup(collationname);
+ else
+ {
+ char *nspname;
+
+ /*
+ * Would this collation be found by regcollationin? If not, qualify it.
+ */
+ if (CollationIsVisible(collationid))
+ nspname = NULL;
+ else
+ nspname = get_namespace_name(collationform->collnamespace);
+
+ result = quote_qualified_identifier(nspname, collationname);
+ }
+
+ ReleaseSysCache(collationtup);
+ }
+ else
+ {
+ /* If OID doesn't match any pg_collation entry, return it numerically */
+ result = (char *) palloc(NAMEDATALEN);
+ snprintf(result, NAMEDATALEN, "%u", collationid);
+ }
+
+ PG_RETURN_CSTRING(result);
+}
+
+/*
+ * regcollationrecv - converts external binary format to regcollation
+ */
+Datum
+regcollationrecv(PG_FUNCTION_ARGS)
+{
+ /* Exactly the same as oidrecv, so share code */
+ return oidrecv(fcinfo);
+}
+
+/*
+ * regcollationsend - converts regcollation to binary format
+ */
+Datum
+regcollationsend(PG_FUNCTION_ARGS)
+{
+ /* Exactly the same as oidsend, so share code */
+ return oidsend(fcinfo);
+}
+
+
+/*
* regtypein - converts "typename" to type OID
*
* The type name can be specified using the full type syntax recognized by
diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c
index 5f9a102a747..00aef855dc0 100644
--- a/src/bin/pg_upgrade/check.c
+++ b/src/bin/pg_upgrade/check.c
@@ -1028,6 +1028,7 @@ check_for_reg_data_type_usage(ClusterInfo *cluster)
" WHERE nspname = 'pg_catalog') AND"
" t.typname IN ( "
/* regclass.oid is preserved, so 'regclass' is OK */
+ " 'regcollation', "
" 'regconfig', "
" 'regdictionary', "
" 'regnamespace', "
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index 6ad90bac3dd..3fee9342cc1 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 202003051
+#define CATALOG_VERSION_NO 202003181
#endif
diff --git a/src/include/catalog/pg_cast.dat b/src/include/catalog/pg_cast.dat
index 6ef8b8a4e7f..01c5328dddb 100644
--- a/src/include/catalog/pg_cast.dat
+++ b/src/include/catalog/pg_cast.dat
@@ -189,6 +189,20 @@
castcontext => 'a', castmethod => 'f' },
{ castsource => 'regclass', casttarget => 'int4', castfunc => '0',
castcontext => 'a', castmethod => 'b' },
+{ castsource => 'oid', casttarget => 'regcollation', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'regcollation', casttarget => 'oid', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'int8', casttarget => 'regcollation', castfunc => 'oid',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'int2', casttarget => 'regcollation', castfunc => 'int4(int2)',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'int4', casttarget => 'regcollation', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'regcollation', casttarget => 'int8', castfunc => 'int8(oid)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'regcollation', casttarget => 'int4', castfunc => '0',
+ castcontext => 'a', castmethod => 'b' },
{ castsource => 'oid', casttarget => 'regtype', castfunc => '0',
castcontext => 'i', castmethod => 'b' },
{ castsource => 'regtype', casttarget => 'oid', castfunc => '0',
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 7fb574f9dcc..a64378b0027 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -6666,6 +6666,15 @@
{ oid => '3495', descr => 'convert classname to regclass',
proname => 'to_regclass', provolatile => 's', prorettype => 'regclass',
proargtypes => 'text', prosrc => 'to_regclass' },
+{ oid => '4193', descr => 'I/O',
+ proname => 'regcollationin', provolatile => 's', prorettype => 'regcollation',
+ proargtypes => 'cstring', prosrc => 'regcollationin' },
+{ oid => '4194', descr => 'I/O',
+ proname => 'regcollationout', provolatile => 's', prorettype => 'cstring',
+ proargtypes => 'regcollation', prosrc => 'regcollationout' },
+{ oid => '4195', descr => 'convert classname to regcollation',
+ proname => 'to_regcollation', provolatile => 's', prorettype => 'regcollation',
+ proargtypes => 'text', prosrc => 'to_regcollation' },
{ oid => '2220', descr => 'I/O',
proname => 'regtypein', provolatile => 's', prorettype => 'regtype',
proargtypes => 'cstring', prosrc => 'regtypein' },
@@ -7446,6 +7455,12 @@
{ oid => '2453', descr => 'I/O',
proname => 'regclasssend', prorettype => 'bytea', proargtypes => 'regclass',
prosrc => 'regclasssend' },
+{ oid => '4196', descr => 'I/O',
+ proname => 'regcollationrecv', prorettype => 'regcollation',
+ proargtypes => 'internal', prosrc => 'regcollationrecv' },
+{ oid => '4197', descr => 'I/O',
+ proname => 'regcollationsend', prorettype => 'bytea', proargtypes => 'regcollation',
+ prosrc => 'regcollationsend' },
{ oid => '2454', descr => 'I/O',
proname => 'regtyperecv', prorettype => 'regtype', proargtypes => 'internal',
prosrc => 'regtyperecv' },
diff --git a/src/include/catalog/pg_type.dat b/src/include/catalog/pg_type.dat
index b00597d6ffc..bb21cf166db 100644
--- a/src/include/catalog/pg_type.dat
+++ b/src/include/catalog/pg_type.dat
@@ -379,6 +379,10 @@
typname => 'regclass', typlen => '4', typbyval => 't', typcategory => 'N',
typinput => 'regclassin', typoutput => 'regclassout',
typreceive => 'regclassrecv', typsend => 'regclasssend', typalign => 'i' },
+{ oid => '4191', array_type_oid => '4192', descr => 'registered collation',
+ typname => 'regcollation', typlen => '4', typbyval => 't', typcategory => 'N',
+ typinput => 'regcollationin', typoutput => 'regcollationout',
+ typreceive => 'regcollationrecv', typsend => 'regcollationsend', typalign => 'i' },
{ oid => '2206', array_type_oid => '2211', descr => 'registered type',
typname => 'regtype', typlen => '4', typbyval => 't', typcategory => 'N',
typinput => 'regtypein', typoutput => 'regtypeout',
diff --git a/src/test/regress/expected/regproc.out b/src/test/regress/expected/regproc.out
index ee4fcda8666..e45ff5483fb 100644
--- a/src/test/regress/expected/regproc.out
+++ b/src/test/regress/expected/regproc.out
@@ -40,6 +40,12 @@ SELECT regtype('int4');
integer
(1 row)
+SELECT regcollation('"POSIX"');
+ regcollation
+--------------
+ "POSIX"
+(1 row)
+
SELECT to_regoper('||/');
to_regoper
------------
@@ -76,6 +82,12 @@ SELECT to_regtype('int4');
integer
(1 row)
+SELECT to_regcollation('"POSIX"');
+ to_regcollation
+-----------------
+ "POSIX"
+(1 row)
+
-- with schemaname
SELECT regoper('pg_catalog.||/');
regoper
@@ -113,6 +125,12 @@ SELECT regtype('pg_catalog.int4');
integer
(1 row)
+SELECT regcollation('pg_catalog."POSIX"');
+ regcollation
+--------------
+ "POSIX"
+(1 row)
+
SELECT to_regoper('pg_catalog.||/');
to_regoper
------------
@@ -143,6 +161,12 @@ SELECT to_regtype('pg_catalog.int4');
integer
(1 row)
+SELECT to_regcollation('pg_catalog."POSIX"');
+ to_regcollation
+-----------------
+ "POSIX"
+(1 row)
+
-- schemaname not applicable
SELECT regrole('regress_regrole_test');
regrole
@@ -244,6 +268,10 @@ SELECT regtype('ng_catalog.int4');
ERROR: schema "ng_catalog" does not exist
LINE 1: SELECT regtype('ng_catalog.int4');
^
+SELECT regcollation('ng_catalog."POSIX"');
+ERROR: schema "ng_catalog" does not exist
+LINE 1: SELECT regcollation('ng_catalog."POSIX"');
+ ^
-- schemaname not applicable
SELECT regrole('regress_regrole_test');
ERROR: role "regress_regrole_test" does not exist
@@ -315,6 +343,12 @@ SELECT to_regtype('int3');
(1 row)
+SELECT to_regcollation('notacollation');
+ to_regcollation
+-----------------
+
+(1 row)
+
-- with schemaname
SELECT to_regoper('ng_catalog.||/');
to_regoper
@@ -352,6 +386,12 @@ SELECT to_regtype('ng_catalog.int4');
(1 row)
+SELECT to_regcollation('ng_catalog."POSIX"');
+ to_regcollation
+-----------------
+
+(1 row)
+
-- schemaname not applicable
SELECT to_regrole('regress_regrole_test');
to_regrole
diff --git a/src/test/regress/sql/regproc.sql b/src/test/regress/sql/regproc.sql
index a60bc289010..faab0c15ce8 100644
--- a/src/test/regress/sql/regproc.sql
+++ b/src/test/regress/sql/regproc.sql
@@ -14,6 +14,7 @@ SELECT regproc('now');
SELECT regprocedure('abs(numeric)');
SELECT regclass('pg_class');
SELECT regtype('int4');
+SELECT regcollation('"POSIX"');
SELECT to_regoper('||/');
SELECT to_regoperator('+(int4,int4)');
@@ -21,6 +22,7 @@ SELECT to_regproc('now');
SELECT to_regprocedure('abs(numeric)');
SELECT to_regclass('pg_class');
SELECT to_regtype('int4');
+SELECT to_regcollation('"POSIX"');
-- with schemaname
@@ -30,12 +32,14 @@ SELECT regproc('pg_catalog.now');
SELECT regprocedure('pg_catalog.abs(numeric)');
SELECT regclass('pg_catalog.pg_class');
SELECT regtype('pg_catalog.int4');
+SELECT regcollation('pg_catalog."POSIX"');
SELECT to_regoper('pg_catalog.||/');
SELECT to_regproc('pg_catalog.now');
SELECT to_regprocedure('pg_catalog.abs(numeric)');
SELECT to_regclass('pg_catalog.pg_class');
SELECT to_regtype('pg_catalog.int4');
+SELECT to_regcollation('pg_catalog."POSIX"');
-- schemaname not applicable
@@ -70,6 +74,7 @@ SELECT regproc('ng_catalog.now');
SELECT regprocedure('ng_catalog.abs(numeric)');
SELECT regclass('ng_catalog.pg_class');
SELECT regtype('ng_catalog.int4');
+SELECT regcollation('ng_catalog."POSIX"');
-- schemaname not applicable
@@ -92,6 +97,7 @@ SELECT to_regproc('know');
SELECT to_regprocedure('absinthe(numeric)');
SELECT to_regclass('pg_classes');
SELECT to_regtype('int3');
+SELECT to_regcollation('notacollation');
-- with schemaname
@@ -101,6 +107,7 @@ SELECT to_regproc('ng_catalog.now');
SELECT to_regprocedure('ng_catalog.abs(numeric)');
SELECT to_regclass('ng_catalog.pg_class');
SELECT to_regtype('ng_catalog.int4');
+SELECT to_regcollation('ng_catalog."POSIX"');
-- schemaname not applicable