Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 838fe25

Browse files
committed
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.
1 parent 6df395f commit 838fe25

File tree

13 files changed

+454
-79
lines changed

13 files changed

+454
-79
lines changed

doc/src/sgml/runtime.sgml

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$Header: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v 1.110 2002/03/24 04:31:06 tgl Exp $
2+
$Header: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v 1.111 2002/04/01 03:34:24 tgl Exp $
33
-->
44

55
<Chapter Id="runtime">
@@ -1174,7 +1174,7 @@ dynamic_library_path = '/usr/local/lib/postgresql:/home/my_project/lib:$libdir'
11741174

11751175
<para>
11761176
The default value for this parameter is
1177-
<literal>$libdir</literal>. If the value is set to an empty
1177+
<literal>'$libdir'</literal>. If the value is set to an empty
11781178
string, the automatic path search is turned off.
11791179
</para>
11801180

@@ -1189,6 +1189,69 @@ dynamic_library_path = '/usr/local/lib/postgresql:/home/my_project/lib:$libdir'
11891189
</listitem>
11901190
</varlistentry>
11911191

1192+
<varlistentry>
1193+
<term><varname>SEARCH_PATH</varname> (<type>string</type>)</term>
1194+
<indexterm><primary>search_path</></>
1195+
<indexterm><primary>namespaces</></>
1196+
<listitem>
1197+
<para>
1198+
This variable specifies the order in which namespaces are searched
1199+
when an object (table, datatype, function, etc) is referenced by a
1200+
simple name with no schema component. When there are objects of
1201+
identical names in different namespaces, the one found first
1202+
in the search path is used. An object that is not in any of the
1203+
namespaces in the search path can only be referenced by specifying
1204+
its containing namespace with a qualified (dotted) name.
1205+
</para>
1206+
1207+
<para>
1208+
The value for search_path has to be a comma-separated
1209+
list of namespace (schema) names. If one of the list items is
1210+
the special value <literal>$user</literal>, then the namespace
1211+
having the same name as the SESSION_USER is substituted, if there
1212+
is such a namespace. (If not, <literal>$user</literal> is ignored.)
1213+
</para>
1214+
1215+
<para>
1216+
The system catalog namespace, <literal>pg_catalog</>, is always
1217+
searched, whether it is mentioned in the path or not. If it is
1218+
mentioned in the path then it will be searched in the specified
1219+
order. If <literal>pg_catalog</> is not in the path then it will
1220+
be searched <emphasis>before</> searching any of the path items.
1221+
It should also be noted that the temporary-table namespace,
1222+
<literal>pg_temp_nnn</>, is implicitly searched before any of
1223+
these.
1224+
</para>
1225+
1226+
<para>
1227+
When objects are created without specifying a particular target
1228+
namespace, they will be placed in the first namespace listed
1229+
in the search path, or in <literal>pg_catalog</> if the search
1230+
path list is empty. (Note that users do not normally have
1231+
permission to write in <literal>pg_catalog</>, so an empty search
1232+
path is not a very useful setting.)
1233+
</para>
1234+
1235+
<para>
1236+
The default value for this parameter is
1237+
<literal>'$user, public'</literal> (where the second part will be
1238+
ignored if there is no namespace named <literal>public</>).
1239+
This supports shared use of a database (where no users
1240+
have private namespaces, and all share use of <literal>public</>),
1241+
private per-user namespaces, and combinations of these. Other
1242+
effects can be obtained by altering the default search path
1243+
setting, either globally or per-user.
1244+
</para>
1245+
1246+
<para>
1247+
By default, a newly created database will contain a world-writable
1248+
namespace named <literal>public</>, but no private namespaces.
1249+
The administrator may choose to restrict permissions on
1250+
<literal>public</> or even remove it, if that suits his purposes.
1251+
</para>
1252+
</listitem>
1253+
</varlistentry>
1254+
11921255
<varlistentry>
11931256
<indexterm>
11941257
<primary>fsync</primary>

src/backend/access/transam/xact.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.119 2002/03/31 06:26:29 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.120 2002/04/01 03:34:25 tgl Exp $
1212
*
1313
* NOTES
1414
* Transaction aborts can now occur two ways:
@@ -241,8 +241,10 @@ bool AMI_OVERRIDE = false;
241241
* ----------------------------------------------------------------
242242
*/
243243

244+
#ifdef NOT_USED
245+
244246
/* --------------------------------
245-
* TranactionFlushEnabled()
247+
* TransactionFlushEnabled()
246248
* SetTransactionFlushEnabled()
247249
*
248250
* These are used to test and set the "TransactionFlushState"
@@ -261,13 +263,14 @@ TransactionFlushEnabled(void)
261263
return TransactionFlushState;
262264
}
263265

264-
#ifdef NOT_USED
265266
void
266267
SetTransactionFlushEnabled(bool state)
267268
{
268269
TransactionFlushState = (state == true);
269270
}
270271

272+
#endif
273+
271274

272275
/* --------------------------------
273276
* IsTransactionState
@@ -300,7 +303,6 @@ IsTransactionState(void)
300303
*/
301304
return false;
302305
}
303-
#endif
304306

305307
/* --------------------------------
306308
* IsAbortedTransactionBlockState

src/backend/catalog/namespace.c

Lines changed: 208 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* Portions Copyright (c) 1994, Regents of the University of California
1414
*
1515
* IDENTIFICATION
16-
* $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.4 2002/03/31 06:26:30 tgl Exp $
16+
* $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.5 2002/04/01 03:34:25 tgl Exp $
1717
*
1818
*-------------------------------------------------------------------------
1919
*/
@@ -30,7 +30,9 @@
3030
#include "miscadmin.h"
3131
#include "nodes/makefuncs.h"
3232
#include "storage/backendid.h"
33+
#include "utils/builtins.h"
3334
#include "utils/fmgroids.h"
35+
#include "utils/guc.h"
3436
#include "utils/lsyscache.h"
3537
#include "utils/syscache.h"
3638

@@ -71,6 +73,12 @@ static Oid defaultCreationNamespace = PG_CATALOG_NAMESPACE;
7173
*/
7274
static Oid myTempNamespace = InvalidOid;
7375

76+
/*
77+
* This is the text equivalent of the search path --- it's the value
78+
* of the GUC variable 'search_path'.
79+
*/
80+
char *namespace_search_path = NULL;
81+
7482

7583
/*
7684
* Deletion ordering constraint item.
@@ -702,3 +710,202 @@ RemoveTempRelationsCallback(void)
702710
CommitTransactionCommand();
703711
}
704712
}
713+
714+
/*
715+
* Routines for handling the GUC variable 'search_path'.
716+
*/
717+
718+
/* parse_hook: is proposed value valid? */
719+
bool
720+
check_search_path(const char *proposed)
721+
{
722+
char *rawname;
723+
List *namelist;
724+
List *l;
725+
726+
/* Need a modifiable copy of string */
727+
rawname = pstrdup(proposed);
728+
729+
/* Parse string into list of identifiers */
730+
if (!SplitIdentifierString(rawname, ',', &namelist))
731+
{
732+
/* syntax error in name list */
733+
pfree(rawname);
734+
freeList(namelist);
735+
return false;
736+
}
737+
738+
/*
739+
* If we aren't inside a transaction, we cannot do database access so
740+
* cannot verify the individual names. Must accept the list on faith.
741+
* (This case can happen, for example, when the postmaster reads a
742+
* search_path setting from postgresql.conf.)
743+
*/
744+
if (!IsTransactionState())
745+
{
746+
pfree(rawname);
747+
freeList(namelist);
748+
return true;
749+
}
750+
751+
/*
752+
* Verify that all the names are either valid namespace names or "$user".
753+
* (We do not require $user to correspond to a valid namespace; should we?)
754+
*/
755+
foreach(l, namelist)
756+
{
757+
char *curname = (char *) lfirst(l);
758+
759+
if (strcmp(curname, "$user") == 0)
760+
continue;
761+
if (!SearchSysCacheExists(NAMESPACENAME,
762+
CStringGetDatum(curname),
763+
0, 0, 0))
764+
{
765+
pfree(rawname);
766+
freeList(namelist);
767+
return false;
768+
}
769+
}
770+
771+
pfree(rawname);
772+
freeList(namelist);
773+
774+
return true;
775+
}
776+
777+
/* assign_hook: do extra actions needed when assigning to search_path */
778+
void
779+
assign_search_path(const char *newval)
780+
{
781+
char *rawname;
782+
List *namelist;
783+
List *oidlist;
784+
List *newpath;
785+
List *l;
786+
MemoryContext oldcxt;
787+
788+
/*
789+
* If we aren't inside a transaction, we cannot do database access so
790+
* cannot look up the names. In this case, do nothing; the internal
791+
* search path will be fixed later by InitializeSearchPath. (We assume
792+
* this situation can only happen in the postmaster or early in backend
793+
* startup.)
794+
*/
795+
if (!IsTransactionState())
796+
return;
797+
798+
/* Need a modifiable copy of string */
799+
rawname = pstrdup(newval);
800+
801+
/* Parse string into list of identifiers */
802+
if (!SplitIdentifierString(rawname, ',', &namelist))
803+
{
804+
/* syntax error in name list */
805+
/* this should not happen if GUC checked check_search_path */
806+
elog(ERROR, "assign_search_path: invalid list syntax");
807+
}
808+
809+
/*
810+
* Convert the list of names to a list of OIDs. If any names are not
811+
* recognizable, just leave them out of the list. (This is our only
812+
* reasonable recourse when the already-accepted default is bogus.)
813+
*/
814+
oidlist = NIL;
815+
foreach(l, namelist)
816+
{
817+
char *curname = (char *) lfirst(l);
818+
Oid namespaceId;
819+
820+
if (strcmp(curname, "$user") == 0)
821+
{
822+
/* $user --- substitute namespace matching user name, if any */
823+
HeapTuple tuple;
824+
825+
tuple = SearchSysCache(SHADOWSYSID,
826+
ObjectIdGetDatum(GetSessionUserId()),
827+
0, 0, 0);
828+
if (HeapTupleIsValid(tuple))
829+
{
830+
char *uname;
831+
832+
uname = NameStr(((Form_pg_shadow) GETSTRUCT(tuple))->usename);
833+
namespaceId = GetSysCacheOid(NAMESPACENAME,
834+
CStringGetDatum(uname),
835+
0, 0, 0);
836+
if (OidIsValid(namespaceId))
837+
oidlist = lappendi(oidlist, namespaceId);
838+
ReleaseSysCache(tuple);
839+
}
840+
}
841+
else
842+
{
843+
/* normal namespace reference */
844+
namespaceId = GetSysCacheOid(NAMESPACENAME,
845+
CStringGetDatum(curname),
846+
0, 0, 0);
847+
if (OidIsValid(namespaceId))
848+
oidlist = lappendi(oidlist, namespaceId);
849+
}
850+
}
851+
852+
/*
853+
* Now that we've successfully built the new list of namespace OIDs,
854+
* save it in permanent storage.
855+
*/
856+
oldcxt = MemoryContextSwitchTo(TopMemoryContext);
857+
newpath = listCopy(oidlist);
858+
MemoryContextSwitchTo(oldcxt);
859+
860+
/* Now safe to assign to state variable. */
861+
freeList(namespaceSearchPath);
862+
namespaceSearchPath = newpath;
863+
864+
/*
865+
* Update info derived from search path.
866+
*/
867+
pathContainsSystemNamespace = intMember(PG_CATALOG_NAMESPACE,
868+
namespaceSearchPath);
869+
870+
if (namespaceSearchPath == NIL)
871+
defaultCreationNamespace = PG_CATALOG_NAMESPACE;
872+
else
873+
defaultCreationNamespace = (Oid) lfirsti(namespaceSearchPath);
874+
875+
/* Clean up. */
876+
pfree(rawname);
877+
freeList(namelist);
878+
freeList(oidlist);
879+
}
880+
881+
/*
882+
* InitializeSearchPath: initialize module during InitPostgres.
883+
*
884+
* This is called after we are up enough to be able to do catalog lookups.
885+
*/
886+
void
887+
InitializeSearchPath(void)
888+
{
889+
/*
890+
* In normal multi-user mode, we want the default search path to be
891+
* '$user,public' (or as much of that as exists, anyway; see the
892+
* error handling in assign_search_path); which is what guc.c has as
893+
* the wired-in default value. But in bootstrap or standalone-backend
894+
* mode, the default search path must be empty so that initdb correctly
895+
* creates everything in PG_CATALOG_NAMESPACE. Accordingly, adjust the
896+
* default setting if we are not running under postmaster. (If a
897+
* non-default setting has been supplied, this will not overwrite it.)
898+
*/
899+
if (!IsUnderPostmaster)
900+
{
901+
SetConfigOption("search_path", "",
902+
PGC_POSTMASTER, PGC_S_DEFAULT);
903+
}
904+
/*
905+
* If a search path setting was provided before we were able to execute
906+
* lookups, establish the internal search path now.
907+
*/
908+
if (namespace_search_path && *namespace_search_path &&
909+
namespaceSearchPath == NIL)
910+
assign_search_path(namespace_search_path);
911+
}

0 commit comments

Comments
 (0)