mirror of
https://github.com/postgres/postgres.git
synced 2025-08-06 18:42:54 +03:00
Per-column collation support
This adds collation support for columns and domains, a COLLATE clause to override it per expression, and B-tree index support. Peter Eisentraut reviewed by Pavel Stehule, Itagaki Takahiro, Robert Haas, Noah Misch
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
|
||||
#include "fmgr.h"
|
||||
#include "access/skey.h"
|
||||
#include "catalog/pg_collation.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/bytea.h"
|
||||
#include "utils/cash.h"
|
||||
@@ -120,8 +121,9 @@ gin_compare_prefix_##type(PG_FUNCTION_ARGS) \
|
||||
int32 res, \
|
||||
cmp; \
|
||||
\
|
||||
cmp = DatumGetInt32(DirectFunctionCall2( \
|
||||
cmp = DatumGetInt32(DirectFunctionCall2WithCollation( \
|
||||
TypeInfo_##type.typecmp, \
|
||||
DEFAULT_COLLATION_OID, \
|
||||
(data->strategy == BTLessStrategyNumber || \
|
||||
data->strategy == BTLessEqualStrategyNumber) \
|
||||
? data->datum : a, \
|
||||
|
@@ -3,6 +3,7 @@
|
||||
*/
|
||||
#include "btree_gist.h"
|
||||
#include "btree_utils_var.h"
|
||||
#include "catalog/pg_collation.h"
|
||||
#include "utils/builtins.h"
|
||||
|
||||
/*
|
||||
@@ -32,37 +33,37 @@ Datum gbt_text_same(PG_FUNCTION_ARGS);
|
||||
static bool
|
||||
gbt_textgt(const void *a, const void *b)
|
||||
{
|
||||
return (DatumGetBool(DirectFunctionCall2(text_gt, PointerGetDatum(a), PointerGetDatum(b))));
|
||||
return (DatumGetBool(DirectFunctionCall2WithCollation(text_gt, DEFAULT_COLLATION_OID, PointerGetDatum(a), PointerGetDatum(b))));
|
||||
}
|
||||
|
||||
static bool
|
||||
gbt_textge(const void *a, const void *b)
|
||||
{
|
||||
return (DatumGetBool(DirectFunctionCall2(text_ge, PointerGetDatum(a), PointerGetDatum(b))));
|
||||
return (DatumGetBool(DirectFunctionCall2WithCollation(text_ge, DEFAULT_COLLATION_OID, PointerGetDatum(a), PointerGetDatum(b))));
|
||||
}
|
||||
|
||||
static bool
|
||||
gbt_texteq(const void *a, const void *b)
|
||||
{
|
||||
return (DatumGetBool(DirectFunctionCall2(texteq, PointerGetDatum(a), PointerGetDatum(b))));
|
||||
return (DatumGetBool(DirectFunctionCall2WithCollation(texteq, DEFAULT_COLLATION_OID, PointerGetDatum(a), PointerGetDatum(b))));
|
||||
}
|
||||
|
||||
static bool
|
||||
gbt_textle(const void *a, const void *b)
|
||||
{
|
||||
return (DatumGetBool(DirectFunctionCall2(text_le, PointerGetDatum(a), PointerGetDatum(b))));
|
||||
return (DatumGetBool(DirectFunctionCall2WithCollation(text_le, DEFAULT_COLLATION_OID, PointerGetDatum(a), PointerGetDatum(b))));
|
||||
}
|
||||
|
||||
static bool
|
||||
gbt_textlt(const void *a, const void *b)
|
||||
{
|
||||
return (DatumGetBool(DirectFunctionCall2(text_lt, PointerGetDatum(a), PointerGetDatum(b))));
|
||||
return (DatumGetBool(DirectFunctionCall2WithCollation(text_lt, DEFAULT_COLLATION_OID, PointerGetDatum(a), PointerGetDatum(b))));
|
||||
}
|
||||
|
||||
static int32
|
||||
gbt_textcmp(const bytea *a, const bytea *b)
|
||||
{
|
||||
return DatumGetInt32(DirectFunctionCall2(bttextcmp, PointerGetDatum(a), PointerGetDatum(b)));
|
||||
return DatumGetInt32(DirectFunctionCall2WithCollation(bttextcmp, DEFAULT_COLLATION_OID, PointerGetDatum(a), PointerGetDatum(b)));
|
||||
}
|
||||
|
||||
static gbtree_vinfo tinfo =
|
||||
|
@@ -8,6 +8,7 @@
|
||||
#include <float.h>
|
||||
|
||||
#include "btree_utils_var.h"
|
||||
#include "catalog/pg_collation.h"
|
||||
#include "utils/pg_locale.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/rel.h"
|
||||
@@ -156,7 +157,7 @@ gbt_bytea_pf_match(const bytea *pf, const bytea *query, const gbtree_vinfo *tinf
|
||||
|
||||
if (tinfo->eml > 1)
|
||||
{
|
||||
out = (varstr_cmp(q, nlen, n, nlen) == 0);
|
||||
out = (varstr_cmp(q, nlen, n, nlen, DEFAULT_COLLATION_OID) == 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@@ -18,7 +18,7 @@ PG_MODULE_MAGIC;
|
||||
* ====================
|
||||
*/
|
||||
|
||||
static int32 citextcmp(text *left, text *right);
|
||||
static int32 citextcmp(text *left, text *right, Oid collid);
|
||||
extern Datum citext_cmp(PG_FUNCTION_ARGS);
|
||||
extern Datum citext_hash(PG_FUNCTION_ARGS);
|
||||
extern Datum citext_eq(PG_FUNCTION_ARGS);
|
||||
@@ -42,17 +42,18 @@ extern Datum citext_larger(PG_FUNCTION_ARGS);
|
||||
* Returns int32 negative, zero, or positive.
|
||||
*/
|
||||
static int32
|
||||
citextcmp(text *left, text *right)
|
||||
citextcmp(text *left, text *right, Oid collid)
|
||||
{
|
||||
char *lcstr,
|
||||
*rcstr;
|
||||
int32 result;
|
||||
|
||||
lcstr = str_tolower(VARDATA_ANY(left), VARSIZE_ANY_EXHDR(left));
|
||||
rcstr = str_tolower(VARDATA_ANY(right), VARSIZE_ANY_EXHDR(right));
|
||||
lcstr = str_tolower(VARDATA_ANY(left), VARSIZE_ANY_EXHDR(left), collid);
|
||||
rcstr = str_tolower(VARDATA_ANY(right), VARSIZE_ANY_EXHDR(right), collid);
|
||||
|
||||
result = varstr_cmp(lcstr, strlen(lcstr),
|
||||
rcstr, strlen(rcstr));
|
||||
rcstr, strlen(rcstr),
|
||||
collid);
|
||||
|
||||
pfree(lcstr);
|
||||
pfree(rcstr);
|
||||
@@ -75,7 +76,7 @@ citext_cmp(PG_FUNCTION_ARGS)
|
||||
text *right = PG_GETARG_TEXT_PP(1);
|
||||
int32 result;
|
||||
|
||||
result = citextcmp(left, right);
|
||||
result = citextcmp(left, right, PG_GET_COLLATION());
|
||||
|
||||
PG_FREE_IF_COPY(left, 0);
|
||||
PG_FREE_IF_COPY(right, 1);
|
||||
@@ -92,7 +93,7 @@ citext_hash(PG_FUNCTION_ARGS)
|
||||
char *str;
|
||||
Datum result;
|
||||
|
||||
str = str_tolower(VARDATA_ANY(txt), VARSIZE_ANY_EXHDR(txt));
|
||||
str = str_tolower(VARDATA_ANY(txt), VARSIZE_ANY_EXHDR(txt), PG_GET_COLLATION());
|
||||
result = hash_any((unsigned char *) str, strlen(str));
|
||||
pfree(str);
|
||||
|
||||
@@ -121,8 +122,8 @@ citext_eq(PG_FUNCTION_ARGS)
|
||||
|
||||
/* We can't compare lengths in advance of downcasing ... */
|
||||
|
||||
lcstr = str_tolower(VARDATA_ANY(left), VARSIZE_ANY_EXHDR(left));
|
||||
rcstr = str_tolower(VARDATA_ANY(right), VARSIZE_ANY_EXHDR(right));
|
||||
lcstr = str_tolower(VARDATA_ANY(left), VARSIZE_ANY_EXHDR(left), PG_GET_COLLATION());
|
||||
rcstr = str_tolower(VARDATA_ANY(right), VARSIZE_ANY_EXHDR(right), PG_GET_COLLATION());
|
||||
|
||||
/*
|
||||
* Since we only care about equality or not-equality, we can avoid all the
|
||||
@@ -151,8 +152,8 @@ citext_ne(PG_FUNCTION_ARGS)
|
||||
|
||||
/* We can't compare lengths in advance of downcasing ... */
|
||||
|
||||
lcstr = str_tolower(VARDATA_ANY(left), VARSIZE_ANY_EXHDR(left));
|
||||
rcstr = str_tolower(VARDATA_ANY(right), VARSIZE_ANY_EXHDR(right));
|
||||
lcstr = str_tolower(VARDATA_ANY(left), VARSIZE_ANY_EXHDR(left), PG_GET_COLLATION());
|
||||
rcstr = str_tolower(VARDATA_ANY(right), VARSIZE_ANY_EXHDR(right), PG_GET_COLLATION());
|
||||
|
||||
/*
|
||||
* Since we only care about equality or not-equality, we can avoid all the
|
||||
@@ -177,7 +178,7 @@ citext_lt(PG_FUNCTION_ARGS)
|
||||
text *right = PG_GETARG_TEXT_PP(1);
|
||||
bool result;
|
||||
|
||||
result = citextcmp(left, right) < 0;
|
||||
result = citextcmp(left, right, PG_GET_COLLATION()) < 0;
|
||||
|
||||
PG_FREE_IF_COPY(left, 0);
|
||||
PG_FREE_IF_COPY(right, 1);
|
||||
@@ -194,7 +195,7 @@ citext_le(PG_FUNCTION_ARGS)
|
||||
text *right = PG_GETARG_TEXT_PP(1);
|
||||
bool result;
|
||||
|
||||
result = citextcmp(left, right) <= 0;
|
||||
result = citextcmp(left, right, PG_GET_COLLATION()) <= 0;
|
||||
|
||||
PG_FREE_IF_COPY(left, 0);
|
||||
PG_FREE_IF_COPY(right, 1);
|
||||
@@ -211,7 +212,7 @@ citext_gt(PG_FUNCTION_ARGS)
|
||||
text *right = PG_GETARG_TEXT_PP(1);
|
||||
bool result;
|
||||
|
||||
result = citextcmp(left, right) > 0;
|
||||
result = citextcmp(left, right, PG_GET_COLLATION()) > 0;
|
||||
|
||||
PG_FREE_IF_COPY(left, 0);
|
||||
PG_FREE_IF_COPY(right, 1);
|
||||
@@ -228,7 +229,7 @@ citext_ge(PG_FUNCTION_ARGS)
|
||||
text *right = PG_GETARG_TEXT_PP(1);
|
||||
bool result;
|
||||
|
||||
result = citextcmp(left, right) >= 0;
|
||||
result = citextcmp(left, right, PG_GET_COLLATION()) >= 0;
|
||||
|
||||
PG_FREE_IF_COPY(left, 0);
|
||||
PG_FREE_IF_COPY(right, 1);
|
||||
@@ -251,7 +252,7 @@ citext_smaller(PG_FUNCTION_ARGS)
|
||||
text *right = PG_GETARG_TEXT_PP(1);
|
||||
text *result;
|
||||
|
||||
result = citextcmp(left, right) < 0 ? left : right;
|
||||
result = citextcmp(left, right, PG_GET_COLLATION()) < 0 ? left : right;
|
||||
PG_RETURN_TEXT_P(result);
|
||||
}
|
||||
|
||||
@@ -264,6 +265,6 @@ citext_larger(PG_FUNCTION_ARGS)
|
||||
text *right = PG_GETARG_TEXT_PP(1);
|
||||
text *result;
|
||||
|
||||
result = citextcmp(left, right) > 0 ? left : right;
|
||||
result = citextcmp(left, right, PG_GET_COLLATION()) > 0 ? left : right;
|
||||
PG_RETURN_TEXT_P(result);
|
||||
}
|
||||
|
@@ -52,7 +52,8 @@ CREATE TYPE citext (
|
||||
STORAGE = extended,
|
||||
-- make it a non-preferred member of string type category
|
||||
CATEGORY = 'S',
|
||||
PREFERRED = false
|
||||
PREFERRED = false,
|
||||
COLLATABLE = true
|
||||
);
|
||||
|
||||
--
|
||||
|
@@ -7,6 +7,7 @@
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#include "catalog/pg_collation.h"
|
||||
#include "utils/array.h"
|
||||
#include "utils/formatting.h"
|
||||
#include "ltree.h"
|
||||
@@ -90,8 +91,8 @@ bool
|
||||
int
|
||||
ltree_strncasecmp(const char *a, const char *b, size_t s)
|
||||
{
|
||||
char *al = str_tolower(a, s);
|
||||
char *bl = str_tolower(b, s);
|
||||
char *al = str_tolower(a, s, DEFAULT_COLLATION_OID);
|
||||
char *bl = str_tolower(b, s, DEFAULT_COLLATION_OID);
|
||||
int res;
|
||||
|
||||
res = strncmp(al, bl, s);
|
||||
|
Reference in New Issue
Block a user