1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-17 06:41:09 +03:00

Create an explicit concept of collations that work for any encoding.

Use collencoding = -1 to represent such a collation in pg_collation.
We need this to make the "default" entry work sanely, and a later
patch will fix the C/POSIX entries to be represented this way instead
of duplicating them across all encodings.  All lookup operations now
search first for an entry that's database-encoding-specific, and then
for the same name with collencoding = -1.

Also some incidental code cleanup in collationcmds.c and pg_collation.c.
This commit is contained in:
Tom Lane
2011-03-11 13:20:11 -05:00
parent ac435a79c8
commit e3c732a85c
9 changed files with 158 additions and 84 deletions

View File

@ -1,7 +1,7 @@
/*-------------------------------------------------------------------------
*
* collationcmds.c
* collation creation command support code
* collation-related commands support code
*
* Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
@ -27,7 +27,6 @@
#include "commands/defrem.h"
#include "mb/pg_wchar.h"
#include "miscadmin.h"
#include "parser/parse_type.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
@ -134,11 +133,11 @@ DefineCollation(List *names, List *parameters)
check_encoding_locale_matches(GetDatabaseEncoding(), collcollate, collctype);
newoid = CollationCreate(collName,
collNamespace,
GetUserId(),
GetDatabaseEncoding(),
collcollate,
collctype);
collNamespace,
GetUserId(),
GetDatabaseEncoding(),
collcollate,
collctype);
/* check that the locales can be loaded */
CommandCounterIncrement();
@ -235,11 +234,22 @@ RenameCollation(List *name, const char *newname)
ObjectIdGetDatum(namespaceOid)))
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_OBJECT),
errmsg("collation \"%s\" for current database encoding \"%s\" already exists in schema \"%s\"",
errmsg("collation \"%s\" for encoding \"%s\" already exists in schema \"%s\"",
newname,
GetDatabaseEncodingName(),
get_namespace_name(namespaceOid))));
/* mustn't match an any-encoding entry, either */
if (SearchSysCacheExists3(COLLNAMEENCNSP,
CStringGetDatum(newname),
Int32GetDatum(-1),
ObjectIdGetDatum(namespaceOid)))
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_OBJECT),
errmsg("collation \"%s\" already exists in schema \"%s\"",
newname,
get_namespace_name(namespaceOid))));
/* must be owner */
if (!pg_collation_ownercheck(collationOid, GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_COLLATION,
@ -256,8 +266,9 @@ RenameCollation(List *name, const char *newname)
simple_heap_update(rel, &tup->t_self, tup);
CatalogUpdateIndexes(rel, tup);
heap_close(rel, NoLock);
heap_freetuple(tup);
heap_close(rel, RowExclusiveLock);
}
/*
@ -275,7 +286,7 @@ AlterCollationOwner(List *name, Oid newOwnerId)
AlterCollationOwner_internal(rel, collationOid, newOwnerId);
heap_close(rel, NoLock);
heap_close(rel, RowExclusiveLock);
}
/*
@ -290,7 +301,7 @@ AlterCollationOwner_oid(Oid collationOid, Oid newOwnerId)
AlterCollationOwner_internal(rel, collationOid, newOwnerId);
heap_close(rel, NoLock);
heap_close(rel, RowExclusiveLock);
}
/*
@ -364,24 +375,14 @@ AlterCollationOwner_internal(Relation rel, Oid collationOid, Oid newOwnerId)
void
AlterCollationNamespace(List *name, const char *newschema)
{
Oid collOid, nspOid;
Relation rel;
rel = heap_open(CollationRelationId, RowExclusiveLock);
Oid collOid,
nspOid;
collOid = get_collation_oid(name, false);
/* get schema OID */
nspOid = LookupCreationNamespace(newschema);
AlterObjectNamespace(rel, COLLOID, -1,
collOid, nspOid,
Anum_pg_collation_collname,
Anum_pg_collation_collnamespace,
Anum_pg_collation_collowner,
ACL_KIND_COLLATION);
heap_close(rel, NoLock);
AlterCollationNamespace_oid(collOid, nspOid);
}
/*
@ -392,9 +393,43 @@ AlterCollationNamespace_oid(Oid collOid, Oid newNspOid)
{
Oid oldNspOid;
Relation rel;
char *collation_name;
rel = heap_open(CollationRelationId, RowExclusiveLock);
/*
* We have to check for name collision ourselves, because
* AlterObjectNamespace doesn't know how to deal with the encoding
* considerations.
*/
collation_name = get_collation_name(collOid);
if (!collation_name)
elog(ERROR, "cache lookup failed for collation %u", collOid);
/* make sure the name doesn't already exist in new schema */
if (SearchSysCacheExists3(COLLNAMEENCNSP,
CStringGetDatum(collation_name),
Int32GetDatum(GetDatabaseEncoding()),
ObjectIdGetDatum(newNspOid)))
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_OBJECT),
errmsg("collation \"%s\" for encoding \"%s\" already exists in schema \"%s\"",
collation_name,
GetDatabaseEncodingName(),
get_namespace_name(newNspOid))));
/* mustn't match an any-encoding entry, either */
if (SearchSysCacheExists3(COLLNAMEENCNSP,
CStringGetDatum(collation_name),
Int32GetDatum(-1),
ObjectIdGetDatum(newNspOid)))
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_OBJECT),
errmsg("collation \"%s\" already exists in schema \"%s\"",
collation_name,
get_namespace_name(newNspOid))));
/* OK, do the work */
oldNspOid = AlterObjectNamespace(rel, COLLOID, -1,
collOid, newNspOid,
Anum_pg_collation_collname,