1
/*-------------------------------------------------------------------------
4
* code to support accessing and searching namespaces
6
* This is separate from pg_namespace.c, which contains the routines that
7
* directly manipulate the pg_namespace system catalog. This module
8
* provides routines associated with defining a "namespace search path"
9
* and implementing search-path-controlled searches.
12
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
13
* Portions Copyright (c) 1994, Regents of the University of California
16
* $PostgreSQL: pgsql/src/backend/catalog/namespace.c,v 1.73 2004-12-31 21:59:38 pgsql Exp $
18
*-------------------------------------------------------------------------
22
#include "access/xact.h"
23
#include "catalog/catname.h"
24
#include "catalog/dependency.h"
25
#include "catalog/namespace.h"
26
#include "catalog/pg_conversion.h"
27
#include "catalog/pg_namespace.h"
28
#include "catalog/pg_opclass.h"
29
#include "catalog/pg_operator.h"
30
#include "catalog/pg_proc.h"
31
#include "catalog/pg_shadow.h"
32
#include "catalog/pg_type.h"
33
#include "commands/dbcommands.h"
34
#include "lib/stringinfo.h"
35
#include "miscadmin.h"
36
#include "nodes/makefuncs.h"
37
#include "storage/backendid.h"
38
#include "storage/ipc.h"
39
#include "utils/acl.h"
40
#include "utils/builtins.h"
41
#include "utils/catcache.h"
42
#include "utils/guc.h"
43
#include "utils/inval.h"
44
#include "utils/lsyscache.h"
45
#include "utils/memutils.h"
46
#include "utils/syscache.h"
50
* The namespace search path is a possibly-empty list of namespace OIDs.
51
* In addition to the explicit list, several implicitly-searched namespaces
54
* 1. If a "special" namespace has been set by PushSpecialNamespace, it is
55
* always searched first. (This is a hack for CREATE SCHEMA.)
57
* 2. If a TEMP table namespace has been initialized in this session, it
58
* is always searched just after any special namespace.
60
* 3. The system catalog namespace is always searched. If the system
61
* namespace is present in the explicit path then it will be searched in
62
* the specified order; otherwise it will be searched after TEMP tables and
63
* *before* the explicit list. (It might seem that the system namespace
64
* should be implicitly last, but this behavior appears to be required by
65
* SQL99. Also, this provides a way to search the system namespace first
66
* without thereby making it the default creation target namespace.)
68
* The default creation target namespace is normally equal to the first
69
* element of the explicit list, but is the "special" namespace when one
70
* has been set. If the explicit list is empty and there is no special
71
* namespace, there is no default target.
73
* In bootstrap mode, the search path is set equal to 'pg_catalog', so that
74
* the system namespace is the only one searched or inserted into.
75
* The initdb script is also careful to set search_path to 'pg_catalog' for
76
* its post-bootstrap standalone backend runs. Otherwise the default search
77
* path is determined by GUC. The factory default path contains the PUBLIC
78
* namespace (if it exists), preceded by the user's personal namespace
81
* If namespaceSearchPathValid is false, then namespaceSearchPath (and other
82
* derived variables) need to be recomputed from namespace_search_path.
83
* We mark it invalid upon an assignment to namespace_search_path or receipt
84
* of a syscache invalidation event for pg_namespace. The recomputation
85
* is done during the next lookup attempt.
87
* Any namespaces mentioned in namespace_search_path that are not readable
88
* by the current user ID are simply left out of namespaceSearchPath; so
89
* we have to be willing to recompute the path when current userid changes.
90
* namespaceUser is the userid the path has been computed for.
93
static List *namespaceSearchPath = NIL;
95
static Oid namespaceUser = InvalidOid;
97
/* default place to create stuff; if InvalidOid, no default */
98
static Oid defaultCreationNamespace = InvalidOid;
100
/* first explicit member of list; usually same as defaultCreationNamespace */
101
static Oid firstExplicitNamespace = InvalidOid;
103
/* The above four values are valid only if namespaceSearchPathValid */
104
static bool namespaceSearchPathValid = true;
107
* myTempNamespace is InvalidOid until and unless a TEMP namespace is set up
108
* in a particular backend session (this happens when a CREATE TEMP TABLE
109
* command is first executed). Thereafter it's the OID of the temp namespace.
111
* myTempNamespaceSubID shows whether we've created the TEMP namespace in the
112
* current subtransaction. The flag propagates up the subtransaction tree,
113
* so the main transaction will correctly recognize the flag if all
114
* intermediate subtransactions commit. When it is InvalidSubTransactionId,
115
* we either haven't made the TEMP namespace yet, or have successfully
116
* committed its creation, depending on whether myTempNamespace is valid.
118
static Oid myTempNamespace = InvalidOid;
120
static SubTransactionId myTempNamespaceSubID = InvalidSubTransactionId;
123
* "Special" namespace for CREATE SCHEMA. If set, it's the first search
124
* path element, and also the default creation namespace.
126
static Oid mySpecialNamespace = InvalidOid;
129
* This is the text equivalent of the search path --- it's the value
130
* of the GUC variable 'search_path'.
132
char *namespace_search_path = NULL;
135
/* Local functions */
136
static void recomputeNamespacePath(void);
137
static void InitTempTableNamespace(void);
138
static void RemoveTempRelations(Oid tempNamespaceId);
139
static void RemoveTempRelationsCallback(int code, Datum arg);
140
static void NamespaceCallback(Datum arg, Oid relid);
142
/* These don't really need to appear in any header file */
143
Datum pg_table_is_visible(PG_FUNCTION_ARGS);
144
Datum pg_type_is_visible(PG_FUNCTION_ARGS);
145
Datum pg_function_is_visible(PG_FUNCTION_ARGS);
146
Datum pg_operator_is_visible(PG_FUNCTION_ARGS);
147
Datum pg_opclass_is_visible(PG_FUNCTION_ARGS);
148
Datum pg_conversion_is_visible(PG_FUNCTION_ARGS);
153
* Given a RangeVar describing an existing relation,
154
* select the proper namespace and look up the relation OID.
156
* If the relation is not found, return InvalidOid if failOK = true,
157
* otherwise raise an error.
160
RangeVarGetRelid(const RangeVar *relation, bool failOK)
166
* We check the catalog name and then ignore it.
168
if (relation->catalogname)
170
if (strcmp(relation->catalogname, get_database_name(MyDatabaseId)) != 0)
172
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
173
errmsg("cross-database references are not implemented: \"%s.%s.%s\"",
174
relation->catalogname, relation->schemaname,
175
relation->relname)));
178
if (relation->schemaname)
180
/* use exact schema given */
181
namespaceId = LookupExplicitNamespace(relation->schemaname);
182
relId = get_relname_relid(relation->relname, namespaceId);
186
/* search the namespace path */
187
relId = RelnameGetRelid(relation->relname);
190
if (!OidIsValid(relId) && !failOK)
192
if (relation->schemaname)
194
(errcode(ERRCODE_UNDEFINED_TABLE),
195
errmsg("relation \"%s.%s\" does not exist",
196
relation->schemaname, relation->relname)));
199
(errcode(ERRCODE_UNDEFINED_TABLE),
200
errmsg("relation \"%s\" does not exist",
201
relation->relname)));
207
* RangeVarGetCreationNamespace
208
* Given a RangeVar describing a to-be-created relation,
209
* choose which namespace to create it in.
211
* Note: calling this may result in a CommandCounterIncrement operation.
212
* That will happen on the first request for a temp table in any particular
213
* backend run; we will need to either create or clean out the temp schema.
216
RangeVarGetCreationNamespace(const RangeVar *newRelation)
221
* We check the catalog name and then ignore it.
223
if (newRelation->catalogname)
225
if (strcmp(newRelation->catalogname, get_database_name(MyDatabaseId)) != 0)
227
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
228
errmsg("cross-database references are not implemented: \"%s.%s.%s\"",
229
newRelation->catalogname, newRelation->schemaname,
230
newRelation->relname)));
233
if (newRelation->istemp)
235
/* TEMP tables are created in our backend-local temp namespace */
236
if (newRelation->schemaname)
238
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
239
errmsg("temporary tables may not specify a schema name")));
240
/* Initialize temp namespace if first time through */
241
if (!OidIsValid(myTempNamespace))
242
InitTempTableNamespace();
243
return myTempNamespace;
246
if (newRelation->schemaname)
248
/* use exact schema given */
249
namespaceId = GetSysCacheOid(NAMESPACENAME,
250
CStringGetDatum(newRelation->schemaname),
252
if (!OidIsValid(namespaceId))
254
(errcode(ERRCODE_UNDEFINED_SCHEMA),
255
errmsg("schema \"%s\" does not exist",
256
newRelation->schemaname)));
257
/* we do not check for USAGE rights here! */
261
/* use the default creation namespace */
262
recomputeNamespacePath();
263
namespaceId = defaultCreationNamespace;
264
if (!OidIsValid(namespaceId))
266
(errcode(ERRCODE_UNDEFINED_SCHEMA),
267
errmsg("no schema has been selected to create in")));
270
/* Note: callers will check for CREATE rights when appropriate */
277
* Try to resolve an unqualified relation name.
278
* Returns OID if relation found in search path, else InvalidOid.
281
RelnameGetRelid(const char *relname)
286
recomputeNamespacePath();
288
foreach(l, namespaceSearchPath)
290
Oid namespaceId = lfirst_oid(l);
292
relid = get_relname_relid(relname, namespaceId);
293
if (OidIsValid(relid))
297
/* Not found in path */
304
* Determine whether a relation (identified by OID) is visible in the
305
* current search path. Visible means "would be found by searching
306
* for the unqualified relation name".
309
RelationIsVisible(Oid relid)
312
Form_pg_class relform;
316
reltup = SearchSysCache(RELOID,
317
ObjectIdGetDatum(relid),
319
if (!HeapTupleIsValid(reltup))
320
elog(ERROR, "cache lookup failed for relation %u", relid);
321
relform = (Form_pg_class) GETSTRUCT(reltup);
323
recomputeNamespacePath();
326
* Quick check: if it ain't in the path at all, it ain't visible.
327
* Items in the system namespace are surely in the path and so we
328
* needn't even do list_member_oid() for them.
330
relnamespace = relform->relnamespace;
331
if (relnamespace != PG_CATALOG_NAMESPACE &&
332
!list_member_oid(namespaceSearchPath, relnamespace))
337
* If it is in the path, it might still not be visible; it could
338
* be hidden by another relation of the same name earlier in the
339
* path. So we must do a slow check to see if this rel would be
340
* found by RelnameGetRelid.
342
char *relname = NameStr(relform->relname);
344
visible = (RelnameGetRelid(relname) == relid);
347
ReleaseSysCache(reltup);
355
* Try to resolve an unqualified datatype name.
356
* Returns OID if type found in search path, else InvalidOid.
358
* This is essentially the same as RelnameGetRelid.
361
TypenameGetTypid(const char *typname)
366
recomputeNamespacePath();
368
foreach(l, namespaceSearchPath)
370
Oid namespaceId = lfirst_oid(l);
372
typid = GetSysCacheOid(TYPENAMENSP,
373
PointerGetDatum(typname),
374
ObjectIdGetDatum(namespaceId),
376
if (OidIsValid(typid))
380
/* Not found in path */
386
* Determine whether a type (identified by OID) is visible in the
387
* current search path. Visible means "would be found by searching
388
* for the unqualified type name".
391
TypeIsVisible(Oid typid)
394
Form_pg_type typform;
398
typtup = SearchSysCache(TYPEOID,
399
ObjectIdGetDatum(typid),
401
if (!HeapTupleIsValid(typtup))
402
elog(ERROR, "cache lookup failed for type %u", typid);
403
typform = (Form_pg_type) GETSTRUCT(typtup);
405
recomputeNamespacePath();
408
* Quick check: if it ain't in the path at all, it ain't visible.
409
* Items in the system namespace are surely in the path and so we
410
* needn't even do list_member_oid() for them.
412
typnamespace = typform->typnamespace;
413
if (typnamespace != PG_CATALOG_NAMESPACE &&
414
!list_member_oid(namespaceSearchPath, typnamespace))
419
* If it is in the path, it might still not be visible; it could
420
* be hidden by another type of the same name earlier in the path.
421
* So we must do a slow check to see if this type would be found
422
* by TypenameGetTypid.
424
char *typname = NameStr(typform->typname);
426
visible = (TypenameGetTypid(typname) == typid);
429
ReleaseSysCache(typtup);
436
* FuncnameGetCandidates
437
* Given a possibly-qualified function name and argument count,
438
* retrieve a list of the possible matches.
440
* If nargs is -1, we return all functions matching the given name,
441
* regardless of argument count.
443
* We search a single namespace if the function name is qualified, else
444
* all namespaces in the search path. The return list will never contain
445
* multiple entries with identical argument lists --- in the multiple-
446
* namespace case, we arrange for entries in earlier namespaces to mask
447
* identical entries in later namespaces.
450
FuncnameGetCandidates(List *names, int nargs)
452
FuncCandidateList resultList = NULL;
459
/* deconstruct the name list */
460
DeconstructQualifiedName(names, &schemaname, &funcname);
464
/* use exact schema given */
465
namespaceId = LookupExplicitNamespace(schemaname);
469
/* flag to indicate we need namespace search */
470
namespaceId = InvalidOid;
471
recomputeNamespacePath();
474
/* Search syscache by name and (optionally) nargs only */
476
catlist = SearchSysCacheList(PROCNAMENSP, 2,
477
CStringGetDatum(funcname),
478
Int16GetDatum(nargs),
481
catlist = SearchSysCacheList(PROCNAMENSP, 1,
482
CStringGetDatum(funcname),
485
for (i = 0; i < catlist->n_members; i++)
487
HeapTuple proctup = &catlist->members[i]->tuple;
488
Form_pg_proc procform = (Form_pg_proc) GETSTRUCT(proctup);
490
FuncCandidateList newResult;
492
nargs = procform->pronargs;
494
if (OidIsValid(namespaceId))
496
/* Consider only procs in specified namespace */
497
if (procform->pronamespace != namespaceId)
499
/* No need to check args, they must all be different */
503
/* Consider only procs that are in the search path */
506
foreach(nsp, namespaceSearchPath)
508
if (procform->pronamespace == lfirst_oid(nsp))
513
continue; /* proc is not in search path */
516
* Okay, it's in the search path, but does it have the same
517
* arguments as something we already accepted? If so, keep
518
* only the one that appears earlier in the search path.
520
* If we have an ordered list from SearchSysCacheList (the normal
521
* case), then any conflicting proc must immediately adjoin
522
* this one in the list, so we only need to look at the newest
523
* result item. If we have an unordered list, we have to scan
524
* the whole result list.
528
FuncCandidateList prevResult;
530
if (catlist->ordered)
532
if (nargs == resultList->nargs &&
533
memcmp(procform->proargtypes, resultList->args,
534
nargs * sizeof(Oid)) == 0)
535
prevResult = resultList;
541
for (prevResult = resultList;
543
prevResult = prevResult->next)
545
if (nargs == prevResult->nargs &&
546
memcmp(procform->proargtypes, prevResult->args,
547
nargs * sizeof(Oid)) == 0)
553
/* We have a match with a previous result */
554
Assert(pathpos != prevResult->pathpos);
555
if (pathpos > prevResult->pathpos)
556
continue; /* keep previous result */
557
/* replace previous result */
558
prevResult->pathpos = pathpos;
559
prevResult->oid = HeapTupleGetOid(proctup);
560
continue; /* args are same, of course */
566
* Okay to add it to result list
568
newResult = (FuncCandidateList)
569
palloc(sizeof(struct _FuncCandidateList) - sizeof(Oid)
570
+ nargs * sizeof(Oid));
571
newResult->pathpos = pathpos;
572
newResult->oid = HeapTupleGetOid(proctup);
573
newResult->nargs = nargs;
574
memcpy(newResult->args, procform->proargtypes, nargs * sizeof(Oid));
576
newResult->next = resultList;
577
resultList = newResult;
580
ReleaseSysCacheList(catlist);
587
* Determine whether a function (identified by OID) is visible in the
588
* current search path. Visible means "would be found by searching
589
* for the unqualified function name with exact argument matches".
592
FunctionIsVisible(Oid funcid)
595
Form_pg_proc procform;
599
proctup = SearchSysCache(PROCOID,
600
ObjectIdGetDatum(funcid),
602
if (!HeapTupleIsValid(proctup))
603
elog(ERROR, "cache lookup failed for function %u", funcid);
604
procform = (Form_pg_proc) GETSTRUCT(proctup);
606
recomputeNamespacePath();
609
* Quick check: if it ain't in the path at all, it ain't visible.
610
* Items in the system namespace are surely in the path and so we
611
* needn't even do list_member_oid() for them.
613
pronamespace = procform->pronamespace;
614
if (pronamespace != PG_CATALOG_NAMESPACE &&
615
!list_member_oid(namespaceSearchPath, pronamespace))
620
* If it is in the path, it might still not be visible; it could
621
* be hidden by another proc of the same name and arguments
622
* earlier in the path. So we must do a slow check to see if this
623
* is the same proc that would be found by FuncnameGetCandidates.
625
char *proname = NameStr(procform->proname);
626
int nargs = procform->pronargs;
627
FuncCandidateList clist;
631
clist = FuncnameGetCandidates(list_make1(makeString(proname)), nargs);
633
for (; clist; clist = clist->next)
635
if (memcmp(clist->args, procform->proargtypes,
636
nargs * sizeof(Oid)) == 0)
638
/* Found the expected entry; is it the right proc? */
639
visible = (clist->oid == funcid);
645
ReleaseSysCache(proctup);
652
* OpernameGetCandidates
653
* Given a possibly-qualified operator name and operator kind,
654
* retrieve a list of the possible matches.
656
* If oprkind is '\0', we return all operators matching the given name,
657
* regardless of arguments.
659
* We search a single namespace if the operator name is qualified, else
660
* all namespaces in the search path. The return list will never contain
661
* multiple entries with identical argument lists --- in the multiple-
662
* namespace case, we arrange for entries in earlier namespaces to mask
663
* identical entries in later namespaces.
665
* The returned items always have two args[] entries --- one or the other
666
* will be InvalidOid for a prefix or postfix oprkind. nargs is 2, too.
669
OpernameGetCandidates(List *names, char oprkind)
671
FuncCandidateList resultList = NULL;
672
char *resultSpace = NULL;
680
/* deconstruct the name list */
681
DeconstructQualifiedName(names, &schemaname, &opername);
685
/* use exact schema given */
686
namespaceId = LookupExplicitNamespace(schemaname);
690
/* flag to indicate we need namespace search */
691
namespaceId = InvalidOid;
692
recomputeNamespacePath();
695
/* Search syscache by name only */
696
catlist = SearchSysCacheList(OPERNAMENSP, 1,
697
CStringGetDatum(opername),
701
* In typical scenarios, most if not all of the operators found by the
702
* catcache search will end up getting returned; and there can be
703
* quite a few, for common operator names such as '=' or '+'. To
704
* reduce the time spent in palloc, we allocate the result space as an
705
* array large enough to hold all the operators. The original coding
706
* of this routine did a separate palloc for each operator, but
707
* profiling revealed that the pallocs used an unreasonably large
708
* fraction of parsing time.
710
#define SPACE_PER_OP MAXALIGN(sizeof(struct _FuncCandidateList) + sizeof(Oid))
712
if (catlist->n_members > 0)
713
resultSpace = palloc(catlist->n_members * SPACE_PER_OP);
715
for (i = 0; i < catlist->n_members; i++)
717
HeapTuple opertup = &catlist->members[i]->tuple;
718
Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup);
720
FuncCandidateList newResult;
722
/* Ignore operators of wrong kind, if specific kind requested */
723
if (oprkind && operform->oprkind != oprkind)
726
if (OidIsValid(namespaceId))
728
/* Consider only opers in specified namespace */
729
if (operform->oprnamespace != namespaceId)
731
/* No need to check args, they must all be different */
735
/* Consider only opers that are in the search path */
738
foreach(nsp, namespaceSearchPath)
740
if (operform->oprnamespace == lfirst_oid(nsp))
745
continue; /* oper is not in search path */
748
* Okay, it's in the search path, but does it have the same
749
* arguments as something we already accepted? If so, keep
750
* only the one that appears earlier in the search path.
752
* If we have an ordered list from SearchSysCacheList (the normal
753
* case), then any conflicting oper must immediately adjoin
754
* this one in the list, so we only need to look at the newest
755
* result item. If we have an unordered list, we have to scan
756
* the whole result list.
760
FuncCandidateList prevResult;
762
if (catlist->ordered)
764
if (operform->oprleft == resultList->args[0] &&
765
operform->oprright == resultList->args[1])
766
prevResult = resultList;
772
for (prevResult = resultList;
774
prevResult = prevResult->next)
776
if (operform->oprleft == prevResult->args[0] &&
777
operform->oprright == prevResult->args[1])
783
/* We have a match with a previous result */
784
Assert(pathpos != prevResult->pathpos);
785
if (pathpos > prevResult->pathpos)
786
continue; /* keep previous result */
787
/* replace previous result */
788
prevResult->pathpos = pathpos;
789
prevResult->oid = HeapTupleGetOid(opertup);
790
continue; /* args are same, of course */
796
* Okay to add it to result list
798
newResult = (FuncCandidateList) (resultSpace + nextResult);
799
nextResult += SPACE_PER_OP;
801
newResult->pathpos = pathpos;
802
newResult->oid = HeapTupleGetOid(opertup);
803
newResult->nargs = 2;
804
newResult->args[0] = operform->oprleft;
805
newResult->args[1] = operform->oprright;
806
newResult->next = resultList;
807
resultList = newResult;
810
ReleaseSysCacheList(catlist);
817
* Determine whether an operator (identified by OID) is visible in the
818
* current search path. Visible means "would be found by searching
819
* for the unqualified operator name with exact argument matches".
822
OperatorIsVisible(Oid oprid)
825
Form_pg_operator oprform;
829
oprtup = SearchSysCache(OPEROID,
830
ObjectIdGetDatum(oprid),
832
if (!HeapTupleIsValid(oprtup))
833
elog(ERROR, "cache lookup failed for operator %u", oprid);
834
oprform = (Form_pg_operator) GETSTRUCT(oprtup);
836
recomputeNamespacePath();
839
* Quick check: if it ain't in the path at all, it ain't visible.
840
* Items in the system namespace are surely in the path and so we
841
* needn't even do list_member_oid() for them.
843
oprnamespace = oprform->oprnamespace;
844
if (oprnamespace != PG_CATALOG_NAMESPACE &&
845
!list_member_oid(namespaceSearchPath, oprnamespace))
850
* If it is in the path, it might still not be visible; it could
851
* be hidden by another operator of the same name and arguments
852
* earlier in the path. So we must do a slow check to see if this
853
* is the same operator that would be found by
854
* OpernameGetCandidates.
856
char *oprname = NameStr(oprform->oprname);
857
FuncCandidateList clist;
861
clist = OpernameGetCandidates(list_make1(makeString(oprname)),
864
for (; clist; clist = clist->next)
866
if (clist->args[0] == oprform->oprleft &&
867
clist->args[1] == oprform->oprright)
869
/* Found the expected entry; is it the right op? */
870
visible = (clist->oid == oprid);
876
ReleaseSysCache(oprtup);
883
* OpclassGetCandidates
884
* Given an index access method OID, retrieve a list of all the
885
* opclasses for that AM that are visible in the search path.
887
* NOTE: the opcname_tmp field in the returned structs should not be used
888
* by callers, because it points at syscache entries that we release at
889
* the end of this routine. If any callers needed the name information,
890
* we could pstrdup() the names ... but at present it'd be wasteful.
893
OpclassGetCandidates(Oid amid)
895
OpclassCandidateList resultList = NULL;
899
/* Search syscache by AM OID only */
900
catlist = SearchSysCacheList(CLAAMNAMENSP, 1,
901
ObjectIdGetDatum(amid),
904
recomputeNamespacePath();
906
for (i = 0; i < catlist->n_members; i++)
908
HeapTuple opctup = &catlist->members[i]->tuple;
909
Form_pg_opclass opcform = (Form_pg_opclass) GETSTRUCT(opctup);
911
OpclassCandidateList newResult;
914
/* Consider only opclasses that are in the search path */
915
foreach(nsp, namespaceSearchPath)
917
if (opcform->opcnamespace == lfirst_oid(nsp))
922
continue; /* opclass is not in search path */
925
* Okay, it's in the search path, but does it have the same name
926
* as something we already accepted? If so, keep only the one
927
* that appears earlier in the search path.
929
* If we have an ordered list from SearchSysCacheList (the normal
930
* case), then any conflicting opclass must immediately adjoin
931
* this one in the list, so we only need to look at the newest
932
* result item. If we have an unordered list, we have to scan the
937
OpclassCandidateList prevResult;
939
if (catlist->ordered)
941
if (strcmp(NameStr(opcform->opcname),
942
resultList->opcname_tmp) == 0)
943
prevResult = resultList;
949
for (prevResult = resultList;
951
prevResult = prevResult->next)
953
if (strcmp(NameStr(opcform->opcname),
954
prevResult->opcname_tmp) == 0)
960
/* We have a match with a previous result */
961
Assert(pathpos != prevResult->pathpos);
962
if (pathpos > prevResult->pathpos)
963
continue; /* keep previous result */
964
/* replace previous result */
965
prevResult->opcname_tmp = NameStr(opcform->opcname);
966
prevResult->pathpos = pathpos;
967
prevResult->oid = HeapTupleGetOid(opctup);
968
prevResult->opcintype = opcform->opcintype;
969
prevResult->opcdefault = opcform->opcdefault;
970
prevResult->opckeytype = opcform->opckeytype;
976
* Okay to add it to result list
978
newResult = (OpclassCandidateList)
979
palloc(sizeof(struct _OpclassCandidateList));
980
newResult->opcname_tmp = NameStr(opcform->opcname);
981
newResult->pathpos = pathpos;
982
newResult->oid = HeapTupleGetOid(opctup);
983
newResult->opcintype = opcform->opcintype;
984
newResult->opcdefault = opcform->opcdefault;
985
newResult->opckeytype = opcform->opckeytype;
986
newResult->next = resultList;
987
resultList = newResult;
990
ReleaseSysCacheList(catlist);
996
* OpclassnameGetOpcid
997
* Try to resolve an unqualified index opclass name.
998
* Returns OID if opclass found in search path, else InvalidOid.
1000
* This is essentially the same as TypenameGetTypid, but we have to have
1001
* an extra argument for the index AM OID.
1004
OpclassnameGetOpcid(Oid amid, const char *opcname)
1009
recomputeNamespacePath();
1011
foreach(l, namespaceSearchPath)
1013
Oid namespaceId = lfirst_oid(l);
1015
opcid = GetSysCacheOid(CLAAMNAMENSP,
1016
ObjectIdGetDatum(amid),
1017
PointerGetDatum(opcname),
1018
ObjectIdGetDatum(namespaceId),
1020
if (OidIsValid(opcid))
1024
/* Not found in path */
1030
* Determine whether an opclass (identified by OID) is visible in the
1031
* current search path. Visible means "would be found by searching
1032
* for the unqualified opclass name".
1035
OpclassIsVisible(Oid opcid)
1038
Form_pg_opclass opcform;
1042
opctup = SearchSysCache(CLAOID,
1043
ObjectIdGetDatum(opcid),
1045
if (!HeapTupleIsValid(opctup))
1046
elog(ERROR, "cache lookup failed for opclass %u", opcid);
1047
opcform = (Form_pg_opclass) GETSTRUCT(opctup);
1049
recomputeNamespacePath();
1052
* Quick check: if it ain't in the path at all, it ain't visible.
1053
* Items in the system namespace are surely in the path and so we
1054
* needn't even do list_member_oid() for them.
1056
opcnamespace = opcform->opcnamespace;
1057
if (opcnamespace != PG_CATALOG_NAMESPACE &&
1058
!list_member_oid(namespaceSearchPath, opcnamespace))
1063
* If it is in the path, it might still not be visible; it could
1064
* be hidden by another opclass of the same name earlier in the
1065
* path. So we must do a slow check to see if this opclass would
1066
* be found by OpclassnameGetOpcid.
1068
char *opcname = NameStr(opcform->opcname);
1070
visible = (OpclassnameGetOpcid(opcform->opcamid, opcname) == opcid);
1073
ReleaseSysCache(opctup);
1079
* ConversionGetConid
1080
* Try to resolve an unqualified conversion name.
1081
* Returns OID if conversion found in search path, else InvalidOid.
1083
* This is essentially the same as RelnameGetRelid.
1086
ConversionGetConid(const char *conname)
1091
recomputeNamespacePath();
1093
foreach(l, namespaceSearchPath)
1095
Oid namespaceId = lfirst_oid(l);
1097
conid = GetSysCacheOid(CONNAMENSP,
1098
PointerGetDatum(conname),
1099
ObjectIdGetDatum(namespaceId),
1101
if (OidIsValid(conid))
1105
/* Not found in path */
1110
* ConversionIsVisible
1111
* Determine whether a conversion (identified by OID) is visible in the
1112
* current search path. Visible means "would be found by searching
1113
* for the unqualified conversion name".
1116
ConversionIsVisible(Oid conid)
1119
Form_pg_conversion conform;
1123
contup = SearchSysCache(CONOID,
1124
ObjectIdGetDatum(conid),
1126
if (!HeapTupleIsValid(contup))
1127
elog(ERROR, "cache lookup failed for conversion %u", conid);
1128
conform = (Form_pg_conversion) GETSTRUCT(contup);
1130
recomputeNamespacePath();
1133
* Quick check: if it ain't in the path at all, it ain't visible.
1134
* Items in the system namespace are surely in the path and so we
1135
* needn't even do list_member_oid() for them.
1137
connamespace = conform->connamespace;
1138
if (connamespace != PG_CATALOG_NAMESPACE &&
1139
!list_member_oid(namespaceSearchPath, connamespace))
1144
* If it is in the path, it might still not be visible; it could
1145
* be hidden by another conversion of the same name earlier in the
1146
* path. So we must do a slow check to see if this conversion
1147
* would be found by ConversionGetConid.
1149
char *conname = NameStr(conform->conname);
1151
visible = (ConversionGetConid(conname) == conid);
1154
ReleaseSysCache(contup);
1160
* DeconstructQualifiedName
1161
* Given a possibly-qualified name expressed as a list of String nodes,
1162
* extract the schema name and object name.
1164
* *nspname_p is set to NULL if there is no explicit schema name.
1167
DeconstructQualifiedName(List *names,
1172
char *schemaname = NULL;
1173
char *objname = NULL;
1175
switch (list_length(names))
1178
objname = strVal(linitial(names));
1181
schemaname = strVal(linitial(names));
1182
objname = strVal(lsecond(names));
1185
catalogname = strVal(linitial(names));
1186
schemaname = strVal(lsecond(names));
1187
objname = strVal(lthird(names));
1190
* We check the catalog name and then ignore it.
1192
if (strcmp(catalogname, get_database_name(MyDatabaseId)) != 0)
1194
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1195
errmsg("cross-database references are not implemented: %s",
1196
NameListToString(names))));
1200
(errcode(ERRCODE_SYNTAX_ERROR),
1201
errmsg("improper qualified name (too many dotted names): %s",
1202
NameListToString(names))));
1206
*nspname_p = schemaname;
1207
*objname_p = objname;
1211
* LookupExplicitNamespace
1212
* Process an explicitly-specified schema name: look up the schema
1213
* and verify we have USAGE (lookup) rights in it.
1215
* Returns the namespace OID. Raises ereport if any problem.
1218
LookupExplicitNamespace(const char *nspname)
1221
AclResult aclresult;
1223
namespaceId = GetSysCacheOid(NAMESPACENAME,
1224
CStringGetDatum(nspname),
1226
if (!OidIsValid(namespaceId))
1228
(errcode(ERRCODE_UNDEFINED_SCHEMA),
1229
errmsg("schema \"%s\" does not exist", nspname)));
1231
aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_USAGE);
1232
if (aclresult != ACLCHECK_OK)
1233
aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
1240
* QualifiedNameGetCreationNamespace
1241
* Given a possibly-qualified name for an object (in List-of-Values
1242
* format), determine what namespace the object should be created in.
1243
* Also extract and return the object name (last component of list).
1245
* This is *not* used for tables. Hence, the TEMP table namespace is
1246
* never selected as the creation target.
1249
QualifiedNameGetCreationNamespace(List *names, char **objname_p)
1255
/* deconstruct the name list */
1256
DeconstructQualifiedName(names, &schemaname, &objname);
1260
/* use exact schema given */
1261
namespaceId = GetSysCacheOid(NAMESPACENAME,
1262
CStringGetDatum(schemaname),
1264
if (!OidIsValid(namespaceId))
1266
(errcode(ERRCODE_UNDEFINED_SCHEMA),
1267
errmsg("schema \"%s\" does not exist", schemaname)));
1268
/* we do not check for USAGE rights here! */
1272
/* use the default creation namespace */
1273
recomputeNamespacePath();
1274
namespaceId = defaultCreationNamespace;
1275
if (!OidIsValid(namespaceId))
1277
(errcode(ERRCODE_UNDEFINED_SCHEMA),
1278
errmsg("no schema has been selected to create in")));
1281
/* Note: callers will check for CREATE rights when appropriate */
1283
*objname_p = objname;
1288
* makeRangeVarFromNameList
1289
* Utility routine to convert a qualified-name list into RangeVar form.
1292
makeRangeVarFromNameList(List *names)
1294
RangeVar *rel = makeRangeVar(NULL, NULL);
1296
switch (list_length(names))
1299
rel->relname = strVal(linitial(names));
1302
rel->schemaname = strVal(linitial(names));
1303
rel->relname = strVal(lsecond(names));
1306
rel->catalogname = strVal(linitial(names));
1307
rel->schemaname = strVal(lsecond(names));
1308
rel->relname = strVal(lthird(names));
1312
(errcode(ERRCODE_SYNTAX_ERROR),
1313
errmsg("improper relation name (too many dotted names): %s",
1314
NameListToString(names))));
1323
* Utility routine to convert a qualified-name list into a string.
1325
* This is used primarily to form error messages, and so we do not quote
1326
* the list elements, for the sake of legibility.
1329
NameListToString(List *names)
1331
StringInfoData string;
1334
initStringInfo(&string);
1338
if (l != list_head(names))
1339
appendStringInfoChar(&string, '.');
1340
appendStringInfoString(&string, strVal(lfirst(l)));
1347
* NameListToQuotedString
1348
* Utility routine to convert a qualified-name list into a string.
1350
* Same as above except that names will be double-quoted where necessary,
1351
* so the string could be re-parsed (eg, by textToQualifiedNameList).
1354
NameListToQuotedString(List *names)
1356
StringInfoData string;
1359
initStringInfo(&string);
1363
if (l != list_head(names))
1364
appendStringInfoChar(&string, '.');
1365
appendStringInfoString(&string, quote_identifier(strVal(lfirst(l))));
1372
* isTempNamespace - is the given namespace my temporary-table namespace?
1375
isTempNamespace(Oid namespaceId)
1377
if (OidIsValid(myTempNamespace) && myTempNamespace == namespaceId)
1383
* isOtherTempNamespace - is the given namespace some other backend's
1384
* temporary-table namespace?
1387
isOtherTempNamespace(Oid namespaceId)
1392
/* If it's my own temp namespace, say "false" */
1393
if (isTempNamespace(namespaceId))
1395
/* Else, if the namespace name starts with "pg_temp_", say "true" */
1396
nspname = get_namespace_name(namespaceId);
1398
return false; /* no such namespace? */
1399
result = (strncmp(nspname, "pg_temp_", 8) == 0);
1405
* PushSpecialNamespace - push a "special" namespace onto the front of the
1408
* This is a slightly messy hack intended only for support of CREATE SCHEMA.
1409
* Although the API is defined to allow a stack of pushed namespaces, we
1410
* presently only support one at a time.
1412
* The pushed namespace will be removed from the search path at end of
1413
* transaction, whether commit or abort.
1416
PushSpecialNamespace(Oid namespaceId)
1418
Assert(!OidIsValid(mySpecialNamespace));
1419
mySpecialNamespace = namespaceId;
1420
namespaceSearchPathValid = false;
1424
* PopSpecialNamespace - remove previously pushed special namespace.
1427
PopSpecialNamespace(Oid namespaceId)
1429
Assert(mySpecialNamespace == namespaceId);
1430
mySpecialNamespace = InvalidOid;
1431
namespaceSearchPathValid = false;
1435
* FindConversionByName - find a conversion by possibly qualified name
1438
FindConversionByName(List *name)
1441
char *conversion_name;
1446
/* deconstruct the name list */
1447
DeconstructQualifiedName(name, &schemaname, &conversion_name);
1451
/* use exact schema given */
1452
namespaceId = LookupExplicitNamespace(schemaname);
1453
return FindConversion(conversion_name, namespaceId);
1457
/* search for it in search path */
1458
recomputeNamespacePath();
1460
foreach(l, namespaceSearchPath)
1462
namespaceId = lfirst_oid(l);
1463
conoid = FindConversion(conversion_name, namespaceId);
1464
if (OidIsValid(conoid))
1469
/* Not found in path */
1474
* FindDefaultConversionProc - find default encoding conversion proc
1477
FindDefaultConversionProc(int4 for_encoding, int4 to_encoding)
1482
recomputeNamespacePath();
1484
foreach(l, namespaceSearchPath)
1486
Oid namespaceId = lfirst_oid(l);
1488
proc = FindDefaultConversion(namespaceId, for_encoding, to_encoding);
1489
if (OidIsValid(proc))
1493
/* Not found in path */
1498
* recomputeNamespacePath - recompute path derived variables if needed.
1501
recomputeNamespacePath(void)
1503
AclId userId = GetUserId();
1510
MemoryContext oldcxt;
1513
* Do nothing if path is already valid.
1515
if (namespaceSearchPathValid && namespaceUser == userId)
1518
/* Need a modifiable copy of namespace_search_path string */
1519
rawname = pstrdup(namespace_search_path);
1521
/* Parse string into list of identifiers */
1522
if (!SplitIdentifierString(rawname, ',', &namelist))
1524
/* syntax error in name list */
1525
/* this should not happen if GUC checked check_search_path */
1526
elog(ERROR, "invalid list syntax");
1530
* Convert the list of names to a list of OIDs. If any names are not
1531
* recognizable or we don't have read access, just leave them out of
1532
* the list. (We can't raise an error, since the search_path setting
1533
* has already been accepted.) Don't make duplicate entries, either.
1536
foreach(l, namelist)
1538
char *curname = (char *) lfirst(l);
1541
if (strcmp(curname, "$user") == 0)
1543
/* $user --- substitute namespace matching user name, if any */
1546
tuple = SearchSysCache(SHADOWSYSID,
1547
ObjectIdGetDatum(userId),
1549
if (HeapTupleIsValid(tuple))
1553
uname = NameStr(((Form_pg_shadow) GETSTRUCT(tuple))->usename);
1554
namespaceId = GetSysCacheOid(NAMESPACENAME,
1555
CStringGetDatum(uname),
1557
ReleaseSysCache(tuple);
1558
if (OidIsValid(namespaceId) &&
1559
!list_member_oid(oidlist, namespaceId) &&
1560
pg_namespace_aclcheck(namespaceId, userId,
1561
ACL_USAGE) == ACLCHECK_OK)
1562
oidlist = lappend_oid(oidlist, namespaceId);
1567
/* normal namespace reference */
1568
namespaceId = GetSysCacheOid(NAMESPACENAME,
1569
CStringGetDatum(curname),
1571
if (OidIsValid(namespaceId) &&
1572
!list_member_oid(oidlist, namespaceId) &&
1573
pg_namespace_aclcheck(namespaceId, userId,
1574
ACL_USAGE) == ACLCHECK_OK)
1575
oidlist = lappend_oid(oidlist, namespaceId);
1580
* Remember the first member of the explicit list.
1583
firstNS = InvalidOid;
1585
firstNS = linitial_oid(oidlist);
1588
* Add any implicitly-searched namespaces to the list. Note these go
1589
* on the front, not the back; also notice that we do not check USAGE
1590
* permissions for these.
1592
if (!list_member_oid(oidlist, PG_CATALOG_NAMESPACE))
1593
oidlist = lcons_oid(PG_CATALOG_NAMESPACE, oidlist);
1595
if (OidIsValid(myTempNamespace) &&
1596
!list_member_oid(oidlist, myTempNamespace))
1597
oidlist = lcons_oid(myTempNamespace, oidlist);
1599
if (OidIsValid(mySpecialNamespace) &&
1600
!list_member_oid(oidlist, mySpecialNamespace))
1601
oidlist = lcons_oid(mySpecialNamespace, oidlist);
1604
* Now that we've successfully built the new list of namespace OIDs,
1605
* save it in permanent storage.
1607
oldcxt = MemoryContextSwitchTo(TopMemoryContext);
1608
newpath = list_copy(oidlist);
1609
MemoryContextSwitchTo(oldcxt);
1611
/* Now safe to assign to state variable. */
1612
list_free(namespaceSearchPath);
1613
namespaceSearchPath = newpath;
1616
* Update info derived from search path.
1618
firstExplicitNamespace = firstNS;
1619
if (OidIsValid(mySpecialNamespace))
1620
defaultCreationNamespace = mySpecialNamespace;
1622
defaultCreationNamespace = firstNS;
1624
/* Mark the path valid. */
1625
namespaceSearchPathValid = true;
1626
namespaceUser = userId;
1630
list_free(namelist);
1635
* InitTempTableNamespace
1636
* Initialize temp table namespace on first use in a particular backend
1639
InitTempTableNamespace(void)
1641
char namespaceName[NAMEDATALEN];
1645
* First, do permission check to see if we are authorized to make temp
1646
* tables. We use a nonstandard error message here since
1647
* "databasename: permission denied" might be a tad cryptic.
1649
* Note that ACL_CREATE_TEMP rights are rechecked in
1650
* pg_namespace_aclmask; that's necessary since current user ID could
1651
* change during the session. But there's no need to make the
1652
* namespace in the first place until a temp table creation request is
1653
* made by someone with appropriate rights.
1655
if (pg_database_aclcheck(MyDatabaseId, GetUserId(),
1656
ACL_CREATE_TEMP) != ACLCHECK_OK)
1658
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1659
errmsg("permission denied to create temporary tables in database \"%s\"",
1660
get_database_name(MyDatabaseId))));
1662
snprintf(namespaceName, sizeof(namespaceName), "pg_temp_%d", MyBackendId);
1664
namespaceId = GetSysCacheOid(NAMESPACENAME,
1665
CStringGetDatum(namespaceName),
1667
if (!OidIsValid(namespaceId))
1670
* First use of this temp namespace in this database; create it.
1671
* The temp namespaces are always owned by the superuser. We
1672
* leave their permissions at default --- i.e., no access except
1673
* to superuser --- to ensure that unprivileged users can't peek
1674
* at other backends' temp tables. This works because the places
1675
* that access the temp namespace for my own backend skip
1676
* permissions checks on it.
1678
namespaceId = NamespaceCreate(namespaceName, BOOTSTRAP_USESYSID);
1679
/* Advance command counter to make namespace visible */
1680
CommandCounterIncrement();
1685
* If the namespace already exists, clean it out (in case the
1686
* former owner crashed without doing so).
1688
RemoveTempRelations(namespaceId);
1692
* Okay, we've prepared the temp namespace ... but it's not committed
1693
* yet, so all our work could be undone by transaction rollback. Set
1694
* flag for AtEOXact_Namespace to know what to do.
1696
myTempNamespace = namespaceId;
1698
/* It should not be done already. */
1699
AssertState(myTempNamespaceSubID == InvalidSubTransactionId);
1700
myTempNamespaceSubID = GetCurrentSubTransactionId();
1702
namespaceSearchPathValid = false; /* need to rebuild list */
1706
* End-of-transaction cleanup for namespaces.
1709
AtEOXact_Namespace(bool isCommit)
1712
* If we abort the transaction in which a temp namespace was selected,
1713
* we'll have to do any creation or cleanout work over again. So,
1714
* just forget the namespace entirely until next time. On the other
1715
* hand, if we commit then register an exit callback to clean out the
1716
* temp tables at backend shutdown. (We only want to register the
1717
* callback once per session, so this is a good place to do it.)
1719
if (myTempNamespaceSubID != InvalidSubTransactionId)
1722
on_shmem_exit(RemoveTempRelationsCallback, 0);
1725
myTempNamespace = InvalidOid;
1726
namespaceSearchPathValid = false; /* need to rebuild list */
1728
myTempNamespaceSubID = InvalidSubTransactionId;
1732
* Clean up if someone failed to do PopSpecialNamespace
1734
if (OidIsValid(mySpecialNamespace))
1736
mySpecialNamespace = InvalidOid;
1737
namespaceSearchPathValid = false; /* need to rebuild list */
1742
* AtEOSubXact_Namespace
1744
* At subtransaction commit, propagate the temp-namespace-creation
1745
* flag to the parent subtransaction.
1747
* At subtransaction abort, forget the flag if we set it up.
1750
AtEOSubXact_Namespace(bool isCommit, SubTransactionId mySubid,
1751
SubTransactionId parentSubid)
1753
if (myTempNamespaceSubID == mySubid)
1756
myTempNamespaceSubID = parentSubid;
1759
myTempNamespaceSubID = InvalidSubTransactionId;
1760
/* TEMP namespace creation failed, so reset state */
1761
myTempNamespace = InvalidOid;
1762
namespaceSearchPathValid = false; /* need to rebuild list */
1768
* Remove all relations in the specified temp namespace.
1770
* This is called at backend shutdown (if we made any temp relations).
1771
* It is also called when we begin using a pre-existing temp namespace,
1772
* in order to clean out any relations that might have been created by
1773
* a crashed backend.
1776
RemoveTempRelations(Oid tempNamespaceId)
1778
ObjectAddress object;
1781
* We want to get rid of everything in the target namespace, but not
1782
* the namespace itself (deleting it only to recreate it later would
1783
* be a waste of cycles). We do this by finding everything that has a
1784
* dependency on the namespace.
1786
object.classId = get_system_catalog_relid(NamespaceRelationName);
1787
object.objectId = tempNamespaceId;
1788
object.objectSubId = 0;
1790
deleteWhatDependsOn(&object, false);
1794
* Callback to remove temp relations at backend exit.
1797
RemoveTempRelationsCallback(int code, Datum arg)
1799
if (OidIsValid(myTempNamespace)) /* should always be true */
1801
/* Need to ensure we have a usable transaction. */
1802
AbortOutOfAnyTransaction();
1803
StartTransactionCommand();
1805
RemoveTempRelations(myTempNamespace);
1807
CommitTransactionCommand();
1813
* Routines for handling the GUC variable 'search_path'.
1816
/* assign_hook: validate new search_path, do extra actions as needed */
1818
assign_search_path(const char *newval, bool doit, GucSource source)
1824
/* Need a modifiable copy of string */
1825
rawname = pstrdup(newval);
1827
/* Parse string into list of identifiers */
1828
if (!SplitIdentifierString(rawname, ',', &namelist))
1830
/* syntax error in name list */
1832
list_free(namelist);
1837
* If we aren't inside a transaction, we cannot do database access so
1838
* cannot verify the individual names. Must accept the list on faith.
1840
if (source >= PGC_S_INTERACTIVE && IsTransactionState())
1843
* Verify that all the names are either valid namespace names or
1844
* "$user". We do not require $user to correspond to a valid
1845
* namespace. We do not check for USAGE rights, either; should
1848
* When source == PGC_S_TEST, we are checking the argument of an
1849
* ALTER DATABASE SET or ALTER USER SET command. It could be that
1850
* the intended use of the search path is for some other database,
1851
* so we should not error out if it mentions schemas not present
1852
* in the current database. We reduce the message to NOTICE
1855
foreach(l, namelist)
1857
char *curname = (char *) lfirst(l);
1859
if (strcmp(curname, "$user") == 0)
1861
if (!SearchSysCacheExists(NAMESPACENAME,
1862
CStringGetDatum(curname),
1864
ereport((source == PGC_S_TEST) ? NOTICE : ERROR,
1865
(errcode(ERRCODE_UNDEFINED_SCHEMA),
1866
errmsg("schema \"%s\" does not exist", curname)));
1871
list_free(namelist);
1874
* We mark the path as needing recomputation, but don't do anything
1875
* until it's needed. This avoids trying to do database access during
1876
* GUC initialization.
1879
namespaceSearchPathValid = false;
1885
* InitializeSearchPath: initialize module during InitPostgres.
1887
* This is called after we are up enough to be able to do catalog lookups.
1890
InitializeSearchPath(void)
1892
if (IsBootstrapProcessingMode())
1895
* In bootstrap mode, the search path must be 'pg_catalog' so that
1896
* tables are created in the proper namespace; ignore the GUC
1899
MemoryContext oldcxt;
1901
oldcxt = MemoryContextSwitchTo(TopMemoryContext);
1902
namespaceSearchPath = list_make1_oid(PG_CATALOG_NAMESPACE);
1903
MemoryContextSwitchTo(oldcxt);
1904
defaultCreationNamespace = PG_CATALOG_NAMESPACE;
1905
firstExplicitNamespace = PG_CATALOG_NAMESPACE;
1906
namespaceSearchPathValid = true;
1907
namespaceUser = GetUserId();
1912
* In normal mode, arrange for a callback on any syscache
1913
* invalidation of pg_namespace rows.
1915
CacheRegisterSyscacheCallback(NAMESPACEOID,
1918
/* Force search path to be recomputed on next use */
1919
namespaceSearchPathValid = false;
1925
* Syscache inval callback function
1928
NamespaceCallback(Datum arg, Oid relid)
1930
/* Force search path to be recomputed on next use */
1931
namespaceSearchPathValid = false;
1935
* Fetch the active search path. The return value is a palloc'ed list
1936
* of OIDs; the caller is responsible for freeing this storage as
1939
* The returned list includes the implicitly-prepended namespaces only if
1940
* includeImplicit is true.
1943
fetch_search_path(bool includeImplicit)
1947
recomputeNamespacePath();
1949
result = list_copy(namespaceSearchPath);
1950
if (!includeImplicit)
1952
while (result && linitial_oid(result) != firstExplicitNamespace)
1953
result = list_delete_first(result);
1960
* Export the FooIsVisible functions as SQL-callable functions.
1964
pg_table_is_visible(PG_FUNCTION_ARGS)
1966
Oid oid = PG_GETARG_OID(0);
1968
PG_RETURN_BOOL(RelationIsVisible(oid));
1972
pg_type_is_visible(PG_FUNCTION_ARGS)
1974
Oid oid = PG_GETARG_OID(0);
1976
PG_RETURN_BOOL(TypeIsVisible(oid));
1980
pg_function_is_visible(PG_FUNCTION_ARGS)
1982
Oid oid = PG_GETARG_OID(0);
1984
PG_RETURN_BOOL(FunctionIsVisible(oid));
1988
pg_operator_is_visible(PG_FUNCTION_ARGS)
1990
Oid oid = PG_GETARG_OID(0);
1992
PG_RETURN_BOOL(OperatorIsVisible(oid));
1996
pg_opclass_is_visible(PG_FUNCTION_ARGS)
1998
Oid oid = PG_GETARG_OID(0);
2000
PG_RETURN_BOOL(OpclassIsVisible(oid));
2004
pg_conversion_is_visible(PG_FUNCTION_ARGS)
2006
Oid oid = PG_GETARG_OID(0);
2008
PG_RETURN_BOOL(ConversionIsVisible(oid));