1 /*-------------------------------------------------------------------------
4 * Functions for the built-in types regproc, regclass, regtype, etc.
6 * These types are all binary-compatible with type Oid, and rely on Oid
7 * for comparison and so forth. Their only interesting behavior is in
8 * special I/O conversion routines.
11 * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
12 * Portions Copyright (c) 1994, Regents of the University of California
16 * $Header: /cvsroot/pgsql/src/backend/utils/adt/regproc.c,v 1.66 2002/04/25 02:56:55 tgl Exp $
18 *-------------------------------------------------------------------------
24 #include "access/genam.h"
25 #include "access/heapam.h"
26 #include "catalog/catname.h"
27 #include "catalog/indexing.h"
28 #include "catalog/namespace.h"
29 #include "catalog/pg_operator.h"
30 #include "catalog/pg_proc.h"
31 #include "catalog/pg_type.h"
32 #include "lib/stringinfo.h"
33 #include "miscadmin.h"
34 #include "parser/parse_type.h"
35 #include "utils/builtins.h"
36 #include "utils/fmgroids.h"
37 #include "utils/lsyscache.h"
38 #include "utils/syscache.h"
41 static List *stringToQualifiedNameList(const char *string, const char *caller);
42 static void parseNameAndArgTypes(const char *string, const char *caller,
44 List **names, int *nargs, Oid *argtypes);
47 /*****************************************************************************
49 *****************************************************************************/
52 * regprocin - converts "proname" to proc OID
54 * We also accept a numeric OID, mostly for historical reasons.
56 * '-' signifies unknown (OID 0). In all other cases, the input must
57 * match an existing pg_proc entry.
60 regprocin(PG_FUNCTION_ARGS)
62 char *pro_name_or_oid = PG_GETARG_CSTRING(0);
63 RegProcedure result = InvalidOid;
65 FuncCandidateList clist;
68 if (strcmp(pro_name_or_oid, "-") == 0)
69 PG_RETURN_OID(InvalidOid);
72 if (pro_name_or_oid[0] >= '0' &&
73 pro_name_or_oid[0] <= '9' &&
74 strspn(pro_name_or_oid, "0123456789") == strlen(pro_name_or_oid))
78 searchOid = DatumGetObjectId(DirectFunctionCall1(oidin,
79 CStringGetDatum(pro_name_or_oid)));
80 result = (RegProcedure) GetSysCacheOid(PROCOID,
81 ObjectIdGetDatum(searchOid),
83 if (!RegProcedureIsValid(result))
84 elog(ERROR, "No procedure with oid %s", pro_name_or_oid);
85 PG_RETURN_OID(result);
88 /* Else it's a name, possibly schema-qualified */
91 * In bootstrap mode we assume the given name is not schema-qualified,
92 * and just search pg_proc for a unique match. This is needed for
93 * initializing other system catalogs (pg_namespace may not exist yet,
94 * and certainly there are no schemas other than pg_catalog).
96 if (IsBootstrapProcessingMode())
104 ScanKeyEntryInitialize(&skey[0], 0x0,
105 (AttrNumber) Anum_pg_proc_proname,
106 (RegProcedure) F_NAMEEQ,
107 CStringGetDatum(pro_name_or_oid));
109 hdesc = heap_openr(ProcedureRelationName, AccessShareLock);
110 sysscan = systable_beginscan(hdesc, ProcedureNameNspIndex, true,
111 SnapshotNow, 1, skey);
113 while (HeapTupleIsValid(tuple = systable_getnext(sysscan)))
115 result = (RegProcedure) tuple->t_data->t_oid;
120 systable_endscan(sysscan);
121 heap_close(hdesc, AccessShareLock);
124 elog(ERROR, "No procedure with name %s", pro_name_or_oid);
125 else if (matches > 1)
126 elog(ERROR, "There is more than one procedure named %s",
128 PG_RETURN_OID(result);
132 * Normal case: parse the name into components and see if it
133 * matches any pg_proc entries in the current search path.
135 names = stringToQualifiedNameList(pro_name_or_oid, "regprocin");
136 clist = FuncnameGetCandidates(names, -1);
139 elog(ERROR, "No procedure with name %s", pro_name_or_oid);
140 else if (clist->next != NULL)
141 elog(ERROR, "There is more than one procedure named %s",
146 PG_RETURN_OID(result);
150 * regprocout - converts proc OID to "pro_name"
153 regprocout(PG_FUNCTION_ARGS)
155 RegProcedure proid = PG_GETARG_OID(0);
159 if (proid == InvalidOid)
161 result = pstrdup("-");
162 PG_RETURN_CSTRING(result);
165 proctup = SearchSysCache(PROCOID,
166 ObjectIdGetDatum(proid),
169 if (HeapTupleIsValid(proctup))
171 Form_pg_proc procform = (Form_pg_proc) GETSTRUCT(proctup);
172 char *proname = NameStr(procform->proname);
175 * In bootstrap mode, skip the fancy namespace stuff and just
176 * return the proc name. (This path is only needed for debugging
179 if (IsBootstrapProcessingMode())
181 result = pstrdup(proname);
186 FuncCandidateList clist;
189 * Would this proc be found (uniquely!) by regprocin?
190 * If not, qualify it.
192 clist = FuncnameGetCandidates(makeList1(makeString(proname)), -1);
193 if (clist != NULL && clist->next == NULL &&
197 nspname = get_namespace_name(procform->pronamespace);
199 result = quote_qualified_identifier(nspname, proname);
202 ReleaseSysCache(proctup);
206 /* If OID doesn't match any pg_proc entry, return it numerically */
207 result = (char *) palloc(NAMEDATALEN);
208 snprintf(result, NAMEDATALEN, "%u", proid);
211 PG_RETURN_CSTRING(result);
216 * regprocedurein - converts "proname(args)" to proc OID
218 * We also accept a numeric OID, mostly for historical reasons.
220 * '-' signifies unknown (OID 0). In all other cases, the input must
221 * match an existing pg_proc entry.
224 regprocedurein(PG_FUNCTION_ARGS)
226 char *pro_name_or_oid = PG_GETARG_CSTRING(0);
227 RegProcedure result = InvalidOid;
230 Oid argtypes[FUNC_MAX_ARGS];
231 FuncCandidateList clist;
234 if (strcmp(pro_name_or_oid, "-") == 0)
235 PG_RETURN_OID(InvalidOid);
238 if (pro_name_or_oid[0] >= '0' &&
239 pro_name_or_oid[0] <= '9' &&
240 strspn(pro_name_or_oid, "0123456789") == strlen(pro_name_or_oid))
244 searchOid = DatumGetObjectId(DirectFunctionCall1(oidin,
245 CStringGetDatum(pro_name_or_oid)));
246 result = (RegProcedure) GetSysCacheOid(PROCOID,
247 ObjectIdGetDatum(searchOid),
249 if (!RegProcedureIsValid(result))
250 elog(ERROR, "No procedure with oid %s", pro_name_or_oid);
251 PG_RETURN_OID(result);
255 * Else it's a name and arguments. Parse the name and arguments,
256 * look up potential matches in the current namespace search list,
257 * and scan to see which one exactly matches the given argument
258 * types. (There will not be more than one match.)
260 * XXX at present, this code will not work in bootstrap mode, hence this
261 * datatype cannot be used for any system column that needs to receive
262 * data during bootstrap.
264 parseNameAndArgTypes(pro_name_or_oid, "regprocedurein", false,
265 &names, &nargs, argtypes);
267 clist = FuncnameGetCandidates(names, nargs);
269 for (; clist; clist = clist->next)
271 if (memcmp(clist->args, argtypes, nargs * sizeof(Oid)) == 0)
276 elog(ERROR, "No procedure with name %s", pro_name_or_oid);
280 PG_RETURN_OID(result);
284 * regprocedureout - converts proc OID to "pro_name(args)"
287 regprocedureout(PG_FUNCTION_ARGS)
289 RegProcedure proid = PG_GETARG_OID(0);
293 if (proid == InvalidOid)
295 result = pstrdup("-");
296 PG_RETURN_CSTRING(result);
299 proctup = SearchSysCache(PROCOID,
300 ObjectIdGetDatum(proid),
303 if (HeapTupleIsValid(proctup))
305 Form_pg_proc procform = (Form_pg_proc) GETSTRUCT(proctup);
306 char *proname = NameStr(procform->proname);
307 int nargs = procform->pronargs;
310 FuncCandidateList clist;
313 /* XXX no support here for bootstrap mode */
316 * Would this proc be found (given the right args) by regprocedurein?
317 * If not, we need to qualify it.
319 clist = FuncnameGetCandidates(makeList1(makeString(proname)), nargs);
321 for (; clist; clist = clist->next)
323 if (memcmp(clist->args, procform->proargtypes,
324 nargs * sizeof(Oid)) == 0)
328 if (clist != NULL && clist->oid == proid)
331 nspname = get_namespace_name(procform->pronamespace);
333 initStringInfo(&buf);
335 appendStringInfo(&buf, "%s(",
336 quote_qualified_identifier(nspname, proname));
337 for (i = 0; i < nargs; i++)
339 appendStringInfo(&buf, "%s%s",
341 format_type_be(procform->proargtypes[i]));
344 appendStringInfo(&buf, ")");
348 ReleaseSysCache(proctup);
352 /* If OID doesn't match any pg_proc entry, return it numerically */
353 result = (char *) palloc(NAMEDATALEN);
354 snprintf(result, NAMEDATALEN, "%u", proid);
357 PG_RETURN_CSTRING(result);
362 * regoperin - converts "oprname" to operator OID
364 * We also accept a numeric OID, mostly for historical reasons.
366 * '0' signifies unknown (OID 0). In all other cases, the input must
367 * match an existing pg_operator entry.
370 regoperin(PG_FUNCTION_ARGS)
372 char *opr_name_or_oid = PG_GETARG_CSTRING(0);
373 Oid result = InvalidOid;
375 FuncCandidateList clist;
378 if (strcmp(opr_name_or_oid, "0") == 0)
379 PG_RETURN_OID(InvalidOid);
382 if (opr_name_or_oid[0] >= '0' &&
383 opr_name_or_oid[0] <= '9' &&
384 strspn(opr_name_or_oid, "0123456789") == strlen(opr_name_or_oid))
388 searchOid = DatumGetObjectId(DirectFunctionCall1(oidin,
389 CStringGetDatum(opr_name_or_oid)));
390 result = GetSysCacheOid(OPEROID,
391 ObjectIdGetDatum(searchOid),
393 if (!OidIsValid(result))
394 elog(ERROR, "No operator with oid %s", opr_name_or_oid);
395 PG_RETURN_OID(result);
398 /* Else it's a name, possibly schema-qualified */
401 * In bootstrap mode we assume the given name is not schema-qualified,
402 * and just search pg_operator for a unique match. This is needed for
403 * initializing other system catalogs (pg_namespace may not exist yet,
404 * and certainly there are no schemas other than pg_catalog).
406 if (IsBootstrapProcessingMode())
414 ScanKeyEntryInitialize(&skey[0], 0x0,
415 (AttrNumber) Anum_pg_operator_oprname,
416 (RegProcedure) F_NAMEEQ,
417 CStringGetDatum(opr_name_or_oid));
419 hdesc = heap_openr(OperatorRelationName, AccessShareLock);
420 sysscan = systable_beginscan(hdesc, OperatorNameNspIndex, true,
421 SnapshotNow, 1, skey);
423 while (HeapTupleIsValid(tuple = systable_getnext(sysscan)))
425 result = tuple->t_data->t_oid;
430 systable_endscan(sysscan);
431 heap_close(hdesc, AccessShareLock);
434 elog(ERROR, "No operator with name %s", opr_name_or_oid);
435 else if (matches > 1)
436 elog(ERROR, "There is more than one operator named %s",
438 PG_RETURN_OID(result);
442 * Normal case: parse the name into components and see if it
443 * matches any pg_operator entries in the current search path.
445 names = stringToQualifiedNameList(opr_name_or_oid, "regoperin");
446 clist = OpernameGetCandidates(names, '\0');
449 elog(ERROR, "No operator with name %s", opr_name_or_oid);
450 else if (clist->next != NULL)
451 elog(ERROR, "There is more than one operator named %s",
456 PG_RETURN_OID(result);
460 * regoperout - converts operator OID to "opr_name"
463 regoperout(PG_FUNCTION_ARGS)
465 Oid oprid = PG_GETARG_OID(0);
469 if (oprid == InvalidOid)
471 result = pstrdup("0");
472 PG_RETURN_CSTRING(result);
475 opertup = SearchSysCache(OPEROID,
476 ObjectIdGetDatum(oprid),
479 if (HeapTupleIsValid(opertup))
481 Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup);
482 char *oprname = NameStr(operform->oprname);
485 * In bootstrap mode, skip the fancy namespace stuff and just
486 * return the oper name. (This path is only needed for debugging
489 if (IsBootstrapProcessingMode())
491 result = pstrdup(oprname);
495 FuncCandidateList clist;
498 * Would this oper be found (uniquely!) by regoperin?
499 * If not, qualify it.
501 clist = OpernameGetCandidates(makeList1(makeString(oprname)),
503 if (clist != NULL && clist->next == NULL &&
505 result = pstrdup(oprname);
510 nspname = get_namespace_name(operform->oprnamespace);
511 nspname = quote_identifier(nspname);
512 result = (char *) palloc(strlen(nspname)+strlen(oprname)+2);
513 sprintf(result, "%s.%s", nspname, oprname);
517 ReleaseSysCache(opertup);
521 /* If OID doesn't match any pg_operator entry, return it numerically */
522 result = (char *) palloc(NAMEDATALEN);
523 snprintf(result, NAMEDATALEN, "%u", oprid);
526 PG_RETURN_CSTRING(result);
531 * regoperatorin - converts "oprname(args)" to operator OID
533 * We also accept a numeric OID, mostly for historical reasons.
535 * '0' signifies unknown (OID 0). In all other cases, the input must
536 * match an existing pg_operator entry.
539 regoperatorin(PG_FUNCTION_ARGS)
541 char *opr_name_or_oid = PG_GETARG_CSTRING(0);
542 Oid result = InvalidOid;
545 Oid argtypes[FUNC_MAX_ARGS];
547 FuncCandidateList clist;
550 if (strcmp(opr_name_or_oid, "0") == 0)
551 PG_RETURN_OID(InvalidOid);
554 if (opr_name_or_oid[0] >= '0' &&
555 opr_name_or_oid[0] <= '9' &&
556 strspn(opr_name_or_oid, "0123456789") == strlen(opr_name_or_oid))
560 searchOid = DatumGetObjectId(DirectFunctionCall1(oidin,
561 CStringGetDatum(opr_name_or_oid)));
562 result = GetSysCacheOid(OPEROID,
563 ObjectIdGetDatum(searchOid),
565 if (!OidIsValid(result))
566 elog(ERROR, "No operator with oid %s", opr_name_or_oid);
567 PG_RETURN_OID(result);
571 * Else it's a name and arguments. Parse the name and arguments,
572 * look up potential matches in the current namespace search list,
573 * and scan to see which one exactly matches the given argument
574 * types. (There will not be more than one match.)
576 * XXX at present, this code will not work in bootstrap mode, hence this
577 * datatype cannot be used for any system column that needs to receive
578 * data during bootstrap.
580 parseNameAndArgTypes(opr_name_or_oid, "regoperatorin", true,
581 &names, &nargs, argtypes);
583 elog(ERROR, "regoperatorin: use NONE to denote the missing argument of a unary operator");
585 elog(ERROR, "regoperatorin: provide two argument types for operator");
587 if (argtypes[0] == InvalidOid)
589 else if (argtypes[1] == InvalidOid)
594 clist = OpernameGetCandidates(names, oprkind);
596 for (; clist; clist = clist->next)
598 if (memcmp(clist->args, argtypes, 2 * sizeof(Oid)) == 0)
603 elog(ERROR, "No operator with name %s", opr_name_or_oid);
607 PG_RETURN_OID(result);
611 * regoperatorout - converts operator OID to "opr_name(args)"
614 regoperatorout(PG_FUNCTION_ARGS)
616 Oid oprid = PG_GETARG_OID(0);
620 if (oprid == InvalidOid)
622 result = pstrdup("0");
623 PG_RETURN_CSTRING(result);
626 opertup = SearchSysCache(OPEROID,
627 ObjectIdGetDatum(oprid),
630 if (HeapTupleIsValid(opertup))
632 Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup);
633 char *oprname = NameStr(operform->oprname);
635 FuncCandidateList clist;
638 /* XXX no support here for bootstrap mode */
641 * Would this oper be found (given the right args) by regoperatorin?
642 * If not, we need to qualify it.
644 clist = OpernameGetCandidates(makeList1(makeString(oprname)),
647 for (; clist; clist = clist->next)
649 if (clist->args[0] == operform->oprleft &&
650 clist->args[1] == operform->oprright)
654 initStringInfo(&buf);
656 if (clist == NULL || clist->oid != oprid)
658 nspname = get_namespace_name(operform->oprnamespace);
659 appendStringInfo(&buf, "%s.",
660 quote_identifier(nspname));
663 appendStringInfo(&buf, "%s(", oprname);
665 if (operform->oprleft)
666 appendStringInfo(&buf, "%s,",
667 format_type_be(operform->oprleft));
669 appendStringInfo(&buf, "NONE,");
671 if (operform->oprright)
672 appendStringInfo(&buf, "%s)",
673 format_type_be(operform->oprright));
675 appendStringInfo(&buf, "NONE)");
679 ReleaseSysCache(opertup);
683 /* If OID doesn't match any pg_operator entry, return it numerically */
684 result = (char *) palloc(NAMEDATALEN);
685 snprintf(result, NAMEDATALEN, "%u", oprid);
688 PG_RETURN_CSTRING(result);
693 * regclassin - converts "classname" to class OID
695 * We also accept a numeric OID, mostly for historical reasons.
697 * '-' signifies unknown (OID 0). In all other cases, the input must
698 * match an existing pg_class entry.
701 regclassin(PG_FUNCTION_ARGS)
703 char *class_name_or_oid = PG_GETARG_CSTRING(0);
704 Oid result = InvalidOid;
708 if (strcmp(class_name_or_oid, "-") == 0)
709 PG_RETURN_OID(InvalidOid);
712 if (class_name_or_oid[0] >= '0' &&
713 class_name_or_oid[0] <= '9' &&
714 strspn(class_name_or_oid, "0123456789") == strlen(class_name_or_oid))
718 searchOid = DatumGetObjectId(DirectFunctionCall1(oidin,
719 CStringGetDatum(class_name_or_oid)));
720 result = GetSysCacheOid(RELOID,
721 ObjectIdGetDatum(searchOid),
723 if (!OidIsValid(result))
724 elog(ERROR, "No class with oid %s", class_name_or_oid);
725 PG_RETURN_OID(result);
728 /* Else it's a name, possibly schema-qualified */
731 * In bootstrap mode we assume the given name is not schema-qualified,
732 * and just search pg_class for a match. This is needed for
733 * initializing other system catalogs (pg_namespace may not exist yet,
734 * and certainly there are no schemas other than pg_catalog).
736 if (IsBootstrapProcessingMode())
743 ScanKeyEntryInitialize(&skey[0], 0x0,
744 (AttrNumber) Anum_pg_class_relname,
745 (RegProcedure) F_NAMEEQ,
746 CStringGetDatum(class_name_or_oid));
748 hdesc = heap_openr(RelationRelationName, AccessShareLock);
749 sysscan = systable_beginscan(hdesc, ClassNameNspIndex, true,
750 SnapshotNow, 1, skey);
752 if (HeapTupleIsValid(tuple = systable_getnext(sysscan)))
753 result = tuple->t_data->t_oid;
755 elog(ERROR, "No class with name %s", class_name_or_oid);
757 /* We assume there can be only one match */
759 systable_endscan(sysscan);
760 heap_close(hdesc, AccessShareLock);
762 PG_RETURN_OID(result);
766 * Normal case: parse the name into components and see if it
767 * matches any pg_class entries in the current search path.
769 names = stringToQualifiedNameList(class_name_or_oid, "regclassin");
771 result = RangeVarGetRelid(makeRangeVarFromNameList(names), false);
773 PG_RETURN_OID(result);
777 * regclassout - converts class OID to "class_name"
780 regclassout(PG_FUNCTION_ARGS)
782 Oid classid = PG_GETARG_OID(0);
786 if (classid == InvalidOid)
788 result = pstrdup("-");
789 PG_RETURN_CSTRING(result);
792 classtup = SearchSysCache(RELOID,
793 ObjectIdGetDatum(classid),
796 if (HeapTupleIsValid(classtup))
798 Form_pg_class classform = (Form_pg_class) GETSTRUCT(classtup);
799 char *classname = NameStr(classform->relname);
802 * In bootstrap mode, skip the fancy namespace stuff and just
803 * return the class name. (This path is only needed for debugging
806 if (IsBootstrapProcessingMode())
808 result = pstrdup(classname);
815 * Would this class be found by regclassin?
816 * If not, qualify it.
818 if (RelnameGetRelid(classname) == classid)
821 nspname = get_namespace_name(classform->relnamespace);
823 result = quote_qualified_identifier(nspname, classname);
826 ReleaseSysCache(classtup);
830 /* If OID doesn't match any pg_class entry, return it numerically */
831 result = (char *) palloc(NAMEDATALEN);
832 snprintf(result, NAMEDATALEN, "%u", classid);
835 PG_RETURN_CSTRING(result);
840 * regtypein - converts "typename" to type OID
842 * We also accept a numeric OID, mostly for historical reasons.
844 * '-' signifies unknown (OID 0). In all other cases, the input must
845 * match an existing pg_type entry.
847 * In bootstrap mode the name must just equal some existing name in pg_type.
848 * In normal mode the type name can be specified using the full type syntax
849 * recognized by the parser; for example, DOUBLE PRECISION and INTEGER[] will
850 * work and be translated to the correct type names. (We ignore any typmod
851 * info generated by the parser, however.)
854 regtypein(PG_FUNCTION_ARGS)
856 char *typ_name_or_oid = PG_GETARG_CSTRING(0);
857 Oid result = InvalidOid;
861 if (strcmp(typ_name_or_oid, "-") == 0)
862 PG_RETURN_OID(InvalidOid);
865 if (typ_name_or_oid[0] >= '0' &&
866 typ_name_or_oid[0] <= '9' &&
867 strspn(typ_name_or_oid, "0123456789") == strlen(typ_name_or_oid))
871 searchOid = DatumGetObjectId(DirectFunctionCall1(oidin,
872 CStringGetDatum(typ_name_or_oid)));
873 result = GetSysCacheOid(TYPEOID,
874 ObjectIdGetDatum(searchOid),
876 if (!OidIsValid(result))
877 elog(ERROR, "No type with oid %s", typ_name_or_oid);
878 PG_RETURN_OID(result);
881 /* Else it's a type name, possibly schema-qualified or decorated */
884 * In bootstrap mode we assume the given name is not schema-qualified,
885 * and just search pg_type for a match. This is needed for
886 * initializing other system catalogs (pg_namespace may not exist yet,
887 * and certainly there are no schemas other than pg_catalog).
889 if (IsBootstrapProcessingMode())
896 ScanKeyEntryInitialize(&skey[0], 0x0,
897 (AttrNumber) Anum_pg_type_typname,
898 (RegProcedure) F_NAMEEQ,
899 CStringGetDatum(typ_name_or_oid));
901 hdesc = heap_openr(TypeRelationName, AccessShareLock);
902 sysscan = systable_beginscan(hdesc, TypeNameNspIndex, true,
903 SnapshotNow, 1, skey);
905 if (HeapTupleIsValid(tuple = systable_getnext(sysscan)))
906 result = tuple->t_data->t_oid;
908 elog(ERROR, "No type with name %s", typ_name_or_oid);
910 /* We assume there can be only one match */
912 systable_endscan(sysscan);
913 heap_close(hdesc, AccessShareLock);
915 PG_RETURN_OID(result);
919 * Normal case: invoke the full parser to deal with special cases
920 * such as array syntax.
922 parseTypeString(typ_name_or_oid, &result, &typmod);
924 PG_RETURN_OID(result);
928 * regtypeout - converts type OID to "typ_name"
931 regtypeout(PG_FUNCTION_ARGS)
933 Oid typid = PG_GETARG_OID(0);
937 if (typid == InvalidOid)
939 result = pstrdup("-");
940 PG_RETURN_CSTRING(result);
943 typetup = SearchSysCache(TYPEOID,
944 ObjectIdGetDatum(typid),
947 if (HeapTupleIsValid(typetup))
949 Form_pg_type typeform = (Form_pg_type) GETSTRUCT(typetup);
950 char *typname = NameStr(typeform->typname);
953 * In bootstrap mode, skip the fancy namespace stuff and just
954 * return the type name. (This path is only needed for debugging
957 if (IsBootstrapProcessingMode())
959 result = pstrdup(typname);
966 * Would this type be found by regtypein?
967 * If not, qualify it.
969 * XXX shouldn't we use format_type instead?
971 if (TypenameGetTypid(typname) == typid)
974 nspname = get_namespace_name(typeform->typnamespace);
976 result = quote_qualified_identifier(nspname, typname);
979 ReleaseSysCache(typetup);
983 /* If OID doesn't match any pg_type entry, return it numerically */
984 result = (char *) palloc(NAMEDATALEN);
985 snprintf(result, NAMEDATALEN, "%u", typid);
988 PG_RETURN_CSTRING(result);
992 /*****************************************************************************
994 *****************************************************************************/
997 * Given a C string, parse it into a qualified-name list.
1000 stringToQualifiedNameList(const char *string, const char *caller)
1007 /* We need a modifiable copy of the input string. */
1008 rawname = pstrdup(string);
1010 if (!SplitIdentifierString(rawname, '.', &namelist))
1011 elog(ERROR, "%s: invalid name syntax", caller);
1013 if (namelist == NIL)
1014 elog(ERROR, "%s: invalid name syntax", caller);
1016 foreach(l, namelist)
1018 char *curname = (char *) lfirst(l);
1020 result = lappend(result, makeString(pstrdup(curname)));
1030 * Given a C string, parse it into a qualified function or operator name
1031 * followed by a parenthesized list of type names. Reduce the
1032 * type names to an array of OIDs (returned into *nargs and *argtypes;
1033 * the argtypes array should be of size FUNC_MAX_ARGS). The function or
1034 * operator name is returned to *names as a List of Strings.
1036 * NONE is accepted as a placeholder for OID 0 if allow_none is true.
1039 parseNameAndArgTypes(const char *string, const char *caller, bool allow_none,
1040 List **names, int *nargs, Oid *argtypes)
1052 /* We need a modifiable copy of the input string. */
1053 rawname = pstrdup(string);
1055 /* Scan to find the expected left paren; mustn't be quoted */
1057 for (ptr = rawname; *ptr; ptr++)
1060 in_quote = !in_quote;
1061 else if (*ptr == '(' && !in_quote)
1065 elog(ERROR, "%s: expected a left parenthesis", caller);
1067 /* Separate the name and parse it into a list */
1069 *names = stringToQualifiedNameList(rawname, caller);
1071 /* Check for the trailing right parenthesis and remove it */
1072 ptr2 = ptr + strlen(ptr);
1073 while (--ptr2 > ptr)
1075 if (!isspace((unsigned char) *ptr2))
1079 elog(ERROR, "%s: expected a right parenthesis", caller);
1082 /* Separate the remaining string into comma-separated type names */
1088 /* allow leading whitespace */
1089 while (isspace((unsigned char) *ptr))
1093 /* End of string. Okay unless we had a comma before. */
1095 elog(ERROR, "%s: expected a type name", caller);
1099 /* Find end of type name --- end of string or comma */
1100 /* ... but not a quoted or parenthesized comma */
1106 in_quote = !in_quote;
1107 else if (*ptr == ',' && !in_quote && paren_count == 0)
1124 if (in_quote || paren_count != 0)
1125 elog(ERROR, "%s: improper type name", caller);
1135 Assert(*ptr == '\0');
1137 /* Lop off trailing whitespace */
1138 while (--ptr2 >= typename)
1140 if (!isspace((unsigned char) *ptr2))
1145 if (allow_none && strcasecmp(typename, "none") == 0)
1147 /* Report NONE as OID 0 */
1148 typeid = InvalidOid;
1153 /* Use full parser to resolve the type name */
1154 parseTypeString(typename, &typeid, &typmod);
1156 if (*nargs >= FUNC_MAX_ARGS)
1157 elog(ERROR, "%s: too many argument datatypes", caller);
1158 argtypes[*nargs] = typeid;