diff options
Diffstat (limited to 'src/backend/utils')
| -rw-r--r-- | src/backend/utils/adt/varlena.c | 147 | ||||
| -rw-r--r-- | src/backend/utils/init/postinit.c | 23 | ||||
| -rw-r--r-- | src/backend/utils/misc/guc.c | 12 | ||||
| -rw-r--r-- | src/backend/utils/misc/postgresql.conf.sample | 1 |
4 files changed, 124 insertions, 59 deletions
diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c index ce3e8dc254..5afaf39887 100644 --- a/src/backend/utils/adt/varlena.c +++ b/src/backend/utils/adt/varlena.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.80 2002/03/30 01:02:42 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.81 2002/04/01 03:34:26 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1046,28 +1046,82 @@ name_text(PG_FUNCTION_ARGS) * functions that take a text parameter representing a qualified name. * We split the name at dots, downcase if not double-quoted, and * truncate names if they're too long. - * - * This is a kluge, really, and exists only for historical reasons. - * A better notation for such functions would be nextval(relname). */ List * textToQualifiedNameList(text *textval, const char *caller) { char *rawname; - char *nextp; List *result = NIL; + List *namelist; + List *l; /* Convert to C string (handles possible detoasting). */ /* Note we rely on being able to modify rawname below. */ rawname = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(textval))); - nextp = rawname; + if (!SplitIdentifierString(rawname, '.', &namelist)) + elog(ERROR, "%s: invalid name syntax", caller); + + if (namelist == NIL) + elog(ERROR, "%s: invalid name syntax", caller); + + foreach(l, namelist) + { + char *curname = (char *) lfirst(l); + + result = lappend(result, makeString(pstrdup(curname))); + } + + pfree(rawname); + freeList(namelist); + + return result; +} + +/* + * SplitIdentifierString --- parse a string containing identifiers + * + * This is the guts of textToQualifiedNameList, and is exported for use in + * other situations such as parsing GUC variables. In the GUC case, it's + * important to avoid memory leaks, so the API is designed to minimize the + * amount of stuff that needs to be allocated and freed. + * + * Inputs: + * rawstring: the input string; must be overwritable! On return, it's + * been modified to contain the separated identifiers. + * separator: the separator punctuation expected between identifiers + * (typically '.' or ','). Whitespace may also appear around + * identifiers. + * Outputs: + * namelist: filled with a palloc'd list of pointers to identifiers within + * rawstring. Caller should freeList() this even on error return. + * + * Returns TRUE if okay, FALSE if there is a syntax error in the string. + * + * Note that an empty string is considered okay here, though not in + * textToQualifiedNameList. + */ +bool +SplitIdentifierString(char *rawstring, char separator, + List **namelist) +{ + char *nextp = rawstring; + bool done = false; + + *namelist = NIL; + + while (isspace((unsigned char) *nextp)) + nextp++; /* skip leading whitespace */ + + if (*nextp == '\0') + return true; /* allow empty string */ + + /* At the top of the loop, we are at start of a new identifier. */ do { char *curname; char *endp; - char *cp; int curlen; if (*nextp == '\"') @@ -1078,56 +1132,54 @@ textToQualifiedNameList(text *textval, const char *caller) { endp = strchr(nextp + 1, '\"'); if (endp == NULL) - elog(ERROR, "%s: invalid quoted name: mismatched quotes", - caller); + return false; /* mismatched quotes */ if (endp[1] != '\"') break; /* found end of quoted name */ /* Collapse adjacent quotes into one quote, and look again */ memmove(endp, endp+1, strlen(endp)); nextp = endp; } - *endp = '\0'; + /* endp now points at the terminating quote */ nextp = endp + 1; - if (*nextp) - { - if (*nextp != '.') - elog(ERROR, "%s: invalid name syntax", - caller); - nextp++; - if (*nextp == '\0') - elog(ERROR, "%s: invalid name syntax", - caller); - } } else { - /* Unquoted name --- extends to next dot */ - if (*nextp == '\0') /* empty name not okay here */ - elog(ERROR, "%s: invalid name syntax", - caller); + /* Unquoted name --- extends to separator or whitespace */ curname = nextp; - endp = strchr(nextp, '.'); - if (endp) + while (*nextp && *nextp != separator && + !isspace((unsigned char) *nextp)) { - *endp = '\0'; - nextp = endp + 1; - if (*nextp == '\0') - elog(ERROR, "%s: invalid name syntax", - caller); - } - else - nextp = nextp + strlen(nextp); - /* - * It's important that this match the identifier downcasing code - * used by backend/parser/scan.l. - */ - for (cp = curname; *cp; cp++) - { - if (isupper((unsigned char) *cp)) - *cp = tolower((unsigned char) *cp); + /* + * It's important that this match the identifier downcasing + * code used by backend/parser/scan.l. + */ + if (isupper((unsigned char) *nextp)) + *nextp = tolower((unsigned char) *nextp); + nextp++; } + endp = nextp; + if (curname == nextp) + return false; /* empty unquoted name not allowed */ } + while (isspace((unsigned char) *nextp)) + nextp++; /* skip trailing whitespace */ + + if (*nextp == separator) + { + nextp++; + while (isspace((unsigned char) *nextp)) + nextp++; /* skip leading whitespace for next */ + /* we expect another name, so done remains false */ + } + else if (*nextp == '\0') + done = true; + else + return false; /* invalid syntax */ + + /* Now safe to overwrite separator with a null */ + *endp = '\0'; + /* Truncate name if it's overlength; again, should match scan.l */ curlen = strlen(curname); if (curlen >= NAMEDATALEN) @@ -1143,15 +1195,12 @@ textToQualifiedNameList(text *textval, const char *caller) /* * Finished isolating current name --- add it to list */ - result = lappend(result, makeString(pstrdup(curname))); - /* - * Loop back if we found a dot - */ - } while (*nextp); + *namelist = lappend(*namelist, curname); - pfree(rawname); + /* Loop back if we didn't reach end of string */ + } while (!done); - return result; + return true; } diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c index 9cd5b194d9..0d36d70bea 100644 --- a/src/backend/utils/init/postinit.c +++ b/src/backend/utils/init/postinit.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.101 2002/03/31 06:26:32 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.102 2002/04/01 03:34:26 tgl Exp $ * * *------------------------------------------------------------------------- @@ -24,10 +24,11 @@ #include "catalog/catalog.h" #include "access/heapam.h" #include "catalog/catname.h" +#include "catalog/namespace.h" #include "catalog/pg_database.h" #include "catalog/pg_shadow.h" #include "commands/trigger.h" -#include "commands/variable.h" /* for set_default_client_encoding() */ +#include "commands/variable.h" #include "mb/pg_wchar.h" #include "miscadmin.h" #include "storage/backendid.h" @@ -372,11 +373,6 @@ InitPostgres(const char *dbname, const char *username) if (!bootstrap) ReverifyMyDatabase(dbname); -#ifdef MULTIBYTE - /* set default client encoding --- uses info from ReverifyMyDatabase */ - set_default_client_encoding(); -#endif - /* * Final phase of relation cache startup: write a new cache file * if necessary. This is done after ReverifyMyDatabase to avoid @@ -385,6 +381,19 @@ InitPostgres(const char *dbname, const char *username) RelationCacheInitializePhase3(); /* + * Initialize various default states that can't be set up until + * we've selected the active user and done ReverifyMyDatabase. + */ + + /* set default namespace search path */ + InitializeSearchPath(); + +#ifdef MULTIBYTE + /* set default client encoding --- uses info from ReverifyMyDatabase */ + set_default_client_encoding(); +#endif + + /* * Set up process-exit callback to do pre-shutdown cleanup. This should * be last because we want shmem_exit to call this routine before the exit * callbacks that are registered by buffer manager, lock manager, etc. diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index d1f6d2bdb0..9c35f0949a 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -4,7 +4,7 @@ * Support for grand unified configuration scheme, including SET * command, configuration file, and command line options. * - * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.63 2002/03/24 04:31:08 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.64 2002/04/01 03:34:26 tgl Exp $ * * Copyright 2000 by PostgreSQL Global Development Group * Written by Peter Eisentraut <peter_e@gmx.net>. @@ -21,6 +21,7 @@ #include "utils/guc.h" #include "access/xlog.h" +#include "catalog/namespace.h" #include "commands/async.h" #include "fmgr.h" #include "libpq/auth.h" @@ -575,6 +576,11 @@ static struct config_string }, { + "search_path", PGC_USERSET, PGC_S_DEFAULT, &namespace_search_path, + "$user,public", check_search_path, assign_search_path + }, + + { "krb_server_keyfile", PGC_POSTMASTER, PGC_S_DEFAULT, &pg_krb_server_keyfile, PG_KRB_SRVTAB, NULL, NULL }, @@ -899,7 +905,7 @@ set_config_option(const char *name, const char *value, int elevel; bool makeDefault; - if (context == PGC_SIGHUP) + if (context == PGC_SIGHUP || source == PGC_S_DEFAULT) elevel = DEBUG1; else if (guc_session_init) elevel = INFO; @@ -1414,7 +1420,7 @@ ProcessGUCArray(ArrayType *array, GucSource source) ParseLongOption(s, &name, &value); if (!value) { - elog(WARNING, "cannot to parse setting \"%s\"", name); + elog(WARNING, "cannot parse setting \"%s\"", name); continue; } diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample index a40b6ce7fa..01f55682b8 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -191,6 +191,7 @@ # Misc # #dynamic_library_path = '$libdir' +#search_path = '$user,public' #australian_timezones = false #authentication_timeout = 60 # min 1, max 600 #deadlock_timeout = 1000 |
