]> granicus.if.org Git - postgresql/commitdiff
Add COLLATION FOR expression
authorPeter Eisentraut <peter_e@gmx.net>
Fri, 2 Mar 2012 19:12:16 +0000 (21:12 +0200)
committerPeter Eisentraut <peter_e@gmx.net>
Fri, 2 Mar 2012 19:12:16 +0000 (21:12 +0200)
reviewed by Jaime Casanova

doc/src/sgml/func.sgml
src/backend/parser/gram.y
src/backend/utils/adt/misc.c
src/include/catalog/catversion.h
src/include/catalog/pg_proc.h
src/include/parser/kwlist.h
src/include/utils/builtins.h
src/test/regress/expected/collate.out
src/test/regress/sql/collate.sql

index 8f6e2d04bdbf543d58e94352b19b930daa9651d8..5c1cff3618d529ead6138c64a54c45f288718225 100644 (file)
@@ -13698,6 +13698,10 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
     <primary>pg_typeof</primary>
    </indexterm>
 
+   <indexterm>
+    <primary>collation for</primary>
+   </indexterm>
+
   <para>
    <xref linkend="functions-info-catalog-table"> lists functions that
    extract information from the system catalogs.
@@ -13859,6 +13863,11 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
        <entry><type>regtype</type></entry>
        <entry>get the data type of any value</entry>
       </row>
+      <row>
+       <entry><literal><function>collation for (<parameter>any</parameter>)</function></literal></entry>
+       <entry><type>text</type></entry>
+       <entry>get the collation of the argument</entry>
+      </row>
      </tbody>
     </tgroup>
    </table>
@@ -13983,6 +13992,27 @@ SELECT typlen FROM pg_type WHERE oid = pg_typeof(33);
       4
 (1 row)
 </programlisting>
+  </para>
+
+  <para>
+   The expression <literal>collation for</literal> returns the collation of the
+   value that is passed to it.  Example:
+<programlisting>
+SELECT collation for (description) FROM pg_description LIMIT 1;
+ pg_collation_for 
+------------------
+ "default"
+(1 row)
+
+SELECT collation for ('foo' COLLATE "de_DE");
+ pg_collation_for 
+------------------
+ "de_DE"
+(1 row)
+</programlisting>
+  The value might be quoted and schema-qualified.  If no collation is derived
+  for the argument expression, then a null value is returned.  If the argument
+  is not of a collatable data type, then an error is raised.
   </para>
 
    <indexterm>
index d1ce2ab0422ccc0db1befca7481519d009f2b4a0..9aea2cd80b5b05429cf72bb43e5e2613a9e1604b 100644 (file)
@@ -10701,6 +10701,19 @@ func_expr:     func_name '(' ')' over_clause
                                        n->location = @1;
                                        $$ = (Node *)n;
                                }
+                       | COLLATION FOR '(' a_expr ')'
+                               {
+                                       FuncCall *n = makeNode(FuncCall);
+                                       n->funcname = SystemFuncName("pg_collation_for");
+                                       n->args = list_make1($4);
+                                       n->agg_order = NIL;
+                                       n->agg_star = FALSE;
+                                       n->agg_distinct = FALSE;
+                                       n->func_variadic = FALSE;
+                                       n->over = NULL;
+                                       n->location = @1;
+                                       $$ = (Node *)n;
+                               }
                        | CURRENT_DATE
                                {
                                        /*
@@ -12152,7 +12165,6 @@ unreserved_keyword:
                        | CLASS
                        | CLOSE
                        | CLUSTER
-                       | COLLATION
                        | COMMENT
                        | COMMENTS
                        | COMMIT
@@ -12491,6 +12503,7 @@ reserved_keyword:
                        | CAST
                        | CHECK
                        | COLLATE
+                       | COLLATION
                        | COLUMN
                        | CONSTRAINT
                        | CREATE
index 3de6a5c992345041605b239dc09f3013e6168076..6a1b47714722ca4a4814056fd007e27721bf80f1 100644 (file)
@@ -32,6 +32,7 @@
 #include "storage/pmsignal.h"
 #include "storage/proc.h"
 #include "storage/procarray.h"
+#include "utils/lsyscache.h"
 #include "tcop/tcopprot.h"
 #include "utils/builtins.h"
 #include "utils/timestamp.h"
@@ -492,3 +493,29 @@ pg_typeof(PG_FUNCTION_ARGS)
 {
        PG_RETURN_OID(get_fn_expr_argtype(fcinfo->flinfo, 0));
 }
+
+
+/*
+ * Implementation of the COLLATE FOR expression; returns the collation
+ * of the argument.
+ */
+Datum
+pg_collation_for(PG_FUNCTION_ARGS)
+{
+       Oid typeid;
+       Oid collid;
+
+       typeid = get_fn_expr_argtype(fcinfo->flinfo, 0);
+       if (!typeid)
+               PG_RETURN_NULL();
+       if (!type_is_collatable(typeid) && typeid != UNKNOWNOID)
+               ereport(ERROR,
+                               (errcode(ERRCODE_DATATYPE_MISMATCH),
+                                errmsg("collations are not supported by type %s",
+                                               format_type_be(typeid))));
+
+       collid = PG_GET_COLLATION();
+       if (!collid)
+               PG_RETURN_NULL();
+       PG_RETURN_TEXT_P(cstring_to_text(generate_collation_name(collid)));
+}
index e5fbbfc8fda6a730a76d733356001db4504d5e78..03353471559e60bcaae634891860232897a131af 100644 (file)
@@ -53,6 +53,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     201203011
+#define CATALOG_VERSION_NO     201203021
 
 #endif
index 8700d0d958a26161d626fae1ae2e58f0c3154250..b476d4757906312f4b9f2213033457558c918687 100644 (file)
@@ -1953,6 +1953,8 @@ DESCR("convert generic options array to name/value table");
 
 DATA(insert OID = 1619 (  pg_typeof                            PGNSP PGUID 12 1 0 0 0 f f f f f f s 1 0 2206 "2276" _null_ _null_ _null_ _null_  pg_typeof _null_ _null_ _null_ ));
 DESCR("type of the argument");
+DATA(insert OID = 3162 (  pg_collation_for             PGNSP PGUID 12 1 0 0 0 f f f f f f s 1 0   25 "2276" _null_ _null_ _null_ _null_  pg_collation_for _null_ _null_ _null_ ));
+DESCR("collation of the argument; implementation of the COLLATION FOR expression");
 
 /* Deferrable unique constraint trigger */
 DATA(insert OID = 1250 (  unique_key_recheck   PGNSP PGUID 12 1 0 0 0 f f f f t f v 0 0 2279 "" _null_ _null_ _null_ _null_ unique_key_recheck _null_ _null_ _null_ ));
index bf71ee541485a44a375a0b389f468941f0b7dcf0..9f6f6d354f3c0124b291fccb6f7702df2a9a7b7d 100644 (file)
@@ -79,7 +79,7 @@ PG_KEYWORD("close", CLOSE, UNRESERVED_KEYWORD)
 PG_KEYWORD("cluster", CLUSTER, UNRESERVED_KEYWORD)
 PG_KEYWORD("coalesce", COALESCE, COL_NAME_KEYWORD)
 PG_KEYWORD("collate", COLLATE, RESERVED_KEYWORD)
-PG_KEYWORD("collation", COLLATION, UNRESERVED_KEYWORD)
+PG_KEYWORD("collation", COLLATION, RESERVED_KEYWORD)
 PG_KEYWORD("column", COLUMN, RESERVED_KEYWORD)
 PG_KEYWORD("comment", COMMENT, UNRESERVED_KEYWORD)
 PG_KEYWORD("comments", COMMENTS, UNRESERVED_KEYWORD)
index fe253bcc7cdf8d08f4fdcf365480dac939ffa207..9fda7ad28ead228fa24a77d39665fc0a6f49426a 100644 (file)
@@ -480,6 +480,7 @@ extern Datum pg_rotate_logfile(PG_FUNCTION_ARGS);
 extern Datum pg_sleep(PG_FUNCTION_ARGS);
 extern Datum pg_get_keywords(PG_FUNCTION_ARGS);
 extern Datum pg_typeof(PG_FUNCTION_ARGS);
+extern Datum pg_collation_for(PG_FUNCTION_ARGS);
 
 /* oid.c */
 extern Datum oidin(PG_FUNCTION_ARGS);
index a15e6911b0af98c92854b6ecdcc6437adf89f824..81ac6de7b3154c4b7593b8ccde6477aa49fc3a03 100644 (file)
@@ -577,6 +577,26 @@ RESET enable_nestloop;
 -- 9.1 bug with useless COLLATE in an expression subject to length coercion
 CREATE TEMP TABLE vctable (f1 varchar(25));
 INSERT INTO vctable VALUES ('foo' COLLATE "C");
+SELECT collation for ('foo'); -- unknown type - null
+ pg_collation_for 
+------------------
+(1 row)
+
+SELECT collation for ('foo'::text);
+ pg_collation_for 
+------------------
+ "default"
+(1 row)
+
+SELECT collation for ((SELECT a FROM collate_test1 LIMIT 1)); -- non-collatable type - error
+ERROR:  collations are not supported by type integer
+SELECT collation for ((SELECT b FROM collate_test1 LIMIT 1));
+ pg_collation_for 
+------------------
+ "C"
+(1 row)
+
 --
 -- Clean up.  Many of these table names will be re-used if the user is
 -- trying to run any platform-specific collation tests later, so we
index f72f3edb9d231ff42267da3f44e8421abcccfbcd..3c960e7ed93209b0c2b9a63472e3cb039c453fa3 100644 (file)
@@ -219,6 +219,13 @@ RESET enable_nestloop;
 CREATE TEMP TABLE vctable (f1 varchar(25));
 INSERT INTO vctable VALUES ('foo' COLLATE "C");
 
+
+SELECT collation for ('foo'); -- unknown type - null
+SELECT collation for ('foo'::text);
+SELECT collation for ((SELECT a FROM collate_test1 LIMIT 1)); -- non-collatable type - error
+SELECT collation for ((SELECT b FROM collate_test1 LIMIT 1));
+
+
 --
 -- Clean up.  Many of these table names will be re-used if the user is
 -- trying to run any platform-specific collation tests later, so we