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