2011-02-12 14:54:13 +01:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
|
|
|
* collationcmds.c
|
2011-03-11 19:20:11 +01:00
|
|
|
* collation-related commands support code
|
2011-02-12 14:54:13 +01:00
|
|
|
*
|
2017-01-03 19:48:53 +01:00
|
|
|
* Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
|
2011-02-12 14:54:13 +01:00
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
|
|
|
* src/backend/commands/collationcmds.c
|
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
#include "postgres.h"
|
|
|
|
|
2017-03-23 20:25:34 +01:00
|
|
|
#include "access/heapam.h"
|
2012-08-30 22:15:44 +02:00
|
|
|
#include "access/htup_details.h"
|
2011-03-04 21:14:37 +01:00
|
|
|
#include "access/xact.h"
|
2011-02-12 14:54:13 +01:00
|
|
|
#include "catalog/dependency.h"
|
|
|
|
#include "catalog/indexing.h"
|
|
|
|
#include "catalog/namespace.h"
|
2017-03-23 20:25:34 +01:00
|
|
|
#include "catalog/objectaccess.h"
|
2011-02-12 14:54:13 +01:00
|
|
|
#include "catalog/pg_collation.h"
|
|
|
|
#include "catalog/pg_collation_fn.h"
|
|
|
|
#include "commands/alter.h"
|
|
|
|
#include "commands/collationcmds.h"
|
2017-03-23 20:25:34 +01:00
|
|
|
#include "commands/comment.h"
|
2011-02-12 14:54:13 +01:00
|
|
|
#include "commands/dbcommands.h"
|
|
|
|
#include "commands/defrem.h"
|
|
|
|
#include "mb/pg_wchar.h"
|
|
|
|
#include "miscadmin.h"
|
|
|
|
#include "utils/builtins.h"
|
|
|
|
#include "utils/lsyscache.h"
|
2011-03-04 21:14:37 +01:00
|
|
|
#include "utils/pg_locale.h"
|
2011-03-26 04:10:07 +01:00
|
|
|
#include "utils/rel.h"
|
2011-02-12 14:54:13 +01:00
|
|
|
#include "utils/syscache.h"
|
|
|
|
|
2017-03-23 20:25:34 +01:00
|
|
|
|
2011-02-12 14:54:13 +01:00
|
|
|
/*
|
|
|
|
* CREATE COLLATION
|
|
|
|
*/
|
Change many routines to return ObjectAddress rather than OID
The changed routines are mostly those that can be directly called by
ProcessUtilitySlow; the intention is to make the affected object
information more precise, in support for future event trigger changes.
Originally it was envisioned that the OID of the affected object would
be enough, and in most cases that is correct, but upon actually
implementing the event trigger changes it turned out that ObjectAddress
is more widely useful.
Additionally, some command execution routines grew an output argument
that's an object address which provides further info about the executed
command. To wit:
* for ALTER DOMAIN / ADD CONSTRAINT, it corresponds to the address of
the new constraint
* for ALTER OBJECT / SET SCHEMA, it corresponds to the address of the
schema that originally contained the object.
* for ALTER EXTENSION {ADD, DROP} OBJECT, it corresponds to the address
of the object added to or dropped from the extension.
There's no user-visible change in this commit, and no functional change
either.
Discussion: 20150218213255.GC6717@tamriel.snowman.net
Reviewed-By: Stephen Frost, Andres Freund
2015-03-03 18:10:50 +01:00
|
|
|
ObjectAddress
|
2017-02-09 04:51:09 +01:00
|
|
|
DefineCollation(ParseState *pstate, List *names, List *parameters, bool if_not_exists)
|
2011-02-12 14:54:13 +01:00
|
|
|
{
|
|
|
|
char *collName;
|
|
|
|
Oid collNamespace;
|
|
|
|
AclResult aclresult;
|
|
|
|
ListCell *pl;
|
2011-04-10 17:42:00 +02:00
|
|
|
DefElem *fromEl = NULL;
|
|
|
|
DefElem *localeEl = NULL;
|
|
|
|
DefElem *lccollateEl = NULL;
|
|
|
|
DefElem *lcctypeEl = NULL;
|
2017-03-23 20:25:34 +01:00
|
|
|
DefElem *providerEl = NULL;
|
|
|
|
DefElem *versionEl = NULL;
|
2011-02-12 14:54:13 +01:00
|
|
|
char *collcollate = NULL;
|
|
|
|
char *collctype = NULL;
|
2017-03-23 20:25:34 +01:00
|
|
|
char *collproviderstr = NULL;
|
|
|
|
int collencoding;
|
|
|
|
char collprovider = 0;
|
|
|
|
char *collversion = NULL;
|
2011-03-04 21:14:37 +01:00
|
|
|
Oid newoid;
|
Change many routines to return ObjectAddress rather than OID
The changed routines are mostly those that can be directly called by
ProcessUtilitySlow; the intention is to make the affected object
information more precise, in support for future event trigger changes.
Originally it was envisioned that the OID of the affected object would
be enough, and in most cases that is correct, but upon actually
implementing the event trigger changes it turned out that ObjectAddress
is more widely useful.
Additionally, some command execution routines grew an output argument
that's an object address which provides further info about the executed
command. To wit:
* for ALTER DOMAIN / ADD CONSTRAINT, it corresponds to the address of
the new constraint
* for ALTER OBJECT / SET SCHEMA, it corresponds to the address of the
schema that originally contained the object.
* for ALTER EXTENSION {ADD, DROP} OBJECT, it corresponds to the address
of the object added to or dropped from the extension.
There's no user-visible change in this commit, and no functional change
either.
Discussion: 20150218213255.GC6717@tamriel.snowman.net
Reviewed-By: Stephen Frost, Andres Freund
2015-03-03 18:10:50 +01:00
|
|
|
ObjectAddress address;
|
2011-02-12 14:54:13 +01:00
|
|
|
|
|
|
|
collNamespace = QualifiedNameGetCreationNamespace(names, &collName);
|
|
|
|
|
|
|
|
aclresult = pg_namespace_aclcheck(collNamespace, GetUserId(), ACL_CREATE);
|
|
|
|
if (aclresult != ACLCHECK_OK)
|
|
|
|
aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
|
|
|
|
get_namespace_name(collNamespace));
|
|
|
|
|
|
|
|
foreach(pl, parameters)
|
|
|
|
{
|
Improve castNode notation by introducing list-extraction-specific variants.
This extends the castNode() notation introduced by commit 5bcab1114 to
provide, in one step, extraction of a list cell's pointer and coercion to
a concrete node type. For example, "lfirst_node(Foo, lc)" is the same
as "castNode(Foo, lfirst(lc))". Almost half of the uses of castNode
that have appeared so far include a list extraction call, so this is
pretty widely useful, and it saves a few more keystrokes compared to the
old way.
As with the previous patch, back-patch the addition of these macros to
pg_list.h, so that the notation will be available when back-patching.
Patch by me, after an idea of Andrew Gierth's.
Discussion: https://postgr.es/m/14197.1491841216@sss.pgh.pa.us
2017-04-10 19:51:29 +02:00
|
|
|
DefElem *defel = lfirst_node(DefElem, pl);
|
2011-02-12 14:54:13 +01:00
|
|
|
DefElem **defelp;
|
|
|
|
|
|
|
|
if (pg_strcasecmp(defel->defname, "from") == 0)
|
|
|
|
defelp = &fromEl;
|
|
|
|
else if (pg_strcasecmp(defel->defname, "locale") == 0)
|
|
|
|
defelp = &localeEl;
|
|
|
|
else if (pg_strcasecmp(defel->defname, "lc_collate") == 0)
|
|
|
|
defelp = &lccollateEl;
|
|
|
|
else if (pg_strcasecmp(defel->defname, "lc_ctype") == 0)
|
|
|
|
defelp = &lcctypeEl;
|
2017-03-23 20:25:34 +01:00
|
|
|
else if (pg_strcasecmp(defel->defname, "provider") == 0)
|
|
|
|
defelp = &providerEl;
|
|
|
|
else if (pg_strcasecmp(defel->defname, "version") == 0)
|
|
|
|
defelp = &versionEl;
|
2011-02-12 14:54:13 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
|
|
|
errmsg("collation attribute \"%s\" not recognized",
|
2016-09-06 18:00:00 +02:00
|
|
|
defel->defname),
|
|
|
|
parser_errposition(pstate, defel->location)));
|
2011-02-12 14:54:13 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
*defelp = defel;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((localeEl && (lccollateEl || lcctypeEl))
|
|
|
|
|| (fromEl && list_length(parameters) != 1))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
|
|
|
errmsg("conflicting or redundant options")));
|
|
|
|
|
|
|
|
if (fromEl)
|
|
|
|
{
|
|
|
|
Oid collid;
|
|
|
|
HeapTuple tp;
|
|
|
|
|
2011-04-10 17:42:00 +02:00
|
|
|
collid = get_collation_oid(defGetQualifiedName(fromEl), false);
|
2011-02-12 14:54:13 +01:00
|
|
|
tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
|
|
|
|
if (!HeapTupleIsValid(tp))
|
|
|
|
elog(ERROR, "cache lookup failed for collation %u", collid);
|
|
|
|
|
|
|
|
collcollate = pstrdup(NameStr(((Form_pg_collation) GETSTRUCT(tp))->collcollate));
|
|
|
|
collctype = pstrdup(NameStr(((Form_pg_collation) GETSTRUCT(tp))->collctype));
|
2017-03-23 20:25:34 +01:00
|
|
|
collprovider = ((Form_pg_collation) GETSTRUCT(tp))->collprovider;
|
2011-02-12 14:54:13 +01:00
|
|
|
|
|
|
|
ReleaseSysCache(tp);
|
2017-06-13 14:49:41 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Copying the "default" collation is not allowed because most code
|
|
|
|
* checks for DEFAULT_COLLATION_OID instead of COLLPROVIDER_DEFAULT,
|
|
|
|
* and so having a second collation with COLLPROVIDER_DEFAULT would
|
|
|
|
* not work and potentially confuse or crash some code. This could be
|
|
|
|
* fixed with some legwork.
|
|
|
|
*/
|
|
|
|
if (collprovider == COLLPROVIDER_DEFAULT)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
|
|
|
errmsg("collation \"default\" cannot be copied")));
|
2011-02-12 14:54:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (localeEl)
|
|
|
|
{
|
|
|
|
collcollate = defGetString(localeEl);
|
|
|
|
collctype = defGetString(localeEl);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lccollateEl)
|
|
|
|
collcollate = defGetString(lccollateEl);
|
|
|
|
|
|
|
|
if (lcctypeEl)
|
|
|
|
collctype = defGetString(lcctypeEl);
|
|
|
|
|
2017-03-23 20:25:34 +01:00
|
|
|
if (providerEl)
|
|
|
|
collproviderstr = defGetString(providerEl);
|
|
|
|
|
|
|
|
if (versionEl)
|
|
|
|
collversion = defGetString(versionEl);
|
|
|
|
|
|
|
|
if (collproviderstr)
|
|
|
|
{
|
|
|
|
if (pg_strcasecmp(collproviderstr, "icu") == 0)
|
|
|
|
collprovider = COLLPROVIDER_ICU;
|
|
|
|
else if (pg_strcasecmp(collproviderstr, "libc") == 0)
|
|
|
|
collprovider = COLLPROVIDER_LIBC;
|
|
|
|
else
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
|
|
|
errmsg("unrecognized collation provider: %s",
|
|
|
|
collproviderstr)));
|
|
|
|
}
|
|
|
|
else if (!fromEl)
|
|
|
|
collprovider = COLLPROVIDER_LIBC;
|
|
|
|
|
2011-02-12 14:54:13 +01:00
|
|
|
if (!collcollate)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
2011-09-07 19:29:26 +02:00
|
|
|
errmsg("parameter \"lc_collate\" must be specified")));
|
2011-02-12 14:54:13 +01:00
|
|
|
|
|
|
|
if (!collctype)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
|
|
|
errmsg("parameter \"lc_ctype\" must be specified")));
|
|
|
|
|
2017-03-23 20:25:34 +01:00
|
|
|
if (collprovider == COLLPROVIDER_ICU)
|
|
|
|
collencoding = -1;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
collencoding = GetDatabaseEncoding();
|
|
|
|
check_encoding_locale_matches(collencoding, collcollate, collctype);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!collversion)
|
|
|
|
collversion = get_collation_actual_version(collprovider, collcollate);
|
2011-02-12 14:54:13 +01:00
|
|
|
|
2011-03-04 21:14:37 +01:00
|
|
|
newoid = CollationCreate(collName,
|
2011-03-11 19:20:11 +01:00
|
|
|
collNamespace,
|
|
|
|
GetUserId(),
|
2017-03-23 20:25:34 +01:00
|
|
|
collprovider,
|
|
|
|
collencoding,
|
2011-03-11 19:20:11 +01:00
|
|
|
collcollate,
|
2017-01-18 18:00:00 +01:00
|
|
|
collctype,
|
2017-03-23 20:25:34 +01:00
|
|
|
collversion,
|
2017-02-09 04:51:09 +01:00
|
|
|
if_not_exists);
|
2017-01-18 18:00:00 +01:00
|
|
|
|
|
|
|
if (!OidIsValid(newoid))
|
|
|
|
return InvalidObjectAddress;
|
2011-03-04 21:14:37 +01:00
|
|
|
|
Change many routines to return ObjectAddress rather than OID
The changed routines are mostly those that can be directly called by
ProcessUtilitySlow; the intention is to make the affected object
information more precise, in support for future event trigger changes.
Originally it was envisioned that the OID of the affected object would
be enough, and in most cases that is correct, but upon actually
implementing the event trigger changes it turned out that ObjectAddress
is more widely useful.
Additionally, some command execution routines grew an output argument
that's an object address which provides further info about the executed
command. To wit:
* for ALTER DOMAIN / ADD CONSTRAINT, it corresponds to the address of
the new constraint
* for ALTER OBJECT / SET SCHEMA, it corresponds to the address of the
schema that originally contained the object.
* for ALTER EXTENSION {ADD, DROP} OBJECT, it corresponds to the address
of the object added to or dropped from the extension.
There's no user-visible change in this commit, and no functional change
either.
Discussion: 20150218213255.GC6717@tamriel.snowman.net
Reviewed-By: Stephen Frost, Andres Freund
2015-03-03 18:10:50 +01:00
|
|
|
ObjectAddressSet(address, CollationRelationId, newoid);
|
|
|
|
|
2011-03-04 21:14:37 +01:00
|
|
|
/* check that the locales can be loaded */
|
|
|
|
CommandCounterIncrement();
|
2011-03-22 21:55:32 +01:00
|
|
|
(void) pg_newlocale_from_collation(newoid);
|
2012-12-24 00:25:03 +01:00
|
|
|
|
Change many routines to return ObjectAddress rather than OID
The changed routines are mostly those that can be directly called by
ProcessUtilitySlow; the intention is to make the affected object
information more precise, in support for future event trigger changes.
Originally it was envisioned that the OID of the affected object would
be enough, and in most cases that is correct, but upon actually
implementing the event trigger changes it turned out that ObjectAddress
is more widely useful.
Additionally, some command execution routines grew an output argument
that's an object address which provides further info about the executed
command. To wit:
* for ALTER DOMAIN / ADD CONSTRAINT, it corresponds to the address of
the new constraint
* for ALTER OBJECT / SET SCHEMA, it corresponds to the address of the
schema that originally contained the object.
* for ALTER EXTENSION {ADD, DROP} OBJECT, it corresponds to the address
of the object added to or dropped from the extension.
There's no user-visible change in this commit, and no functional change
either.
Discussion: 20150218213255.GC6717@tamriel.snowman.net
Reviewed-By: Stephen Frost, Andres Freund
2015-03-03 18:10:50 +01:00
|
|
|
return address;
|
2011-02-12 14:54:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
Rework order of checks in ALTER / SET SCHEMA
When attempting to move an object into the schema in which it already
was, for most objects classes we were correctly complaining about
exactly that ("object is already in schema"); but for some other object
classes, such as functions, we were instead complaining of a name
collision ("object already exists in schema"). The latter is wrong and
misleading, per complaint from Robert Haas in
CA+TgmoZ0+gNf7RDKRc3u5rHXffP=QjqPZKGxb4BsPz65k7qnHQ@mail.gmail.com
To fix, refactor the way these checks are done. As a bonus, the
resulting code is smaller and can also share some code with Rename
cases.
While at it, remove use of getObjectDescriptionOids() in error messages.
These are normally disallowed because of translatability considerations,
but this one had slipped through since 9.1. (Not sure that this is
worth backpatching, though, as it would create some untranslated
messages in back branches.)
This is loosely based on a patch by KaiGai Kohei, heavily reworked by
me.
2013-01-15 17:23:43 +01:00
|
|
|
* Subroutine for ALTER COLLATION SET SCHEMA and RENAME
|
|
|
|
*
|
|
|
|
* Is there a collation with the same name of the given collation already in
|
|
|
|
* the given namespace? If so, raise an appropriate error message.
|
2011-02-12 14:54:13 +01:00
|
|
|
*/
|
Rework order of checks in ALTER / SET SCHEMA
When attempting to move an object into the schema in which it already
was, for most objects classes we were correctly complaining about
exactly that ("object is already in schema"); but for some other object
classes, such as functions, we were instead complaining of a name
collision ("object already exists in schema"). The latter is wrong and
misleading, per complaint from Robert Haas in
CA+TgmoZ0+gNf7RDKRc3u5rHXffP=QjqPZKGxb4BsPz65k7qnHQ@mail.gmail.com
To fix, refactor the way these checks are done. As a bonus, the
resulting code is smaller and can also share some code with Rename
cases.
While at it, remove use of getObjectDescriptionOids() in error messages.
These are normally disallowed because of translatability considerations,
but this one had slipped through since 9.1. (Not sure that this is
worth backpatching, though, as it would create some untranslated
messages in back branches.)
This is loosely based on a patch by KaiGai Kohei, heavily reworked by
me.
2013-01-15 17:23:43 +01:00
|
|
|
void
|
|
|
|
IsThereCollationInNamespace(const char *collname, Oid nspOid)
|
2011-02-12 14:54:13 +01:00
|
|
|
{
|
2011-03-11 19:20:11 +01:00
|
|
|
/* make sure the name doesn't already exist in new schema */
|
|
|
|
if (SearchSysCacheExists3(COLLNAMEENCNSP,
|
Rework order of checks in ALTER / SET SCHEMA
When attempting to move an object into the schema in which it already
was, for most objects classes we were correctly complaining about
exactly that ("object is already in schema"); but for some other object
classes, such as functions, we were instead complaining of a name
collision ("object already exists in schema"). The latter is wrong and
misleading, per complaint from Robert Haas in
CA+TgmoZ0+gNf7RDKRc3u5rHXffP=QjqPZKGxb4BsPz65k7qnHQ@mail.gmail.com
To fix, refactor the way these checks are done. As a bonus, the
resulting code is smaller and can also share some code with Rename
cases.
While at it, remove use of getObjectDescriptionOids() in error messages.
These are normally disallowed because of translatability considerations,
but this one had slipped through since 9.1. (Not sure that this is
worth backpatching, though, as it would create some untranslated
messages in back branches.)
This is loosely based on a patch by KaiGai Kohei, heavily reworked by
me.
2013-01-15 17:23:43 +01:00
|
|
|
CStringGetDatum(collname),
|
2011-03-11 19:20:11 +01:00
|
|
|
Int32GetDatum(GetDatabaseEncoding()),
|
Rework order of checks in ALTER / SET SCHEMA
When attempting to move an object into the schema in which it already
was, for most objects classes we were correctly complaining about
exactly that ("object is already in schema"); but for some other object
classes, such as functions, we were instead complaining of a name
collision ("object already exists in schema"). The latter is wrong and
misleading, per complaint from Robert Haas in
CA+TgmoZ0+gNf7RDKRc3u5rHXffP=QjqPZKGxb4BsPz65k7qnHQ@mail.gmail.com
To fix, refactor the way these checks are done. As a bonus, the
resulting code is smaller and can also share some code with Rename
cases.
While at it, remove use of getObjectDescriptionOids() in error messages.
These are normally disallowed because of translatability considerations,
but this one had slipped through since 9.1. (Not sure that this is
worth backpatching, though, as it would create some untranslated
messages in back branches.)
This is loosely based on a patch by KaiGai Kohei, heavily reworked by
me.
2013-01-15 17:23:43 +01:00
|
|
|
ObjectIdGetDatum(nspOid)))
|
2011-03-11 19:20:11 +01:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_DUPLICATE_OBJECT),
|
|
|
|
errmsg("collation \"%s\" for encoding \"%s\" already exists in schema \"%s\"",
|
Rework order of checks in ALTER / SET SCHEMA
When attempting to move an object into the schema in which it already
was, for most objects classes we were correctly complaining about
exactly that ("object is already in schema"); but for some other object
classes, such as functions, we were instead complaining of a name
collision ("object already exists in schema"). The latter is wrong and
misleading, per complaint from Robert Haas in
CA+TgmoZ0+gNf7RDKRc3u5rHXffP=QjqPZKGxb4BsPz65k7qnHQ@mail.gmail.com
To fix, refactor the way these checks are done. As a bonus, the
resulting code is smaller and can also share some code with Rename
cases.
While at it, remove use of getObjectDescriptionOids() in error messages.
These are normally disallowed because of translatability considerations,
but this one had slipped through since 9.1. (Not sure that this is
worth backpatching, though, as it would create some untranslated
messages in back branches.)
This is loosely based on a patch by KaiGai Kohei, heavily reworked by
me.
2013-01-15 17:23:43 +01:00
|
|
|
collname, GetDatabaseEncodingName(),
|
|
|
|
get_namespace_name(nspOid))));
|
2011-03-11 19:20:11 +01:00
|
|
|
|
|
|
|
/* mustn't match an any-encoding entry, either */
|
|
|
|
if (SearchSysCacheExists3(COLLNAMEENCNSP,
|
Rework order of checks in ALTER / SET SCHEMA
When attempting to move an object into the schema in which it already
was, for most objects classes we were correctly complaining about
exactly that ("object is already in schema"); but for some other object
classes, such as functions, we were instead complaining of a name
collision ("object already exists in schema"). The latter is wrong and
misleading, per complaint from Robert Haas in
CA+TgmoZ0+gNf7RDKRc3u5rHXffP=QjqPZKGxb4BsPz65k7qnHQ@mail.gmail.com
To fix, refactor the way these checks are done. As a bonus, the
resulting code is smaller and can also share some code with Rename
cases.
While at it, remove use of getObjectDescriptionOids() in error messages.
These are normally disallowed because of translatability considerations,
but this one had slipped through since 9.1. (Not sure that this is
worth backpatching, though, as it would create some untranslated
messages in back branches.)
This is loosely based on a patch by KaiGai Kohei, heavily reworked by
me.
2013-01-15 17:23:43 +01:00
|
|
|
CStringGetDatum(collname),
|
2011-03-11 19:20:11 +01:00
|
|
|
Int32GetDatum(-1),
|
Rework order of checks in ALTER / SET SCHEMA
When attempting to move an object into the schema in which it already
was, for most objects classes we were correctly complaining about
exactly that ("object is already in schema"); but for some other object
classes, such as functions, we were instead complaining of a name
collision ("object already exists in schema"). The latter is wrong and
misleading, per complaint from Robert Haas in
CA+TgmoZ0+gNf7RDKRc3u5rHXffP=QjqPZKGxb4BsPz65k7qnHQ@mail.gmail.com
To fix, refactor the way these checks are done. As a bonus, the
resulting code is smaller and can also share some code with Rename
cases.
While at it, remove use of getObjectDescriptionOids() in error messages.
These are normally disallowed because of translatability considerations,
but this one had slipped through since 9.1. (Not sure that this is
worth backpatching, though, as it would create some untranslated
messages in back branches.)
This is loosely based on a patch by KaiGai Kohei, heavily reworked by
me.
2013-01-15 17:23:43 +01:00
|
|
|
ObjectIdGetDatum(nspOid)))
|
2011-03-11 19:20:11 +01:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_DUPLICATE_OBJECT),
|
|
|
|
errmsg("collation \"%s\" already exists in schema \"%s\"",
|
Rework order of checks in ALTER / SET SCHEMA
When attempting to move an object into the schema in which it already
was, for most objects classes we were correctly complaining about
exactly that ("object is already in schema"); but for some other object
classes, such as functions, we were instead complaining of a name
collision ("object already exists in schema"). The latter is wrong and
misleading, per complaint from Robert Haas in
CA+TgmoZ0+gNf7RDKRc3u5rHXffP=QjqPZKGxb4BsPz65k7qnHQ@mail.gmail.com
To fix, refactor the way these checks are done. As a bonus, the
resulting code is smaller and can also share some code with Rename
cases.
While at it, remove use of getObjectDescriptionOids() in error messages.
These are normally disallowed because of translatability considerations,
but this one had slipped through since 9.1. (Not sure that this is
worth backpatching, though, as it would create some untranslated
messages in back branches.)
This is loosely based on a patch by KaiGai Kohei, heavily reworked by
me.
2013-01-15 17:23:43 +01:00
|
|
|
collname, get_namespace_name(nspOid))));
|
2011-02-12 14:54:13 +01:00
|
|
|
}
|
2017-01-18 18:00:00 +01:00
|
|
|
|
2017-03-23 20:25:34 +01:00
|
|
|
/*
|
|
|
|
* ALTER COLLATION
|
|
|
|
*/
|
|
|
|
ObjectAddress
|
|
|
|
AlterCollation(AlterCollationStmt *stmt)
|
|
|
|
{
|
|
|
|
Relation rel;
|
|
|
|
Oid collOid;
|
|
|
|
HeapTuple tup;
|
|
|
|
Form_pg_collation collForm;
|
|
|
|
Datum collversion;
|
|
|
|
bool isnull;
|
|
|
|
char *oldversion;
|
|
|
|
char *newversion;
|
|
|
|
ObjectAddress address;
|
|
|
|
|
|
|
|
rel = heap_open(CollationRelationId, RowExclusiveLock);
|
|
|
|
collOid = get_collation_oid(stmt->collname, false);
|
|
|
|
|
|
|
|
if (!pg_collation_ownercheck(collOid, GetUserId()))
|
|
|
|
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_COLLATION,
|
|
|
|
NameListToString(stmt->collname));
|
|
|
|
|
|
|
|
tup = SearchSysCacheCopy1(COLLOID, ObjectIdGetDatum(collOid));
|
|
|
|
if (!HeapTupleIsValid(tup))
|
|
|
|
elog(ERROR, "cache lookup failed for collation %u", collOid);
|
|
|
|
|
|
|
|
collForm = (Form_pg_collation) GETSTRUCT(tup);
|
|
|
|
collversion = SysCacheGetAttr(COLLOID, tup, Anum_pg_collation_collversion,
|
|
|
|
&isnull);
|
|
|
|
oldversion = isnull ? NULL : TextDatumGetCString(collversion);
|
|
|
|
|
|
|
|
newversion = get_collation_actual_version(collForm->collprovider, NameStr(collForm->collcollate));
|
|
|
|
|
|
|
|
/* cannot change from NULL to non-NULL or vice versa */
|
|
|
|
if ((!oldversion && newversion) || (oldversion && !newversion))
|
|
|
|
elog(ERROR, "invalid collation version change");
|
|
|
|
else if (oldversion && newversion && strcmp(newversion, oldversion) != 0)
|
|
|
|
{
|
2017-05-17 22:31:56 +02:00
|
|
|
bool nulls[Natts_pg_collation];
|
|
|
|
bool replaces[Natts_pg_collation];
|
|
|
|
Datum values[Natts_pg_collation];
|
2017-03-23 20:25:34 +01:00
|
|
|
|
|
|
|
ereport(NOTICE,
|
|
|
|
(errmsg("changing version from %s to %s",
|
|
|
|
oldversion, newversion)));
|
|
|
|
|
|
|
|
memset(values, 0, sizeof(values));
|
|
|
|
memset(nulls, false, sizeof(nulls));
|
|
|
|
memset(replaces, false, sizeof(replaces));
|
|
|
|
|
|
|
|
values[Anum_pg_collation_collversion - 1] = CStringGetTextDatum(newversion);
|
|
|
|
replaces[Anum_pg_collation_collversion - 1] = true;
|
|
|
|
|
|
|
|
tup = heap_modify_tuple(tup, RelationGetDescr(rel),
|
|
|
|
values, nulls, replaces);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ereport(NOTICE,
|
|
|
|
(errmsg("version has not changed")));
|
|
|
|
|
|
|
|
CatalogTupleUpdate(rel, &tup->t_self, tup);
|
|
|
|
|
|
|
|
InvokeObjectPostAlterHook(CollationRelationId, collOid, 0);
|
|
|
|
|
|
|
|
ObjectAddressSet(address, CollationRelationId, collOid);
|
|
|
|
|
|
|
|
heap_freetuple(tup);
|
|
|
|
heap_close(rel, NoLock);
|
|
|
|
|
|
|
|
return address;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Datum
|
|
|
|
pg_collation_actual_version(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
Oid collid = PG_GETARG_OID(0);
|
|
|
|
HeapTuple tp;
|
|
|
|
char *collcollate;
|
|
|
|
char collprovider;
|
|
|
|
char *version;
|
|
|
|
|
|
|
|
tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
|
|
|
|
if (!HeapTupleIsValid(tp))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
|
|
|
errmsg("collation with OID %u does not exist", collid)));
|
|
|
|
|
|
|
|
collcollate = pstrdup(NameStr(((Form_pg_collation) GETSTRUCT(tp))->collcollate));
|
|
|
|
collprovider = ((Form_pg_collation) GETSTRUCT(tp))->collprovider;
|
|
|
|
|
|
|
|
ReleaseSysCache(tp);
|
|
|
|
|
|
|
|
version = get_collation_actual_version(collprovider, collcollate);
|
|
|
|
|
|
|
|
if (version)
|
|
|
|
PG_RETURN_TEXT_P(cstring_to_text(version));
|
|
|
|
else
|
|
|
|
PG_RETURN_NULL();
|
|
|
|
}
|
|
|
|
|
2017-01-18 18:00:00 +01:00
|
|
|
|
|
|
|
/*
|
2017-03-23 20:25:34 +01:00
|
|
|
* "Normalize" a libc locale name, stripping off encoding tags such as
|
2017-01-18 18:00:00 +01:00
|
|
|
* ".utf8" (e.g., "en_US.utf8" -> "en_US", but "br_FR.iso885915@euro"
|
|
|
|
* -> "br_FR@euro"). Return true if a new, different name was
|
|
|
|
* generated.
|
|
|
|
*/
|
|
|
|
pg_attribute_unused()
|
|
|
|
static bool
|
2017-03-23 20:25:34 +01:00
|
|
|
normalize_libc_locale_name(char *new, const char *old)
|
2017-01-18 18:00:00 +01:00
|
|
|
{
|
|
|
|
char *n = new;
|
|
|
|
const char *o = old;
|
|
|
|
bool changed = false;
|
|
|
|
|
|
|
|
while (*o)
|
|
|
|
{
|
|
|
|
if (*o == '.')
|
|
|
|
{
|
|
|
|
/* skip over encoding tag such as ".utf8" or ".UTF-8" */
|
|
|
|
o++;
|
|
|
|
while ((*o >= 'A' && *o <= 'Z')
|
|
|
|
|| (*o >= 'a' && *o <= 'z')
|
|
|
|
|| (*o >= '0' && *o <= '9')
|
|
|
|
|| (*o == '-'))
|
|
|
|
o++;
|
|
|
|
changed = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
*n++ = *o++;
|
|
|
|
}
|
|
|
|
*n = '\0';
|
|
|
|
|
|
|
|
return changed;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-03-23 20:25:34 +01:00
|
|
|
#ifdef USE_ICU
|
Fix memory leakage in ICU encoding conversion, and other code review.
Callers of icu_to_uchar() neglected to pfree the result string when done
with it. This results in catastrophic memory leaks in varstr_cmp(),
because of our prevailing assumption that btree comparison functions don't
leak memory. For safety, make all the call sites clean up leaks, though
I suspect that we could get away without it in formatting.c. I audited
callers of icu_from_uchar() as well, but found no places that seemed to
have a comparable issue.
Add function API specifications for icu_to_uchar() and icu_from_uchar();
the lack of any thought-through specification is perhaps not unrelated
to the existence of this bug in the first place. Fix icu_to_uchar()
to guarantee a nul-terminated result; although no existing caller appears
to care, the fact that it would have been nul-terminated except in
extreme corner cases seems ideally designed to bite someone on the rear
someday. Fix ucnv_fromUChars() destCapacity argument --- in the worst
case, that could perhaps have led to a non-nul-terminated result, too.
Fix icu_from_uchar() to have a more reasonable definition of the function
result --- no callers are actually paying attention, so this isn't a live
bug, but it's certainly sloppily designed. Const-ify icu_from_uchar()'s
input string for consistency.
That is not the end of what needs to be done to these functions, but
it's as much as I have the patience for right now.
Discussion: https://postgr.es/m/1955.1498181798@sss.pgh.pa.us
2017-06-23 18:22:06 +02:00
|
|
|
/*
|
|
|
|
* Get the ICU language tag for a locale name.
|
|
|
|
* The result is a palloc'd string.
|
|
|
|
*/
|
2017-03-23 20:25:34 +01:00
|
|
|
static char *
|
|
|
|
get_icu_language_tag(const char *localename)
|
|
|
|
{
|
|
|
|
char buf[ULOC_FULLNAME_CAPACITY];
|
|
|
|
UErrorCode status;
|
|
|
|
|
|
|
|
status = U_ZERO_ERROR;
|
|
|
|
uloc_toLanguageTag(localename, buf, sizeof(buf), TRUE, &status);
|
|
|
|
if (U_FAILURE(status))
|
|
|
|
ereport(ERROR,
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
(errmsg("could not convert locale name \"%s\" to language tag: %s",
|
|
|
|
localename, u_errorName(status))));
|
2017-03-23 20:25:34 +01:00
|
|
|
|
|
|
|
return pstrdup(buf);
|
|
|
|
}
|
|
|
|
|
Fix memory leakage in ICU encoding conversion, and other code review.
Callers of icu_to_uchar() neglected to pfree the result string when done
with it. This results in catastrophic memory leaks in varstr_cmp(),
because of our prevailing assumption that btree comparison functions don't
leak memory. For safety, make all the call sites clean up leaks, though
I suspect that we could get away without it in formatting.c. I audited
callers of icu_from_uchar() as well, but found no places that seemed to
have a comparable issue.
Add function API specifications for icu_to_uchar() and icu_from_uchar();
the lack of any thought-through specification is perhaps not unrelated
to the existence of this bug in the first place. Fix icu_to_uchar()
to guarantee a nul-terminated result; although no existing caller appears
to care, the fact that it would have been nul-terminated except in
extreme corner cases seems ideally designed to bite someone on the rear
someday. Fix ucnv_fromUChars() destCapacity argument --- in the worst
case, that could perhaps have led to a non-nul-terminated result, too.
Fix icu_from_uchar() to have a more reasonable definition of the function
result --- no callers are actually paying attention, so this isn't a live
bug, but it's certainly sloppily designed. Const-ify icu_from_uchar()'s
input string for consistency.
That is not the end of what needs to be done to these functions, but
it's as much as I have the patience for right now.
Discussion: https://postgr.es/m/1955.1498181798@sss.pgh.pa.us
2017-06-23 18:22:06 +02:00
|
|
|
/*
|
|
|
|
* Get a comment (specifically, the display name) for an ICU locale.
|
|
|
|
* The result is a palloc'd string.
|
|
|
|
*/
|
2017-03-23 20:25:34 +01:00
|
|
|
static char *
|
|
|
|
get_icu_locale_comment(const char *localename)
|
|
|
|
{
|
|
|
|
UErrorCode status;
|
|
|
|
UChar displayname[128];
|
|
|
|
int32 len_uchar;
|
|
|
|
char *result;
|
|
|
|
|
|
|
|
status = U_ZERO_ERROR;
|
Fix memory leakage in ICU encoding conversion, and other code review.
Callers of icu_to_uchar() neglected to pfree the result string when done
with it. This results in catastrophic memory leaks in varstr_cmp(),
because of our prevailing assumption that btree comparison functions don't
leak memory. For safety, make all the call sites clean up leaks, though
I suspect that we could get away without it in formatting.c. I audited
callers of icu_from_uchar() as well, but found no places that seemed to
have a comparable issue.
Add function API specifications for icu_to_uchar() and icu_from_uchar();
the lack of any thought-through specification is perhaps not unrelated
to the existence of this bug in the first place. Fix icu_to_uchar()
to guarantee a nul-terminated result; although no existing caller appears
to care, the fact that it would have been nul-terminated except in
extreme corner cases seems ideally designed to bite someone on the rear
someday. Fix ucnv_fromUChars() destCapacity argument --- in the worst
case, that could perhaps have led to a non-nul-terminated result, too.
Fix icu_from_uchar() to have a more reasonable definition of the function
result --- no callers are actually paying attention, so this isn't a live
bug, but it's certainly sloppily designed. Const-ify icu_from_uchar()'s
input string for consistency.
That is not the end of what needs to be done to these functions, but
it's as much as I have the patience for right now.
Discussion: https://postgr.es/m/1955.1498181798@sss.pgh.pa.us
2017-06-23 18:22:06 +02:00
|
|
|
len_uchar = uloc_getDisplayName(localename, "en",
|
|
|
|
&displayname[0], sizeof(displayname),
|
|
|
|
&status);
|
2017-03-23 20:25:34 +01:00
|
|
|
if (U_FAILURE(status))
|
|
|
|
ereport(ERROR,
|
Fix memory leakage in ICU encoding conversion, and other code review.
Callers of icu_to_uchar() neglected to pfree the result string when done
with it. This results in catastrophic memory leaks in varstr_cmp(),
because of our prevailing assumption that btree comparison functions don't
leak memory. For safety, make all the call sites clean up leaks, though
I suspect that we could get away without it in formatting.c. I audited
callers of icu_from_uchar() as well, but found no places that seemed to
have a comparable issue.
Add function API specifications for icu_to_uchar() and icu_from_uchar();
the lack of any thought-through specification is perhaps not unrelated
to the existence of this bug in the first place. Fix icu_to_uchar()
to guarantee a nul-terminated result; although no existing caller appears
to care, the fact that it would have been nul-terminated except in
extreme corner cases seems ideally designed to bite someone on the rear
someday. Fix ucnv_fromUChars() destCapacity argument --- in the worst
case, that could perhaps have led to a non-nul-terminated result, too.
Fix icu_from_uchar() to have a more reasonable definition of the function
result --- no callers are actually paying attention, so this isn't a live
bug, but it's certainly sloppily designed. Const-ify icu_from_uchar()'s
input string for consistency.
That is not the end of what needs to be done to these functions, but
it's as much as I have the patience for right now.
Discussion: https://postgr.es/m/1955.1498181798@sss.pgh.pa.us
2017-06-23 18:22:06 +02:00
|
|
|
(errmsg("could not get display name for locale \"%s\": %s",
|
2017-03-23 20:25:34 +01:00
|
|
|
localename, u_errorName(status))));
|
|
|
|
|
|
|
|
icu_from_uchar(&result, displayname, len_uchar);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
Phase 2 of pgindent updates.
Change pg_bsd_indent to follow upstream rules for placement of comments
to the right of code, and remove pgindent hack that caused comments
following #endif to not obey the general rule.
Commit e3860ffa4dd0dad0dd9eea4be9cc1412373a8c89 wasn't actually using
the published version of pg_bsd_indent, but a hacked-up version that
tried to minimize the amount of movement of comments to the right of
code. The situation of interest is where such a comment has to be
moved to the right of its default placement at column 33 because there's
code there. BSD indent has always moved right in units of tab stops
in such cases --- but in the previous incarnation, indent was working
in 8-space tab stops, while now it knows we use 4-space tabs. So the
net result is that in about half the cases, such comments are placed
one tab stop left of before. This is better all around: it leaves
more room on the line for comment text, and it means that in such
cases the comment uniformly starts at the next 4-space tab stop after
the code, rather than sometimes one and sometimes two tabs after.
Also, ensure that comments following #endif are indented the same
as comments following other preprocessor commands such as #else.
That inconsistency turns out to have been self-inflicted damage
from a poorly-thought-through post-indent "fixup" in pgindent.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:18:54 +02:00
|
|
|
#endif /* USE_ICU */
|
2017-03-23 20:25:34 +01:00
|
|
|
|
|
|
|
|
2017-01-18 18:00:00 +01:00
|
|
|
Datum
|
|
|
|
pg_import_system_collations(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
bool if_not_exists = PG_GETARG_BOOL(0);
|
2017-01-18 19:44:19 +01:00
|
|
|
Oid nspid = PG_GETARG_OID(1);
|
2017-01-18 18:00:00 +01:00
|
|
|
|
2017-06-12 16:28:37 +02:00
|
|
|
#if defined(HAVE_LOCALE_T) && !defined(WIN32)
|
2017-01-18 18:00:00 +01:00
|
|
|
FILE *locale_a_handle;
|
|
|
|
char localebuf[NAMEDATALEN]; /* we assume ASCII so this is fine */
|
|
|
|
int count = 0;
|
2017-01-18 19:44:19 +01:00
|
|
|
List *aliaslist = NIL;
|
|
|
|
List *localelist = NIL;
|
|
|
|
List *enclist = NIL;
|
|
|
|
ListCell *lca,
|
|
|
|
*lcl,
|
|
|
|
*lce;
|
2017-01-18 18:00:00 +01:00
|
|
|
#endif
|
|
|
|
|
|
|
|
if (!superuser())
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
|
|
|
(errmsg("must be superuser to import system collations"))));
|
|
|
|
|
2017-06-12 16:28:37 +02:00
|
|
|
#if !(defined(HAVE_LOCALE_T) && !defined(WIN32)) && !defined(USE_ICU)
|
|
|
|
/* silence compiler warnings */
|
|
|
|
(void) if_not_exists;
|
|
|
|
(void) nspid;
|
|
|
|
#endif
|
|
|
|
|
2017-01-18 18:00:00 +01:00
|
|
|
#if defined(HAVE_LOCALE_T) && !defined(WIN32)
|
|
|
|
locale_a_handle = OpenPipeStream("locale -a", "r");
|
|
|
|
if (locale_a_handle == NULL)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode_for_file_access(),
|
|
|
|
errmsg("could not execute command \"%s\": %m",
|
|
|
|
"locale -a")));
|
|
|
|
|
|
|
|
while (fgets(localebuf, sizeof(localebuf), locale_a_handle))
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
size_t len;
|
|
|
|
int enc;
|
|
|
|
bool skip;
|
|
|
|
char alias[NAMEDATALEN];
|
|
|
|
|
|
|
|
len = strlen(localebuf);
|
|
|
|
|
|
|
|
if (len == 0 || localebuf[len - 1] != '\n')
|
|
|
|
{
|
|
|
|
elog(DEBUG1, "locale name too long, skipped: \"%s\"", localebuf);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
localebuf[len - 1] = '\0';
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Some systems have locale names that don't consist entirely of ASCII
|
|
|
|
* letters (such as "bokmål" or "français"). This is
|
|
|
|
* pretty silly, since we need the locale itself to interpret the
|
|
|
|
* non-ASCII characters. We can't do much with those, so we filter
|
|
|
|
* them out.
|
|
|
|
*/
|
|
|
|
skip = false;
|
|
|
|
for (i = 0; i < len; i++)
|
|
|
|
{
|
|
|
|
if (IS_HIGHBIT_SET(localebuf[i]))
|
|
|
|
{
|
|
|
|
skip = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (skip)
|
|
|
|
{
|
|
|
|
elog(DEBUG1, "locale name has non-ASCII characters, skipped: \"%s\"", localebuf);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
enc = pg_get_encoding_from_locale(localebuf, false);
|
|
|
|
if (enc < 0)
|
|
|
|
{
|
|
|
|
/* error message printed by pg_get_encoding_from_locale() */
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (!PG_VALID_BE_ENCODING(enc))
|
|
|
|
continue; /* ignore locales for client-only encodings */
|
|
|
|
if (enc == PG_SQL_ASCII)
|
|
|
|
continue; /* C/POSIX are already in the catalog */
|
|
|
|
|
|
|
|
count++;
|
|
|
|
|
2017-03-23 20:25:34 +01:00
|
|
|
CollationCreate(localebuf, nspid, GetUserId(), COLLPROVIDER_LIBC, enc,
|
|
|
|
localebuf, localebuf,
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
get_collation_actual_version(COLLPROVIDER_LIBC, localebuf),
|
2017-03-23 20:25:34 +01:00
|
|
|
if_not_exists);
|
2017-01-18 18:00:00 +01:00
|
|
|
|
|
|
|
CommandCounterIncrement();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Generate aliases such as "en_US" in addition to "en_US.utf8" for
|
|
|
|
* ease of use. Note that collation names are unique per encoding
|
|
|
|
* only, so this doesn't clash with "en_US" for LATIN1, say.
|
|
|
|
*
|
2017-01-18 19:44:19 +01:00
|
|
|
* However, it might conflict with a name we'll see later in the
|
|
|
|
* "locale -a" output. So save up the aliases and try to add them
|
|
|
|
* after we've read all the output.
|
2017-01-18 18:00:00 +01:00
|
|
|
*/
|
2017-03-23 20:25:34 +01:00
|
|
|
if (normalize_libc_locale_name(alias, localebuf))
|
2017-01-18 18:00:00 +01:00
|
|
|
{
|
2017-01-18 19:44:19 +01:00
|
|
|
aliaslist = lappend(aliaslist, pstrdup(alias));
|
|
|
|
localelist = lappend(localelist, pstrdup(localebuf));
|
|
|
|
enclist = lappend_int(enclist, enc);
|
2017-01-18 18:00:00 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ClosePipeStream(locale_a_handle);
|
|
|
|
|
2017-01-18 19:44:19 +01:00
|
|
|
/* Now try to add any aliases we created */
|
|
|
|
forthree(lca, aliaslist, lcl, localelist, lce, enclist)
|
|
|
|
{
|
|
|
|
char *alias = (char *) lfirst(lca);
|
|
|
|
char *locale = (char *) lfirst(lcl);
|
|
|
|
int enc = lfirst_int(lce);
|
|
|
|
|
2017-03-23 20:25:34 +01:00
|
|
|
CollationCreate(alias, nspid, GetUserId(), COLLPROVIDER_LIBC, enc,
|
|
|
|
locale, locale,
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
get_collation_actual_version(COLLPROVIDER_LIBC, locale),
|
2017-03-23 20:25:34 +01:00
|
|
|
true);
|
2017-01-18 19:44:19 +01:00
|
|
|
CommandCounterIncrement();
|
|
|
|
}
|
|
|
|
|
2017-01-18 18:00:00 +01:00
|
|
|
if (count == 0)
|
2017-01-23 19:45:32 +01:00
|
|
|
ereport(WARNING,
|
2017-01-18 18:00:00 +01:00
|
|
|
(errmsg("no usable system locales were found")));
|
Phase 2 of pgindent updates.
Change pg_bsd_indent to follow upstream rules for placement of comments
to the right of code, and remove pgindent hack that caused comments
following #endif to not obey the general rule.
Commit e3860ffa4dd0dad0dd9eea4be9cc1412373a8c89 wasn't actually using
the published version of pg_bsd_indent, but a hacked-up version that
tried to minimize the amount of movement of comments to the right of
code. The situation of interest is where such a comment has to be
moved to the right of its default placement at column 33 because there's
code there. BSD indent has always moved right in units of tab stops
in such cases --- but in the previous incarnation, indent was working
in 8-space tab stops, while now it knows we use 4-space tabs. So the
net result is that in about half the cases, such comments are placed
one tab stop left of before. This is better all around: it leaves
more room on the line for comment text, and it means that in such
cases the comment uniformly starts at the next 4-space tab stop after
the code, rather than sometimes one and sometimes two tabs after.
Also, ensure that comments following #endif are indented the same
as comments following other preprocessor commands such as #else.
That inconsistency turns out to have been self-inflicted damage
from a poorly-thought-through post-indent "fixup" in pgindent.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:18:54 +02:00
|
|
|
#endif /* not HAVE_LOCALE_T && not WIN32 */
|
2017-01-18 18:00:00 +01:00
|
|
|
|
2017-03-23 20:25:34 +01:00
|
|
|
#ifdef USE_ICU
|
|
|
|
if (!is_encoding_supported_by_icu(GetDatabaseEncoding()))
|
|
|
|
{
|
|
|
|
ereport(NOTICE,
|
|
|
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
|
|
|
errmsg("encoding \"%s\" not supported by ICU",
|
|
|
|
pg_encoding_to_char(GetDatabaseEncoding()))));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-05-17 22:31:56 +02:00
|
|
|
int i;
|
2017-03-23 20:25:34 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Start the loop at -1 to sneak in the root locale without too much
|
|
|
|
* code duplication.
|
|
|
|
*/
|
|
|
|
for (i = -1; i < ucol_countAvailable(); i++)
|
|
|
|
{
|
|
|
|
const char *name;
|
|
|
|
char *langtag;
|
|
|
|
const char *collcollate;
|
|
|
|
UEnumeration *en;
|
|
|
|
UErrorCode status;
|
|
|
|
const char *val;
|
|
|
|
Oid collid;
|
|
|
|
|
|
|
|
if (i == -1)
|
2017-05-17 22:31:56 +02:00
|
|
|
name = ""; /* ICU root locale */
|
2017-03-23 20:25:34 +01:00
|
|
|
else
|
|
|
|
name = ucol_getAvailable(i);
|
|
|
|
|
|
|
|
langtag = get_icu_language_tag(name);
|
|
|
|
collcollate = U_ICU_VERSION_MAJOR_NUM >= 54 ? langtag : name;
|
|
|
|
collid = CollationCreate(psprintf("%s-x-icu", langtag),
|
|
|
|
nspid, GetUserId(), COLLPROVIDER_ICU, -1,
|
|
|
|
collcollate, collcollate,
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
get_collation_actual_version(COLLPROVIDER_ICU, collcollate),
|
2017-03-23 20:25:34 +01:00
|
|
|
if_not_exists);
|
|
|
|
|
|
|
|
CreateComments(collid, CollationRelationId, 0,
|
|
|
|
get_icu_locale_comment(name));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Add keyword variants
|
|
|
|
*/
|
|
|
|
status = U_ZERO_ERROR;
|
|
|
|
en = ucol_getKeywordValuesForLocale("collation", name, TRUE, &status);
|
|
|
|
if (U_FAILURE(status))
|
|
|
|
ereport(ERROR,
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
(errmsg("could not get keyword values for locale \"%s\": %s",
|
|
|
|
name, u_errorName(status))));
|
2017-03-23 20:25:34 +01:00
|
|
|
|
|
|
|
status = U_ZERO_ERROR;
|
|
|
|
uenum_reset(en, &status);
|
|
|
|
while ((val = uenum_next(en, NULL, &status)))
|
|
|
|
{
|
2017-05-17 22:31:56 +02:00
|
|
|
char *localeid = psprintf("%s@collation=%s", name, val);
|
2017-03-23 20:25:34 +01:00
|
|
|
|
2017-05-17 22:31:56 +02:00
|
|
|
langtag = get_icu_language_tag(localeid);
|
2017-03-23 20:25:34 +01:00
|
|
|
collcollate = U_ICU_VERSION_MAJOR_NUM >= 54 ? langtag : localeid;
|
|
|
|
collid = CollationCreate(psprintf("%s-x-icu", langtag),
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
nspid, GetUserId(), COLLPROVIDER_ICU, -1,
|
2017-03-23 20:25:34 +01:00
|
|
|
collcollate, collcollate,
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
get_collation_actual_version(COLLPROVIDER_ICU, collcollate),
|
2017-03-23 20:25:34 +01:00
|
|
|
if_not_exists);
|
|
|
|
CreateComments(collid, CollationRelationId, 0,
|
|
|
|
get_icu_locale_comment(localeid));
|
|
|
|
}
|
|
|
|
if (U_FAILURE(status))
|
|
|
|
ereport(ERROR,
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
(errmsg("could not get keyword values for locale \"%s\": %s",
|
|
|
|
name, u_errorName(status))));
|
2017-03-23 20:25:34 +01:00
|
|
|
uenum_close(en);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2017-01-18 18:00:00 +01:00
|
|
|
PG_RETURN_VOID();
|
|
|
|
}
|