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-2005, 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.96 2005/10/15 02:49:29 momjian Exp $
18 *-------------------------------------------------------------------------
24 #include "access/genam.h"
25 #include "access/heapam.h"
26 #include "catalog/indexing.h"
27 #include "catalog/namespace.h"
28 #include "catalog/pg_operator.h"
29 #include "catalog/pg_proc.h"
30 #include "catalog/pg_type.h"
31 #include "lib/stringinfo.h"
32 #include "miscadmin.h"
33 #include "parser/parse_type.h"
34 #include "utils/builtins.h"
35 #include "utils/fmgroids.h"
36 #include "utils/lsyscache.h"
37 #include "utils/syscache.h"
39 static void parseNameAndArgTypes(const char *string, const char *caller,
41 List **names, int *nargs, Oid *argtypes);
44 /*****************************************************************************
46 *****************************************************************************/
49 * regprocin - converts "proname" to proc OID
51 * We also accept a numeric OID, for symmetry with the output routine.
53 * '-' signifies unknown (OID 0). In all other cases, the input must
54 * match an existing pg_proc entry.
57 regprocin(PG_FUNCTION_ARGS)
59 char *pro_name_or_oid = PG_GETARG_CSTRING(0);
60 RegProcedure result = InvalidOid;
62 FuncCandidateList clist;
65 if (strcmp(pro_name_or_oid, "-") == 0)
66 PG_RETURN_OID(InvalidOid);
69 if (pro_name_or_oid[0] >= '0' &&
70 pro_name_or_oid[0] <= '9' &&
71 strspn(pro_name_or_oid, "0123456789") == strlen(pro_name_or_oid))
73 result = DatumGetObjectId(DirectFunctionCall1(oidin,
74 CStringGetDatum(pro_name_or_oid)));
75 PG_RETURN_OID(result);
78 /* Else it's a name, possibly schema-qualified */
81 * In bootstrap mode we assume the given name is not schema-qualified, and
82 * just search pg_proc for a unique match. This is needed for
83 * initializing other system catalogs (pg_namespace may not exist yet, and
84 * certainly there are no schemas other than pg_catalog).
86 if (IsBootstrapProcessingMode())
96 BTEqualStrategyNumber, F_NAMEEQ,
97 CStringGetDatum(pro_name_or_oid));
99 hdesc = heap_open(ProcedureRelationId, AccessShareLock);
100 sysscan = systable_beginscan(hdesc, ProcedureNameArgsNspIndexId, true,
101 SnapshotNow, 1, skey);
103 while (HeapTupleIsValid(tuple = systable_getnext(sysscan)))
105 result = (RegProcedure) HeapTupleGetOid(tuple);
110 systable_endscan(sysscan);
111 heap_close(hdesc, AccessShareLock);
115 (errcode(ERRCODE_UNDEFINED_FUNCTION),
116 errmsg("function \"%s\" does not exist", pro_name_or_oid)));
118 else if (matches > 1)
120 (errcode(ERRCODE_AMBIGUOUS_FUNCTION),
121 errmsg("more than one function named \"%s\"",
124 PG_RETURN_OID(result);
128 * Normal case: parse the name into components and see if it matches any
129 * pg_proc entries in the current search path.
131 names = stringToQualifiedNameList(pro_name_or_oid, "regprocin");
132 clist = FuncnameGetCandidates(names, -1);
136 (errcode(ERRCODE_UNDEFINED_FUNCTION),
137 errmsg("function \"%s\" does not exist", pro_name_or_oid)));
138 else if (clist->next != NULL)
140 (errcode(ERRCODE_AMBIGUOUS_FUNCTION),
141 errmsg("more than one function 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 return
176 * the proc name. (This path is only needed for debugging output
179 if (IsBootstrapProcessingMode())
180 result = pstrdup(proname);
184 FuncCandidateList clist;
187 * Would this proc be found (uniquely!) by regprocin? If not,
190 clist = FuncnameGetCandidates(list_make1(makeString(proname)), -1);
191 if (clist != NULL && clist->next == NULL &&
195 nspname = get_namespace_name(procform->pronamespace);
197 result = quote_qualified_identifier(nspname, proname);
200 ReleaseSysCache(proctup);
204 /* If OID doesn't match any pg_proc entry, return it numerically */
205 result = (char *) palloc(NAMEDATALEN);
206 snprintf(result, NAMEDATALEN, "%u", proid);
209 PG_RETURN_CSTRING(result);
213 * regprocrecv - converts external binary format to regproc
216 regprocrecv(PG_FUNCTION_ARGS)
218 /* Exactly the same as oidrecv, so share code */
219 return oidrecv(fcinfo);
223 * regprocsend - converts regproc to binary format
226 regprocsend(PG_FUNCTION_ARGS)
228 /* Exactly the same as oidsend, so share code */
229 return oidsend(fcinfo);
234 * regprocedurein - converts "proname(args)" to proc OID
236 * We also accept a numeric OID, for symmetry with the output routine.
238 * '-' signifies unknown (OID 0). In all other cases, the input must
239 * match an existing pg_proc entry.
242 regprocedurein(PG_FUNCTION_ARGS)
244 char *pro_name_or_oid = PG_GETARG_CSTRING(0);
245 RegProcedure result = InvalidOid;
248 Oid argtypes[FUNC_MAX_ARGS];
249 FuncCandidateList clist;
252 if (strcmp(pro_name_or_oid, "-") == 0)
253 PG_RETURN_OID(InvalidOid);
256 if (pro_name_or_oid[0] >= '0' &&
257 pro_name_or_oid[0] <= '9' &&
258 strspn(pro_name_or_oid, "0123456789") == strlen(pro_name_or_oid))
260 result = DatumGetObjectId(DirectFunctionCall1(oidin,
261 CStringGetDatum(pro_name_or_oid)));
262 PG_RETURN_OID(result);
266 * Else it's a name and arguments. Parse the name and arguments, look up
267 * potential matches in the current namespace search list, and scan to see
268 * which one exactly matches the given argument types. (There will not be
269 * more than one match.)
271 * XXX at present, this code will not work in bootstrap mode, hence this
272 * datatype cannot be used for any system column that needs to receive
273 * data during bootstrap.
275 parseNameAndArgTypes(pro_name_or_oid, "regprocedurein", false,
276 &names, &nargs, argtypes);
278 clist = FuncnameGetCandidates(names, nargs);
280 for (; clist; clist = clist->next)
282 if (memcmp(clist->args, argtypes, nargs * sizeof(Oid)) == 0)
288 (errcode(ERRCODE_UNDEFINED_FUNCTION),
289 errmsg("function \"%s\" does not exist", pro_name_or_oid)));
293 PG_RETURN_OID(result);
297 * format_procedure - converts proc OID to "pro_name(args)"
299 * This exports the useful functionality of regprocedureout for use
300 * in other backend modules. The result is a palloc'd string.
303 format_procedure(Oid procedure_oid)
308 proctup = SearchSysCache(PROCOID,
309 ObjectIdGetDatum(procedure_oid),
312 if (HeapTupleIsValid(proctup))
314 Form_pg_proc procform = (Form_pg_proc) GETSTRUCT(proctup);
315 char *proname = NameStr(procform->proname);
316 int nargs = procform->pronargs;
321 /* XXX no support here for bootstrap mode */
323 initStringInfo(&buf);
326 * Would this proc be found (given the right args) by regprocedurein?
327 * If not, we need to qualify it.
329 if (FunctionIsVisible(procedure_oid))
332 nspname = get_namespace_name(procform->pronamespace);
334 appendStringInfo(&buf, "%s(",
335 quote_qualified_identifier(nspname, proname));
336 for (i = 0; i < nargs; i++)
338 Oid thisargtype = procform->proargtypes.values[i];
341 appendStringInfoChar(&buf, ',');
342 appendStringInfoString(&buf, format_type_be(thisargtype));
344 appendStringInfoChar(&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", procedure_oid);
361 * regprocedureout - converts proc OID to "pro_name(args)"
364 regprocedureout(PG_FUNCTION_ARGS)
366 RegProcedure proid = PG_GETARG_OID(0);
369 if (proid == InvalidOid)
370 result = pstrdup("-");
372 result = format_procedure(proid);
374 PG_RETURN_CSTRING(result);
378 * regprocedurerecv - converts external binary format to regprocedure
381 regprocedurerecv(PG_FUNCTION_ARGS)
383 /* Exactly the same as oidrecv, so share code */
384 return oidrecv(fcinfo);
388 * regproceduresend - converts regprocedure to binary format
391 regproceduresend(PG_FUNCTION_ARGS)
393 /* Exactly the same as oidsend, so share code */
394 return oidsend(fcinfo);
399 * regoperin - converts "oprname" to operator OID
401 * We also accept a numeric OID, for symmetry with the output routine.
403 * '0' signifies unknown (OID 0). In all other cases, the input must
404 * match an existing pg_operator entry.
407 regoperin(PG_FUNCTION_ARGS)
409 char *opr_name_or_oid = PG_GETARG_CSTRING(0);
410 Oid result = InvalidOid;
412 FuncCandidateList clist;
415 if (strcmp(opr_name_or_oid, "0") == 0)
416 PG_RETURN_OID(InvalidOid);
419 if (opr_name_or_oid[0] >= '0' &&
420 opr_name_or_oid[0] <= '9' &&
421 strspn(opr_name_or_oid, "0123456789") == strlen(opr_name_or_oid))
423 result = DatumGetObjectId(DirectFunctionCall1(oidin,
424 CStringGetDatum(opr_name_or_oid)));
425 PG_RETURN_OID(result);
428 /* Else it's a name, possibly schema-qualified */
431 * In bootstrap mode we assume the given name is not schema-qualified, and
432 * just search pg_operator for a unique match. This is needed for
433 * initializing other system catalogs (pg_namespace may not exist yet, and
434 * certainly there are no schemas other than pg_catalog).
436 if (IsBootstrapProcessingMode())
444 ScanKeyInit(&skey[0],
445 Anum_pg_operator_oprname,
446 BTEqualStrategyNumber, F_NAMEEQ,
447 CStringGetDatum(opr_name_or_oid));
449 hdesc = heap_open(OperatorRelationId, AccessShareLock);
450 sysscan = systable_beginscan(hdesc, OperatorNameNspIndexId, true,
451 SnapshotNow, 1, skey);
453 while (HeapTupleIsValid(tuple = systable_getnext(sysscan)))
455 result = HeapTupleGetOid(tuple);
460 systable_endscan(sysscan);
461 heap_close(hdesc, AccessShareLock);
465 (errcode(ERRCODE_UNDEFINED_FUNCTION),
466 errmsg("operator does not exist: %s", opr_name_or_oid)));
467 else if (matches > 1)
469 (errcode(ERRCODE_AMBIGUOUS_FUNCTION),
470 errmsg("more than one operator named %s",
473 PG_RETURN_OID(result);
477 * Normal case: parse the name into components and see if it matches any
478 * pg_operator entries in the current search path.
480 names = stringToQualifiedNameList(opr_name_or_oid, "regoperin");
481 clist = OpernameGetCandidates(names, '\0');
485 (errcode(ERRCODE_UNDEFINED_FUNCTION),
486 errmsg("operator does not exist: %s", opr_name_or_oid)));
487 else if (clist->next != NULL)
489 (errcode(ERRCODE_AMBIGUOUS_FUNCTION),
490 errmsg("more than one operator named %s",
495 PG_RETURN_OID(result);
499 * regoperout - converts operator OID to "opr_name"
502 regoperout(PG_FUNCTION_ARGS)
504 Oid oprid = PG_GETARG_OID(0);
508 if (oprid == InvalidOid)
510 result = pstrdup("0");
511 PG_RETURN_CSTRING(result);
514 opertup = SearchSysCache(OPEROID,
515 ObjectIdGetDatum(oprid),
518 if (HeapTupleIsValid(opertup))
520 Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup);
521 char *oprname = NameStr(operform->oprname);
524 * In bootstrap mode, skip the fancy namespace stuff and just return
525 * the oper name. (This path is only needed for debugging output
528 if (IsBootstrapProcessingMode())
529 result = pstrdup(oprname);
532 FuncCandidateList clist;
535 * Would this oper be found (uniquely!) by regoperin? If not,
538 clist = OpernameGetCandidates(list_make1(makeString(oprname)),
540 if (clist != NULL && clist->next == NULL &&
542 result = pstrdup(oprname);
547 nspname = get_namespace_name(operform->oprnamespace);
548 nspname = quote_identifier(nspname);
549 result = (char *) palloc(strlen(nspname) + strlen(oprname) + 2);
550 sprintf(result, "%s.%s", nspname, oprname);
554 ReleaseSysCache(opertup);
559 * If OID doesn't match any pg_operator entry, return it numerically
561 result = (char *) palloc(NAMEDATALEN);
562 snprintf(result, NAMEDATALEN, "%u", oprid);
565 PG_RETURN_CSTRING(result);
569 * regoperrecv - converts external binary format to regoper
572 regoperrecv(PG_FUNCTION_ARGS)
574 /* Exactly the same as oidrecv, so share code */
575 return oidrecv(fcinfo);
579 * regopersend - converts regoper to binary format
582 regopersend(PG_FUNCTION_ARGS)
584 /* Exactly the same as oidsend, so share code */
585 return oidsend(fcinfo);
590 * regoperatorin - converts "oprname(args)" to operator OID
592 * We also accept a numeric OID, for symmetry with the output routine.
594 * '0' signifies unknown (OID 0). In all other cases, the input must
595 * match an existing pg_operator entry.
598 regoperatorin(PG_FUNCTION_ARGS)
600 char *opr_name_or_oid = PG_GETARG_CSTRING(0);
601 Oid result = InvalidOid;
604 Oid argtypes[FUNC_MAX_ARGS];
606 FuncCandidateList clist;
609 if (strcmp(opr_name_or_oid, "0") == 0)
610 PG_RETURN_OID(InvalidOid);
613 if (opr_name_or_oid[0] >= '0' &&
614 opr_name_or_oid[0] <= '9' &&
615 strspn(opr_name_or_oid, "0123456789") == strlen(opr_name_or_oid))
617 result = DatumGetObjectId(DirectFunctionCall1(oidin,
618 CStringGetDatum(opr_name_or_oid)));
619 PG_RETURN_OID(result);
623 * Else it's a name and arguments. Parse the name and arguments, look up
624 * potential matches in the current namespace search list, and scan to see
625 * which one exactly matches the given argument types. (There will not be
626 * more than one match.)
628 * XXX at present, this code will not work in bootstrap mode, hence this
629 * datatype cannot be used for any system column that needs to receive
630 * data during bootstrap.
632 parseNameAndArgTypes(opr_name_or_oid, "regoperatorin", true,
633 &names, &nargs, argtypes);
636 (errcode(ERRCODE_UNDEFINED_PARAMETER),
637 errmsg("missing argument"),
638 errhint("Use NONE to denote the missing argument of a unary operator.")));
641 (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
642 errmsg("too many arguments"),
643 errhint("Provide two argument types for operator.")));
645 if (argtypes[0] == InvalidOid)
647 else if (argtypes[1] == InvalidOid)
652 clist = OpernameGetCandidates(names, oprkind);
654 for (; clist; clist = clist->next)
656 if (memcmp(clist->args, argtypes, 2 * sizeof(Oid)) == 0)
662 (errcode(ERRCODE_UNDEFINED_FUNCTION),
663 errmsg("operator does not exist: %s", opr_name_or_oid)));
667 PG_RETURN_OID(result);
671 * format_operator - converts operator OID to "opr_name(args)"
673 * This exports the useful functionality of regoperatorout for use
674 * in other backend modules. The result is a palloc'd string.
677 format_operator(Oid operator_oid)
682 opertup = SearchSysCache(OPEROID,
683 ObjectIdGetDatum(operator_oid),
686 if (HeapTupleIsValid(opertup))
688 Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup);
689 char *oprname = NameStr(operform->oprname);
693 /* XXX no support here for bootstrap mode */
695 initStringInfo(&buf);
698 * Would this oper be found (given the right args) by regoperatorin?
699 * If not, we need to qualify it.
701 if (!OperatorIsVisible(operator_oid))
703 nspname = get_namespace_name(operform->oprnamespace);
704 appendStringInfo(&buf, "%s.",
705 quote_identifier(nspname));
708 appendStringInfo(&buf, "%s(", oprname);
710 if (operform->oprleft)
711 appendStringInfo(&buf, "%s,",
712 format_type_be(operform->oprleft));
714 appendStringInfo(&buf, "NONE,");
716 if (operform->oprright)
717 appendStringInfo(&buf, "%s)",
718 format_type_be(operform->oprright));
720 appendStringInfo(&buf, "NONE)");
724 ReleaseSysCache(opertup);
729 * If OID doesn't match any pg_operator entry, return it numerically
731 result = (char *) palloc(NAMEDATALEN);
732 snprintf(result, NAMEDATALEN, "%u", operator_oid);
739 * regoperatorout - converts operator OID to "opr_name(args)"
742 regoperatorout(PG_FUNCTION_ARGS)
744 Oid oprid = PG_GETARG_OID(0);
747 if (oprid == InvalidOid)
748 result = pstrdup("0");
750 result = format_operator(oprid);
752 PG_RETURN_CSTRING(result);
756 * regoperatorrecv - converts external binary format to regoperator
759 regoperatorrecv(PG_FUNCTION_ARGS)
761 /* Exactly the same as oidrecv, so share code */
762 return oidrecv(fcinfo);
766 * regoperatorsend - converts regoperator to binary format
769 regoperatorsend(PG_FUNCTION_ARGS)
771 /* Exactly the same as oidsend, so share code */
772 return oidsend(fcinfo);
777 * regclassin - converts "classname" to class OID
779 * We also accept a numeric OID, for symmetry with the output routine.
781 * '-' signifies unknown (OID 0). In all other cases, the input must
782 * match an existing pg_class entry.
785 regclassin(PG_FUNCTION_ARGS)
787 char *class_name_or_oid = PG_GETARG_CSTRING(0);
788 Oid result = InvalidOid;
792 if (strcmp(class_name_or_oid, "-") == 0)
793 PG_RETURN_OID(InvalidOid);
796 if (class_name_or_oid[0] >= '0' &&
797 class_name_or_oid[0] <= '9' &&
798 strspn(class_name_or_oid, "0123456789") == strlen(class_name_or_oid))
800 result = DatumGetObjectId(DirectFunctionCall1(oidin,
801 CStringGetDatum(class_name_or_oid)));
802 PG_RETURN_OID(result);
805 /* Else it's a name, possibly schema-qualified */
808 * In bootstrap mode we assume the given name is not schema-qualified, and
809 * just search pg_class for a match. This is needed for initializing
810 * other system catalogs (pg_namespace may not exist yet, and certainly
811 * there are no schemas other than pg_catalog).
813 if (IsBootstrapProcessingMode())
820 ScanKeyInit(&skey[0],
821 Anum_pg_class_relname,
822 BTEqualStrategyNumber, F_NAMEEQ,
823 CStringGetDatum(class_name_or_oid));
825 hdesc = heap_open(RelationRelationId, AccessShareLock);
826 sysscan = systable_beginscan(hdesc, ClassNameNspIndexId, true,
827 SnapshotNow, 1, skey);
829 if (HeapTupleIsValid(tuple = systable_getnext(sysscan)))
830 result = HeapTupleGetOid(tuple);
833 (errcode(ERRCODE_UNDEFINED_TABLE),
834 errmsg("relation \"%s\" does not exist", class_name_or_oid)));
836 /* We assume there can be only one match */
838 systable_endscan(sysscan);
839 heap_close(hdesc, AccessShareLock);
841 PG_RETURN_OID(result);
845 * Normal case: parse the name into components and see if it matches any
846 * pg_class entries in the current search path.
848 names = stringToQualifiedNameList(class_name_or_oid, "regclassin");
850 result = RangeVarGetRelid(makeRangeVarFromNameList(names), false);
852 PG_RETURN_OID(result);
856 * regclassout - converts class OID to "class_name"
859 regclassout(PG_FUNCTION_ARGS)
861 Oid classid = PG_GETARG_OID(0);
865 if (classid == InvalidOid)
867 result = pstrdup("-");
868 PG_RETURN_CSTRING(result);
871 classtup = SearchSysCache(RELOID,
872 ObjectIdGetDatum(classid),
875 if (HeapTupleIsValid(classtup))
877 Form_pg_class classform = (Form_pg_class) GETSTRUCT(classtup);
878 char *classname = NameStr(classform->relname);
881 * In bootstrap mode, skip the fancy namespace stuff and just return
882 * the class name. (This path is only needed for debugging output
885 if (IsBootstrapProcessingMode())
886 result = pstrdup(classname);
892 * Would this class be found by regclassin? If not, qualify it.
894 if (RelationIsVisible(classid))
897 nspname = get_namespace_name(classform->relnamespace);
899 result = quote_qualified_identifier(nspname, classname);
902 ReleaseSysCache(classtup);
906 /* If OID doesn't match any pg_class entry, return it numerically */
907 result = (char *) palloc(NAMEDATALEN);
908 snprintf(result, NAMEDATALEN, "%u", classid);
911 PG_RETURN_CSTRING(result);
915 * regclassrecv - converts external binary format to regclass
918 regclassrecv(PG_FUNCTION_ARGS)
920 /* Exactly the same as oidrecv, so share code */
921 return oidrecv(fcinfo);
925 * regclasssend - converts regclass to binary format
928 regclasssend(PG_FUNCTION_ARGS)
930 /* Exactly the same as oidsend, so share code */
931 return oidsend(fcinfo);
936 * regtypein - converts "typename" to type OID
938 * We also accept a numeric OID, for symmetry with the output routine.
940 * '-' signifies unknown (OID 0). In all other cases, the input must
941 * match an existing pg_type entry.
943 * In bootstrap mode the name must just equal some existing name in pg_type.
944 * In normal mode the type name can be specified using the full type syntax
945 * recognized by the parser; for example, DOUBLE PRECISION and INTEGER[] will
946 * work and be translated to the correct type names. (We ignore any typmod
947 * info generated by the parser, however.)
950 regtypein(PG_FUNCTION_ARGS)
952 char *typ_name_or_oid = PG_GETARG_CSTRING(0);
953 Oid result = InvalidOid;
957 if (strcmp(typ_name_or_oid, "-") == 0)
958 PG_RETURN_OID(InvalidOid);
961 if (typ_name_or_oid[0] >= '0' &&
962 typ_name_or_oid[0] <= '9' &&
963 strspn(typ_name_or_oid, "0123456789") == strlen(typ_name_or_oid))
965 result = DatumGetObjectId(DirectFunctionCall1(oidin,
966 CStringGetDatum(typ_name_or_oid)));
967 PG_RETURN_OID(result);
970 /* Else it's a type name, possibly schema-qualified or decorated */
973 * In bootstrap mode we assume the given name is not schema-qualified, and
974 * just search pg_type for a match. This is needed for initializing other
975 * system catalogs (pg_namespace may not exist yet, and certainly there
976 * are no schemas other than pg_catalog).
978 if (IsBootstrapProcessingMode())
985 ScanKeyInit(&skey[0],
986 Anum_pg_type_typname,
987 BTEqualStrategyNumber, F_NAMEEQ,
988 CStringGetDatum(typ_name_or_oid));
990 hdesc = heap_open(TypeRelationId, AccessShareLock);
991 sysscan = systable_beginscan(hdesc, TypeNameNspIndexId, true,
992 SnapshotNow, 1, skey);
994 if (HeapTupleIsValid(tuple = systable_getnext(sysscan)))
995 result = HeapTupleGetOid(tuple);
998 (errcode(ERRCODE_UNDEFINED_OBJECT),
999 errmsg("type \"%s\" does not exist", typ_name_or_oid)));
1001 /* We assume there can be only one match */
1003 systable_endscan(sysscan);
1004 heap_close(hdesc, AccessShareLock);
1006 PG_RETURN_OID(result);
1010 * Normal case: invoke the full parser to deal with special cases such as
1013 parseTypeString(typ_name_or_oid, &result, &typmod);
1015 PG_RETURN_OID(result);
1019 * regtypeout - converts type OID to "typ_name"
1022 regtypeout(PG_FUNCTION_ARGS)
1024 Oid typid = PG_GETARG_OID(0);
1028 if (typid == InvalidOid)
1030 result = pstrdup("-");
1031 PG_RETURN_CSTRING(result);
1034 typetup = SearchSysCache(TYPEOID,
1035 ObjectIdGetDatum(typid),
1038 if (HeapTupleIsValid(typetup))
1040 Form_pg_type typeform = (Form_pg_type) GETSTRUCT(typetup);
1043 * In bootstrap mode, skip the fancy namespace stuff and just return
1044 * the type name. (This path is only needed for debugging output
1047 if (IsBootstrapProcessingMode())
1049 char *typname = NameStr(typeform->typname);
1051 result = pstrdup(typname);
1054 result = format_type_be(typid);
1056 ReleaseSysCache(typetup);
1060 /* If OID doesn't match any pg_type entry, return it numerically */
1061 result = (char *) palloc(NAMEDATALEN);
1062 snprintf(result, NAMEDATALEN, "%u", typid);
1065 PG_RETURN_CSTRING(result);
1069 * regtyperecv - converts external binary format to regtype
1072 regtyperecv(PG_FUNCTION_ARGS)
1074 /* Exactly the same as oidrecv, so share code */
1075 return oidrecv(fcinfo);
1079 * regtypesend - converts regtype to binary format
1082 regtypesend(PG_FUNCTION_ARGS)
1084 /* Exactly the same as oidsend, so share code */
1085 return oidsend(fcinfo);
1090 * text_regclass: convert text to regclass
1093 text_regclass(PG_FUNCTION_ARGS)
1095 text *relname = PG_GETARG_TEXT_P(0);
1099 rv = makeRangeVarFromNameList(textToQualifiedNameList(relname));
1100 result = RangeVarGetRelid(rv, false);
1102 PG_RETURN_OID(result);
1107 * Given a C string, parse it into a qualified-name list.
1110 stringToQualifiedNameList(const char *string, const char *caller)
1117 /* We need a modifiable copy of the input string. */
1118 rawname = pstrdup(string);
1120 if (!SplitIdentifierString(rawname, '.', &namelist))
1122 (errcode(ERRCODE_INVALID_NAME),
1123 errmsg("invalid name syntax")));
1125 if (namelist == NIL)
1127 (errcode(ERRCODE_INVALID_NAME),
1128 errmsg("invalid name syntax")));
1130 foreach(l, namelist)
1132 char *curname = (char *) lfirst(l);
1134 result = lappend(result, makeString(pstrdup(curname)));
1138 list_free(namelist);
1143 /*****************************************************************************
1144 * SUPPORT ROUTINES *
1145 *****************************************************************************/
1148 * Given a C string, parse it into a qualified function or operator name
1149 * followed by a parenthesized list of type names. Reduce the
1150 * type names to an array of OIDs (returned into *nargs and *argtypes;
1151 * the argtypes array should be of size FUNC_MAX_ARGS). The function or
1152 * operator name is returned to *names as a List of Strings.
1154 * If allowNone is TRUE, accept "NONE" and return it as InvalidOid (this is
1155 * for unary operators).
1158 parseNameAndArgTypes(const char *string, const char *caller,
1160 List **names, int *nargs, Oid *argtypes)
1172 /* We need a modifiable copy of the input string. */
1173 rawname = pstrdup(string);
1175 /* Scan to find the expected left paren; mustn't be quoted */
1177 for (ptr = rawname; *ptr; ptr++)
1180 in_quote = !in_quote;
1181 else if (*ptr == '(' && !in_quote)
1186 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1187 errmsg("expected a left parenthesis")));
1189 /* Separate the name and parse it into a list */
1191 *names = stringToQualifiedNameList(rawname, caller);
1193 /* Check for the trailing right parenthesis and remove it */
1194 ptr2 = ptr + strlen(ptr);
1195 while (--ptr2 > ptr)
1197 if (!isspace((unsigned char) *ptr2))
1202 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1203 errmsg("expected a right parenthesis")));
1207 /* Separate the remaining string into comma-separated type names */
1213 /* allow leading whitespace */
1214 while (isspace((unsigned char) *ptr))
1218 /* End of string. Okay unless we had a comma before. */
1221 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1222 errmsg("expected a type name")));
1226 /* Find end of type name --- end of string or comma */
1227 /* ... but not a quoted or parenthesized comma */
1233 in_quote = !in_quote;
1234 else if (*ptr == ',' && !in_quote && paren_count == 0)
1251 if (in_quote || paren_count != 0)
1253 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1254 errmsg("improper type name")));
1265 Assert(*ptr == '\0');
1267 /* Lop off trailing whitespace */
1268 while (--ptr2 >= typename)
1270 if (!isspace((unsigned char) *ptr2))
1275 if (allowNone && pg_strcasecmp(typename, "none") == 0)
1277 /* Special case for NONE */
1278 typeid = InvalidOid;
1283 /* Use full parser to resolve the type name */
1284 parseTypeString(typename, &typeid, &typmod);
1286 if (*nargs >= FUNC_MAX_ARGS)
1288 (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
1289 errmsg("too many arguments")));
1291 argtypes[*nargs] = typeid;