1
0
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:
Peter Eisentraut
2011-02-08 23:04:18 +02:00
parent 1703f0e8da
commit 414c5a2ea6
156 changed files with 4519 additions and 582 deletions

View File

@ -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 ---------- */

View File

@ -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),

View File

@ -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,