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-2004, PostgreSQL Global Development Group
12 * Portions Copyright (c) 1994, Regents of the University of California
16 * $PostgreSQL: pgsql/src/backend/utils/adt/regproc.c,v 1.91 2004/08/29 05:06:49 momjian 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"
40 static void parseNameAndArgTypes(const char *string, const char *caller,
42 List **names, int *nargs, Oid *argtypes);
45 /*****************************************************************************
47 *****************************************************************************/
50 * regprocin - converts "proname" to proc OID
52 * We also accept a numeric OID, for symmetry with the output routine.
54 * '-' signifies unknown (OID 0). In all other cases, the input must
55 * match an existing pg_proc entry.
58 regprocin(PG_FUNCTION_ARGS)
60 char *pro_name_or_oid = PG_GETARG_CSTRING(0);
61 RegProcedure result = InvalidOid;
63 FuncCandidateList clist;
66 if (strcmp(pro_name_or_oid, "-") == 0)
67 PG_RETURN_OID(InvalidOid);
70 if (pro_name_or_oid[0] >= '0' &&
71 pro_name_or_oid[0] <= '9' &&
72 strspn(pro_name_or_oid, "0123456789") == strlen(pro_name_or_oid))
74 result = DatumGetObjectId(DirectFunctionCall1(oidin,
75 CStringGetDatum(pro_name_or_oid)));
76 PG_RETURN_OID(result);
79 /* Else it's a name, possibly schema-qualified */
82 * In bootstrap mode we assume the given name is not schema-qualified,
83 * and just search pg_proc for a unique match. This is needed for
84 * initializing other system catalogs (pg_namespace may not exist yet,
85 * and certainly there are no schemas other than pg_catalog).
87 if (IsBootstrapProcessingMode())
97 BTEqualStrategyNumber, F_NAMEEQ,
98 CStringGetDatum(pro_name_or_oid));
100 hdesc = heap_openr(ProcedureRelationName, AccessShareLock);
101 sysscan = systable_beginscan(hdesc, ProcedureNameNspIndex, true,
102 SnapshotNow, 1, skey);
104 while (HeapTupleIsValid(tuple = systable_getnext(sysscan)))
106 result = (RegProcedure) HeapTupleGetOid(tuple);
111 systable_endscan(sysscan);
112 heap_close(hdesc, AccessShareLock);
116 (errcode(ERRCODE_UNDEFINED_FUNCTION),
117 errmsg("function \"%s\" does not exist", pro_name_or_oid)));
119 else if (matches > 1)
121 (errcode(ERRCODE_AMBIGUOUS_FUNCTION),
122 errmsg("more than one function named \"%s\"",
125 PG_RETURN_OID(result);
129 * Normal case: parse the name into components and see if it matches
130 * any pg_proc entries in the current search path.
132 names = stringToQualifiedNameList(pro_name_or_oid, "regprocin");
133 clist = FuncnameGetCandidates(names, -1);
137 (errcode(ERRCODE_UNDEFINED_FUNCTION),
138 errmsg("function \"%s\" does not exist", pro_name_or_oid)));
139 else if (clist->next != NULL)
141 (errcode(ERRCODE_AMBIGUOUS_FUNCTION),
142 errmsg("more than one function named \"%s\"",
147 PG_RETURN_OID(result);
151 * regprocout - converts proc OID to "pro_name"
154 regprocout(PG_FUNCTION_ARGS)
156 RegProcedure proid = PG_GETARG_OID(0);
160 if (proid == InvalidOid)
162 result = pstrdup("-");
163 PG_RETURN_CSTRING(result);
166 proctup = SearchSysCache(PROCOID,
167 ObjectIdGetDatum(proid),
170 if (HeapTupleIsValid(proctup))
172 Form_pg_proc procform = (Form_pg_proc) GETSTRUCT(proctup);
173 char *proname = NameStr(procform->proname);
176 * In bootstrap mode, skip the fancy namespace stuff and just
177 * return the proc name. (This path is only needed for debugging
180 if (IsBootstrapProcessingMode())
181 result = pstrdup(proname);
185 FuncCandidateList clist;
188 * Would this proc be found (uniquely!) by regprocin? If not,
191 clist = FuncnameGetCandidates(list_make1(makeString(proname)), -1);
192 if (clist != NULL && clist->next == NULL &&
196 nspname = get_namespace_name(procform->pronamespace);
198 result = quote_qualified_identifier(nspname, proname);
201 ReleaseSysCache(proctup);
205 /* If OID doesn't match any pg_proc entry, return it numerically */
206 result = (char *) palloc(NAMEDATALEN);
207 snprintf(result, NAMEDATALEN, "%u", proid);
210 PG_RETURN_CSTRING(result);
214 * regprocrecv - converts external binary format to regproc
217 regprocrecv(PG_FUNCTION_ARGS)
219 /* Exactly the same as oidrecv, so share code */
220 return oidrecv(fcinfo);
224 * regprocsend - converts regproc to binary format
227 regprocsend(PG_FUNCTION_ARGS)
229 /* Exactly the same as oidsend, so share code */
230 return oidsend(fcinfo);
235 * regprocedurein - converts "proname(args)" to proc OID
237 * We also accept a numeric OID, for symmetry with the output routine.
239 * '-' signifies unknown (OID 0). In all other cases, the input must
240 * match an existing pg_proc entry.
243 regprocedurein(PG_FUNCTION_ARGS)
245 char *pro_name_or_oid = PG_GETARG_CSTRING(0);
246 RegProcedure result = InvalidOid;
249 Oid argtypes[FUNC_MAX_ARGS];
250 FuncCandidateList clist;
253 if (strcmp(pro_name_or_oid, "-") == 0)
254 PG_RETURN_OID(InvalidOid);
257 if (pro_name_or_oid[0] >= '0' &&
258 pro_name_or_oid[0] <= '9' &&
259 strspn(pro_name_or_oid, "0123456789") == strlen(pro_name_or_oid))
261 result = DatumGetObjectId(DirectFunctionCall1(oidin,
262 CStringGetDatum(pro_name_or_oid)));
263 PG_RETURN_OID(result);
267 * Else it's a name and arguments. Parse the name and arguments, look
268 * up potential matches in the current namespace search list, and scan
269 * to see which one exactly matches the given argument types. (There
270 * will not be more than one match.)
272 * XXX at present, this code will not work in bootstrap mode, hence this
273 * datatype cannot be used for any system column that needs to receive
274 * data during bootstrap.
276 parseNameAndArgTypes(pro_name_or_oid, "regprocedurein", false,
277 &names, &nargs, argtypes);
279 clist = FuncnameGetCandidates(names, nargs);
281 for (; clist; clist = clist->next)
283 if (memcmp(clist->args, argtypes, nargs * sizeof(Oid)) == 0)
289 (errcode(ERRCODE_UNDEFINED_FUNCTION),
290 errmsg("function \"%s\" does not exist", pro_name_or_oid)));
294 PG_RETURN_OID(result);
298 * format_procedure - converts proc OID to "pro_name(args)"
300 * This exports the useful functionality of regprocedureout for use
301 * in other backend modules. The result is a palloc'd string.
304 format_procedure(Oid procedure_oid)
309 proctup = SearchSysCache(PROCOID,
310 ObjectIdGetDatum(procedure_oid),
313 if (HeapTupleIsValid(proctup))
315 Form_pg_proc procform = (Form_pg_proc) GETSTRUCT(proctup);
316 char *proname = NameStr(procform->proname);
317 int nargs = procform->pronargs;
322 /* XXX no support here for bootstrap mode */
324 initStringInfo(&buf);
327 * Would this proc be found (given the right args) by
328 * regprocedurein? If not, we need to qualify it.
330 if (FunctionIsVisible(procedure_oid))
333 nspname = get_namespace_name(procform->pronamespace);
335 appendStringInfo(&buf, "%s(",
336 quote_qualified_identifier(nspname, proname));
337 for (i = 0; i < nargs; i++)
339 Oid thisargtype = procform->proargtypes[i];
342 appendStringInfoChar(&buf, ',');
343 appendStringInfoString(&buf, format_type_be(thisargtype));
345 appendStringInfoChar(&buf, ')');
349 ReleaseSysCache(proctup);
353 /* If OID doesn't match any pg_proc entry, return it numerically */
354 result = (char *) palloc(NAMEDATALEN);
355 snprintf(result, NAMEDATALEN, "%u", procedure_oid);
362 * regprocedureout - converts proc OID to "pro_name(args)"
365 regprocedureout(PG_FUNCTION_ARGS)
367 RegProcedure proid = PG_GETARG_OID(0);
370 if (proid == InvalidOid)
371 result = pstrdup("-");
373 result = format_procedure(proid);
375 PG_RETURN_CSTRING(result);
379 * regprocedurerecv - converts external binary format to regprocedure
382 regprocedurerecv(PG_FUNCTION_ARGS)
384 /* Exactly the same as oidrecv, so share code */
385 return oidrecv(fcinfo);
389 * regproceduresend - converts regprocedure to binary format
392 regproceduresend(PG_FUNCTION_ARGS)
394 /* Exactly the same as oidsend, so share code */
395 return oidsend(fcinfo);
400 * regoperin - converts "oprname" to operator OID
402 * We also accept a numeric OID, for symmetry with the output routine.
404 * '0' signifies unknown (OID 0). In all other cases, the input must
405 * match an existing pg_operator entry.
408 regoperin(PG_FUNCTION_ARGS)
410 char *opr_name_or_oid = PG_GETARG_CSTRING(0);
411 Oid result = InvalidOid;
413 FuncCandidateList clist;
416 if (strcmp(opr_name_or_oid, "0") == 0)
417 PG_RETURN_OID(InvalidOid);
420 if (opr_name_or_oid[0] >= '0' &&
421 opr_name_or_oid[0] <= '9' &&
422 strspn(opr_name_or_oid, "0123456789") == strlen(opr_name_or_oid))
424 result = DatumGetObjectId(DirectFunctionCall1(oidin,
425 CStringGetDatum(opr_name_or_oid)));
426 PG_RETURN_OID(result);
429 /* Else it's a name, possibly schema-qualified */
432 * In bootstrap mode we assume the given name is not schema-qualified,
433 * and just search pg_operator for a unique match. This is needed for
434 * initializing other system catalogs (pg_namespace may not exist yet,
435 * and certainly there are no schemas other than pg_catalog).
437 if (IsBootstrapProcessingMode())
445 ScanKeyInit(&skey[0],
446 Anum_pg_operator_oprname,
447 BTEqualStrategyNumber, F_NAMEEQ,
448 CStringGetDatum(opr_name_or_oid));
450 hdesc = heap_openr(OperatorRelationName, AccessShareLock);
451 sysscan = systable_beginscan(hdesc, OperatorNameNspIndex, true,
452 SnapshotNow, 1, skey);
454 while (HeapTupleIsValid(tuple = systable_getnext(sysscan)))
456 result = HeapTupleGetOid(tuple);
461 systable_endscan(sysscan);
462 heap_close(hdesc, AccessShareLock);
466 (errcode(ERRCODE_UNDEFINED_FUNCTION),
467 errmsg("operator does not exist: %s", opr_name_or_oid)));
468 else if (matches > 1)
470 (errcode(ERRCODE_AMBIGUOUS_FUNCTION),
471 errmsg("more than one operator named %s",
474 PG_RETURN_OID(result);
478 * Normal case: parse the name into components and see if it matches
479 * any pg_operator entries in the current search path.
481 names = stringToQualifiedNameList(opr_name_or_oid, "regoperin");
482 clist = OpernameGetCandidates(names, '\0');
486 (errcode(ERRCODE_UNDEFINED_FUNCTION),
487 errmsg("operator does not exist: %s", opr_name_or_oid)));
488 else if (clist->next != NULL)
490 (errcode(ERRCODE_AMBIGUOUS_FUNCTION),
491 errmsg("more than one operator named %s",
496 PG_RETURN_OID(result);
500 * regoperout - converts operator OID to "opr_name"
503 regoperout(PG_FUNCTION_ARGS)
505 Oid oprid = PG_GETARG_OID(0);
509 if (oprid == InvalidOid)
511 result = pstrdup("0");
512 PG_RETURN_CSTRING(result);
515 opertup = SearchSysCache(OPEROID,
516 ObjectIdGetDatum(oprid),
519 if (HeapTupleIsValid(opertup))
521 Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup);
522 char *oprname = NameStr(operform->oprname);
525 * In bootstrap mode, skip the fancy namespace stuff and just
526 * return the oper name. (This path is only needed for debugging
529 if (IsBootstrapProcessingMode())
530 result = pstrdup(oprname);
533 FuncCandidateList clist;
536 * Would this oper be found (uniquely!) by regoperin? If not,
539 clist = OpernameGetCandidates(list_make1(makeString(oprname)),
541 if (clist != NULL && clist->next == NULL &&
543 result = pstrdup(oprname);
548 nspname = get_namespace_name(operform->oprnamespace);
549 nspname = quote_identifier(nspname);
550 result = (char *) palloc(strlen(nspname) + strlen(oprname) + 2);
551 sprintf(result, "%s.%s", nspname, oprname);
555 ReleaseSysCache(opertup);
560 * If OID doesn't match any pg_operator entry, return it
563 result = (char *) palloc(NAMEDATALEN);
564 snprintf(result, NAMEDATALEN, "%u", oprid);
567 PG_RETURN_CSTRING(result);
571 * regoperrecv - converts external binary format to regoper
574 regoperrecv(PG_FUNCTION_ARGS)
576 /* Exactly the same as oidrecv, so share code */
577 return oidrecv(fcinfo);
581 * regopersend - converts regoper to binary format
584 regopersend(PG_FUNCTION_ARGS)
586 /* Exactly the same as oidsend, so share code */
587 return oidsend(fcinfo);
592 * regoperatorin - converts "oprname(args)" to operator OID
594 * We also accept a numeric OID, for symmetry with the output routine.
596 * '0' signifies unknown (OID 0). In all other cases, the input must
597 * match an existing pg_operator entry.
600 regoperatorin(PG_FUNCTION_ARGS)
602 char *opr_name_or_oid = PG_GETARG_CSTRING(0);
603 Oid result = InvalidOid;
606 Oid argtypes[FUNC_MAX_ARGS];
608 FuncCandidateList clist;
611 if (strcmp(opr_name_or_oid, "0") == 0)
612 PG_RETURN_OID(InvalidOid);
615 if (opr_name_or_oid[0] >= '0' &&
616 opr_name_or_oid[0] <= '9' &&
617 strspn(opr_name_or_oid, "0123456789") == strlen(opr_name_or_oid))
619 result = DatumGetObjectId(DirectFunctionCall1(oidin,
620 CStringGetDatum(opr_name_or_oid)));
621 PG_RETURN_OID(result);
625 * Else it's a name and arguments. Parse the name and arguments, look
626 * up potential matches in the current namespace search list, and scan
627 * to see which one exactly matches the given argument types. (There
628 * will not be more than one match.)
630 * XXX at present, this code will not work in bootstrap mode, hence this
631 * datatype cannot be used for any system column that needs to receive
632 * data during bootstrap.
634 parseNameAndArgTypes(opr_name_or_oid, "regoperatorin", true,
635 &names, &nargs, argtypes);
638 (errcode(ERRCODE_UNDEFINED_PARAMETER),
639 errmsg("missing argument"),
640 errhint("Use NONE to denote the missing argument of a unary operator.")));
643 (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
644 errmsg("too many arguments"),
645 errhint("Provide two argument types for operator.")));
647 if (argtypes[0] == InvalidOid)
649 else if (argtypes[1] == InvalidOid)
654 clist = OpernameGetCandidates(names, oprkind);
656 for (; clist; clist = clist->next)
658 if (memcmp(clist->args, argtypes, 2 * sizeof(Oid)) == 0)
664 (errcode(ERRCODE_UNDEFINED_FUNCTION),
665 errmsg("operator does not exist: %s", opr_name_or_oid)));
669 PG_RETURN_OID(result);
673 * format_operator - converts operator OID to "opr_name(args)"
675 * This exports the useful functionality of regoperatorout for use
676 * in other backend modules. The result is a palloc'd string.
679 format_operator(Oid operator_oid)
684 opertup = SearchSysCache(OPEROID,
685 ObjectIdGetDatum(operator_oid),
688 if (HeapTupleIsValid(opertup))
690 Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup);
691 char *oprname = NameStr(operform->oprname);
695 /* XXX no support here for bootstrap mode */
697 initStringInfo(&buf);
700 * Would this oper be found (given the right args) by
701 * regoperatorin? If not, we need to qualify it.
703 if (!OperatorIsVisible(operator_oid))
705 nspname = get_namespace_name(operform->oprnamespace);
706 appendStringInfo(&buf, "%s.",
707 quote_identifier(nspname));
710 appendStringInfo(&buf, "%s(", oprname);
712 if (operform->oprleft)
713 appendStringInfo(&buf, "%s,",
714 format_type_be(operform->oprleft));
716 appendStringInfo(&buf, "NONE,");
718 if (operform->oprright)
719 appendStringInfo(&buf, "%s)",
720 format_type_be(operform->oprright));
722 appendStringInfo(&buf, "NONE)");
726 ReleaseSysCache(opertup);
731 * If OID doesn't match any pg_operator entry, return it
734 result = (char *) palloc(NAMEDATALEN);
735 snprintf(result, NAMEDATALEN, "%u", operator_oid);
742 * regoperatorout - converts operator OID to "opr_name(args)"
745 regoperatorout(PG_FUNCTION_ARGS)
747 Oid oprid = PG_GETARG_OID(0);
750 if (oprid == InvalidOid)
751 result = pstrdup("0");
753 result = format_operator(oprid);
755 PG_RETURN_CSTRING(result);
759 * regoperatorrecv - converts external binary format to regoperator
762 regoperatorrecv(PG_FUNCTION_ARGS)
764 /* Exactly the same as oidrecv, so share code */
765 return oidrecv(fcinfo);
769 * regoperatorsend - converts regoperator to binary format
772 regoperatorsend(PG_FUNCTION_ARGS)
774 /* Exactly the same as oidsend, so share code */
775 return oidsend(fcinfo);
780 * regclassin - converts "classname" to class OID
782 * We also accept a numeric OID, for symmetry with the output routine.
784 * '-' signifies unknown (OID 0). In all other cases, the input must
785 * match an existing pg_class entry.
788 regclassin(PG_FUNCTION_ARGS)
790 char *class_name_or_oid = PG_GETARG_CSTRING(0);
791 Oid result = InvalidOid;
795 if (strcmp(class_name_or_oid, "-") == 0)
796 PG_RETURN_OID(InvalidOid);
799 if (class_name_or_oid[0] >= '0' &&
800 class_name_or_oid[0] <= '9' &&
801 strspn(class_name_or_oid, "0123456789") == strlen(class_name_or_oid))
803 result = DatumGetObjectId(DirectFunctionCall1(oidin,
804 CStringGetDatum(class_name_or_oid)));
805 PG_RETURN_OID(result);
808 /* Else it's a name, possibly schema-qualified */
811 * In bootstrap mode we assume the given name is not schema-qualified,
812 * and just search pg_class for a match. This is needed for
813 * initializing other system catalogs (pg_namespace may not exist yet,
814 * and certainly there are no schemas other than pg_catalog).
816 if (IsBootstrapProcessingMode())
823 ScanKeyInit(&skey[0],
824 Anum_pg_class_relname,
825 BTEqualStrategyNumber, F_NAMEEQ,
826 CStringGetDatum(class_name_or_oid));
828 hdesc = heap_openr(RelationRelationName, AccessShareLock);
829 sysscan = systable_beginscan(hdesc, ClassNameNspIndex, true,
830 SnapshotNow, 1, skey);
832 if (HeapTupleIsValid(tuple = systable_getnext(sysscan)))
833 result = HeapTupleGetOid(tuple);
836 (errcode(ERRCODE_UNDEFINED_TABLE),
837 errmsg("relation \"%s\" does not exist", class_name_or_oid)));
839 /* We assume there can be only one match */
841 systable_endscan(sysscan);
842 heap_close(hdesc, AccessShareLock);
844 PG_RETURN_OID(result);
848 * Normal case: parse the name into components and see if it matches
849 * any pg_class entries in the current search path.
851 names = stringToQualifiedNameList(class_name_or_oid, "regclassin");
853 result = RangeVarGetRelid(makeRangeVarFromNameList(names), false);
855 PG_RETURN_OID(result);
859 * regclassout - converts class OID to "class_name"
862 regclassout(PG_FUNCTION_ARGS)
864 Oid classid = PG_GETARG_OID(0);
868 if (classid == InvalidOid)
870 result = pstrdup("-");
871 PG_RETURN_CSTRING(result);
874 classtup = SearchSysCache(RELOID,
875 ObjectIdGetDatum(classid),
878 if (HeapTupleIsValid(classtup))
880 Form_pg_class classform = (Form_pg_class) GETSTRUCT(classtup);
881 char *classname = NameStr(classform->relname);
884 * In bootstrap mode, skip the fancy namespace stuff and just
885 * return the class name. (This path is only needed for debugging
888 if (IsBootstrapProcessingMode())
889 result = pstrdup(classname);
895 * Would this class be found by regclassin? If not, qualify
898 if (RelationIsVisible(classid))
901 nspname = get_namespace_name(classform->relnamespace);
903 result = quote_qualified_identifier(nspname, classname);
906 ReleaseSysCache(classtup);
910 /* If OID doesn't match any pg_class entry, return it numerically */
911 result = (char *) palloc(NAMEDATALEN);
912 snprintf(result, NAMEDATALEN, "%u", classid);
915 PG_RETURN_CSTRING(result);
919 * regclassrecv - converts external binary format to regclass
922 regclassrecv(PG_FUNCTION_ARGS)
924 /* Exactly the same as oidrecv, so share code */
925 return oidrecv(fcinfo);
929 * regclasssend - converts regclass to binary format
932 regclasssend(PG_FUNCTION_ARGS)
934 /* Exactly the same as oidsend, so share code */
935 return oidsend(fcinfo);
940 * regtypein - converts "typename" to type OID
942 * We also accept a numeric OID, for symmetry with the output routine.
944 * '-' signifies unknown (OID 0). In all other cases, the input must
945 * match an existing pg_type entry.
947 * In bootstrap mode the name must just equal some existing name in pg_type.
948 * In normal mode the type name can be specified using the full type syntax
949 * recognized by the parser; for example, DOUBLE PRECISION and INTEGER[] will
950 * work and be translated to the correct type names. (We ignore any typmod
951 * info generated by the parser, however.)
954 regtypein(PG_FUNCTION_ARGS)
956 char *typ_name_or_oid = PG_GETARG_CSTRING(0);
957 Oid result = InvalidOid;
961 if (strcmp(typ_name_or_oid, "-") == 0)
962 PG_RETURN_OID(InvalidOid);
965 if (typ_name_or_oid[0] >= '0' &&
966 typ_name_or_oid[0] <= '9' &&
967 strspn(typ_name_or_oid, "0123456789") == strlen(typ_name_or_oid))
969 result = DatumGetObjectId(DirectFunctionCall1(oidin,
970 CStringGetDatum(typ_name_or_oid)));
971 PG_RETURN_OID(result);
974 /* Else it's a type name, possibly schema-qualified or decorated */
977 * In bootstrap mode we assume the given name is not schema-qualified,
978 * and just search pg_type for a match. This is needed for
979 * initializing other system catalogs (pg_namespace may not exist yet,
980 * and certainly there are no schemas other than pg_catalog).
982 if (IsBootstrapProcessingMode())
989 ScanKeyInit(&skey[0],
990 Anum_pg_type_typname,
991 BTEqualStrategyNumber, F_NAMEEQ,
992 CStringGetDatum(typ_name_or_oid));
994 hdesc = heap_openr(TypeRelationName, AccessShareLock);
995 sysscan = systable_beginscan(hdesc, TypeNameNspIndex, true,
996 SnapshotNow, 1, skey);
998 if (HeapTupleIsValid(tuple = systable_getnext(sysscan)))
999 result = HeapTupleGetOid(tuple);
1002 (errcode(ERRCODE_UNDEFINED_OBJECT),
1003 errmsg("type \"%s\" does not exist", typ_name_or_oid)));
1005 /* We assume there can be only one match */
1007 systable_endscan(sysscan);
1008 heap_close(hdesc, AccessShareLock);
1010 PG_RETURN_OID(result);
1014 * Normal case: invoke the full parser to deal with special cases such
1017 parseTypeString(typ_name_or_oid, &result, &typmod);
1019 PG_RETURN_OID(result);
1023 * regtypeout - converts type OID to "typ_name"
1026 regtypeout(PG_FUNCTION_ARGS)
1028 Oid typid = PG_GETARG_OID(0);
1032 if (typid == InvalidOid)
1034 result = pstrdup("-");
1035 PG_RETURN_CSTRING(result);
1038 typetup = SearchSysCache(TYPEOID,
1039 ObjectIdGetDatum(typid),
1042 if (HeapTupleIsValid(typetup))
1044 Form_pg_type typeform = (Form_pg_type) GETSTRUCT(typetup);
1047 * In bootstrap mode, skip the fancy namespace stuff and just
1048 * return the type name. (This path is only needed for debugging
1051 if (IsBootstrapProcessingMode())
1053 char *typname = NameStr(typeform->typname);
1055 result = pstrdup(typname);
1058 result = format_type_be(typid);
1060 ReleaseSysCache(typetup);
1064 /* If OID doesn't match any pg_type entry, return it numerically */
1065 result = (char *) palloc(NAMEDATALEN);
1066 snprintf(result, NAMEDATALEN, "%u", typid);
1069 PG_RETURN_CSTRING(result);
1073 * regtyperecv - converts external binary format to regtype
1076 regtyperecv(PG_FUNCTION_ARGS)
1078 /* Exactly the same as oidrecv, so share code */
1079 return oidrecv(fcinfo);
1083 * regtypesend - converts regtype to binary format
1086 regtypesend(PG_FUNCTION_ARGS)
1088 /* Exactly the same as oidsend, so share code */
1089 return oidsend(fcinfo);
1094 * Given a C string, parse it into a qualified-name list.
1097 stringToQualifiedNameList(const char *string, const char *caller)
1104 /* We need a modifiable copy of the input string. */
1105 rawname = pstrdup(string);
1107 if (!SplitIdentifierString(rawname, '.', &namelist))
1109 (errcode(ERRCODE_INVALID_NAME),
1110 errmsg("invalid name syntax")));
1112 if (namelist == NIL)
1114 (errcode(ERRCODE_INVALID_NAME),
1115 errmsg("invalid name syntax")));
1117 foreach(l, namelist)
1119 char *curname = (char *) lfirst(l);
1121 result = lappend(result, makeString(pstrdup(curname)));
1125 list_free(namelist);
1130 /*****************************************************************************
1131 * SUPPORT ROUTINES *
1132 *****************************************************************************/
1135 * Given a C string, parse it into a qualified function or operator name
1136 * followed by a parenthesized list of type names. Reduce the
1137 * type names to an array of OIDs (returned into *nargs and *argtypes;
1138 * the argtypes array should be of size FUNC_MAX_ARGS). The function or
1139 * operator name is returned to *names as a List of Strings.
1141 * If allowNone is TRUE, accept "NONE" and return it as InvalidOid (this is
1142 * for unary operators).
1145 parseNameAndArgTypes(const char *string, const char *caller,
1147 List **names, int *nargs, Oid *argtypes)
1159 /* We need a modifiable copy of the input string. */
1160 rawname = pstrdup(string);
1162 /* Scan to find the expected left paren; mustn't be quoted */
1164 for (ptr = rawname; *ptr; ptr++)
1167 in_quote = !in_quote;
1168 else if (*ptr == '(' && !in_quote)
1173 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1174 errmsg("expected a left parenthesis")));
1176 /* Separate the name and parse it into a list */
1178 *names = stringToQualifiedNameList(rawname, caller);
1180 /* Check for the trailing right parenthesis and remove it */
1181 ptr2 = ptr + strlen(ptr);
1182 while (--ptr2 > ptr)
1184 if (!isspace((unsigned char) *ptr2))
1189 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1190 errmsg("expected a right parenthesis")));
1194 /* Separate the remaining string into comma-separated type names */
1200 /* allow leading whitespace */
1201 while (isspace((unsigned char) *ptr))
1205 /* End of string. Okay unless we had a comma before. */
1208 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1209 errmsg("expected a type name")));
1213 /* Find end of type name --- end of string or comma */
1214 /* ... but not a quoted or parenthesized comma */
1220 in_quote = !in_quote;
1221 else if (*ptr == ',' && !in_quote && paren_count == 0)
1238 if (in_quote || paren_count != 0)
1240 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1241 errmsg("improper type name")));
1252 Assert(*ptr == '\0');
1254 /* Lop off trailing whitespace */
1255 while (--ptr2 >= typename)
1257 if (!isspace((unsigned char) *ptr2))
1262 if (allowNone && pg_strcasecmp(typename, "none") == 0)
1264 /* Special case for NONE */
1265 typeid = InvalidOid;
1270 /* Use full parser to resolve the type name */
1271 parseTypeString(typename, &typeid, &typmod);
1273 if (*nargs >= FUNC_MAX_ARGS)
1275 (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
1276 errmsg("too many arguments")));
1278 argtypes[*nargs] = typeid;