Implement type regcollation
authorPeter Eisentraut <peter@eisentraut.org>
Wed, 18 Mar 2020 20:20:01 +0000 (21:20 +0100)
committerPeter Eisentraut <peter@eisentraut.org>
Wed, 18 Mar 2020 20:21:00 +0000 (21:21 +0100)
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

doc/src/sgml/datatype.sgml
doc/src/sgml/func.sgml
doc/src/sgml/ref/pgupgrade.sgml
src/backend/utils/adt/regproc.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/sql/regproc.sql

index 157fe4e72759fae7d5774bfe4909302fa00db5e3..b9c5214ab8b846e37c2121b1ee32fc4ae4f5eb0a 100644 (file)
@@ -4476,6 +4476,10 @@ INSERT INTO mytable VALUES(-1);  -- fails
     <primary>regclass</primary>
    </indexterm>
 
+   <indexterm zone="datatype-oid">
+    <primary>regcollation</primary>
+   </indexterm>
+
    <indexterm zone="datatype-oid">
     <primary>regconfig</primary>
    </indexterm>
@@ -4602,6 +4606,12 @@ SELECT * FROM pg_attribute
         <entry><literal>pg_type</literal></entry>
        </row>
 
+       <row>
+        <entry><type>regcollation</type></entry>
+        <entry><structname>pg_collation</structname></entry>
+        <entry>collation name</entry>
+        <entry><literal>"POSIX"</literal></entry>
+       </row>
 
        <row>
         <entry><type>regconfig</type></entry>
index 2a8683a734746d979a30f6c2bb6dffc7bd38b13c..464a48ed6afcda5bbb6ee52f19ea5df80a581a55 100644 (file)
@@ -18177,6 +18177,10 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
     <primary>to_regclass</primary>
    </indexterm>
 
+   <indexterm>
+    <primary>to_regcollation</primary>
+   </indexterm>
+
    <indexterm>
     <primary>to_regnamespace</primary>
    </indexterm>
@@ -18389,6 +18393,11 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
        <entry><type>regclass</type></entry>
        <entry>get the OID of the named relation</entry>
       </row>
+      <row>
+       <entry><literal><function>to_regcollation(<parameter>coll_name</parameter>)</function></literal></entry>
+       <entry><type>regcollation</type></entry>
+       <entry>get the OID of the named collation</entry>
+      </row>
       <row>
        <entry><literal><function>to_regnamespace(<parameter>schema_name</parameter>)</function></literal></entry>
        <entry><type>regnamespace</type></entry>
@@ -18720,11 +18729,11 @@ SELECT collation for ('foo' COLLATE "de_DE");
   </para>
 
   <para>
-   The functions <function>to_regclass</function>,
+   The functions <function>to_regclass</function>, <function>to_regcollation</function>,
    <function>to_regnamespace</function>, <function>to_regoper</function>,
    <function>to_regoperator</function>, <function>to_regrole</function>,
    <function>to_regproc</function>, <function>to_regprocedure</function>, and
-   <function>to_regtype</function>, functions translate relation, schema,
+   <function>to_regtype</function>, functions translate relation, collation, schema,
    operator, role, function, and type names (given as <type>text</type>) to
    objects of the corresponding <type>reg*</type> type (see <xref
    linkend="datatype-oid"/> about the types).  These functions differ from a
index 9e4b2d69a4da8d2eb49e3960cf5965046e108b00..49de1d57ab23c6589feac4c39f574edb6e8926ff 100644 (file)
@@ -774,6 +774,7 @@ psql --username=postgres --file=script.sql postgres
    <application>pg_upgrade</application> does not support upgrading of databases
    containing table columns using these <type>reg*</type> OID-referencing system data types:
    <simplelist>
+    <member><type>regcollation</type></member>
     <member><type>regconfig</type></member>
     <member><type>regdictionary</type></member>
     <member><type>regnamespace</type></member>
index f0fa52bc27eb8406646fc22df282a8293ae9bfb5..da8cc0cf6b2ec4ffca4bb886f36af7a55aaa07fc 100644 (file)
@@ -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"
@@ -1043,6 +1044,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
  *
index 5f9a102a7476cbe3b12f8916b5988668b3be55a0..00aef855dc0761baf9454a103dc7d2747c367c27 100644 (file)
@@ -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', "
index 6ad90bac3ddccdb039cf3f53d8e6ae8a0b2df5bb..3fee9342cc12d459622772484db3ac8f96537271 100644 (file)
@@ -53,6 +53,6 @@
  */
 
 /*                         yyyymmddN */
-#define CATALOG_VERSION_NO 202003051
+#define CATALOG_VERSION_NO 202003181
 
 #endif
index 6ef8b8a4e7fc1331ed5888a49e832e7a7fad5db9..01c5328dddb3b649f719a7b7f440e4252de27ce1 100644 (file)
   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',
index 7fb574f9dcc855eb5c2823c62d5cf368f98bf928..a64378b0027c3454c684aab4b0eb85340fb34c18 100644 (file)
 { 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' },
 { 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' },
index b00597d6ffc5aa2e471dd4bd952812aeb3db9600..bb21cf166db286d01e0e33872c65fe4c9de4d792 100644 (file)
   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',
index ee4fcda86662e8383e3b4816825a6f950f71a68d..e45ff5483fb1fc1e68cd13f679aca7dfbf5868f6 100644 (file)
@@ -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 
index a60bc28901092dec91c74d2e61f1f48f0b2f421f..faab0c15ce8f481f48bb92606c4833264046eb76 100644 (file)
@@ -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