aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/transam/xlog.c259
-rw-r--r--src/backend/bootstrap/bootstrap.c6
-rw-r--r--src/backend/optimizer/path/indxpath.c82
-rw-r--r--src/backend/postmaster/postmaster.c8
-rw-r--r--src/backend/tcop/postgres.c7
-rw-r--r--src/backend/utils/adt/cash.c6
-rw-r--r--src/backend/utils/adt/selfuncs.c57
-rw-r--r--src/include/access/xlog.h6
-rw-r--r--src/include/catalog/catversion.h4
-rw-r--r--src/include/utils/builtins.h3
10 files changed, 315 insertions, 123 deletions
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 46aa03edf69..fd99732d213 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.33 2000/11/21 22:27:26 petere Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.34 2000/11/25 20:33:50 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -20,6 +20,9 @@
#include <sys/time.h>
#include <sys/types.h>
#include <dirent.h>
+#ifdef USE_LOCALE
+#include <locale.h>
+#endif
#include "access/transam.h"
#include "access/xact.h"
@@ -30,12 +33,11 @@
#include "storage/s_lock.h"
#include "access/xlog.h"
#include "access/xlogutils.h"
+#include "utils/builtins.h"
#include "utils/relcache.h"
#include "miscadmin.h"
-char XLogDir[MAXPGPATH];
-char ControlFilePath[MAXPGPATH];
int XLOGbuffers = 8;
XLogRecPtr MyLastRecPtr = {0, 0};
bool StopIfError = false;
@@ -50,6 +52,9 @@ SPINLOCK ControlFileLockId;
/* To generate new xid */
SPINLOCK XidGenLockId;
+static char XLogDir[MAXPGPATH];
+static char ControlFilePath[MAXPGPATH];
+
#define MinXLOGbuffers 4
typedef struct XLgwrRqst
@@ -107,6 +112,10 @@ typedef struct XLogCtlData
static XLogCtlData *XLogCtl = NULL;
+/*
+ * Contents of pg_control
+ */
+
typedef enum DBState
{
DB_STARTUP = 0,
@@ -116,31 +125,39 @@ typedef enum DBState
DB_IN_PRODUCTION
} DBState;
+#define LOCALE_NAME_BUFLEN 128
+
typedef struct ControlFileData
{
+ /*
+ * XLOG state
+ */
uint32 logId; /* current log file id */
uint32 logSeg; /* current log file segment (1-based) */
XLogRecPtr checkPoint; /* last check point record ptr */
time_t time; /* time stamp of last modification */
- DBState state; /* */
+ DBState state; /* see enum above */
/*
* this data is used to make sure that configuration of this DB is
- * compatible with the current backend
+ * compatible with the backend executable
*/
uint32 blcksz; /* block size for this DB */
uint32 relseg_size; /* blocks per segment of large relation */
uint32 catalog_version_no; /* internal version number */
- char archdir[MAXPGPATH]; /* where to move offline log files */
+ /* active locales --- "C" if compiled without USE_LOCALE: */
+ char lc_collate[LOCALE_NAME_BUFLEN];
+ char lc_ctype[LOCALE_NAME_BUFLEN];
/*
- * MORE DATA FOLLOWS AT THE END OF THIS STRUCTURE - locations of data
- * dirs
+ * important directory locations
*/
+ char archdir[MAXPGPATH]; /* where to move offline log files */
} ControlFileData;
static ControlFileData *ControlFile = NULL;
+
typedef struct CheckPoint
{
XLogRecPtr redo; /* next RecPtr available when we */
@@ -204,6 +221,8 @@ static void XLogWrite(char *buffer);
static int XLogFileInit(uint32 log, uint32 seg, bool *usexistent);
static int XLogFileOpen(uint32 log, uint32 seg, bool econt);
static XLogRecord *ReadRecord(XLogRecPtr *RecPtr, char *buffer);
+static void WriteControlFile(void);
+static void ReadControlFile(void);
static char *str_time(time_t tnow);
static void xlog_outrec(char *buf, XLogRecord *record);
@@ -1210,26 +1229,170 @@ next_record_is_invalid:;
return (record);
}
+/*
+ * I/O routines for pg_control
+ *
+ * *ControlFile is a buffer in shared memory that holds an image of the
+ * contents of pg_control. WriteControlFile() initializes pg_control
+ * given a preloaded buffer, ReadControlFile() loads the buffer from
+ * the pg_control file (during postmaster or standalone-backend startup),
+ * and UpdateControlFile() rewrites pg_control after we modify xlog state.
+ *
+ * For simplicity, WriteControlFile() initializes the fields of pg_control
+ * that are related to checking backend/database compatibility, and
+ * ReadControlFile() verifies they are correct. We could split out the
+ * I/O and compatibility-check functions, but there seems no need currently.
+ */
+
+void
+XLOGPathInit(void)
+{
+ /* Init XLOG file paths */
+ snprintf(XLogDir, MAXPGPATH, "%s/pg_xlog", DataDir);
+ snprintf(ControlFilePath, MAXPGPATH, "%s/global/pg_control", DataDir);
+}
+
+static void
+WriteControlFile(void)
+{
+ int fd;
+ char buffer[BLCKSZ];
+#ifdef USE_LOCALE
+ char *localeptr;
+#endif
+
+ /*
+ * Initialize compatibility-check fields
+ */
+ ControlFile->blcksz = BLCKSZ;
+ ControlFile->relseg_size = RELSEG_SIZE;
+ ControlFile->catalog_version_no = CATALOG_VERSION_NO;
+#ifdef USE_LOCALE
+ localeptr = setlocale(LC_COLLATE, NULL);
+ if (!localeptr)
+ elog(STOP, "Invalid LC_COLLATE setting");
+ StrNCpy(ControlFile->lc_collate, localeptr, LOCALE_NAME_BUFLEN);
+ localeptr = setlocale(LC_CTYPE, NULL);
+ if (!localeptr)
+ elog(STOP, "Invalid LC_CTYPE setting");
+ StrNCpy(ControlFile->lc_ctype, localeptr, LOCALE_NAME_BUFLEN);
+ /*
+ * Issue warning notice if initdb'ing in a locale that will not permit
+ * LIKE index optimization. This is not a clean place to do it, but
+ * I don't see a better place either...
+ */
+ if (!locale_is_like_safe())
+ elog(NOTICE, "Initializing database with %s collation order."
+ "\n\tThis locale setting will prevent use of index optimization for"
+ "\n\tLIKE and regexp searches. If you are concerned about speed of"
+ "\n\tsuch queries, you may wish to set LC_COLLATE to \"C\" and"
+ "\n\tre-initdb. For more information see the Administrator's Guide.",
+ ControlFile->lc_collate);
+#else
+ strcpy(ControlFile->lc_collate, "C");
+ strcpy(ControlFile->lc_ctype, "C");
+#endif
+
+ /*
+ * We write out BLCKSZ bytes into pg_control, zero-padding the
+ * excess over sizeof(ControlFileData). This reduces the odds
+ * of premature-EOF errors when reading pg_control. We'll still
+ * fail when we check the contents of the file, but hopefully with
+ * a more specific error than "couldn't read pg_control".
+ */
+ if (sizeof(ControlFileData) > BLCKSZ)
+ elog(STOP, "sizeof(ControlFileData) is too large ... fix xlog.c");
+ memset(buffer, 0, BLCKSZ);
+ memcpy(buffer, ControlFile, sizeof(ControlFileData));
+
+ fd = BasicOpenFile(ControlFilePath, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, S_IRUSR | S_IWUSR);
+ if (fd < 0)
+ elog(STOP, "WriteControlFile failed to create control file (%s): %m",
+ ControlFilePath);
+
+ if (write(fd, buffer, BLCKSZ) != BLCKSZ)
+ elog(STOP, "WriteControlFile failed to write control file: %m");
+
+ if (fsync(fd) != 0)
+ elog(STOP, "WriteControlFile failed to fsync control file: %m");
+
+ close(fd);
+}
+
+static void
+ReadControlFile(void)
+{
+ int fd;
+
+ /*
+ * Read data...
+ */
+ fd = BasicOpenFile(ControlFilePath, O_RDWR | PG_BINARY, S_IRUSR | S_IWUSR);
+ if (fd < 0)
+ elog(STOP, "open(\"%s\") failed: %m", ControlFilePath);
+
+ if (read(fd, ControlFile, sizeof(ControlFileData)) != sizeof(ControlFileData))
+ elog(STOP, "read(\"%s\") failed: %m", ControlFilePath);
+
+ close(fd);
+
+ /*
+ * Do compatibility checking immediately. We do this here for 2 reasons:
+ *
+ * (1) if the database isn't compatible with the backend executable,
+ * we want to abort before we can possibly do any damage;
+ *
+ * (2) this code is executed in the postmaster, so the setlocale() will
+ * propagate to forked backends, which aren't going to read this file
+ * for themselves. (These locale settings are considered critical
+ * compatibility items because they can affect sort order of indexes.)
+ */
+ if (ControlFile->blcksz != BLCKSZ)
+ elog(STOP, "database was initialized with BLCKSZ %d,\n\tbut the backend was compiled with BLCKSZ %d.\n\tlooks like you need to initdb.",
+ ControlFile->blcksz, BLCKSZ);
+ if (ControlFile->relseg_size != RELSEG_SIZE)
+ elog(STOP, "database was initialized with RELSEG_SIZE %d,\n\tbut the backend was compiled with RELSEG_SIZE %d.\n\tlooks like you need to initdb.",
+ ControlFile->relseg_size, RELSEG_SIZE);
+ if (ControlFile->catalog_version_no != CATALOG_VERSION_NO)
+ elog(STOP, "database was initialized with CATALOG_VERSION_NO %d,\n\tbut the backend was compiled with CATALOG_VERSION_NO %d.\n\tlooks like you need to initdb.",
+ ControlFile->catalog_version_no, CATALOG_VERSION_NO);
+#ifdef USE_LOCALE
+ if (setlocale(LC_COLLATE, ControlFile->lc_collate) == NULL)
+ elog(STOP, "database was initialized with LC_COLLATE '%s',\n\twhich is not recognized by setlocale().\n\tlooks like you need to initdb.",
+ ControlFile->lc_collate);
+ if (setlocale(LC_CTYPE, ControlFile->lc_ctype) == NULL)
+ elog(STOP, "database was initialized with LC_CTYPE '%s',\n\twhich is not recognized by setlocale().\n\tlooks like you need to initdb.",
+ ControlFile->lc_ctype);
+#else
+ if (strcmp(ControlFile->lc_collate, "C") != 0 ||
+ strcmp(ControlFile->lc_ctype, "C") != 0)
+ elog(STOP, "database was initialized with LC_COLLATE '%s' and LC_CTYPE '%s',\n\tbut the backend was compiled without locale support.\n\tlooks like you need to initdb or recompile.",
+ ControlFile->lc_collate, ControlFile->lc_ctype);
+#endif
+}
+
void
-UpdateControlFile()
+UpdateControlFile(void)
{
int fd;
fd = BasicOpenFile(ControlFilePath, O_RDWR | PG_BINARY, S_IRUSR | S_IWUSR);
if (fd < 0)
- elog(STOP, "open(cntlfile) failed: %m");
+ elog(STOP, "open(\"%s\") failed: %m", ControlFilePath);
- if (write(fd, ControlFile, BLCKSZ) != BLCKSZ)
+ if (write(fd, ControlFile, sizeof(ControlFileData)) != sizeof(ControlFileData))
elog(STOP, "write(cntlfile) failed: %m");
if (fsync(fd) != 0)
elog(STOP, "fsync(cntlfile) failed: %m");
close(fd);
-
- return;
}
+/*
+ * Management of shared memory for XLOG
+ */
+
int
XLOGShmemSize(void)
{
@@ -1237,7 +1400,8 @@ XLOGShmemSize(void)
XLOGbuffers = MinXLOGbuffers;
return (sizeof(XLogCtlData) + BLCKSZ * XLOGbuffers +
- sizeof(XLogRecPtr) * XLOGbuffers + BLCKSZ);
+ sizeof(XLogRecPtr) * XLOGbuffers +
+ sizeof(ControlFileData));
}
void
@@ -1245,16 +1409,25 @@ XLOGShmemInit(void)
{
bool found;
+ /* this must agree with space requested by XLOGShmemSize() */
if (XLOGbuffers < MinXLOGbuffers)
XLOGbuffers = MinXLOGbuffers;
- ControlFile = (ControlFileData *)
- ShmemInitStruct("Control File", BLCKSZ, &found);
- Assert(!found);
XLogCtl = (XLogCtlData *)
ShmemInitStruct("XLOG Ctl", sizeof(XLogCtlData) + BLCKSZ * XLOGbuffers +
sizeof(XLogRecPtr) * XLOGbuffers, &found);
Assert(!found);
+ ControlFile = (ControlFileData *)
+ ShmemInitStruct("Control File", sizeof(ControlFileData), &found);
+ Assert(!found);
+
+ /*
+ * If we are not in bootstrap mode, pg_control should already exist.
+ * Read and validate it immediately (see comments in ReadControlFile()
+ * for the reasons why).
+ */
+ if (!IsBootstrapProcessingMode())
+ ReadControlFile();
}
/*
@@ -1263,22 +1436,14 @@ XLOGShmemInit(void)
void
BootStrapXLOG()
{
- int fd;
- char buffer[BLCKSZ];
CheckPoint checkPoint;
-
#ifdef XLOG
+ char buffer[BLCKSZ];
bool usexistent = false;
XLogPageHeader page = (XLogPageHeader) buffer;
XLogRecord *record;
-
#endif
- fd = BasicOpenFile(ControlFilePath, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, S_IRUSR | S_IWUSR);
- if (fd < 0)
- elog(STOP, "BootStrapXLOG failed to create control file (%s): %m",
- ControlFilePath);
-
checkPoint.redo.xlogid = 0;
checkPoint.redo.xrecoff = SizeOfXLogPHD;
checkPoint.undo = checkPoint.redo;
@@ -1319,23 +1484,15 @@ BootStrapXLOG()
#endif
- memset(ControlFile, 0, BLCKSZ);
+ memset(ControlFile, 0, sizeof(ControlFileData));
ControlFile->logId = 0;
ControlFile->logSeg = 1;
ControlFile->checkPoint = checkPoint.redo;
ControlFile->time = time(NULL);
ControlFile->state = DB_SHUTDOWNED;
- ControlFile->blcksz = BLCKSZ;
- ControlFile->relseg_size = RELSEG_SIZE;
- ControlFile->catalog_version_no = CATALOG_VERSION_NO;
+ /* some additional ControlFile fields are set in WriteControlFile() */
- if (write(fd, ControlFile, BLCKSZ) != BLCKSZ)
- elog(STOP, "BootStrapXLOG failed to write control file: %m");
-
- if (fsync(fd) != 0)
- elog(STOP, "BootStrapXLOG failed to fsync control file: %m");
-
- close(fd);
+ WriteControlFile();
}
static char *
@@ -1367,7 +1524,6 @@ StartupXLOG()
bool sie_saved = false;
#endif
- int fd;
elog(LOG, "starting up");
@@ -1389,16 +1545,12 @@ StartupXLOG()
S_INIT_LOCK(&(XLogCtl->chkp_lck));
/*
- * Open/read Control file
+ * Read control file and check XLOG status looks valid.
+ *
+ * Note: in most control paths, *ControlFile is already valid and we
+ * need not do ReadControlFile() here, but might as well do it to be sure.
*/
- fd = BasicOpenFile(ControlFilePath, O_RDWR | PG_BINARY, S_IRUSR | S_IWUSR);
- if (fd < 0)
- elog(STOP, "open(\"%s\") failed: %m", ControlFilePath);
-
- if (read(fd, ControlFile, BLCKSZ) != BLCKSZ)
- elog(STOP, "read(\"%s\") failed: %m", ControlFilePath);
-
- close(fd);
+ ReadControlFile();
if (ControlFile->logSeg == 0 ||
ControlFile->time <= 0 ||
@@ -1407,17 +1559,6 @@ StartupXLOG()
!XRecOffIsValid(ControlFile->checkPoint.xrecoff))
elog(STOP, "control file context is broken");
- /* Check for incompatible database */
- if (ControlFile->blcksz != BLCKSZ)
- elog(STOP, "database was initialized with BLCKSZ %d,\n\tbut the backend was compiled with BLCKSZ %d.\n\tlooks like you need to initdb.",
- ControlFile->blcksz, BLCKSZ);
- if (ControlFile->relseg_size != RELSEG_SIZE)
- elog(STOP, "database was initialized with RELSEG_SIZE %d,\n\tbut the backend was compiled with RELSEG_SIZE %d.\n\tlooks like you need to initdb.",
- ControlFile->relseg_size, RELSEG_SIZE);
- if (ControlFile->catalog_version_no != CATALOG_VERSION_NO)
- elog(STOP, "database was initialized with CATALOG_VERSION_NO %d,\n\tbut the backend was compiled with CATALOG_VERSION_NO %d.\n\tlooks like you need to initdb.",
- ControlFile->catalog_version_no, CATALOG_VERSION_NO);
-
if (ControlFile->state == DB_SHUTDOWNED)
elog(LOG, "database system was shut down at %s",
str_time(ControlFile->time));
@@ -1425,12 +1566,10 @@ StartupXLOG()
elog(LOG, "database system shutdown was interrupted at %s",
str_time(ControlFile->time));
else if (ControlFile->state == DB_IN_RECOVERY)
- {
elog(LOG, "database system was interrupted being in recovery at %s\n"
"\tThis propably means that some data blocks are corrupted\n"
"\tand you will have to use last backup for recovery.",
str_time(ControlFile->time));
- }
else if (ControlFile->state == DB_IN_PRODUCTION)
elog(LOG, "database system was interrupted at %s",
str_time(ControlFile->time));
diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c
index 2c03e5e1359..3f2bf76a36e 100644
--- a/src/backend/bootstrap/bootstrap.c
+++ b/src/backend/bootstrap/bootstrap.c
@@ -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();
diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c
index 43577f94f99..63e3a53af5a 100644
--- a/src/backend/optimizer/path/indxpath.c
+++ b/src/backend/optimizer/path/indxpath.c
@@ -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)
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 805fd679bed..e68e30fbd5c 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -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.
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index f7d3e1c1b02..0f8dec00d89 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -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");
}
/*
diff --git a/src/backend/utils/adt/cash.c b/src/backend/utils/adt/cash.c
index 696559a59ea..f081e2568c2 100644
--- a/src/backend/utils/adt/cash.c
+++ b/src/backend/utils/adt/cash.c
@@ -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();
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index 63e4d9b46d2..8d4c4d080a4 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -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)
diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h
index 493a0e9091b..4654296e116 100644
--- a/src/include/access/xlog.h
+++ b/src/include/access/xlog.h
@@ -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 */
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index 270b52cac97..85e4c02b533 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.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
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index 42d2d81173d..7caf379a115 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -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 */