PostgreSQL Source Code  git master
namespace.c
Go to the documentation of this file.
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-2020, PostgreSQL Global Development Group
13  * Portions Copyright (c) 1994, Regents of the University of California
14  *
15  * IDENTIFICATION
16  * src/backend/catalog/namespace.c
17  *
18  *-------------------------------------------------------------------------
19  */
20 #include "postgres.h"
21 
22 #include "access/htup_details.h"
23 #include "access/parallel.h"
24 #include "access/xact.h"
25 #include "access/xlog.h"
26 #include "catalog/dependency.h"
27 #include "catalog/objectaccess.h"
28 #include "catalog/pg_authid.h"
29 #include "catalog/pg_collation.h"
30 #include "catalog/pg_conversion.h"
31 #include "catalog/pg_namespace.h"
32 #include "catalog/pg_opclass.h"
33 #include "catalog/pg_operator.h"
34 #include "catalog/pg_opfamily.h"
35 #include "catalog/pg_proc.h"
37 #include "catalog/pg_ts_config.h"
38 #include "catalog/pg_ts_dict.h"
39 #include "catalog/pg_ts_parser.h"
40 #include "catalog/pg_ts_template.h"
41 #include "catalog/pg_type.h"
42 #include "commands/dbcommands.h"
43 #include "funcapi.h"
44 #include "mb/pg_wchar.h"
45 #include "miscadmin.h"
46 #include "nodes/makefuncs.h"
47 #include "parser/parse_func.h"
48 #include "storage/ipc.h"
49 #include "storage/lmgr.h"
50 #include "storage/sinvaladt.h"
51 #include "utils/acl.h"
52 #include "utils/builtins.h"
53 #include "utils/catcache.h"
54 #include "utils/guc.h"
55 #include "utils/inval.h"
56 #include "utils/lsyscache.h"
57 #include "utils/memutils.h"
58 #include "utils/syscache.h"
59 #include "utils/varlena.h"
60 
61 
62 /*
63  * The namespace search path is a possibly-empty list of namespace OIDs.
64  * In addition to the explicit list, implicitly-searched namespaces
65  * may be included:
66  *
67  * 1. If a TEMP table namespace has been initialized in this session, it
68  * is implicitly searched first. (The only time this doesn't happen is
69  * when we are obeying an override search path spec that says not to use the
70  * temp namespace, or the temp namespace is included in the explicit list.)
71  *
72  * 2. The system catalog namespace is always searched. If the system
73  * namespace is present in the explicit path then it will be searched in
74  * the specified order; otherwise it will be searched after TEMP tables and
75  * *before* the explicit list. (It might seem that the system namespace
76  * should be implicitly last, but this behavior appears to be required by
77  * SQL99. Also, this provides a way to search the system namespace first
78  * without thereby making it the default creation target namespace.)
79  *
80  * For security reasons, searches using the search path will ignore the temp
81  * namespace when searching for any object type other than relations and
82  * types. (We must allow types since temp tables have rowtypes.)
83  *
84  * The default creation target namespace is always the first element of the
85  * explicit list. If the explicit list is empty, there is no default target.
86  *
87  * The textual specification of search_path can include "$user" to refer to
88  * the namespace named the same as the current user, if any. (This is just
89  * ignored if there is no such namespace.) Also, it can include "pg_temp"
90  * to refer to the current backend's temp namespace. This is usually also
91  * ignorable if the temp namespace hasn't been set up, but there's a special
92  * case: if "pg_temp" appears first then it should be the default creation
93  * target. We kluge this case a little bit so that the temp namespace isn't
94  * set up until the first attempt to create something in it. (The reason for
95  * klugery is that we can't create the temp namespace outside a transaction,
96  * but initial GUC processing of search_path happens outside a transaction.)
97  * activeTempCreationPending is true if "pg_temp" appears first in the string
98  * but is not reflected in activeCreationNamespace because the namespace isn't
99  * set up yet.
100  *
101  * In bootstrap mode, the search path is set equal to "pg_catalog", so that
102  * the system namespace is the only one searched or inserted into.
103  * initdb is also careful to set search_path to "pg_catalog" for its
104  * post-bootstrap standalone backend runs. Otherwise the default search
105  * path is determined by GUC. The factory default path contains the PUBLIC
106  * namespace (if it exists), preceded by the user's personal namespace
107  * (if one exists).
108  *
109  * We support a stack of "override" search path settings for use within
110  * specific sections of backend code. namespace_search_path is ignored
111  * whenever the override stack is nonempty. activeSearchPath is always
112  * the actually active path; it points either to the search list of the
113  * topmost stack entry, or to baseSearchPath which is the list derived
114  * from namespace_search_path.
115  *
116  * If baseSearchPathValid is false, then baseSearchPath (and other
117  * derived variables) need to be recomputed from namespace_search_path.
118  * We mark it invalid upon an assignment to namespace_search_path or receipt
119  * of a syscache invalidation event for pg_namespace. The recomputation
120  * is done during the next non-overridden lookup attempt. Note that an
121  * override spec is never subject to recomputation.
122  *
123  * Any namespaces mentioned in namespace_search_path that are not readable
124  * by the current user ID are simply left out of baseSearchPath; so
125  * we have to be willing to recompute the path when current userid changes.
126  * namespaceUser is the userid the path has been computed for.
127  *
128  * Note: all data pointed to by these List variables is in TopMemoryContext.
129  *
130  * activePathGeneration is incremented whenever the effective values of
131  * activeSearchPath/activeCreationNamespace/activeTempCreationPending change.
132  * This can be used to quickly detect whether any change has happened since
133  * a previous examination of the search path state.
134  */
135 
136 /* These variables define the actually active state: */
137 
139 
140 /* default place to create stuff; if InvalidOid, no default */
142 
143 /* if true, activeCreationNamespace is wrong, it should be temp namespace */
144 static bool activeTempCreationPending = false;
145 
146 /* current generation counter; make sure this is never zero */
147 static uint64 activePathGeneration = 1;
148 
149 /* These variables are the values last derived from namespace_search_path: */
150 
152 
154 
155 static bool baseTempCreationPending = false;
156 
158 
159 /* The above four values are valid only if baseSearchPathValid */
160 static bool baseSearchPathValid = true;
161 
162 /* Override requests are remembered in a stack of OverrideStackEntry structs */
163 
164 typedef struct
165 {
166  List *searchPath; /* the desired search path */
167  Oid creationNamespace; /* the desired creation namespace */
168  int nestLevel; /* subtransaction nesting level */
170 
172 
173 /*
174  * myTempNamespace is InvalidOid until and unless a TEMP namespace is set up
175  * in a particular backend session (this happens when a CREATE TEMP TABLE
176  * command is first executed). Thereafter it's the OID of the temp namespace.
177  *
178  * myTempToastNamespace is the OID of the namespace for my temp tables' toast
179  * tables. It is set when myTempNamespace is, and is InvalidOid before that.
180  *
181  * myTempNamespaceSubID shows whether we've created the TEMP namespace in the
182  * current subtransaction. The flag propagates up the subtransaction tree,
183  * so the main transaction will correctly recognize the flag if all
184  * intermediate subtransactions commit. When it is InvalidSubTransactionId,
185  * we either haven't made the TEMP namespace yet, or have successfully
186  * committed its creation, depending on whether myTempNamespace is valid.
187  */
189 
191 
193 
194 /*
195  * This is the user's textual search path specification --- it's the value
196  * of the GUC variable 'search_path'.
197  */
199 
200 
201 /* Local functions */
202 static void recomputeNamespacePath(void);
203 static void AccessTempTableNamespace(bool force);
204 static void InitTempTableNamespace(void);
205 static void RemoveTempRelations(Oid tempNamespaceId);
206 static void RemoveTempRelationsCallback(int code, Datum arg);
207 static void NamespaceCallback(Datum arg, int cacheid, uint32 hashvalue);
208 static bool MatchNamedCall(HeapTuple proctup, int nargs, List *argnames,
209  int **argnumbers);
210 
211 
212 /*
213  * RangeVarGetRelidExtended
214  * Given a RangeVar describing an existing relation,
215  * select the proper namespace and look up the relation OID.
216  *
217  * If the schema or relation is not found, return InvalidOid if flags contains
218  * RVR_MISSING_OK, otherwise raise an error.
219  *
220  * If flags contains RVR_NOWAIT, throw an error if we'd have to wait for a
221  * lock.
222  *
223  * If flags contains RVR_SKIP_LOCKED, return InvalidOid if we'd have to wait
224  * for a lock.
225  *
226  * flags cannot contain both RVR_NOWAIT and RVR_SKIP_LOCKED.
227  *
228  * Note that if RVR_MISSING_OK and RVR_SKIP_LOCKED are both specified, a
229  * return value of InvalidOid could either mean the relation is missing or it
230  * could not be locked.
231  *
232  * Callback allows caller to check permissions or acquire additional locks
233  * prior to grabbing the relation lock.
234  */
235 Oid
236 RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode,
237  uint32 flags,
238  RangeVarGetRelidCallback callback, void *callback_arg)
239 {
240  uint64 inval_count;
241  Oid relId;
242  Oid oldRelId = InvalidOid;
243  bool retry = false;
244  bool missing_ok = (flags & RVR_MISSING_OK) != 0;
245 
246  /* verify that flags do no conflict */
247  Assert(!((flags & RVR_NOWAIT) && (flags & RVR_SKIP_LOCKED)));
248 
249  /*
250  * We check the catalog name and then ignore it.
251  */
252  if (relation->catalogname)
253  {
254  if (strcmp(relation->catalogname, get_database_name(MyDatabaseId)) != 0)
255  ereport(ERROR,
256  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
257  errmsg("cross-database references are not implemented: \"%s.%s.%s\"",
258  relation->catalogname, relation->schemaname,
259  relation->relname)));
260  }
261 
262  /*
263  * DDL operations can change the results of a name lookup. Since all such
264  * operations will generate invalidation messages, we keep track of
265  * whether any such messages show up while we're performing the operation,
266  * and retry until either (1) no more invalidation messages show up or (2)
267  * the answer doesn't change.
268  *
269  * But if lockmode = NoLock, then we assume that either the caller is OK
270  * with the answer changing under them, or that they already hold some
271  * appropriate lock, and therefore return the first answer we get without
272  * checking for invalidation messages. Also, if the requested lock is
273  * already held, LockRelationOid will not AcceptInvalidationMessages, so
274  * we may fail to notice a change. We could protect against that case by
275  * calling AcceptInvalidationMessages() before beginning this loop, but
276  * that would add a significant amount overhead, so for now we don't.
277  */
278  for (;;)
279  {
280  /*
281  * Remember this value, so that, after looking up the relation name
282  * and locking its OID, we can check whether any invalidation messages
283  * have been processed that might require a do-over.
284  */
285  inval_count = SharedInvalidMessageCounter;
286 
287  /*
288  * Some non-default relpersistence value may have been specified. The
289  * parser never generates such a RangeVar in simple DML, but it can
290  * happen in contexts such as "CREATE TEMP TABLE foo (f1 int PRIMARY
291  * KEY)". Such a command will generate an added CREATE INDEX
292  * operation, which must be careful to find the temp table, even when
293  * pg_temp is not first in the search path.
294  */
295  if (relation->relpersistence == RELPERSISTENCE_TEMP)
296  {
298  relId = InvalidOid; /* this probably can't happen? */
299  else
300  {
301  if (relation->schemaname)
302  {
303  Oid namespaceId;
304 
305  namespaceId = LookupExplicitNamespace(relation->schemaname, missing_ok);
306 
307  /*
308  * For missing_ok, allow a non-existent schema name to
309  * return InvalidOid.
310  */
311  if (namespaceId != myTempNamespace)
312  ereport(ERROR,
313  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
314  errmsg("temporary tables cannot specify a schema name")));
315  }
316 
317  relId = get_relname_relid(relation->relname, myTempNamespace);
318  }
319  }
320  else if (relation->schemaname)
321  {
322  Oid namespaceId;
323 
324  /* use exact schema given */
325  namespaceId = LookupExplicitNamespace(relation->schemaname, missing_ok);
326  if (missing_ok && !OidIsValid(namespaceId))
327  relId = InvalidOid;
328  else
329  relId = get_relname_relid(relation->relname, namespaceId);
330  }
331  else
332  {
333  /* search the namespace path */
334  relId = RelnameGetRelid(relation->relname);
335  }
336 
337  /*
338  * Invoke caller-supplied callback, if any.
339  *
340  * This callback is a good place to check permissions: we haven't
341  * taken the table lock yet (and it's really best to check permissions
342  * before locking anything!), but we've gotten far enough to know what
343  * OID we think we should lock. Of course, concurrent DDL might
344  * change things while we're waiting for the lock, but in that case
345  * the callback will be invoked again for the new OID.
346  */
347  if (callback)
348  callback(relation, relId, oldRelId, callback_arg);
349 
350  /*
351  * If no lock requested, we assume the caller knows what they're
352  * doing. They should have already acquired a heavyweight lock on
353  * this relation earlier in the processing of this same statement, so
354  * it wouldn't be appropriate to AcceptInvalidationMessages() here, as
355  * that might pull the rug out from under them.
356  */
357  if (lockmode == NoLock)
358  break;
359 
360  /*
361  * If, upon retry, we get back the same OID we did last time, then the
362  * invalidation messages we processed did not change the final answer.
363  * So we're done.
364  *
365  * If we got a different OID, we've locked the relation that used to
366  * have this name rather than the one that does now. So release the
367  * lock.
368  */
369  if (retry)
370  {
371  if (relId == oldRelId)
372  break;
373  if (OidIsValid(oldRelId))
374  UnlockRelationOid(oldRelId, lockmode);
375  }
376 
377  /*
378  * Lock relation. This will also accept any pending invalidation
379  * messages. If we got back InvalidOid, indicating not found, then
380  * there's nothing to lock, but we accept invalidation messages
381  * anyway, to flush any negative catcache entries that may be
382  * lingering.
383  */
384  if (!OidIsValid(relId))
386  else if (!(flags & (RVR_NOWAIT | RVR_SKIP_LOCKED)))
387  LockRelationOid(relId, lockmode);
388  else if (!ConditionalLockRelationOid(relId, lockmode))
389  {
390  int elevel = (flags & RVR_SKIP_LOCKED) ? DEBUG1 : ERROR;
391 
392  if (relation->schemaname)
393  ereport(elevel,
394  (errcode(ERRCODE_LOCK_NOT_AVAILABLE),
395  errmsg("could not obtain lock on relation \"%s.%s\"",
396  relation->schemaname, relation->relname)));
397  else
398  ereport(elevel,
399  (errcode(ERRCODE_LOCK_NOT_AVAILABLE),
400  errmsg("could not obtain lock on relation \"%s\"",
401  relation->relname)));
402 
403  return InvalidOid;
404  }
405 
406  /*
407  * If no invalidation message were processed, we're done!
408  */
409  if (inval_count == SharedInvalidMessageCounter)
410  break;
411 
412  /*
413  * Something may have changed. Let's repeat the name lookup, to make
414  * sure this name still references the same relation it did
415  * previously.
416  */
417  retry = true;
418  oldRelId = relId;
419  }
420 
421  if (!OidIsValid(relId))
422  {
423  int elevel = missing_ok ? DEBUG1 : ERROR;
424 
425  if (relation->schemaname)
426  ereport(elevel,
428  errmsg("relation \"%s.%s\" does not exist",
429  relation->schemaname, relation->relname)));
430  else
431  ereport(elevel,
433  errmsg("relation \"%s\" does not exist",
434  relation->relname)));
435  }
436  return relId;
437 }
438 
439 /*
440  * RangeVarGetCreationNamespace
441  * Given a RangeVar describing a to-be-created relation,
442  * choose which namespace to create it in.
443  *
444  * Note: calling this may result in a CommandCounterIncrement operation.
445  * That will happen on the first request for a temp table in any particular
446  * backend run; we will need to either create or clean out the temp schema.
447  */
448 Oid
450 {
451  Oid namespaceId;
452 
453  /*
454  * We check the catalog name and then ignore it.
455  */
456  if (newRelation->catalogname)
457  {
458  if (strcmp(newRelation->catalogname, get_database_name(MyDatabaseId)) != 0)
459  ereport(ERROR,
460  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
461  errmsg("cross-database references are not implemented: \"%s.%s.%s\"",
462  newRelation->catalogname, newRelation->schemaname,
463  newRelation->relname)));
464  }
465 
466  if (newRelation->schemaname)
467  {
468  /* check for pg_temp alias */
469  if (strcmp(newRelation->schemaname, "pg_temp") == 0)
470  {
471  /* Initialize temp namespace */
473  return myTempNamespace;
474  }
475  /* use exact schema given */
476  namespaceId = get_namespace_oid(newRelation->schemaname, false);
477  /* we do not check for USAGE rights here! */
478  }
479  else if (newRelation->relpersistence == RELPERSISTENCE_TEMP)
480  {
481  /* Initialize temp namespace */
483  return myTempNamespace;
484  }
485  else
486  {
487  /* use the default creation namespace */
490  {
491  /* Need to initialize temp namespace */
493  return myTempNamespace;
494  }
495  namespaceId = activeCreationNamespace;
496  if (!OidIsValid(namespaceId))
497  ereport(ERROR,
498  (errcode(ERRCODE_UNDEFINED_SCHEMA),
499  errmsg("no schema has been selected to create in")));
500  }
501 
502  /* Note: callers will check for CREATE rights when appropriate */
503 
504  return namespaceId;
505 }
506 
507 /*
508  * RangeVarGetAndCheckCreationNamespace
509  *
510  * This function returns the OID of the namespace in which a new relation
511  * with a given name should be created. If the user does not have CREATE
512  * permission on the target namespace, this function will instead signal
513  * an ERROR.
514  *
515  * If non-NULL, *existing_relation_id is set to the OID of any existing relation
516  * with the same name which already exists in that namespace, or to InvalidOid
517  * if no such relation exists.
518  *
519  * If lockmode != NoLock, the specified lock mode is acquired on the existing
520  * relation, if any, provided that the current user owns the target relation.
521  * However, if lockmode != NoLock and the user does not own the target
522  * relation, we throw an ERROR, as we must not try to lock relations the
523  * user does not have permissions on.
524  *
525  * As a side effect, this function acquires AccessShareLock on the target
526  * namespace. Without this, the namespace could be dropped before our
527  * transaction commits, leaving behind relations with relnamespace pointing
528  * to a no-longer-existent namespace.
529  *
530  * As a further side-effect, if the selected namespace is a temporary namespace,
531  * we mark the RangeVar as RELPERSISTENCE_TEMP.
532  */
533 Oid
535  LOCKMODE lockmode,
536  Oid *existing_relation_id)
537 {
538  uint64 inval_count;
539  Oid relid;
540  Oid oldrelid = InvalidOid;
541  Oid nspid;
542  Oid oldnspid = InvalidOid;
543  bool retry = false;
544 
545  /*
546  * We check the catalog name and then ignore it.
547  */
548  if (relation->catalogname)
549  {
550  if (strcmp(relation->catalogname, get_database_name(MyDatabaseId)) != 0)
551  ereport(ERROR,
552  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
553  errmsg("cross-database references are not implemented: \"%s.%s.%s\"",
554  relation->catalogname, relation->schemaname,
555  relation->relname)));
556  }
557 
558  /*
559  * As in RangeVarGetRelidExtended(), we guard against concurrent DDL
560  * operations by tracking whether any invalidation messages are processed
561  * while we're doing the name lookups and acquiring locks. See comments
562  * in that function for a more detailed explanation of this logic.
563  */
564  for (;;)
565  {
566  AclResult aclresult;
567 
568  inval_count = SharedInvalidMessageCounter;
569 
570  /* Look up creation namespace and check for existing relation. */
571  nspid = RangeVarGetCreationNamespace(relation);
572  Assert(OidIsValid(nspid));
573  if (existing_relation_id != NULL)
574  relid = get_relname_relid(relation->relname, nspid);
575  else
576  relid = InvalidOid;
577 
578  /*
579  * In bootstrap processing mode, we don't bother with permissions or
580  * locking. Permissions might not be working yet, and locking is
581  * unnecessary.
582  */
584  break;
585 
586  /* Check namespace permissions. */
587  aclresult = pg_namespace_aclcheck(nspid, GetUserId(), ACL_CREATE);
588  if (aclresult != ACLCHECK_OK)
589  aclcheck_error(aclresult, OBJECT_SCHEMA,
590  get_namespace_name(nspid));
591 
592  if (retry)
593  {
594  /* If nothing changed, we're done. */
595  if (relid == oldrelid && nspid == oldnspid)
596  break;
597  /* If creation namespace has changed, give up old lock. */
598  if (nspid != oldnspid)
599  UnlockDatabaseObject(NamespaceRelationId, oldnspid, 0,
601  /* If name points to something different, give up old lock. */
602  if (relid != oldrelid && OidIsValid(oldrelid) && lockmode != NoLock)
603  UnlockRelationOid(oldrelid, lockmode);
604  }
605 
606  /* Lock namespace. */
607  if (nspid != oldnspid)
608  LockDatabaseObject(NamespaceRelationId, nspid, 0, AccessShareLock);
609 
610  /* Lock relation, if required if and we have permission. */
611  if (lockmode != NoLock && OidIsValid(relid))
612  {
613  if (!pg_class_ownercheck(relid, GetUserId()))
615  relation->relname);
616  if (relid != oldrelid)
617  LockRelationOid(relid, lockmode);
618  }
619 
620  /* If no invalidation message were processed, we're done! */
621  if (inval_count == SharedInvalidMessageCounter)
622  break;
623 
624  /* Something may have changed, so recheck our work. */
625  retry = true;
626  oldrelid = relid;
627  oldnspid = nspid;
628  }
629 
630  RangeVarAdjustRelationPersistence(relation, nspid);
631  if (existing_relation_id != NULL)
632  *existing_relation_id = relid;
633  return nspid;
634 }
635 
636 /*
637  * Adjust the relpersistence for an about-to-be-created relation based on the
638  * creation namespace, and throw an error for invalid combinations.
639  */
640 void
642 {
643  switch (newRelation->relpersistence)
644  {
645  case RELPERSISTENCE_TEMP:
646  if (!isTempOrTempToastNamespace(nspid))
647  {
648  if (isAnyTempNamespace(nspid))
649  ereport(ERROR,
650  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
651  errmsg("cannot create relations in temporary schemas of other sessions")));
652  else
653  ereport(ERROR,
654  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
655  errmsg("cannot create temporary relation in non-temporary schema")));
656  }
657  break;
658  case RELPERSISTENCE_PERMANENT:
659  if (isTempOrTempToastNamespace(nspid))
660  newRelation->relpersistence = RELPERSISTENCE_TEMP;
661  else if (isAnyTempNamespace(nspid))
662  ereport(ERROR,
663  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
664  errmsg("cannot create relations in temporary schemas of other sessions")));
665  break;
666  default:
667  if (isAnyTempNamespace(nspid))
668  ereport(ERROR,
669  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
670  errmsg("only temporary relations may be created in temporary schemas")));
671  }
672 }
673 
674 /*
675  * RelnameGetRelid
676  * Try to resolve an unqualified relation name.
677  * Returns OID if relation found in search path, else InvalidOid.
678  */
679 Oid
681 {
682  Oid relid;
683  ListCell *l;
684 
686 
687  foreach(l, activeSearchPath)
688  {
689  Oid namespaceId = lfirst_oid(l);
690 
691  relid = get_relname_relid(relname, namespaceId);
692  if (OidIsValid(relid))
693  return relid;
694  }
695 
696  /* Not found in path */
697  return InvalidOid;
698 }
699 
700 
701 /*
702  * RelationIsVisible
703  * Determine whether a relation (identified by OID) is visible in the
704  * current search path. Visible means "would be found by searching
705  * for the unqualified relation name".
706  */
707 bool
709 {
710  HeapTuple reltup;
711  Form_pg_class relform;
712  Oid relnamespace;
713  bool visible;
714 
715  reltup = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
716  if (!HeapTupleIsValid(reltup))
717  elog(ERROR, "cache lookup failed for relation %u", relid);
718  relform = (Form_pg_class) GETSTRUCT(reltup);
719 
721 
722  /*
723  * Quick check: if it ain't in the path at all, it ain't visible. Items in
724  * the system namespace are surely in the path and so we needn't even do
725  * list_member_oid() for them.
726  */
727  relnamespace = relform->relnamespace;
728  if (relnamespace != PG_CATALOG_NAMESPACE &&
729  !list_member_oid(activeSearchPath, relnamespace))
730  visible = false;
731  else
732  {
733  /*
734  * If it is in the path, it might still not be visible; it could be
735  * hidden by another relation of the same name earlier in the path. So
736  * we must do a slow check for conflicting relations.
737  */
738  char *relname = NameStr(relform->relname);
739  ListCell *l;
740 
741  visible = false;
742  foreach(l, activeSearchPath)
743  {
744  Oid namespaceId = lfirst_oid(l);
745 
746  if (namespaceId == relnamespace)
747  {
748  /* Found it first in path */
749  visible = true;
750  break;
751  }
752  if (OidIsValid(get_relname_relid(relname, namespaceId)))
753  {
754  /* Found something else first in path */
755  break;
756  }
757  }
758  }
759 
760  ReleaseSysCache(reltup);
761 
762  return visible;
763 }
764 
765 
766 /*
767  * TypenameGetTypid
768  * Wrapper for binary compatibility.
769  */
770 Oid
772 {
773  return TypenameGetTypidExtended(typname, true);
774 }
775 
776 /*
777  * TypenameGetTypidExtended
778  * Try to resolve an unqualified datatype name.
779  * Returns OID if type found in search path, else InvalidOid.
780  *
781  * This is essentially the same as RelnameGetRelid.
782  */
783 Oid
784 TypenameGetTypidExtended(const char *typname, bool temp_ok)
785 {
786  Oid typid;
787  ListCell *l;
788 
790 
791  foreach(l, activeSearchPath)
792  {
793  Oid namespaceId = lfirst_oid(l);
794 
795  if (!temp_ok && namespaceId == myTempNamespace)
796  continue; /* do not look in temp namespace */
797 
798  typid = GetSysCacheOid2(TYPENAMENSP, Anum_pg_type_oid,
799  PointerGetDatum(typname),
800  ObjectIdGetDatum(namespaceId));
801  if (OidIsValid(typid))
802  return typid;
803  }
804 
805  /* Not found in path */
806  return InvalidOid;
807 }
808 
809 /*
810  * TypeIsVisible
811  * Determine whether a type (identified by OID) is visible in the
812  * current search path. Visible means "would be found by searching
813  * for the unqualified type name".
814  */
815 bool
817 {
818  HeapTuple typtup;
819  Form_pg_type typform;
820  Oid typnamespace;
821  bool visible;
822 
823  typtup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
824  if (!HeapTupleIsValid(typtup))
825  elog(ERROR, "cache lookup failed for type %u", typid);
826  typform = (Form_pg_type) GETSTRUCT(typtup);
827 
829 
830  /*
831  * Quick check: if it ain't in the path at all, it ain't visible. Items in
832  * the system namespace are surely in the path and so we needn't even do
833  * list_member_oid() for them.
834  */
835  typnamespace = typform->typnamespace;
836  if (typnamespace != PG_CATALOG_NAMESPACE &&
837  !list_member_oid(activeSearchPath, typnamespace))
838  visible = false;
839  else
840  {
841  /*
842  * If it is in the path, it might still not be visible; it could be
843  * hidden by another type of the same name earlier in the path. So we
844  * must do a slow check for conflicting types.
845  */
846  char *typname = NameStr(typform->typname);
847  ListCell *l;
848 
849  visible = false;
850  foreach(l, activeSearchPath)
851  {
852  Oid namespaceId = lfirst_oid(l);
853 
854  if (namespaceId == typnamespace)
855  {
856  /* Found it first in path */
857  visible = true;
858  break;
859  }
861  PointerGetDatum(typname),
862  ObjectIdGetDatum(namespaceId)))
863  {
864  /* Found something else first in path */
865  break;
866  }
867  }
868  }
869 
870  ReleaseSysCache(typtup);
871 
872  return visible;
873 }
874 
875 
876 /*
877  * FuncnameGetCandidates
878  * Given a possibly-qualified function name and argument count,
879  * retrieve a list of the possible matches.
880  *
881  * If nargs is -1, we return all functions matching the given name,
882  * regardless of argument count. (argnames must be NIL, and expand_variadic
883  * and expand_defaults must be false, in this case.)
884  *
885  * If argnames isn't NIL, we are considering a named- or mixed-notation call,
886  * and only functions having all the listed argument names will be returned.
887  * (We assume that length(argnames) <= nargs and all the passed-in names are
888  * distinct.) The returned structs will include an argnumbers array showing
889  * the actual argument index for each logical argument position.
890  *
891  * If expand_variadic is true, then variadic functions having the same number
892  * or fewer arguments will be retrieved, with the variadic argument and any
893  * additional argument positions filled with the variadic element type.
894  * nvargs in the returned struct is set to the number of such arguments.
895  * If expand_variadic is false, variadic arguments are not treated specially,
896  * and the returned nvargs will always be zero.
897  *
898  * If expand_defaults is true, functions that could match after insertion of
899  * default argument values will also be retrieved. In this case the returned
900  * structs could have nargs > passed-in nargs, and ndargs is set to the number
901  * of additional args (which can be retrieved from the function's
902  * proargdefaults entry).
903  *
904  * It is not possible for nvargs and ndargs to both be nonzero in the same
905  * list entry, since default insertion allows matches to functions with more
906  * than nargs arguments while the variadic transformation requires the same
907  * number or less.
908  *
909  * When argnames isn't NIL, the returned args[] type arrays are not ordered
910  * according to the functions' declarations, but rather according to the call:
911  * first any positional arguments, then the named arguments, then defaulted
912  * arguments (if needed and allowed by expand_defaults). The argnumbers[]
913  * array can be used to map this back to the catalog information.
914  * argnumbers[k] is set to the proargtypes index of the k'th call argument.
915  *
916  * We search a single namespace if the function name is qualified, else
917  * all namespaces in the search path. In the multiple-namespace case,
918  * we arrange for entries in earlier namespaces to mask identical entries in
919  * later namespaces.
920  *
921  * When expanding variadics, we arrange for non-variadic functions to mask
922  * variadic ones if the expanded argument list is the same. It is still
923  * possible for there to be conflicts between different variadic functions,
924  * however.
925  *
926  * It is guaranteed that the return list will never contain multiple entries
927  * with identical argument lists. When expand_defaults is true, the entries
928  * could have more than nargs positions, but we still guarantee that they are
929  * distinct in the first nargs positions. However, if argnames isn't NIL or
930  * either expand_variadic or expand_defaults is true, there might be multiple
931  * candidate functions that expand to identical argument lists. Rather than
932  * throw error here, we report such situations by returning a single entry
933  * with oid = 0 that represents a set of such conflicting candidates.
934  * The caller might end up discarding such an entry anyway, but if it selects
935  * such an entry it should react as though the call were ambiguous.
936  *
937  * If missing_ok is true, an empty list (NULL) is returned if the name was
938  * schema- qualified with a schema that does not exist. Likewise if no
939  * candidate is found for other reasons.
940  */
942 FuncnameGetCandidates(List *names, int nargs, List *argnames,
943  bool expand_variadic, bool expand_defaults,
944  bool missing_ok)
945 {
946  FuncCandidateList resultList = NULL;
947  bool any_special = false;
948  char *schemaname;
949  char *funcname;
950  Oid namespaceId;
951  CatCList *catlist;
952  int i;
953 
954  /* check for caller error */
955  Assert(nargs >= 0 || !(expand_variadic | expand_defaults));
956 
957  /* deconstruct the name list */
958  DeconstructQualifiedName(names, &schemaname, &funcname);
959 
960  if (schemaname)
961  {
962  /* use exact schema given */
963  namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
964  if (!OidIsValid(namespaceId))
965  return NULL;
966  }
967  else
968  {
969  /* flag to indicate we need namespace search */
970  namespaceId = InvalidOid;
972  }
973 
974  /* Search syscache by name only */
976 
977  for (i = 0; i < catlist->n_members; i++)
978  {
979  HeapTuple proctup = &catlist->members[i]->tuple;
980  Form_pg_proc procform = (Form_pg_proc) GETSTRUCT(proctup);
981  int pronargs = procform->pronargs;
982  int effective_nargs;
983  int pathpos = 0;
984  bool variadic;
985  bool use_defaults;
986  Oid va_elem_type;
987  int *argnumbers = NULL;
988  FuncCandidateList newResult;
989 
990  if (OidIsValid(namespaceId))
991  {
992  /* Consider only procs in specified namespace */
993  if (procform->pronamespace != namespaceId)
994  continue;
995  }
996  else
997  {
998  /*
999  * Consider only procs that are in the search path and are not in
1000  * the temp namespace.
1001  */
1002  ListCell *nsp;
1003 
1004  foreach(nsp, activeSearchPath)
1005  {
1006  if (procform->pronamespace == lfirst_oid(nsp) &&
1007  procform->pronamespace != myTempNamespace)
1008  break;
1009  pathpos++;
1010  }
1011  if (nsp == NULL)
1012  continue; /* proc is not in search path */
1013  }
1014 
1015  if (argnames != NIL)
1016  {
1017  /*
1018  * Call uses named or mixed notation
1019  *
1020  * Named or mixed notation can match a variadic function only if
1021  * expand_variadic is off; otherwise there is no way to match the
1022  * presumed-nameless parameters expanded from the variadic array.
1023  */
1024  if (OidIsValid(procform->provariadic) && expand_variadic)
1025  continue;
1026  va_elem_type = InvalidOid;
1027  variadic = false;
1028 
1029  /*
1030  * Check argument count.
1031  */
1032  Assert(nargs >= 0); /* -1 not supported with argnames */
1033 
1034  if (pronargs > nargs && expand_defaults)
1035  {
1036  /* Ignore if not enough default expressions */
1037  if (nargs + procform->pronargdefaults < pronargs)
1038  continue;
1039  use_defaults = true;
1040  }
1041  else
1042  use_defaults = false;
1043 
1044  /* Ignore if it doesn't match requested argument count */
1045  if (pronargs != nargs && !use_defaults)
1046  continue;
1047 
1048  /* Check for argument name match, generate positional mapping */
1049  if (!MatchNamedCall(proctup, nargs, argnames,
1050  &argnumbers))
1051  continue;
1052 
1053  /* Named argument matching is always "special" */
1054  any_special = true;
1055  }
1056  else
1057  {
1058  /*
1059  * Call uses positional notation
1060  *
1061  * Check if function is variadic, and get variadic element type if
1062  * so. If expand_variadic is false, we should just ignore
1063  * variadic-ness.
1064  */
1065  if (pronargs <= nargs && expand_variadic)
1066  {
1067  va_elem_type = procform->provariadic;
1068  variadic = OidIsValid(va_elem_type);
1069  any_special |= variadic;
1070  }
1071  else
1072  {
1073  va_elem_type = InvalidOid;
1074  variadic = false;
1075  }
1076 
1077  /*
1078  * Check if function can match by using parameter defaults.
1079  */
1080  if (pronargs > nargs && expand_defaults)
1081  {
1082  /* Ignore if not enough default expressions */
1083  if (nargs + procform->pronargdefaults < pronargs)
1084  continue;
1085  use_defaults = true;
1086  any_special = true;
1087  }
1088  else
1089  use_defaults = false;
1090 
1091  /* Ignore if it doesn't match requested argument count */
1092  if (nargs >= 0 && pronargs != nargs && !variadic && !use_defaults)
1093  continue;
1094  }
1095 
1096  /*
1097  * We must compute the effective argument list so that we can easily
1098  * compare it to earlier results. We waste a palloc cycle if it gets
1099  * masked by an earlier result, but really that's a pretty infrequent
1100  * case so it's not worth worrying about.
1101  */
1102  effective_nargs = Max(pronargs, nargs);
1103  newResult = (FuncCandidateList)
1105  effective_nargs * sizeof(Oid));
1106  newResult->pathpos = pathpos;
1107  newResult->oid = procform->oid;
1108  newResult->nargs = effective_nargs;
1109  newResult->argnumbers = argnumbers;
1110  if (argnumbers)
1111  {
1112  /* Re-order the argument types into call's logical order */
1113  Oid *proargtypes = procform->proargtypes.values;
1114  int i;
1115 
1116  for (i = 0; i < pronargs; i++)
1117  newResult->args[i] = proargtypes[argnumbers[i]];
1118  }
1119  else
1120  {
1121  /* Simple positional case, just copy proargtypes as-is */
1122  memcpy(newResult->args, procform->proargtypes.values,
1123  pronargs * sizeof(Oid));
1124  }
1125  if (variadic)
1126  {
1127  int i;
1128 
1129  newResult->nvargs = effective_nargs - pronargs + 1;
1130  /* Expand variadic argument into N copies of element type */
1131  for (i = pronargs - 1; i < effective_nargs; i++)
1132  newResult->args[i] = va_elem_type;
1133  }
1134  else
1135  newResult->nvargs = 0;
1136  newResult->ndargs = use_defaults ? pronargs - nargs : 0;
1137 
1138  /*
1139  * Does it have the same arguments as something we already accepted?
1140  * If so, decide what to do to avoid returning duplicate argument
1141  * lists. We can skip this check for the single-namespace case if no
1142  * special (named, variadic or defaults) match has been made, since
1143  * then the unique index on pg_proc guarantees all the matches have
1144  * different argument lists.
1145  */
1146  if (resultList != NULL &&
1147  (any_special || !OidIsValid(namespaceId)))
1148  {
1149  /*
1150  * If we have an ordered list from SearchSysCacheList (the normal
1151  * case), then any conflicting proc must immediately adjoin this
1152  * one in the list, so we only need to look at the newest result
1153  * item. If we have an unordered list, we have to scan the whole
1154  * result list. Also, if either the current candidate or any
1155  * previous candidate is a special match, we can't assume that
1156  * conflicts are adjacent.
1157  *
1158  * We ignore defaulted arguments in deciding what is a match.
1159  */
1160  FuncCandidateList prevResult;
1161 
1162  if (catlist->ordered && !any_special)
1163  {
1164  /* ndargs must be 0 if !any_special */
1165  if (effective_nargs == resultList->nargs &&
1166  memcmp(newResult->args,
1167  resultList->args,
1168  effective_nargs * sizeof(Oid)) == 0)
1169  prevResult = resultList;
1170  else
1171  prevResult = NULL;
1172  }
1173  else
1174  {
1175  int cmp_nargs = newResult->nargs - newResult->ndargs;
1176 
1177  for (prevResult = resultList;
1178  prevResult;
1179  prevResult = prevResult->next)
1180  {
1181  if (cmp_nargs == prevResult->nargs - prevResult->ndargs &&
1182  memcmp(newResult->args,
1183  prevResult->args,
1184  cmp_nargs * sizeof(Oid)) == 0)
1185  break;
1186  }
1187  }
1188 
1189  if (prevResult)
1190  {
1191  /*
1192  * We have a match with a previous result. Decide which one
1193  * to keep, or mark it ambiguous if we can't decide. The
1194  * logic here is preference > 0 means prefer the old result,
1195  * preference < 0 means prefer the new, preference = 0 means
1196  * ambiguous.
1197  */
1198  int preference;
1199 
1200  if (pathpos != prevResult->pathpos)
1201  {
1202  /*
1203  * Prefer the one that's earlier in the search path.
1204  */
1205  preference = pathpos - prevResult->pathpos;
1206  }
1207  else if (variadic && prevResult->nvargs == 0)
1208  {
1209  /*
1210  * With variadic functions we could have, for example,
1211  * both foo(numeric) and foo(variadic numeric[]) in the
1212  * same namespace; if so we prefer the non-variadic match
1213  * on efficiency grounds.
1214  */
1215  preference = 1;
1216  }
1217  else if (!variadic && prevResult->nvargs > 0)
1218  {
1219  preference = -1;
1220  }
1221  else
1222  {
1223  /*----------
1224  * We can't decide. This can happen with, for example,
1225  * both foo(numeric, variadic numeric[]) and
1226  * foo(variadic numeric[]) in the same namespace, or
1227  * both foo(int) and foo (int, int default something)
1228  * in the same namespace, or both foo(a int, b text)
1229  * and foo(b text, a int) in the same namespace.
1230  *----------
1231  */
1232  preference = 0;
1233  }
1234 
1235  if (preference > 0)
1236  {
1237  /* keep previous result */
1238  pfree(newResult);
1239  continue;
1240  }
1241  else if (preference < 0)
1242  {
1243  /* remove previous result from the list */
1244  if (prevResult == resultList)
1245  resultList = prevResult->next;
1246  else
1247  {
1248  FuncCandidateList prevPrevResult;
1249 
1250  for (prevPrevResult = resultList;
1251  prevPrevResult;
1252  prevPrevResult = prevPrevResult->next)
1253  {
1254  if (prevResult == prevPrevResult->next)
1255  {
1256  prevPrevResult->next = prevResult->next;
1257  break;
1258  }
1259  }
1260  Assert(prevPrevResult); /* assert we found it */
1261  }
1262  pfree(prevResult);
1263  /* fall through to add newResult to list */
1264  }
1265  else
1266  {
1267  /* mark old result as ambiguous, discard new */
1268  prevResult->oid = InvalidOid;
1269  pfree(newResult);
1270  continue;
1271  }
1272  }
1273  }
1274 
1275  /*
1276  * Okay to add it to result list
1277  */
1278  newResult->next = resultList;
1279  resultList = newResult;
1280  }
1281 
1282  ReleaseSysCacheList(catlist);
1283 
1284  return resultList;
1285 }
1286 
1287 /*
1288  * MatchNamedCall
1289  * Given a pg_proc heap tuple and a call's list of argument names,
1290  * check whether the function could match the call.
1291  *
1292  * The call could match if all supplied argument names are accepted by
1293  * the function, in positions after the last positional argument, and there
1294  * are defaults for all unsupplied arguments.
1295  *
1296  * The number of positional arguments is nargs - list_length(argnames).
1297  * Note caller has already done basic checks on argument count.
1298  *
1299  * On match, return true and fill *argnumbers with a palloc'd array showing
1300  * the mapping from call argument positions to actual function argument
1301  * numbers. Defaulted arguments are included in this map, at positions
1302  * after the last supplied argument.
1303  */
1304 static bool
1305 MatchNamedCall(HeapTuple proctup, int nargs, List *argnames,
1306  int **argnumbers)
1307 {
1308  Form_pg_proc procform = (Form_pg_proc) GETSTRUCT(proctup);
1309  int pronargs = procform->pronargs;
1310  int numposargs = nargs - list_length(argnames);
1311  int pronallargs;
1312  Oid *p_argtypes;
1313  char **p_argnames;
1314  char *p_argmodes;
1315  bool arggiven[FUNC_MAX_ARGS];
1316  bool isnull;
1317  int ap; /* call args position */
1318  int pp; /* proargs position */
1319  ListCell *lc;
1320 
1321  Assert(argnames != NIL);
1322  Assert(numposargs >= 0);
1323  Assert(nargs <= pronargs);
1324 
1325  /* Ignore this function if its proargnames is null */
1326  (void) SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_proargnames,
1327  &isnull);
1328  if (isnull)
1329  return false;
1330 
1331  /* OK, let's extract the argument names and types */
1332  pronallargs = get_func_arg_info(proctup,
1333  &p_argtypes, &p_argnames, &p_argmodes);
1334  Assert(p_argnames != NULL);
1335 
1336  /* initialize state for matching */
1337  *argnumbers = (int *) palloc(pronargs * sizeof(int));
1338  memset(arggiven, false, pronargs * sizeof(bool));
1339 
1340  /* there are numposargs positional args before the named args */
1341  for (ap = 0; ap < numposargs; ap++)
1342  {
1343  (*argnumbers)[ap] = ap;
1344  arggiven[ap] = true;
1345  }
1346 
1347  /* now examine the named args */
1348  foreach(lc, argnames)
1349  {
1350  char *argname = (char *) lfirst(lc);
1351  bool found;
1352  int i;
1353 
1354  pp = 0;
1355  found = false;
1356  for (i = 0; i < pronallargs; i++)
1357  {
1358  /* consider only input parameters */
1359  if (p_argmodes &&
1360  (p_argmodes[i] != FUNC_PARAM_IN &&
1361  p_argmodes[i] != FUNC_PARAM_INOUT &&
1362  p_argmodes[i] != FUNC_PARAM_VARIADIC))
1363  continue;
1364  if (p_argnames[i] && strcmp(p_argnames[i], argname) == 0)
1365  {
1366  /* fail if argname matches a positional argument */
1367  if (arggiven[pp])
1368  return false;
1369  arggiven[pp] = true;
1370  (*argnumbers)[ap] = pp;
1371  found = true;
1372  break;
1373  }
1374  /* increase pp only for input parameters */
1375  pp++;
1376  }
1377  /* if name isn't in proargnames, fail */
1378  if (!found)
1379  return false;
1380  ap++;
1381  }
1382 
1383  Assert(ap == nargs); /* processed all actual parameters */
1384 
1385  /* Check for default arguments */
1386  if (nargs < pronargs)
1387  {
1388  int first_arg_with_default = pronargs - procform->pronargdefaults;
1389 
1390  for (pp = numposargs; pp < pronargs; pp++)
1391  {
1392  if (arggiven[pp])
1393  continue;
1394  /* fail if arg not given and no default available */
1395  if (pp < first_arg_with_default)
1396  return false;
1397  (*argnumbers)[ap++] = pp;
1398  }
1399  }
1400 
1401  Assert(ap == pronargs); /* processed all function parameters */
1402 
1403  return true;
1404 }
1405 
1406 /*
1407  * FunctionIsVisible
1408  * Determine whether a function (identified by OID) is visible in the
1409  * current search path. Visible means "would be found by searching
1410  * for the unqualified function name with exact argument matches".
1411  */
1412 bool
1414 {
1415  HeapTuple proctup;
1416  Form_pg_proc procform;
1417  Oid pronamespace;
1418  bool visible;
1419 
1420  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1421  if (!HeapTupleIsValid(proctup))
1422  elog(ERROR, "cache lookup failed for function %u", funcid);
1423  procform = (Form_pg_proc) GETSTRUCT(proctup);
1424 
1426 
1427  /*
1428  * Quick check: if it ain't in the path at all, it ain't visible. Items in
1429  * the system namespace are surely in the path and so we needn't even do
1430  * list_member_oid() for them.
1431  */
1432  pronamespace = procform->pronamespace;
1433  if (pronamespace != PG_CATALOG_NAMESPACE &&
1434  !list_member_oid(activeSearchPath, pronamespace))
1435  visible = false;
1436  else
1437  {
1438  /*
1439  * If it is in the path, it might still not be visible; it could be
1440  * hidden by another proc of the same name and arguments earlier in
1441  * the path. So we must do a slow check to see if this is the same
1442  * proc that would be found by FuncnameGetCandidates.
1443  */
1444  char *proname = NameStr(procform->proname);
1445  int nargs = procform->pronargs;
1446  FuncCandidateList clist;
1447 
1448  visible = false;
1449 
1450  clist = FuncnameGetCandidates(list_make1(makeString(proname)),
1451  nargs, NIL, false, false, false);
1452 
1453  for (; clist; clist = clist->next)
1454  {
1455  if (memcmp(clist->args, procform->proargtypes.values,
1456  nargs * sizeof(Oid)) == 0)
1457  {
1458  /* Found the expected entry; is it the right proc? */
1459  visible = (clist->oid == funcid);
1460  break;
1461  }
1462  }
1463  }
1464 
1465  ReleaseSysCache(proctup);
1466 
1467  return visible;
1468 }
1469 
1470 
1471 /*
1472  * OpernameGetOprid
1473  * Given a possibly-qualified operator name and exact input datatypes,
1474  * look up the operator. Returns InvalidOid if not found.
1475  *
1476  * Pass oprleft = InvalidOid for a prefix op.
1477  *
1478  * If the operator name is not schema-qualified, it is sought in the current
1479  * namespace search path. If the name is schema-qualified and the given
1480  * schema does not exist, InvalidOid is returned.
1481  */
1482 Oid
1483 OpernameGetOprid(List *names, Oid oprleft, Oid oprright)
1484 {
1485  char *schemaname;
1486  char *opername;
1487  CatCList *catlist;
1488  ListCell *l;
1489 
1490  /* deconstruct the name list */
1491  DeconstructQualifiedName(names, &schemaname, &opername);
1492 
1493  if (schemaname)
1494  {
1495  /* search only in exact schema given */
1496  Oid namespaceId;
1497 
1498  namespaceId = LookupExplicitNamespace(schemaname, true);
1499  if (OidIsValid(namespaceId))
1500  {
1501  HeapTuple opertup;
1502 
1503  opertup = SearchSysCache4(OPERNAMENSP,
1504  CStringGetDatum(opername),
1505  ObjectIdGetDatum(oprleft),
1506  ObjectIdGetDatum(oprright),
1507  ObjectIdGetDatum(namespaceId));
1508  if (HeapTupleIsValid(opertup))
1509  {
1510  Form_pg_operator operclass = (Form_pg_operator) GETSTRUCT(opertup);
1511  Oid result = operclass->oid;
1512 
1513  ReleaseSysCache(opertup);
1514  return result;
1515  }
1516  }
1517 
1518  return InvalidOid;
1519  }
1520 
1521  /* Search syscache by name and argument types */
1522  catlist = SearchSysCacheList3(OPERNAMENSP,
1523  CStringGetDatum(opername),
1524  ObjectIdGetDatum(oprleft),
1525  ObjectIdGetDatum(oprright));
1526 
1527  if (catlist->n_members == 0)
1528  {
1529  /* no hope, fall out early */
1530  ReleaseSysCacheList(catlist);
1531  return InvalidOid;
1532  }
1533 
1534  /*
1535  * We have to find the list member that is first in the search path, if
1536  * there's more than one. This doubly-nested loop looks ugly, but in
1537  * practice there should usually be few catlist members.
1538  */
1540 
1541  foreach(l, activeSearchPath)
1542  {
1543  Oid namespaceId = lfirst_oid(l);
1544  int i;
1545 
1546  if (namespaceId == myTempNamespace)
1547  continue; /* do not look in temp namespace */
1548 
1549  for (i = 0; i < catlist->n_members; i++)
1550  {
1551  HeapTuple opertup = &catlist->members[i]->tuple;
1552  Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup);
1553 
1554  if (operform->oprnamespace == namespaceId)
1555  {
1556  Oid result = operform->oid;
1557 
1558  ReleaseSysCacheList(catlist);
1559  return result;
1560  }
1561  }
1562  }
1563 
1564  ReleaseSysCacheList(catlist);
1565  return InvalidOid;
1566 }
1567 
1568 /*
1569  * OpernameGetCandidates
1570  * Given a possibly-qualified operator name and operator kind,
1571  * retrieve a list of the possible matches.
1572  *
1573  * If oprkind is '\0', we return all operators matching the given name,
1574  * regardless of arguments.
1575  *
1576  * We search a single namespace if the operator name is qualified, else
1577  * all namespaces in the search path. The return list will never contain
1578  * multiple entries with identical argument lists --- in the multiple-
1579  * namespace case, we arrange for entries in earlier namespaces to mask
1580  * identical entries in later namespaces.
1581  *
1582  * The returned items always have two args[] entries --- the first will be
1583  * InvalidOid for a prefix oprkind. nargs is always 2, too.
1584  */
1586 OpernameGetCandidates(List *names, char oprkind, bool missing_schema_ok)
1587 {
1588  FuncCandidateList resultList = NULL;
1589  char *resultSpace = NULL;
1590  int nextResult = 0;
1591  char *schemaname;
1592  char *opername;
1593  Oid namespaceId;
1594  CatCList *catlist;
1595  int i;
1596 
1597  /* deconstruct the name list */
1598  DeconstructQualifiedName(names, &schemaname, &opername);
1599 
1600  if (schemaname)
1601  {
1602  /* use exact schema given */
1603  namespaceId = LookupExplicitNamespace(schemaname, missing_schema_ok);
1604  if (missing_schema_ok && !OidIsValid(namespaceId))
1605  return NULL;
1606  }
1607  else
1608  {
1609  /* flag to indicate we need namespace search */
1610  namespaceId = InvalidOid;
1612  }
1613 
1614  /* Search syscache by name only */
1615  catlist = SearchSysCacheList1(OPERNAMENSP, CStringGetDatum(opername));
1616 
1617  /*
1618  * In typical scenarios, most if not all of the operators found by the
1619  * catcache search will end up getting returned; and there can be quite a
1620  * few, for common operator names such as '=' or '+'. To reduce the time
1621  * spent in palloc, we allocate the result space as an array large enough
1622  * to hold all the operators. The original coding of this routine did a
1623  * separate palloc for each operator, but profiling revealed that the
1624  * pallocs used an unreasonably large fraction of parsing time.
1625  */
1626 #define SPACE_PER_OP MAXALIGN(offsetof(struct _FuncCandidateList, args) + \
1627  2 * sizeof(Oid))
1628 
1629  if (catlist->n_members > 0)
1630  resultSpace = palloc(catlist->n_members * SPACE_PER_OP);
1631 
1632  for (i = 0; i < catlist->n_members; i++)
1633  {
1634  HeapTuple opertup = &catlist->members[i]->tuple;
1635  Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup);
1636  int pathpos = 0;
1637  FuncCandidateList newResult;
1638 
1639  /* Ignore operators of wrong kind, if specific kind requested */
1640  if (oprkind && operform->oprkind != oprkind)
1641  continue;
1642 
1643  if (OidIsValid(namespaceId))
1644  {
1645  /* Consider only opers in specified namespace */
1646  if (operform->oprnamespace != namespaceId)
1647  continue;
1648  /* No need to check args, they must all be different */
1649  }
1650  else
1651  {
1652  /*
1653  * Consider only opers that are in the search path and are not in
1654  * the temp namespace.
1655  */
1656  ListCell *nsp;
1657 
1658  foreach(nsp, activeSearchPath)
1659  {
1660  if (operform->oprnamespace == lfirst_oid(nsp) &&
1661  operform->oprnamespace != myTempNamespace)
1662  break;
1663  pathpos++;
1664  }
1665  if (nsp == NULL)
1666  continue; /* oper is not in search path */
1667 
1668  /*
1669  * Okay, it's in the search path, but does it have the same
1670  * arguments as something we already accepted? If so, keep only
1671  * the one that appears earlier in the search path.
1672  *
1673  * If we have an ordered list from SearchSysCacheList (the normal
1674  * case), then any conflicting oper must immediately adjoin this
1675  * one in the list, so we only need to look at the newest result
1676  * item. If we have an unordered list, we have to scan the whole
1677  * result list.
1678  */
1679  if (resultList)
1680  {
1681  FuncCandidateList prevResult;
1682 
1683  if (catlist->ordered)
1684  {
1685  if (operform->oprleft == resultList->args[0] &&
1686  operform->oprright == resultList->args[1])
1687  prevResult = resultList;
1688  else
1689  prevResult = NULL;
1690  }
1691  else
1692  {
1693  for (prevResult = resultList;
1694  prevResult;
1695  prevResult = prevResult->next)
1696  {
1697  if (operform->oprleft == prevResult->args[0] &&
1698  operform->oprright == prevResult->args[1])
1699  break;
1700  }
1701  }
1702  if (prevResult)
1703  {
1704  /* We have a match with a previous result */
1705  Assert(pathpos != prevResult->pathpos);
1706  if (pathpos > prevResult->pathpos)
1707  continue; /* keep previous result */
1708  /* replace previous result */
1709  prevResult->pathpos = pathpos;
1710  prevResult->oid = operform->oid;
1711  continue; /* args are same, of course */
1712  }
1713  }
1714  }
1715 
1716  /*
1717  * Okay to add it to result list
1718  */
1719  newResult = (FuncCandidateList) (resultSpace + nextResult);
1720  nextResult += SPACE_PER_OP;
1721 
1722  newResult->pathpos = pathpos;
1723  newResult->oid = operform->oid;
1724  newResult->nargs = 2;
1725  newResult->nvargs = 0;
1726  newResult->ndargs = 0;
1727  newResult->argnumbers = NULL;
1728  newResult->args[0] = operform->oprleft;
1729  newResult->args[1] = operform->oprright;
1730  newResult->next = resultList;
1731  resultList = newResult;
1732  }
1733 
1734  ReleaseSysCacheList(catlist);
1735 
1736  return resultList;
1737 }
1738 
1739 /*
1740  * OperatorIsVisible
1741  * Determine whether an operator (identified by OID) is visible in the
1742  * current search path. Visible means "would be found by searching
1743  * for the unqualified operator name with exact argument matches".
1744  */
1745 bool
1747 {
1748  HeapTuple oprtup;
1749  Form_pg_operator oprform;
1750  Oid oprnamespace;
1751  bool visible;
1752 
1753  oprtup = SearchSysCache1(OPEROID, ObjectIdGetDatum(oprid));
1754  if (!HeapTupleIsValid(oprtup))
1755  elog(ERROR, "cache lookup failed for operator %u", oprid);
1756  oprform = (Form_pg_operator) GETSTRUCT(oprtup);
1757 
1759 
1760  /*
1761  * Quick check: if it ain't in the path at all, it ain't visible. Items in
1762  * the system namespace are surely in the path and so we needn't even do
1763  * list_member_oid() for them.
1764  */
1765  oprnamespace = oprform->oprnamespace;
1766  if (oprnamespace != PG_CATALOG_NAMESPACE &&
1767  !list_member_oid(activeSearchPath, oprnamespace))
1768  visible = false;
1769  else
1770  {
1771  /*
1772  * If it is in the path, it might still not be visible; it could be
1773  * hidden by another operator of the same name and arguments earlier
1774  * in the path. So we must do a slow check to see if this is the same
1775  * operator that would be found by OpernameGetOprid.
1776  */
1777  char *oprname = NameStr(oprform->oprname);
1778 
1779  visible = (OpernameGetOprid(list_make1(makeString(oprname)),
1780  oprform->oprleft, oprform->oprright)
1781  == oprid);
1782  }
1783 
1784  ReleaseSysCache(oprtup);
1785 
1786  return visible;
1787 }
1788 
1789 
1790 /*
1791  * OpclassnameGetOpcid
1792  * Try to resolve an unqualified index opclass name.
1793  * Returns OID if opclass found in search path, else InvalidOid.
1794  *
1795  * This is essentially the same as TypenameGetTypid, but we have to have
1796  * an extra argument for the index AM OID.
1797  */
1798 Oid
1799 OpclassnameGetOpcid(Oid amid, const char *opcname)
1800 {
1801  Oid opcid;
1802  ListCell *l;
1803 
1805 
1806  foreach(l, activeSearchPath)
1807  {
1808  Oid namespaceId = lfirst_oid(l);
1809 
1810  if (namespaceId == myTempNamespace)
1811  continue; /* do not look in temp namespace */
1812 
1813  opcid = GetSysCacheOid3(CLAAMNAMENSP, Anum_pg_opclass_oid,
1814  ObjectIdGetDatum(amid),
1815  PointerGetDatum(opcname),
1816  ObjectIdGetDatum(namespaceId));
1817  if (OidIsValid(opcid))
1818  return opcid;
1819  }
1820 
1821  /* Not found in path */
1822  return InvalidOid;
1823 }
1824 
1825 /*
1826  * OpclassIsVisible
1827  * Determine whether an opclass (identified by OID) is visible in the
1828  * current search path. Visible means "would be found by searching
1829  * for the unqualified opclass name".
1830  */
1831 bool
1833 {
1834  HeapTuple opctup;
1835  Form_pg_opclass opcform;
1836  Oid opcnamespace;
1837  bool visible;
1838 
1839  opctup = SearchSysCache1(CLAOID, ObjectIdGetDatum(opcid));
1840  if (!HeapTupleIsValid(opctup))
1841  elog(ERROR, "cache lookup failed for opclass %u", opcid);
1842  opcform = (Form_pg_opclass) GETSTRUCT(opctup);
1843 
1845 
1846  /*
1847  * Quick check: if it ain't in the path at all, it ain't visible. Items in
1848  * the system namespace are surely in the path and so we needn't even do
1849  * list_member_oid() for them.
1850  */
1851  opcnamespace = opcform->opcnamespace;
1852  if (opcnamespace != PG_CATALOG_NAMESPACE &&
1853  !list_member_oid(activeSearchPath, opcnamespace))
1854  visible = false;
1855  else
1856  {
1857  /*
1858  * If it is in the path, it might still not be visible; it could be
1859  * hidden by another opclass of the same name earlier in the path. So
1860  * we must do a slow check to see if this opclass would be found by
1861  * OpclassnameGetOpcid.
1862  */
1863  char *opcname = NameStr(opcform->opcname);
1864 
1865  visible = (OpclassnameGetOpcid(opcform->opcmethod, opcname) == opcid);
1866  }
1867 
1868  ReleaseSysCache(opctup);
1869 
1870  return visible;
1871 }
1872 
1873 /*
1874  * OpfamilynameGetOpfid
1875  * Try to resolve an unqualified index opfamily name.
1876  * Returns OID if opfamily found in search path, else InvalidOid.
1877  *
1878  * This is essentially the same as TypenameGetTypid, but we have to have
1879  * an extra argument for the index AM OID.
1880  */
1881 Oid
1882 OpfamilynameGetOpfid(Oid amid, const char *opfname)
1883 {
1884  Oid opfid;
1885  ListCell *l;
1886 
1888 
1889  foreach(l, activeSearchPath)
1890  {
1891  Oid namespaceId = lfirst_oid(l);
1892 
1893  if (namespaceId == myTempNamespace)
1894  continue; /* do not look in temp namespace */
1895 
1896  opfid = GetSysCacheOid3(OPFAMILYAMNAMENSP, Anum_pg_opfamily_oid,
1897  ObjectIdGetDatum(amid),
1898  PointerGetDatum(opfname),
1899  ObjectIdGetDatum(namespaceId));
1900  if (OidIsValid(opfid))
1901  return opfid;
1902  }
1903 
1904  /* Not found in path */
1905  return InvalidOid;
1906 }
1907 
1908 /*
1909  * OpfamilyIsVisible
1910  * Determine whether an opfamily (identified by OID) is visible in the
1911  * current search path. Visible means "would be found by searching
1912  * for the unqualified opfamily name".
1913  */
1914 bool
1916 {
1917  HeapTuple opftup;
1918  Form_pg_opfamily opfform;
1919  Oid opfnamespace;
1920  bool visible;
1921 
1922  opftup = SearchSysCache1(OPFAMILYOID, ObjectIdGetDatum(opfid));
1923  if (!HeapTupleIsValid(opftup))
1924  elog(ERROR, "cache lookup failed for opfamily %u", opfid);
1925  opfform = (Form_pg_opfamily) GETSTRUCT(opftup);
1926 
1928 
1929  /*
1930  * Quick check: if it ain't in the path at all, it ain't visible. Items in
1931  * the system namespace are surely in the path and so we needn't even do
1932  * list_member_oid() for them.
1933  */
1934  opfnamespace = opfform->opfnamespace;
1935  if (opfnamespace != PG_CATALOG_NAMESPACE &&
1936  !list_member_oid(activeSearchPath, opfnamespace))
1937  visible = false;
1938  else
1939  {
1940  /*
1941  * If it is in the path, it might still not be visible; it could be
1942  * hidden by another opfamily of the same name earlier in the path. So
1943  * we must do a slow check to see if this opfamily would be found by
1944  * OpfamilynameGetOpfid.
1945  */
1946  char *opfname = NameStr(opfform->opfname);
1947 
1948  visible = (OpfamilynameGetOpfid(opfform->opfmethod, opfname) == opfid);
1949  }
1950 
1951  ReleaseSysCache(opftup);
1952 
1953  return visible;
1954 }
1955 
1956 /*
1957  * lookup_collation
1958  * If there's a collation of the given name/namespace, and it works
1959  * with the given encoding, return its OID. Else return InvalidOid.
1960  */
1961 static Oid
1962 lookup_collation(const char *collname, Oid collnamespace, int32 encoding)
1963 {
1964  Oid collid;
1965  HeapTuple colltup;
1966  Form_pg_collation collform;
1967 
1968  /* Check for encoding-specific entry (exact match) */
1969  collid = GetSysCacheOid3(COLLNAMEENCNSP, Anum_pg_collation_oid,
1970  PointerGetDatum(collname),
1971  Int32GetDatum(encoding),
1972  ObjectIdGetDatum(collnamespace));
1973  if (OidIsValid(collid))
1974  return collid;
1975 
1976  /*
1977  * Check for any-encoding entry. This takes a bit more work: while libc
1978  * collations with collencoding = -1 do work with all encodings, ICU
1979  * collations only work with certain encodings, so we have to check that
1980  * aspect before deciding it's a match.
1981  */
1982  colltup = SearchSysCache3(COLLNAMEENCNSP,
1983  PointerGetDatum(collname),
1984  Int32GetDatum(-1),
1985  ObjectIdGetDatum(collnamespace));
1986  if (!HeapTupleIsValid(colltup))
1987  return InvalidOid;
1988  collform = (Form_pg_collation) GETSTRUCT(colltup);
1989  if (collform->collprovider == COLLPROVIDER_ICU)
1990  {
1991  if (is_encoding_supported_by_icu(encoding))
1992  collid = collform->oid;
1993  else
1994  collid = InvalidOid;
1995  }
1996  else
1997  {
1998  collid = collform->oid;
1999  }
2000  ReleaseSysCache(colltup);
2001  return collid;
2002 }
2003 
2004 /*
2005  * CollationGetCollid
2006  * Try to resolve an unqualified collation name.
2007  * Returns OID if collation found in search path, else InvalidOid.
2008  *
2009  * Note that this will only find collations that work with the current
2010  * database's encoding.
2011  */
2012 Oid
2013 CollationGetCollid(const char *collname)
2014 {
2015  int32 dbencoding = GetDatabaseEncoding();
2016  ListCell *l;
2017 
2019 
2020  foreach(l, activeSearchPath)
2021  {
2022  Oid namespaceId = lfirst_oid(l);
2023  Oid collid;
2024 
2025  if (namespaceId == myTempNamespace)
2026  continue; /* do not look in temp namespace */
2027 
2028  collid = lookup_collation(collname, namespaceId, dbencoding);
2029  if (OidIsValid(collid))
2030  return collid;
2031  }
2032 
2033  /* Not found in path */
2034  return InvalidOid;
2035 }
2036 
2037 /*
2038  * CollationIsVisible
2039  * Determine whether a collation (identified by OID) is visible in the
2040  * current search path. Visible means "would be found by searching
2041  * for the unqualified collation name".
2042  *
2043  * Note that only collations that work with the current database's encoding
2044  * will be considered visible.
2045  */
2046 bool
2048 {
2049  HeapTuple colltup;
2050  Form_pg_collation collform;
2051  Oid collnamespace;
2052  bool visible;
2053 
2054  colltup = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
2055  if (!HeapTupleIsValid(colltup))
2056  elog(ERROR, "cache lookup failed for collation %u", collid);
2057  collform = (Form_pg_collation) GETSTRUCT(colltup);
2058 
2060 
2061  /*
2062  * Quick check: if it ain't in the path at all, it ain't visible. Items in
2063  * the system namespace are surely in the path and so we needn't even do
2064  * list_member_oid() for them.
2065  */
2066  collnamespace = collform->collnamespace;
2067  if (collnamespace != PG_CATALOG_NAMESPACE &&
2068  !list_member_oid(activeSearchPath, collnamespace))
2069  visible = false;
2070  else
2071  {
2072  /*
2073  * If it is in the path, it might still not be visible; it could be
2074  * hidden by another collation of the same name earlier in the path,
2075  * or it might not work with the current DB encoding. So we must do a
2076  * slow check to see if this collation would be found by
2077  * CollationGetCollid.
2078  */
2079  char *collname = NameStr(collform->collname);
2080 
2081  visible = (CollationGetCollid(collname) == collid);
2082  }
2083 
2084  ReleaseSysCache(colltup);
2085 
2086  return visible;
2087 }
2088 
2089 
2090 /*
2091  * ConversionGetConid
2092  * Try to resolve an unqualified conversion name.
2093  * Returns OID if conversion found in search path, else InvalidOid.
2094  *
2095  * This is essentially the same as RelnameGetRelid.
2096  */
2097 Oid
2098 ConversionGetConid(const char *conname)
2099 {
2100  Oid conid;
2101  ListCell *l;
2102 
2104 
2105  foreach(l, activeSearchPath)
2106  {
2107  Oid namespaceId = lfirst_oid(l);
2108 
2109  if (namespaceId == myTempNamespace)
2110  continue; /* do not look in temp namespace */
2111 
2112  conid = GetSysCacheOid2(CONNAMENSP, Anum_pg_conversion_oid,
2113  PointerGetDatum(conname),
2114  ObjectIdGetDatum(namespaceId));
2115  if (OidIsValid(conid))
2116  return conid;
2117  }
2118 
2119  /* Not found in path */
2120  return InvalidOid;
2121 }
2122 
2123 /*
2124  * ConversionIsVisible
2125  * Determine whether a conversion (identified by OID) is visible in the
2126  * current search path. Visible means "would be found by searching
2127  * for the unqualified conversion name".
2128  */
2129 bool
2131 {
2132  HeapTuple contup;
2133  Form_pg_conversion conform;
2134  Oid connamespace;
2135  bool visible;
2136 
2137  contup = SearchSysCache1(CONVOID, ObjectIdGetDatum(conid));
2138  if (!HeapTupleIsValid(contup))
2139  elog(ERROR, "cache lookup failed for conversion %u", conid);
2140  conform = (Form_pg_conversion) GETSTRUCT(contup);
2141 
2143 
2144  /*
2145  * Quick check: if it ain't in the path at all, it ain't visible. Items in
2146  * the system namespace are surely in the path and so we needn't even do
2147  * list_member_oid() for them.
2148  */
2149  connamespace = conform->connamespace;
2150  if (connamespace != PG_CATALOG_NAMESPACE &&
2151  !list_member_oid(activeSearchPath, connamespace))
2152  visible = false;
2153  else
2154  {
2155  /*
2156  * If it is in the path, it might still not be visible; it could be
2157  * hidden by another conversion of the same name earlier in the path.
2158  * So we must do a slow check to see if this conversion would be found
2159  * by ConversionGetConid.
2160  */
2161  char *conname = NameStr(conform->conname);
2162 
2163  visible = (ConversionGetConid(conname) == conid);
2164  }
2165 
2166  ReleaseSysCache(contup);
2167 
2168  return visible;
2169 }
2170 
2171 /*
2172  * get_statistics_object_oid - find a statistics object by possibly qualified name
2173  *
2174  * If not found, returns InvalidOid if missing_ok, else throws error
2175  */
2176 Oid
2177 get_statistics_object_oid(List *names, bool missing_ok)
2178 {
2179  char *schemaname;
2180  char *stats_name;
2181  Oid namespaceId;
2182  Oid stats_oid = InvalidOid;
2183  ListCell *l;
2184 
2185  /* deconstruct the name list */
2186  DeconstructQualifiedName(names, &schemaname, &stats_name);
2187 
2188  if (schemaname)
2189  {
2190  /* use exact schema given */
2191  namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
2192  if (missing_ok && !OidIsValid(namespaceId))
2193  stats_oid = InvalidOid;
2194  else
2195  stats_oid = GetSysCacheOid2(STATEXTNAMENSP, Anum_pg_statistic_ext_oid,
2196  PointerGetDatum(stats_name),
2197  ObjectIdGetDatum(namespaceId));
2198  }
2199  else
2200  {
2201  /* search for it in search path */
2203 
2204  foreach(l, activeSearchPath)
2205  {
2206  namespaceId = lfirst_oid(l);
2207 
2208  if (namespaceId == myTempNamespace)
2209  continue; /* do not look in temp namespace */
2210  stats_oid = GetSysCacheOid2(STATEXTNAMENSP, Anum_pg_statistic_ext_oid,
2211  PointerGetDatum(stats_name),
2212  ObjectIdGetDatum(namespaceId));
2213  if (OidIsValid(stats_oid))
2214  break;
2215  }
2216  }
2217 
2218  if (!OidIsValid(stats_oid) && !missing_ok)
2219  ereport(ERROR,
2220  (errcode(ERRCODE_UNDEFINED_OBJECT),
2221  errmsg("statistics object \"%s\" does not exist",
2222  NameListToString(names))));
2223 
2224  return stats_oid;
2225 }
2226 
2227 /*
2228  * StatisticsObjIsVisible
2229  * Determine whether a statistics object (identified by OID) is visible in
2230  * the current search path. Visible means "would be found by searching
2231  * for the unqualified statistics object name".
2232  */
2233 bool
2235 {
2236  HeapTuple stxtup;
2237  Form_pg_statistic_ext stxform;
2238  Oid stxnamespace;
2239  bool visible;
2240 
2241  stxtup = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(relid));
2242  if (!HeapTupleIsValid(stxtup))
2243  elog(ERROR, "cache lookup failed for statistics object %u", relid);
2244  stxform = (Form_pg_statistic_ext) GETSTRUCT(stxtup);
2245 
2247 
2248  /*
2249  * Quick check: if it ain't in the path at all, it ain't visible. Items in
2250  * the system namespace are surely in the path and so we needn't even do
2251  * list_member_oid() for them.
2252  */
2253  stxnamespace = stxform->stxnamespace;
2254  if (stxnamespace != PG_CATALOG_NAMESPACE &&
2255  !list_member_oid(activeSearchPath, stxnamespace))
2256  visible = false;
2257  else
2258  {
2259  /*
2260  * If it is in the path, it might still not be visible; it could be
2261  * hidden by another statistics object of the same name earlier in the
2262  * path. So we must do a slow check for conflicting objects.
2263  */
2264  char *stxname = NameStr(stxform->stxname);
2265  ListCell *l;
2266 
2267  visible = false;
2268  foreach(l, activeSearchPath)
2269  {
2270  Oid namespaceId = lfirst_oid(l);
2271 
2272  if (namespaceId == stxnamespace)
2273  {
2274  /* Found it first in path */
2275  visible = true;
2276  break;
2277  }
2279  PointerGetDatum(stxname),
2280  ObjectIdGetDatum(namespaceId)))
2281  {
2282  /* Found something else first in path */
2283  break;
2284  }
2285  }
2286  }
2287 
2288  ReleaseSysCache(stxtup);
2289 
2290  return visible;
2291 }
2292 
2293 /*
2294  * get_ts_parser_oid - find a TS parser by possibly qualified name
2295  *
2296  * If not found, returns InvalidOid if missing_ok, else throws error
2297  */
2298 Oid
2299 get_ts_parser_oid(List *names, bool missing_ok)
2300 {
2301  char *schemaname;
2302  char *parser_name;
2303  Oid namespaceId;
2304  Oid prsoid = InvalidOid;
2305  ListCell *l;
2306 
2307  /* deconstruct the name list */
2308  DeconstructQualifiedName(names, &schemaname, &parser_name);
2309 
2310  if (schemaname)
2311  {
2312  /* use exact schema given */
2313  namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
2314  if (missing_ok && !OidIsValid(namespaceId))
2315  prsoid = InvalidOid;
2316  else
2317  prsoid = GetSysCacheOid2(TSPARSERNAMENSP, Anum_pg_ts_parser_oid,
2318  PointerGetDatum(parser_name),
2319  ObjectIdGetDatum(namespaceId));
2320  }
2321  else
2322  {
2323  /* search for it in search path */
2325 
2326  foreach(l, activeSearchPath)
2327  {
2328  namespaceId = lfirst_oid(l);
2329 
2330  if (namespaceId == myTempNamespace)
2331  continue; /* do not look in temp namespace */
2332 
2333  prsoid = GetSysCacheOid2(TSPARSERNAMENSP, Anum_pg_ts_parser_oid,
2334  PointerGetDatum(parser_name),
2335  ObjectIdGetDatum(namespaceId));
2336  if (OidIsValid(prsoid))
2337  break;
2338  }
2339  }
2340 
2341  if (!OidIsValid(prsoid) && !missing_ok)
2342  ereport(ERROR,
2343  (errcode(ERRCODE_UNDEFINED_OBJECT),
2344  errmsg("text search parser \"%s\" does not exist",
2345  NameListToString(names))));
2346 
2347  return prsoid;
2348 }
2349 
2350 /*
2351  * TSParserIsVisible
2352  * Determine whether a parser (identified by OID) is visible in the
2353  * current search path. Visible means "would be found by searching
2354  * for the unqualified parser name".
2355  */
2356 bool
2358 {
2359  HeapTuple tup;
2360  Form_pg_ts_parser form;
2361  Oid namespace;
2362  bool visible;
2363 
2365  if (!HeapTupleIsValid(tup))
2366  elog(ERROR, "cache lookup failed for text search parser %u", prsId);
2367  form = (Form_pg_ts_parser) GETSTRUCT(tup);
2368 
2370 
2371  /*
2372  * Quick check: if it ain't in the path at all, it ain't visible. Items in
2373  * the system namespace are surely in the path and so we needn't even do
2374  * list_member_oid() for them.
2375  */
2376  namespace = form->prsnamespace;
2377  if (namespace != PG_CATALOG_NAMESPACE &&
2378  !list_member_oid(activeSearchPath, namespace))
2379  visible = false;
2380  else
2381  {
2382  /*
2383  * If it is in the path, it might still not be visible; it could be
2384  * hidden by another parser of the same name earlier in the path. So
2385  * we must do a slow check for conflicting parsers.
2386  */
2387  char *name = NameStr(form->prsname);
2388  ListCell *l;
2389 
2390  visible = false;
2391  foreach(l, activeSearchPath)
2392  {
2393  Oid namespaceId = lfirst_oid(l);
2394 
2395  if (namespaceId == myTempNamespace)
2396  continue; /* do not look in temp namespace */
2397 
2398  if (namespaceId == namespace)
2399  {
2400  /* Found it first in path */
2401  visible = true;
2402  break;
2403  }
2405  PointerGetDatum(name),
2406  ObjectIdGetDatum(namespaceId)))
2407  {
2408  /* Found something else first in path */
2409  break;
2410  }
2411  }
2412  }
2413 
2414  ReleaseSysCache(tup);
2415 
2416  return visible;
2417 }
2418 
2419 /*
2420  * get_ts_dict_oid - find a TS dictionary by possibly qualified name
2421  *
2422  * If not found, returns InvalidOid if missing_ok, else throws error
2423  */
2424 Oid
2425 get_ts_dict_oid(List *names, bool missing_ok)
2426 {
2427  char *schemaname;
2428  char *dict_name;
2429  Oid namespaceId;
2430  Oid dictoid = InvalidOid;
2431  ListCell *l;
2432 
2433  /* deconstruct the name list */
2434  DeconstructQualifiedName(names, &schemaname, &dict_name);
2435 
2436  if (schemaname)
2437  {
2438  /* use exact schema given */
2439  namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
2440  if (missing_ok && !OidIsValid(namespaceId))
2441  dictoid = InvalidOid;
2442  else
2443  dictoid = GetSysCacheOid2(TSDICTNAMENSP, Anum_pg_ts_dict_oid,
2444  PointerGetDatum(dict_name),
2445  ObjectIdGetDatum(namespaceId));
2446  }
2447  else
2448  {
2449  /* search for it in search path */
2451 
2452  foreach(l, activeSearchPath)
2453  {
2454  namespaceId = lfirst_oid(l);
2455 
2456  if (namespaceId == myTempNamespace)
2457  continue; /* do not look in temp namespace */
2458 
2459  dictoid = GetSysCacheOid2(TSDICTNAMENSP, Anum_pg_ts_dict_oid,
2460  PointerGetDatum(dict_name),
2461  ObjectIdGetDatum(namespaceId));
2462  if (OidIsValid(dictoid))
2463  break;
2464  }
2465  }
2466 
2467  if (!OidIsValid(dictoid) && !missing_ok)
2468  ereport(ERROR,
2469  (errcode(ERRCODE_UNDEFINED_OBJECT),
2470  errmsg("text search dictionary \"%s\" does not exist",
2471  NameListToString(names))));
2472 
2473  return dictoid;
2474 }
2475 
2476 /*
2477  * TSDictionaryIsVisible
2478  * Determine whether a dictionary (identified by OID) is visible in the
2479  * current search path. Visible means "would be found by searching
2480  * for the unqualified dictionary name".
2481  */
2482 bool
2484 {
2485  HeapTuple tup;
2486  Form_pg_ts_dict form;
2487  Oid namespace;
2488  bool visible;
2489 
2490  tup = SearchSysCache1(TSDICTOID, ObjectIdGetDatum(dictId));
2491  if (!HeapTupleIsValid(tup))
2492  elog(ERROR, "cache lookup failed for text search dictionary %u",
2493  dictId);
2494  form = (Form_pg_ts_dict) GETSTRUCT(tup);
2495 
2497 
2498  /*
2499  * Quick check: if it ain't in the path at all, it ain't visible. Items in
2500  * the system namespace are surely in the path and so we needn't even do
2501  * list_member_oid() for them.
2502  */
2503  namespace = form->dictnamespace;
2504  if (namespace != PG_CATALOG_NAMESPACE &&
2505  !list_member_oid(activeSearchPath, namespace))
2506  visible = false;
2507  else
2508  {
2509  /*
2510  * If it is in the path, it might still not be visible; it could be
2511  * hidden by another dictionary of the same name earlier in the path.
2512  * So we must do a slow check for conflicting dictionaries.
2513  */
2514  char *name = NameStr(form->dictname);
2515  ListCell *l;
2516 
2517  visible = false;
2518  foreach(l, activeSearchPath)
2519  {
2520  Oid namespaceId = lfirst_oid(l);
2521 
2522  if (namespaceId == myTempNamespace)
2523  continue; /* do not look in temp namespace */
2524 
2525  if (namespaceId == namespace)
2526  {
2527  /* Found it first in path */
2528  visible = true;
2529  break;
2530  }
2532  PointerGetDatum(name),
2533  ObjectIdGetDatum(namespaceId)))
2534  {
2535  /* Found something else first in path */
2536  break;
2537  }
2538  }
2539  }
2540 
2541  ReleaseSysCache(tup);
2542 
2543  return visible;
2544 }
2545 
2546 /*
2547  * get_ts_template_oid - find a TS template by possibly qualified name
2548  *
2549  * If not found, returns InvalidOid if missing_ok, else throws error
2550  */
2551 Oid
2552 get_ts_template_oid(List *names, bool missing_ok)
2553 {
2554  char *schemaname;
2555  char *template_name;
2556  Oid namespaceId;
2557  Oid tmploid = InvalidOid;
2558  ListCell *l;
2559 
2560  /* deconstruct the name list */
2561  DeconstructQualifiedName(names, &schemaname, &template_name);
2562 
2563  if (schemaname)
2564  {
2565  /* use exact schema given */
2566  namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
2567  if (missing_ok && !OidIsValid(namespaceId))
2568  tmploid = InvalidOid;
2569  else
2570  tmploid = GetSysCacheOid2(TSTEMPLATENAMENSP, Anum_pg_ts_template_oid,
2571  PointerGetDatum(template_name),
2572  ObjectIdGetDatum(namespaceId));
2573  }
2574  else
2575  {
2576  /* search for it in search path */
2578 
2579  foreach(l, activeSearchPath)
2580  {
2581  namespaceId = lfirst_oid(l);
2582 
2583  if (namespaceId == myTempNamespace)
2584  continue; /* do not look in temp namespace */
2585 
2586  tmploid = GetSysCacheOid2(TSTEMPLATENAMENSP, Anum_pg_ts_template_oid,
2587  PointerGetDatum(template_name),
2588  ObjectIdGetDatum(namespaceId));
2589  if (OidIsValid(tmploid))
2590  break;
2591  }
2592  }
2593 
2594  if (!OidIsValid(tmploid) && !missing_ok)
2595  ereport(ERROR,
2596  (errcode(ERRCODE_UNDEFINED_OBJECT),
2597  errmsg("text search template \"%s\" does not exist",
2598  NameListToString(names))));
2599 
2600  return tmploid;
2601 }
2602 
2603 /*
2604  * TSTemplateIsVisible
2605  * Determine whether a template (identified by OID) is visible in the
2606  * current search path. Visible means "would be found by searching
2607  * for the unqualified template name".
2608  */
2609 bool
2611 {
2612  HeapTuple tup;
2613  Form_pg_ts_template form;
2614  Oid namespace;
2615  bool visible;
2616 
2618  if (!HeapTupleIsValid(tup))
2619  elog(ERROR, "cache lookup failed for text search template %u", tmplId);
2620  form = (Form_pg_ts_template) GETSTRUCT(tup);
2621 
2623 
2624  /*
2625  * Quick check: if it ain't in the path at all, it ain't visible. Items in
2626  * the system namespace are surely in the path and so we needn't even do
2627  * list_member_oid() for them.
2628  */
2629  namespace = form->tmplnamespace;
2630  if (namespace != PG_CATALOG_NAMESPACE &&
2631  !list_member_oid(activeSearchPath, namespace))
2632  visible = false;
2633  else
2634  {
2635  /*
2636  * If it is in the path, it might still not be visible; it could be
2637  * hidden by another template of the same name earlier in the path. So
2638  * we must do a slow check for conflicting templates.
2639  */
2640  char *name = NameStr(form->tmplname);
2641  ListCell *l;
2642 
2643  visible = false;
2644  foreach(l, activeSearchPath)
2645  {
2646  Oid namespaceId = lfirst_oid(l);
2647 
2648  if (namespaceId == myTempNamespace)
2649  continue; /* do not look in temp namespace */
2650 
2651  if (namespaceId == namespace)
2652  {
2653  /* Found it first in path */
2654  visible = true;
2655  break;
2656  }
2658  PointerGetDatum(name),
2659  ObjectIdGetDatum(namespaceId)))
2660  {
2661  /* Found something else first in path */
2662  break;
2663  }
2664  }
2665  }
2666 
2667  ReleaseSysCache(tup);
2668 
2669  return visible;
2670 }
2671 
2672 /*
2673  * get_ts_config_oid - find a TS config by possibly qualified name
2674  *
2675  * If not found, returns InvalidOid if missing_ok, else throws error
2676  */
2677 Oid
2678 get_ts_config_oid(List *names, bool missing_ok)
2679 {
2680  char *schemaname;
2681  char *config_name;
2682  Oid namespaceId;
2683  Oid cfgoid = InvalidOid;
2684  ListCell *l;
2685 
2686  /* deconstruct the name list */
2687  DeconstructQualifiedName(names, &schemaname, &config_name);
2688 
2689  if (schemaname)
2690  {
2691  /* use exact schema given */
2692  namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
2693  if (missing_ok && !OidIsValid(namespaceId))
2694  cfgoid = InvalidOid;
2695  else
2696  cfgoid = GetSysCacheOid2(TSCONFIGNAMENSP, Anum_pg_ts_config_oid,
2697  PointerGetDatum(config_name),
2698  ObjectIdGetDatum(namespaceId));
2699  }
2700  else
2701  {
2702  /* search for it in search path */
2704 
2705  foreach(l, activeSearchPath)
2706  {
2707  namespaceId = lfirst_oid(l);
2708 
2709  if (namespaceId == myTempNamespace)
2710  continue; /* do not look in temp namespace */
2711 
2712  cfgoid = GetSysCacheOid2(TSCONFIGNAMENSP, Anum_pg_ts_config_oid,
2713  PointerGetDatum(config_name),
2714  ObjectIdGetDatum(namespaceId));
2715  if (OidIsValid(cfgoid))
2716  break;
2717  }
2718  }
2719 
2720  if (!OidIsValid(cfgoid) && !missing_ok)
2721  ereport(ERROR,
2722  (errcode(ERRCODE_UNDEFINED_OBJECT),
2723  errmsg("text search configuration \"%s\" does not exist",
2724  NameListToString(names))));
2725 
2726  return cfgoid;
2727 }
2728 
2729 /*
2730  * TSConfigIsVisible
2731  * Determine whether a text search configuration (identified by OID)
2732  * is visible in the current search path. Visible means "would be found
2733  * by searching for the unqualified text search configuration name".
2734  */
2735 bool
2737 {
2738  HeapTuple tup;
2739  Form_pg_ts_config form;
2740  Oid namespace;
2741  bool visible;
2742 
2744  if (!HeapTupleIsValid(tup))
2745  elog(ERROR, "cache lookup failed for text search configuration %u",
2746  cfgid);
2747  form = (Form_pg_ts_config) GETSTRUCT(tup);
2748 
2750 
2751  /*
2752  * Quick check: if it ain't in the path at all, it ain't visible. Items in
2753  * the system namespace are surely in the path and so we needn't even do
2754  * list_member_oid() for them.
2755  */
2756  namespace = form->cfgnamespace;
2757  if (namespace != PG_CATALOG_NAMESPACE &&
2758  !list_member_oid(activeSearchPath, namespace))
2759  visible = false;
2760  else
2761  {
2762  /*
2763  * If it is in the path, it might still not be visible; it could be
2764  * hidden by another configuration of the same name earlier in the
2765  * path. So we must do a slow check for conflicting configurations.
2766  */
2767  char *name = NameStr(form->cfgname);
2768  ListCell *l;
2769 
2770  visible = false;
2771  foreach(l, activeSearchPath)
2772  {
2773  Oid namespaceId = lfirst_oid(l);
2774 
2775  if (namespaceId == myTempNamespace)
2776  continue; /* do not look in temp namespace */
2777 
2778  if (namespaceId == namespace)
2779  {
2780  /* Found it first in path */
2781  visible = true;
2782  break;
2783  }
2785  PointerGetDatum(name),
2786  ObjectIdGetDatum(namespaceId)))
2787  {
2788  /* Found something else first in path */
2789  break;
2790  }
2791  }
2792  }
2793 
2794  ReleaseSysCache(tup);
2795 
2796  return visible;
2797 }
2798 
2799 
2800 /*
2801  * DeconstructQualifiedName
2802  * Given a possibly-qualified name expressed as a list of String nodes,
2803  * extract the schema name and object name.
2804  *
2805  * *nspname_p is set to NULL if there is no explicit schema name.
2806  */
2807 void
2809  char **nspname_p,
2810  char **objname_p)
2811 {
2812  char *catalogname;
2813  char *schemaname = NULL;
2814  char *objname = NULL;
2815 
2816  switch (list_length(names))
2817  {
2818  case 1:
2819  objname = strVal(linitial(names));
2820  break;
2821  case 2:
2822  schemaname = strVal(linitial(names));
2823  objname = strVal(lsecond(names));
2824  break;
2825  case 3:
2826  catalogname = strVal(linitial(names));
2827  schemaname = strVal(lsecond(names));
2828  objname = strVal(lthird(names));
2829 
2830  /*
2831  * We check the catalog name and then ignore it.
2832  */
2833  if (strcmp(catalogname, get_database_name(MyDatabaseId)) != 0)
2834  ereport(ERROR,
2835  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2836  errmsg("cross-database references are not implemented: %s",
2837  NameListToString(names))));
2838  break;
2839  default:
2840  ereport(ERROR,
2841  (errcode(ERRCODE_SYNTAX_ERROR),
2842  errmsg("improper qualified name (too many dotted names): %s",
2843  NameListToString(names))));
2844  break;
2845  }
2846 
2847  *nspname_p = schemaname;
2848  *objname_p = objname;
2849 }
2850 
2851 /*
2852  * LookupNamespaceNoError
2853  * Look up a schema name.
2854  *
2855  * Returns the namespace OID, or InvalidOid if not found.
2856  *
2857  * Note this does NOT perform any permissions check --- callers are
2858  * responsible for being sure that an appropriate check is made.
2859  * In the majority of cases LookupExplicitNamespace is preferable.
2860  */
2861 Oid
2862 LookupNamespaceNoError(const char *nspname)
2863 {
2864  /* check for pg_temp alias */
2865  if (strcmp(nspname, "pg_temp") == 0)
2866  {
2868  {
2870  return myTempNamespace;
2871  }
2872 
2873  /*
2874  * Since this is used only for looking up existing objects, there is
2875  * no point in trying to initialize the temp namespace here; and doing
2876  * so might create problems for some callers. Just report "not found".
2877  */
2878  return InvalidOid;
2879  }
2880 
2881  return get_namespace_oid(nspname, true);
2882 }
2883 
2884 /*
2885  * LookupExplicitNamespace
2886  * Process an explicitly-specified schema name: look up the schema
2887  * and verify we have USAGE (lookup) rights in it.
2888  *
2889  * Returns the namespace OID
2890  */
2891 Oid
2892 LookupExplicitNamespace(const char *nspname, bool missing_ok)
2893 {
2894  Oid namespaceId;
2895  AclResult aclresult;
2896 
2897  /* check for pg_temp alias */
2898  if (strcmp(nspname, "pg_temp") == 0)
2899  {
2901  return myTempNamespace;
2902 
2903  /*
2904  * Since this is used only for looking up existing objects, there is
2905  * no point in trying to initialize the temp namespace here; and doing
2906  * so might create problems for some callers --- just fall through.
2907  */
2908  }
2909 
2910  namespaceId = get_namespace_oid(nspname, missing_ok);
2911  if (missing_ok && !OidIsValid(namespaceId))
2912  return InvalidOid;
2913 
2914  aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_USAGE);
2915  if (aclresult != ACLCHECK_OK)
2916  aclcheck_error(aclresult, OBJECT_SCHEMA,
2917  nspname);
2918  /* Schema search hook for this lookup */
2919  InvokeNamespaceSearchHook(namespaceId, true);
2920 
2921  return namespaceId;
2922 }
2923 
2924 /*
2925  * LookupCreationNamespace
2926  * Look up the schema and verify we have CREATE rights on it.
2927  *
2928  * This is just like LookupExplicitNamespace except for the different
2929  * permission check, and that we are willing to create pg_temp if needed.
2930  *
2931  * Note: calling this may result in a CommandCounterIncrement operation,
2932  * if we have to create or clean out the temp namespace.
2933  */
2934 Oid
2935 LookupCreationNamespace(const char *nspname)
2936 {
2937  Oid namespaceId;
2938  AclResult aclresult;
2939 
2940  /* check for pg_temp alias */
2941  if (strcmp(nspname, "pg_temp") == 0)
2942  {
2943  /* Initialize temp namespace */
2944  AccessTempTableNamespace(false);
2945  return myTempNamespace;
2946  }
2947 
2948  namespaceId = get_namespace_oid(nspname, false);
2949 
2950  aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_CREATE);
2951  if (aclresult != ACLCHECK_OK)
2952  aclcheck_error(aclresult, OBJECT_SCHEMA,
2953  nspname);
2954 
2955  return namespaceId;
2956 }
2957 
2958 /*
2959  * Common checks on switching namespaces.
2960  *
2961  * We complain if either the old or new namespaces is a temporary schema
2962  * (or temporary toast schema), or if either the old or new namespaces is the
2963  * TOAST schema.
2964  */
2965 void
2966 CheckSetNamespace(Oid oldNspOid, Oid nspOid)
2967 {
2968  /* disallow renaming into or out of temp schemas */
2969  if (isAnyTempNamespace(nspOid) || isAnyTempNamespace(oldNspOid))
2970  ereport(ERROR,
2971  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2972  errmsg("cannot move objects into or out of temporary schemas")));
2973 
2974  /* same for TOAST schema */
2975  if (nspOid == PG_TOAST_NAMESPACE || oldNspOid == PG_TOAST_NAMESPACE)
2976  ereport(ERROR,
2977  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2978  errmsg("cannot move objects into or out of TOAST schema")));
2979 }
2980 
2981 /*
2982  * QualifiedNameGetCreationNamespace
2983  * Given a possibly-qualified name for an object (in List-of-Values
2984  * format), determine what namespace the object should be created in.
2985  * Also extract and return the object name (last component of list).
2986  *
2987  * Note: this does not apply any permissions check. Callers must check
2988  * for CREATE rights on the selected namespace when appropriate.
2989  *
2990  * Note: calling this may result in a CommandCounterIncrement operation,
2991  * if we have to create or clean out the temp namespace.
2992  */
2993 Oid
2994 QualifiedNameGetCreationNamespace(List *names, char **objname_p)
2995 {
2996  char *schemaname;
2997  Oid namespaceId;
2998 
2999  /* deconstruct the name list */
3000  DeconstructQualifiedName(names, &schemaname, objname_p);
3001 
3002  if (schemaname)
3003  {
3004  /* check for pg_temp alias */
3005  if (strcmp(schemaname, "pg_temp") == 0)
3006  {
3007  /* Initialize temp namespace */
3008  AccessTempTableNamespace(false);
3009  return myTempNamespace;
3010  }
3011  /* use exact schema given */
3012  namespaceId = get_namespace_oid(schemaname, false);
3013  /* we do not check for USAGE rights here! */
3014  }
3015  else
3016  {
3017  /* use the default creation namespace */
3020  {
3021  /* Need to initialize temp namespace */
3023  return myTempNamespace;
3024  }
3025  namespaceId = activeCreationNamespace;
3026  if (!OidIsValid(namespaceId))
3027  ereport(ERROR,
3028  (errcode(ERRCODE_UNDEFINED_SCHEMA),
3029  errmsg("no schema has been selected to create in")));
3030  }
3031 
3032  return namespaceId;
3033 }
3034 
3035 /*
3036  * get_namespace_oid - given a namespace name, look up the OID
3037  *
3038  * If missing_ok is false, throw an error if namespace name not found. If
3039  * true, just return InvalidOid.
3040  */
3041 Oid
3042 get_namespace_oid(const char *nspname, bool missing_ok)
3043 {
3044  Oid oid;
3045 
3046  oid = GetSysCacheOid1(NAMESPACENAME, Anum_pg_namespace_oid,
3047  CStringGetDatum(nspname));
3048  if (!OidIsValid(oid) && !missing_ok)
3049  ereport(ERROR,
3050  (errcode(ERRCODE_UNDEFINED_SCHEMA),
3051  errmsg("schema \"%s\" does not exist", nspname)));
3052 
3053  return oid;
3054 }
3055 
3056 /*
3057  * makeRangeVarFromNameList
3058  * Utility routine to convert a qualified-name list into RangeVar form.
3059  */
3060 RangeVar *
3062 {
3063  RangeVar *rel = makeRangeVar(NULL, NULL, -1);
3064 
3065  switch (list_length(names))
3066  {
3067  case 1:
3068  rel->relname = strVal(linitial(names));
3069  break;
3070  case 2:
3071  rel->schemaname = strVal(linitial(names));
3072  rel->relname = strVal(lsecond(names));
3073  break;
3074  case 3:
3075  rel->catalogname = strVal(linitial(names));
3076  rel->schemaname = strVal(lsecond(names));
3077  rel->relname = strVal(lthird(names));
3078  break;
3079  default:
3080  ereport(ERROR,
3081  (errcode(ERRCODE_SYNTAX_ERROR),
3082  errmsg("improper relation name (too many dotted names): %s",
3083  NameListToString(names))));
3084  break;
3085  }
3086 
3087  return rel;
3088 }
3089 
3090 /*
3091  * NameListToString
3092  * Utility routine to convert a qualified-name list into a string.
3093  *
3094  * This is used primarily to form error messages, and so we do not quote
3095  * the list elements, for the sake of legibility.
3096  *
3097  * In most scenarios the list elements should always be Value strings,
3098  * but we also allow A_Star for the convenience of ColumnRef processing.
3099  */
3100 char *
3102 {
3104  ListCell *l;
3105 
3106  initStringInfo(&string);
3107 
3108  foreach(l, names)
3109  {
3110  Node *name = (Node *) lfirst(l);
3111 
3112  if (l != list_head(names))
3113  appendStringInfoChar(&string, '.');
3114 
3115  if (IsA(name, String))
3116  appendStringInfoString(&string, strVal(name));
3117  else if (IsA(name, A_Star))
3118  appendStringInfoChar(&string, '*');
3119  else
3120  elog(ERROR, "unexpected node type in name list: %d",
3121  (int) nodeTag(name));
3122  }
3123 
3124  return string.data;
3125 }
3126 
3127 /*
3128  * NameListToQuotedString
3129  * Utility routine to convert a qualified-name list into a string.
3130  *
3131  * Same as above except that names will be double-quoted where necessary,
3132  * so the string could be re-parsed (eg, by textToQualifiedNameList).
3133  */
3134 char *
3136 {
3138  ListCell *l;
3139 
3140  initStringInfo(&string);
3141 
3142  foreach(l, names)
3143  {
3144  if (l != list_head(names))
3145  appendStringInfoChar(&string, '.');
3147  }
3148 
3149  return string.data;
3150 }
3151 
3152 /*
3153  * isTempNamespace - is the given namespace my temporary-table namespace?
3154  */
3155 bool
3156 isTempNamespace(Oid namespaceId)
3157 {
3158  if (OidIsValid(myTempNamespace) && myTempNamespace == namespaceId)
3159  return true;
3160  return false;
3161 }
3162 
3163 /*
3164  * isTempToastNamespace - is the given namespace my temporary-toast-table
3165  * namespace?
3166  */
3167 bool
3169 {
3170  if (OidIsValid(myTempToastNamespace) && myTempToastNamespace == namespaceId)
3171  return true;
3172  return false;
3173 }
3174 
3175 /*
3176  * isTempOrTempToastNamespace - is the given namespace my temporary-table
3177  * namespace or my temporary-toast-table namespace?
3178  */
3179 bool
3181 {
3182  if (OidIsValid(myTempNamespace) &&
3183  (myTempNamespace == namespaceId || myTempToastNamespace == namespaceId))
3184  return true;
3185  return false;
3186 }
3187 
3188 /*
3189  * isAnyTempNamespace - is the given namespace a temporary-table namespace
3190  * (either my own, or another backend's)? Temporary-toast-table namespaces
3191  * are included, too.
3192  */
3193 bool
3195 {
3196  bool result;
3197  char *nspname;
3198 
3199  /* True if the namespace name starts with "pg_temp_" or "pg_toast_temp_" */
3200  nspname = get_namespace_name(namespaceId);
3201  if (!nspname)
3202  return false; /* no such namespace? */
3203  result = (strncmp(nspname, "pg_temp_", 8) == 0) ||
3204  (strncmp(nspname, "pg_toast_temp_", 14) == 0);
3205  pfree(nspname);
3206  return result;
3207 }
3208 
3209 /*
3210  * isOtherTempNamespace - is the given namespace some other backend's
3211  * temporary-table namespace (including temporary-toast-table namespaces)?
3212  *
3213  * Note: for most purposes in the C code, this function is obsolete. Use
3214  * RELATION_IS_OTHER_TEMP() instead to detect non-local temp relations.
3215  */
3216 bool
3218 {
3219  /* If it's my own temp namespace, say "false" */
3220  if (isTempOrTempToastNamespace(namespaceId))
3221  return false;
3222  /* Else, if it's any temp namespace, say "true" */
3223  return isAnyTempNamespace(namespaceId);
3224 }
3225 
3226 /*
3227  * checkTempNamespaceStatus - is the given namespace owned and actively used
3228  * by a backend?
3229  *
3230  * Note: this can be used while scanning relations in pg_class to detect
3231  * orphaned temporary tables or namespaces with a backend connected to a
3232  * given database. The result may be out of date quickly, so the caller
3233  * must be careful how to handle this information.
3234  */
3237 {
3238  PGPROC *proc;
3239  int backendId;
3240 
3242 
3243  backendId = GetTempNamespaceBackendId(namespaceId);
3244 
3245  /* No such namespace, or its name shows it's not temp? */
3246  if (backendId == InvalidBackendId)
3247  return TEMP_NAMESPACE_NOT_TEMP;
3248 
3249  /* Is the backend alive? */
3250  proc = BackendIdGetProc(backendId);
3251  if (proc == NULL)
3252  return TEMP_NAMESPACE_IDLE;
3253 
3254  /* Is the backend connected to the same database we are looking at? */
3255  if (proc->databaseId != MyDatabaseId)
3256  return TEMP_NAMESPACE_IDLE;
3257 
3258  /* Does the backend own the temporary namespace? */
3259  if (proc->tempNamespaceId != namespaceId)
3260  return TEMP_NAMESPACE_IDLE;
3261 
3262  /* Yup, so namespace is busy */
3263  return TEMP_NAMESPACE_IN_USE;
3264 }
3265 
3266 /*
3267  * GetTempNamespaceBackendId - if the given namespace is a temporary-table
3268  * namespace (either my own, or another backend's), return the BackendId
3269  * that owns it. Temporary-toast-table namespaces are included, too.
3270  * If it isn't a temp namespace, return InvalidBackendId.
3271  */
3272 int
3274 {
3275  int result;
3276  char *nspname;
3277 
3278  /* See if the namespace name starts with "pg_temp_" or "pg_toast_temp_" */
3279  nspname = get_namespace_name(namespaceId);
3280  if (!nspname)
3281  return InvalidBackendId; /* no such namespace? */
3282  if (strncmp(nspname, "pg_temp_", 8) == 0)
3283  result = atoi(nspname + 8);
3284  else if (strncmp(nspname, "pg_toast_temp_", 14) == 0)
3285  result = atoi(nspname + 14);
3286  else
3287  result = InvalidBackendId;
3288  pfree(nspname);
3289  return result;
3290 }
3291 
3292 /*
3293  * GetTempToastNamespace - get the OID of my temporary-toast-table namespace,
3294  * which must already be assigned. (This is only used when creating a toast
3295  * table for a temp table, so we must have already done InitTempTableNamespace)
3296  */
3297 Oid
3299 {
3301  return myTempToastNamespace;
3302 }
3303 
3304 
3305 /*
3306  * GetTempNamespaceState - fetch status of session's temporary namespace
3307  *
3308  * This is used for conveying state to a parallel worker, and is not meant
3309  * for general-purpose access.
3310  */
3311 void
3312 GetTempNamespaceState(Oid *tempNamespaceId, Oid *tempToastNamespaceId)
3313 {
3314  /* Return namespace OIDs, or 0 if session has not created temp namespace */
3315  *tempNamespaceId = myTempNamespace;
3316  *tempToastNamespaceId = myTempToastNamespace;
3317 }
3318 
3319 /*
3320  * SetTempNamespaceState - set status of session's temporary namespace
3321  *
3322  * This is used for conveying state to a parallel worker, and is not meant for
3323  * general-purpose access. By transferring these namespace OIDs to workers,
3324  * we ensure they will have the same notion of the search path as their leader
3325  * does.
3326  */
3327 void
3328 SetTempNamespaceState(Oid tempNamespaceId, Oid tempToastNamespaceId)
3329 {
3330  /* Worker should not have created its own namespaces ... */
3334 
3335  /* Assign same namespace OIDs that leader has */
3336  myTempNamespace = tempNamespaceId;
3337  myTempToastNamespace = tempToastNamespaceId;
3338 
3339  /*
3340  * It's fine to leave myTempNamespaceSubID == InvalidSubTransactionId.
3341  * Even if the namespace is new so far as the leader is concerned, it's
3342  * not new to the worker, and we certainly wouldn't want the worker trying
3343  * to destroy it.
3344  */
3345 
3346  baseSearchPathValid = false; /* may need to rebuild list */
3347 }
3348 
3349 
3350 /*
3351  * GetOverrideSearchPath - fetch current search path definition in form
3352  * used by PushOverrideSearchPath.
3353  *
3354  * The result structure is allocated in the specified memory context
3355  * (which might or might not be equal to CurrentMemoryContext); but any
3356  * junk created by revalidation calculations will be in CurrentMemoryContext.
3357  */
3360 {
3361  OverrideSearchPath *result;
3362  List *schemas;
3363  MemoryContext oldcxt;
3364 
3366 
3367  oldcxt = MemoryContextSwitchTo(context);
3368 
3369  result = (OverrideSearchPath *) palloc0(sizeof(OverrideSearchPath));
3370  schemas = list_copy(activeSearchPath);
3371  while (schemas && linitial_oid(schemas) != activeCreationNamespace)
3372  {
3373  if (linitial_oid(schemas) == myTempNamespace)
3374  result->addTemp = true;
3375  else
3376  {
3377  Assert(linitial_oid(schemas) == PG_CATALOG_NAMESPACE);
3378  result->addCatalog = true;
3379  }
3380  schemas = list_delete_first(schemas);
3381  }
3382  result->schemas = schemas;
3383  result->generation = activePathGeneration;
3384 
3385  MemoryContextSwitchTo(oldcxt);
3386 
3387  return result;
3388 }
3389 
3390 /*
3391  * CopyOverrideSearchPath - copy the specified OverrideSearchPath.
3392  *
3393  * The result structure is allocated in CurrentMemoryContext.
3394  */
3397 {
3398  OverrideSearchPath *result;
3399 
3400  result = (OverrideSearchPath *) palloc(sizeof(OverrideSearchPath));
3401  result->schemas = list_copy(path->schemas);
3402  result->addCatalog = path->addCatalog;
3403  result->addTemp = path->addTemp;
3404  result->generation = path->generation;
3405 
3406  return result;
3407 }
3408 
3409 /*
3410  * OverrideSearchPathMatchesCurrent - does path match current setting?
3411  *
3412  * This is tested over and over in some common code paths, and in the typical
3413  * scenario where the active search path seldom changes, it'll always succeed.
3414  * We make that case fast by keeping a generation counter that is advanced
3415  * whenever the active search path changes.
3416  */
3417 bool
3419 {
3420  ListCell *lc,
3421  *lcp;
3422 
3424 
3425  /* Quick out if already known equal to active path. */
3426  if (path->generation == activePathGeneration)
3427  return true;
3428 
3429  /* We scan down the activeSearchPath to see if it matches the input. */
3430  lc = list_head(activeSearchPath);
3431 
3432  /* If path->addTemp, first item should be my temp namespace. */
3433  if (path->addTemp)
3434  {
3435  if (lc && lfirst_oid(lc) == myTempNamespace)
3436  lc = lnext(activeSearchPath, lc);
3437  else
3438  return false;
3439  }
3440  /* If path->addCatalog, next item should be pg_catalog. */
3441  if (path->addCatalog)
3442  {
3443  if (lc && lfirst_oid(lc) == PG_CATALOG_NAMESPACE)
3444  lc = lnext(activeSearchPath, lc);
3445  else
3446  return false;
3447  }
3448  /* We should now be looking at the activeCreationNamespace. */
3449  if (activeCreationNamespace != (lc ? lfirst_oid(lc) : InvalidOid))
3450  return false;
3451  /* The remainder of activeSearchPath should match path->schemas. */
3452  foreach(lcp, path->schemas)
3453  {
3454  if (lc && lfirst_oid(lc) == lfirst_oid(lcp))
3455  lc = lnext(activeSearchPath, lc);
3456  else
3457  return false;
3458  }
3459  if (lc)
3460  return false;
3461 
3462  /*
3463  * Update path->generation so that future tests will return quickly, so
3464  * long as the active search path doesn't change.
3465  */
3467 
3468  return true;
3469 }
3470 
3471 /*
3472  * PushOverrideSearchPath - temporarily override the search path
3473  *
3474  * We allow nested overrides, hence the push/pop terminology. The GUC
3475  * search_path variable is ignored while an override is active.
3476  *
3477  * It's possible that newpath->useTemp is set but there is no longer any
3478  * active temp namespace, if the path was saved during a transaction that
3479  * created a temp namespace and was later rolled back. In that case we just
3480  * ignore useTemp. A plausible alternative would be to create a new temp
3481  * namespace, but for existing callers that's not necessary because an empty
3482  * temp namespace wouldn't affect their results anyway.
3483  *
3484  * It's also worth noting that other schemas listed in newpath might not
3485  * exist anymore either. We don't worry about this because OIDs that match
3486  * no existing namespace will simply not produce any hits during searches.
3487  */
3488 void
3490 {
3491  OverrideStackEntry *entry;
3492  List *oidlist;
3493  Oid firstNS;
3494  MemoryContext oldcxt;
3495 
3496  /*
3497  * Copy the list for safekeeping, and insert implicitly-searched
3498  * namespaces as needed. This code should track recomputeNamespacePath.
3499  */
3501 
3502  oidlist = list_copy(newpath->schemas);
3503 
3504  /*
3505  * Remember the first member of the explicit list.
3506  */
3507  if (oidlist == NIL)
3508  firstNS = InvalidOid;
3509  else
3510  firstNS = linitial_oid(oidlist);
3511 
3512  /*
3513  * Add any implicitly-searched namespaces to the list. Note these go on
3514  * the front, not the back; also notice that we do not check USAGE
3515  * permissions for these.
3516  */
3517  if (newpath->addCatalog)
3518  oidlist = lcons_oid(PG_CATALOG_NAMESPACE, oidlist);
3519 
3520  if (newpath->addTemp && OidIsValid(myTempNamespace))
3521  oidlist = lcons_oid(myTempNamespace, oidlist);
3522 
3523  /*
3524  * Build the new stack entry, then insert it at the head of the list.
3525  */
3526  entry = (OverrideStackEntry *) palloc(sizeof(OverrideStackEntry));
3527  entry->searchPath = oidlist;
3528  entry->creationNamespace = firstNS;
3530 
3531  overrideStack = lcons(entry, overrideStack);
3532 
3533  /* And make it active. */
3534  activeSearchPath = entry->searchPath;
3536  activeTempCreationPending = false; /* XXX is this OK? */
3537 
3538  /*
3539  * We always increment activePathGeneration when pushing/popping an
3540  * override path. In current usage, these actions always change the
3541  * effective path state, so there's no value in checking to see if it
3542  * didn't change.
3543  */
3545 
3546  MemoryContextSwitchTo(oldcxt);
3547 }
3548 
3549 /*
3550  * PopOverrideSearchPath - undo a previous PushOverrideSearchPath
3551  *
3552  * Any push during a (sub)transaction will be popped automatically at abort.
3553  * But it's caller error if a push isn't popped in normal control flow.
3554  */
3555 void
3557 {
3558  OverrideStackEntry *entry;
3559 
3560  /* Sanity checks. */
3561  if (overrideStack == NIL)
3562  elog(ERROR, "bogus PopOverrideSearchPath call");
3563  entry = (OverrideStackEntry *) linitial(overrideStack);
3564  if (entry->nestLevel != GetCurrentTransactionNestLevel())
3565  elog(ERROR, "bogus PopOverrideSearchPath call");
3566 
3567  /* Pop the stack and free storage. */
3568  overrideStack = list_delete_first(overrideStack);
3569  list_free(entry->searchPath);
3570  pfree(entry);
3571 
3572  /* Activate the next level down. */
3573  if (overrideStack)
3574  {
3575  entry = (OverrideStackEntry *) linitial(overrideStack);
3576  activeSearchPath = entry->searchPath;
3578  activeTempCreationPending = false; /* XXX is this OK? */
3579  }
3580  else
3581  {
3582  /* If not baseSearchPathValid, this is useless but harmless */
3583  activeSearchPath = baseSearchPath;
3586  }
3587 
3588  /* As above, the generation always increments. */
3590 }
3591 
3592 
3593 /*
3594  * get_collation_oid - find a collation by possibly qualified name
3595  *
3596  * Note that this will only find collations that work with the current
3597  * database's encoding.
3598  */
3599 Oid
3600 get_collation_oid(List *name, bool missing_ok)
3601 {
3602  char *schemaname;
3603  char *collation_name;
3604  int32 dbencoding = GetDatabaseEncoding();
3605  Oid namespaceId;
3606  Oid colloid;
3607  ListCell *l;
3608 
3609  /* deconstruct the name list */
3610  DeconstructQualifiedName(name, &schemaname, &collation_name);
3611 
3612  if (schemaname)
3613  {
3614  /* use exact schema given */
3615  namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
3616  if (missing_ok && !OidIsValid(namespaceId))
3617  return InvalidOid;
3618 
3619  colloid = lookup_collation(collation_name, namespaceId, dbencoding);
3620  if (OidIsValid(colloid))
3621  return colloid;
3622  }
3623  else
3624  {
3625  /* search for it in search path */
3627 
3628  foreach(l, activeSearchPath)
3629  {
3630  namespaceId = lfirst_oid(l);
3631 
3632  if (namespaceId == myTempNamespace)
3633  continue; /* do not look in temp namespace */
3634 
3635  colloid = lookup_collation(collation_name, namespaceId, dbencoding);
3636  if (OidIsValid(colloid))
3637  return colloid;
3638  }
3639  }
3640 
3641  /* Not found in path */
3642  if (!missing_ok)
3643  ereport(ERROR,
3644  (errcode(ERRCODE_UNDEFINED_OBJECT),
3645  errmsg("collation \"%s\" for encoding \"%s\" does not exist",
3647  return InvalidOid;
3648 }
3649 
3650 /*
3651  * get_conversion_oid - find a conversion by possibly qualified name
3652  */
3653 Oid
3654 get_conversion_oid(List *name, bool missing_ok)
3655 {
3656  char *schemaname;
3657  char *conversion_name;
3658  Oid namespaceId;
3659  Oid conoid = InvalidOid;
3660  ListCell *l;
3661 
3662  /* deconstruct the name list */
3663  DeconstructQualifiedName(name, &schemaname, &conversion_name);
3664 
3665  if (schemaname)
3666  {
3667  /* use exact schema given */
3668  namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
3669  if (missing_ok && !OidIsValid(namespaceId))
3670  conoid = InvalidOid;
3671  else
3672  conoid = GetSysCacheOid2(CONNAMENSP, Anum_pg_conversion_oid,
3673  PointerGetDatum(conversion_name),
3674  ObjectIdGetDatum(namespaceId));
3675  }
3676  else
3677  {
3678  /* search for it in search path */
3680 
3681  foreach(l, activeSearchPath)
3682  {
3683  namespaceId = lfirst_oid(l);
3684 
3685  if (namespaceId == myTempNamespace)
3686  continue; /* do not look in temp namespace */
3687 
3688  conoid = GetSysCacheOid2(CONNAMENSP, Anum_pg_conversion_oid,
3689  PointerGetDatum(conversion_name),
3690  ObjectIdGetDatum(namespaceId));
3691  if (OidIsValid(conoid))
3692  return conoid;
3693  }
3694  }
3695 
3696  /* Not found in path */
3697  if (!OidIsValid(conoid) && !missing_ok)
3698  ereport(ERROR,
3699  (errcode(ERRCODE_UNDEFINED_OBJECT),
3700  errmsg("conversion \"%s\" does not exist",
3701  NameListToString(name))));
3702  return conoid;
3703 }
3704 
3705 /*
3706  * FindDefaultConversionProc - find default encoding conversion proc
3707  */
3708 Oid
3709 FindDefaultConversionProc(int32 for_encoding, int32 to_encoding)
3710 {
3711  Oid proc;
3712  ListCell *l;
3713 
3715 
3716  foreach(l, activeSearchPath)
3717  {
3718  Oid namespaceId = lfirst_oid(l);
3719 
3720  if (namespaceId == myTempNamespace)
3721  continue; /* do not look in temp namespace */
3722 
3723  proc = FindDefaultConversion(namespaceId, for_encoding, to_encoding);
3724  if (OidIsValid(proc))
3725  return proc;
3726  }
3727 
3728  /* Not found in path */
3729  return InvalidOid;
3730 }
3731 
3732 /*
3733  * recomputeNamespacePath - recompute path derived variables if needed.
3734  */
3735 static void
3737 {
3738  Oid roleid = GetUserId();
3739  char *rawname;
3740  List *namelist;
3741  List *oidlist;
3742  List *newpath;
3743  ListCell *l;
3744  bool temp_missing;
3745  Oid firstNS;
3746  bool pathChanged;
3747  MemoryContext oldcxt;
3748 
3749  /* Do nothing if an override search spec is active. */
3750  if (overrideStack)
3751  return;
3752 
3753  /* Do nothing if path is already valid. */
3754  if (baseSearchPathValid && namespaceUser == roleid)
3755  return;
3756 
3757  /* Need a modifiable copy of namespace_search_path string */
3758  rawname = pstrdup(namespace_search_path);
3759 
3760  /* Parse string into list of identifiers */
3761  if (!SplitIdentifierString(rawname, ',', &namelist))
3762  {
3763  /* syntax error in name list */
3764  /* this should not happen if GUC checked check_search_path */
3765  elog(ERROR, "invalid list syntax");
3766  }
3767 
3768  /*
3769  * Convert the list of names to a list of OIDs. If any names are not
3770  * recognizable or we don't have read access, just leave them out of the
3771  * list. (We can't raise an error, since the search_path setting has
3772  * already been accepted.) Don't make duplicate entries, either.
3773  */
3774  oidlist = NIL;
3775  temp_missing = false;
3776  foreach(l, namelist)
3777  {
3778  char *curname = (char *) lfirst(l);
3779  Oid namespaceId;
3780 
3781  if (strcmp(curname, "$user") == 0)
3782  {
3783  /* $user --- substitute namespace matching user name, if any */
3784  HeapTuple tuple;
3785 
3786  tuple = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
3787  if (HeapTupleIsValid(tuple))
3788  {
3789  char *rname;
3790 
3791  rname = NameStr(((Form_pg_authid) GETSTRUCT(tuple))->rolname);
3792  namespaceId = get_namespace_oid(rname, true);
3793  ReleaseSysCache(tuple);
3794  if (OidIsValid(namespaceId) &&
3795  !list_member_oid(oidlist, namespaceId) &&
3796  pg_namespace_aclcheck(namespaceId, roleid,
3797  ACL_USAGE) == ACLCHECK_OK &&
3798  InvokeNamespaceSearchHook(namespaceId, false))
3799  oidlist = lappend_oid(oidlist, namespaceId);
3800  }
3801  }
3802  else if (strcmp(curname, "pg_temp") == 0)
3803  {
3804  /* pg_temp --- substitute temp namespace, if any */
3806  {
3807  if (!list_member_oid(oidlist, myTempNamespace) &&
3809  oidlist = lappend_oid(oidlist, myTempNamespace);
3810  }
3811  else
3812  {
3813  /* If it ought to be the creation namespace, set flag */
3814  if (oidlist == NIL)
3815  temp_missing = true;
3816  }
3817  }
3818  else
3819  {
3820  /* normal namespace reference */
3821  namespaceId = get_namespace_oid(curname, true);
3822  if (OidIsValid(namespaceId) &&
3823  !list_member_oid(oidlist, namespaceId) &&
3824  pg_namespace_aclcheck(namespaceId, roleid,
3825  ACL_USAGE) == ACLCHECK_OK &&
3826  InvokeNamespaceSearchHook(namespaceId, false))
3827  oidlist = lappend_oid(oidlist, namespaceId);
3828  }
3829  }
3830 
3831  /*
3832  * Remember the first member of the explicit list. (Note: this is
3833  * nominally wrong if temp_missing, but we need it anyway to distinguish
3834  * explicit from implicit mention of pg_catalog.)
3835  */
3836  if (oidlist == NIL)
3837  firstNS = InvalidOid;
3838  else
3839  firstNS = linitial_oid(oidlist);
3840 
3841  /*
3842  * Add any implicitly-searched namespaces to the list. Note these go on
3843  * the front, not the back; also notice that we do not check USAGE
3844  * permissions for these.
3845  */
3846  if (!list_member_oid(oidlist, PG_CATALOG_NAMESPACE))
3847  oidlist = lcons_oid(PG_CATALOG_NAMESPACE, oidlist);
3848 
3849  if (OidIsValid(myTempNamespace) &&
3850  !list_member_oid(oidlist, myTempNamespace))
3851  oidlist = lcons_oid(myTempNamespace, oidlist);
3852 
3853  /*
3854  * We want to detect the case where the effective value of the base search
3855  * path variables didn't change. As long as we're doing so, we can avoid
3856  * copying the OID list unncessarily.
3857  */
3858  if (baseCreationNamespace == firstNS &&
3859  baseTempCreationPending == temp_missing &&
3860  equal(oidlist, baseSearchPath))
3861  {
3862  pathChanged = false;
3863  }
3864  else
3865  {
3866  pathChanged = true;
3867 
3868  /* Must save OID list in permanent storage. */
3870  newpath = list_copy(oidlist);
3871  MemoryContextSwitchTo(oldcxt);
3872 
3873  /* Now safe to assign to state variables. */
3874  list_free(baseSearchPath);
3875  baseSearchPath = newpath;
3876  baseCreationNamespace = firstNS;
3877  baseTempCreationPending = temp_missing;
3878  }
3879 
3880  /* Mark the path valid. */
3881  baseSearchPathValid = true;
3882  namespaceUser = roleid;
3883 
3884  /* And make it active. */
3885  activeSearchPath = baseSearchPath;
3888 
3889  /*
3890  * Bump the generation only if something actually changed. (Notice that
3891  * what we compared to was the old state of the base path variables; so
3892  * this does not deal with the situation where we have just popped an
3893  * override path and restored the prior state of the base path. Instead
3894  * we rely on the override-popping logic to have bumped the generation.)
3895  */
3896  if (pathChanged)
3898 
3899  /* Clean up. */
3900  pfree(rawname);
3901  list_free(namelist);
3902  list_free(oidlist);
3903 }
3904 
3905 /*
3906  * AccessTempTableNamespace
3907  * Provide access to a temporary namespace, potentially creating it
3908  * if not present yet. This routine registers if the namespace gets
3909  * in use in this transaction. 'force' can be set to true to allow
3910  * the caller to enforce the creation of the temporary namespace for
3911  * use in this backend, which happens if its creation is pending.
3912  */
3913 static void
3915 {
3916  /*
3917  * Make note that this temporary namespace has been accessed in this
3918  * transaction.
3919  */
3921 
3922  /*
3923  * If the caller attempting to access a temporary schema expects the
3924  * creation of the namespace to be pending and should be enforced, then go
3925  * through the creation.
3926  */
3927  if (!force && OidIsValid(myTempNamespace))
3928  return;
3929 
3930  /*
3931  * The temporary tablespace does not exist yet and is wanted, so
3932  * initialize it.
3933  */
3935 }
3936 
3937 /*
3938  * InitTempTableNamespace
3939  * Initialize temp table namespace on first use in a particular backend
3940  */
3941 static void
3943 {
3944  char namespaceName[NAMEDATALEN];
3945  Oid namespaceId;
3946  Oid toastspaceId;
3947 
3949 
3950  /*
3951  * First, do permission check to see if we are authorized to make temp
3952  * tables. We use a nonstandard error message here since "databasename:
3953  * permission denied" might be a tad cryptic.
3954  *
3955  * Note that ACL_CREATE_TEMP rights are rechecked in pg_namespace_aclmask;
3956  * that's necessary since current user ID could change during the session.
3957  * But there's no need to make the namespace in the first place until a
3958  * temp table creation request is made by someone with appropriate rights.
3959  */
3962  ereport(ERROR,
3963  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3964  errmsg("permission denied to create temporary tables in database \"%s\"",
3966 
3967  /*
3968  * Do not allow a Hot Standby session to make temp tables. Aside from
3969  * problems with modifying the system catalogs, there is a naming
3970  * conflict: pg_temp_N belongs to the session with BackendId N on the
3971  * primary, not to a hot standby session with the same BackendId. We
3972  * should not be able to get here anyway due to XactReadOnly checks, but
3973  * let's just make real sure. Note that this also backstops various
3974  * operations that allow XactReadOnly transactions to modify temp tables;
3975  * they'd need RecoveryInProgress checks if not for this.
3976  */
3977  if (RecoveryInProgress())
3978  ereport(ERROR,
3979  (errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION),
3980  errmsg("cannot create temporary tables during recovery")));
3981 
3982  /* Parallel workers can't create temporary tables, either. */
3983  if (IsParallelWorker())
3984  ereport(ERROR,
3985  (errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION),
3986  errmsg("cannot create temporary tables during a parallel operation")));
3987 
3988  snprintf(namespaceName, sizeof(namespaceName), "pg_temp_%d", MyBackendId);
3989 
3990  namespaceId = get_namespace_oid(namespaceName, true);
3991  if (!OidIsValid(namespaceId))
3992  {
3993  /*
3994  * First use of this temp namespace in this database; create it. The
3995  * temp namespaces are always owned by the superuser. We leave their
3996  * permissions at default --- i.e., no access except to superuser ---
3997  * to ensure that unprivileged users can't peek at other backends'
3998  * temp tables. This works because the places that access the temp
3999  * namespace for my own backend skip permissions checks on it.
4000  */
4001  namespaceId = NamespaceCreate(namespaceName, BOOTSTRAP_SUPERUSERID,
4002  true);
4003  /* Advance command counter to make namespace visible */
4005  }
4006  else
4007  {
4008  /*
4009  * If the namespace already exists, clean it out (in case the former
4010  * owner crashed without doing so).
4011  */
4012  RemoveTempRelations(namespaceId);
4013  }
4014 
4015  /*
4016  * If the corresponding toast-table namespace doesn't exist yet, create
4017  * it. (We assume there is no need to clean it out if it does exist, since
4018  * dropping a parent table should make its toast table go away.)
4019  */
4020  snprintf(namespaceName, sizeof(namespaceName), "pg_toast_temp_%d",
4021  MyBackendId);
4022 
4023  toastspaceId = get_namespace_oid(namespaceName, true);
4024  if (!OidIsValid(toastspaceId))
4025  {
4026  toastspaceId = NamespaceCreate(namespaceName, BOOTSTRAP_SUPERUSERID,
4027  true);
4028  /* Advance command counter to make namespace visible */
4030  }
4031 
4032  /*
4033  * Okay, we've prepared the temp namespace ... but it's not committed yet,
4034  * so all our work could be undone by transaction rollback. Set flag for
4035  * AtEOXact_Namespace to know what to do.
4036  */
4037  myTempNamespace = namespaceId;
4038  myTempToastNamespace = toastspaceId;
4039 
4040  /*
4041  * Mark MyProc as owning this namespace which other processes can use to
4042  * decide if a temporary namespace is in use or not. We assume that
4043  * assignment of namespaceId is an atomic operation. Even if it is not,
4044  * the temporary relation which resulted in the creation of this temporary
4045  * namespace is still locked until the current transaction commits, and
4046  * its pg_namespace row is not visible yet. However it does not matter:
4047  * this flag makes the namespace as being in use, so no objects created on
4048  * it would be removed concurrently.
4049  */
4050  MyProc->tempNamespaceId = namespaceId;
4051 
4052  /* It should not be done already. */
4055 
4056  baseSearchPathValid = false; /* need to rebuild list */
4057 }
4058 
4059 /*
4060  * End-of-transaction cleanup for namespaces.
4061  */
4062 void
4063 AtEOXact_Namespace(bool isCommit, bool parallel)
4064 {
4065  /*
4066  * If we abort the transaction in which a temp namespace was selected,
4067  * we'll have to do any creation or cleanout work over again. So, just
4068  * forget the namespace entirely until next time. On the other hand, if
4069  * we commit then register an exit callback to clean out the temp tables
4070  * at backend shutdown. (We only want to register the callback once per
4071  * session, so this is a good place to do it.)
4072  */
4073  if (myTempNamespaceSubID != InvalidSubTransactionId && !parallel)
4074  {
4075  if (isCommit)
4077  else
4078  {
4081  baseSearchPathValid = false; /* need to rebuild list */
4082 
4083  /*
4084  * Reset the temporary namespace flag in MyProc. We assume that
4085  * this operation is atomic.
4086  *
4087  * Because this transaction is aborting, the pg_namespace row is
4088  * not visible to anyone else anyway, but that doesn't matter:
4089  * it's not a problem if objects contained in this namespace are
4090  * removed concurrently.
4091  */
4093  }
4095  }
4096 
4097  /*
4098  * Clean up if someone failed to do PopOverrideSearchPath
4099  */
4100  if (overrideStack)
4101  {
4102  if (isCommit)
4103  elog(WARNING, "leaked override search path");
4104  while (overrideStack)
4105  {
4106  OverrideStackEntry *entry;
4107 
4108  entry = (OverrideStackEntry *) linitial(overrideStack);
4109  overrideStack = list_delete_first(overrideStack);
4110  list_free(entry->searchPath);
4111  pfree(entry);
4112  }
4113  /* If not baseSearchPathValid, this is useless but harmless */
4114  activeSearchPath = baseSearchPath;
4117  /* Always bump generation --- see note in recomputeNamespacePath */
4119  }
4120 }
4121 
4122 /*
4123  * AtEOSubXact_Namespace
4124  *
4125  * At subtransaction commit, propagate the temp-namespace-creation
4126  * flag to the parent subtransaction.
4127  *
4128  * At subtransaction abort, forget the flag if we set it up.
4129  */
4130 void
4132  SubTransactionId parentSubid)
4133 {
4134  OverrideStackEntry *entry;
4135 
4136  if (myTempNamespaceSubID == mySubid)
4137  {
4138  if (isCommit)
4139  myTempNamespaceSubID = parentSubid;
4140  else
4141  {
4143  /* TEMP namespace creation failed, so reset state */
4146  baseSearchPathValid = false; /* need to rebuild list */
4147 
4148  /*
4149  * Reset the temporary namespace flag in MyProc. We assume that
4150  * this operation is atomic.
4151  *
4152  * Because this subtransaction is aborting, the pg_namespace row
4153  * is not visible to anyone else anyway, but that doesn't matter:
4154  * it's not a problem if objects contained in this namespace are
4155  * removed concurrently.
4156  */
4158  }
4159  }
4160 
4161  /*
4162  * Clean up if someone failed to do PopOverrideSearchPath
4163  */
4164  while (overrideStack)
4165  {
4166  entry = (OverrideStackEntry *) linitial(overrideStack);
4168  break;
4169  if (isCommit)
4170  elog(WARNING, "leaked override search path");
4171  overrideStack = list_delete_first(overrideStack);
4172  list_free(entry->searchPath);
4173  pfree(entry);
4174  /* Always bump generation --- see note in recomputeNamespacePath */
4176  }
4177 
4178  /* Activate the next level down. */
4179  if (overrideStack)
4180  {
4181  entry = (OverrideStackEntry *) linitial(overrideStack);
4182  activeSearchPath = entry->searchPath;
4184  activeTempCreationPending = false; /* XXX is this OK? */
4185 
4186  /*
4187  * It's probably unnecessary to bump generation here, but this should
4188  * not be a performance-critical case, so better to be over-cautious.
4189  */
4191  }
4192  else
4193  {
4194  /* If not baseSearchPathValid, this is useless but harmless */
4195  activeSearchPath = baseSearchPath;
4198 
4199  /*
4200  * If we popped an override stack entry, then we already bumped the
4201  * generation above. If we did not, then the above assignments did
4202  * nothing and we need not bump the generation.
4203  */
4204  }
4205 }
4206 
4207 /*
4208  * Remove all relations in the specified temp namespace.
4209  *
4210  * This is called at backend shutdown (if we made any temp relations).
4211  * It is also called when we begin using a pre-existing temp namespace,
4212  * in order to clean out any relations that might have been created by
4213  * a crashed backend.
4214  */
4215 static void
4216 RemoveTempRelations(Oid tempNamespaceId)
4217 {
4218  ObjectAddress object;
4219 
4220  /*
4221  * We want to get rid of everything in the target namespace, but not the
4222  * namespace itself (deleting it only to recreate it later would be a
4223  * waste of cycles). Hence, specify SKIP_ORIGINAL. It's also an INTERNAL
4224  * deletion, and we want to not drop any extensions that might happen to
4225  * own temp objects.
4226  */
4227  object.classId = NamespaceRelationId;
4228  object.objectId = tempNamespaceId;
4229  object.objectSubId = 0;
4230 
4231  performDeletion(&object, DROP_CASCADE,
4236 }
4237 
4238 /*
4239  * Callback to remove temp relations at backend exit.
4240  */
4241 static void
4243 {
4244  if (OidIsValid(myTempNamespace)) /* should always be true */
4245  {
4246  /* Need to ensure we have a usable transaction. */
4249 
4251 
4253  }
4254 }
4255 
4256 /*
4257  * Remove all temp tables from the temporary namespace.
4258  */
4259 void
4261 {
4264 }
4265 
4266 
4267 /*
4268  * Routines for handling the GUC variable 'search_path'.
4269  */
4270 
4271 /* check_hook: validate new search_path value */
4272 bool
4273 check_search_path(char **newval, void **extra, GucSource source)
4274 {
4275  char *rawname;
4276  List *namelist;
4277 
4278  /* Need a modifiable copy of string */
4279  rawname = pstrdup(*newval);
4280 
4281  /* Parse string into list of identifiers */
4282  if (!SplitIdentifierString(rawname, ',', &namelist))
4283  {
4284  /* syntax error in name list */
4285  GUC_check_errdetail("List syntax is invalid.");
4286  pfree(rawname);
4287  list_free(namelist);
4288  return false;
4289  }
4290 
4291  /*
4292  * We used to try to check that the named schemas exist, but there are
4293  * many valid use-cases for having search_path settings that include
4294  * schemas that don't exist; and often, we are not inside a transaction
4295  * here and so can't consult the system catalogs anyway. So now, the only
4296  * requirement is syntactic validity of the identifier list.
4297  */
4298 
4299  pfree(rawname);
4300  list_free(namelist);
4301 
4302  return true;
4303 }
4304 
4305 /* assign_hook: do extra actions as needed */
4306 void
4307 assign_search_path(const char *newval, void *extra)
4308 {
4309  /*
4310  * We mark the path as needing recomputation, but don't do anything until
4311  * it's needed. This avoids trying to do database access during GUC
4312  * initialization, or outside a transaction.
4313  */
4314  baseSearchPathValid = false;
4315 }
4316 
4317 /*
4318  * InitializeSearchPath: initialize module during InitPostgres.
4319  *
4320  * This is called after we are up enough to be able to do catalog lookups.
4321  */
4322 void
4324 {
4326  {
4327  /*
4328  * In bootstrap mode, the search path must be 'pg_catalog' so that
4329  * tables are created in the proper namespace; ignore the GUC setting.
4330  */
4331  MemoryContext oldcxt;
4332 
4334  baseSearchPath = list_make1_oid(PG_CATALOG_NAMESPACE);
4335  MemoryContextSwitchTo(oldcxt);
4336  baseCreationNamespace = PG_CATALOG_NAMESPACE;
4337  baseTempCreationPending = false;
4338  baseSearchPathValid = true;
4340  activeSearchPath = baseSearchPath;
4343  activePathGeneration++; /* pro forma */
4344  }
4345  else
4346  {
4347  /*
4348  * In normal mode, arrange for a callback on any syscache invalidation
4349  * of pg_namespace rows.
4350  */
4353  (Datum) 0);
4354  /* Force search path to be recomputed on next use */
4355  baseSearchPathValid = false;
4356  }
4357 }
4358 
4359 /*
4360  * NamespaceCallback
4361  * Syscache inval callback function
4362  */
4363 static void
4364 NamespaceCallback(Datum arg, int cacheid, uint32 hashvalue)
4365 {
4366  /* Force search path to be recomputed on next use */
4367  baseSearchPathValid = false;
4368 }
4369 
4370 /*
4371  * Fetch the active search path. The return value is a palloc'ed list
4372  * of OIDs; the caller is responsible for freeing this storage as
4373  * appropriate.
4374  *
4375  * The returned list includes the implicitly-prepended namespaces only if
4376  * includeImplicit is true.
4377  *
4378  * Note: calling this may result in a CommandCounterIncrement operation,
4379  * if we have to create or clean out the temp namespace.
4380  */
4381 List *
4382 fetch_search_path(bool includeImplicit)
4383 {
4384  List *result;
4385 
4387 
4388  /*
4389  * If the temp namespace should be first, force it to exist. This is so
4390  * that callers can trust the result to reflect the actual default
4391  * creation namespace. It's a bit bogus to do this here, since
4392  * current_schema() is supposedly a stable function without side-effects,
4393  * but the alternatives seem worse.
4394  */
4396  {
4399  }
4400 
4401  result = list_copy(activeSearchPath);
4402  if (!includeImplicit)
4403  {
4404  while (result && linitial_oid(result) != activeCreationNamespace)
4405  result = list_delete_first(result);
4406  }
4407 
4408  return result;
4409 }
4410 
4411 /*
4412  * Fetch the active search path into a caller-allocated array of OIDs.
4413  * Returns the number of path entries. (If this is more than sarray_len,
4414  * then the data didn't fit and is not all stored.)
4415  *
4416  * The returned list always includes the implicitly-prepended namespaces,
4417  * but never includes the temp namespace. (This is suitable for existing
4418  * users, which would want to ignore the temp namespace anyway.) This
4419  * definition allows us to not worry about initializing the temp namespace.
4420  */
4421 int
4422 fetch_search_path_array(Oid *sarray, int sarray_len)
4423 {
4424  int count = 0;
4425  ListCell *l;
4426 
4428 
4429  foreach(l, activeSearchPath)
4430  {
4431  Oid namespaceId = lfirst_oid(l);
4432 
4433  if (namespaceId == myTempNamespace)
4434  continue; /* do not include temp namespace */
4435 
4436  if (count < sarray_len)
4437  sarray[count] = namespaceId;
4438  count++;
4439  }
4440 
4441  return count;
4442 }
4443 
4444 
4445 /*
4446  * Export the FooIsVisible functions as SQL-callable functions.
4447  *
4448  * Note: as of Postgres 8.4, these will silently return NULL if called on
4449  * a nonexistent object OID, rather than failing. This is to avoid race
4450  * condition errors when a query that's scanning a catalog using an MVCC
4451  * snapshot uses one of these functions. The underlying IsVisible functions
4452  * always use an up-to-date snapshot and so might see the object as already
4453  * gone when it's still visible to the transaction snapshot. (There is no race
4454  * condition in the current coding because we don't accept sinval messages
4455  * between the SearchSysCacheExists test and the subsequent lookup.)
4456  */
4457 
4458 Datum
4460 {
4461  Oid oid = PG_GETARG_OID(0);
4462 
4464  PG_RETURN_NULL();
4465 
4467 }
4468 
4469 Datum
4471 {
4472  Oid oid = PG_GETARG_OID(0);
4473 
4475  PG_RETURN_NULL();
4476 
4478 }
4479 
4480 Datum
4482 {
4483  Oid oid = PG_GETARG_OID(0);
4484 
4486  PG_RETURN_NULL();
4487 
4489 }
4490 
4491 Datum
4493 {
4494  Oid oid = PG_GETARG_OID(0);
4495 
4497  PG_RETURN_NULL();
4498 
4500 }
4501 
4502 Datum
4504 {
4505  Oid oid = PG_GETARG_OID(0);
4506 
4508  PG_RETURN_NULL();
4509 
4511 }
4512 
4513 Datum
4515 {
4516  Oid oid = PG_GETARG_OID(0);
4517 
4519  PG_RETURN_NULL();
4520 
4522 }
4523 
4524 Datum
4526 {
4527  Oid oid = PG_GETARG_OID(0);
4528 
4530  PG_RETURN_NULL();
4531 
4533 }
4534 
4535 Datum
4537 {
4538  Oid oid = PG_GETARG_OID(0);
4539 
4541  PG_RETURN_NULL();
4542 
4544 }
4545 
4546 Datum
4548 {
4549  Oid oid = PG_GETARG_OID(0);
4550 
4552  PG_RETURN_NULL();
4553 
4555 }
4556 
4557 Datum
4559 {
4560  Oid oid = PG_GETARG_OID(0);
4561 
4563  PG_RETURN_NULL();
4564 
4566 }
4567 
4568 Datum
4570 {
4571  Oid oid = PG_GETARG_OID(0);
4572 
4574  PG_RETURN_NULL();
4575 
4577 }
4578 
4579 Datum
4581 {
4582  Oid oid = PG_GETARG_OID(0);
4583 
4585  PG_RETURN_NULL();
4586 
4588 }
4589 
4590 Datum
4592 {
4593  Oid oid = PG_GETARG_OID(0);
4594 
4596  PG_RETURN_NULL();
4597 
4599 }
4600 
4601 Datum
4603 {
4605 }
4606 
4607 Datum
4609 {
4610  Oid oid = PG_GETARG_OID(0);
4611 
4613 }
Value * makeString(char *str)
Definition: value.c:53
void ResetTempTableNamespace(void)
Definition: namespace.c:4260
#define NIL
Definition: pg_list.h:65
bool ConditionalLockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:151
static bool baseSearchPathValid
Definition: namespace.c:160
#define IsA(nodeptr, _type_)
Definition: nodes.h:579
int n_members
Definition: catcache.h:176
Oid get_namespace_oid(const char *nspname, bool missing_ok)
Definition: namespace.c:3042
#define DEBUG1
Definition: elog.h:25
Oid LookupExplicitNamespace(const char *nspname, bool missing_ok)
Definition: namespace.c:2892
static void AccessTempTableNamespace(bool force)
Definition: namespace.c:3914
BackendId MyBackendId
Definition: globals.c:81
NameData proname
Definition: pg_proc.h:35
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define AssertState(condition)
Definition: c.h:748
#define ERRCODE_UNDEFINED_TABLE
Definition: pgbench.c:74
void AcceptInvalidationMessages(void)
Definition: inval.c:684
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10709
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:310
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:3032
FormData_pg_ts_config * Form_pg_ts_config
Definition: pg_ts_config.h:48
int LOCKMODE
Definition: lockdefs.h:26
Oid GetUserId(void)
Definition: miscinit.c:476
Oid TypenameGetTypid(const char *typname)
Definition: namespace.c:771
Datum pg_type_is_visible(PG_FUNCTION_ARGS)
Definition: namespace.c:4470
void UnlockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:199
Oid oprid(Operator op)
Definition: parse_oper.c:250
Oid tempNamespaceId
Definition: proc.h:148
#define GUC_check_errdetail
Definition: guc.h:415
NameData rolname
Definition: pg_authid.h:34
Oid RelnameGetRelid(const char *relname)
Definition: namespace.c:680
Datum pg_my_temp_schema(PG_FUNCTION_ARGS)
Definition: namespace.c:4602
Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p)
Definition: namespace.c:2994
PGPROC * MyProc
Definition: proc.c:67
bool isTempOrTempToastNamespace(Oid namespaceId)
Definition: namespace.c:3180
#define PointerGetDatum(X)
Definition: postgres.h:556
static Oid myTempToastNamespace
Definition: namespace.c:190
Oid LookupCreationNamespace(const char *nspname)
Definition: namespace.c:2935
#define GetSysCacheOid1(cacheId, oidcol, key1)
Definition: syscache.h:192
char get_rel_relkind(Oid relid)
Definition: lsyscache.c:1915
char * pstrdup(const char *in)
Definition: mcxt.c:1187
void CommitTransactionCommand(void)
Definition: xact.c:2947
Datum pg_opclass_is_visible(PG_FUNCTION_ARGS)
Definition: namespace.c:4503
void GetTempNamespaceState(Oid *tempNamespaceId, Oid *tempToastNamespaceId)
Definition: namespace.c:3312
void PushOverrideSearchPath(OverrideSearchPath *newpath)
Definition: namespace.c:3489
Datum pg_conversion_is_visible(PG_FUNCTION_ARGS)
Definition: namespace.c:4536
bool is_encoding_supported_by_icu(int encoding)
Definition: encnames.c:459
#define PERFORM_DELETION_SKIP_ORIGINAL
Definition: dependency.h:137
int get_func_arg_info(HeapTuple procTup, Oid **p_argtypes, char ***p_argnames, char **p_argmodes)
Definition: funcapi.c:1094
static Oid myTempNamespace
Definition: namespace.c:188
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define AccessShareLock
Definition: lockdefs.h:36
static List * overrideStack
Definition: namespace.c:171
bool StatisticsObjIsVisible(Oid relid)
Definition: namespace.c:2234
List * list_copy(const List *oldlist)
Definition: list.c:1403
Definition: nodes.h:528
#define strVal(v)
Definition: value.h:54
int errcode(int sqlerrcode)
Definition: elog.c:610
Oid get_ts_config_oid(List *names, bool missing_ok)
Definition: namespace.c:2678
bool OperatorIsVisible(Oid oprid)
Definition: namespace.c:1746
int GetTempNamespaceBackendId(Oid namespaceId)
Definition: namespace.c:3273
void DeconstructQualifiedName(List *names, char **nspname_p, char **objname_p)
Definition: namespace.c:2808
bool FunctionIsVisible(Oid funcid)
Definition: namespace.c:1413
static Oid namespaceUser
Definition: namespace.c:157
RangeVar * makeRangeVarFromNameList(List *names)
Definition: namespace.c:3061
Oid CollationGetCollid(const char *collname)
Definition: namespace.c:2013
uint32 SubTransactionId
Definition: c.h:524
List * lcons_oid(Oid datum, List *list)
Definition: list.c:489
int16 pronargs
Definition: pg_proc.h:81
NameData relname
Definition: pg_class.h:38
unsigned int Oid
Definition: postgres_ext.h:31
bool RecoveryInProgress(void)
Definition: xlog.c:8074
Oid OpclassnameGetOpcid(Oid amid, const char *opcname)
Definition: namespace.c:1799
List * lappend_oid(List *list, Oid datum)
Definition: list.c:357
#define OidIsValid(objectId)
Definition: c.h:651
int fetch_search_path_array(Oid *sarray, int sarray_len)
Definition: namespace.c:4422
void AbortOutOfAnyTransaction(void)
Definition: xact.c:4580
AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4625
Oid TypenameGetTypidExtended(const char *typname, bool temp_ok)
Definition: namespace.c:784
void RangeVarAdjustRelationPersistence(RangeVar *newRelation, Oid nspid)
Definition: namespace.c:641
#define lsecond(l)
Definition: pg_list.h:179
signed int int32
Definition: c.h:362
FuncCandidateList OpernameGetCandidates(List *names, char oprkind, bool missing_schema_ok)
Definition: namespace.c:1586
GucSource
Definition: guc.h:105
static void recomputeNamespacePath(void)
Definition: namespace.c:3736
char * schemaname
Definition: primnodes.h:67
TempNamespaceStatus checkTempNamespaceStatus(Oid namespaceId)
Definition: namespace.c:3236
#define FUNC_MAX_ARGS
#define InvokeNamespaceSearchHook(objectId, ereport_on_violation)
Definition: objectaccess.h:186
CatCTup * members[FLEXIBLE_ARRAY_MEMBER]
Definition: catcache.h:178
#define list_make1(x1)
Definition: pg_list.h:206
#define NAMEDATALEN
Oid ConversionGetConid(const char *conname)
Definition: namespace.c:2098
FormData_pg_authid * Form_pg_authid
Definition: pg_authid.h:56
char * relname
Definition: primnodes.h:68
Oid OpernameGetOprid(List *names, Oid oprleft, Oid oprright)
Definition: namespace.c:1483
Oid get_ts_dict_oid(List *names, bool missing_ok)
Definition: namespace.c:2425
static Oid lookup_collation(const char *collname, Oid collnamespace, int32 encoding)
Definition: namespace.c:1962
static Oid activeCreationNamespace
Definition: namespace.c:141
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3294
Oid OpfamilynameGetOpfid(Oid amid, const char *opfname)
Definition: namespace.c:1882
#define SearchSysCacheExists1(cacheId, key1)
Definition: syscache.h:183
Oid args[FLEXIBLE_ARRAY_MEMBER]
Definition: namespace.h:37
void pfree(void *pointer)
Definition: mcxt.c:1057
#define linitial(l)
Definition: pg_list.h:174
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define GetSysCacheOid3(cacheId, oidcol, key1, key2, key3)
Definition: syscache.h:196
#define ACL_CREATE
Definition: parsenodes.h:84
struct _FuncCandidateList * FuncCandidateList
bool TSConfigIsVisible(Oid cfgid)
Definition: namespace.c:2736
static bool baseTempCreationPending
Definition: namespace.c:155
FuncCandidateList FuncnameGetCandidates(List *names, int nargs, List *argnames, bool expand_variadic, bool expand_defaults, bool missing_ok)
Definition: namespace.c:942
HeapTuple SearchSysCache3(int cacheId, Datum key1, Datum key2, Datum key3)
Definition: syscache.c:1138
void InitializeSearchPath(void)
Definition: namespace.c:4323
Oid get_statistics_object_oid(List *names, bool missing_ok)
Definition: namespace.c:2177
static void callback(struct sockaddr *addr, struct sockaddr *mask, void *unused)
Definition: test_ifaddrs.c:48
OverrideSearchPath * CopyOverrideSearchPath(OverrideSearchPath *path)
Definition: namespace.c:3396
Oid get_relname_relid(const char *relname, Oid relnamespace)
Definition: lsyscache.c:1797
OverrideSearchPath * GetOverrideSearchPath(MemoryContext context)
Definition: namespace.c:3359
char * get_database_name(Oid dbid)
Definition: dbcommands.c:2155
Datum pg_opfamily_is_visible(PG_FUNCTION_ARGS)
Definition: namespace.c:4514
FormData_pg_ts_dict * Form_pg_ts_dict
Definition: pg_ts_dict.h:52
Oid GetTempToastNamespace(void)
Definition: namespace.c:3298
static uint64 activePathGeneration
Definition: namespace.c:147
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
Oid get_ts_template_oid(List *names, bool missing_ok)
Definition: namespace.c:2552
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3191
void SetTempNamespaceState(Oid tempNamespaceId, Oid tempToastNamespaceId)
Definition: namespace.c:3328
#define NoLock
Definition: lockdefs.h:34
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
bool SplitIdentifierString(char *rawstring, char separator, List **namelist)
Definition: varlena.c:3702
Datum pg_function_is_visible(PG_FUNCTION_ARGS)
Definition: namespace.c:4481
#define CStringGetDatum(X)
Definition: postgres.h:578
char string[11]
Definition: preproc-type.c:46
void LockDatabaseObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:976
void before_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:333
void performDeletion(const ObjectAddress *object, DropBehavior behavior, int flags)
Definition: dependency.c:312
static ListCell * list_head(const List *l)
Definition: pg_list.h:125
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, uint32 flags, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:236
Oid databaseId
Definition: proc.h:145
unsigned int uint32
Definition: c.h:374
static SubTransactionId myTempNamespaceSubID
Definition: namespace.c:192
bool isTempNamespace(Oid namespaceId)
Definition: namespace.c:3156
#define ACL_USAGE
Definition: parsenodes.h:82
#define SearchSysCacheList1(cacheId, key1)
Definition: syscache.h:210
bool CollationIsVisible(Oid collid)
Definition: namespace.c:2047
#define SPACE_PER_OP
HeapTuple SearchSysCache4(int cacheId, Datum key1, Datum key2, Datum key3, Datum key4)
Definition: syscache.c:1149
struct _FuncCandidateList * next
Definition: namespace.h:30
static void NamespaceCallback(Datum arg, int cacheid, uint32 hashvalue)
Definition: namespace.c:4364
Datum pg_ts_config_is_visible(PG_FUNCTION_ARGS)
Definition: namespace.c:4591
static bool activeTempCreationPending
Definition: namespace.c:144
bool OpfamilyIsVisible(Oid opfid)
Definition: namespace.c:1915
#define IsParallelWorker()
Definition: parallel.h:61
MemoryContext TopMemoryContext
Definition: mcxt.c:44
Datum pg_ts_template_is_visible(PG_FUNCTION_ARGS)
Definition: namespace.c:4580
void CheckSetNamespace(Oid oldNspOid, Oid nspOid)
Definition: namespace.c:2966
void UnlockDatabaseObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:997
static Oid baseCreationNamespace
Definition: namespace.c:153
NameData typname
Definition: pg_type.h:41
int MyXactFlags
Definition: xact.c:132
static void InitTempTableNamespace(void)
Definition: namespace.c:3942
bool isTempToastNamespace(Oid namespaceId)
Definition: namespace.c:3168
#define XACT_FLAGS_ACCESSEDTEMPNAMESPACE
Definition: xact.h:101
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
bool TSDictionaryIsVisible(Oid dictId)
Definition: namespace.c:2483
#define WARNING
Definition: elog.h:40
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
char * NameListToString(List *names)
Definition: namespace.c:3101
static int elevel
Definition: vacuumlazy.c:333
char * NameListToQuotedString(List *names)
Definition: namespace.c:3135
Oid RangeVarGetAndCheckCreationNamespace(RangeVar *relation, LOCKMODE lockmode, Oid *existing_relation_id)
Definition: namespace.c:534
#define ReleaseSysCacheList(x)
Definition: syscache.h:217
void PopOverrideSearchPath(void)
Definition: namespace.c:3556
#define InvalidBackendId
Definition: backendid.h:23
FormData_pg_opfamily * Form_pg_opfamily
Definition: pg_opfamily.h:51
char * namespace_search_path
Definition: namespace.c:198
static List * baseSearchPath
Definition: namespace.c:151
void CacheRegisterSyscacheCallback(int cacheid, SyscacheCallbackFunction func, Datum arg)
Definition: inval.c:1434
void * palloc0(Size size)
Definition: mcxt.c:981
AclResult
Definition: acl.h:177
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:358
uintptr_t Datum
Definition: postgres.h:367
void CommandCounterIncrement(void)
Definition: xact.c:1021
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
FormData_pg_ts_parser * Form_pg_ts_parser
Definition: pg_ts_parser.h:55
FormData_pg_conversion * Form_pg_conversion
Definition: pg_conversion.h:61
int GetDatabaseEncoding(void)
Definition: mbutils.c:1151
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1377
#define list_make1_oid(x1)
Definition: pg_list.h:228
Datum pg_ts_parser_is_visible(PG_FUNCTION_ARGS)
Definition: namespace.c:4558
Oid MyDatabaseId
Definition: globals.c:85
bool OpclassIsVisible(Oid opcid)
Definition: namespace.c:1832
uint64 SharedInvalidMessageCounter
Definition: sinval.c:26
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:133
#define InvalidOid
Definition: postgres_ext.h:36
void assign_search_path(const char *newval, void *extra)
Definition: namespace.c:4307
Datum pg_ts_dict_is_visible(PG_FUNCTION_ARGS)
Definition: namespace.c:4569
#define ereport(elevel,...)
Definition: elog.h:144
int GetCurrentTransactionNestLevel(void)
Definition: xact.c:857
TempNamespaceStatus
Definition: namespace.h:43
List * lcons(void *datum, List *list)
Definition: list.c:453
bool ConversionIsVisible(Oid conid)
Definition: namespace.c:2130
bool OverrideSearchPathMatchesCurrent(OverrideSearchPath *path)
Definition: namespace.c:3418
#define Max(x, y)
Definition: c.h:921
Datum pg_is_other_temp_schema(PG_FUNCTION_ARGS)
Definition: namespace.c:4608
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:674
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
AclResult pg_database_aclcheck(Oid db_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4575
Oid get_ts_parser_oid(List *names, bool missing_ok)
Definition: namespace.c:2299
#define Assert(condition)
Definition: c.h:745
#define lfirst(lc)
Definition: pg_list.h:169
const char * GetDatabaseEncodingName(void)
Definition: mbutils.c:1157
bool TypeIsVisible(Oid typid)
Definition: namespace.c:816
#define PERFORM_DELETION_QUIETLY
Definition: dependency.h:136
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:723
bool pg_class_ownercheck(Oid class_oid, Oid roleid)
Definition: aclchk.c:4687
void StartTransactionCommand(void)
Definition: xact.c:2846
#define GetSysCacheOid2(cacheId, oidcol, key1, key2)
Definition: syscache.h:194
Datum pg_operator_is_visible(PG_FUNCTION_ARGS)
Definition: namespace.c:4492
static void RemoveTempRelations(Oid tempNamespaceId)
Definition: namespace.c:4216
#define linitial_oid(l)
Definition: pg_list.h:176
bool check_search_path(char **newval, void **extra, GucSource source)
Definition: namespace.c:4273
FormData_pg_type * Form_pg_type
Definition: pg_type.h:255
static int list_length(const List *l)
Definition: pg_list.h:149
#define newval
Oid FindDefaultConversionProc(int32 for_encoding, int32 to_encoding)
Definition: namespace.c:3709
#define SearchSysCacheExists2(cacheId, key1, key2)
Definition: syscache.h:185
#define InvalidSubTransactionId
Definition: c.h:526
int32 encoding
Definition: pg_database.h:41
FormData_pg_operator * Form_pg_operator
Definition: pg_operator.h:83
const char * name
Definition: encode.c:561
static bool MatchNamedCall(HeapTuple proctup, int nargs, List *argnames, int **argnumbers)
Definition: namespace.c:1305
FormData_pg_collation * Form_pg_collation
Definition: pg_collation.h:51
Datum pg_collation_is_visible(PG_FUNCTION_ARGS)
Definition: namespace.c:4525
#define nodeTag(nodeptr)
Definition: nodes.h:533
char relpersistence
Definition: primnodes.h:71
Oid get_conversion_oid(List *name, bool missing_ok)
Definition: namespace.c:3654
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:393
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
static List * activeSearchPath
Definition: namespace.c:138
#define Int32GetDatum(X)
Definition: postgres.h:479
bool ordered
Definition: catcache.h:174
bool TSTemplateIsVisible(Oid tmplId)
Definition: namespace.c:2610
bool TSParserIsVisible(Oid prsId)
Definition: namespace.c:2357
void * palloc(Size size)
Definition: mcxt.c:950
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define SearchSysCacheList3(cacheId, key1, key2, key3)
Definition: syscache.h:214
bool RelationIsVisible(Oid relid)
Definition: namespace.c:708
bool isOtherTempNamespace(Oid namespaceId)
Definition: namespace.c:3217
void list_free(List *list)
Definition: list.c:1376
FormData_pg_ts_template * Form_pg_ts_template
#define elog(elevel,...)
Definition: elog.h:214
int i
#define ACL_CREATE_TEMP
Definition: parsenodes.h:85
ObjectType get_relkind_objtype(char relkind)
#define NameStr(name)
Definition: c.h:622
void(* RangeVarGetRelidCallback)(const RangeVar *relation, Oid relId, Oid oldRelId, void *callback_arg)
Definition: namespace.h:75
void * arg
#define lthird(l)
Definition: pg_list.h:184
bool isAnyTempNamespace(Oid namespaceId)
Definition: namespace.c:3194
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
HeapTupleData tuple
Definition: catcache.h:121
void AtEOSubXact_Namespace(bool isCommit, SubTransactionId mySubid, SubTransactionId parentSubid)
Definition: namespace.c:4131
Oid FindDefaultConversion(Oid name_space, int32 for_encoding, int32 to_encoding)
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:108
Datum pg_statistics_obj_is_visible(PG_FUNCTION_ARGS)
Definition: namespace.c:4547
#define PERFORM_DELETION_SKIP_EXTENSIONS
Definition: dependency.h:138
Datum pg_table_is_visible(PG_FUNCTION_ARGS)
Definition: namespace.c:4459
FormData_pg_opclass * Form_pg_opclass
Definition: pg_opclass.h:83
void AtEOXact_Namespace(bool isCommit, bool parallel)
Definition: namespace.c:4063
Definition: proc.h:112
Oid get_collation_oid(List *name, bool missing_ok)
Definition: namespace.c:3600
Definition: pg_list.h:50
#define PG_RETURN_OID(x)
Definition: fmgr.h:359
#define snprintf
Definition: port.h:193
List * fetch_search_path(bool includeImplicit)
Definition: namespace.c:4382
RangeVar * makeRangeVar(char *schemaname, char *relname, int location)
Definition: makefuncs.c:422
#define PG_RETURN_NULL()
Definition: fmgr.h:344
char * catalogname
Definition: primnodes.h:66
static void RemoveTempRelationsCallback(int code, Datum arg)
Definition: namespace.c:4242
#define offsetof(type, field)
Definition: c.h:668
Oid RangeVarGetCreationNamespace(const RangeVar *newRelation)
Definition: namespace.c:449
FormData_pg_statistic_ext * Form_pg_statistic_ext
#define lfirst_oid(lc)
Definition: pg_list.h:171
Oid NamespaceCreate(const char *nspName, Oid ownerId, bool isTemp)
Definition: pg_namespace.c:43
List * list_delete_first(List *list)
Definition: list.c:860
Oid LookupNamespaceNoError(const char *nspname)
Definition: namespace.c:2862
#define PERFORM_DELETION_INTERNAL
Definition: dependency.h:134
PGPROC * BackendIdGetProc(int backendID)
Definition: sinvaladt.c:376