Commit bbea3643 authored by Tom Lane's avatar Tom Lane

Store current LC_COLLATE and LC_CTYPE settings in pg_control during initdb;

re-adopt these settings at every postmaster or standalone-backend startup.
This should fix problems with indexes becoming corrupt due to failure to
provide consistent locale environment for postmaster at all times.  Also,
refuse to start up a non-locale-enabled compilation in a database originally
initdb'd with a non-C locale.  Suppress LIKE index optimization if locale
is not "C" or "POSIX" (are there any other locales where it's safe?).
Issue NOTICE during initdb if selected locale disables LIKE optimization.
parent 0432ce99
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v 1.38 2000/11/22 01:41:12 momjian Exp $
$Header: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v 1.39 2000/11/25 20:33:47 tgl Exp $
-->
<Chapter Id="runtime">
......@@ -79,9 +79,9 @@ $Header: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v 1.38 2000/11/22 01:41:12 mom
<command>initdb</command> will attempt to create the directory you
specify if it does not already exist. It is likely that it won't
have the permission to do so (if you followed our advice and
created an unprivileged account). In that case you can create the
directory yourself (as root) and transfer ownership of it or grant
write access to it. Here is how this might work:
created an unprivileged account). In that case you should create the
directory yourself (as root) and transfer ownership of it to the
Postgres user account. Here is how this might work:
<screen>
root# <userinput>mkdir /usr/local/pgsql/data</userinput>
root# <userinput>chown postgres /usr/local/pgsql/data</userinput>
......@@ -101,6 +101,28 @@ postgres&gt; <userinput>initdb -D /usr/local/pgsql/data</userinput>
access. <command>initdb</command> therefore revokes access
permissions from everyone but the Postgres user account.
</para>
<para>
One surprise you might encounter while running <command>initdb</command> is
a notice similar to this one:
<screen>
NOTICE: Initializing database with en_US collation order.
This locale setting will prevent use of index optimization for
LIKE and regexp searches. If you are concerned about speed of
such queries, you may wish to set LC_COLLATE to "C" and
re-initdb. For more information see the Administrator's Guide.
</screen>
This notice is intended to warn you that the currently selected locale
will cause indexes to be sorted in an order that prevents them from
being used for LIKE and regular-expression searches. If you need
good performance of such searches, you should set your current locale
to "C" and re-run <command>initdb</command>. On most systems, setting the
current locale is done by changing the value of the environment variable
<literal>LC_ALL</literal> or <literal>LANG</literal>. The sort order used
within a particular database cluster is set by <command>initdb</command>
and cannot be changed later, short of dumping all data, re-initdb,
reload data. So it's important to make this choice correctly now.
</para>
</sect1>
<sect1 id="postmaster-start">
......
This diff is collapsed.
......@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.100 2000/11/21 21:15:59 petere Exp $
* $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.101 2000/11/25 20:33:51 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -321,6 +321,8 @@ BootstrapMain(int argc, char *argv[])
}
}
XLOGPathInit();
BaseInit();
if (!IsUnderPostmaster)
......@@ -333,8 +335,6 @@ BootstrapMain(int argc, char *argv[])
/*
* XLOG operations
*/
snprintf(XLogDir, MAXPGPATH, "%s/pg_xlog", DataDir);
snprintf(ControlFilePath, MAXPGPATH, "%s/global/pg_control", DataDir);
SetProcessingMode(NormalProcessing);
if (xlogop == BS_XLOG_NOP)
StartupXLOG();
......
......@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.98 2000/11/16 22:30:24 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.99 2000/11/25 20:33:51 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -1746,56 +1746,68 @@ match_special_index_operator(Expr *clause, Oid opclass, Oid relam,
case OID_BPCHAR_LIKE_OP:
case OID_VARCHAR_LIKE_OP:
case OID_NAME_LIKE_OP:
/* the right-hand const is type text for all of these */
patt = DatumGetCString(DirectFunctionCall1(textout,
constvalue));
isIndexable = pattern_fixed_prefix(patt, Pattern_Type_Like,
&prefix, &rest) != Pattern_Prefix_None;
if (prefix)
pfree(prefix);
pfree(patt);
if (locale_is_like_safe())
{
/* the right-hand const is type text for all of these */
patt = DatumGetCString(DirectFunctionCall1(textout,
constvalue));
isIndexable = pattern_fixed_prefix(patt, Pattern_Type_Like,
&prefix, &rest) != Pattern_Prefix_None;
if (prefix)
pfree(prefix);
pfree(patt);
}
break;
case OID_TEXT_ICLIKE_OP:
case OID_BPCHAR_ICLIKE_OP:
case OID_VARCHAR_ICLIKE_OP:
case OID_NAME_ICLIKE_OP:
/* the right-hand const is type text for all of these */
patt = DatumGetCString(DirectFunctionCall1(textout,
constvalue));
isIndexable = pattern_fixed_prefix(patt, Pattern_Type_Like_IC,
&prefix, &rest) != Pattern_Prefix_None;
if (prefix)
pfree(prefix);
pfree(patt);
if (locale_is_like_safe())
{
/* the right-hand const is type text for all of these */
patt = DatumGetCString(DirectFunctionCall1(textout,
constvalue));
isIndexable = pattern_fixed_prefix(patt, Pattern_Type_Like_IC,
&prefix, &rest) != Pattern_Prefix_None;
if (prefix)
pfree(prefix);
pfree(patt);
}
break;
case OID_TEXT_REGEXEQ_OP:
case OID_BPCHAR_REGEXEQ_OP:
case OID_VARCHAR_REGEXEQ_OP:
case OID_NAME_REGEXEQ_OP:
/* the right-hand const is type text for all of these */
patt = DatumGetCString(DirectFunctionCall1(textout,
constvalue));
isIndexable = pattern_fixed_prefix(patt, Pattern_Type_Regex,
&prefix, &rest) != Pattern_Prefix_None;
if (prefix)
pfree(prefix);
pfree(patt);
if (locale_is_like_safe())
{
/* the right-hand const is type text for all of these */
patt = DatumGetCString(DirectFunctionCall1(textout,
constvalue));
isIndexable = pattern_fixed_prefix(patt, Pattern_Type_Regex,
&prefix, &rest) != Pattern_Prefix_None;
if (prefix)
pfree(prefix);
pfree(patt);
}
break;
case OID_TEXT_ICREGEXEQ_OP:
case OID_BPCHAR_ICREGEXEQ_OP:
case OID_VARCHAR_ICREGEXEQ_OP:
case OID_NAME_ICREGEXEQ_OP:
/* the right-hand const is type text for all of these */
patt = DatumGetCString(DirectFunctionCall1(textout,
constvalue));
isIndexable = pattern_fixed_prefix(patt, Pattern_Type_Regex_IC,
&prefix, &rest) != Pattern_Prefix_None;
if (prefix)
pfree(prefix);
pfree(patt);
if (locale_is_like_safe())
{
/* the right-hand const is type text for all of these */
patt = DatumGetCString(DirectFunctionCall1(textout,
constvalue));
isIndexable = pattern_fixed_prefix(patt, Pattern_Type_Regex_IC,
&prefix, &rest) != Pattern_Prefix_None;
if (prefix)
pfree(prefix);
pfree(patt);
}
break;
}
......@@ -2053,8 +2065,8 @@ prefix_quals(Var *leftop, Oid expr_op,
result = makeList1(expr);
/*
* If we can create a string larger than the prefix, say "x <
* greaterstr".
* If we can create a string larger than the prefix, we can say
* "x < greaterstr".
*/
greaterstr = make_greater_string(prefix, datatype);
if (greaterstr)
......
......@@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.191 2000/11/25 19:05:42 petere Exp $
* $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.192 2000/11/25 20:33:52 tgl Exp $
*
* NOTES
*
......@@ -617,13 +617,11 @@ PostmasterMain(int argc, char *argv[])
}
#endif
XLOGPathInit();
/* set up shared memory and semaphores */
reset_shared(PostPortNumber);
/* Init XLOG paths */
snprintf(XLogDir, MAXPGPATH, "%s/pg_xlog", DataDir);
snprintf(ControlFilePath, MAXPGPATH, "%s/global/pg_control", DataDir);
/*
* Initialize the list of active backends. This list is only used for
* garbage collecting the backend processes.
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.190 2000/11/25 19:05:42 petere Exp $
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.191 2000/11/25 20:33:52 tgl Exp $
*
* NOTES
* this is the "main" module of the postgres backend and
......@@ -1525,9 +1525,8 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha
*/
on_proc_exit(UnlinkPidFile, 0);
XLOGPathInit();
BaseInit();
snprintf(XLogDir, MAXPGPATH, "%s/pg_xlog", DataDir);
snprintf(ControlFilePath, MAXPGPATH, "%s/global/pg_control", DataDir);
StartupXLOG();
}
......@@ -1636,7 +1635,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha
if (!IsUnderPostmaster)
{
puts("\nPOSTGRES backend interactive interface ");
puts("$Revision: 1.190 $ $Date: 2000/11/25 19:05:42 $\n");
puts("$Revision: 1.191 $ $Date: 2000/11/25 20:33:52 $\n");
}
/*
......
......@@ -9,7 +9,7 @@
* workings can be found in the book "Software Solutions in C" by
* Dale Schumacher, Academic Press, ISBN: 0-12-632360-7.
*
* $Header: /cvsroot/pgsql/src/backend/utils/adt/cash.c,v 1.46 2000/11/18 03:55:51 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/adt/cash.c,v 1.47 2000/11/25 20:33:52 tgl Exp $
*/
#include <limits.h>
......@@ -84,10 +84,6 @@ cash_in(PG_FUNCTION_ARGS)
*nsymbol;
#ifdef USE_LOCALE
#ifdef CASHDEBUG
setlocale(LC_ALL, "");
lconvert = localeconv();
#endif
if (lconvert == NULL)
lconvert = localeconv();
......
......@@ -15,7 +15,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.82 2000/11/16 22:30:31 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.83 2000/11/25 20:33:53 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -24,6 +24,9 @@
#include <ctype.h>
#include <math.h>
#ifdef USE_LOCALE
#include <locale.h>
#endif
#include "access/heapam.h"
#include "catalog/catname.h"
......@@ -1581,6 +1584,11 @@ pattern_fixed_prefix(char *patt, Pattern_Type ptype,
*
* A fixed prefix "foo" is estimated as the selectivity of the expression
* "var >= 'foo' AND var < 'fop'" (see also indxqual.c).
*
* XXX Note: we make use of the upper bound to estimate operator selectivity
* even if the locale is such that we cannot rely on the upper-bound string.
* The selectivity only needs to be approximately right anyway, so it seems
* more useful to use the upper-bound code than not.
*/
static Selectivity
prefix_selectivity(char *prefix,
......@@ -1862,6 +1870,44 @@ pattern_selectivity(char *patt, Pattern_Type ptype)
return result;
}
/*
* Test whether the database's LOCALE setting is safe for LIKE/regexp index
* optimization. The key requirement here is that given a prefix string,
* say "foo", we must be able to generate another string "fop" that is
* greater than all strings "foobar" starting with "foo". Unfortunately,
* many non-C locales have bizarre collation rules in which "fop" > "foo"
* is not sufficient to ensure "fop" > "foobar". Until we can come up
* with a more bulletproof way of generating the upper-bound string,
* disable the optimization in locales where it is not known to be safe.
*/
bool
locale_is_like_safe(void)
{
#ifdef USE_LOCALE
/* Cache result so we only have to compute it once */
static int result = -1;
char *localeptr;
if (result >= 0)
return (bool) result;
localeptr = setlocale(LC_COLLATE, NULL);
if (!localeptr)
elog(STOP, "Invalid LC_COLLATE setting");
/*
* Currently we accept only "C" and "POSIX" (do any systems still
* return "POSIX"?). Which other locales allow safe optimization?
*/
if (strcmp(localeptr, "C") == 0)
result = true;
else if (strcmp(localeptr, "POSIX") == 0)
result = true;
else
result = false;
return (bool) result;
#else /* not USE_LOCALE */
return true; /* We must be in C locale, which is OK */
#endif /* USE_LOCALE */
}
/*
* Try to generate a string greater than the given string or any string it is
......@@ -1878,9 +1924,12 @@ pattern_selectivity(char *patt, Pattern_Type ptype)
* This could be rather slow in the worst case, but in most cases we won't
* have to try more than one or two strings before succeeding.
*
* XXX in a sufficiently weird locale, this might produce incorrect results?
* For example, in German I believe "ss" is treated specially --- if we are
* given "foos" and return "foot", will this actually be greater than "fooss"?
* XXX this is actually not sufficient, since it only copes with the case
* where individual characters collate in an order different from their
* numeric code assignments. It does not handle cases where there are
* cross-character effects, such as specially sorted digraphs, multiple
* sort passes, etc. For now, we just shut down the whole thing in locales
* that do such things :-(
*/
char *
make_greater_string(const char *str, Oid datatype)
......
......@@ -3,7 +3,7 @@
*
* PostgreSQL transaction log manager
*
* $Header: /cvsroot/pgsql/src/include/access/xlog.h,v 1.10 2000/11/21 21:16:05 petere Exp $
* $Header: /cvsroot/pgsql/src/include/access/xlog.h,v 1.11 2000/11/25 20:33:53 tgl Exp $
*/
#ifndef XLOG_H
#define XLOG_H
......@@ -107,13 +107,11 @@ extern void xlog_desc(char *buf, uint8 xl_info, char* rec);
extern void UpdateControlFile(void);
extern int XLOGShmemSize(void);
extern void XLOGShmemInit(void);
extern void XLOGPathInit(void);
extern void BootStrapXLOG(void);
extern void StartupXLOG(void);
extern void ShutdownXLOG(void);
extern void CreateCheckPoint(bool shutdown);
extern void SetThisStartUpID(void);
extern char XLogDir[];
extern char ControlFilePath[];
#endif /* XLOG_H */
......@@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: catversion.h,v 1.63 2000/11/21 03:23:19 tgl Exp $
* $Id: catversion.h,v 1.64 2000/11/25 20:33:53 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
#define CATALOG_VERSION_NO 200011211
#define CATALOG_VERSION_NO 200011251
#endif
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: builtins.h,v 1.142 2000/11/21 03:23:20 tgl Exp $
* $Id: builtins.h,v 1.143 2000/11/25 20:33:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -376,6 +376,7 @@ extern Pattern_Prefix_Status pattern_fixed_prefix(char *patt,
Pattern_Type ptype,
char **prefix,
char **rest);
extern bool locale_is_like_safe(void);
extern char *make_greater_string(const char *str, Oid datatype);
/* tid.c */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment