This changes the data type of the catalog fields datcollate, datctype,
collcollate, and collctype from name to text. There wasn't ever a
really good reason for them to be of type name; presumably this was
just carried over from when they were fixed-size fields in pg_control,
first into the corresponding pg_database fields, and then to
pg_collation. The values are not identifiers or object names, and we
don't ever look them up that way.
Changing to type text saves space in the typical case, since locale
names are typically only a few bytes long. But it is also possible
that an ICU locale name with several customization options appended
could be longer than 63 bytes, so this also enables that case, which
was previously probably broken.
Reviewed-by: Julien Rouhaud
Discussion: https://www.postgresql.org/message-id/flat/
5e756dd6-0e91-d778-96fd-
b1bcb06c161a@2ndquadrant.com
|
- collcollate name
+ collcollate text
LC_COLLATE for this collation object
|
- collctype name
+ collctype text
LC_CTYPE for this collation object
- |
- datcollate name
-
- LC_COLLATE for this database
-
-
-
- |
- datctype name
-
- LC_CTYPE for this database
-
-
-
|
datistemplate bool
+ |
+ datcollate text
+
+ LC_COLLATE for this database
+
+
+
+ |
+ datctype text
+
+ LC_CTYPE for this database
+
+
+
|
datacl aclitem[]
HeapTuple tup;
Datum values[Natts_pg_collation];
bool nulls[Natts_pg_collation];
- NameData name_name,
- name_collate,
- name_ctype;
+ NameData name_name;
Oid oid;
ObjectAddress myself,
referenced;
values[Anum_pg_collation_collprovider - 1] = CharGetDatum(collprovider);
values[Anum_pg_collation_collisdeterministic - 1] = BoolGetDatum(collisdeterministic);
values[Anum_pg_collation_collencoding - 1] = Int32GetDatum(collencoding);
- namestrcpy(&name_collate, collcollate);
- values[Anum_pg_collation_collcollate - 1] = NameGetDatum(&name_collate);
- namestrcpy(&name_ctype, collctype);
- values[Anum_pg_collation_collctype - 1] = NameGetDatum(&name_ctype);
+ values[Anum_pg_collation_collcollate - 1] = CStringGetTextDatum(collcollate);
+ values[Anum_pg_collation_collctype - 1] = CStringGetTextDatum(collctype);
if (collversion)
values[Anum_pg_collation_collversion - 1] = CStringGetTextDatum(collversion);
else
{
Oid collid;
HeapTuple tp;
+ Datum datum;
+ bool isnull;
collid = get_collation_oid(defGetQualifiedName(fromEl), false);
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));
collprovider = ((Form_pg_collation) GETSTRUCT(tp))->collprovider;
collisdeterministic = ((Form_pg_collation) GETSTRUCT(tp))->collisdeterministic;
collencoding = ((Form_pg_collation) GETSTRUCT(tp))->collencoding;
+ datum = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collcollate, &isnull);
+ if (!isnull)
+ collcollate = TextDatumGetCString(datum);
+ else
+ collcollate = NULL;
+
+ datum = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collctype, &isnull);
+ if (!isnull)
+ collctype = TextDatumGetCString(datum);
+ else
+ collctype = NULL;
+
ReleaseSysCache(tp);
/*
Oid collOid;
HeapTuple tup;
Form_pg_collation collForm;
- Datum collversion;
+ Datum datum;
bool isnull;
char *oldversion;
char *newversion;
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);
+ datum = SysCacheGetAttr(COLLOID, tup, Anum_pg_collation_collversion, &isnull);
+ oldversion = isnull ? NULL : TextDatumGetCString(datum);
- newversion = get_collation_actual_version(collForm->collprovider, NameStr(collForm->collcollate));
+ datum = SysCacheGetAttr(COLLOID, tup, Anum_pg_collation_collcollate, &isnull);
+ Assert(!isnull);
+ newversion = get_collation_actual_version(collForm->collprovider, TextDatumGetCString(datum));
/* cannot change from NULL to non-NULL or vice versa */
if ((!oldversion && newversion) || (oldversion && !newversion))
{
Oid collid = PG_GETARG_OID(0);
HeapTuple tp;
- char *collcollate;
char collprovider;
+ Datum datum;
+ bool isnull;
char *version;
tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
(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);
+ datum = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collcollate, &isnull);
+ Assert(!isnull);
+ version = get_collation_actual_version(collprovider, TextDatumGetCString(datum));
- version = get_collation_actual_version(collprovider, collcollate);
+ ReleaseSysCache(tp);
if (version)
PG_RETURN_TEXT_P(cstring_to_text(version));
#ifdef READ_LOCALE_A_OUTPUT
{
FILE *locale_a_handle;
- char localebuf[NAMEDATALEN]; /* we assume ASCII so this is fine */
+ char localebuf[LOCALE_NAME_BUFLEN];
int nvalid = 0;
Oid collid;
CollAliasData *aliases;
{
size_t len;
int enc;
- char alias[NAMEDATALEN];
+ char alias[LOCALE_NAME_BUFLEN];
len = strlen(localebuf);
DirectFunctionCall1(namein, CStringGetDatum(dbname));
new_record[Anum_pg_database_datdba - 1] = ObjectIdGetDatum(datdba);
new_record[Anum_pg_database_encoding - 1] = Int32GetDatum(encoding);
- new_record[Anum_pg_database_datcollate - 1] =
- DirectFunctionCall1(namein, CStringGetDatum(dbcollate));
- new_record[Anum_pg_database_datctype - 1] =
- DirectFunctionCall1(namein, CStringGetDatum(dbctype));
+ new_record[Anum_pg_database_datcollate - 1] = CStringGetTextDatum(dbcollate);
+ new_record[Anum_pg_database_datctype - 1] = CStringGetTextDatum(dbctype);
new_record[Anum_pg_database_datistemplate - 1] = BoolGetDatum(dbistemplate);
new_record[Anum_pg_database_datallowconn - 1] = BoolGetDatum(dballowconnections);
new_record[Anum_pg_database_datconnlimit - 1] = Int32GetDatum(dbconnlimit);
if (strcmp(name, NameStr(dbform->datname)) == 0)
{
+ Datum datum;
+ bool isnull;
+
/* oid of the database */
if (dbIdP)
*dbIdP = dbOid;
*dbTablespace = dbform->dattablespace;
/* default locale settings for this database */
if (dbCollate)
- *dbCollate = pstrdup(NameStr(dbform->datcollate));
+ {
+ datum = SysCacheGetAttr(DATABASEOID, tuple, Anum_pg_database_datcollate, &isnull);
+ Assert(!isnull);
+ *dbCollate = TextDatumGetCString(datum);
+ }
if (dbCtype)
- *dbCtype = pstrdup(NameStr(dbform->datctype));
+ {
+ datum = SysCacheGetAttr(DATABASEOID, tuple, Anum_pg_database_datctype, &isnull);
+ Assert(!isnull);
+ *dbCtype = TextDatumGetCString(datum);
+ }
ReleaseSysCache(tuple);
result = true;
break;
*/
if (category == LC_CTYPE)
{
- static char save_lc_ctype[NAMEDATALEN + 20];
+ static char save_lc_ctype[LOCALE_NAME_BUFLEN];
/* copy setlocale() return value before callee invokes it again */
strlcpy(save_lc_ctype, result, sizeof(save_lc_ctype));
{
/* Attempt to set the flags */
HeapTuple tp;
- Form_pg_collation collform;
+ Datum datum;
+ bool isnull;
const char *collcollate;
const char *collctype;
tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collation));
if (!HeapTupleIsValid(tp))
elog(ERROR, "cache lookup failed for collation %u", collation);
- collform = (Form_pg_collation) GETSTRUCT(tp);
- collcollate = NameStr(collform->collcollate);
- collctype = NameStr(collform->collctype);
+ datum = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collcollate, &isnull);
+ Assert(!isnull);
+ collcollate = TextDatumGetCString(datum);
+ datum = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collctype, &isnull);
+ Assert(!isnull);
+ collctype = TextDatumGetCString(datum);
cache_entry->collate_is_c = ((strcmp(collcollate, "C") == 0) ||
(strcmp(collcollate, "POSIX") == 0));
const char *collctype pg_attribute_unused();
struct pg_locale_struct result;
pg_locale_t resultp;
- Datum collversion;
+ Datum datum;
bool isnull;
tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
elog(ERROR, "cache lookup failed for collation %u", collid);
collform = (Form_pg_collation) GETSTRUCT(tp);
- collcollate = NameStr(collform->collcollate);
- collctype = NameStr(collform->collctype);
+ datum = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collcollate, &isnull);
+ Assert(!isnull);
+ collcollate = TextDatumGetCString(datum);
+ datum = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collctype, &isnull);
+ Assert(!isnull);
+ collctype = TextDatumGetCString(datum);
/* We'll fill in the result struct locally before allocating memory */
memset(&result, 0, sizeof(result));
#endif /* not USE_ICU */
}
- collversion = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collversion,
+ datum = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collversion,
&isnull);
if (!isnull)
{
char *actual_versionstr;
char *collversionstr;
+ collversionstr = TextDatumGetCString(datum);
+
actual_versionstr = get_collation_actual_version(collform->collprovider, collcollate);
if (!actual_versionstr)
{
(errmsg("collation \"%s\" has no actual version, but a version was specified",
NameStr(collform->collname))));
}
- collversionstr = TextDatumGetCString(collversion);
if (strcmp(actual_versionstr, collversionstr) != 0)
ereport(WARNING,
#include "storage/sync.h"
#include "tcop/tcopprot.h"
#include "utils/acl.h"
+#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/guc.h"
#include "utils/memutils.h"
{
HeapTuple tup;
Form_pg_database dbform;
+ Datum datum;
+ bool isnull;
char *collate;
char *ctype;
PGC_BACKEND, PGC_S_DYNAMIC_DEFAULT);
/* assign locale variables */
- collate = NameStr(dbform->datcollate);
- ctype = NameStr(dbform->datctype);
+ datum = SysCacheGetAttr(DATABASEOID, tup, Anum_pg_database_datcollate, &isnull);
+ Assert(!isnull);
+ collate = TextDatumGetCString(datum);
+ datum = SysCacheGetAttr(DATABASEOID, tup, Anum_pg_database_datctype, &isnull);
+ Assert(!isnull);
+ ctype = TextDatumGetCString(datum);
if (pg_perm_setlocale(LC_COLLATE, collate) == NULL)
ereport(FATAL,
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 202201201
+#define CATALOG_VERSION_NO 202201271
#endif
char collprovider; /* see constants below */
bool collisdeterministic BKI_DEFAULT(t);
int32 collencoding; /* encoding for this collation; -1 = "all" */
- NameData collcollate; /* LC_COLLATE setting */
- NameData collctype; /* LC_CTYPE setting */
#ifdef CATALOG_VARLEN /* variable-length fields start here */
+ text collcollate BKI_FORCE_NOT_NULL; /* LC_COLLATE setting */
+ text collctype BKI_FORCE_NOT_NULL; /* LC_CTYPE setting */
text collversion BKI_DEFAULT(_null_); /* provider-dependent
* version of collation
* data */
/* character encoding */
int32 encoding;
- /* LC_COLLATE setting */
- NameData datcollate;
-
- /* LC_CTYPE setting */
- NameData datctype;
-
/* allowed as CREATE DATABASE template? */
bool datistemplate;
Oid dattablespace BKI_LOOKUP(pg_tablespace);
#ifdef CATALOG_VARLEN /* variable-length fields start here */
+ /* LC_COLLATE setting */
+ text datcollate BKI_FORCE_NOT_NULL;
+
+ /* LC_CTYPE setting */
+ text datctype BKI_FORCE_NOT_NULL;
+
/* access permissions */
aclitem datacl[1];
#endif
#endif
#endif
+/* use for libc locale names */
+#define LOCALE_NAME_BUFLEN 128
/* GUC settings */
extern char *locale_messages;