mirror of
https://github.com/postgres/postgres.git
synced 2025-07-03 20:02:46 +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:
94
src/backend/utils/cache/lsyscache.c
vendored
94
src/backend/utils/cache/lsyscache.c
vendored
@ -20,6 +20,7 @@
|
||||
#include "bootstrap/bootstrap.h"
|
||||
#include "catalog/pg_amop.h"
|
||||
#include "catalog/pg_amproc.h"
|
||||
#include "catalog/pg_collation.h"
|
||||
#include "catalog/pg_constraint.h"
|
||||
#include "catalog/pg_namespace.h"
|
||||
#include "catalog/pg_opclass.h"
|
||||
@ -902,6 +903,33 @@ get_atttypmod(Oid relid, AttrNumber attnum)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* get_attcollation
|
||||
*
|
||||
* Given the relation id and the attribute number,
|
||||
* return the "attcollation" field from the attribute relation.
|
||||
*/
|
||||
Oid
|
||||
get_attcollation(Oid relid, AttrNumber attnum)
|
||||
{
|
||||
HeapTuple tp;
|
||||
|
||||
tp = SearchSysCache2(ATTNUM,
|
||||
ObjectIdGetDatum(relid),
|
||||
Int16GetDatum(attnum));
|
||||
if (HeapTupleIsValid(tp))
|
||||
{
|
||||
Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
|
||||
Oid result;
|
||||
|
||||
result = att_tup->attcollation;
|
||||
ReleaseSysCache(tp);
|
||||
return result;
|
||||
}
|
||||
else
|
||||
return InvalidOid;
|
||||
}
|
||||
|
||||
/*
|
||||
* get_atttypetypmod
|
||||
*
|
||||
@ -931,6 +959,36 @@ get_atttypetypmod(Oid relid, AttrNumber attnum,
|
||||
ReleaseSysCache(tp);
|
||||
}
|
||||
|
||||
/* ---------- COLLATION CACHE ---------- */
|
||||
|
||||
/*
|
||||
* get_collation_name
|
||||
* Returns the name of a given pg_collation entry.
|
||||
*
|
||||
* Returns a palloc'd copy of the string, or NULL if no such constraint.
|
||||
*
|
||||
* NOTE: since collation name is not unique, be wary of code that uses this
|
||||
* for anything except preparing error messages.
|
||||
*/
|
||||
char *
|
||||
get_collation_name(Oid colloid)
|
||||
{
|
||||
HeapTuple tp;
|
||||
|
||||
tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(colloid));
|
||||
if (HeapTupleIsValid(tp))
|
||||
{
|
||||
Form_pg_collation colltup = (Form_pg_collation) GETSTRUCT(tp);
|
||||
char *result;
|
||||
|
||||
result = pstrdup(NameStr(colltup->collname));
|
||||
ReleaseSysCache(tp);
|
||||
return result;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* ---------- CONSTRAINT CACHE ---------- */
|
||||
|
||||
/*
|
||||
@ -2523,6 +2581,42 @@ get_typmodout(Oid typid)
|
||||
}
|
||||
#endif /* NOT_USED */
|
||||
|
||||
/*
|
||||
* get_typcollation
|
||||
*
|
||||
* Given the type OID, return the type's typcollation attribute.
|
||||
*/
|
||||
Oid
|
||||
get_typcollation(Oid typid)
|
||||
{
|
||||
HeapTuple tp;
|
||||
|
||||
tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
|
||||
if (HeapTupleIsValid(tp))
|
||||
{
|
||||
Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
|
||||
Oid result;
|
||||
|
||||
result = typtup->typcollation;
|
||||
ReleaseSysCache(tp);
|
||||
return result;
|
||||
}
|
||||
else
|
||||
return InvalidOid;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* type_is_collatable
|
||||
*
|
||||
* Return whether the type cares about collations
|
||||
*/
|
||||
bool
|
||||
type_is_collatable(Oid typid)
|
||||
{
|
||||
return OidIsValid(get_typcollation(typid));
|
||||
}
|
||||
|
||||
|
||||
/* ---------- STATISTICS CACHE ---------- */
|
||||
|
||||
|
35
src/backend/utils/cache/relcache.c
vendored
35
src/backend/utils/cache/relcache.c
vendored
@ -976,9 +976,11 @@ RelationInitIndexAccessInfo(Relation relation)
|
||||
{
|
||||
HeapTuple tuple;
|
||||
Form_pg_am aform;
|
||||
Datum indcollDatum;
|
||||
Datum indclassDatum;
|
||||
Datum indoptionDatum;
|
||||
bool isnull;
|
||||
oidvector *indcoll;
|
||||
oidvector *indclass;
|
||||
int2vector *indoption;
|
||||
MemoryContext indexcxt;
|
||||
@ -1061,9 +1063,25 @@ RelationInitIndexAccessInfo(Relation relation)
|
||||
relation->rd_supportinfo = NULL;
|
||||
}
|
||||
|
||||
relation->rd_indcollation = (Oid *)
|
||||
MemoryContextAllocZero(indexcxt, natts * sizeof(Oid));
|
||||
|
||||
relation->rd_indoption = (int16 *)
|
||||
MemoryContextAllocZero(indexcxt, natts * sizeof(int16));
|
||||
|
||||
/*
|
||||
* indcollation cannot be referenced directly through the C struct, because it
|
||||
* comes after the variable-width indkey field. Must extract the datum
|
||||
* the hard way...
|
||||
*/
|
||||
indcollDatum = fastgetattr(relation->rd_indextuple,
|
||||
Anum_pg_index_indcollation,
|
||||
GetPgIndexDescriptor(),
|
||||
&isnull);
|
||||
Assert(!isnull);
|
||||
indcoll = (oidvector *) DatumGetPointer(indcollDatum);
|
||||
memcpy(relation->rd_indcollation, indcoll->values, natts * sizeof(Oid));
|
||||
|
||||
/*
|
||||
* indclass cannot be referenced directly through the C struct, because it
|
||||
* comes after the variable-width indkey field. Must extract the datum
|
||||
@ -3988,6 +4006,7 @@ load_relcache_init_file(bool shared)
|
||||
RegProcedure *support;
|
||||
int nsupport;
|
||||
int16 *indoption;
|
||||
Oid *indcollation;
|
||||
|
||||
/* Count nailed indexes to ensure we have 'em all */
|
||||
if (rel->rd_isnailed)
|
||||
@ -4054,6 +4073,16 @@ load_relcache_init_file(bool shared)
|
||||
|
||||
rel->rd_support = support;
|
||||
|
||||
/* next, read the vector of collation OIDs */
|
||||
if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
|
||||
goto read_failed;
|
||||
|
||||
indcollation = (Oid *) MemoryContextAlloc(indexcxt, len);
|
||||
if (fread(indcollation, 1, len, fp) != len)
|
||||
goto read_failed;
|
||||
|
||||
rel->rd_indcollation = indcollation;
|
||||
|
||||
/* finally, read the vector of indoption values */
|
||||
if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
|
||||
goto read_failed;
|
||||
@ -4087,6 +4116,7 @@ load_relcache_init_file(bool shared)
|
||||
Assert(rel->rd_support == NULL);
|
||||
Assert(rel->rd_supportinfo == NULL);
|
||||
Assert(rel->rd_indoption == NULL);
|
||||
Assert(rel->rd_indcollation == NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -4305,6 +4335,11 @@ write_relcache_init_file(bool shared)
|
||||
relform->relnatts * (am->amsupport * sizeof(RegProcedure)),
|
||||
fp);
|
||||
|
||||
/* next, write the vector of collation OIDs */
|
||||
write_item(rel->rd_indcollation,
|
||||
relform->relnatts * sizeof(Oid),
|
||||
fp);
|
||||
|
||||
/* finally, write the vector of indoption values */
|
||||
write_item(rel->rd_indoption,
|
||||
relform->relnatts * sizeof(int16),
|
||||
|
23
src/backend/utils/cache/syscache.c
vendored
23
src/backend/utils/cache/syscache.c
vendored
@ -28,6 +28,7 @@
|
||||
#include "catalog/pg_auth_members.h"
|
||||
#include "catalog/pg_authid.h"
|
||||
#include "catalog/pg_cast.h"
|
||||
#include "catalog/pg_collation.h"
|
||||
#include "catalog/pg_constraint.h"
|
||||
#include "catalog/pg_conversion.h"
|
||||
#include "catalog/pg_database.h"
|
||||
@ -267,6 +268,28 @@ static const struct cachedesc cacheinfo[] = {
|
||||
},
|
||||
64
|
||||
},
|
||||
{CollationRelationId, /* COLLNAMEENCNSP */
|
||||
CollationNameEncNspIndexId,
|
||||
3,
|
||||
{
|
||||
Anum_pg_collation_collname,
|
||||
Anum_pg_collation_collencoding,
|
||||
Anum_pg_collation_collnamespace,
|
||||
0
|
||||
},
|
||||
256
|
||||
},
|
||||
{CollationRelationId, /* COLLOID */
|
||||
CollationOidIndexId,
|
||||
1,
|
||||
{
|
||||
ObjectIdAttributeNumber,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
},
|
||||
256
|
||||
},
|
||||
{ConversionRelationId, /* CONDEFAULT */
|
||||
ConversionDefaultIndexId,
|
||||
4,
|
||||
|
Reference in New Issue
Block a user