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-2008, PostgreSQL Global Development Group
12 * Portions Copyright (c) 1994, Regents of the University of California
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_class.h"
29 #include "catalog/pg_operator.h"
30 #include "catalog/pg_proc.h"
31 #include "catalog/pg_ts_config.h"
32 #include "catalog/pg_ts_dict.h"
33 #include "catalog/pg_type.h"
34 #include "miscadmin.h"
35 #include "parser/parse_type.h"
36 #include "utils/builtins.h"
37 #include "utils/fmgroids.h"
38 #include "utils/lsyscache.h"
39 #include "utils/syscache.h"
40 #include "utils/tqual.h"
42 static void parseNameAndArgTypes(const char *string
, bool allowNone
,
43 List
**names
, int *nargs
, Oid
*argtypes
);
46 /*****************************************************************************
48 *****************************************************************************/
51 * regprocin - converts "proname" to proc OID
53 * We also accept a numeric OID, for symmetry with the output routine.
55 * '-' signifies unknown (OID 0). In all other cases, the input must
56 * match an existing pg_proc entry.
59 regprocin(PG_FUNCTION_ARGS
)
61 char *pro_name_or_oid
= PG_GETARG_CSTRING(0);
62 RegProcedure result
= InvalidOid
;
64 FuncCandidateList clist
;
67 if (strcmp(pro_name_or_oid
, "-") == 0)
68 PG_RETURN_OID(InvalidOid
);
71 if (pro_name_or_oid
[0] >= '0' &&
72 pro_name_or_oid
[0] <= '9' &&
73 strspn(pro_name_or_oid
, "0123456789") == strlen(pro_name_or_oid
))
75 result
= DatumGetObjectId(DirectFunctionCall1(oidin
,
76 CStringGetDatum(pro_name_or_oid
)));
77 PG_RETURN_OID(result
);
80 /* Else it's a name, possibly schema-qualified */
83 * In bootstrap mode we assume the given name is not schema-qualified, and
84 * just search pg_proc for a unique match. This is needed for
85 * initializing other system catalogs (pg_namespace may not exist yet, and
86 * certainly there are no schemas other than pg_catalog).
88 if (IsBootstrapProcessingMode())
98 BTEqualStrategyNumber
, F_NAMEEQ
,
99 CStringGetDatum(pro_name_or_oid
));
101 hdesc
= heap_open(ProcedureRelationId
, AccessShareLock
);
102 sysscan
= systable_beginscan(hdesc
, ProcedureNameArgsNspIndexId
, true,
103 SnapshotNow
, 1, skey
);
105 while (HeapTupleIsValid(tuple
= systable_getnext(sysscan
)))
107 result
= (RegProcedure
) HeapTupleGetOid(tuple
);
112 systable_endscan(sysscan
);
113 heap_close(hdesc
, AccessShareLock
);
117 (errcode(ERRCODE_UNDEFINED_FUNCTION
),
118 errmsg("function \"%s\" does not exist", pro_name_or_oid
)));
120 else if (matches
> 1)
122 (errcode(ERRCODE_AMBIGUOUS_FUNCTION
),
123 errmsg("more than one function named \"%s\"",
126 PG_RETURN_OID(result
);
130 * Normal case: parse the name into components and see if it matches any
131 * pg_proc entries in the current search path.
133 names
= stringToQualifiedNameList(pro_name_or_oid
);
134 clist
= FuncnameGetCandidates(names
, -1, false);
138 (errcode(ERRCODE_UNDEFINED_FUNCTION
),
139 errmsg("function \"%s\" does not exist", pro_name_or_oid
)));
140 else if (clist
->next
!= NULL
)
142 (errcode(ERRCODE_AMBIGUOUS_FUNCTION
),
143 errmsg("more than one function named \"%s\"",
148 PG_RETURN_OID(result
);
152 * regprocout - converts proc OID to "pro_name"
155 regprocout(PG_FUNCTION_ARGS
)
157 RegProcedure proid
= PG_GETARG_OID(0);
161 if (proid
== InvalidOid
)
163 result
= pstrdup("-");
164 PG_RETURN_CSTRING(result
);
167 proctup
= SearchSysCache(PROCOID
,
168 ObjectIdGetDatum(proid
),
171 if (HeapTupleIsValid(proctup
))
173 Form_pg_proc procform
= (Form_pg_proc
) GETSTRUCT(proctup
);
174 char *proname
= NameStr(procform
->proname
);
177 * In bootstrap mode, skip the fancy namespace stuff and just return
178 * the proc name. (This path is only needed for debugging output
181 if (IsBootstrapProcessingMode())
182 result
= pstrdup(proname
);
186 FuncCandidateList clist
;
189 * Would this proc be found (uniquely!) by regprocin? If not,
192 clist
= FuncnameGetCandidates(list_make1(makeString(proname
)),
194 if (clist
!= NULL
&& clist
->next
== NULL
&&
198 nspname
= get_namespace_name(procform
->pronamespace
);
200 result
= quote_qualified_identifier(nspname
, proname
);
203 ReleaseSysCache(proctup
);
207 /* If OID doesn't match any pg_proc entry, return it numerically */
208 result
= (char *) palloc(NAMEDATALEN
);
209 snprintf(result
, NAMEDATALEN
, "%u", proid
);
212 PG_RETURN_CSTRING(result
);
216 * regprocrecv - converts external binary format to regproc
219 regprocrecv(PG_FUNCTION_ARGS
)
221 /* Exactly the same as oidrecv, so share code */
222 return oidrecv(fcinfo
);
226 * regprocsend - converts regproc to binary format
229 regprocsend(PG_FUNCTION_ARGS
)
231 /* Exactly the same as oidsend, so share code */
232 return oidsend(fcinfo
);
237 * regprocedurein - converts "proname(args)" to proc OID
239 * We also accept a numeric OID, for symmetry with the output routine.
241 * '-' signifies unknown (OID 0). In all other cases, the input must
242 * match an existing pg_proc entry.
245 regprocedurein(PG_FUNCTION_ARGS
)
247 char *pro_name_or_oid
= PG_GETARG_CSTRING(0);
248 RegProcedure result
= InvalidOid
;
251 Oid argtypes
[FUNC_MAX_ARGS
];
252 FuncCandidateList clist
;
255 if (strcmp(pro_name_or_oid
, "-") == 0)
256 PG_RETURN_OID(InvalidOid
);
259 if (pro_name_or_oid
[0] >= '0' &&
260 pro_name_or_oid
[0] <= '9' &&
261 strspn(pro_name_or_oid
, "0123456789") == strlen(pro_name_or_oid
))
263 result
= DatumGetObjectId(DirectFunctionCall1(oidin
,
264 CStringGetDatum(pro_name_or_oid
)));
265 PG_RETURN_OID(result
);
269 * Else it's a name and arguments. Parse the name and arguments, look up
270 * potential matches in the current namespace search list, and scan to see
271 * which one exactly matches the given argument types. (There will not be
272 * more than one match.)
274 * XXX at present, this code will not work in bootstrap mode, hence this
275 * datatype cannot be used for any system column that needs to receive
276 * data during bootstrap.
278 parseNameAndArgTypes(pro_name_or_oid
, false, &names
, &nargs
, argtypes
);
280 clist
= FuncnameGetCandidates(names
, nargs
, false);
282 for (; clist
; clist
= clist
->next
)
284 if (memcmp(clist
->args
, argtypes
, nargs
* sizeof(Oid
)) == 0)
290 (errcode(ERRCODE_UNDEFINED_FUNCTION
),
291 errmsg("function \"%s\" does not exist", pro_name_or_oid
)));
295 PG_RETURN_OID(result
);
299 * format_procedure - converts proc OID to "pro_name(args)"
301 * This exports the useful functionality of regprocedureout for use
302 * in other backend modules. The result is a palloc'd string.
305 format_procedure(Oid procedure_oid
)
310 proctup
= SearchSysCache(PROCOID
,
311 ObjectIdGetDatum(procedure_oid
),
314 if (HeapTupleIsValid(proctup
))
316 Form_pg_proc procform
= (Form_pg_proc
) GETSTRUCT(proctup
);
317 char *proname
= NameStr(procform
->proname
);
318 int nargs
= procform
->pronargs
;
323 /* XXX no support here for bootstrap mode */
325 initStringInfo(&buf
);
328 * Would this proc be found (given the right args) by regprocedurein?
329 * If not, we need to qualify it.
331 if (FunctionIsVisible(procedure_oid
))
334 nspname
= get_namespace_name(procform
->pronamespace
);
336 appendStringInfo(&buf
, "%s(",
337 quote_qualified_identifier(nspname
, proname
));
338 for (i
= 0; i
< nargs
; i
++)
340 Oid thisargtype
= procform
->proargtypes
.values
[i
];
343 appendStringInfoChar(&buf
, ',');
344 appendStringInfoString(&buf
, format_type_be(thisargtype
));
346 appendStringInfoChar(&buf
, ')');
350 ReleaseSysCache(proctup
);
354 /* If OID doesn't match any pg_proc entry, return it numerically */
355 result
= (char *) palloc(NAMEDATALEN
);
356 snprintf(result
, NAMEDATALEN
, "%u", procedure_oid
);
363 * regprocedureout - converts proc OID to "pro_name(args)"
366 regprocedureout(PG_FUNCTION_ARGS
)
368 RegProcedure proid
= PG_GETARG_OID(0);
371 if (proid
== InvalidOid
)
372 result
= pstrdup("-");
374 result
= format_procedure(proid
);
376 PG_RETURN_CSTRING(result
);
380 * regprocedurerecv - converts external binary format to regprocedure
383 regprocedurerecv(PG_FUNCTION_ARGS
)
385 /* Exactly the same as oidrecv, so share code */
386 return oidrecv(fcinfo
);
390 * regproceduresend - converts regprocedure to binary format
393 regproceduresend(PG_FUNCTION_ARGS
)
395 /* Exactly the same as oidsend, so share code */
396 return oidsend(fcinfo
);
401 * regoperin - converts "oprname" to operator OID
403 * We also accept a numeric OID, for symmetry with the output routine.
405 * '0' signifies unknown (OID 0). In all other cases, the input must
406 * match an existing pg_operator entry.
409 regoperin(PG_FUNCTION_ARGS
)
411 char *opr_name_or_oid
= PG_GETARG_CSTRING(0);
412 Oid result
= InvalidOid
;
414 FuncCandidateList clist
;
417 if (strcmp(opr_name_or_oid
, "0") == 0)
418 PG_RETURN_OID(InvalidOid
);
421 if (opr_name_or_oid
[0] >= '0' &&
422 opr_name_or_oid
[0] <= '9' &&
423 strspn(opr_name_or_oid
, "0123456789") == strlen(opr_name_or_oid
))
425 result
= DatumGetObjectId(DirectFunctionCall1(oidin
,
426 CStringGetDatum(opr_name_or_oid
)));
427 PG_RETURN_OID(result
);
430 /* Else it's a name, possibly schema-qualified */
433 * In bootstrap mode we assume the given name is not schema-qualified, and
434 * just search pg_operator for a unique match. This is needed for
435 * initializing other system catalogs (pg_namespace may not exist yet, and
436 * certainly there are no schemas other than pg_catalog).
438 if (IsBootstrapProcessingMode())
446 ScanKeyInit(&skey
[0],
447 Anum_pg_operator_oprname
,
448 BTEqualStrategyNumber
, F_NAMEEQ
,
449 CStringGetDatum(opr_name_or_oid
));
451 hdesc
= heap_open(OperatorRelationId
, AccessShareLock
);
452 sysscan
= systable_beginscan(hdesc
, OperatorNameNspIndexId
, true,
453 SnapshotNow
, 1, skey
);
455 while (HeapTupleIsValid(tuple
= systable_getnext(sysscan
)))
457 result
= HeapTupleGetOid(tuple
);
462 systable_endscan(sysscan
);
463 heap_close(hdesc
, AccessShareLock
);
467 (errcode(ERRCODE_UNDEFINED_FUNCTION
),
468 errmsg("operator does not exist: %s", opr_name_or_oid
)));
469 else if (matches
> 1)
471 (errcode(ERRCODE_AMBIGUOUS_FUNCTION
),
472 errmsg("more than one operator named %s",
475 PG_RETURN_OID(result
);
479 * Normal case: parse the name into components and see if it matches any
480 * pg_operator entries in the current search path.
482 names
= stringToQualifiedNameList(opr_name_or_oid
);
483 clist
= OpernameGetCandidates(names
, '\0');
487 (errcode(ERRCODE_UNDEFINED_FUNCTION
),
488 errmsg("operator does not exist: %s", opr_name_or_oid
)));
489 else if (clist
->next
!= NULL
)
491 (errcode(ERRCODE_AMBIGUOUS_FUNCTION
),
492 errmsg("more than one operator named %s",
497 PG_RETURN_OID(result
);
501 * regoperout - converts operator OID to "opr_name"
504 regoperout(PG_FUNCTION_ARGS
)
506 Oid oprid
= PG_GETARG_OID(0);
510 if (oprid
== InvalidOid
)
512 result
= pstrdup("0");
513 PG_RETURN_CSTRING(result
);
516 opertup
= SearchSysCache(OPEROID
,
517 ObjectIdGetDatum(oprid
),
520 if (HeapTupleIsValid(opertup
))
522 Form_pg_operator operform
= (Form_pg_operator
) GETSTRUCT(opertup
);
523 char *oprname
= NameStr(operform
->oprname
);
526 * In bootstrap mode, skip the fancy namespace stuff and just return
527 * the oper name. (This path is only needed for debugging output
530 if (IsBootstrapProcessingMode())
531 result
= pstrdup(oprname
);
534 FuncCandidateList clist
;
537 * Would this oper be found (uniquely!) by regoperin? If not,
540 clist
= OpernameGetCandidates(list_make1(makeString(oprname
)),
542 if (clist
!= NULL
&& clist
->next
== NULL
&&
544 result
= pstrdup(oprname
);
549 nspname
= get_namespace_name(operform
->oprnamespace
);
550 nspname
= quote_identifier(nspname
);
551 result
= (char *) palloc(strlen(nspname
) + strlen(oprname
) + 2);
552 sprintf(result
, "%s.%s", nspname
, oprname
);
556 ReleaseSysCache(opertup
);
561 * If OID doesn't match any pg_operator entry, return it numerically
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);
606 Oid argtypes
[FUNC_MAX_ARGS
];
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
, true, &names
, &nargs
, argtypes
);
635 (errcode(ERRCODE_UNDEFINED_PARAMETER
),
636 errmsg("missing argument"),
637 errhint("Use NONE to denote the missing argument of a unary operator.")));
640 (errcode(ERRCODE_TOO_MANY_ARGUMENTS
),
641 errmsg("too many arguments"),
642 errhint("Provide two argument types for operator.")));
644 result
= OpernameGetOprid(names
, argtypes
[0], argtypes
[1]);
646 if (!OidIsValid(result
))
648 (errcode(ERRCODE_UNDEFINED_FUNCTION
),
649 errmsg("operator does not exist: %s", opr_name_or_oid
)));
651 PG_RETURN_OID(result
);
655 * format_operator - converts operator OID to "opr_name(args)"
657 * This exports the useful functionality of regoperatorout for use
658 * in other backend modules. The result is a palloc'd string.
661 format_operator(Oid operator_oid
)
666 opertup
= SearchSysCache(OPEROID
,
667 ObjectIdGetDatum(operator_oid
),
670 if (HeapTupleIsValid(opertup
))
672 Form_pg_operator operform
= (Form_pg_operator
) GETSTRUCT(opertup
);
673 char *oprname
= NameStr(operform
->oprname
);
677 /* XXX no support here for bootstrap mode */
679 initStringInfo(&buf
);
682 * Would this oper be found (given the right args) by regoperatorin?
683 * If not, we need to qualify it.
685 if (!OperatorIsVisible(operator_oid
))
687 nspname
= get_namespace_name(operform
->oprnamespace
);
688 appendStringInfo(&buf
, "%s.",
689 quote_identifier(nspname
));
692 appendStringInfo(&buf
, "%s(", oprname
);
694 if (operform
->oprleft
)
695 appendStringInfo(&buf
, "%s,",
696 format_type_be(operform
->oprleft
));
698 appendStringInfo(&buf
, "NONE,");
700 if (operform
->oprright
)
701 appendStringInfo(&buf
, "%s)",
702 format_type_be(operform
->oprright
));
704 appendStringInfo(&buf
, "NONE)");
708 ReleaseSysCache(opertup
);
713 * If OID doesn't match any pg_operator entry, return it numerically
715 result
= (char *) palloc(NAMEDATALEN
);
716 snprintf(result
, NAMEDATALEN
, "%u", operator_oid
);
723 * regoperatorout - converts operator OID to "opr_name(args)"
726 regoperatorout(PG_FUNCTION_ARGS
)
728 Oid oprid
= PG_GETARG_OID(0);
731 if (oprid
== InvalidOid
)
732 result
= pstrdup("0");
734 result
= format_operator(oprid
);
736 PG_RETURN_CSTRING(result
);
740 * regoperatorrecv - converts external binary format to regoperator
743 regoperatorrecv(PG_FUNCTION_ARGS
)
745 /* Exactly the same as oidrecv, so share code */
746 return oidrecv(fcinfo
);
750 * regoperatorsend - converts regoperator to binary format
753 regoperatorsend(PG_FUNCTION_ARGS
)
755 /* Exactly the same as oidsend, so share code */
756 return oidsend(fcinfo
);
761 * regclassin - converts "classname" to class OID
763 * We also accept a numeric OID, for symmetry with the output routine.
765 * '-' signifies unknown (OID 0). In all other cases, the input must
766 * match an existing pg_class entry.
769 regclassin(PG_FUNCTION_ARGS
)
771 char *class_name_or_oid
= PG_GETARG_CSTRING(0);
772 Oid result
= InvalidOid
;
776 if (strcmp(class_name_or_oid
, "-") == 0)
777 PG_RETURN_OID(InvalidOid
);
780 if (class_name_or_oid
[0] >= '0' &&
781 class_name_or_oid
[0] <= '9' &&
782 strspn(class_name_or_oid
, "0123456789") == strlen(class_name_or_oid
))
784 result
= DatumGetObjectId(DirectFunctionCall1(oidin
,
785 CStringGetDatum(class_name_or_oid
)));
786 PG_RETURN_OID(result
);
789 /* Else it's a name, possibly schema-qualified */
792 * In bootstrap mode we assume the given name is not schema-qualified, and
793 * just search pg_class for a match. This is needed for initializing
794 * other system catalogs (pg_namespace may not exist yet, and certainly
795 * there are no schemas other than pg_catalog).
797 if (IsBootstrapProcessingMode())
804 ScanKeyInit(&skey
[0],
805 Anum_pg_class_relname
,
806 BTEqualStrategyNumber
, F_NAMEEQ
,
807 CStringGetDatum(class_name_or_oid
));
809 hdesc
= heap_open(RelationRelationId
, AccessShareLock
);
810 sysscan
= systable_beginscan(hdesc
, ClassNameNspIndexId
, true,
811 SnapshotNow
, 1, skey
);
813 if (HeapTupleIsValid(tuple
= systable_getnext(sysscan
)))
814 result
= HeapTupleGetOid(tuple
);
817 (errcode(ERRCODE_UNDEFINED_TABLE
),
818 errmsg("relation \"%s\" does not exist", class_name_or_oid
)));
820 /* We assume there can be only one match */
822 systable_endscan(sysscan
);
823 heap_close(hdesc
, AccessShareLock
);
825 PG_RETURN_OID(result
);
829 * Normal case: parse the name into components and see if it matches any
830 * pg_class entries in the current search path.
832 names
= stringToQualifiedNameList(class_name_or_oid
);
834 result
= RangeVarGetRelid(makeRangeVarFromNameList(names
), false);
836 PG_RETURN_OID(result
);
840 * regclassout - converts class OID to "class_name"
843 regclassout(PG_FUNCTION_ARGS
)
845 Oid classid
= PG_GETARG_OID(0);
849 if (classid
== InvalidOid
)
851 result
= pstrdup("-");
852 PG_RETURN_CSTRING(result
);
855 classtup
= SearchSysCache(RELOID
,
856 ObjectIdGetDatum(classid
),
859 if (HeapTupleIsValid(classtup
))
861 Form_pg_class classform
= (Form_pg_class
) GETSTRUCT(classtup
);
862 char *classname
= NameStr(classform
->relname
);
865 * In bootstrap mode, skip the fancy namespace stuff and just return
866 * the class name. (This path is only needed for debugging output
869 if (IsBootstrapProcessingMode())
870 result
= pstrdup(classname
);
876 * Would this class be found by regclassin? If not, qualify it.
878 if (RelationIsVisible(classid
))
881 nspname
= get_namespace_name(classform
->relnamespace
);
883 result
= quote_qualified_identifier(nspname
, classname
);
886 ReleaseSysCache(classtup
);
890 /* If OID doesn't match any pg_class entry, return it numerically */
891 result
= (char *) palloc(NAMEDATALEN
);
892 snprintf(result
, NAMEDATALEN
, "%u", classid
);
895 PG_RETURN_CSTRING(result
);
899 * regclassrecv - converts external binary format to regclass
902 regclassrecv(PG_FUNCTION_ARGS
)
904 /* Exactly the same as oidrecv, so share code */
905 return oidrecv(fcinfo
);
909 * regclasssend - converts regclass to binary format
912 regclasssend(PG_FUNCTION_ARGS
)
914 /* Exactly the same as oidsend, so share code */
915 return oidsend(fcinfo
);
920 * regtypein - converts "typename" to type OID
922 * We also accept a numeric OID, for symmetry with the output routine.
924 * '-' signifies unknown (OID 0). In all other cases, the input must
925 * match an existing pg_type entry.
927 * In bootstrap mode the name must just equal some existing name in pg_type.
928 * In normal mode the type name can be specified using the full type syntax
929 * recognized by the parser; for example, DOUBLE PRECISION and INTEGER[] will
930 * work and be translated to the correct type names. (We ignore any typmod
931 * info generated by the parser, however.)
934 regtypein(PG_FUNCTION_ARGS
)
936 char *typ_name_or_oid
= PG_GETARG_CSTRING(0);
937 Oid result
= InvalidOid
;
941 if (strcmp(typ_name_or_oid
, "-") == 0)
942 PG_RETURN_OID(InvalidOid
);
945 if (typ_name_or_oid
[0] >= '0' &&
946 typ_name_or_oid
[0] <= '9' &&
947 strspn(typ_name_or_oid
, "0123456789") == strlen(typ_name_or_oid
))
949 result
= DatumGetObjectId(DirectFunctionCall1(oidin
,
950 CStringGetDatum(typ_name_or_oid
)));
951 PG_RETURN_OID(result
);
954 /* Else it's a type name, possibly schema-qualified or decorated */
957 * In bootstrap mode we assume the given name is not schema-qualified, and
958 * just search pg_type for a match. This is needed for initializing other
959 * system catalogs (pg_namespace may not exist yet, and certainly there
960 * are no schemas other than pg_catalog).
962 if (IsBootstrapProcessingMode())
969 ScanKeyInit(&skey
[0],
970 Anum_pg_type_typname
,
971 BTEqualStrategyNumber
, F_NAMEEQ
,
972 CStringGetDatum(typ_name_or_oid
));
974 hdesc
= heap_open(TypeRelationId
, AccessShareLock
);
975 sysscan
= systable_beginscan(hdesc
, TypeNameNspIndexId
, true,
976 SnapshotNow
, 1, skey
);
978 if (HeapTupleIsValid(tuple
= systable_getnext(sysscan
)))
979 result
= HeapTupleGetOid(tuple
);
982 (errcode(ERRCODE_UNDEFINED_OBJECT
),
983 errmsg("type \"%s\" does not exist", typ_name_or_oid
)));
985 /* We assume there can be only one match */
987 systable_endscan(sysscan
);
988 heap_close(hdesc
, AccessShareLock
);
990 PG_RETURN_OID(result
);
994 * Normal case: invoke the full parser to deal with special cases such as
997 parseTypeString(typ_name_or_oid
, &result
, &typmod
);
999 PG_RETURN_OID(result
);
1003 * regtypeout - converts type OID to "typ_name"
1006 regtypeout(PG_FUNCTION_ARGS
)
1008 Oid typid
= PG_GETARG_OID(0);
1012 if (typid
== InvalidOid
)
1014 result
= pstrdup("-");
1015 PG_RETURN_CSTRING(result
);
1018 typetup
= SearchSysCache(TYPEOID
,
1019 ObjectIdGetDatum(typid
),
1022 if (HeapTupleIsValid(typetup
))
1024 Form_pg_type typeform
= (Form_pg_type
) GETSTRUCT(typetup
);
1027 * In bootstrap mode, skip the fancy namespace stuff and just return
1028 * the type name. (This path is only needed for debugging output
1031 if (IsBootstrapProcessingMode())
1033 char *typname
= NameStr(typeform
->typname
);
1035 result
= pstrdup(typname
);
1038 result
= format_type_be(typid
);
1040 ReleaseSysCache(typetup
);
1044 /* If OID doesn't match any pg_type entry, return it numerically */
1045 result
= (char *) palloc(NAMEDATALEN
);
1046 snprintf(result
, NAMEDATALEN
, "%u", typid
);
1049 PG_RETURN_CSTRING(result
);
1053 * regtyperecv - converts external binary format to regtype
1056 regtyperecv(PG_FUNCTION_ARGS
)
1058 /* Exactly the same as oidrecv, so share code */
1059 return oidrecv(fcinfo
);
1063 * regtypesend - converts regtype to binary format
1066 regtypesend(PG_FUNCTION_ARGS
)
1068 /* Exactly the same as oidsend, so share code */
1069 return oidsend(fcinfo
);
1074 * regconfigin - converts "tsconfigname" to tsconfig OID
1076 * We also accept a numeric OID, for symmetry with the output routine.
1078 * '-' signifies unknown (OID 0). In all other cases, the input must
1079 * match an existing pg_ts_config entry.
1081 * This function is not needed in bootstrap mode, so we don't worry about
1082 * making it work then.
1085 regconfigin(PG_FUNCTION_ARGS
)
1087 char *cfg_name_or_oid
= PG_GETARG_CSTRING(0);
1092 if (strcmp(cfg_name_or_oid
, "-") == 0)
1093 PG_RETURN_OID(InvalidOid
);
1096 if (cfg_name_or_oid
[0] >= '0' &&
1097 cfg_name_or_oid
[0] <= '9' &&
1098 strspn(cfg_name_or_oid
, "0123456789") == strlen(cfg_name_or_oid
))
1100 result
= DatumGetObjectId(DirectFunctionCall1(oidin
,
1101 CStringGetDatum(cfg_name_or_oid
)));
1102 PG_RETURN_OID(result
);
1106 * Normal case: parse the name into components and see if it matches any
1107 * pg_ts_config entries in the current search path.
1109 names
= stringToQualifiedNameList(cfg_name_or_oid
);
1111 result
= TSConfigGetCfgid(names
, false);
1113 PG_RETURN_OID(result
);
1117 * regconfigout - converts tsconfig OID to "tsconfigname"
1120 regconfigout(PG_FUNCTION_ARGS
)
1122 Oid cfgid
= PG_GETARG_OID(0);
1126 if (cfgid
== InvalidOid
)
1128 result
= pstrdup("-");
1129 PG_RETURN_CSTRING(result
);
1132 cfgtup
= SearchSysCache(TSCONFIGOID
,
1133 ObjectIdGetDatum(cfgid
),
1136 if (HeapTupleIsValid(cfgtup
))
1138 Form_pg_ts_config cfgform
= (Form_pg_ts_config
) GETSTRUCT(cfgtup
);
1139 char *cfgname
= NameStr(cfgform
->cfgname
);
1143 * Would this config be found by regconfigin? If not, qualify it.
1145 if (TSConfigIsVisible(cfgid
))
1148 nspname
= get_namespace_name(cfgform
->cfgnamespace
);
1150 result
= quote_qualified_identifier(nspname
, cfgname
);
1152 ReleaseSysCache(cfgtup
);
1156 /* If OID doesn't match any pg_ts_config row, return it numerically */
1157 result
= (char *) palloc(NAMEDATALEN
);
1158 snprintf(result
, NAMEDATALEN
, "%u", cfgid
);
1161 PG_RETURN_CSTRING(result
);
1165 * regconfigrecv - converts external binary format to regconfig
1168 regconfigrecv(PG_FUNCTION_ARGS
)
1170 /* Exactly the same as oidrecv, so share code */
1171 return oidrecv(fcinfo
);
1175 * regconfigsend - converts regconfig to binary format
1178 regconfigsend(PG_FUNCTION_ARGS
)
1180 /* Exactly the same as oidsend, so share code */
1181 return oidsend(fcinfo
);
1186 * regdictionaryin - converts "tsdictionaryname" to tsdictionary OID
1188 * We also accept a numeric OID, for symmetry with the output routine.
1190 * '-' signifies unknown (OID 0). In all other cases, the input must
1191 * match an existing pg_ts_dict entry.
1193 * This function is not needed in bootstrap mode, so we don't worry about
1194 * making it work then.
1197 regdictionaryin(PG_FUNCTION_ARGS
)
1199 char *dict_name_or_oid
= PG_GETARG_CSTRING(0);
1204 if (strcmp(dict_name_or_oid
, "-") == 0)
1205 PG_RETURN_OID(InvalidOid
);
1208 if (dict_name_or_oid
[0] >= '0' &&
1209 dict_name_or_oid
[0] <= '9' &&
1210 strspn(dict_name_or_oid
, "0123456789") == strlen(dict_name_or_oid
))
1212 result
= DatumGetObjectId(DirectFunctionCall1(oidin
,
1213 CStringGetDatum(dict_name_or_oid
)));
1214 PG_RETURN_OID(result
);
1218 * Normal case: parse the name into components and see if it matches any
1219 * pg_ts_dict entries in the current search path.
1221 names
= stringToQualifiedNameList(dict_name_or_oid
);
1223 result
= TSDictionaryGetDictid(names
, false);
1225 PG_RETURN_OID(result
);
1229 * regdictionaryout - converts tsdictionary OID to "tsdictionaryname"
1232 regdictionaryout(PG_FUNCTION_ARGS
)
1234 Oid dictid
= PG_GETARG_OID(0);
1238 if (dictid
== InvalidOid
)
1240 result
= pstrdup("-");
1241 PG_RETURN_CSTRING(result
);
1244 dicttup
= SearchSysCache(TSDICTOID
,
1245 ObjectIdGetDatum(dictid
),
1248 if (HeapTupleIsValid(dicttup
))
1250 Form_pg_ts_dict dictform
= (Form_pg_ts_dict
) GETSTRUCT(dicttup
);
1251 char *dictname
= NameStr(dictform
->dictname
);
1255 * Would this dictionary be found by regdictionaryin? If not, qualify
1258 if (TSDictionaryIsVisible(dictid
))
1261 nspname
= get_namespace_name(dictform
->dictnamespace
);
1263 result
= quote_qualified_identifier(nspname
, dictname
);
1265 ReleaseSysCache(dicttup
);
1269 /* If OID doesn't match any pg_ts_dict row, return it numerically */
1270 result
= (char *) palloc(NAMEDATALEN
);
1271 snprintf(result
, NAMEDATALEN
, "%u", dictid
);
1274 PG_RETURN_CSTRING(result
);
1278 * regdictionaryrecv - converts external binary format to regdictionary
1281 regdictionaryrecv(PG_FUNCTION_ARGS
)
1283 /* Exactly the same as oidrecv, so share code */
1284 return oidrecv(fcinfo
);
1288 * regdictionarysend - converts regdictionary to binary format
1291 regdictionarysend(PG_FUNCTION_ARGS
)
1293 /* Exactly the same as oidsend, so share code */
1294 return oidsend(fcinfo
);
1299 * text_regclass: convert text to regclass
1301 * This could be replaced by CoerceViaIO, except that we need to treat
1302 * text-to-regclass as an implicit cast to support legacy forms of nextval()
1303 * and related functions.
1306 text_regclass(PG_FUNCTION_ARGS
)
1308 text
*relname
= PG_GETARG_TEXT_P(0);
1312 rv
= makeRangeVarFromNameList(textToQualifiedNameList(relname
));
1313 result
= RangeVarGetRelid(rv
, false);
1315 PG_RETURN_OID(result
);
1320 * Given a C string, parse it into a qualified-name list.
1323 stringToQualifiedNameList(const char *string
)
1330 /* We need a modifiable copy of the input string. */
1331 rawname
= pstrdup(string
);
1333 if (!SplitIdentifierString(rawname
, '.', &namelist
))
1335 (errcode(ERRCODE_INVALID_NAME
),
1336 errmsg("invalid name syntax")));
1338 if (namelist
== NIL
)
1340 (errcode(ERRCODE_INVALID_NAME
),
1341 errmsg("invalid name syntax")));
1343 foreach(l
, namelist
)
1345 char *curname
= (char *) lfirst(l
);
1347 result
= lappend(result
, makeString(pstrdup(curname
)));
1351 list_free(namelist
);
1356 /*****************************************************************************
1357 * SUPPORT ROUTINES *
1358 *****************************************************************************/
1361 * Given a C string, parse it into a qualified function or operator name
1362 * followed by a parenthesized list of type names. Reduce the
1363 * type names to an array of OIDs (returned into *nargs and *argtypes;
1364 * the argtypes array should be of size FUNC_MAX_ARGS). The function or
1365 * operator name is returned to *names as a List of Strings.
1367 * If allowNone is TRUE, accept "NONE" and return it as InvalidOid (this is
1368 * for unary operators).
1371 parseNameAndArgTypes(const char *string
, bool allowNone
, List
**names
,
1372 int *nargs
, Oid
*argtypes
)
1384 /* We need a modifiable copy of the input string. */
1385 rawname
= pstrdup(string
);
1387 /* Scan to find the expected left paren; mustn't be quoted */
1389 for (ptr
= rawname
; *ptr
; ptr
++)
1392 in_quote
= !in_quote
;
1393 else if (*ptr
== '(' && !in_quote
)
1398 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION
),
1399 errmsg("expected a left parenthesis")));
1401 /* Separate the name and parse it into a list */
1403 *names
= stringToQualifiedNameList(rawname
);
1405 /* Check for the trailing right parenthesis and remove it */
1406 ptr2
= ptr
+ strlen(ptr
);
1407 while (--ptr2
> ptr
)
1409 if (!isspace((unsigned char) *ptr2
))
1414 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION
),
1415 errmsg("expected a right parenthesis")));
1419 /* Separate the remaining string into comma-separated type names */
1425 /* allow leading whitespace */
1426 while (isspace((unsigned char) *ptr
))
1430 /* End of string. Okay unless we had a comma before. */
1433 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION
),
1434 errmsg("expected a type name")));
1438 /* Find end of type name --- end of string or comma */
1439 /* ... but not a quoted or parenthesized comma */
1445 in_quote
= !in_quote
;
1446 else if (*ptr
== ',' && !in_quote
&& paren_count
== 0)
1463 if (in_quote
|| paren_count
!= 0)
1465 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION
),
1466 errmsg("improper type name")));
1477 Assert(*ptr
== '\0');
1479 /* Lop off trailing whitespace */
1480 while (--ptr2
>= typename
)
1482 if (!isspace((unsigned char) *ptr2
))
1487 if (allowNone
&& pg_strcasecmp(typename
, "none") == 0)
1489 /* Special case for NONE */
1490 typeid = InvalidOid
;
1495 /* Use full parser to resolve the type name */
1496 parseTypeString(typename
, &typeid, &typmod
);
1498 if (*nargs
>= FUNC_MAX_ARGS
)
1500 (errcode(ERRCODE_TOO_MANY_ARGUMENTS
),
1501 errmsg("too many arguments")));
1503 argtypes
[*nargs
] = typeid;