mirror of
https://github.com/postgres/postgres.git
synced 2025-11-12 05:01:15 +03:00
Merge the last few variable.c configuration variables into the generic
GUC support. It's now possible to set datestyle, timezone, and client_encoding from postgresql.conf and per-database or per-user settings. Also, implement rollback of SET commands that occur in a transaction that later fails. Create a SET LOCAL var = value syntax that sets the variable only for the duration of the current transaction. All per previous discussions in pghackers.
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.89 2002/04/21 19:48:12 thomas Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.90 2002/05/17 01:19:18 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -3571,11 +3571,17 @@ EncodeInterval(struct tm * tm, fsec_t fsec, int style, char *str)
|
||||
} /* EncodeInterval() */
|
||||
|
||||
|
||||
void
|
||||
ClearDateCache(bool dummy)
|
||||
/* GUC assign_hook for australian_timezones */
|
||||
bool
|
||||
ClearDateCache(bool newval, bool doit, bool interactive)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAXDATEFIELDS; i++)
|
||||
datecache[i] = NULL;
|
||||
if (doit)
|
||||
{
|
||||
for (i = 0; i < MAXDATEFIELDS; i++)
|
||||
datecache[i] = NULL;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
*
|
||||
* PostgreSQL locale utilities
|
||||
*
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/pg_locale.c,v 1.16 2002/04/03 05:39:31 petere Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/pg_locale.c,v 1.17 2002/05/17 01:19:18 tgl Exp $
|
||||
*
|
||||
* Portions Copyright (c) 2002, PostgreSQL Global Development Group
|
||||
*
|
||||
@@ -10,89 +10,73 @@
|
||||
*/
|
||||
|
||||
#include "postgres.h"
|
||||
#include "utils/pg_locale.h"
|
||||
|
||||
#include <locale.h>
|
||||
|
||||
#include "utils/pg_locale.h"
|
||||
|
||||
|
||||
/* GUC storage area */
|
||||
|
||||
char * locale_messages;
|
||||
char * locale_monetary;
|
||||
char * locale_numeric;
|
||||
char * locale_time;
|
||||
char *locale_messages;
|
||||
char *locale_monetary;
|
||||
char *locale_numeric;
|
||||
char *locale_time;
|
||||
|
||||
/* GUC parse hooks */
|
||||
|
||||
bool locale_messages_check(const char *proposed)
|
||||
{
|
||||
#ifdef LC_MESSAGES
|
||||
return chklocale(LC_MESSAGES, proposed);
|
||||
#else
|
||||
/* We return true here so LC_MESSAGES can be set in the
|
||||
configuration file on every system. */
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool locale_monetary_check(const char *proposed)
|
||||
{
|
||||
return chklocale(LC_MONETARY, proposed);
|
||||
}
|
||||
|
||||
bool locale_numeric_check(const char *proposed)
|
||||
{
|
||||
return chklocale(LC_NUMERIC, proposed);
|
||||
}
|
||||
|
||||
bool locale_time_check(const char *proposed)
|
||||
{
|
||||
return chklocale(LC_TIME, proposed);
|
||||
}
|
||||
|
||||
/* GUC assign hooks */
|
||||
|
||||
void locale_messages_assign(const char *value)
|
||||
static const char *
|
||||
locale_xxx_assign(int category, const char *value, bool doit, bool interactive)
|
||||
{
|
||||
if (doit)
|
||||
{
|
||||
if (!setlocale(category, value))
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
char *save;
|
||||
|
||||
save = setlocale(category, NULL);
|
||||
if (!save)
|
||||
return NULL;
|
||||
|
||||
if (!setlocale(category, value))
|
||||
return NULL;
|
||||
|
||||
setlocale(category, save);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
const char *
|
||||
locale_messages_assign(const char *value, bool doit, bool interactive)
|
||||
{
|
||||
/* LC_MESSAGES category does not exist everywhere, but accept it anyway */
|
||||
#ifdef LC_MESSAGES
|
||||
setlocale(LC_MESSAGES, value);
|
||||
return locale_xxx_assign(LC_MESSAGES, value, doit, interactive);
|
||||
#else
|
||||
return value;
|
||||
#endif
|
||||
}
|
||||
|
||||
void locale_monetary_assign(const char *value)
|
||||
const char *
|
||||
locale_monetary_assign(const char *value, bool doit, bool interactive)
|
||||
{
|
||||
setlocale(LC_MONETARY, value);
|
||||
return locale_xxx_assign(LC_MONETARY, value, doit, interactive);
|
||||
}
|
||||
|
||||
void locale_numeric_assign(const char *value)
|
||||
const char *
|
||||
locale_numeric_assign(const char *value, bool doit, bool interactive)
|
||||
{
|
||||
setlocale(LC_NUMERIC, value);
|
||||
return locale_xxx_assign(LC_NUMERIC, value, doit, interactive);
|
||||
}
|
||||
|
||||
void locale_time_assign(const char *value)
|
||||
const char *
|
||||
locale_time_assign(const char *value, bool doit, bool interactive)
|
||||
{
|
||||
setlocale(LC_TIME, value);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Returns true if the proposed string represents a valid locale of
|
||||
* the given category. This is probably pretty slow, but it's not
|
||||
* called in critical places.
|
||||
*/
|
||||
bool
|
||||
chklocale(int category, const char *proposed)
|
||||
{
|
||||
char *save;
|
||||
|
||||
save = setlocale(category, NULL);
|
||||
if (!save)
|
||||
return false;
|
||||
|
||||
if (!setlocale(category, proposed))
|
||||
return false;
|
||||
|
||||
setlocale(category, save);
|
||||
return true;
|
||||
return locale_xxx_assign(LC_TIME, value, doit, interactive);
|
||||
}
|
||||
|
||||
|
||||
@@ -123,7 +107,6 @@ lc_collate_is_c(void)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Return the POSIX lconv struct (contains number/money formatting
|
||||
* information) with locale information for all categories.
|
||||
@@ -131,10 +114,11 @@ lc_collate_is_c(void)
|
||||
struct lconv *
|
||||
PGLC_localeconv(void)
|
||||
{
|
||||
struct lconv *extlconv;
|
||||
static bool CurrentLocaleConvValid = false;
|
||||
static struct lconv CurrentLocaleConv;
|
||||
|
||||
struct lconv *extlconv;
|
||||
|
||||
/* Did we do it already? */
|
||||
if (CurrentLocaleConvValid)
|
||||
return &CurrentLocaleConv;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* back to source text
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.104 2002/05/12 23:43:03 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.105 2002/05/17 01:19:18 tgl Exp $
|
||||
*
|
||||
* This software is copyrighted by Jan Wieck - Hamburg.
|
||||
*
|
||||
@@ -2576,27 +2576,33 @@ quote_identifier(const char *ident)
|
||||
* and contains only lowercase letters, digits, and underscores, *and* is
|
||||
* not any SQL keyword. Otherwise, supply quotes.
|
||||
*/
|
||||
int nquotes = 0;
|
||||
bool safe;
|
||||
const char *ptr;
|
||||
char *result;
|
||||
char *optr;
|
||||
|
||||
/*
|
||||
* would like to use <ctype.h> macros here, but they might yield
|
||||
* unwanted locale-specific results...
|
||||
*/
|
||||
safe = ((ident[0] >= 'a' && ident[0] <= 'z') || ident[0] == '_');
|
||||
if (safe)
|
||||
|
||||
for (ptr = ident; *ptr; ptr++)
|
||||
{
|
||||
const char *ptr;
|
||||
char ch = *ptr;
|
||||
|
||||
for (ptr = ident + 1; *ptr; ptr++)
|
||||
if ((ch >= 'a' && ch <= 'z') ||
|
||||
(ch >= '0' && ch <= '9') ||
|
||||
(ch == '_'))
|
||||
{
|
||||
char ch = *ptr;
|
||||
|
||||
safe = ((ch >= 'a' && ch <= 'z') ||
|
||||
(ch >= '0' && ch <= '9') ||
|
||||
(ch == '_'));
|
||||
if (!safe)
|
||||
break;
|
||||
/* okay */
|
||||
}
|
||||
else
|
||||
{
|
||||
safe = false;
|
||||
if (ch == '"')
|
||||
nquotes++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2618,8 +2624,21 @@ quote_identifier(const char *ident)
|
||||
if (safe)
|
||||
return ident; /* no change needed */
|
||||
|
||||
result = (char *) palloc(strlen(ident) + 2 + 1);
|
||||
sprintf(result, "\"%s\"", ident);
|
||||
result = (char *) palloc(strlen(ident) + nquotes + 2 + 1);
|
||||
|
||||
optr = result;
|
||||
*optr++ = '"';
|
||||
for (ptr = ident; *ptr; ptr++)
|
||||
{
|
||||
char ch = *ptr;
|
||||
|
||||
if (ch == '"')
|
||||
*optr++ = '"';
|
||||
*optr++ = ch;
|
||||
}
|
||||
*optr++ = '"';
|
||||
*optr = '\0';
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user