Commit 6688d287 authored by Peter Eisentraut's avatar Peter Eisentraut

Add COLLATION FOR expression

reviewed by Jaime Casanova
parent d41f510c
...@@ -13698,6 +13698,10 @@ SELECT pg_type_is_visible('myschema.widget'::regtype); ...@@ -13698,6 +13698,10 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
<primary>pg_typeof</primary> <primary>pg_typeof</primary>
</indexterm> </indexterm>
<indexterm>
<primary>collation for</primary>
</indexterm>
<para> <para>
<xref linkend="functions-info-catalog-table"> lists functions that <xref linkend="functions-info-catalog-table"> lists functions that
extract information from the system catalogs. extract information from the system catalogs.
...@@ -13859,6 +13863,11 @@ SELECT pg_type_is_visible('myschema.widget'::regtype); ...@@ -13859,6 +13863,11 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
<entry><type>regtype</type></entry> <entry><type>regtype</type></entry>
<entry>get the data type of any value</entry> <entry>get the data type of any value</entry>
</row> </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> </tbody>
</tgroup> </tgroup>
</table> </table>
...@@ -13983,6 +13992,27 @@ SELECT typlen FROM pg_type WHERE oid = pg_typeof(33); ...@@ -13983,6 +13992,27 @@ SELECT typlen FROM pg_type WHERE oid = pg_typeof(33);
4 4
(1 row) (1 row)
</programlisting> </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> </para>
<indexterm> <indexterm>
......
...@@ -10701,6 +10701,19 @@ func_expr: func_name '(' ')' over_clause ...@@ -10701,6 +10701,19 @@ func_expr: func_name '(' ')' over_clause
n->location = @1; n->location = @1;
$$ = (Node *)n; $$ = (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 | CURRENT_DATE
{ {
/* /*
...@@ -12152,7 +12165,6 @@ unreserved_keyword: ...@@ -12152,7 +12165,6 @@ unreserved_keyword:
| CLASS | CLASS
| CLOSE | CLOSE
| CLUSTER | CLUSTER
| COLLATION
| COMMENT | COMMENT
| COMMENTS | COMMENTS
| COMMIT | COMMIT
...@@ -12491,6 +12503,7 @@ reserved_keyword: ...@@ -12491,6 +12503,7 @@ reserved_keyword:
| CAST | CAST
| CHECK | CHECK
| COLLATE | COLLATE
| COLLATION
| COLUMN | COLUMN
| CONSTRAINT | CONSTRAINT
| CREATE | CREATE
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include "storage/pmsignal.h" #include "storage/pmsignal.h"
#include "storage/proc.h" #include "storage/proc.h"
#include "storage/procarray.h" #include "storage/procarray.h"
#include "utils/lsyscache.h"
#include "tcop/tcopprot.h" #include "tcop/tcopprot.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/timestamp.h" #include "utils/timestamp.h"
...@@ -492,3 +493,29 @@ pg_typeof(PG_FUNCTION_ARGS) ...@@ -492,3 +493,29 @@ pg_typeof(PG_FUNCTION_ARGS)
{ {
PG_RETURN_OID(get_fn_expr_argtype(fcinfo->flinfo, 0)); 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)));
}
...@@ -53,6 +53,6 @@ ...@@ -53,6 +53,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 201203011 #define CATALOG_VERSION_NO 201203021
#endif #endif
...@@ -1953,6 +1953,8 @@ DESCR("convert generic options array to name/value table"); ...@@ -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_ )); 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"); 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 */ /* 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_ )); 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_ ));
......
...@@ -79,7 +79,7 @@ PG_KEYWORD("close", CLOSE, UNRESERVED_KEYWORD) ...@@ -79,7 +79,7 @@ PG_KEYWORD("close", CLOSE, UNRESERVED_KEYWORD)
PG_KEYWORD("cluster", CLUSTER, UNRESERVED_KEYWORD) PG_KEYWORD("cluster", CLUSTER, UNRESERVED_KEYWORD)
PG_KEYWORD("coalesce", COALESCE, COL_NAME_KEYWORD) PG_KEYWORD("coalesce", COALESCE, COL_NAME_KEYWORD)
PG_KEYWORD("collate", COLLATE, RESERVED_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("column", COLUMN, RESERVED_KEYWORD)
PG_KEYWORD("comment", COMMENT, UNRESERVED_KEYWORD) PG_KEYWORD("comment", COMMENT, UNRESERVED_KEYWORD)
PG_KEYWORD("comments", COMMENTS, UNRESERVED_KEYWORD) PG_KEYWORD("comments", COMMENTS, UNRESERVED_KEYWORD)
......
...@@ -480,6 +480,7 @@ extern Datum pg_rotate_logfile(PG_FUNCTION_ARGS); ...@@ -480,6 +480,7 @@ extern Datum pg_rotate_logfile(PG_FUNCTION_ARGS);
extern Datum pg_sleep(PG_FUNCTION_ARGS); extern Datum pg_sleep(PG_FUNCTION_ARGS);
extern Datum pg_get_keywords(PG_FUNCTION_ARGS); extern Datum pg_get_keywords(PG_FUNCTION_ARGS);
extern Datum pg_typeof(PG_FUNCTION_ARGS); extern Datum pg_typeof(PG_FUNCTION_ARGS);
extern Datum pg_collation_for(PG_FUNCTION_ARGS);
/* oid.c */ /* oid.c */
extern Datum oidin(PG_FUNCTION_ARGS); extern Datum oidin(PG_FUNCTION_ARGS);
......
...@@ -577,6 +577,26 @@ RESET enable_nestloop; ...@@ -577,6 +577,26 @@ RESET enable_nestloop;
-- 9.1 bug with useless COLLATE in an expression subject to length coercion -- 9.1 bug with useless COLLATE in an expression subject to length coercion
CREATE TEMP TABLE vctable (f1 varchar(25)); CREATE TEMP TABLE vctable (f1 varchar(25));
INSERT INTO vctable VALUES ('foo' COLLATE "C"); 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 -- 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 -- trying to run any platform-specific collation tests later, so we
......
...@@ -219,6 +219,13 @@ RESET enable_nestloop; ...@@ -219,6 +219,13 @@ RESET enable_nestloop;
CREATE TEMP TABLE vctable (f1 varchar(25)); CREATE TEMP TABLE vctable (f1 varchar(25));
INSERT INTO vctable VALUES ('foo' COLLATE "C"); 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 -- 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 -- trying to run any platform-specific collation tests later, so we
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment