diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/access/transam/xlog.c | 259 | ||||
-rw-r--r-- | src/backend/bootstrap/bootstrap.c | 6 | ||||
-rw-r--r-- | src/backend/optimizer/path/indxpath.c | 82 | ||||
-rw-r--r-- | src/backend/postmaster/postmaster.c | 8 | ||||
-rw-r--r-- | src/backend/tcop/postgres.c | 7 | ||||
-rw-r--r-- | src/backend/utils/adt/cash.c | 6 | ||||
-rw-r--r-- | src/backend/utils/adt/selfuncs.c | 57 | ||||
-rw-r--r-- | src/include/access/xlog.h | 6 | ||||
-rw-r--r-- | src/include/catalog/catversion.h | 4 | ||||
-rw-r--r-- | src/include/utils/builtins.h | 3 |
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 */ |