Create an explicit concept of collations that work for any encoding.
authorTom Lane <[email protected]>
Fri, 11 Mar 2011 18:20:11 +0000 (13:20 -0500)
committerTom Lane <[email protected]>
Fri, 11 Mar 2011 18:20:11 +0000 (13:20 -0500)
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.

doc/src/sgml/catalogs.sgml
src/backend/catalog/information_schema.sql
src/backend/catalog/namespace.c
src/backend/catalog/pg_collation.c
src/backend/commands/collationcmds.c
src/bin/psql/tab-complete.c
src/include/catalog/catversion.h
src/include/catalog/pg_collation.h
src/test/regress/expected/collate.linux.utf8.out

index 297ad532080d7320853884aff41b701944c98bb0..64d1cda899068167520c771f4abe5e3d04743237 100644 (file)
       <entry><structfield>collencoding</structfield></entry>
       <entry><type>int4</type></entry>
       <entry></entry>
-      <entry>Encoding to which the collation is applicable</entry>
+      <entry>Encoding in which the collation is applicable, or -1 if it
+       works for any encoding</entry>
      </row>
 
      <row>
    <structfield>collencoding</>, <structfield>collnamespace</>) not just
    (<structfield>collname</>, <structfield>collnamespace</>).
    <productname>PostgreSQL</productname> generally ignores all
-   collations not belonging to the current database's encoding; therefore
-   it is sufficient to use a qualified SQL name
+   collations that do not have <structfield>collencoding</> equal to
+   either the current database's encoding or -1, and creation of new
+   entries matching an entry with <structfield>collencoding</> = -1
+   is forbidden.  Therefore it is sufficient to use a qualified SQL name
    (<replaceable>schema</>.<replaceable>name</>) to identify a collation,
    even though this is not unique according to the catalog definition.
-   The current database's encoding is automatically used as an additional
-   lookup key.  The reason for defining the catalog this way is that
+   The reason for defining the catalog this way is that
    <application>initdb</> fills it in at cluster initialization time with
    entries for all locales available on the system, so it must be able to
    hold entries for all encodings that might ever be used in the cluster.
index 1c47d81ba8cac38417fb1b3b853183e1725d5c4c..c623fb7e75cc7ad1788c34f6604bc26bbeafb875 100644 (file)
@@ -448,7 +448,7 @@ CREATE VIEW collations AS
            CAST('NO PAD' AS character_data) AS pad_attribute
     FROM pg_collation c, pg_namespace nc
     WHERE c.collnamespace = nc.oid
-          AND collencoding = (SELECT encoding FROM pg_catalog.pg_database WHERE datname = pg_catalog.current_database());
+          AND collencoding IN (-1, (SELECT encoding FROM pg_database WHERE datname = current_database()));
 
 GRANT SELECT ON collations TO PUBLIC;
 
@@ -467,7 +467,7 @@ CREATE VIEW collation_character_set_applicability AS
            CAST(getdatabaseencoding() AS sql_identifier) AS character_set_name
     FROM pg_collation c, pg_namespace nc
     WHERE c.collnamespace = nc.oid
-          AND collencoding = (SELECT encoding FROM pg_catalog.pg_database WHERE datname = pg_catalog.current_database());
+          AND collencoding IN (-1, (SELECT encoding FROM pg_database WHERE datname = current_database()));
 
 GRANT SELECT ON collation_character_set_applicability TO PUBLIC;
 
@@ -2036,7 +2036,7 @@ CREATE VIEW usage_privileges AS
 
     WHERE u.oid = c.collowner
           AND c.collnamespace = n.oid
-          AND c.collencoding = (SELECT encoding FROM pg_catalog.pg_database WHERE datname = pg_catalog.current_database())
+          AND collencoding IN (-1, (SELECT encoding FROM pg_database WHERE datname = current_database()))
 
     UNION ALL
 
index 8b04b9fd9b381d1b8c924d7c0abb18c01cff6a6c..77c9805aed1c6d70214c01938b957d88377f969d 100644 (file)
@@ -1617,13 +1617,11 @@ OpfamilyIsVisible(Oid opfid)
  * CollationGetCollid
  *     Try to resolve an unqualified collation name.
  *     Returns OID if collation found in search path, else InvalidOid.
- *
- * This is essentially the same as RelnameGetRelid.
  */
 Oid
 CollationGetCollid(const char *collname)
 {
-   Oid         collid;
+   int32       dbencoding = GetDatabaseEncoding();
    ListCell   *l;
 
    recomputeNamespacePath();
@@ -1631,13 +1629,23 @@ CollationGetCollid(const char *collname)
    foreach(l, activeSearchPath)
    {
        Oid         namespaceId = lfirst_oid(l);
+       Oid         collid;
 
        if (namespaceId == myTempNamespace)
            continue;           /* do not look in temp namespace */
 
+       /* Check for database-encoding-specific entry */
+       collid = GetSysCacheOid3(COLLNAMEENCNSP,
+                                PointerGetDatum(collname),
+                                Int32GetDatum(dbencoding),
+                                ObjectIdGetDatum(namespaceId));
+       if (OidIsValid(collid))
+           return collid;
+
+       /* Check for any-encoding entry */
        collid = GetSysCacheOid3(COLLNAMEENCNSP,
                                 PointerGetDatum(collname),
-                                Int32GetDatum(GetDatabaseEncoding()),
+                                Int32GetDatum(-1),
                                 ObjectIdGetDatum(namespaceId));
        if (OidIsValid(collid))
            return collid;
@@ -2901,12 +2909,10 @@ get_collation_oid(List *name, bool missing_ok)
 {
    char       *schemaname;
    char       *collation_name;
+   int32       dbencoding = GetDatabaseEncoding();
    Oid         namespaceId;
-   Oid         colloid = InvalidOid;
+   Oid         colloid;
    ListCell   *l;
-   int         encoding;
-
-   encoding = GetDatabaseEncoding();
 
    /* deconstruct the name list */
    DeconstructQualifiedName(name, &schemaname, &collation_name);
@@ -2915,10 +2921,20 @@ get_collation_oid(List *name, bool missing_ok)
    {
        /* use exact schema given */
        namespaceId = LookupExplicitNamespace(schemaname);
+
+       /* first try for encoding-specific entry, then any-encoding */
        colloid = GetSysCacheOid3(COLLNAMEENCNSP,
                                  PointerGetDatum(collation_name),
-                                 Int32GetDatum(encoding),
+                                 Int32GetDatum(dbencoding),
                                  ObjectIdGetDatum(namespaceId));
+       if (OidIsValid(colloid))
+           return colloid;
+       colloid = GetSysCacheOid3(COLLNAMEENCNSP,
+                                 PointerGetDatum(collation_name),
+                                 Int32GetDatum(-1),
+                                 ObjectIdGetDatum(namespaceId));
+       if (OidIsValid(colloid))
+           return colloid;
    }
    else
    {
@@ -2934,7 +2950,13 @@ get_collation_oid(List *name, bool missing_ok)
 
            colloid = GetSysCacheOid3(COLLNAMEENCNSP,
                                      PointerGetDatum(collation_name),
-                                     Int32GetDatum(encoding),
+                                     Int32GetDatum(dbencoding),
+                                     ObjectIdGetDatum(namespaceId));
+           if (OidIsValid(colloid))
+               return colloid;
+           colloid = GetSysCacheOid3(COLLNAMEENCNSP,
+                                     PointerGetDatum(collation_name),
+                                     Int32GetDatum(-1),
                                      ObjectIdGetDatum(namespaceId));
            if (OidIsValid(colloid))
                return colloid;
@@ -2942,12 +2964,12 @@ get_collation_oid(List *name, bool missing_ok)
    }
 
    /* Not found in path */
-   if (!OidIsValid(colloid) && !missing_ok)
+   if (!missing_ok)
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_OBJECT),
-                errmsg("collation \"%s\" for current database encoding \"%s\" does not exist",
+                errmsg("collation \"%s\" for encoding \"%s\" does not exist",
                        NameListToString(name), GetDatabaseEncodingName())));
-   return colloid;
+   return InvalidOid;
 }
 
 /*
index 54a75a6f62341743a2d4f189003b6a0503ca5e99..708078463ba79dbbd374da6b2a99b249fd75c169 100644 (file)
@@ -14,6 +14,7 @@
  */
 #include "postgres.h"
 
+#include "access/genam.h"
 #include "access/heapam.h"
 #include "access/sysattr.h"
 #include "catalog/dependency.h"
 #include "catalog/pg_collation.h"
 #include "catalog/pg_collation_fn.h"
 #include "catalog/pg_namespace.h"
-#include "catalog/pg_proc.h"
 #include "mb/pg_wchar.h"
-#include "miscadmin.h"
-#include "utils/acl.h"
 #include "utils/builtins.h"
 #include "utils/fmgroids.h"
-#include "utils/rel.h"
 #include "utils/syscache.h"
 #include "utils/tqual.h"
 
+
 /*
  * CollationCreate
  *
@@ -43,12 +41,11 @@ CollationCreate(const char *collname, Oid collnamespace,
                int32 collencoding,
                const char *collcollate, const char *collctype)
 {
-   int         i;
    Relation    rel;
    TupleDesc   tupDesc;
    HeapTuple   tup;
-   bool        nulls[Natts_pg_collation];
    Datum       values[Natts_pg_collation];
+   bool        nulls[Natts_pg_collation];
    NameData    name_name, name_collate, name_ctype;
    Oid         oid;
    ObjectAddress myself,
@@ -60,7 +57,13 @@ CollationCreate(const char *collname, Oid collnamespace,
    AssertArg(collcollate);
    AssertArg(collctype);
 
-   /* make sure there is no existing collation of same name */
+   /*
+    * Make sure there is no existing collation of same name & encoding.
+    *
+    * This would be caught by the unique index anyway; we're just giving
+    * a friendlier error message.  The unique index provides a backstop
+    * against race conditions.
+    */
    if (SearchSysCacheExists3(COLLNAMEENCNSP,
                              PointerGetDatum(collname),
                              Int32GetDatum(collencoding),
@@ -70,18 +73,27 @@ CollationCreate(const char *collname, Oid collnamespace,
                 errmsg("collation \"%s\" for encoding \"%s\" already exists",
                        collname, pg_encoding_to_char(collencoding))));
 
+   /*
+    * Also forbid matching an any-encoding entry.  This test of course is
+    * not backed up by the unique index, but it's not a problem since we
+    * don't support adding any-encoding entries after initdb.
+    */
+   if (SearchSysCacheExists3(COLLNAMEENCNSP,
+                             PointerGetDatum(collname),
+                             Int32GetDatum(-1),
+                             ObjectIdGetDatum(collnamespace)))
+       ereport(ERROR,
+               (errcode(ERRCODE_DUPLICATE_OBJECT),
+                errmsg("collation \"%s\" already exists",
+                       collname)));
+
    /* open pg_collation */
    rel = heap_open(CollationRelationId, RowExclusiveLock);
-   tupDesc = rel->rd_att;
-
-   /* initialize nulls and values */
-   for (i = 0; i < Natts_pg_collation; i++)
-   {
-       nulls[i] = false;
-       values[i] = (Datum) NULL;
-   }
+   tupDesc = RelationGetDescr(rel);
 
    /* form a tuple */
+   memset(nulls, 0, sizeof(nulls));
+
    namestrcpy(&name_name, collname);
    values[Anum_pg_collation_collname - 1] = NameGetDatum(&name_name);
    values[Anum_pg_collation_collnamespace - 1] = ObjectIdGetDatum(collnamespace);
@@ -101,8 +113,9 @@ CollationCreate(const char *collname, Oid collnamespace,
    /* update the index if any */
    CatalogUpdateIndexes(rel, tup);
 
+   /* set up dependencies for the new collation */
    myself.classId = CollationRelationId;
-   myself.objectId = HeapTupleGetOid(tup);
+   myself.objectId = oid;
    myself.objectSubId = 0;
 
    /* create dependency on namespace */
@@ -120,7 +133,7 @@ CollationCreate(const char *collname, Oid collnamespace,
 
    /* Post creation hook for new collation */
    InvokeObjectAccessHook(OAT_POST_CREATE,
-                          CollationRelationId, HeapTupleGetOid(tup), 0);
+                          CollationRelationId, oid, 0);
 
    heap_freetuple(tup);
    heap_close(rel, RowExclusiveLock);
@@ -138,26 +151,28 @@ void
 RemoveCollationById(Oid collationOid)
 {
    Relation    rel;
-   HeapTuple   tuple;
-   HeapScanDesc scan;
    ScanKeyData scanKeyData;
+   SysScanDesc scandesc;
+   HeapTuple   tuple;
+
+   rel = heap_open(CollationRelationId, RowExclusiveLock);
 
    ScanKeyInit(&scanKeyData,
                ObjectIdAttributeNumber,
                BTEqualStrategyNumber, F_OIDEQ,
                ObjectIdGetDatum(collationOid));
 
-   /* open pg_collation */
-   rel = heap_open(CollationRelationId, RowExclusiveLock);
+   scandesc = systable_beginscan(rel, CollationOidIndexId, true,
+                                 SnapshotNow, 1, &scanKeyData);
 
-   scan = heap_beginscan(rel, SnapshotNow,
-                         1, &scanKeyData);
+   tuple = systable_getnext(scandesc);
 
-   /* search for the target tuple */
-   if (HeapTupleIsValid(tuple = heap_getnext(scan, ForwardScanDirection)))
+   if (HeapTupleIsValid(tuple))
        simple_heap_delete(rel, &tuple->t_self);
    else
        elog(ERROR, "could not find tuple for collation %u", collationOid);
-   heap_endscan(scan);
+
+   systable_endscan(scandesc);
+
    heap_close(rel, RowExclusiveLock);
 }
index a52cb351ac83219e4f39276c691f8ad0ab7f919b..6dafb7223c42d4867a0526e72c5b02225bf42f8a 100644 (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,
index 2214471ceab10d864f1e5c4070a919cc63e0f495..7019123725d3d8c30a779c572fd73759e25d8460 100644 (file)
@@ -609,7 +609,7 @@ static const pgsql_thing_t words_after_create[] = {
    {"AGGREGATE", NULL, &Query_for_list_of_aggregates},
    {"CAST", NULL, NULL},       /* Casts have complex structures for names, so
                                 * skip it */
-   {"COLLATION", "SELECT pg_catalog.quote_ident(collname) FROM pg_catalog.pg_collation WHERE collencoding = pg_char_to_encoding(getdatabaseencoding()) AND substring(pg_catalog.quote_ident(collname),1,%d)='%s'"},
+   {"COLLATION", "SELECT pg_catalog.quote_ident(collname) FROM pg_catalog.pg_collation WHERE collencoding IN (-1, pg_catalog.pg_char_to_encoding(pg_catalog.getdatabaseencoding())) AND substring(pg_catalog.quote_ident(collname),1,%d)='%s'"},
 
    /*
     * CREATE CONSTRAINT TRIGGER is not supported here because it is designed
index 22a0b89b44287d155de18bea4c76899b70f51a5c..27ce7955772e92038dd8b4bf0cac80864e297e7f 100644 (file)
@@ -53,6 +53,6 @@
  */
 
 /*                         yyyymmddN */
-#define CATALOG_VERSION_NO 201103101
+#define CATALOG_VERSION_NO 201103111
 
 #endif
index 6decfb13b39370ca725f60a5228af329657a6ae7..e90aa050f54ea79bae72633c451eb973b3c4c862 100644 (file)
@@ -32,9 +32,9 @@
 CATALOG(pg_collation,3456)
 {
    NameData    collname;       /* collation name */
-   Oid         collnamespace;  /* OID of namespace containing this collation */
-   Oid         collowner;
-   int4        collencoding;   /* encoding that this collation applies to */
+   Oid         collnamespace;  /* OID of namespace containing collation */
+   Oid         collowner;      /* owner of collation */
+   int4        collencoding;   /* encoding for this collation; -1 = "all" */
    NameData    collcollate;    /* LC_COLLATE setting */
    NameData    collctype;      /* LC_CTYPE setting */
 } FormData_pg_collation;
@@ -58,8 +58,8 @@ typedef FormData_pg_collation *Form_pg_collation;
 #define Anum_pg_collation_collcollate  5
 #define Anum_pg_collation_collctype        6
 
-DATA(insert OID = 100 ( default PGNSP PGUID 0 "" "" ));
-DESCR("placeholder for default collation");
+DATA(insert OID = 100 ( default PGNSP PGUID -1 "" "" ));
+DESCR("database's default collation");
 #define DEFAULT_COLLATION_OID          100
 
 #endif   /* PG_COLLATION_H */
index 5ad5de2f00b36f8f65b68fadb8f19b12b3add2b9..2102298abaa10e929c5b5da76d1cefcc9bdd5bc7 100644 (file)
@@ -18,14 +18,14 @@ CREATE TABLE collate_test_fail (
     a int,
     b text COLLATE "ja_JP.eucjp"
 );
-ERROR:  collation "ja_JP.eucjp" for current database encoding "UTF8" does not exist
+ERROR:  collation "ja_JP.eucjp" for encoding "UTF8" does not exist
 LINE 3:     b text COLLATE "ja_JP.eucjp"
                    ^
 CREATE TABLE collate_test_fail (
     a int,
     b text COLLATE "foo"
 );
-ERROR:  collation "foo" for current database encoding "UTF8" does not exist
+ERROR:  collation "foo" for encoding "UTF8" does not exist
 LINE 3:     b text COLLATE "foo"
                    ^
 CREATE TABLE collate_test_fail (
@@ -752,7 +752,7 @@ ERROR:  parameter "lc_ctype" must be specified
 CREATE COLLATION testx (locale = 'nonsense'); -- fail
 ERROR:  could not create locale "nonsense": No such file or directory
 CREATE COLLATION test4 FROM nonsense;
-ERROR:  collation "nonsense" for current database encoding "UTF8" does not exist
+ERROR:  collation "nonsense" for encoding "UTF8" does not exist
 CREATE COLLATION test5 FROM test0;
 SELECT collname, collencoding, collcollate, collctype FROM pg_collation WHERE collname LIKE 'test%' ORDER BY 1;
  collname | collencoding | collcollate | collctype  
@@ -764,9 +764,9 @@ SELECT collname, collencoding, collcollate, collctype FROM pg_collation WHERE co
 
 ALTER COLLATION test1 RENAME TO test11;
 ALTER COLLATION test0 RENAME TO test11; -- fail
-ERROR:  collation "test11" for current database encoding "UTF8" already exists in schema "public"
+ERROR:  collation "test11" for encoding "UTF8" already exists in schema "public"
 ALTER COLLATION test1 RENAME TO test22; -- fail
-ERROR:  collation "test1" for current database encoding "UTF8" does not exist
+ERROR:  collation "test1" for encoding "UTF8" does not exist
 ALTER COLLATION test11 OWNER TO regress_test_role;
 ALTER COLLATION test11 OWNER TO nonsense;
 ERROR:  role "nonsense" does not exist
@@ -785,7 +785,7 @@ SELECT collname, nspname, obj_description(pg_collation.oid, 'pg_collation')
 
 DROP COLLATION test0, test_schema.test11, test5;
 DROP COLLATION test0; -- fail
-ERROR:  collation "test0" for current database encoding "UTF8" does not exist
+ERROR:  collation "test0" for encoding "UTF8" does not exist
 DROP COLLATION IF EXISTS test0;
 NOTICE:  collation "test0" does not exist, skipping
 SELECT collname FROM pg_collation WHERE collname LIKE 'test%';