LCOV - differential code coverage report
Current view: top level - src/backend/catalog - namespace.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GBC GIC GNC CBC EUB ECB DUB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 85.6 % 1433 1227 1 35 119 51 43 772 15 397 111 789 1 6
Current Date: 2023-04-08 15:15:32 Functions: 89.0 % 91 81 10 79 2 10 81
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           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                 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a