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