Create a new GUC variable search_path to control the namespace search

path.  The default behavior if no per-user schemas are created is that
all users share a 'public' namespace, thus providing behavior backwards
compatible with 7.2 and earlier releases.  Probably the semantics and
default setting will need to be fine-tuned, but this is a start.
This commit is contained in:
Tom Lane 2002-04-01 03:34:27 +00:00
parent 6df395f63a
commit 838fe25a95
13 changed files with 454 additions and 79 deletions

View File

@ -1,5 +1,5 @@
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v 1.110 2002/03/24 04:31:06 tgl Exp $
$Header: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v 1.111 2002/04/01 03:34:24 tgl Exp $
-->
<Chapter Id="runtime">
@ -1174,7 +1174,7 @@ dynamic_library_path = '/usr/local/lib/postgresql:/home/my_project/lib:$libdir'
<para>
The default value for this parameter is
<literal>$libdir</literal>. If the value is set to an empty
<literal>'$libdir'</literal>. If the value is set to an empty
string, the automatic path search is turned off.
</para>
@ -1189,6 +1189,69 @@ dynamic_library_path = '/usr/local/lib/postgresql:/home/my_project/lib:$libdir'
</listitem>
</varlistentry>
<varlistentry>
<term><varname>SEARCH_PATH</varname> (<type>string</type>)</term>
<indexterm><primary>search_path</></>
<indexterm><primary>namespaces</></>
<listitem>
<para>
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.
</para>
<para>
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 <literal>$user</literal>, then the namespace
having the same name as the SESSION_USER is substituted, if there
is such a namespace. (If not, <literal>$user</literal> is ignored.)
</para>
<para>
The system catalog namespace, <literal>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 <literal>pg_catalog</> is not in the path then it will
be searched <emphasis>before</> searching any of the path items.
It should also be noted that the temporary-table namespace,
<literal>pg_temp_nnn</>, is implicitly searched before any of
these.
</para>
<para>
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 <literal>pg_catalog</> if the search
path list is empty. (Note that users do not normally have
permission to write in <literal>pg_catalog</>, so an empty search
path is not a very useful setting.)
</para>
<para>
The default value for this parameter is
<literal>'$user, public'</literal> (where the second part will be
ignored if there is no namespace named <literal>public</>).
This supports shared use of a database (where no users
have private namespaces, and all share use of <literal>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.
</para>
<para>
By default, a newly created database will contain a world-writable
namespace named <literal>public</>, but no private namespaces.
The administrator may choose to restrict permissions on
<literal>public</> or even remove it, if that suits his purposes.
</para>
</listitem>
</varlistentry>
<varlistentry>
<indexterm>
<primary>fsync</primary>

View File

@ -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

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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"
@ -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;
}

View File

@ -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

View File

@ -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
};

View File

@ -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);

View File

@ -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 */

View File

@ -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

View File

@ -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);