diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml index 9c118d2be2..43b6931fe1 100644 --- a/doc/src/sgml/runtime.sgml +++ b/doc/src/sgml/runtime.sgml @@ -1,5 +1,5 @@ @@ -1174,7 +1174,7 @@ dynamic_library_path = '/usr/local/lib/postgresql:/home/my_project/lib:$libdir' The default value for this parameter is - $libdir. If the value is set to an empty + '$libdir'. If the value is set to an empty string, the automatic path search is turned off. @@ -1189,6 +1189,69 @@ dynamic_library_path = '/usr/local/lib/postgresql:/home/my_project/lib:$libdir' + + SEARCH_PATH (string) + search_path + namespaces + + + This variable specifies the order in which namespaces are searched + when an object (table, datatype, function, etc) is referenced by a + simple name with no schema component. When there are objects of + identical names in different namespaces, the one found first + in the search path is used. An object that is not in any of the + namespaces in the search path can only be referenced by specifying + its containing namespace with a qualified (dotted) name. + + + + The value for search_path has to be a comma-separated + list of namespace (schema) names. If one of the list items is + the special value $user, then the namespace + having the same name as the SESSION_USER is substituted, if there + is such a namespace. (If not, $user is ignored.) + + + + The system catalog namespace, pg_catalog, is always + searched, whether it is mentioned in the path or not. If it is + mentioned in the path then it will be searched in the specified + order. If pg_catalog is not in the path then it will + be searched before searching any of the path items. + It should also be noted that the temporary-table namespace, + pg_temp_nnn, is implicitly searched before any of + these. + + + + When objects are created without specifying a particular target + namespace, they will be placed in the first namespace listed + in the search path, or in pg_catalog if the search + path list is empty. (Note that users do not normally have + permission to write in pg_catalog, so an empty search + path is not a very useful setting.) + + + + The default value for this parameter is + '$user, public' (where the second part will be + ignored if there is no namespace named public). + This supports shared use of a database (where no users + have private namespaces, and all share use of public), + private per-user namespaces, and combinations of these. Other + effects can be obtained by altering the default search path + setting, either globally or per-user. + + + + By default, a newly created database will contain a world-writable + namespace named public, but no private namespaces. + The administrator may choose to restrict permissions on + public or even remove it, if that suits his purposes. + + + + fsync diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c index 046f3d52aa..ca66b0afaf 100644 --- a/src/backend/access/transam/xact.c +++ b/src/backend/access/transam/xact.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.119 2002/03/31 06:26:29 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.120 2002/04/01 03:34:25 tgl Exp $ * * NOTES * Transaction aborts can now occur two ways: @@ -241,8 +241,10 @@ bool AMI_OVERRIDE = false; * ---------------------------------------------------------------- */ +#ifdef NOT_USED + /* -------------------------------- - * TranactionFlushEnabled() + * TransactionFlushEnabled() * SetTransactionFlushEnabled() * * These are used to test and set the "TransactionFlushState" @@ -261,13 +263,14 @@ TransactionFlushEnabled(void) return TransactionFlushState; } -#ifdef NOT_USED void SetTransactionFlushEnabled(bool state) { TransactionFlushState = (state == true); } +#endif + /* -------------------------------- * IsTransactionState @@ -300,7 +303,6 @@ IsTransactionState(void) */ return false; } -#endif /* -------------------------------- * IsAbortedTransactionBlockState diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c index a1be64bd80..fab1912b1b 100644 --- a/src/backend/catalog/namespace.c +++ b/src/backend/catalog/namespace.c @@ -13,7 +13,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.4 2002/03/31 06:26:30 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.5 2002/04/01 03:34:25 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -30,7 +30,9 @@ #include "miscadmin.h" #include "nodes/makefuncs.h" #include "storage/backendid.h" +#include "utils/builtins.h" #include "utils/fmgroids.h" +#include "utils/guc.h" #include "utils/lsyscache.h" #include "utils/syscache.h" @@ -71,6 +73,12 @@ static Oid defaultCreationNamespace = PG_CATALOG_NAMESPACE; */ static Oid myTempNamespace = InvalidOid; +/* + * This is the text equivalent of the search path --- it's the value + * of the GUC variable 'search_path'. + */ +char *namespace_search_path = NULL; + /* * Deletion ordering constraint item. @@ -702,3 +710,202 @@ RemoveTempRelationsCallback(void) CommitTransactionCommand(); } } + +/* + * Routines for handling the GUC variable 'search_path'. + */ + +/* parse_hook: is proposed value valid? */ +bool +check_search_path(const char *proposed) +{ + char *rawname; + List *namelist; + List *l; + + /* Need a modifiable copy of string */ + rawname = pstrdup(proposed); + + /* Parse string into list of identifiers */ + if (!SplitIdentifierString(rawname, ',', &namelist)) + { + /* syntax error in name list */ + pfree(rawname); + freeList(namelist); + return false; + } + + /* + * If we aren't inside a transaction, we cannot do database access so + * cannot verify the individual names. Must accept the list on faith. + * (This case can happen, for example, when the postmaster reads a + * search_path setting from postgresql.conf.) + */ + if (!IsTransactionState()) + { + pfree(rawname); + freeList(namelist); + return true; + } + + /* + * Verify that all the names are either valid namespace names or "$user". + * (We do not require $user to correspond to a valid namespace; should we?) + */ + foreach(l, namelist) + { + char *curname = (char *) lfirst(l); + + if (strcmp(curname, "$user") == 0) + continue; + if (!SearchSysCacheExists(NAMESPACENAME, + CStringGetDatum(curname), + 0, 0, 0)) + { + pfree(rawname); + freeList(namelist); + return false; + } + } + + pfree(rawname); + freeList(namelist); + + return true; +} + +/* assign_hook: do extra actions needed when assigning to search_path */ +void +assign_search_path(const char *newval) +{ + char *rawname; + List *namelist; + List *oidlist; + List *newpath; + List *l; + MemoryContext oldcxt; + + /* + * If we aren't inside a transaction, we cannot do database access so + * cannot look up the names. In this case, do nothing; the internal + * search path will be fixed later by InitializeSearchPath. (We assume + * this situation can only happen in the postmaster or early in backend + * startup.) + */ + if (!IsTransactionState()) + return; + + /* Need a modifiable copy of string */ + rawname = pstrdup(newval); + + /* Parse string into list of identifiers */ + if (!SplitIdentifierString(rawname, ',', &namelist)) + { + /* syntax error in name list */ + /* this should not happen if GUC checked check_search_path */ + elog(ERROR, "assign_search_path: invalid list syntax"); + } + + /* + * Convert the list of names to a list of OIDs. If any names are not + * recognizable, just leave them out of the list. (This is our only + * reasonable recourse when the already-accepted default is bogus.) + */ + oidlist = NIL; + foreach(l, namelist) + { + char *curname = (char *) lfirst(l); + Oid namespaceId; + + if (strcmp(curname, "$user") == 0) + { + /* $user --- substitute namespace matching user name, if any */ + HeapTuple tuple; + + tuple = SearchSysCache(SHADOWSYSID, + ObjectIdGetDatum(GetSessionUserId()), + 0, 0, 0); + if (HeapTupleIsValid(tuple)) + { + char *uname; + + uname = NameStr(((Form_pg_shadow) GETSTRUCT(tuple))->usename); + namespaceId = GetSysCacheOid(NAMESPACENAME, + CStringGetDatum(uname), + 0, 0, 0); + if (OidIsValid(namespaceId)) + oidlist = lappendi(oidlist, namespaceId); + ReleaseSysCache(tuple); + } + } + else + { + /* normal namespace reference */ + namespaceId = GetSysCacheOid(NAMESPACENAME, + CStringGetDatum(curname), + 0, 0, 0); + if (OidIsValid(namespaceId)) + oidlist = lappendi(oidlist, namespaceId); + } + } + + /* + * Now that we've successfully built the new list of namespace OIDs, + * save it in permanent storage. + */ + oldcxt = MemoryContextSwitchTo(TopMemoryContext); + newpath = listCopy(oidlist); + MemoryContextSwitchTo(oldcxt); + + /* Now safe to assign to state variable. */ + freeList(namespaceSearchPath); + namespaceSearchPath = newpath; + + /* + * Update info derived from search path. + */ + pathContainsSystemNamespace = intMember(PG_CATALOG_NAMESPACE, + namespaceSearchPath); + + if (namespaceSearchPath == NIL) + defaultCreationNamespace = PG_CATALOG_NAMESPACE; + else + defaultCreationNamespace = (Oid) lfirsti(namespaceSearchPath); + + /* Clean up. */ + pfree(rawname); + freeList(namelist); + freeList(oidlist); +} + +/* + * InitializeSearchPath: initialize module during InitPostgres. + * + * This is called after we are up enough to be able to do catalog lookups. + */ +void +InitializeSearchPath(void) +{ + /* + * In normal multi-user mode, we want the default search path to be + * '$user,public' (or as much of that as exists, anyway; see the + * error handling in assign_search_path); which is what guc.c has as + * the wired-in default value. But in bootstrap or standalone-backend + * mode, the default search path must be empty so that initdb correctly + * creates everything in PG_CATALOG_NAMESPACE. Accordingly, adjust the + * default setting if we are not running under postmaster. (If a + * non-default setting has been supplied, this will not overwrite it.) + */ + if (!IsUnderPostmaster) + { + SetConfigOption("search_path", "", + PGC_POSTMASTER, PGC_S_DEFAULT); + } + /* + * If a search path setting was provided before we were able to execute + * lookups, establish the internal search path now. + */ + if (namespace_search_path && *namespace_search_path && + namespaceSearchPath == NIL) + assign_search_path(namespace_search_path); +} diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 4ebddde891..64cc3d60ca 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.297 2002/03/29 19:06:10 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.298 2002/04/01 03:34:25 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -94,6 +94,7 @@ static void insertSelectOptions(SelectStmt *stmt, static Node *makeSetOp(SetOperation op, bool all, Node *larg, Node *rarg); static Node *doNegate(Node *n); static void doNegateFloat(Value *v); +static bool set_name_needs_quotes(const char *name); #define MASK(b) (1 << (b)) @@ -909,19 +910,26 @@ var_value: opt_boolean { $$ = $1; } if ($1 == NIL) elog(ERROR, "SET must have at least one argument"); + /* compute space needed; allow for quotes and comma */ foreach (n, $1) { Value *p = (Value *) lfirst(n); Assert(IsA(p, String)); - /* keep track of room for string and trailing comma */ - slen += (strlen(p->val.str) + 1); + slen += (strlen(p->val.str) + 3); } result = palloc(slen + 1); *result = '\0'; foreach (n, $1) { Value *p = (Value *) lfirst(n); - strcat(result, p->val.str); + if (set_name_needs_quotes(p->val.str)) + { + strcat(result, "\""); + strcat(result, p->val.str); + strcat(result, "\""); + } + else + strcat(result, p->val.str); strcat(result, ","); } /* remove the trailing comma from the last element */ @@ -6568,3 +6576,25 @@ doNegateFloat(Value *v) v->val.str = newval; } } + +/* + * Decide whether to put double quotes around a name appearing in a SET + * name_list. Presently, do so if the name contains whitespace, commas, + * or uppercase characters. (This is correct assuming that the result + * will be deparsed by SplitIdentifierString or similar logic.) + */ +static bool +set_name_needs_quotes(const char *name) +{ + if (*name == '\0') + return true; /* empty name does need quotes */ + while (*name) + { + if (*name == ',' || + isspace((unsigned char) *name) || + isupper((unsigned char) *name)) + return true; + name++; + } + return false; +} 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 @@ -384,6 +380,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 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 . @@ -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" @@ -574,6 +575,11 @@ static struct config_string "$libdir", NULL, NULL }, + { + "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 diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c index 003ec9fe33..f25a45ef62 100644 --- a/src/bin/psql/tab-complete.c +++ b/src/bin/psql/tab-complete.c @@ -3,7 +3,7 @@ * * Copyright 2000 by PostgreSQL Global Development Group * - * $Header: /cvsroot/pgsql/src/bin/psql/tab-complete.c,v 1.46 2002/03/24 04:31:08 tgl Exp $ + * $Header: /cvsroot/pgsql/src/bin/psql/tab-complete.c,v 1.47 2002/04/01 03:34:27 tgl Exp $ */ /*---------------------------------------------------------------------- @@ -267,6 +267,7 @@ psql_completion(char *text, int start, int end) "geqo_selection_bias", "default_transaction_isolation", + "search_path", NULL }; diff --git a/src/include/access/xact.h b/src/include/access/xact.h index 796a053836..0cfc1652f2 100644 --- a/src/include/access/xact.h +++ b/src/include/access/xact.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: xact.h,v 1.41 2001/11/05 17:46:31 momjian Exp $ + * $Id: xact.h,v 1.42 2002/04/01 03:34:27 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -97,9 +97,7 @@ typedef struct xl_xact_abort * extern definitions * ---------------- */ -extern int TransactionFlushEnabled(void); -extern void SetTransactionFlushEnabled(bool state); - +extern bool IsTransactionState(void); extern bool IsAbortedTransactionBlockState(void); extern TransactionId GetCurrentTransactionId(void); extern CommandId GetCurrentCommandId(void); diff --git a/src/include/catalog/namespace.h b/src/include/catalog/namespace.h index aed33a10b3..a8a64bd7db 100644 --- a/src/include/catalog/namespace.h +++ b/src/include/catalog/namespace.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: namespace.h,v 1.4 2002/03/31 06:26:32 tgl Exp $ + * $Id: namespace.h,v 1.5 2002/04/01 03:34:27 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -31,4 +31,11 @@ extern RangeVar *makeRangeVarFromNameList(List *names); extern bool isTempNamespace(Oid namespaceId); +/* stuff for search_path GUC variable */ +extern char *namespace_search_path; + +extern bool check_search_path(const char *proposed); +extern void assign_search_path(const char *newval); +extern void InitializeSearchPath(void); + #endif /* NAMESPACE_H */ diff --git a/src/include/catalog/pg_namespace.h b/src/include/catalog/pg_namespace.h index fceee09fcb..d058206dae 100644 --- a/src/include/catalog/pg_namespace.h +++ b/src/include/catalog/pg_namespace.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: pg_namespace.h,v 1.3 2002/03/31 06:26:32 tgl Exp $ + * $Id: pg_namespace.h,v 1.4 2002/04/01 03:34:27 tgl Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki @@ -72,7 +72,7 @@ DESCR("System catalog namespace"); DATA(insert OID = 99 ( "pg_toast" PGUID "{=}" )); DESCR("Reserved namespace for TOAST tables"); #define PG_TOAST_NAMESPACE 99 -DATA(insert OID = 2071 ( "pg_public" PGUID "{=rw}" )); +DATA(insert OID = 2071 ( "public" PGUID "{=rw}" )); DESCR("Standard public namespace"); #define PG_PUBLIC_NAMESPACE 2071 diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index 7bd111cd54..342aa4e99f 100644 --- a/src/include/utils/builtins.h +++ b/src/include/utils/builtins.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: builtins.h,v 1.174 2002/03/30 01:02:42 tgl Exp $ + * $Id: builtins.h,v 1.175 2002/04/01 03:34:27 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -411,6 +411,8 @@ extern Datum name_text(PG_FUNCTION_ARGS); extern Datum text_name(PG_FUNCTION_ARGS); extern int varstr_cmp(char *arg1, int len1, char *arg2, int len2); extern List *textToQualifiedNameList(text *textval, const char *caller); +extern bool SplitIdentifierString(char *rawstring, char separator, + List **namelist); extern Datum byteain(PG_FUNCTION_ARGS); extern Datum byteaout(PG_FUNCTION_ARGS);