1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-14 08:21:07 +03:00

Make LC_COLLATE and LC_CTYPE database-level settings. Collation and

ctype are now more like encoding, stored in new datcollate and datctype
columns in pg_database.

This is a stripped-down version of Radek Strnad's patch, with further
changes by me.
This commit is contained in:
Heikki Linnakangas
2008-09-23 09:20:39 +00:00
parent c52aab5525
commit 61d9674988
30 changed files with 440 additions and 248 deletions

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.318 2008/09/08 16:42:15 tgl Exp $
* $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.319 2008/09/23 09:20:35 heikki Exp $
*
*-------------------------------------------------------------------------
*/
@ -46,7 +46,7 @@
#include "storage/smgr.h"
#include "storage/spin.h"
#include "utils/builtins.h"
#include "utils/pg_locale.h"
#include "utils/guc.h"
#include "utils/ps_status.h"
@ -3847,7 +3847,6 @@ WriteControlFile(void)
{
int fd;
char buffer[PG_CONTROL_SIZE]; /* need not be aligned */
char *localeptr;
/*
* Initialize version and compatibility-check fields
@ -3876,18 +3875,6 @@ WriteControlFile(void)
ControlFile->float4ByVal = FLOAT4PASSBYVAL;
ControlFile->float8ByVal = FLOAT8PASSBYVAL;
ControlFile->localeBuflen = LOCALE_NAME_BUFLEN;
localeptr = setlocale(LC_COLLATE, NULL);
if (!localeptr)
ereport(PANIC,
(errmsg("invalid LC_COLLATE setting")));
StrNCpy(ControlFile->lc_collate, localeptr, LOCALE_NAME_BUFLEN);
localeptr = setlocale(LC_CTYPE, NULL);
if (!localeptr)
ereport(PANIC,
(errmsg("invalid LC_CTYPE setting")));
StrNCpy(ControlFile->lc_ctype, localeptr, LOCALE_NAME_BUFLEN);
/* Contents are protected with a CRC */
INIT_CRC32(ControlFile->crc);
COMP_CRC32(ControlFile->crc,
@ -4126,34 +4113,6 @@ ReadControlFile(void)
" but the server was compiled without USE_FLOAT8_BYVAL."),
errhint("It looks like you need to recompile or initdb.")));
#endif
if (ControlFile->localeBuflen != LOCALE_NAME_BUFLEN)
ereport(FATAL,
(errmsg("database files are incompatible with server"),
errdetail("The database cluster was initialized with LOCALE_NAME_BUFLEN %d,"
" but the server was compiled with LOCALE_NAME_BUFLEN %d.",
ControlFile->localeBuflen, LOCALE_NAME_BUFLEN),
errhint("It looks like you need to recompile or initdb.")));
if (pg_perm_setlocale(LC_COLLATE, ControlFile->lc_collate) == NULL)
ereport(FATAL,
(errmsg("database files are incompatible with operating system"),
errdetail("The database cluster was initialized with LC_COLLATE \"%s\","
" which is not recognized by setlocale().",
ControlFile->lc_collate),
errhint("It looks like you need to initdb or install locale support.")));
if (pg_perm_setlocale(LC_CTYPE, ControlFile->lc_ctype) == NULL)
ereport(FATAL,
(errmsg("database files are incompatible with operating system"),
errdetail("The database cluster was initialized with LC_CTYPE \"%s\","
" which is not recognized by setlocale().",
ControlFile->lc_ctype),
errhint("It looks like you need to initdb or install locale support.")));
/* Make the fixed locale settings visible as GUC variables, too */
SetConfigOption("lc_collate", ControlFile->lc_collate,
PGC_INTERNAL, PGC_S_OVERRIDE);
SetConfigOption("lc_ctype", ControlFile->lc_ctype,
PGC_INTERNAL, PGC_S_OVERRIDE);
}
void

View File

@ -13,7 +13,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.210 2008/08/04 18:03:46 tgl Exp $
* $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.211 2008/09/23 09:20:35 heikki Exp $
*
*-------------------------------------------------------------------------
*/
@ -53,6 +53,7 @@
#include "utils/fmgroids.h"
#include "utils/guc.h"
#include "utils/lsyscache.h"
#include "utils/pg_locale.h"
#include "utils/syscache.h"
#include "utils/tqual.h"
@ -69,7 +70,7 @@ static bool get_db_info(const char *name, LOCKMODE lockmode,
Oid *dbIdP, Oid *ownerIdP,
int *encodingP, bool *dbIsTemplateP, bool *dbAllowConnP,
Oid *dbLastSysOidP, TransactionId *dbFrozenXidP,
Oid *dbTablespace);
Oid *dbTablespace, char **dbCollate, char **dbCtype);
static bool have_createdb_privilege(void);
static void remove_dbtablespaces(Oid db_id);
static bool check_db_file_conflict(Oid db_id);
@ -87,6 +88,8 @@ createdb(const CreatedbStmt *stmt)
Oid src_dboid;
Oid src_owner;
int src_encoding;
char *src_collate;
char *src_ctype;
bool src_istemplate;
bool src_allowconn;
Oid src_lastsysoid;
@ -104,10 +107,14 @@ createdb(const CreatedbStmt *stmt)
DefElem *downer = NULL;
DefElem *dtemplate = NULL;
DefElem *dencoding = NULL;
DefElem *dcollate = NULL;
DefElem *dctype = NULL;
DefElem *dconnlimit = NULL;
char *dbname = stmt->dbname;
char *dbowner = NULL;
const char *dbtemplate = NULL;
char *dbcollate = NULL;
char *dbctype = NULL;
int encoding = -1;
int dbconnlimit = -1;
int ctype_encoding;
@ -152,6 +159,22 @@ createdb(const CreatedbStmt *stmt)
errmsg("conflicting or redundant options")));
dencoding = defel;
}
else if (strcmp(defel->defname, "collate") == 0)
{
if (dcollate)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("conflicting or redundant options")));
dcollate = defel;
}
else if (strcmp(defel->defname, "ctype") == 0)
{
if (dctype)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("conflicting or redundant options")));
dctype = defel;
}
else if (strcmp(defel->defname, "connectionlimit") == 0)
{
if (dconnlimit)
@ -205,6 +228,11 @@ createdb(const CreatedbStmt *stmt)
elog(ERROR, "unrecognized node type: %d",
nodeTag(dencoding->arg));
}
if (dcollate && dcollate->arg)
dbcollate = strVal(dcollate->arg);
if (dctype && dctype->arg)
dbctype = strVal(dctype->arg);
if (dconnlimit && dconnlimit->arg)
dbconnlimit = intVal(dconnlimit->arg);
@ -243,7 +271,8 @@ createdb(const CreatedbStmt *stmt)
if (!get_db_info(dbtemplate, ShareLock,
&src_dboid, &src_owner, &src_encoding,
&src_istemplate, &src_allowconn, &src_lastsysoid,
&src_frozenxid, &src_deftablespace))
&src_frozenxid, &src_deftablespace,
&src_collate, &src_ctype))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_DATABASE),
errmsg("template database \"%s\" does not exist",
@ -262,9 +291,13 @@ createdb(const CreatedbStmt *stmt)
dbtemplate)));
}
/* If encoding is defaulted, use source's encoding */
/* If encoding or locales are defaulted, use source's setting */
if (encoding < 0)
encoding = src_encoding;
if (dbcollate == NULL)
dbcollate = src_collate;
if (dbctype == NULL)
dbctype = src_ctype;
/* Some encodings are client only */
if (!PG_VALID_BE_ENCODING(encoding))
@ -272,6 +305,16 @@ createdb(const CreatedbStmt *stmt)
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("invalid server encoding %d", encoding)));
/* Check that the chosen locales are valid */
if (!check_locale(LC_COLLATE, dbcollate))
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("invalid locale name %s", dbcollate)));
if (!check_locale(LC_CTYPE, dbctype))
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("invalid locale name %s", dbctype)));
/*
* Check whether encoding matches server locale settings. We allow
* mismatch in three cases:
@ -290,7 +333,7 @@ createdb(const CreatedbStmt *stmt)
*
* Note: if you change this policy, fix initdb to match.
*/
ctype_encoding = pg_get_encoding_from_locale(NULL);
ctype_encoding = pg_get_encoding_from_locale(dbctype);
if (!(ctype_encoding == encoding ||
ctype_encoding == PG_SQL_ASCII ||
@ -299,12 +342,32 @@ createdb(const CreatedbStmt *stmt)
#endif
(encoding == PG_SQL_ASCII && superuser())))
ereport(ERROR,
(errmsg("encoding %s does not match server's locale %s",
(errmsg("encoding %s does not match locale %s",
pg_encoding_to_char(encoding),
setlocale(LC_CTYPE, NULL)),
errdetail("The server's LC_CTYPE setting requires encoding %s.",
dbctype),
errdetail("The chosen LC_CTYPE setting requires encoding %s.",
pg_encoding_to_char(ctype_encoding))));
/*
* Check that the new locale is compatible with the source database.
*
* We know that template0 doesn't contain any indexes that depend on
* collation or ctype, so template0 can be used as template for
* any locale.
*/
if (strcmp(dbtemplate, "template0") != 0)
{
if (strcmp(dbcollate, src_collate))
ereport(ERROR,
(errmsg("new collation is incompatible with the collation of the template database (%s)", src_collate),
errhint("Use the same collation as in the template database, or use template0 as template")));
if (strcmp(dbctype, src_ctype))
ereport(ERROR,
(errmsg("new ctype is incompatible with the ctype of the template database (%s)", src_ctype),
errhint("Use the same ctype as in the template database, or use template0 as template")));
}
/* Resolve default tablespace for new database */
if (dtablespacename && dtablespacename->arg)
{
@ -421,6 +484,10 @@ createdb(const CreatedbStmt *stmt)
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_datistemplate - 1] = BoolGetDatum(false);
new_record[Anum_pg_database_datallowconn - 1] = BoolGetDatum(true);
new_record[Anum_pg_database_datconnlimit - 1] = Int32GetDatum(dbconnlimit);
@ -629,7 +696,7 @@ dropdb(const char *dbname, bool missing_ok)
pgdbrel = heap_open(DatabaseRelationId, RowExclusiveLock);
if (!get_db_info(dbname, AccessExclusiveLock, &db_id, NULL, NULL,
&db_istemplate, NULL, NULL, NULL, NULL))
&db_istemplate, NULL, NULL, NULL, NULL, NULL, NULL))
{
if (!missing_ok)
{
@ -781,7 +848,7 @@ RenameDatabase(const char *oldname, const char *newname)
rel = heap_open(DatabaseRelationId, RowExclusiveLock);
if (!get_db_info(oldname, AccessExclusiveLock, &db_id, NULL, NULL,
NULL, NULL, NULL, NULL, NULL))
NULL, NULL, NULL, NULL, NULL, NULL, NULL))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_DATABASE),
errmsg("database \"%s\" does not exist", oldname)));
@ -1168,7 +1235,7 @@ get_db_info(const char *name, LOCKMODE lockmode,
Oid *dbIdP, Oid *ownerIdP,
int *encodingP, bool *dbIsTemplateP, bool *dbAllowConnP,
Oid *dbLastSysOidP, TransactionId *dbFrozenXidP,
Oid *dbTablespace)
Oid *dbTablespace, char **dbCollate, char **dbCtype)
{
bool result = false;
Relation relation;
@ -1259,6 +1326,11 @@ get_db_info(const char *name, LOCKMODE lockmode,
/* default tablespace for this database */
if (dbTablespace)
*dbTablespace = dbform->dattablespace;
/* default locale settings for this database */
if (dbCollate)
*dbCollate = pstrdup(NameStr(dbform->datcollate));
if (dbCtype)
*dbCtype = pstrdup(NameStr(dbform->datctype));
ReleaseSysCache(tuple);
result = true;
break;

View File

@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.623 2008/09/11 15:27:30 tgl Exp $
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.624 2008/09/23 09:20:35 heikki Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@ -398,7 +398,7 @@ static TypeName *TableFuncTypeName(List *columns);
CLUSTER COALESCE COLLATE COLUMN COMMENT COMMIT
COMMITTED CONCURRENTLY CONFIGURATION CONNECTION CONSTRAINT CONSTRAINTS
CONTENT_P CONTINUE_P CONVERSION_P COPY COST CREATE CREATEDB
CREATEROLE CREATEUSER CROSS CSV CURRENT_P CURRENT_DATE CURRENT_ROLE
CREATEROLE CREATEUSER CROSS CSV CTYPE CURRENT_P CURRENT_DATE CURRENT_ROLE
CURRENT_TIME CURRENT_TIMESTAMP CURRENT_USER CURSOR CYCLE
DATABASE DAY_P DEALLOCATE DEC DECIMAL_P DECLARE DEFAULT DEFAULTS
@ -5458,6 +5458,22 @@ createdb_opt_item:
{
$$ = makeDefElem("encoding", NULL);
}
| COLLATE opt_equal Sconst
{
$$ = makeDefElem("collate", (Node *)makeString($3));
}
| COLLATE opt_equal DEFAULT
{
$$ = makeDefElem("collate", NULL);
}
| CTYPE opt_equal Sconst
{
$$ = makeDefElem("ctype", (Node *)makeString($3));
}
| CTYPE opt_equal DEFAULT
{
$$ = makeDefElem("ctype", NULL);
}
| CONNECTION LIMIT opt_equal SignedIconst
{
$$ = makeDefElem("connectionlimit", (Node *)makeInteger($4));
@ -9216,6 +9232,7 @@ unreserved_keyword:
| CREATEROLE
| CREATEUSER
| CSV
| CTYPE
| CURRENT_P
| CURSOR
| CYCLE

View File

@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/keywords.c,v 1.200 2008/08/29 13:02:32 petere Exp $
* $PostgreSQL: pgsql/src/backend/parser/keywords.c,v 1.201 2008/09/23 09:20:36 heikki Exp $
*
*-------------------------------------------------------------------------
*/
@ -114,6 +114,7 @@ const ScanKeyword ScanKeywords[] = {
{"createuser", CREATEUSER, UNRESERVED_KEYWORD},
{"cross", CROSS, TYPE_FUNC_NAME_KEYWORD},
{"csv", CSV, UNRESERVED_KEYWORD},
{"ctype", CTYPE, UNRESERVED_KEYWORD},
{"current", CURRENT_P, UNRESERVED_KEYWORD},
{"current_date", CURRENT_DATE, RESERVED_KEYWORD},
{"current_role", CURRENT_ROLE, RESERVED_KEYWORD},

View File

@ -37,7 +37,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.563 2008/09/15 12:32:57 mha Exp $
* $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.564 2008/09/23 09:20:36 heikki Exp $
*
* NOTES
*
@ -403,8 +403,8 @@ typedef struct
char my_exec_path[MAXPGPATH];
char pkglib_path[MAXPGPATH];
char ExtraOptions[MAXPGPATH];
char lc_collate[LOCALE_NAME_BUFLEN];
char lc_ctype[LOCALE_NAME_BUFLEN];
char lc_collate[NAMEDATALEN];
char lc_ctype[NAMEDATALEN];
} BackendParameters;
static void read_backend_variables(char *id, Port *port);
@ -4294,8 +4294,8 @@ save_backend_variables(BackendParameters * param, Port *port,
strlcpy(param->ExtraOptions, ExtraOptions, MAXPGPATH);
strlcpy(param->lc_collate, setlocale(LC_COLLATE, NULL), LOCALE_NAME_BUFLEN);
strlcpy(param->lc_ctype, setlocale(LC_CTYPE, NULL), LOCALE_NAME_BUFLEN);
strlcpy(param->lc_collate, setlocale(LC_COLLATE, NULL), NAMEDATALEN);
strlcpy(param->lc_ctype, setlocale(LC_CTYPE, NULL), NAMEDATALEN);
return true;
}

View File

@ -4,7 +4,7 @@
*
* Portions Copyright (c) 2002-2008, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/backend/utils/adt/pg_locale.c,v 1.41 2008/05/19 18:08:16 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/pg_locale.c,v 1.42 2008/09/23 09:20:36 heikki Exp $
*
*-----------------------------------------------------------------------
*/
@ -76,7 +76,7 @@ static bool CurrentLCTimeValid = false;
/* Environment variable storage area */
#define LC_ENV_BUFSIZE (LOCALE_NAME_BUFLEN + 20)
#define LC_ENV_BUFSIZE (NAMEDATALEN + 20)
static char lc_collate_envbuf[LC_ENV_BUFSIZE];
static char lc_ctype_envbuf[LC_ENV_BUFSIZE];
@ -189,6 +189,31 @@ pg_perm_setlocale(int category, const char *locale)
}
/*
* Is the locale name valid for the locale category?
*/
bool
check_locale(int category, const char *value)
{
char *save;
bool ret;
save = setlocale(category, NULL);
if (!save)
return false; /* won't happen, we hope */
/* save may be pointing at a modifiable scratch variable, see above */
save = pstrdup(save);
/* set the locale with setlocale, to see if it accepts it. */
ret = (setlocale(category, value) != NULL);
setlocale(category, save); /* assume this won't fail */
pfree(save);
return ret;
}
/* GUC assign hooks */
/*
@ -203,21 +228,9 @@ pg_perm_setlocale(int category, const char *locale)
static const char *
locale_xxx_assign(int category, const char *value, bool doit, GucSource source)
{
char *save;
save = setlocale(category, NULL);
if (!save)
return NULL; /* won't happen, we hope */
/* save may be pointing at a modifiable scratch variable, see above */
save = pstrdup(save);
if (!setlocale(category, value))
if (!check_locale(category, value))
value = NULL; /* set failure return marker */
setlocale(category, save); /* assume this won't fail */
pfree(save);
/* need to reload cache next time? */
if (doit && value != NULL)
{

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.185 2008/09/11 14:01:09 alvherre Exp $
* $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.186 2008/09/23 09:20:36 heikki Exp $
*
*
*-------------------------------------------------------------------------
@ -159,6 +159,8 @@ CheckMyDatabase(const char *name, bool am_superuser)
{
HeapTuple tup;
Form_pg_database dbform;
char *collate;
char *ctype;
/* Fetch our real pg_database row */
tup = SearchSysCache(DATABASEOID,
@ -240,6 +242,28 @@ CheckMyDatabase(const char *name, bool am_superuser)
/* If we have no other source of client_encoding, use server encoding */
SetConfigOption("client_encoding", GetDatabaseEncodingName(),
PGC_BACKEND, PGC_S_DEFAULT);
/* assign locale variables */
collate = NameStr(dbform->datcollate);
ctype = NameStr(dbform->datctype);
if (setlocale(LC_COLLATE, collate) == NULL)
ereport(FATAL,
(errmsg("database locale is incompatible with operating system"),
errdetail("The database was initialized with LC_COLLATE \"%s\", "
" which is not recognized by setlocale().", collate),
errhint("Recreate the database with another locale or install the missing locale.")));
if (setlocale(LC_CTYPE, ctype) == NULL)
ereport(FATAL,
(errmsg("database locale is incompatible with operating system"),
errdetail("The database was initialized with LC_CTYPE \"%s\", "
" which is not recognized by setlocale().", ctype),
errhint("Recreate the database with another locale or install the missing locale.")));
/* Make the locale settings visible as GUC variables, too */
SetConfigOption("lc_collate", collate, PGC_INTERNAL, PGC_S_OVERRIDE);
SetConfigOption("lc_ctype", ctype, PGC_INTERNAL, PGC_S_OVERRIDE);
/*
* Lastly, set up any database-specific configuration variables.

View File

@ -42,7 +42,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
* Portions taken from FreeBSD.
*
* $PostgreSQL: pgsql/src/bin/initdb/initdb.c,v 1.159 2008/08/05 12:09:30 mha Exp $
* $PostgreSQL: pgsql/src/bin/initdb/initdb.c,v 1.160 2008/09/23 09:20:37 heikki Exp $
*
*-------------------------------------------------------------------------
*/
@ -1353,6 +1353,10 @@ bootstrap_template1(char *short_version)
bki_lines = replace_token(bki_lines, "ENCODING", encodingid);
bki_lines = replace_token(bki_lines, "LC_COLLATE", lc_collate);
bki_lines = replace_token(bki_lines, "LC_CTYPE", lc_ctype);
/*
* Pass correct LC_xxx environment to bootstrap.
*
@ -2179,6 +2183,8 @@ locale_date_order(const char *locale)
/*
* check if given string is a valid locale specifier
*
* this should match the backend check_locale() function
*/
static bool
chklocale(const char *locale)
@ -2378,12 +2384,12 @@ usage(const char *progname)
printf(_("\nOptions:\n"));
printf(_(" [-D, --pgdata=]DATADIR location for this database cluster\n"));
printf(_(" -E, --encoding=ENCODING set default encoding for new databases\n"));
printf(_(" --locale=LOCALE initialize database cluster with given locale\n"));
printf(_(" --locale=LOCALE set default locale for new databases\n"));
printf(_(" --lc-collate, --lc-ctype, --lc-messages=LOCALE\n"
" --lc-monetary, --lc-numeric, --lc-time=LOCALE\n"
" initialize database cluster with given locale\n"
" in the respective category (default taken from\n"
" environment)\n"));
" set default locale in the respective\n"
" category for new databases (default\n"
" taken from environment)\n"));
printf(_(" --no-locale equivalent to --locale=C\n"));
printf(_(" -T, --text-search-config=CFG\n"
" default text search configuration\n"));

View File

@ -6,7 +6,7 @@
* copyright (c) Oliver Elphick <olly@lfix.co.uk>, 2001;
* licence: BSD
*
* $PostgreSQL: pgsql/src/bin/pg_controldata/pg_controldata.c,v 1.39 2008/04/21 00:26:46 tgl Exp $
* $PostgreSQL: pgsql/src/bin/pg_controldata/pg_controldata.c,v 1.40 2008/09/23 09:20:37 heikki Exp $
*/
#include "postgres_fe.h"
@ -220,12 +220,5 @@ main(int argc, char *argv[])
(ControlFile.float4ByVal ? _("by value") : _("by reference")));
printf(_("Float8 argument passing: %s\n"),
(ControlFile.float8ByVal ? _("by value") : _("by reference")));
printf(_("Maximum length of locale name: %u\n"),
ControlFile.localeBuflen);
printf(_("LC_COLLATE: %s\n"),
ControlFile.lc_collate);
printf(_("LC_CTYPE: %s\n"),
ControlFile.lc_ctype);
return 0;
}

View File

@ -12,7 +12,7 @@
* by PostgreSQL
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.500 2008/09/08 15:26:23 tgl Exp $
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.501 2008/09/23 09:20:37 heikki Exp $
*
*-------------------------------------------------------------------------
*/
@ -1542,12 +1542,16 @@ dumpDatabase(Archive *AH)
i_oid,
i_dba,
i_encoding,
i_collate,
i_ctype,
i_tablespace;
CatalogId dbCatId;
DumpId dbDumpId;
const char *datname,
*dba,
*encoding,
*collate,
*ctype,
*tablespace;
datname = PQdb(g_conn);
@ -1559,11 +1563,26 @@ dumpDatabase(Archive *AH)
selectSourceSchema("pg_catalog");
/* Get the database owner and parameters from pg_database */
if (g_fout->remoteVersion >= 80200)
if (g_fout->remoteVersion >= 80400)
{
appendPQExpBuffer(dbQry, "SELECT tableoid, oid, "
"(%s datdba) as dba, "
"pg_encoding_to_char(encoding) as encoding, "
"datcollate, datctype, "
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) as tablespace, "
"shobj_description(oid, 'pg_database') as description "
"FROM pg_database "
"WHERE datname = ",
username_subquery);
appendStringLiteralAH(dbQry, datname, AH);
}
else if (g_fout->remoteVersion >= 80200)
{
appendPQExpBuffer(dbQry, "SELECT tableoid, oid, "
"(%s datdba) as dba, "
"pg_encoding_to_char(encoding) as encoding, "
"NULL as datcollate, NULL as datctype, "
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) as tablespace, "
"shobj_description(oid, 'pg_database') as description "
@ -1577,6 +1596,7 @@ dumpDatabase(Archive *AH)
appendPQExpBuffer(dbQry, "SELECT tableoid, oid, "
"(%s datdba) as dba, "
"pg_encoding_to_char(encoding) as encoding, "
"NULL as datcollate, NULL as datctype, "
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) as tablespace "
"FROM pg_database "
"WHERE datname = ",
@ -1588,6 +1608,7 @@ dumpDatabase(Archive *AH)
appendPQExpBuffer(dbQry, "SELECT tableoid, oid, "
"(%s datdba) as dba, "
"pg_encoding_to_char(encoding) as encoding, "
"NULL as datcollate, NULL as datctype, "
"NULL as tablespace "
"FROM pg_database "
"WHERE datname = ",
@ -1601,6 +1622,7 @@ dumpDatabase(Archive *AH)
"oid, "
"(%s datdba) as dba, "
"pg_encoding_to_char(encoding) as encoding, "
"NULL as datcollate, NULL as datctype, "
"NULL as tablespace "
"FROM pg_database "
"WHERE datname = ",
@ -1631,12 +1653,16 @@ dumpDatabase(Archive *AH)
i_oid = PQfnumber(res, "oid");
i_dba = PQfnumber(res, "dba");
i_encoding = PQfnumber(res, "encoding");
i_collate = PQfnumber(res, "collate");
i_ctype = PQfnumber(res, "ctype");
i_tablespace = PQfnumber(res, "tablespace");
dbCatId.tableoid = atooid(PQgetvalue(res, 0, i_tableoid));
dbCatId.oid = atooid(PQgetvalue(res, 0, i_oid));
dba = PQgetvalue(res, 0, i_dba);
encoding = PQgetvalue(res, 0, i_encoding);
collate = PQgetvalue(res, 0, i_collate);
ctype = PQgetvalue(res, 0, i_ctype);
tablespace = PQgetvalue(res, 0, i_tablespace);
appendPQExpBuffer(creaQry, "CREATE DATABASE %s WITH TEMPLATE = template0",
@ -1646,6 +1672,16 @@ dumpDatabase(Archive *AH)
appendPQExpBuffer(creaQry, " ENCODING = ");
appendStringLiteralAH(creaQry, encoding, AH);
}
if (strlen(collate) > 0)
{
appendPQExpBuffer(creaQry, " COLLATE = ");
appendStringLiteralAH(creaQry, collate, AH);
}
if (strlen(ctype) > 0)
{
appendPQExpBuffer(creaQry, " CTYPE = ");
appendStringLiteralAH(creaQry, ctype, AH);
}
if (strlen(tablespace) > 0 && strcmp(tablespace, "pg_default") != 0)
appendPQExpBuffer(creaQry, " TABLESPACE = %s",
fmtId(tablespace));

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dumpall.c,v 1.106 2008/08/29 17:28:43 alvherre Exp $
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dumpall.c,v 1.107 2008/09/23 09:20:38 heikki Exp $
*
*-------------------------------------------------------------------------
*/
@ -925,11 +925,22 @@ dumpCreateDB(PGconn *conn)
fprintf(OPF, "--\n-- Database creation\n--\n\n");
if (server_version >= 80100)
if (server_version >= 80400)
res = executeQuery(conn,
"SELECT datname, "
"coalesce(rolname, (select rolname from pg_authid where oid=(select datdba from pg_database where datname='template0'))), "
"pg_encoding_to_char(d.encoding), "
"datcollate, datctype, "
"datistemplate, datacl, datconnlimit, "
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = d.dattablespace) AS dattablespace "
"FROM pg_database d LEFT JOIN pg_authid u ON (datdba = u.oid) "
"WHERE datallowconn ORDER BY 1");
else if (server_version >= 80100)
res = executeQuery(conn,
"SELECT datname, "
"coalesce(rolname, (select rolname from pg_authid where oid=(select datdba from pg_database where datname='template0'))), "
"pg_encoding_to_char(d.encoding), "
"null::text AS datcollate, null::text AS datctype, "
"datistemplate, datacl, datconnlimit, "
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = d.dattablespace) AS dattablespace "
"FROM pg_database d LEFT JOIN pg_authid u ON (datdba = u.oid) "
@ -939,6 +950,7 @@ dumpCreateDB(PGconn *conn)
"SELECT datname, "
"coalesce(usename, (select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), "
"pg_encoding_to_char(d.encoding), "
"null::text AS datcollate, null::text AS datctype, "
"datistemplate, datacl, -1 as datconnlimit, "
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = d.dattablespace) AS dattablespace "
"FROM pg_database d LEFT JOIN pg_shadow u ON (datdba = usesysid) "
@ -948,6 +960,7 @@ dumpCreateDB(PGconn *conn)
"SELECT datname, "
"coalesce(usename, (select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), "
"pg_encoding_to_char(d.encoding), "
"null::text AS datcollate, null::text AS datctype, "
"datistemplate, datacl, -1 as datconnlimit, "
"'pg_default' AS dattablespace "
"FROM pg_database d LEFT JOIN pg_shadow u ON (datdba = usesysid) "
@ -959,6 +972,7 @@ dumpCreateDB(PGconn *conn)
"(select usename from pg_shadow where usesysid=datdba), "
"(select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), "
"pg_encoding_to_char(d.encoding), "
"null::text AS datcollate, null::text AS datctype, "
"datistemplate, '' as datacl, -1 as datconnlimit, "
"'pg_default' AS dattablespace "
"FROM pg_database d "
@ -973,6 +987,7 @@ dumpCreateDB(PGconn *conn)
"SELECT datname, "
"(select usename from pg_shadow where usesysid=datdba), "
"pg_encoding_to_char(d.encoding), "
"null::text AS datcollate, null::text AS datctype, "
"'f' as datistemplate, "
"'' as datacl, -1 as datconnlimit, "
"'pg_default' AS dattablespace "
@ -985,10 +1000,12 @@ dumpCreateDB(PGconn *conn)
char *dbname = PQgetvalue(res, i, 0);
char *dbowner = PQgetvalue(res, i, 1);
char *dbencoding = PQgetvalue(res, i, 2);
char *dbistemplate = PQgetvalue(res, i, 3);
char *dbacl = PQgetvalue(res, i, 4);
char *dbconnlimit = PQgetvalue(res, i, 5);
char *dbtablespace = PQgetvalue(res, i, 6);
char *dbcollate = PQgetvalue(res, i, 3);
char *dbctype = PQgetvalue(res, i, 4);
char *dbistemplate = PQgetvalue(res, i, 5);
char *dbacl = PQgetvalue(res, i, 6);
char *dbconnlimit = PQgetvalue(res, i, 7);
char *dbtablespace = PQgetvalue(res, i, 8);
char *fdbname;
fdbname = strdup(fmtId(dbname));
@ -1016,6 +1033,18 @@ dumpCreateDB(PGconn *conn)
appendPQExpBuffer(buf, " ENCODING = ");
appendStringLiteralConn(buf, dbencoding, conn);
if (strlen(dbcollate) != 0)
{
appendPQExpBuffer(buf, " COLLATE = ");
appendStringLiteralConn(buf, dbcollate, conn);
}
if (strlen(dbctype) != 0)
{
appendPQExpBuffer(buf, " CTYPE = ");
appendStringLiteralConn(buf, dbctype, conn);
}
/*
* Output tablespace if it isn't the default. For default, it
* uses the default from the template database. If tablespace is

View File

@ -23,7 +23,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/bin/pg_resetxlog/pg_resetxlog.c,v 1.65 2008/04/21 00:26:46 tgl Exp $
* $PostgreSQL: pgsql/src/bin/pg_resetxlog/pg_resetxlog.c,v 1.66 2008/09/23 09:20:38 heikki Exp $
*
*-------------------------------------------------------------------------
*/
@ -493,22 +493,6 @@ GuessControlValues(void)
#endif
ControlFile.float4ByVal = FLOAT4PASSBYVAL;
ControlFile.float8ByVal = FLOAT8PASSBYVAL;
ControlFile.localeBuflen = LOCALE_NAME_BUFLEN;
localeptr = setlocale(LC_COLLATE, "");
if (!localeptr)
{
fprintf(stderr, _("%s: invalid LC_COLLATE setting\n"), progname);
exit(1);
}
strlcpy(ControlFile.lc_collate, localeptr, sizeof(ControlFile.lc_collate));
localeptr = setlocale(LC_CTYPE, "");
if (!localeptr)
{
fprintf(stderr, _("%s: invalid LC_CTYPE setting\n"), progname);
exit(1);
}
strlcpy(ControlFile.lc_ctype, localeptr, sizeof(ControlFile.lc_ctype));
/*
* XXX eventually, should try to grovel through old XLOG to develop more
@ -584,12 +568,6 @@ PrintControlValues(bool guessed)
(ControlFile.float4ByVal ? _("by value") : _("by reference")));
printf(_("Float8 argument passing: %s\n"),
(ControlFile.float8ByVal ? _("by value") : _("by reference")));
printf(_("Maximum length of locale name: %u\n"),
ControlFile.localeBuflen);
printf(_("LC_COLLATE: %s\n"),
ControlFile.lc_collate);
printf(_("LC_CTYPE: %s\n"),
ControlFile.lc_ctype);
}

View File

@ -8,7 +8,7 @@
*
* Copyright (c) 2000-2008, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/bin/psql/describe.c,v 1.184 2008/07/18 04:20:24 tgl Exp $
* $PostgreSQL: pgsql/src/bin/psql/describe.c,v 1.185 2008/09/23 09:20:38 heikki Exp $
*/
#include "postgres_fe.h"
@ -454,11 +454,18 @@ listAllDbs(bool verbose)
printfPQExpBuffer(&buf,
"SELECT d.datname as \"%s\",\n"
" pg_catalog.pg_get_userbyid(d.datdba) as \"%s\",\n"
" pg_catalog.pg_encoding_to_char(d.encoding) as \"%s\",\n"
" d.datacl as \"%s\"",
" pg_catalog.pg_encoding_to_char(d.encoding) as \"%s\",\n",
gettext_noop("Name"),
gettext_noop("Owner"),
gettext_noop("Encoding"),
gettext_noop("Encoding"));
if (pset.sversion >= 80400)
appendPQExpBuffer(&buf,
" d.datcollate as \"%s\",\n"
" d.datctype as \"%s\",\n",
gettext_noop("Collation"),
gettext_noop("Ctype"));
appendPQExpBuffer(&buf,
" d.datacl as \"%s\"",
gettext_noop("Access Privileges"));
if (verbose && pset.sversion >= 80200)
appendPQExpBuffer(&buf,

View File

@ -5,7 +5,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/bin/scripts/createdb.c,v 1.26 2008/01/01 19:45:56 momjian Exp $
* $PostgreSQL: pgsql/src/bin/scripts/createdb.c,v 1.27 2008/09/23 09:20:38 heikki Exp $
*
*-------------------------------------------------------------------------
*/
@ -32,6 +32,8 @@ main(int argc, char *argv[])
{"tablespace", required_argument, NULL, 'D'},
{"template", required_argument, NULL, 'T'},
{"encoding", required_argument, NULL, 'E'},
{"lc-collate", required_argument, NULL, 1},
{"lc-ctype", required_argument, NULL, 2},
{NULL, 0, NULL, 0}
};
@ -50,6 +52,8 @@ main(int argc, char *argv[])
char *tablespace = NULL;
char *template = NULL;
char *encoding = NULL;
char *lc_collate = NULL;
char *lc_ctype = NULL;
PQExpBufferData sql;
@ -95,6 +99,12 @@ main(int argc, char *argv[])
case 'E':
encoding = optarg;
break;
case 1:
lc_collate = optarg;
break;
case 2:
lc_ctype = optarg;
break;
default:
fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
exit(1);
@ -152,6 +162,11 @@ main(int argc, char *argv[])
appendPQExpBuffer(&sql, " ENCODING '%s'", encoding);
if (template)
appendPQExpBuffer(&sql, " TEMPLATE %s", fmtId(template));
if (lc_collate)
appendPQExpBuffer(&sql, " COLLATE '%s'", lc_collate);
if (lc_ctype)
appendPQExpBuffer(&sql, " CTYPE '%s'", lc_ctype);
appendPQExpBuffer(&sql, ";\n");
conn = connectDatabase(strcmp(dbname, "postgres") == 0 ? "template1" : "postgres",
@ -209,6 +224,8 @@ help(const char *progname)
printf(_("\nOptions:\n"));
printf(_(" -D, --tablespace=TABLESPACE default tablespace for the database\n"));
printf(_(" -E, --encoding=ENCODING encoding for the database\n"));
printf(_(" --lc-collate=LOCALE LC_COLLATE setting for the database\n"));
printf(_(" --lc-ctype=LOCALE LC_CTYPE setting for the database\n"));
printf(_(" -O, --owner=OWNER database user to own the new database\n"));
printf(_(" -T, --template=TEMPLATE template database to copy\n"));
printf(_(" -e, --echo show the commands being sent to the server\n"));

View File

@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.487 2008/09/19 19:03:40 tgl Exp $
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.488 2008/09/23 09:20:38 heikki Exp $
*
*-------------------------------------------------------------------------
*/
@ -53,6 +53,6 @@
*/
/* yyyymmddN */
#define CATALOG_VERSION_NO 200809191
#define CATALOG_VERSION_NO 200809231
#endif

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/pg_control.h,v 1.41 2008/04/21 00:26:47 tgl Exp $
* $PostgreSQL: pgsql/src/include/catalog/pg_control.h,v 1.42 2008/09/23 09:20:39 heikki Exp $
*
*-------------------------------------------------------------------------
*/
@ -21,7 +21,7 @@
/* Version identifier for this pg_control format */
#define PG_CONTROL_VERSION 842
#define PG_CONTROL_VERSION 843
/*
* Body of CheckPoint XLOG records. This is declared here because we keep
@ -59,15 +59,12 @@ typedef enum DBState
DB_IN_PRODUCTION
} DBState;
#define LOCALE_NAME_BUFLEN 128
/*
* Contents of pg_control.
*
* NOTE: try to keep this under 512 bytes so that it will fit on one physical
* sector of typical disk drives. This reduces the odds of corruption due to
* power failure midway through a write. Currently it fits comfortably,
* but we could probably reduce LOCALE_NAME_BUFLEN if things get tight.
* power failure midway through a write.
*/
typedef struct ControlFileData
@ -144,11 +141,6 @@ typedef struct ControlFileData
bool float4ByVal; /* float4 pass-by-value? */
bool float8ByVal; /* float8, int8, etc pass-by-value? */
/* active locales */
uint32 localeBuflen;
char lc_collate[LOCALE_NAME_BUFLEN];
char lc_ctype[LOCALE_NAME_BUFLEN];
/* CRC of all above ... MUST BE LAST! */
pg_crc32 crc;
} ControlFileData;

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/pg_database.h,v 1.47 2008/03/27 03:57:34 tgl Exp $
* $PostgreSQL: pgsql/src/include/catalog/pg_database.h,v 1.48 2008/09/23 09:20:39 heikki Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
@ -33,6 +33,8 @@ CATALOG(pg_database,1262) BKI_SHARED_RELATION
NameData datname; /* database name */
Oid datdba; /* owner of database */
int4 encoding; /* character encoding */
NameData datcollate; /* LC_COLLATE setting */
NameData datctype; /* LC_CTYPE setting */
bool datistemplate; /* allowed as CREATE DATABASE template? */
bool datallowconn; /* new connections allowed? */
int4 datconnlimit; /* max connections allowed (-1=no limit) */
@ -54,20 +56,22 @@ typedef FormData_pg_database *Form_pg_database;
* compiler constants for pg_database
* ----------------
*/
#define Natts_pg_database 11
#define Natts_pg_database 13
#define Anum_pg_database_datname 1
#define Anum_pg_database_datdba 2
#define Anum_pg_database_encoding 3
#define Anum_pg_database_datistemplate 4
#define Anum_pg_database_datallowconn 5
#define Anum_pg_database_datconnlimit 6
#define Anum_pg_database_datlastsysoid 7
#define Anum_pg_database_datfrozenxid 8
#define Anum_pg_database_dattablespace 9
#define Anum_pg_database_datconfig 10
#define Anum_pg_database_datacl 11
#define Anum_pg_database_datcollate 4
#define Anum_pg_database_datctype 5
#define Anum_pg_database_datistemplate 6
#define Anum_pg_database_datallowconn 7
#define Anum_pg_database_datconnlimit 8
#define Anum_pg_database_datlastsysoid 9
#define Anum_pg_database_datfrozenxid 10
#define Anum_pg_database_dattablespace 11
#define Anum_pg_database_datconfig 12
#define Anum_pg_database_datacl 13
DATA(insert OID = 1 ( template1 PGUID ENCODING t t -1 0 0 1663 _null_ _null_ ));
DATA(insert OID = 1 ( template1 PGUID ENCODING "LC_COLLATE" "LC_CTYPE" t t -1 0 0 1663 _null_ _null_));
SHDESCR("default template database");
#define TemplateDbOid 1

View File

@ -2,7 +2,7 @@
*
* PostgreSQL locale utilities
*
* $PostgreSQL: pgsql/src/include/utils/pg_locale.h,v 1.25 2008/05/19 18:08:16 tgl Exp $
* $PostgreSQL: pgsql/src/include/utils/pg_locale.h,v 1.26 2008/09/23 09:20:39 heikki Exp $
*
* Copyright (c) 2002-2008, PostgreSQL Global Development Group
*
@ -39,6 +39,7 @@ extern const char *locale_numeric_assign(const char *value,
extern const char *locale_time_assign(const char *value,
bool doit, GucSource source);
extern bool check_locale(int category, const char *locale);
extern char *pg_perm_setlocale(int category, const char *locale);
extern bool lc_collate_is_c(void);

View File

@ -1,4 +1,4 @@
/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/preproc.y,v 1.371 2008/08/20 14:09:16 meskes Exp $ */
/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/preproc.y,v 1.372 2008/09/23 09:20:39 heikki Exp $ */
/* Copyright comment */
%{
@ -428,7 +428,7 @@ add_typedef(char *name, char * dimension, char * length, enum ECPGttype type_enu
CLUSTER COALESCE COLLATE COLUMN COMMENT COMMIT
COMMITTED CONCURRENTLY CONFIGURATION CONNECTION CONSTRAINT CONSTRAINTS
CONTENT_P CONTINUE_P CONVERSION_P COPY COST CREATE CREATEDB
CREATEROLE CREATEUSER CROSS CSV CURRENT_P CURRENT_DATE CURRENT_ROLE
CREATEROLE CREATEUSER CROSS CSV CTYPE CURRENT_P CURRENT_DATE CURRENT_ROLE
CURRENT_TIME CURRENT_TIMESTAMP CURRENT_USER CURSOR CYCLE
DATABASE DAY_P DEALLOCATE DEC DECIMAL_P DECLARE DEFAULT DEFAULTS