]> granicus.if.org Git - postgresql/blob - src/backend/catalog/namespace.c
Fix compile warnings.
[postgresql] / src / backend / catalog / namespace.c
1 /*-------------------------------------------------------------------------
2  *
3  * namespace.c
4  *        code to support accessing and searching namespaces
5  *
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.
10  *
11  *
12  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
13  * Portions Copyright (c) 1994, Regents of the University of California
14  *
15  * IDENTIFICATION
16  *        $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.53 2003/06/27 17:03:29 tgl Exp $
17  *
18  *-------------------------------------------------------------------------
19  */
20 #include "postgres.h"
21
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/inval.h"
43 #include "utils/lsyscache.h"
44 #include "utils/memutils.h"
45 #include "utils/syscache.h"
46
47
48 /*
49  * The namespace search path is a possibly-empty list of namespace OIDs.
50  * In addition to the explicit list, several implicitly-searched namespaces
51  * may be included:
52  *
53  * 1. If a "special" namespace has been set by PushSpecialNamespace, it is
54  * always searched first.  (This is a hack for CREATE SCHEMA.)
55  *
56  * 2. If a TEMP table namespace has been initialized in this session, it
57  * is always searched just after any special namespace.
58  *
59  * 3. The system catalog namespace is always searched.  If the system
60  * namespace is present in the explicit path then it will be searched in
61  * the specified order; otherwise it will be searched after TEMP tables and
62  * *before* the explicit list.  (It might seem that the system namespace
63  * should be implicitly last, but this behavior appears to be required by
64  * SQL99.  Also, this provides a way to search the system namespace first
65  * without thereby making it the default creation target namespace.)
66  *
67  * The default creation target namespace is normally equal to the first
68  * element of the explicit list, but is the "special" namespace when one
69  * has been set.  If the explicit list is empty and there is no special
70  * namespace, there is no default target.
71  *
72  * In bootstrap mode, the search path is set equal to 'pg_catalog', so that
73  * the system namespace is the only one searched or inserted into.
74  * The initdb script is also careful to set search_path to 'pg_catalog' for
75  * its post-bootstrap standalone backend runs.  Otherwise the default search
76  * path is determined by GUC.  The factory default path contains the PUBLIC
77  * namespace (if it exists), preceded by the user's personal namespace
78  * (if one exists).
79  *
80  * If namespaceSearchPathValid is false, then namespaceSearchPath (and other
81  * derived variables) need to be recomputed from namespace_search_path.
82  * We mark it invalid upon an assignment to namespace_search_path or receipt
83  * of a syscache invalidation event for pg_namespace.  The recomputation
84  * is done during the next lookup attempt.
85  *
86  * Any namespaces mentioned in namespace_search_path that are not readable
87  * by the current user ID are simply left out of namespaceSearchPath; so
88  * we have to be willing to recompute the path when current userid changes.
89  * namespaceUser is the userid the path has been computed for.
90  */
91
92 static List *namespaceSearchPath = NIL;
93
94 static Oid      namespaceUser = InvalidOid;
95
96 /* default place to create stuff; if InvalidOid, no default */
97 static Oid      defaultCreationNamespace = InvalidOid;
98
99 /* first explicit member of list; usually same as defaultCreationNamespace */
100 static Oid      firstExplicitNamespace = InvalidOid;
101
102 /* The above four values are valid only if namespaceSearchPathValid */
103 static bool namespaceSearchPathValid = true;
104
105 /*
106  * myTempNamespace is InvalidOid until and unless a TEMP namespace is set up
107  * in a particular backend session (this happens when a CREATE TEMP TABLE
108  * command is first executed).  Thereafter it's the OID of the temp namespace.
109  * firstTempTransaction flags whether we've committed creation of the TEMP
110  * namespace or not.
111  */
112 static Oid      myTempNamespace = InvalidOid;
113
114 static bool firstTempTransaction = false;
115
116 /*
117  * "Special" namespace for CREATE SCHEMA.  If set, it's the first search
118  * path element, and also the default creation namespace.
119  */
120 static Oid      mySpecialNamespace = InvalidOid;
121
122 /*
123  * This is the text equivalent of the search path --- it's the value
124  * of the GUC variable 'search_path'.
125  */
126 char       *namespace_search_path = NULL;
127
128
129 /* Local functions */
130 static void recomputeNamespacePath(void);
131 static void InitTempTableNamespace(void);
132 static void RemoveTempRelations(Oid tempNamespaceId);
133 static void RemoveTempRelationsCallback(void);
134 static void NamespaceCallback(Datum arg, Oid relid);
135
136 /* These don't really need to appear in any header file */
137 Datum           pg_table_is_visible(PG_FUNCTION_ARGS);
138 Datum           pg_type_is_visible(PG_FUNCTION_ARGS);
139 Datum           pg_function_is_visible(PG_FUNCTION_ARGS);
140 Datum           pg_operator_is_visible(PG_FUNCTION_ARGS);
141 Datum           pg_opclass_is_visible(PG_FUNCTION_ARGS);
142 Datum           pg_conversion_is_visible(PG_FUNCTION_ARGS);
143
144
145 /*
146  * RangeVarGetRelid
147  *              Given a RangeVar describing an existing relation,
148  *              select the proper namespace and look up the relation OID.
149  *
150  * If the relation is not found, return InvalidOid if failOK = true,
151  * otherwise raise an error.
152  */
153 Oid
154 RangeVarGetRelid(const RangeVar *relation, bool failOK)
155 {
156         Oid                     namespaceId;
157         Oid                     relId;
158
159         /*
160          * We check the catalog name and then ignore it.
161          */
162         if (relation->catalogname)
163         {
164                 if (strcmp(relation->catalogname, get_database_name(MyDatabaseId)) != 0)
165                         elog(ERROR, "Cross-database references are not implemented");
166         }
167
168         if (relation->schemaname)
169         {
170                 /* use exact schema given */
171                 namespaceId = LookupExplicitNamespace(relation->schemaname);
172                 relId = get_relname_relid(relation->relname, namespaceId);
173         }
174         else
175         {
176                 /* search the namespace path */
177                 relId = RelnameGetRelid(relation->relname);
178         }
179
180         if (!OidIsValid(relId) && !failOK)
181         {
182                 if (relation->schemaname)
183                         elog(ERROR, "Relation \"%s\".\"%s\" does not exist",
184                                  relation->schemaname, relation->relname);
185                 else
186                         elog(ERROR, "Relation \"%s\" does not exist",
187                                  relation->relname);
188         }
189         return relId;
190 }
191
192 /*
193  * RangeVarGetCreationNamespace
194  *              Given a RangeVar describing a to-be-created relation,
195  *              choose which namespace to create it in.
196  *
197  * Note: calling this may result in a CommandCounterIncrement operation.
198  * That will happen on the first request for a temp table in any particular
199  * backend run; we will need to either create or clean out the temp schema.
200  */
201 Oid
202 RangeVarGetCreationNamespace(const RangeVar *newRelation)
203 {
204         Oid                     namespaceId;
205
206         /*
207          * We check the catalog name and then ignore it.
208          */
209         if (newRelation->catalogname)
210         {
211                 if (strcmp(newRelation->catalogname, get_database_name(MyDatabaseId)) != 0)
212                         elog(ERROR, "Cross-database references are not implemented");
213         }
214
215         if (newRelation->istemp)
216         {
217                 /* TEMP tables are created in our backend-local temp namespace */
218                 if (newRelation->schemaname)
219                         elog(ERROR, "TEMP tables may not specify a namespace");
220                 /* Initialize temp namespace if first time through */
221                 if (!OidIsValid(myTempNamespace))
222                         InitTempTableNamespace();
223                 return myTempNamespace;
224         }
225
226         if (newRelation->schemaname)
227         {
228                 /* use exact schema given */
229                 namespaceId = GetSysCacheOid(NAMESPACENAME,
230                                                                 CStringGetDatum(newRelation->schemaname),
231                                                                          0, 0, 0);
232                 if (!OidIsValid(namespaceId))
233                         elog(ERROR, "Namespace \"%s\" does not exist",
234                                  newRelation->schemaname);
235                 /* we do not check for USAGE rights here! */
236         }
237         else
238         {
239                 /* use the default creation namespace */
240                 recomputeNamespacePath();
241                 namespaceId = defaultCreationNamespace;
242                 if (!OidIsValid(namespaceId))
243                         elog(ERROR, "No namespace has been selected to create in");
244         }
245
246         /* Note: callers will check for CREATE rights when appropriate */
247
248         return namespaceId;
249 }
250
251 /*
252  * RelnameGetRelid
253  *              Try to resolve an unqualified relation name.
254  *              Returns OID if relation found in search path, else InvalidOid.
255  */
256 Oid
257 RelnameGetRelid(const char *relname)
258 {
259         Oid                     relid;
260         List       *lptr;
261
262         recomputeNamespacePath();
263
264         foreach(lptr, namespaceSearchPath)
265         {
266                 Oid                     namespaceId = lfirsto(lptr);
267
268                 relid = get_relname_relid(relname, namespaceId);
269                 if (OidIsValid(relid))
270                         return relid;
271         }
272
273         /* Not found in path */
274         return InvalidOid;
275 }
276
277
278 /*
279  * RelationIsVisible
280  *              Determine whether a relation (identified by OID) is visible in the
281  *              current search path.  Visible means "would be found by searching
282  *              for the unqualified relation name".
283  */
284 bool
285 RelationIsVisible(Oid relid)
286 {
287         HeapTuple       reltup;
288         Form_pg_class relform;
289         Oid                     relnamespace;
290         bool            visible;
291
292         reltup = SearchSysCache(RELOID,
293                                                         ObjectIdGetDatum(relid),
294                                                         0, 0, 0);
295         if (!HeapTupleIsValid(reltup))
296                 elog(ERROR, "Cache lookup failed for relation %u", relid);
297         relform = (Form_pg_class) GETSTRUCT(reltup);
298
299         recomputeNamespacePath();
300
301         /*
302          * Quick check: if it ain't in the path at all, it ain't visible.
303          * Items in the system namespace are surely in the path and so we
304          * needn't even do oidMember() for them.
305          */
306         relnamespace = relform->relnamespace;
307         if (relnamespace != PG_CATALOG_NAMESPACE &&
308                 !oidMember(relnamespace, namespaceSearchPath))
309                 visible = false;
310         else
311         {
312                 /*
313                  * If it is in the path, it might still not be visible; it could
314                  * be hidden by another relation of the same name earlier in the
315                  * path. So we must do a slow check to see if this rel would be
316                  * found by RelnameGetRelid.
317                  */
318                 char       *relname = NameStr(relform->relname);
319
320                 visible = (RelnameGetRelid(relname) == relid);
321         }
322
323         ReleaseSysCache(reltup);
324
325         return visible;
326 }
327
328
329 /*
330  * TypenameGetTypid
331  *              Try to resolve an unqualified datatype name.
332  *              Returns OID if type found in search path, else InvalidOid.
333  *
334  * This is essentially the same as RelnameGetRelid.
335  */
336 Oid
337 TypenameGetTypid(const char *typname)
338 {
339         Oid                     typid;
340         List       *lptr;
341
342         recomputeNamespacePath();
343
344         foreach(lptr, namespaceSearchPath)
345         {
346                 Oid                     namespaceId = lfirsto(lptr);
347
348                 typid = GetSysCacheOid(TYPENAMENSP,
349                                                            PointerGetDatum(typname),
350                                                            ObjectIdGetDatum(namespaceId),
351                                                            0, 0);
352                 if (OidIsValid(typid))
353                         return typid;
354         }
355
356         /* Not found in path */
357         return InvalidOid;
358 }
359
360 /*
361  * TypeIsVisible
362  *              Determine whether a type (identified by OID) is visible in the
363  *              current search path.  Visible means "would be found by searching
364  *              for the unqualified type name".
365  */
366 bool
367 TypeIsVisible(Oid typid)
368 {
369         HeapTuple       typtup;
370         Form_pg_type typform;
371         Oid                     typnamespace;
372         bool            visible;
373
374         typtup = SearchSysCache(TYPEOID,
375                                                         ObjectIdGetDatum(typid),
376                                                         0, 0, 0);
377         if (!HeapTupleIsValid(typtup))
378                 elog(ERROR, "Cache lookup failed for type %u", typid);
379         typform = (Form_pg_type) GETSTRUCT(typtup);
380
381         recomputeNamespacePath();
382
383         /*
384          * Quick check: if it ain't in the path at all, it ain't visible.
385          * Items in the system namespace are surely in the path and so we
386          * needn't even do oidMember() for them.
387          */
388         typnamespace = typform->typnamespace;
389         if (typnamespace != PG_CATALOG_NAMESPACE &&
390                 !oidMember(typnamespace, namespaceSearchPath))
391                 visible = false;
392         else
393         {
394                 /*
395                  * If it is in the path, it might still not be visible; it could
396                  * be hidden by another type of the same name earlier in the path.
397                  * So we must do a slow check to see if this type would be found
398                  * by TypenameGetTypid.
399                  */
400                 char       *typname = NameStr(typform->typname);
401
402                 visible = (TypenameGetTypid(typname) == typid);
403         }
404
405         ReleaseSysCache(typtup);
406
407         return visible;
408 }
409
410
411 /*
412  * FuncnameGetCandidates
413  *              Given a possibly-qualified function name and argument count,
414  *              retrieve a list of the possible matches.
415  *
416  * If nargs is -1, we return all functions matching the given name,
417  * regardless of argument count.
418  *
419  * We search a single namespace if the function name is qualified, else
420  * all namespaces in the search path.  The return list will never contain
421  * multiple entries with identical argument lists --- in the multiple-
422  * namespace case, we arrange for entries in earlier namespaces to mask
423  * identical entries in later namespaces.
424  */
425 FuncCandidateList
426 FuncnameGetCandidates(List *names, int nargs)
427 {
428         FuncCandidateList resultList = NULL;
429         char       *schemaname;
430         char       *funcname;
431         Oid                     namespaceId;
432         CatCList   *catlist;
433         int                     i;
434
435         /* deconstruct the name list */
436         DeconstructQualifiedName(names, &schemaname, &funcname);
437
438         if (schemaname)
439         {
440                 /* use exact schema given */
441                 namespaceId = LookupExplicitNamespace(schemaname);
442         }
443         else
444         {
445                 /* flag to indicate we need namespace search */
446                 namespaceId = InvalidOid;
447                 recomputeNamespacePath();
448         }
449
450         /* Search syscache by name and (optionally) nargs only */
451         if (nargs >= 0)
452                 catlist = SearchSysCacheList(PROCNAMENSP, 2,
453                                                                          CStringGetDatum(funcname),
454                                                                          Int16GetDatum(nargs),
455                                                                          0, 0);
456         else
457                 catlist = SearchSysCacheList(PROCNAMENSP, 1,
458                                                                          CStringGetDatum(funcname),
459                                                                          0, 0, 0);
460
461         for (i = 0; i < catlist->n_members; i++)
462         {
463                 HeapTuple       proctup = &catlist->members[i]->tuple;
464                 Form_pg_proc procform = (Form_pg_proc) GETSTRUCT(proctup);
465                 int                     pathpos = 0;
466                 FuncCandidateList newResult;
467
468                 nargs = procform->pronargs;
469
470                 if (OidIsValid(namespaceId))
471                 {
472                         /* Consider only procs in specified namespace */
473                         if (procform->pronamespace != namespaceId)
474                                 continue;
475                         /* No need to check args, they must all be different */
476                 }
477                 else
478                 {
479                         /* Consider only procs that are in the search path */
480                         List       *nsp;
481
482                         foreach(nsp, namespaceSearchPath)
483                         {
484                                 if (procform->pronamespace == lfirsto(nsp))
485                                         break;
486                                 pathpos++;
487                         }
488                         if (nsp == NIL)
489                                 continue;               /* proc is not in search path */
490
491                         /*
492                          * Okay, it's in the search path, but does it have the same
493                          * arguments as something we already accepted?  If so, keep
494                          * only the one that appears earlier in the search path.
495                          *
496                          * If we have an ordered list from SearchSysCacheList (the normal
497                          * case), then any conflicting proc must immediately adjoin
498                          * this one in the list, so we only need to look at the newest
499                          * result item.  If we have an unordered list, we have to scan
500                          * the whole result list.
501                          */
502                         if (resultList)
503                         {
504                                 FuncCandidateList prevResult;
505
506                                 if (catlist->ordered)
507                                 {
508                                         if (nargs == resultList->nargs &&
509                                                 memcmp(procform->proargtypes, resultList->args,
510                                                            nargs * sizeof(Oid)) == 0)
511                                                 prevResult = resultList;
512                                         else
513                                                 prevResult = NULL;
514                                 }
515                                 else
516                                 {
517                                         for (prevResult = resultList;
518                                                  prevResult;
519                                                  prevResult = prevResult->next)
520                                         {
521                                                 if (nargs == prevResult->nargs &&
522                                                   memcmp(procform->proargtypes, prevResult->args,
523                                                                  nargs * sizeof(Oid)) == 0)
524                                                         break;
525                                         }
526                                 }
527                                 if (prevResult)
528                                 {
529                                         /* We have a match with a previous result */
530                                         Assert(pathpos != prevResult->pathpos);
531                                         if (pathpos > prevResult->pathpos)
532                                                 continue;               /* keep previous result */
533                                         /* replace previous result */
534                                         prevResult->pathpos = pathpos;
535                                         prevResult->oid = HeapTupleGetOid(proctup);
536                                         continue;       /* args are same, of course */
537                                 }
538                         }
539                 }
540
541                 /*
542                  * Okay to add it to result list
543                  */
544                 newResult = (FuncCandidateList)
545                         palloc(sizeof(struct _FuncCandidateList) - sizeof(Oid)
546                                    + nargs * sizeof(Oid));
547                 newResult->pathpos = pathpos;
548                 newResult->oid = HeapTupleGetOid(proctup);
549                 newResult->nargs = nargs;
550                 memcpy(newResult->args, procform->proargtypes, nargs * sizeof(Oid));
551
552                 newResult->next = resultList;
553                 resultList = newResult;
554         }
555
556         ReleaseSysCacheList(catlist);
557
558         return resultList;
559 }
560
561 /*
562  * FunctionIsVisible
563  *              Determine whether a function (identified by OID) is visible in the
564  *              current search path.  Visible means "would be found by searching
565  *              for the unqualified function name with exact argument matches".
566  */
567 bool
568 FunctionIsVisible(Oid funcid)
569 {
570         HeapTuple       proctup;
571         Form_pg_proc procform;
572         Oid                     pronamespace;
573         bool            visible;
574
575         proctup = SearchSysCache(PROCOID,
576                                                          ObjectIdGetDatum(funcid),
577                                                          0, 0, 0);
578         if (!HeapTupleIsValid(proctup))
579                 elog(ERROR, "Cache lookup failed for procedure %u", funcid);
580         procform = (Form_pg_proc) GETSTRUCT(proctup);
581
582         recomputeNamespacePath();
583
584         /*
585          * Quick check: if it ain't in the path at all, it ain't visible.
586          * Items in the system namespace are surely in the path and so we
587          * needn't even do oidMember() for them.
588          */
589         pronamespace = procform->pronamespace;
590         if (pronamespace != PG_CATALOG_NAMESPACE &&
591                 !oidMember(pronamespace, namespaceSearchPath))
592                 visible = false;
593         else
594         {
595                 /*
596                  * If it is in the path, it might still not be visible; it could
597                  * be hidden by another proc of the same name and arguments
598                  * earlier in the path.  So we must do a slow check to see if this
599                  * is the same proc that would be found by FuncnameGetCandidates.
600                  */
601                 char       *proname = NameStr(procform->proname);
602                 int                     nargs = procform->pronargs;
603                 FuncCandidateList clist;
604
605                 visible = false;
606
607                 clist = FuncnameGetCandidates(makeList1(makeString(proname)), nargs);
608
609                 for (; clist; clist = clist->next)
610                 {
611                         if (memcmp(clist->args, procform->proargtypes,
612                                            nargs * sizeof(Oid)) == 0)
613                         {
614                                 /* Found the expected entry; is it the right proc? */
615                                 visible = (clist->oid == funcid);
616                                 break;
617                         }
618                 }
619         }
620
621         ReleaseSysCache(proctup);
622
623         return visible;
624 }
625
626
627 /*
628  * OpernameGetCandidates
629  *              Given a possibly-qualified operator name and operator kind,
630  *              retrieve a list of the possible matches.
631  *
632  * If oprkind is '\0', we return all operators matching the given name,
633  * regardless of arguments.
634  *
635  * We search a single namespace if the operator name is qualified, else
636  * all namespaces in the search path.  The return list will never contain
637  * multiple entries with identical argument lists --- in the multiple-
638  * namespace case, we arrange for entries in earlier namespaces to mask
639  * identical entries in later namespaces.
640  *
641  * The returned items always have two args[] entries --- one or the other
642  * will be InvalidOid for a prefix or postfix oprkind.  nargs is 2, too.
643  */
644 FuncCandidateList
645 OpernameGetCandidates(List *names, char oprkind)
646 {
647         FuncCandidateList resultList = NULL;
648         char       *schemaname;
649         char       *opername;
650         Oid                     namespaceId;
651         CatCList   *catlist;
652         int                     i;
653
654         /* deconstruct the name list */
655         DeconstructQualifiedName(names, &schemaname, &opername);
656
657         if (schemaname)
658         {
659                 /* use exact schema given */
660                 namespaceId = LookupExplicitNamespace(schemaname);
661         }
662         else
663         {
664                 /* flag to indicate we need namespace search */
665                 namespaceId = InvalidOid;
666                 recomputeNamespacePath();
667         }
668
669         /* Search syscache by name only */
670         catlist = SearchSysCacheList(OPERNAMENSP, 1,
671                                                                  CStringGetDatum(opername),
672                                                                  0, 0, 0);
673
674         for (i = 0; i < catlist->n_members; i++)
675         {
676                 HeapTuple       opertup = &catlist->members[i]->tuple;
677                 Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup);
678                 int                     pathpos = 0;
679                 FuncCandidateList newResult;
680
681                 /* Ignore operators of wrong kind, if specific kind requested */
682                 if (oprkind && operform->oprkind != oprkind)
683                         continue;
684
685                 if (OidIsValid(namespaceId))
686                 {
687                         /* Consider only opers in specified namespace */
688                         if (operform->oprnamespace != namespaceId)
689                                 continue;
690                         /* No need to check args, they must all be different */
691                 }
692                 else
693                 {
694                         /* Consider only opers that are in the search path */
695                         List       *nsp;
696
697                         foreach(nsp, namespaceSearchPath)
698                         {
699                                 if (operform->oprnamespace == lfirsto(nsp))
700                                         break;
701                                 pathpos++;
702                         }
703                         if (nsp == NIL)
704                                 continue;               /* oper is not in search path */
705
706                         /*
707                          * Okay, it's in the search path, but does it have the same
708                          * arguments as something we already accepted?  If so, keep
709                          * only the one that appears earlier in the search path.
710                          *
711                          * If we have an ordered list from SearchSysCacheList (the normal
712                          * case), then any conflicting oper must immediately adjoin
713                          * this one in the list, so we only need to look at the newest
714                          * result item.  If we have an unordered list, we have to scan
715                          * the whole result list.
716                          */
717                         if (resultList)
718                         {
719                                 FuncCandidateList prevResult;
720
721                                 if (catlist->ordered)
722                                 {
723                                         if (operform->oprleft == resultList->args[0] &&
724                                                 operform->oprright == resultList->args[1])
725                                                 prevResult = resultList;
726                                         else
727                                                 prevResult = NULL;
728                                 }
729                                 else
730                                 {
731                                         for (prevResult = resultList;
732                                                  prevResult;
733                                                  prevResult = prevResult->next)
734                                         {
735                                                 if (operform->oprleft == prevResult->args[0] &&
736                                                         operform->oprright == prevResult->args[1])
737                                                         break;
738                                         }
739                                 }
740                                 if (prevResult)
741                                 {
742                                         /* We have a match with a previous result */
743                                         Assert(pathpos != prevResult->pathpos);
744                                         if (pathpos > prevResult->pathpos)
745                                                 continue;               /* keep previous result */
746                                         /* replace previous result */
747                                         prevResult->pathpos = pathpos;
748                                         prevResult->oid = HeapTupleGetOid(opertup);
749                                         continue;       /* args are same, of course */
750                                 }
751                         }
752                 }
753
754                 /*
755                  * Okay to add it to result list
756                  */
757                 newResult = (FuncCandidateList)
758                         palloc(sizeof(struct _FuncCandidateList) + sizeof(Oid));
759                 newResult->pathpos = pathpos;
760                 newResult->oid = HeapTupleGetOid(opertup);
761                 newResult->nargs = 2;
762                 newResult->args[0] = operform->oprleft;
763                 newResult->args[1] = operform->oprright;
764                 newResult->next = resultList;
765                 resultList = newResult;
766         }
767
768         ReleaseSysCacheList(catlist);
769
770         return resultList;
771 }
772
773 /*
774  * OperatorIsVisible
775  *              Determine whether an operator (identified by OID) is visible in the
776  *              current search path.  Visible means "would be found by searching
777  *              for the unqualified operator name with exact argument matches".
778  */
779 bool
780 OperatorIsVisible(Oid oprid)
781 {
782         HeapTuple       oprtup;
783         Form_pg_operator oprform;
784         Oid                     oprnamespace;
785         bool            visible;
786
787         oprtup = SearchSysCache(OPEROID,
788                                                         ObjectIdGetDatum(oprid),
789                                                         0, 0, 0);
790         if (!HeapTupleIsValid(oprtup))
791                 elog(ERROR, "Cache lookup failed for operator %u", oprid);
792         oprform = (Form_pg_operator) GETSTRUCT(oprtup);
793
794         recomputeNamespacePath();
795
796         /*
797          * Quick check: if it ain't in the path at all, it ain't visible.
798          * Items in the system namespace are surely in the path and so we
799          * needn't even do oidMember() for them.
800          */
801         oprnamespace = oprform->oprnamespace;
802         if (oprnamespace != PG_CATALOG_NAMESPACE &&
803                 !oidMember(oprnamespace, namespaceSearchPath))
804                 visible = false;
805         else
806         {
807                 /*
808                  * If it is in the path, it might still not be visible; it could
809                  * be hidden by another operator of the same name and arguments
810                  * earlier in the path.  So we must do a slow check to see if this
811                  * is the same operator that would be found by
812                  * OpernameGetCandidates.
813                  */
814                 char       *oprname = NameStr(oprform->oprname);
815                 FuncCandidateList clist;
816
817                 visible = false;
818
819                 clist = OpernameGetCandidates(makeList1(makeString(oprname)),
820                                                                           oprform->oprkind);
821
822                 for (; clist; clist = clist->next)
823                 {
824                         if (clist->args[0] == oprform->oprleft &&
825                                 clist->args[1] == oprform->oprright)
826                         {
827                                 /* Found the expected entry; is it the right op? */
828                                 visible = (clist->oid == oprid);
829                                 break;
830                         }
831                 }
832         }
833
834         ReleaseSysCache(oprtup);
835
836         return visible;
837 }
838
839
840 /*
841  * OpclassGetCandidates
842  *              Given an index access method OID, retrieve a list of all the
843  *              opclasses for that AM that are visible in the search path.
844  *
845  * NOTE: the opcname_tmp field in the returned structs should not be used
846  * by callers, because it points at syscache entries that we release at
847  * the end of this routine.  If any callers needed the name information,
848  * we could pstrdup() the names ... but at present it'd be wasteful.
849  */
850 OpclassCandidateList
851 OpclassGetCandidates(Oid amid)
852 {
853         OpclassCandidateList resultList = NULL;
854         CatCList   *catlist;
855         int                     i;
856
857         /* Search syscache by AM OID only */
858         catlist = SearchSysCacheList(CLAAMNAMENSP, 1,
859                                                                  ObjectIdGetDatum(amid),
860                                                                  0, 0, 0);
861
862         recomputeNamespacePath();
863
864         for (i = 0; i < catlist->n_members; i++)
865         {
866                 HeapTuple       opctup = &catlist->members[i]->tuple;
867                 Form_pg_opclass opcform = (Form_pg_opclass) GETSTRUCT(opctup);
868                 int                     pathpos = 0;
869                 OpclassCandidateList newResult;
870                 List       *nsp;
871
872                 /* Consider only opclasses that are in the search path */
873                 foreach(nsp, namespaceSearchPath)
874                 {
875                         if (opcform->opcnamespace == lfirsto(nsp))
876                                 break;
877                         pathpos++;
878                 }
879                 if (nsp == NIL)
880                         continue;                       /* opclass is not in search path */
881
882                 /*
883                  * Okay, it's in the search path, but does it have the same name
884                  * as something we already accepted?  If so, keep only the one
885                  * that appears earlier in the search path.
886                  *
887                  * If we have an ordered list from SearchSysCacheList (the normal
888                  * case), then any conflicting opclass must immediately adjoin
889                  * this one in the list, so we only need to look at the newest
890                  * result item.  If we have an unordered list, we have to scan the
891                  * whole result list.
892                  */
893                 if (resultList)
894                 {
895                         OpclassCandidateList prevResult;
896
897                         if (catlist->ordered)
898                         {
899                                 if (strcmp(NameStr(opcform->opcname),
900                                                    resultList->opcname_tmp) == 0)
901                                         prevResult = resultList;
902                                 else
903                                         prevResult = NULL;
904                         }
905                         else
906                         {
907                                 for (prevResult = resultList;
908                                          prevResult;
909                                          prevResult = prevResult->next)
910                                 {
911                                         if (strcmp(NameStr(opcform->opcname),
912                                                            prevResult->opcname_tmp) == 0)
913                                                 break;
914                                 }
915                         }
916                         if (prevResult)
917                         {
918                                 /* We have a match with a previous result */
919                                 Assert(pathpos != prevResult->pathpos);
920                                 if (pathpos > prevResult->pathpos)
921                                         continue;       /* keep previous result */
922                                 /* replace previous result */
923                                 prevResult->opcname_tmp = NameStr(opcform->opcname);
924                                 prevResult->pathpos = pathpos;
925                                 prevResult->oid = HeapTupleGetOid(opctup);
926                                 prevResult->opcintype = opcform->opcintype;
927                                 prevResult->opcdefault = opcform->opcdefault;
928                                 prevResult->opckeytype = opcform->opckeytype;
929                                 continue;
930                         }
931                 }
932
933                 /*
934                  * Okay to add it to result list
935                  */
936                 newResult = (OpclassCandidateList)
937                         palloc(sizeof(struct _OpclassCandidateList));
938                 newResult->opcname_tmp = NameStr(opcform->opcname);
939                 newResult->pathpos = pathpos;
940                 newResult->oid = HeapTupleGetOid(opctup);
941                 newResult->opcintype = opcform->opcintype;
942                 newResult->opcdefault = opcform->opcdefault;
943                 newResult->opckeytype = opcform->opckeytype;
944                 newResult->next = resultList;
945                 resultList = newResult;
946         }
947
948         ReleaseSysCacheList(catlist);
949
950         return resultList;
951 }
952
953 /*
954  * OpclassnameGetOpcid
955  *              Try to resolve an unqualified index opclass name.
956  *              Returns OID if opclass found in search path, else InvalidOid.
957  *
958  * This is essentially the same as TypenameGetTypid, but we have to have
959  * an extra argument for the index AM OID.
960  */
961 Oid
962 OpclassnameGetOpcid(Oid amid, const char *opcname)
963 {
964         Oid                     opcid;
965         List       *lptr;
966
967         recomputeNamespacePath();
968
969         foreach(lptr, namespaceSearchPath)
970         {
971                 Oid                     namespaceId = lfirsto(lptr);
972
973                 opcid = GetSysCacheOid(CLAAMNAMENSP,
974                                                            ObjectIdGetDatum(amid),
975                                                            PointerGetDatum(opcname),
976                                                            ObjectIdGetDatum(namespaceId),
977                                                            0);
978                 if (OidIsValid(opcid))
979                         return opcid;
980         }
981
982         /* Not found in path */
983         return InvalidOid;
984 }
985
986 /*
987  * OpclassIsVisible
988  *              Determine whether an opclass (identified by OID) is visible in the
989  *              current search path.  Visible means "would be found by searching
990  *              for the unqualified opclass name".
991  */
992 bool
993 OpclassIsVisible(Oid opcid)
994 {
995         HeapTuple       opctup;
996         Form_pg_opclass opcform;
997         Oid                     opcnamespace;
998         bool            visible;
999
1000         opctup = SearchSysCache(CLAOID,
1001                                                         ObjectIdGetDatum(opcid),
1002                                                         0, 0, 0);
1003         if (!HeapTupleIsValid(opctup))
1004                 elog(ERROR, "Cache lookup failed for opclass %u", opcid);
1005         opcform = (Form_pg_opclass) GETSTRUCT(opctup);
1006
1007         recomputeNamespacePath();
1008
1009         /*
1010          * Quick check: if it ain't in the path at all, it ain't visible.
1011          * Items in the system namespace are surely in the path and so we
1012          * needn't even do oidMember() for them.
1013          */
1014         opcnamespace = opcform->opcnamespace;
1015         if (opcnamespace != PG_CATALOG_NAMESPACE &&
1016                 !oidMember(opcnamespace, namespaceSearchPath))
1017                 visible = false;
1018         else
1019         {
1020                 /*
1021                  * If it is in the path, it might still not be visible; it could
1022                  * be hidden by another opclass of the same name earlier in the
1023                  * path. So we must do a slow check to see if this opclass would
1024                  * be found by OpclassnameGetOpcid.
1025                  */
1026                 char       *opcname = NameStr(opcform->opcname);
1027
1028                 visible = (OpclassnameGetOpcid(opcform->opcamid, opcname) == opcid);
1029         }
1030
1031         ReleaseSysCache(opctup);
1032
1033         return visible;
1034 }
1035
1036 /*
1037  * ConversionGetConid
1038  *              Try to resolve an unqualified conversion name.
1039  *              Returns OID if conversion found in search path, else InvalidOid.
1040  *
1041  * This is essentially the same as RelnameGetRelid.
1042  */
1043 Oid
1044 ConversionGetConid(const char *conname)
1045 {
1046         Oid             conid;
1047         List       *lptr;
1048
1049         recomputeNamespacePath();
1050
1051         foreach(lptr, namespaceSearchPath)
1052         {
1053                 Oid                     namespaceId = lfirsto(lptr);
1054
1055                 conid = GetSysCacheOid(CONNAMENSP,
1056                                                            PointerGetDatum(conname),
1057                                                            ObjectIdGetDatum(namespaceId),
1058                                                            0, 0);
1059                 if (OidIsValid(conid))
1060                         return conid;
1061         }
1062
1063         /* Not found in path */
1064         return InvalidOid;
1065 }
1066
1067 /*
1068  * ConversionIsVisible
1069  *              Determine whether a conversion (identified by OID) is visible in the
1070  *              current search path.  Visible means "would be found by searching
1071  *              for the unqualified conversion name".
1072  */
1073 bool
1074 ConversionIsVisible(Oid conid)
1075 {
1076         HeapTuple       contup;
1077         Form_pg_conversion conform;
1078         Oid                     connamespace;
1079         bool            visible;
1080
1081         contup = SearchSysCache(CONOID,
1082                                                         ObjectIdGetDatum(conid),
1083                                                         0, 0, 0);
1084         if (!HeapTupleIsValid(contup))
1085                 elog(ERROR, "Cache lookup failed for conversion %u", conid);
1086         conform = (Form_pg_conversion) GETSTRUCT(contup);
1087
1088         recomputeNamespacePath();
1089
1090         /*
1091          * Quick check: if it ain't in the path at all, it ain't visible.
1092          * Items in the system namespace are surely in the path and so we
1093          * needn't even do oidMember() for them.
1094          */
1095         connamespace = conform->connamespace;
1096         if (connamespace != PG_CATALOG_NAMESPACE &&
1097                 !oidMember(connamespace, namespaceSearchPath))
1098                 visible = false;
1099         else
1100         {
1101                 /*
1102                  * If it is in the path, it might still not be visible; it could
1103                  * be hidden by another conversion of the same name earlier in the
1104                  * path. So we must do a slow check to see if this conversion would
1105                  * be found by ConversionGetConid.
1106                  */
1107                 char       *conname = NameStr(conform->conname);
1108                 
1109                 visible = (ConversionGetConid(conname) == conid);
1110         }
1111
1112         ReleaseSysCache(contup);
1113
1114         return visible;
1115 }
1116
1117 /*
1118  * DeconstructQualifiedName
1119  *              Given a possibly-qualified name expressed as a list of String nodes,
1120  *              extract the schema name and object name.
1121  *
1122  * *nspname_p is set to NULL if there is no explicit schema name.
1123  */
1124 void
1125 DeconstructQualifiedName(List *names,
1126                                                  char **nspname_p,
1127                                                  char **objname_p)
1128 {
1129         char       *catalogname;
1130         char       *schemaname = NULL;
1131         char       *objname = NULL;
1132
1133         switch (length(names))
1134         {
1135                 case 1:
1136                         objname = strVal(lfirst(names));
1137                         break;
1138                 case 2:
1139                         schemaname = strVal(lfirst(names));
1140                         objname = strVal(lsecond(names));
1141                         break;
1142                 case 3:
1143                         catalogname = strVal(lfirst(names));
1144                         schemaname = strVal(lsecond(names));
1145                         objname = strVal(lthird(names));
1146
1147                         /*
1148                          * We check the catalog name and then ignore it.
1149                          */
1150                         if (strcmp(catalogname, get_database_name(MyDatabaseId)) != 0)
1151                                 elog(ERROR, "Cross-database references are not implemented");
1152                         break;
1153                 default:
1154                         elog(ERROR, "Improper qualified name (too many dotted names): %s",
1155                                  NameListToString(names));
1156                         break;
1157         }
1158
1159         *nspname_p = schemaname;
1160         *objname_p = objname;
1161 }
1162
1163 /*
1164  * LookupExplicitNamespace
1165  *              Process an explicitly-specified schema name: look up the schema
1166  *              and verify we have USAGE (lookup) rights in it.
1167  *
1168  * Returns the namespace OID.  Raises elog if any problem.
1169  */
1170 Oid
1171 LookupExplicitNamespace(const char *nspname)
1172 {
1173         Oid                     namespaceId;
1174         AclResult       aclresult;
1175
1176         namespaceId = GetSysCacheOid(NAMESPACENAME,
1177                                                                  CStringGetDatum(nspname),
1178                                                                  0, 0, 0);
1179         if (!OidIsValid(namespaceId))
1180                 elog(ERROR, "Namespace \"%s\" does not exist", nspname);
1181
1182         aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_USAGE);
1183         if (aclresult != ACLCHECK_OK)
1184                 aclcheck_error(aclresult, nspname);
1185
1186         return namespaceId;
1187 }
1188
1189 /*
1190  * QualifiedNameGetCreationNamespace
1191  *              Given a possibly-qualified name for an object (in List-of-Values
1192  *              format), determine what namespace the object should be created in.
1193  *              Also extract and return the object name (last component of list).
1194  *
1195  * This is *not* used for tables.  Hence, the TEMP table namespace is
1196  * never selected as the creation target.
1197  */
1198 Oid
1199 QualifiedNameGetCreationNamespace(List *names, char **objname_p)
1200 {
1201         char       *schemaname;
1202         char       *objname;
1203         Oid                     namespaceId;
1204
1205         /* deconstruct the name list */
1206         DeconstructQualifiedName(names, &schemaname, &objname);
1207
1208         if (schemaname)
1209         {
1210                 /* use exact schema given */
1211                 namespaceId = GetSysCacheOid(NAMESPACENAME,
1212                                                                          CStringGetDatum(schemaname),
1213                                                                          0, 0, 0);
1214                 if (!OidIsValid(namespaceId))
1215                         elog(ERROR, "Namespace \"%s\" does not exist",
1216                                  schemaname);
1217                 /* we do not check for USAGE rights here! */
1218         }
1219         else
1220         {
1221                 /* use the default creation namespace */
1222                 recomputeNamespacePath();
1223                 namespaceId = defaultCreationNamespace;
1224                 if (!OidIsValid(namespaceId))
1225                         elog(ERROR, "No namespace has been selected to create in");
1226         }
1227
1228         /* Note: callers will check for CREATE rights when appropriate */
1229
1230         *objname_p = objname;
1231         return namespaceId;
1232 }
1233
1234 /*
1235  * makeRangeVarFromNameList
1236  *              Utility routine to convert a qualified-name list into RangeVar form.
1237  */
1238 RangeVar *
1239 makeRangeVarFromNameList(List *names)
1240 {
1241         RangeVar   *rel = makeRangeVar(NULL, NULL);
1242
1243         switch (length(names))
1244         {
1245                 case 1:
1246                         rel->relname = strVal(lfirst(names));
1247                         break;
1248                 case 2:
1249                         rel->schemaname = strVal(lfirst(names));
1250                         rel->relname = strVal(lsecond(names));
1251                         break;
1252                 case 3:
1253                         rel->catalogname = strVal(lfirst(names));
1254                         rel->schemaname = strVal(lsecond(names));
1255                         rel->relname = strVal(lthird(names));
1256                         break;
1257                 default:
1258                         elog(ERROR, "Improper relation name (too many dotted names)");
1259                         break;
1260         }
1261
1262         return rel;
1263 }
1264
1265 /*
1266  * NameListToString
1267  *              Utility routine to convert a qualified-name list into a string.
1268  *
1269  * This is used primarily to form error messages, and so we do not quote
1270  * the list elements, for the sake of legibility.
1271  */
1272 char *
1273 NameListToString(List *names)
1274 {
1275         StringInfoData string;
1276         List       *l;
1277
1278         initStringInfo(&string);
1279
1280         foreach(l, names)
1281         {
1282                 if (l != names)
1283                         appendStringInfoChar(&string, '.');
1284                 appendStringInfoString(&string, strVal(lfirst(l)));
1285         }
1286
1287         return string.data;
1288 }
1289
1290 /*
1291  * NameListToQuotedString
1292  *              Utility routine to convert a qualified-name list into a string.
1293  *
1294  * Same as above except that names will be double-quoted where necessary,
1295  * so the string could be re-parsed (eg, by textToQualifiedNameList).
1296  */
1297 char *
1298 NameListToQuotedString(List *names)
1299 {
1300         StringInfoData string;
1301         List       *l;
1302
1303         initStringInfo(&string);
1304
1305         foreach(l, names)
1306         {
1307                 if (l != names)
1308                         appendStringInfoChar(&string, '.');
1309                 appendStringInfoString(&string, quote_identifier(strVal(lfirst(l))));
1310         }
1311
1312         return string.data;
1313 }
1314
1315 /*
1316  * isTempNamespace - is the given namespace my temporary-table namespace?
1317  */
1318 bool
1319 isTempNamespace(Oid namespaceId)
1320 {
1321         if (OidIsValid(myTempNamespace) && myTempNamespace == namespaceId)
1322                 return true;
1323         return false;
1324 }
1325
1326 /*
1327  * isOtherTempNamespace - is the given namespace some other backend's
1328  * temporary-table namespace?
1329  */
1330 bool
1331 isOtherTempNamespace(Oid namespaceId)
1332 {
1333         bool            result;
1334         char       *nspname;
1335
1336         /* If it's my own temp namespace, say "false" */
1337         if (isTempNamespace(namespaceId))
1338                 return false;
1339         /* Else, if the namespace name starts with "pg_temp_", say "true" */
1340         nspname = get_namespace_name(namespaceId);
1341         if (!nspname)
1342                 return false;                   /* no such namespace? */
1343         result = (strncmp(nspname, "pg_temp_", 8) == 0);
1344         pfree(nspname);
1345         return result;
1346 }
1347
1348 /*
1349  * PushSpecialNamespace - push a "special" namespace onto the front of the
1350  * search path.
1351  *
1352  * This is a slightly messy hack intended only for support of CREATE SCHEMA.
1353  * Although the API is defined to allow a stack of pushed namespaces, we
1354  * presently only support one at a time.
1355  *
1356  * The pushed namespace will be removed from the search path at end of
1357  * transaction, whether commit or abort.
1358  */
1359 void
1360 PushSpecialNamespace(Oid namespaceId)
1361 {
1362         Assert(!OidIsValid(mySpecialNamespace));
1363         mySpecialNamespace = namespaceId;
1364         namespaceSearchPathValid = false;
1365 }
1366
1367 /*
1368  * PopSpecialNamespace - remove previously pushed special namespace.
1369  */
1370 void
1371 PopSpecialNamespace(Oid namespaceId)
1372 {
1373         Assert(mySpecialNamespace == namespaceId);
1374         mySpecialNamespace = InvalidOid;
1375         namespaceSearchPathValid = false;
1376 }
1377
1378 /*
1379  * FindConversionByName - find a conversion by possibly qualified name
1380  */
1381 Oid
1382 FindConversionByName(List *name)
1383 {
1384         char       *schemaname;
1385         char       *conversion_name;
1386         Oid                     namespaceId;
1387         Oid                     conoid;
1388         List       *lptr;
1389
1390         /* deconstruct the name list */
1391         DeconstructQualifiedName(name, &schemaname, &conversion_name);
1392
1393         if (schemaname)
1394         {
1395                 /* use exact schema given */
1396                 namespaceId = LookupExplicitNamespace(schemaname);
1397                 return FindConversion(conversion_name, namespaceId);
1398         }
1399         else
1400         {
1401                 /* search for it in search path */
1402                 recomputeNamespacePath();
1403
1404                 foreach(lptr, namespaceSearchPath)
1405                 {
1406                         namespaceId = lfirsto(lptr);
1407                         conoid = FindConversion(conversion_name, namespaceId);
1408                         if (OidIsValid(conoid))
1409                                 return conoid;
1410                 }
1411         }
1412
1413         /* Not found in path */
1414         return InvalidOid;
1415 }
1416
1417 /*
1418  * FindDefaultConversionProc - find default encoding conversion proc
1419  */
1420 Oid
1421 FindDefaultConversionProc(int4 for_encoding, int4 to_encoding)
1422 {
1423         Oid                     proc;
1424         List       *lptr;
1425
1426         recomputeNamespacePath();
1427
1428         foreach(lptr, namespaceSearchPath)
1429         {
1430                 Oid                     namespaceId = lfirsto(lptr);
1431
1432                 proc = FindDefaultConversion(namespaceId, for_encoding, to_encoding);
1433                 if (OidIsValid(proc))
1434                         return proc;
1435         }
1436
1437         /* Not found in path */
1438         return InvalidOid;
1439 }
1440
1441 /*
1442  * recomputeNamespacePath - recompute path derived variables if needed.
1443  */
1444 static void
1445 recomputeNamespacePath(void)
1446 {
1447         AclId           userId = GetUserId();
1448         char       *rawname;
1449         List       *namelist;
1450         List       *oidlist;
1451         List       *newpath;
1452         List       *l;
1453         Oid                     firstNS;
1454         MemoryContext oldcxt;
1455
1456         /*
1457          * Do nothing if path is already valid.
1458          */
1459         if (namespaceSearchPathValid && namespaceUser == userId)
1460                 return;
1461
1462         /* Need a modifiable copy of namespace_search_path string */
1463         rawname = pstrdup(namespace_search_path);
1464
1465         /* Parse string into list of identifiers */
1466         if (!SplitIdentifierString(rawname, ',', &namelist))
1467         {
1468                 /* syntax error in name list */
1469                 /* this should not happen if GUC checked check_search_path */
1470                 elog(ERROR, "recomputeNamespacePath: invalid list syntax");
1471         }
1472
1473         /*
1474          * Convert the list of names to a list of OIDs.  If any names are not
1475          * recognizable or we don't have read access, just leave them out of
1476          * the list.  (We can't raise an error, since the search_path setting
1477          * has already been accepted.)  Don't make duplicate entries, either.
1478          */
1479         oidlist = NIL;
1480         foreach(l, namelist)
1481         {
1482                 char       *curname = (char *) lfirst(l);
1483                 Oid                     namespaceId;
1484
1485                 if (strcmp(curname, "$user") == 0)
1486                 {
1487                         /* $user --- substitute namespace matching user name, if any */
1488                         HeapTuple       tuple;
1489
1490                         tuple = SearchSysCache(SHADOWSYSID,
1491                                                                    ObjectIdGetDatum(userId),
1492                                                                    0, 0, 0);
1493                         if (HeapTupleIsValid(tuple))
1494                         {
1495                                 char       *uname;
1496
1497                                 uname = NameStr(((Form_pg_shadow) GETSTRUCT(tuple))->usename);
1498                                 namespaceId = GetSysCacheOid(NAMESPACENAME,
1499                                                                                          CStringGetDatum(uname),
1500                                                                                          0, 0, 0);
1501                                 ReleaseSysCache(tuple);
1502                                 if (OidIsValid(namespaceId) &&
1503                                         !oidMember(namespaceId, oidlist) &&
1504                                         pg_namespace_aclcheck(namespaceId, userId,
1505                                                                                   ACL_USAGE) == ACLCHECK_OK)
1506                                         oidlist = lappendo(oidlist, namespaceId);
1507                         }
1508                 }
1509                 else
1510                 {
1511                         /* normal namespace reference */
1512                         namespaceId = GetSysCacheOid(NAMESPACENAME,
1513                                                                                  CStringGetDatum(curname),
1514                                                                                  0, 0, 0);
1515                         if (OidIsValid(namespaceId) &&
1516                                 !oidMember(namespaceId, oidlist) &&
1517                                 pg_namespace_aclcheck(namespaceId, userId,
1518                                                                           ACL_USAGE) == ACLCHECK_OK)
1519                                 oidlist = lappendo(oidlist, namespaceId);
1520                 }
1521         }
1522
1523         /*
1524          * Remember the first member of the explicit list.
1525          */
1526         if (oidlist == NIL)
1527                 firstNS = InvalidOid;
1528         else
1529                 firstNS = lfirsto(oidlist);
1530
1531         /*
1532          * Add any implicitly-searched namespaces to the list.  Note these go
1533          * on the front, not the back; also notice that we do not check USAGE
1534          * permissions for these.
1535          */
1536         if (!oidMember(PG_CATALOG_NAMESPACE, oidlist))
1537                 oidlist = lconso(PG_CATALOG_NAMESPACE, oidlist);
1538
1539         if (OidIsValid(myTempNamespace) &&
1540                 !oidMember(myTempNamespace, oidlist))
1541                 oidlist = lconso(myTempNamespace, oidlist);
1542
1543         if (OidIsValid(mySpecialNamespace) &&
1544                 !oidMember(mySpecialNamespace, oidlist))
1545                 oidlist = lconso(mySpecialNamespace, oidlist);
1546
1547         /*
1548          * Now that we've successfully built the new list of namespace OIDs,
1549          * save it in permanent storage.
1550          */
1551         oldcxt = MemoryContextSwitchTo(TopMemoryContext);
1552         newpath = listCopy(oidlist);
1553         MemoryContextSwitchTo(oldcxt);
1554
1555         /* Now safe to assign to state variable. */
1556         freeList(namespaceSearchPath);
1557         namespaceSearchPath = newpath;
1558
1559         /*
1560          * Update info derived from search path.
1561          */
1562         firstExplicitNamespace = firstNS;
1563         if (OidIsValid(mySpecialNamespace))
1564                 defaultCreationNamespace = mySpecialNamespace;
1565         else
1566                 defaultCreationNamespace = firstNS;
1567
1568         /* Mark the path valid. */
1569         namespaceSearchPathValid = true;
1570         namespaceUser = userId;
1571
1572         /* Clean up. */
1573         pfree(rawname);
1574         freeList(namelist);
1575         freeList(oidlist);
1576 }
1577
1578 /*
1579  * InitTempTableNamespace
1580  *              Initialize temp table namespace on first use in a particular backend
1581  */
1582 static void
1583 InitTempTableNamespace(void)
1584 {
1585         char            namespaceName[NAMEDATALEN];
1586         Oid                     namespaceId;
1587
1588         /*
1589          * First, do permission check to see if we are authorized to make temp
1590          * tables.      We use a nonstandard error message here since
1591          * "databasename: permission denied" might be a tad cryptic.
1592          *
1593          * Note we apply the check to the session user, not the currently active
1594          * userid, since we are not going to change our minds about temp table
1595          * availability during the session.
1596          */
1597         if (pg_database_aclcheck(MyDatabaseId, GetSessionUserId(),
1598                                                          ACL_CREATE_TEMP) != ACLCHECK_OK)
1599                 elog(ERROR, "%s: not authorized to create temp tables",
1600                          get_database_name(MyDatabaseId));
1601
1602         snprintf(namespaceName, sizeof(namespaceName), "pg_temp_%d", MyBackendId);
1603
1604         namespaceId = GetSysCacheOid(NAMESPACENAME,
1605                                                                  CStringGetDatum(namespaceName),
1606                                                                  0, 0, 0);
1607         if (!OidIsValid(namespaceId))
1608         {
1609                 /*
1610                  * First use of this temp namespace in this database; create it.
1611                  * The temp namespaces are always owned by the superuser.  We
1612                  * leave their permissions at default --- i.e., no access except
1613                  * to superuser --- to ensure that unprivileged users can't peek
1614                  * at other backends' temp tables.  This works because the places
1615                  * that access the temp namespace for my own backend skip
1616                  * permissions checks on it.
1617                  */
1618                 namespaceId = NamespaceCreate(namespaceName, BOOTSTRAP_USESYSID);
1619                 /* Advance command counter to make namespace visible */
1620                 CommandCounterIncrement();
1621         }
1622         else
1623         {
1624                 /*
1625                  * If the namespace already exists, clean it out (in case the
1626                  * former owner crashed without doing so).
1627                  */
1628                 RemoveTempRelations(namespaceId);
1629         }
1630
1631         /*
1632          * Okay, we've prepared the temp namespace ... but it's not committed
1633          * yet, so all our work could be undone by transaction rollback.  Set
1634          * flag for AtEOXact_Namespace to know what to do.
1635          */
1636         myTempNamespace = namespaceId;
1637
1638         firstTempTransaction = true;
1639
1640         namespaceSearchPathValid = false;       /* need to rebuild list */
1641 }
1642
1643 /*
1644  * End-of-transaction cleanup for namespaces.
1645  */
1646 void
1647 AtEOXact_Namespace(bool isCommit)
1648 {
1649         /*
1650          * If we abort the transaction in which a temp namespace was selected,
1651          * we'll have to do any creation or cleanout work over again.  So,
1652          * just forget the namespace entirely until next time.  On the other
1653          * hand, if we commit then register an exit callback to clean out the
1654          * temp tables at backend shutdown.  (We only want to register the
1655          * callback once per session, so this is a good place to do it.)
1656          */
1657         if (firstTempTransaction)
1658         {
1659                 if (isCommit)
1660                         on_shmem_exit(RemoveTempRelationsCallback, 0);
1661                 else
1662                 {
1663                         myTempNamespace = InvalidOid;
1664                         namespaceSearchPathValid = false;       /* need to rebuild list */
1665                 }
1666                 firstTempTransaction = false;
1667         }
1668
1669         /*
1670          * Clean up if someone failed to do PopSpecialNamespace
1671          */
1672         if (OidIsValid(mySpecialNamespace))
1673         {
1674                 mySpecialNamespace = InvalidOid;
1675                 namespaceSearchPathValid = false;               /* need to rebuild list */
1676         }
1677 }
1678
1679 /*
1680  * Remove all relations in the specified temp namespace.
1681  *
1682  * This is called at backend shutdown (if we made any temp relations).
1683  * It is also called when we begin using a pre-existing temp namespace,
1684  * in order to clean out any relations that might have been created by
1685  * a crashed backend.
1686  */
1687 static void
1688 RemoveTempRelations(Oid tempNamespaceId)
1689 {
1690         ObjectAddress object;
1691
1692         /*
1693          * We want to get rid of everything in the target namespace, but not
1694          * the namespace itself (deleting it only to recreate it later would be
1695          * a waste of cycles).  We do this by finding everything that has a
1696          * dependency on the namespace.
1697          */
1698         object.classId = get_system_catalog_relid(NamespaceRelationName);
1699         object.objectId = tempNamespaceId;
1700         object.objectSubId = 0;
1701
1702         deleteWhatDependsOn(&object, false);
1703 }
1704
1705 /*
1706  * Callback to remove temp relations at backend exit.
1707  */
1708 static void
1709 RemoveTempRelationsCallback(void)
1710 {
1711         if (OidIsValid(myTempNamespace))        /* should always be true */
1712         {
1713                 /* Need to ensure we have a usable transaction. */
1714                 AbortOutOfAnyTransaction();
1715                 StartTransactionCommand();
1716
1717                 RemoveTempRelations(myTempNamespace);
1718
1719                 CommitTransactionCommand();
1720         }
1721 }
1722
1723
1724 /*
1725  * Routines for handling the GUC variable 'search_path'.
1726  */
1727
1728 /* assign_hook: validate new search_path, do extra actions as needed */
1729 const char *
1730 assign_search_path(const char *newval, bool doit, bool interactive)
1731 {
1732         char       *rawname;
1733         List       *namelist;
1734         List       *l;
1735
1736         /* Need a modifiable copy of string */
1737         rawname = pstrdup(newval);
1738
1739         /* Parse string into list of identifiers */
1740         if (!SplitIdentifierString(rawname, ',', &namelist))
1741         {
1742                 /* syntax error in name list */
1743                 pfree(rawname);
1744                 freeList(namelist);
1745                 return NULL;
1746         }
1747
1748         /*
1749          * If we aren't inside a transaction, we cannot do database access so
1750          * cannot verify the individual names.  Must accept the list on faith.
1751          */
1752         if (interactive && IsTransactionState())
1753         {
1754                 /*
1755                  * Verify that all the names are either valid namespace names or
1756                  * "$user".  We do not require $user to correspond to a valid
1757                  * namespace.  We do not check for USAGE rights, either; should
1758                  * we?
1759                  */
1760                 foreach(l, namelist)
1761                 {
1762                         char       *curname = (char *) lfirst(l);
1763
1764                         if (strcmp(curname, "$user") == 0)
1765                                 continue;
1766                         if (!SearchSysCacheExists(NAMESPACENAME,
1767                                                                           CStringGetDatum(curname),
1768                                                                           0, 0, 0))
1769                                 elog(ERROR, "Namespace \"%s\" does not exist", curname);
1770                 }
1771         }
1772
1773         pfree(rawname);
1774         freeList(namelist);
1775
1776         /*
1777          * We mark the path as needing recomputation, but don't do anything
1778          * until it's needed.  This avoids trying to do database access during
1779          * GUC initialization.
1780          */
1781         if (doit)
1782                 namespaceSearchPathValid = false;
1783
1784         return newval;
1785 }
1786
1787 /*
1788  * InitializeSearchPath: initialize module during InitPostgres.
1789  *
1790  * This is called after we are up enough to be able to do catalog lookups.
1791  */
1792 void
1793 InitializeSearchPath(void)
1794 {
1795         if (IsBootstrapProcessingMode())
1796         {
1797                 /*
1798                  * In bootstrap mode, the search path must be 'pg_catalog' so that
1799                  * tables are created in the proper namespace; ignore the GUC
1800                  * setting.
1801                  */
1802                 MemoryContext oldcxt;
1803
1804                 oldcxt = MemoryContextSwitchTo(TopMemoryContext);
1805                 namespaceSearchPath = makeListo1(PG_CATALOG_NAMESPACE);
1806                 MemoryContextSwitchTo(oldcxt);
1807                 defaultCreationNamespace = PG_CATALOG_NAMESPACE;
1808                 firstExplicitNamespace = PG_CATALOG_NAMESPACE;
1809                 namespaceSearchPathValid = true;
1810                 namespaceUser = GetUserId();
1811         }
1812         else
1813         {
1814                 /*
1815                  * In normal mode, arrange for a callback on any syscache
1816                  * invalidation of pg_namespace rows.
1817                  */
1818                 CacheRegisterSyscacheCallback(NAMESPACEOID,
1819                                                                           NamespaceCallback,
1820                                                                           (Datum) 0);
1821                 /* Force search path to be recomputed on next use */
1822                 namespaceSearchPathValid = false;
1823         }
1824 }
1825
1826 /*
1827  * NamespaceCallback
1828  *              Syscache inval callback function
1829  */
1830 static void
1831 NamespaceCallback(Datum arg, Oid relid)
1832 {
1833         /* Force search path to be recomputed on next use */
1834         namespaceSearchPathValid = false;
1835 }
1836
1837 /*
1838  * Fetch the active search path, expressed as a List of OIDs.
1839  *
1840  * The returned list includes the implicitly-prepended namespaces only if
1841  * includeImplicit is true.
1842  *
1843  * NB: caller must treat the list as read-only!
1844  */
1845 List *
1846 fetch_search_path(bool includeImplicit)
1847 {
1848         List       *result;
1849
1850         recomputeNamespacePath();
1851
1852         result = namespaceSearchPath;
1853         if (!includeImplicit)
1854         {
1855                 while (result && lfirsto(result) != firstExplicitNamespace)
1856                         result = lnext(result);
1857         }
1858
1859         return result;
1860 }
1861
1862 /*
1863  * Export the FooIsVisible functions as SQL-callable functions.
1864  */
1865
1866 Datum
1867 pg_table_is_visible(PG_FUNCTION_ARGS)
1868 {
1869         Oid                     oid = PG_GETARG_OID(0);
1870
1871         PG_RETURN_BOOL(RelationIsVisible(oid));
1872 }
1873
1874 Datum
1875 pg_type_is_visible(PG_FUNCTION_ARGS)
1876 {
1877         Oid                     oid = PG_GETARG_OID(0);
1878
1879         PG_RETURN_BOOL(TypeIsVisible(oid));
1880 }
1881
1882 Datum
1883 pg_function_is_visible(PG_FUNCTION_ARGS)
1884 {
1885         Oid                     oid = PG_GETARG_OID(0);
1886
1887         PG_RETURN_BOOL(FunctionIsVisible(oid));
1888 }
1889
1890 Datum
1891 pg_operator_is_visible(PG_FUNCTION_ARGS)
1892 {
1893         Oid                     oid = PG_GETARG_OID(0);
1894
1895         PG_RETURN_BOOL(OperatorIsVisible(oid));
1896 }
1897
1898 Datum
1899 pg_opclass_is_visible(PG_FUNCTION_ARGS)
1900 {
1901         Oid                     oid = PG_GETARG_OID(0);
1902
1903         PG_RETURN_BOOL(OpclassIsVisible(oid));
1904 }
1905
1906 Datum
1907 pg_conversion_is_visible(PG_FUNCTION_ARGS)
1908 {
1909         Oid                     oid = PG_GETARG_OID(0);
1910
1911         PG_RETURN_BOOL(ConversionIsVisible(oid));
1912 }