aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/collationcmds.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/commands/collationcmds.c')
-rw-r--r--src/backend/commands/collationcmds.c83
1 files changed, 59 insertions, 24 deletions
diff --git a/src/backend/commands/collationcmds.c b/src/backend/commands/collationcmds.c
index a52cb351ac8..6dafb7223c4 100644
--- a/src/backend/commands/collationcmds.c
+++ b/src/backend/commands/collationcmds.c
@@ -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,