diff options
Diffstat (limited to 'src/backend/utils/adt/regproc.c')
-rw-r--r-- | src/backend/utils/adt/regproc.c | 1134 |
1 files changed, 0 insertions, 1134 deletions
diff --git a/src/backend/utils/adt/regproc.c b/src/backend/utils/adt/regproc.c deleted file mode 100644 index 18569e5479b..00000000000 --- a/src/backend/utils/adt/regproc.c +++ /dev/null @@ -1,1134 +0,0 @@ -/*------------------------------------------------------------------------- - * - * regproc.c - * Functions for the built-in types regproc, regclass, regtype, etc. - * - * These types are all binary-compatible with type Oid, and rely on Oid - * for comparison and so forth. Their only interesting behavior is in - * special I/O conversion routines. - * - * - * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group - * Portions Copyright (c) 1994, Regents of the University of California - * - * - * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/regproc.c,v 1.70 2002/06/20 20:29:38 momjian Exp $ - * - *------------------------------------------------------------------------- - */ -#include "postgres.h" - -#include <ctype.h> - -#include "access/genam.h" -#include "access/heapam.h" -#include "catalog/catname.h" -#include "catalog/indexing.h" -#include "catalog/namespace.h" -#include "catalog/pg_operator.h" -#include "catalog/pg_proc.h" -#include "catalog/pg_type.h" -#include "lib/stringinfo.h" -#include "miscadmin.h" -#include "parser/parse_type.h" -#include "utils/builtins.h" -#include "utils/fmgroids.h" -#include "utils/lsyscache.h" -#include "utils/syscache.h" - -static void parseNameAndArgTypes(const char *string, const char *caller, - const char *type0_spelling, - List **names, int *nargs, Oid *argtypes); - - -/***************************************************************************** - * USER I/O ROUTINES * - *****************************************************************************/ - -/* - * regprocin - converts "proname" to proc OID - * - * We also accept a numeric OID, mostly for historical reasons. - * - * '-' signifies unknown (OID 0). In all other cases, the input must - * match an existing pg_proc entry. - */ -Datum -regprocin(PG_FUNCTION_ARGS) -{ - char *pro_name_or_oid = PG_GETARG_CSTRING(0); - RegProcedure result = InvalidOid; - List *names; - FuncCandidateList clist; - - /* '-' ? */ - if (strcmp(pro_name_or_oid, "-") == 0) - PG_RETURN_OID(InvalidOid); - - /* Numeric OID? */ - if (pro_name_or_oid[0] >= '0' && - pro_name_or_oid[0] <= '9' && - strspn(pro_name_or_oid, "0123456789") == strlen(pro_name_or_oid)) - { - Oid searchOid; - - searchOid = DatumGetObjectId(DirectFunctionCall1(oidin, - CStringGetDatum(pro_name_or_oid))); - result = (RegProcedure) GetSysCacheOid(PROCOID, - ObjectIdGetDatum(searchOid), - 0, 0, 0); - if (!RegProcedureIsValid(result)) - elog(ERROR, "No procedure with oid %s", pro_name_or_oid); - PG_RETURN_OID(result); - } - - /* Else it's a name, possibly schema-qualified */ - - /* - * In bootstrap mode we assume the given name is not schema-qualified, - * and just search pg_proc for a unique match. This is needed for - * initializing other system catalogs (pg_namespace may not exist yet, - * and certainly there are no schemas other than pg_catalog). - */ - if (IsBootstrapProcessingMode()) - { - int matches = 0; - Relation hdesc; - ScanKeyData skey[1]; - SysScanDesc sysscan; - HeapTuple tuple; - - ScanKeyEntryInitialize(&skey[0], 0x0, - (AttrNumber) Anum_pg_proc_proname, - (RegProcedure) F_NAMEEQ, - CStringGetDatum(pro_name_or_oid)); - - hdesc = heap_openr(ProcedureRelationName, AccessShareLock); - sysscan = systable_beginscan(hdesc, ProcedureNameNspIndex, true, - SnapshotNow, 1, skey); - - while (HeapTupleIsValid(tuple = systable_getnext(sysscan))) - { - result = (RegProcedure) tuple->t_data->t_oid; - if (++matches > 1) - break; - } - - systable_endscan(sysscan); - heap_close(hdesc, AccessShareLock); - - if (matches == 0) - elog(ERROR, "No procedure with name %s", pro_name_or_oid); - else if (matches > 1) - elog(ERROR, "There is more than one procedure named %s", - pro_name_or_oid); - PG_RETURN_OID(result); - } - - /* - * Normal case: parse the name into components and see if it - * matches any pg_proc entries in the current search path. - */ - names = stringToQualifiedNameList(pro_name_or_oid, "regprocin"); - clist = FuncnameGetCandidates(names, -1); - - if (clist == NULL) - elog(ERROR, "No procedure with name %s", pro_name_or_oid); - else if (clist->next != NULL) - elog(ERROR, "There is more than one procedure named %s", - pro_name_or_oid); - - result = clist->oid; - - PG_RETURN_OID(result); -} - -/* - * regprocout - converts proc OID to "pro_name" - */ -Datum -regprocout(PG_FUNCTION_ARGS) -{ - RegProcedure proid = PG_GETARG_OID(0); - char *result; - HeapTuple proctup; - - if (proid == InvalidOid) - { - result = pstrdup("-"); - PG_RETURN_CSTRING(result); - } - - proctup = SearchSysCache(PROCOID, - ObjectIdGetDatum(proid), - 0, 0, 0); - - if (HeapTupleIsValid(proctup)) - { - Form_pg_proc procform = (Form_pg_proc) GETSTRUCT(proctup); - char *proname = NameStr(procform->proname); - - /* - * In bootstrap mode, skip the fancy namespace stuff and just - * return the proc name. (This path is only needed for debugging - * output anyway.) - */ - if (IsBootstrapProcessingMode()) - { - result = pstrdup(proname); - } - else - { - char *nspname; - FuncCandidateList clist; - - /* - * Would this proc be found (uniquely!) by regprocin? - * If not, qualify it. - */ - clist = FuncnameGetCandidates(makeList1(makeString(proname)), -1); - if (clist != NULL && clist->next == NULL && - clist->oid == proid) - nspname = NULL; - else - nspname = get_namespace_name(procform->pronamespace); - - result = quote_qualified_identifier(nspname, proname); - } - - ReleaseSysCache(proctup); - } - else - { - /* If OID doesn't match any pg_proc entry, return it numerically */ - result = (char *) palloc(NAMEDATALEN); - snprintf(result, NAMEDATALEN, "%u", proid); - } - - PG_RETURN_CSTRING(result); -} - - -/* - * regprocedurein - converts "proname(args)" to proc OID - * - * We also accept a numeric OID, mostly for historical reasons. - * - * '-' signifies unknown (OID 0). In all other cases, the input must - * match an existing pg_proc entry. - */ -Datum -regprocedurein(PG_FUNCTION_ARGS) -{ - char *pro_name_or_oid = PG_GETARG_CSTRING(0); - RegProcedure result = InvalidOid; - List *names; - int nargs; - Oid argtypes[FUNC_MAX_ARGS]; - FuncCandidateList clist; - - /* '-' ? */ - if (strcmp(pro_name_or_oid, "-") == 0) - PG_RETURN_OID(InvalidOid); - - /* Numeric OID? */ - if (pro_name_or_oid[0] >= '0' && - pro_name_or_oid[0] <= '9' && - strspn(pro_name_or_oid, "0123456789") == strlen(pro_name_or_oid)) - { - Oid searchOid; - - searchOid = DatumGetObjectId(DirectFunctionCall1(oidin, - CStringGetDatum(pro_name_or_oid))); - result = (RegProcedure) GetSysCacheOid(PROCOID, - ObjectIdGetDatum(searchOid), - 0, 0, 0); - if (!RegProcedureIsValid(result)) - elog(ERROR, "No procedure with oid %s", pro_name_or_oid); - PG_RETURN_OID(result); - } - - /* - * Else it's a name and arguments. Parse the name and arguments, - * look up potential matches in the current namespace search list, - * and scan to see which one exactly matches the given argument - * types. (There will not be more than one match.) - * - * XXX at present, this code will not work in bootstrap mode, hence this - * datatype cannot be used for any system column that needs to receive - * data during bootstrap. - */ - parseNameAndArgTypes(pro_name_or_oid, "regprocedurein", "opaque", - &names, &nargs, argtypes); - - clist = FuncnameGetCandidates(names, nargs); - - for (; clist; clist = clist->next) - { - if (memcmp(clist->args, argtypes, nargs * sizeof(Oid)) == 0) - break; - } - - if (clist == NULL) - elog(ERROR, "No procedure with name %s", pro_name_or_oid); - - result = clist->oid; - - PG_RETURN_OID(result); -} - -/* - * regprocedureout - converts proc OID to "pro_name(args)" - */ -Datum -regprocedureout(PG_FUNCTION_ARGS) -{ - RegProcedure proid = PG_GETARG_OID(0); - char *result; - HeapTuple proctup; - - if (proid == InvalidOid) - { - result = pstrdup("-"); - PG_RETURN_CSTRING(result); - } - - proctup = SearchSysCache(PROCOID, - ObjectIdGetDatum(proid), - 0, 0, 0); - - if (HeapTupleIsValid(proctup)) - { - Form_pg_proc procform = (Form_pg_proc) GETSTRUCT(proctup); - char *proname = NameStr(procform->proname); - int nargs = procform->pronargs; - int i; - char *nspname; - StringInfoData buf; - - /* XXX no support here for bootstrap mode */ - - initStringInfo(&buf); - - /* - * Would this proc be found (given the right args) by regprocedurein? - * If not, we need to qualify it. - */ - if (FunctionIsVisible(proid)) - nspname = NULL; - else - nspname = get_namespace_name(procform->pronamespace); - - appendStringInfo(&buf, "%s(", - quote_qualified_identifier(nspname, proname)); - for (i = 0; i < nargs; i++) - { - Oid thisargtype = procform->proargtypes[i]; - - if (i > 0) - appendStringInfoChar(&buf, ','); - if (OidIsValid(thisargtype)) - appendStringInfo(&buf, "%s", format_type_be(thisargtype)); - else - appendStringInfo(&buf, "opaque"); - } - appendStringInfoChar(&buf, ')'); - - result = buf.data; - - ReleaseSysCache(proctup); - } - else - { - /* If OID doesn't match any pg_proc entry, return it numerically */ - result = (char *) palloc(NAMEDATALEN); - snprintf(result, NAMEDATALEN, "%u", proid); - } - - PG_RETURN_CSTRING(result); -} - - -/* - * regoperin - converts "oprname" to operator OID - * - * We also accept a numeric OID, mostly for historical reasons. - * - * '0' signifies unknown (OID 0). In all other cases, the input must - * match an existing pg_operator entry. - */ -Datum -regoperin(PG_FUNCTION_ARGS) -{ - char *opr_name_or_oid = PG_GETARG_CSTRING(0); - Oid result = InvalidOid; - List *names; - FuncCandidateList clist; - - /* '0' ? */ - if (strcmp(opr_name_or_oid, "0") == 0) - PG_RETURN_OID(InvalidOid); - - /* Numeric OID? */ - if (opr_name_or_oid[0] >= '0' && - opr_name_or_oid[0] <= '9' && - strspn(opr_name_or_oid, "0123456789") == strlen(opr_name_or_oid)) - { - Oid searchOid; - - searchOid = DatumGetObjectId(DirectFunctionCall1(oidin, - CStringGetDatum(opr_name_or_oid))); - result = GetSysCacheOid(OPEROID, - ObjectIdGetDatum(searchOid), - 0, 0, 0); - if (!OidIsValid(result)) - elog(ERROR, "No operator with oid %s", opr_name_or_oid); - PG_RETURN_OID(result); - } - - /* Else it's a name, possibly schema-qualified */ - - /* - * In bootstrap mode we assume the given name is not schema-qualified, - * and just search pg_operator for a unique match. This is needed for - * initializing other system catalogs (pg_namespace may not exist yet, - * and certainly there are no schemas other than pg_catalog). - */ - if (IsBootstrapProcessingMode()) - { - int matches = 0; - Relation hdesc; - ScanKeyData skey[1]; - SysScanDesc sysscan; - HeapTuple tuple; - - ScanKeyEntryInitialize(&skey[0], 0x0, - (AttrNumber) Anum_pg_operator_oprname, - (RegProcedure) F_NAMEEQ, - CStringGetDatum(opr_name_or_oid)); - - hdesc = heap_openr(OperatorRelationName, AccessShareLock); - sysscan = systable_beginscan(hdesc, OperatorNameNspIndex, true, - SnapshotNow, 1, skey); - - while (HeapTupleIsValid(tuple = systable_getnext(sysscan))) - { - result = tuple->t_data->t_oid; - if (++matches > 1) - break; - } - - systable_endscan(sysscan); - heap_close(hdesc, AccessShareLock); - - if (matches == 0) - elog(ERROR, "No operator with name %s", opr_name_or_oid); - else if (matches > 1) - elog(ERROR, "There is more than one operator named %s", - opr_name_or_oid); - PG_RETURN_OID(result); - } - - /* - * Normal case: parse the name into components and see if it - * matches any pg_operator entries in the current search path. - */ - names = stringToQualifiedNameList(opr_name_or_oid, "regoperin"); - clist = OpernameGetCandidates(names, '\0'); - - if (clist == NULL) - elog(ERROR, "No operator with name %s", opr_name_or_oid); - else if (clist->next != NULL) - elog(ERROR, "There is more than one operator named %s", - opr_name_or_oid); - - result = clist->oid; - - PG_RETURN_OID(result); -} - -/* - * regoperout - converts operator OID to "opr_name" - */ -Datum -regoperout(PG_FUNCTION_ARGS) -{ - Oid oprid = PG_GETARG_OID(0); - char *result; - HeapTuple opertup; - - if (oprid == InvalidOid) - { - result = pstrdup("0"); - PG_RETURN_CSTRING(result); - } - - opertup = SearchSysCache(OPEROID, - ObjectIdGetDatum(oprid), - 0, 0, 0); - - if (HeapTupleIsValid(opertup)) - { - Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup); - char *oprname = NameStr(operform->oprname); - - /* - * In bootstrap mode, skip the fancy namespace stuff and just - * return the oper name. (This path is only needed for debugging - * output anyway.) - */ - if (IsBootstrapProcessingMode()) - { - result = pstrdup(oprname); - } - else - { - FuncCandidateList clist; - - /* - * Would this oper be found (uniquely!) by regoperin? - * If not, qualify it. - */ - clist = OpernameGetCandidates(makeList1(makeString(oprname)), - '\0'); - if (clist != NULL && clist->next == NULL && - clist->oid == oprid) - result = pstrdup(oprname); - else - { - const char *nspname; - - nspname = get_namespace_name(operform->oprnamespace); - nspname = quote_identifier(nspname); - result = (char *) palloc(strlen(nspname)+strlen(oprname)+2); - sprintf(result, "%s.%s", nspname, oprname); - } - } - - ReleaseSysCache(opertup); - } - else - { - /* If OID doesn't match any pg_operator entry, return it numerically */ - result = (char *) palloc(NAMEDATALEN); - snprintf(result, NAMEDATALEN, "%u", oprid); - } - - PG_RETURN_CSTRING(result); -} - - -/* - * regoperatorin - converts "oprname(args)" to operator OID - * - * We also accept a numeric OID, mostly for historical reasons. - * - * '0' signifies unknown (OID 0). In all other cases, the input must - * match an existing pg_operator entry. - */ -Datum -regoperatorin(PG_FUNCTION_ARGS) -{ - char *opr_name_or_oid = PG_GETARG_CSTRING(0); - Oid result = InvalidOid; - List *names; - int nargs; - Oid argtypes[FUNC_MAX_ARGS]; - char oprkind; - FuncCandidateList clist; - - /* '0' ? */ - if (strcmp(opr_name_or_oid, "0") == 0) - PG_RETURN_OID(InvalidOid); - - /* Numeric OID? */ - if (opr_name_or_oid[0] >= '0' && - opr_name_or_oid[0] <= '9' && - strspn(opr_name_or_oid, "0123456789") == strlen(opr_name_or_oid)) - { - Oid searchOid; - - searchOid = DatumGetObjectId(DirectFunctionCall1(oidin, - CStringGetDatum(opr_name_or_oid))); - result = GetSysCacheOid(OPEROID, - ObjectIdGetDatum(searchOid), - 0, 0, 0); - if (!OidIsValid(result)) - elog(ERROR, "No operator with oid %s", opr_name_or_oid); - PG_RETURN_OID(result); - } - - /* - * Else it's a name and arguments. Parse the name and arguments, - * look up potential matches in the current namespace search list, - * and scan to see which one exactly matches the given argument - * types. (There will not be more than one match.) - * - * XXX at present, this code will not work in bootstrap mode, hence this - * datatype cannot be used for any system column that needs to receive - * data during bootstrap. - */ - parseNameAndArgTypes(opr_name_or_oid, "regoperatorin", "none", - &names, &nargs, argtypes); - if (nargs == 1) - elog(ERROR, "regoperatorin: use NONE to denote the missing argument of a unary operator"); - if (nargs != 2) - elog(ERROR, "regoperatorin: provide two argument types for operator"); - - if (argtypes[0] == InvalidOid) - oprkind = 'l'; - else if (argtypes[1] == InvalidOid) - oprkind = 'r'; - else - oprkind = 'b'; - - clist = OpernameGetCandidates(names, oprkind); - - for (; clist; clist = clist->next) - { - if (memcmp(clist->args, argtypes, 2 * sizeof(Oid)) == 0) - break; - } - - if (clist == NULL) - elog(ERROR, "No operator with name %s", opr_name_or_oid); - - result = clist->oid; - - PG_RETURN_OID(result); -} - -/* - * regoperatorout - converts operator OID to "opr_name(args)" - */ -Datum -regoperatorout(PG_FUNCTION_ARGS) -{ - Oid oprid = PG_GETARG_OID(0); - char *result; - HeapTuple opertup; - - if (oprid == InvalidOid) - { - result = pstrdup("0"); - PG_RETURN_CSTRING(result); - } - - opertup = SearchSysCache(OPEROID, - ObjectIdGetDatum(oprid), - 0, 0, 0); - - if (HeapTupleIsValid(opertup)) - { - Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup); - char *oprname = NameStr(operform->oprname); - char *nspname; - StringInfoData buf; - - /* XXX no support here for bootstrap mode */ - - initStringInfo(&buf); - - /* - * Would this oper be found (given the right args) by regoperatorin? - * If not, we need to qualify it. - */ - if (!OperatorIsVisible(oprid)) - { - nspname = get_namespace_name(operform->oprnamespace); - appendStringInfo(&buf, "%s.", - quote_identifier(nspname)); - } - - appendStringInfo(&buf, "%s(", oprname); - - if (operform->oprleft) - appendStringInfo(&buf, "%s,", - format_type_be(operform->oprleft)); - else - appendStringInfo(&buf, "NONE,"); - - if (operform->oprright) - appendStringInfo(&buf, "%s)", - format_type_be(operform->oprright)); - else - appendStringInfo(&buf, "NONE)"); - - result = buf.data; - - ReleaseSysCache(opertup); - } - else - { - /* If OID doesn't match any pg_operator entry, return it numerically */ - result = (char *) palloc(NAMEDATALEN); - snprintf(result, NAMEDATALEN, "%u", oprid); - } - - PG_RETURN_CSTRING(result); -} - - -/* - * regclassin - converts "classname" to class OID - * - * We also accept a numeric OID, mostly for historical reasons. - * - * '-' signifies unknown (OID 0). In all other cases, the input must - * match an existing pg_class entry. - */ -Datum -regclassin(PG_FUNCTION_ARGS) -{ - char *class_name_or_oid = PG_GETARG_CSTRING(0); - Oid result = InvalidOid; - List *names; - - /* '-' ? */ - if (strcmp(class_name_or_oid, "-") == 0) - PG_RETURN_OID(InvalidOid); - - /* Numeric OID? */ - if (class_name_or_oid[0] >= '0' && - class_name_or_oid[0] <= '9' && - strspn(class_name_or_oid, "0123456789") == strlen(class_name_or_oid)) - { - Oid searchOid; - - searchOid = DatumGetObjectId(DirectFunctionCall1(oidin, - CStringGetDatum(class_name_or_oid))); - result = GetSysCacheOid(RELOID, - ObjectIdGetDatum(searchOid), - 0, 0, 0); - if (!OidIsValid(result)) - elog(ERROR, "No class with oid %s", class_name_or_oid); - PG_RETURN_OID(result); - } - - /* Else it's a name, possibly schema-qualified */ - - /* - * In bootstrap mode we assume the given name is not schema-qualified, - * and just search pg_class for a match. This is needed for - * initializing other system catalogs (pg_namespace may not exist yet, - * and certainly there are no schemas other than pg_catalog). - */ - if (IsBootstrapProcessingMode()) - { - Relation hdesc; - ScanKeyData skey[1]; - SysScanDesc sysscan; - HeapTuple tuple; - - ScanKeyEntryInitialize(&skey[0], 0x0, - (AttrNumber) Anum_pg_class_relname, - (RegProcedure) F_NAMEEQ, - CStringGetDatum(class_name_or_oid)); - - hdesc = heap_openr(RelationRelationName, AccessShareLock); - sysscan = systable_beginscan(hdesc, ClassNameNspIndex, true, - SnapshotNow, 1, skey); - - if (HeapTupleIsValid(tuple = systable_getnext(sysscan))) - result = tuple->t_data->t_oid; - else - elog(ERROR, "No class with name %s", class_name_or_oid); - - /* We assume there can be only one match */ - - systable_endscan(sysscan); - heap_close(hdesc, AccessShareLock); - - PG_RETURN_OID(result); - } - - /* - * Normal case: parse the name into components and see if it - * matches any pg_class entries in the current search path. - */ - names = stringToQualifiedNameList(class_name_or_oid, "regclassin"); - - result = RangeVarGetRelid(makeRangeVarFromNameList(names), false); - - PG_RETURN_OID(result); -} - -/* - * regclassout - converts class OID to "class_name" - */ -Datum -regclassout(PG_FUNCTION_ARGS) -{ - Oid classid = PG_GETARG_OID(0); - char *result; - HeapTuple classtup; - - if (classid == InvalidOid) - { - result = pstrdup("-"); - PG_RETURN_CSTRING(result); - } - - classtup = SearchSysCache(RELOID, - ObjectIdGetDatum(classid), - 0, 0, 0); - - if (HeapTupleIsValid(classtup)) - { - Form_pg_class classform = (Form_pg_class) GETSTRUCT(classtup); - char *classname = NameStr(classform->relname); - - /* - * In bootstrap mode, skip the fancy namespace stuff and just - * return the class name. (This path is only needed for debugging - * output anyway.) - */ - if (IsBootstrapProcessingMode()) - { - result = pstrdup(classname); - } - else - { - char *nspname; - - /* - * Would this class be found by regclassin? - * If not, qualify it. - */ - if (RelationIsVisible(classid)) - nspname = NULL; - else - nspname = get_namespace_name(classform->relnamespace); - - result = quote_qualified_identifier(nspname, classname); - } - - ReleaseSysCache(classtup); - } - else - { - /* If OID doesn't match any pg_class entry, return it numerically */ - result = (char *) palloc(NAMEDATALEN); - snprintf(result, NAMEDATALEN, "%u", classid); - } - - PG_RETURN_CSTRING(result); -} - - -/* - * regtypein - converts "typename" to type OID - * - * We also accept a numeric OID, mostly for historical reasons. - * - * '-' signifies unknown (OID 0). In all other cases, the input must - * match an existing pg_type entry. - * - * In bootstrap mode the name must just equal some existing name in pg_type. - * In normal mode the type name can be specified using the full type syntax - * recognized by the parser; for example, DOUBLE PRECISION and INTEGER[] will - * work and be translated to the correct type names. (We ignore any typmod - * info generated by the parser, however.) - */ -Datum -regtypein(PG_FUNCTION_ARGS) -{ - char *typ_name_or_oid = PG_GETARG_CSTRING(0); - Oid result = InvalidOid; - int32 typmod; - - /* '-' ? */ - if (strcmp(typ_name_or_oid, "-") == 0) - PG_RETURN_OID(InvalidOid); - - /* Numeric OID? */ - if (typ_name_or_oid[0] >= '0' && - typ_name_or_oid[0] <= '9' && - strspn(typ_name_or_oid, "0123456789") == strlen(typ_name_or_oid)) - { - Oid searchOid; - - searchOid = DatumGetObjectId(DirectFunctionCall1(oidin, - CStringGetDatum(typ_name_or_oid))); - result = GetSysCacheOid(TYPEOID, - ObjectIdGetDatum(searchOid), - 0, 0, 0); - if (!OidIsValid(result)) - elog(ERROR, "No type with oid %s", typ_name_or_oid); - PG_RETURN_OID(result); - } - - /* Else it's a type name, possibly schema-qualified or decorated */ - - /* - * In bootstrap mode we assume the given name is not schema-qualified, - * and just search pg_type for a match. This is needed for - * initializing other system catalogs (pg_namespace may not exist yet, - * and certainly there are no schemas other than pg_catalog). - */ - if (IsBootstrapProcessingMode()) - { - Relation hdesc; - ScanKeyData skey[1]; - SysScanDesc sysscan; - HeapTuple tuple; - - ScanKeyEntryInitialize(&skey[0], 0x0, - (AttrNumber) Anum_pg_type_typname, - (RegProcedure) F_NAMEEQ, - CStringGetDatum(typ_name_or_oid)); - - hdesc = heap_openr(TypeRelationName, AccessShareLock); - sysscan = systable_beginscan(hdesc, TypeNameNspIndex, true, - SnapshotNow, 1, skey); - - if (HeapTupleIsValid(tuple = systable_getnext(sysscan))) - result = tuple->t_data->t_oid; - else - elog(ERROR, "No type with name %s", typ_name_or_oid); - - /* We assume there can be only one match */ - - systable_endscan(sysscan); - heap_close(hdesc, AccessShareLock); - - PG_RETURN_OID(result); - } - - /* - * Normal case: invoke the full parser to deal with special cases - * such as array syntax. - */ - parseTypeString(typ_name_or_oid, &result, &typmod); - - PG_RETURN_OID(result); -} - -/* - * regtypeout - converts type OID to "typ_name" - */ -Datum -regtypeout(PG_FUNCTION_ARGS) -{ - Oid typid = PG_GETARG_OID(0); - char *result; - HeapTuple typetup; - - if (typid == InvalidOid) - { - result = pstrdup("-"); - PG_RETURN_CSTRING(result); - } - - typetup = SearchSysCache(TYPEOID, - ObjectIdGetDatum(typid), - 0, 0, 0); - - if (HeapTupleIsValid(typetup)) - { - Form_pg_type typeform = (Form_pg_type) GETSTRUCT(typetup); - - /* - * In bootstrap mode, skip the fancy namespace stuff and just - * return the type name. (This path is only needed for debugging - * output anyway.) - */ - if (IsBootstrapProcessingMode()) - { - char *typname = NameStr(typeform->typname); - - result = pstrdup(typname); - } - else - { - result = format_type_be(typid); - } - - ReleaseSysCache(typetup); - } - else - { - /* If OID doesn't match any pg_type entry, return it numerically */ - result = (char *) palloc(NAMEDATALEN); - snprintf(result, NAMEDATALEN, "%u", typid); - } - - PG_RETURN_CSTRING(result); -} - - -/* - * Given a C string, parse it into a qualified-name list. - */ -List * -stringToQualifiedNameList(const char *string, const char *caller) -{ - char *rawname; - List *result = NIL; - List *namelist; - List *l; - - /* We need a modifiable copy of the input string. */ - rawname = pstrdup(string); - - if (!SplitIdentifierString(rawname, '.', &namelist)) - elog(ERROR, "%s: invalid name syntax", caller); - - if (namelist == NIL) - elog(ERROR, "%s: invalid name syntax", caller); - - foreach(l, namelist) - { - char *curname = (char *) lfirst(l); - - result = lappend(result, makeString(pstrdup(curname))); - } - - pfree(rawname); - freeList(namelist); - - return result; -} - -/***************************************************************************** - * SUPPORT ROUTINES * - *****************************************************************************/ - -/* - * Given a C string, parse it into a qualified function or operator name - * followed by a parenthesized list of type names. Reduce the - * type names to an array of OIDs (returned into *nargs and *argtypes; - * the argtypes array should be of size FUNC_MAX_ARGS). The function or - * operator name is returned to *names as a List of Strings. - * - * If type0_spelling is not NULL, it is a name to be accepted as a - * placeholder for OID 0. - */ -static void -parseNameAndArgTypes(const char *string, const char *caller, - const char *type0_spelling, - List **names, int *nargs, Oid *argtypes) -{ - char *rawname; - char *ptr; - char *ptr2; - char *typename; - bool in_quote; - bool had_comma; - int paren_count; - Oid typeid; - int32 typmod; - - /* We need a modifiable copy of the input string. */ - rawname = pstrdup(string); - - /* Scan to find the expected left paren; mustn't be quoted */ - in_quote = false; - for (ptr = rawname; *ptr; ptr++) - { - if (*ptr == '"') - in_quote = !in_quote; - else if (*ptr == '(' && !in_quote) - break; - } - if (*ptr == '\0') - elog(ERROR, "%s: expected a left parenthesis", caller); - - /* Separate the name and parse it into a list */ - *ptr++ = '\0'; - *names = stringToQualifiedNameList(rawname, caller); - - /* Check for the trailing right parenthesis and remove it */ - ptr2 = ptr + strlen(ptr); - while (--ptr2 > ptr) - { - if (!isspace((unsigned char) *ptr2)) - break; - } - if (*ptr2 != ')') - elog(ERROR, "%s: expected a right parenthesis", caller); - *ptr2 = '\0'; - - /* Separate the remaining string into comma-separated type names */ - *nargs = 0; - had_comma = false; - - for (;;) - { - /* allow leading whitespace */ - while (isspace((unsigned char) *ptr)) - ptr++; - if (*ptr == '\0') - { - /* End of string. Okay unless we had a comma before. */ - if (had_comma) - elog(ERROR, "%s: expected a type name", caller); - break; - } - typename = ptr; - /* Find end of type name --- end of string or comma */ - /* ... but not a quoted or parenthesized comma */ - in_quote = false; - paren_count = 0; - for (; *ptr; ptr++) - { - if (*ptr == '"') - in_quote = !in_quote; - else if (*ptr == ',' && !in_quote && paren_count == 0) - break; - else if (!in_quote) - { - switch (*ptr) - { - case '(': - case '[': - paren_count++; - break; - case ')': - case ']': - paren_count--; - break; - } - } - } - if (in_quote || paren_count != 0) - elog(ERROR, "%s: improper type name", caller); - ptr2 = ptr; - if (*ptr == ',') - { - had_comma = true; - *ptr++ = '\0'; - } - else - { - had_comma = false; - Assert(*ptr == '\0'); - } - /* Lop off trailing whitespace */ - while (--ptr2 >= typename) - { - if (!isspace((unsigned char) *ptr2)) - break; - *ptr2 = '\0'; - } - - if (type0_spelling && strcasecmp(typename, type0_spelling) == 0) - { - /* Special case for OPAQUE or NONE */ - typeid = InvalidOid; - typmod = -1; - } - else - { - /* Use full parser to resolve the type name */ - parseTypeString(typename, &typeid, &typmod); - } - if (*nargs >= FUNC_MAX_ARGS) - elog(ERROR, "%s: too many argument datatypes", caller); - argtypes[*nargs] = typeid; - (*nargs)++; - } - - pfree(rawname); -} |