in src/postgres/src_backend_catalog_namespace.c [207:716]
static bool MatchNamedCall(HeapTuple proctup, int nargs, List *argnames,
int **argnumbers);
/*
* RangeVarGetRelid
* Given a RangeVar describing an existing relation,
* select the proper namespace and look up the relation OID.
*
* If the schema or relation is not found, return InvalidOid if missing_ok
* = true, otherwise raise an error.
*
* If nowait = true, throw an error if we'd have to wait for a lock.
*
* Callback allows caller to check permissions or acquire additional locks
* prior to grabbing the relation lock.
*/
/*
* RangeVarGetCreationNamespace
* Given a RangeVar describing a to-be-created relation,
* choose which namespace to create it in.
*
* Note: calling this may result in a CommandCounterIncrement operation.
* That will happen on the first request for a temp table in any particular
* backend run; we will need to either create or clean out the temp schema.
*/
/*
* RangeVarGetAndCheckCreationNamespace
*
* This function returns the OID of the namespace in which a new relation
* with a given name should be created. If the user does not have CREATE
* permission on the target namespace, this function will instead signal
* an ERROR.
*
* If non-NULL, *existing_oid is set to the OID of any existing relation with
* the same name which already exists in that namespace, or to InvalidOid if
* no such relation exists.
*
* If lockmode != NoLock, the specified lock mode is acquired on the existing
* relation, if any, provided that the current user owns the target relation.
* However, if lockmode != NoLock and the user does not own the target
* relation, we throw an ERROR, as we must not try to lock relations the
* user does not have permissions on.
*
* As a side effect, this function acquires AccessShareLock on the target
* namespace. Without this, the namespace could be dropped before our
* transaction commits, leaving behind relations with relnamespace pointing
* to a no-longer-existent namespace.
*
* As a further side-effect, if the selected namespace is a temporary namespace,
* we mark the RangeVar as RELPERSISTENCE_TEMP.
*/
/*
* Adjust the relpersistence for an about-to-be-created relation based on the
* creation namespace, and throw an error for invalid combinations.
*/
/*
* RelnameGetRelid
* Try to resolve an unqualified relation name.
* Returns OID if relation found in search path, else InvalidOid.
*/
/*
* RelationIsVisible
* Determine whether a relation (identified by OID) is visible in the
* current search path. Visible means "would be found by searching
* for the unqualified relation name".
*/
/*
* TypenameGetTypid
* Try to resolve an unqualified datatype name.
* Returns OID if type found in search path, else InvalidOid.
*
* This is essentially the same as RelnameGetRelid.
*/
/*
* TypeIsVisible
* Determine whether a type (identified by OID) is visible in the
* current search path. Visible means "would be found by searching
* for the unqualified type name".
*/
/*
* FuncnameGetCandidates
* Given a possibly-qualified function name and argument count,
* retrieve a list of the possible matches.
*
* If nargs is -1, we return all functions matching the given name,
* regardless of argument count. (argnames must be NIL, and expand_variadic
* and expand_defaults must be false, in this case.)
*
* If argnames isn't NIL, we are considering a named- or mixed-notation call,
* and only functions having all the listed argument names will be returned.
* (We assume that length(argnames) <= nargs and all the passed-in names are
* distinct.) The returned structs will include an argnumbers array showing
* the actual argument index for each logical argument position.
*
* If expand_variadic is true, then variadic functions having the same number
* or fewer arguments will be retrieved, with the variadic argument and any
* additional argument positions filled with the variadic element type.
* nvargs in the returned struct is set to the number of such arguments.
* If expand_variadic is false, variadic arguments are not treated specially,
* and the returned nvargs will always be zero.
*
* If expand_defaults is true, functions that could match after insertion of
* default argument values will also be retrieved. In this case the returned
* structs could have nargs > passed-in nargs, and ndargs is set to the number
* of additional args (which can be retrieved from the function's
* proargdefaults entry).
*
* It is not possible for nvargs and ndargs to both be nonzero in the same
* list entry, since default insertion allows matches to functions with more
* than nargs arguments while the variadic transformation requires the same
* number or less.
*
* When argnames isn't NIL, the returned args[] type arrays are not ordered
* according to the functions' declarations, but rather according to the call:
* first any positional arguments, then the named arguments, then defaulted
* arguments (if needed and allowed by expand_defaults). The argnumbers[]
* array can be used to map this back to the catalog information.
* argnumbers[k] is set to the proargtypes index of the k'th call argument.
*
* We search a single namespace if the function name is qualified, else
* all namespaces in the search path. In the multiple-namespace case,
* we arrange for entries in earlier namespaces to mask identical entries in
* later namespaces.
*
* When expanding variadics, we arrange for non-variadic functions to mask
* variadic ones if the expanded argument list is the same. It is still
* possible for there to be conflicts between different variadic functions,
* however.
*
* It is guaranteed that the return list will never contain multiple entries
* with identical argument lists. When expand_defaults is true, the entries
* could have more than nargs positions, but we still guarantee that they are
* distinct in the first nargs positions. However, if argnames isn't NIL or
* either expand_variadic or expand_defaults is true, there might be multiple
* candidate functions that expand to identical argument lists. Rather than
* throw error here, we report such situations by returning a single entry
* with oid = 0 that represents a set of such conflicting candidates.
* The caller might end up discarding such an entry anyway, but if it selects
* such an entry it should react as though the call were ambiguous.
*
* If missing_ok is true, an empty list (NULL) is returned if the name was
* schema- qualified with a schema that does not exist. Likewise if no
* candidate is found for other reasons.
*/
/*
* MatchNamedCall
* Given a pg_proc heap tuple and a call's list of argument names,
* check whether the function could match the call.
*
* The call could match if all supplied argument names are accepted by
* the function, in positions after the last positional argument, and there
* are defaults for all unsupplied arguments.
*
* The number of positional arguments is nargs - list_length(argnames).
* Note caller has already done basic checks on argument count.
*
* On match, return true and fill *argnumbers with a palloc'd array showing
* the mapping from call argument positions to actual function argument
* numbers. Defaulted arguments are included in this map, at positions
* after the last supplied argument.
*/
/*
* FunctionIsVisible
* Determine whether a function (identified by OID) is visible in the
* current search path. Visible means "would be found by searching
* for the unqualified function name with exact argument matches".
*/
/*
* OpernameGetOprid
* Given a possibly-qualified operator name and exact input datatypes,
* look up the operator. Returns InvalidOid if not found.
*
* Pass oprleft = InvalidOid for a prefix op, oprright = InvalidOid for
* a postfix op.
*
* If the operator name is not schema-qualified, it is sought in the current
* namespace search path. If the name is schema-qualified and the given
* schema does not exist, InvalidOid is returned.
*/
/*
* OpernameGetCandidates
* Given a possibly-qualified operator name and operator kind,
* retrieve a list of the possible matches.
*
* If oprkind is '\0', we return all operators matching the given name,
* regardless of arguments.
*
* We search a single namespace if the operator name is qualified, else
* all namespaces in the search path. The return list will never contain
* multiple entries with identical argument lists --- in the multiple-
* namespace case, we arrange for entries in earlier namespaces to mask
* identical entries in later namespaces.
*
* The returned items always have two args[] entries --- one or the other
* will be InvalidOid for a prefix or postfix oprkind. nargs is 2, too.
*/
#define SPACE_PER_OP MAXALIGN(offsetof(struct _FuncCandidateList, args) + \
2 * sizeof(Oid))
/*
* OperatorIsVisible
* Determine whether an operator (identified by OID) is visible in the
* current search path. Visible means "would be found by searching
* for the unqualified operator name with exact argument matches".
*/
/*
* OpclassnameGetOpcid
* Try to resolve an unqualified index opclass name.
* Returns OID if opclass found in search path, else InvalidOid.
*
* This is essentially the same as TypenameGetTypid, but we have to have
* an extra argument for the index AM OID.
*/
/*
* OpclassIsVisible
* Determine whether an opclass (identified by OID) is visible in the
* current search path. Visible means "would be found by searching
* for the unqualified opclass name".
*/
/*
* OpfamilynameGetOpfid
* Try to resolve an unqualified index opfamily name.
* Returns OID if opfamily found in search path, else InvalidOid.
*
* This is essentially the same as TypenameGetTypid, but we have to have
* an extra argument for the index AM OID.
*/
/*
* OpfamilyIsVisible
* Determine whether an opfamily (identified by OID) is visible in the
* current search path. Visible means "would be found by searching
* for the unqualified opfamily name".
*/
/*
* lookup_collation
* If there's a collation of the given name/namespace, and it works
* with the given encoding, return its OID. Else return InvalidOid.
*/
/*
* CollationGetCollid
* Try to resolve an unqualified collation name.
* Returns OID if collation found in search path, else InvalidOid.
*
* Note that this will only find collations that work with the current
* database's encoding.
*/
/*
* CollationIsVisible
* Determine whether a collation (identified by OID) is visible in the
* current search path. Visible means "would be found by searching
* for the unqualified collation name".
*
* Note that only collations that work with the current database's encoding
* will be considered visible.
*/
/*
* ConversionGetConid
* Try to resolve an unqualified conversion name.
* Returns OID if conversion found in search path, else InvalidOid.
*
* This is essentially the same as RelnameGetRelid.
*/
/*
* ConversionIsVisible
* Determine whether a conversion (identified by OID) is visible in the
* current search path. Visible means "would be found by searching
* for the unqualified conversion name".
*/
/*
* get_statistics_object_oid - find a statistics object by possibly qualified name
*
* If not found, returns InvalidOid if missing_ok, else throws error
*/
/*
* StatisticsObjIsVisible
* Determine whether a statistics object (identified by OID) is visible in
* the current search path. Visible means "would be found by searching
* for the unqualified statistics object name".
*/
/*
* get_ts_parser_oid - find a TS parser by possibly qualified name
*
* If not found, returns InvalidOid if missing_ok, else throws error
*/
/*
* TSParserIsVisible
* Determine whether a parser (identified by OID) is visible in the
* current search path. Visible means "would be found by searching
* for the unqualified parser name".
*/
/*
* get_ts_dict_oid - find a TS dictionary by possibly qualified name
*
* If not found, returns InvalidOid if failOK, else throws error
*/
/*
* TSDictionaryIsVisible
* Determine whether a dictionary (identified by OID) is visible in the
* current search path. Visible means "would be found by searching
* for the unqualified dictionary name".
*/
/*
* get_ts_template_oid - find a TS template by possibly qualified name
*
* If not found, returns InvalidOid if missing_ok, else throws error
*/
/*
* TSTemplateIsVisible
* Determine whether a template (identified by OID) is visible in the
* current search path. Visible means "would be found by searching
* for the unqualified template name".
*/
/*
* get_ts_config_oid - find a TS config by possibly qualified name
*
* If not found, returns InvalidOid if missing_ok, else throws error
*/
/*
* TSConfigIsVisible
* Determine whether a text search configuration (identified by OID)
* is visible in the current search path. Visible means "would be found
* by searching for the unqualified text search configuration name".
*/
/*
* DeconstructQualifiedName
* Given a possibly-qualified name expressed as a list of String nodes,
* extract the schema name and object name.
*
* *nspname_p is set to NULL if there is no explicit schema name.
*/
/*
* LookupNamespaceNoError
* Look up a schema name.
*
* Returns the namespace OID, or InvalidOid if not found.
*
* Note this does NOT perform any permissions check --- callers are
* responsible for being sure that an appropriate check is made.
* In the majority of cases LookupExplicitNamespace is preferable.
*/
/*
* LookupExplicitNamespace
* Process an explicitly-specified schema name: look up the schema
* and verify we have USAGE (lookup) rights in it.
*
* Returns the namespace OID
*/
/*
* LookupCreationNamespace
* Look up the schema and verify we have CREATE rights on it.
*
* This is just like LookupExplicitNamespace except for the different
* permission check, and that we are willing to create pg_temp if needed.
*
* Note: calling this may result in a CommandCounterIncrement operation,
* if we have to create or clean out the temp namespace.
*/
/*
* Common checks on switching namespaces.
*
* We complain if either the old or new namespaces is a temporary schema
* (or temporary toast schema), or if either the old or new namespaces is the
* TOAST schema.
*/
/*
* QualifiedNameGetCreationNamespace
* Given a possibly-qualified name for an object (in List-of-Values
* format), determine what namespace the object should be created in.
* Also extract and return the object name (last component of list).
*
* Note: this does not apply any permissions check. Callers must check
* for CREATE rights on the selected namespace when appropriate.
*
* Note: calling this may result in a CommandCounterIncrement operation,
* if we have to create or clean out the temp namespace.
*/
/*
* get_namespace_oid - given a namespace name, look up the OID
*
* If missing_ok is false, throw an error if namespace name not found. If
* true, just return InvalidOid.
*/
/*
* makeRangeVarFromNameList
* Utility routine to convert a qualified-name list into RangeVar form.
*/
/*
* NameListToString
* Utility routine to convert a qualified-name list into a string.
*
* This is used primarily to form error messages, and so we do not quote
* the list elements, for the sake of legibility.
*
* In most scenarios the list elements should always be Value strings,
* but we also allow A_Star for the convenience of ColumnRef processing.
*/
char *
NameListToString(List *names)
{
StringInfoData string;
ListCell *l;
initStringInfo(&string);
foreach(l, names)
{
Node *name = (Node *) lfirst(l);
if (l != list_head(names))
appendStringInfoChar(&string, '.');
if (IsA(name, String))
appendStringInfoString(&string, strVal(name));
else if (IsA(name, A_Star))
appendStringInfoChar(&string, '*');
else
elog(ERROR, "unexpected node type in name list: %d",
(int) nodeTag(name));
}
return string.data;
}