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_operator.h"
29 #include "catalog/pg_proc.h"
30 #include "catalog/pg_ts_config.h"
31 #include "catalog/pg_ts_dict.h"
32 #include "catalog/pg_type.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"
39 #include "utils/tqual.h"
41 static void parseNameAndArgTypes(const char *string
, bool allowNone
,
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, and
83 * just search pg_proc for a unique match. This is needed for
84 * initializing other system catalogs (pg_namespace may not exist yet, and
85 * 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_open(ProcedureRelationId
, AccessShareLock
);
101 sysscan
= systable_beginscan(hdesc
, ProcedureNameArgsNspIndexId
, 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 any
130 * pg_proc entries in the current search path.
132 names
= stringToQualifiedNameList(pro_name_or_oid
);
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 return
177 * the proc name. (This path is only needed for debugging output
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 up
268 * potential matches in the current namespace search list, and scan to see
269 * which one exactly matches the given argument types. (There will not be
270 * 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
, false, &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
);
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);
604 Oid argtypes
[FUNC_MAX_ARGS
];
607 if (strcmp(opr_name_or_oid
, "0") == 0)
608 PG_RETURN_OID(InvalidOid
);
611 if (opr_name_or_oid
[0] >= '0' &&
612 opr_name_or_oid
[0] <= '9' &&
613 strspn(opr_name_or_oid
, "0123456789") == strlen(opr_name_or_oid
))
615 result
= DatumGetObjectId(DirectFunctionCall1(oidin
,
616 CStringGetDatum(opr_name_or_oid
)));
617 PG_RETURN_OID(result
);
621 * Else it's a name and arguments. Parse the name and arguments, look up
622 * potential matches in the current namespace search list, and scan to see
623 * which one exactly matches the given argument types. (There will not be
624 * more than one match.)
626 * XXX at present, this code will not work in bootstrap mode, hence this
627 * datatype cannot be used for any system column that needs to receive
628 * data during bootstrap.
630 parseNameAndArgTypes(opr_name_or_oid
, true, &names
, &nargs
, argtypes
);
633 (errcode(ERRCODE_UNDEFINED_PARAMETER
),
634 errmsg("missing argument"),
635 errhint("Use NONE to denote the missing argument of a unary operator.")));
638 (errcode(ERRCODE_TOO_MANY_ARGUMENTS
),
639 errmsg("too many arguments"),
640 errhint("Provide two argument types for operator.")));
642 result
= OpernameGetOprid(names
, argtypes
[0], argtypes
[1]);
644 if (!OidIsValid(result
))
646 (errcode(ERRCODE_UNDEFINED_FUNCTION
),
647 errmsg("operator does not exist: %s", opr_name_or_oid
)));
649 PG_RETURN_OID(result
);
653 * format_operator - converts operator OID to "opr_name(args)"
655 * This exports the useful functionality of regoperatorout for use
656 * in other backend modules. The result is a palloc'd string.
659 format_operator(Oid operator_oid
)
664 opertup
= SearchSysCache(OPEROID
,
665 ObjectIdGetDatum(operator_oid
),
668 if (HeapTupleIsValid(opertup
))
670 Form_pg_operator operform
= (Form_pg_operator
) GETSTRUCT(opertup
);
671 char *oprname
= NameStr(operform
->oprname
);
675 /* XXX no support here for bootstrap mode */
677 initStringInfo(&buf
);
680 * Would this oper be found (given the right args) by regoperatorin?
681 * If not, we need to qualify it.
683 if (!OperatorIsVisible(operator_oid
))
685 nspname
= get_namespace_name(operform
->oprnamespace
);
686 appendStringInfo(&buf
, "%s.",
687 quote_identifier(nspname
));
690 appendStringInfo(&buf
, "%s(", oprname
);
692 if (operform
->oprleft
)
693 appendStringInfo(&buf
, "%s,",
694 format_type_be(operform
->oprleft
));
696 appendStringInfo(&buf
, "NONE,");
698 if (operform
->oprright
)
699 appendStringInfo(&buf
, "%s)",
700 format_type_be(operform
->oprright
));
702 appendStringInfo(&buf
, "NONE)");
706 ReleaseSysCache(opertup
);
711 * If OID doesn't match any pg_operator entry, return it numerically
713 result
= (char *) palloc(NAMEDATALEN
);
714 snprintf(result
, NAMEDATALEN
, "%u", operator_oid
);
721 * regoperatorout - converts operator OID to "opr_name(args)"
724 regoperatorout(PG_FUNCTION_ARGS
)
726 Oid oprid
= PG_GETARG_OID(0);
729 if (oprid
== InvalidOid
)
730 result
= pstrdup("0");
732 result
= format_operator(oprid
);
734 PG_RETURN_CSTRING(result
);
738 * regoperatorrecv - converts external binary format to regoperator
741 regoperatorrecv(PG_FUNCTION_ARGS
)
743 /* Exactly the same as oidrecv, so share code */
744 return oidrecv(fcinfo
);
748 * regoperatorsend - converts regoperator to binary format
751 regoperatorsend(PG_FUNCTION_ARGS
)
753 /* Exactly the same as oidsend, so share code */
754 return oidsend(fcinfo
);
759 * regclassin - converts "classname" to class OID
761 * We also accept a numeric OID, for symmetry with the output routine.
763 * '-' signifies unknown (OID 0). In all other cases, the input must
764 * match an existing pg_class entry.
767 regclassin(PG_FUNCTION_ARGS
)
769 char *class_name_or_oid
= PG_GETARG_CSTRING(0);
770 Oid result
= InvalidOid
;
774 if (strcmp(class_name_or_oid
, "-") == 0)
775 PG_RETURN_OID(InvalidOid
);
778 if (class_name_or_oid
[0] >= '0' &&
779 class_name_or_oid
[0] <= '9' &&
780 strspn(class_name_or_oid
, "0123456789") == strlen(class_name_or_oid
))
782 result
= DatumGetObjectId(DirectFunctionCall1(oidin
,
783 CStringGetDatum(class_name_or_oid
)));
784 PG_RETURN_OID(result
);
787 /* Else it's a name, possibly schema-qualified */
790 * In bootstrap mode we assume the given name is not schema-qualified, and
791 * just search pg_class for a match. This is needed for initializing
792 * other system catalogs (pg_namespace may not exist yet, and certainly
793 * there are no schemas other than pg_catalog).
795 if (IsBootstrapProcessingMode())
802 ScanKeyInit(&skey
[0],
803 Anum_pg_class_relname
,
804 BTEqualStrategyNumber
, F_NAMEEQ
,
805 CStringGetDatum(class_name_or_oid
));
807 hdesc
= heap_open(RelationRelationId
, AccessShareLock
);
808 sysscan
= systable_beginscan(hdesc
, ClassNameNspIndexId
, true,
809 SnapshotNow
, 1, skey
);
811 if (HeapTupleIsValid(tuple
= systable_getnext(sysscan
)))
812 result
= HeapTupleGetOid(tuple
);
815 (errcode(ERRCODE_UNDEFINED_TABLE
),
816 errmsg("relation \"%s\" does not exist", class_name_or_oid
)));
818 /* We assume there can be only one match */
820 systable_endscan(sysscan
);
821 heap_close(hdesc
, AccessShareLock
);
823 PG_RETURN_OID(result
);
827 * Normal case: parse the name into components and see if it matches any
828 * pg_class entries in the current search path.
830 names
= stringToQualifiedNameList(class_name_or_oid
);
832 result
= RangeVarGetRelid(makeRangeVarFromNameList(names
), false);
834 PG_RETURN_OID(result
);
838 * regclassout - converts class OID to "class_name"
841 regclassout(PG_FUNCTION_ARGS
)
843 Oid classid
= PG_GETARG_OID(0);
847 if (classid
== InvalidOid
)
849 result
= pstrdup("-");
850 PG_RETURN_CSTRING(result
);
853 classtup
= SearchSysCache(RELOID
,
854 ObjectIdGetDatum(classid
),
857 if (HeapTupleIsValid(classtup
))
859 Form_pg_class classform
= (Form_pg_class
) GETSTRUCT(classtup
);
860 char *classname
= NameStr(classform
->relname
);
863 * In bootstrap mode, skip the fancy namespace stuff and just return
864 * the class name. (This path is only needed for debugging output
867 if (IsBootstrapProcessingMode())
868 result
= pstrdup(classname
);
874 * Would this class be found by regclassin? If not, qualify it.
876 if (RelationIsVisible(classid
))
879 nspname
= get_namespace_name(classform
->relnamespace
);
881 result
= quote_qualified_identifier(nspname
, classname
);
884 ReleaseSysCache(classtup
);
888 /* If OID doesn't match any pg_class entry, return it numerically */
889 result
= (char *) palloc(NAMEDATALEN
);
890 snprintf(result
, NAMEDATALEN
, "%u", classid
);
893 PG_RETURN_CSTRING(result
);
897 * regclassrecv - converts external binary format to regclass
900 regclassrecv(PG_FUNCTION_ARGS
)
902 /* Exactly the same as oidrecv, so share code */
903 return oidrecv(fcinfo
);
907 * regclasssend - converts regclass to binary format
910 regclasssend(PG_FUNCTION_ARGS
)
912 /* Exactly the same as oidsend, so share code */
913 return oidsend(fcinfo
);
918 * regtypein - converts "typename" to type OID
920 * We also accept a numeric OID, for symmetry with the output routine.
922 * '-' signifies unknown (OID 0). In all other cases, the input must
923 * match an existing pg_type entry.
925 * In bootstrap mode the name must just equal some existing name in pg_type.
926 * In normal mode the type name can be specified using the full type syntax
927 * recognized by the parser; for example, DOUBLE PRECISION and INTEGER[] will
928 * work and be translated to the correct type names. (We ignore any typmod
929 * info generated by the parser, however.)
932 regtypein(PG_FUNCTION_ARGS
)
934 char *typ_name_or_oid
= PG_GETARG_CSTRING(0);
935 Oid result
= InvalidOid
;
939 if (strcmp(typ_name_or_oid
, "-") == 0)
940 PG_RETURN_OID(InvalidOid
);
943 if (typ_name_or_oid
[0] >= '0' &&
944 typ_name_or_oid
[0] <= '9' &&
945 strspn(typ_name_or_oid
, "0123456789") == strlen(typ_name_or_oid
))
947 result
= DatumGetObjectId(DirectFunctionCall1(oidin
,
948 CStringGetDatum(typ_name_or_oid
)));
949 PG_RETURN_OID(result
);
952 /* Else it's a type name, possibly schema-qualified or decorated */
955 * In bootstrap mode we assume the given name is not schema-qualified, and
956 * just search pg_type for a match. This is needed for initializing other
957 * system catalogs (pg_namespace may not exist yet, and certainly there
958 * are no schemas other than pg_catalog).
960 if (IsBootstrapProcessingMode())
967 ScanKeyInit(&skey
[0],
968 Anum_pg_type_typname
,
969 BTEqualStrategyNumber
, F_NAMEEQ
,
970 CStringGetDatum(typ_name_or_oid
));
972 hdesc
= heap_open(TypeRelationId
, AccessShareLock
);
973 sysscan
= systable_beginscan(hdesc
, TypeNameNspIndexId
, true,
974 SnapshotNow
, 1, skey
);
976 if (HeapTupleIsValid(tuple
= systable_getnext(sysscan
)))
977 result
= HeapTupleGetOid(tuple
);
980 (errcode(ERRCODE_UNDEFINED_OBJECT
),
981 errmsg("type \"%s\" does not exist", typ_name_or_oid
)));
983 /* We assume there can be only one match */
985 systable_endscan(sysscan
);
986 heap_close(hdesc
, AccessShareLock
);
988 PG_RETURN_OID(result
);
992 * Normal case: invoke the full parser to deal with special cases such as
995 parseTypeString(typ_name_or_oid
, &result
, &typmod
);
997 PG_RETURN_OID(result
);
1001 * regtypeout - converts type OID to "typ_name"
1004 regtypeout(PG_FUNCTION_ARGS
)
1006 Oid typid
= PG_GETARG_OID(0);
1010 if (typid
== InvalidOid
)
1012 result
= pstrdup("-");
1013 PG_RETURN_CSTRING(result
);
1016 typetup
= SearchSysCache(TYPEOID
,
1017 ObjectIdGetDatum(typid
),
1020 if (HeapTupleIsValid(typetup
))
1022 Form_pg_type typeform
= (Form_pg_type
) GETSTRUCT(typetup
);
1025 * In bootstrap mode, skip the fancy namespace stuff and just return
1026 * the type name. (This path is only needed for debugging output
1029 if (IsBootstrapProcessingMode())
1031 char *typname
= NameStr(typeform
->typname
);
1033 result
= pstrdup(typname
);
1036 result
= format_type_be(typid
);
1038 ReleaseSysCache(typetup
);
1042 /* If OID doesn't match any pg_type entry, return it numerically */
1043 result
= (char *) palloc(NAMEDATALEN
);
1044 snprintf(result
, NAMEDATALEN
, "%u", typid
);
1047 PG_RETURN_CSTRING(result
);
1051 * regtyperecv - converts external binary format to regtype
1054 regtyperecv(PG_FUNCTION_ARGS
)
1056 /* Exactly the same as oidrecv, so share code */
1057 return oidrecv(fcinfo
);
1061 * regtypesend - converts regtype to binary format
1064 regtypesend(PG_FUNCTION_ARGS
)
1066 /* Exactly the same as oidsend, so share code */
1067 return oidsend(fcinfo
);
1072 * regconfigin - converts "tsconfigname" to tsconfig OID
1074 * We also accept a numeric OID, for symmetry with the output routine.
1076 * '-' signifies unknown (OID 0). In all other cases, the input must
1077 * match an existing pg_ts_config entry.
1079 * This function is not needed in bootstrap mode, so we don't worry about
1080 * making it work then.
1083 regconfigin(PG_FUNCTION_ARGS
)
1085 char *cfg_name_or_oid
= PG_GETARG_CSTRING(0);
1090 if (strcmp(cfg_name_or_oid
, "-") == 0)
1091 PG_RETURN_OID(InvalidOid
);
1094 if (cfg_name_or_oid
[0] >= '0' &&
1095 cfg_name_or_oid
[0] <= '9' &&
1096 strspn(cfg_name_or_oid
, "0123456789") == strlen(cfg_name_or_oid
))
1098 result
= DatumGetObjectId(DirectFunctionCall1(oidin
,
1099 CStringGetDatum(cfg_name_or_oid
)));
1100 PG_RETURN_OID(result
);
1104 * Normal case: parse the name into components and see if it matches any
1105 * pg_ts_config entries in the current search path.
1107 names
= stringToQualifiedNameList(cfg_name_or_oid
);
1109 result
= TSConfigGetCfgid(names
, false);
1111 PG_RETURN_OID(result
);
1115 * regconfigout - converts tsconfig OID to "tsconfigname"
1118 regconfigout(PG_FUNCTION_ARGS
)
1120 Oid cfgid
= PG_GETARG_OID(0);
1124 if (cfgid
== InvalidOid
)
1126 result
= pstrdup("-");
1127 PG_RETURN_CSTRING(result
);
1130 cfgtup
= SearchSysCache(TSCONFIGOID
,
1131 ObjectIdGetDatum(cfgid
),
1134 if (HeapTupleIsValid(cfgtup
))
1136 Form_pg_ts_config cfgform
= (Form_pg_ts_config
) GETSTRUCT(cfgtup
);
1137 char *cfgname
= NameStr(cfgform
->cfgname
);
1141 * Would this config be found by regconfigin? If not, qualify it.
1143 if (TSConfigIsVisible(cfgid
))
1146 nspname
= get_namespace_name(cfgform
->cfgnamespace
);
1148 result
= quote_qualified_identifier(nspname
, cfgname
);
1150 ReleaseSysCache(cfgtup
);
1154 /* If OID doesn't match any pg_ts_config row, return it numerically */
1155 result
= (char *) palloc(NAMEDATALEN
);
1156 snprintf(result
, NAMEDATALEN
, "%u", cfgid
);
1159 PG_RETURN_CSTRING(result
);
1163 * regconfigrecv - converts external binary format to regconfig
1166 regconfigrecv(PG_FUNCTION_ARGS
)
1168 /* Exactly the same as oidrecv, so share code */
1169 return oidrecv(fcinfo
);
1173 * regconfigsend - converts regconfig to binary format
1176 regconfigsend(PG_FUNCTION_ARGS
)
1178 /* Exactly the same as oidsend, so share code */
1179 return oidsend(fcinfo
);
1184 * regdictionaryin - converts "tsdictionaryname" to tsdictionary OID
1186 * We also accept a numeric OID, for symmetry with the output routine.
1188 * '-' signifies unknown (OID 0). In all other cases, the input must
1189 * match an existing pg_ts_dict entry.
1191 * This function is not needed in bootstrap mode, so we don't worry about
1192 * making it work then.
1195 regdictionaryin(PG_FUNCTION_ARGS
)
1197 char *dict_name_or_oid
= PG_GETARG_CSTRING(0);
1202 if (strcmp(dict_name_or_oid
, "-") == 0)
1203 PG_RETURN_OID(InvalidOid
);
1206 if (dict_name_or_oid
[0] >= '0' &&
1207 dict_name_or_oid
[0] <= '9' &&
1208 strspn(dict_name_or_oid
, "0123456789") == strlen(dict_name_or_oid
))
1210 result
= DatumGetObjectId(DirectFunctionCall1(oidin
,
1211 CStringGetDatum(dict_name_or_oid
)));
1212 PG_RETURN_OID(result
);
1216 * Normal case: parse the name into components and see if it matches any
1217 * pg_ts_dict entries in the current search path.
1219 names
= stringToQualifiedNameList(dict_name_or_oid
);
1221 result
= TSDictionaryGetDictid(names
, false);
1223 PG_RETURN_OID(result
);
1227 * regdictionaryout - converts tsdictionary OID to "tsdictionaryname"
1230 regdictionaryout(PG_FUNCTION_ARGS
)
1232 Oid dictid
= PG_GETARG_OID(0);
1236 if (dictid
== InvalidOid
)
1238 result
= pstrdup("-");
1239 PG_RETURN_CSTRING(result
);
1242 dicttup
= SearchSysCache(TSDICTOID
,
1243 ObjectIdGetDatum(dictid
),
1246 if (HeapTupleIsValid(dicttup
))
1248 Form_pg_ts_dict dictform
= (Form_pg_ts_dict
) GETSTRUCT(dicttup
);
1249 char *dictname
= NameStr(dictform
->dictname
);
1253 * Would this dictionary be found by regdictionaryin? If not, qualify
1256 if (TSDictionaryIsVisible(dictid
))
1259 nspname
= get_namespace_name(dictform
->dictnamespace
);
1261 result
= quote_qualified_identifier(nspname
, dictname
);
1263 ReleaseSysCache(dicttup
);
1267 /* If OID doesn't match any pg_ts_dict row, return it numerically */
1268 result
= (char *) palloc(NAMEDATALEN
);
1269 snprintf(result
, NAMEDATALEN
, "%u", dictid
);
1272 PG_RETURN_CSTRING(result
);
1276 * regdictionaryrecv - converts external binary format to regdictionary
1279 regdictionaryrecv(PG_FUNCTION_ARGS
)
1281 /* Exactly the same as oidrecv, so share code */
1282 return oidrecv(fcinfo
);
1286 * regdictionarysend - converts regdictionary to binary format
1289 regdictionarysend(PG_FUNCTION_ARGS
)
1291 /* Exactly the same as oidsend, so share code */
1292 return oidsend(fcinfo
);
1297 * text_regclass: convert text to regclass
1299 * This could be replaced by CoerceViaIO, except that we need to treat
1300 * text-to-regclass as an implicit cast to support legacy forms of nextval()
1301 * and related functions.
1304 text_regclass(PG_FUNCTION_ARGS
)
1306 text
*relname
= PG_GETARG_TEXT_P(0);
1310 rv
= makeRangeVarFromNameList(textToQualifiedNameList(relname
));
1311 result
= RangeVarGetRelid(rv
, false);
1313 PG_RETURN_OID(result
);
1318 * Given a C string, parse it into a qualified-name list.
1321 stringToQualifiedNameList(const char *string
)
1328 /* We need a modifiable copy of the input string. */
1329 rawname
= pstrdup(string
);
1331 if (!SplitIdentifierString(rawname
, '.', &namelist
))
1333 (errcode(ERRCODE_INVALID_NAME
),
1334 errmsg("invalid name syntax")));
1336 if (namelist
== NIL
)
1338 (errcode(ERRCODE_INVALID_NAME
),
1339 errmsg("invalid name syntax")));
1341 foreach(l
, namelist
)
1343 char *curname
= (char *) lfirst(l
);
1345 result
= lappend(result
, makeString(pstrdup(curname
)));
1349 list_free(namelist
);
1354 /*****************************************************************************
1355 * SUPPORT ROUTINES *
1356 *****************************************************************************/
1359 * Given a C string, parse it into a qualified function or operator name
1360 * followed by a parenthesized list of type names. Reduce the
1361 * type names to an array of OIDs (returned into *nargs and *argtypes;
1362 * the argtypes array should be of size FUNC_MAX_ARGS). The function or
1363 * operator name is returned to *names as a List of Strings.
1365 * If allowNone is TRUE, accept "NONE" and return it as InvalidOid (this is
1366 * for unary operators).
1369 parseNameAndArgTypes(const char *string
, bool allowNone
, List
**names
,
1370 int *nargs
, Oid
*argtypes
)
1382 /* We need a modifiable copy of the input string. */
1383 rawname
= pstrdup(string
);
1385 /* Scan to find the expected left paren; mustn't be quoted */
1387 for (ptr
= rawname
; *ptr
; ptr
++)
1390 in_quote
= !in_quote
;
1391 else if (*ptr
== '(' && !in_quote
)
1396 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION
),
1397 errmsg("expected a left parenthesis")));
1399 /* Separate the name and parse it into a list */
1401 *names
= stringToQualifiedNameList(rawname
);
1403 /* Check for the trailing right parenthesis and remove it */
1404 ptr2
= ptr
+ strlen(ptr
);
1405 while (--ptr2
> ptr
)
1407 if (!isspace((unsigned char) *ptr2
))
1412 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION
),
1413 errmsg("expected a right parenthesis")));
1417 /* Separate the remaining string into comma-separated type names */
1423 /* allow leading whitespace */
1424 while (isspace((unsigned char) *ptr
))
1428 /* End of string. Okay unless we had a comma before. */
1431 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION
),
1432 errmsg("expected a type name")));
1436 /* Find end of type name --- end of string or comma */
1437 /* ... but not a quoted or parenthesized comma */
1443 in_quote
= !in_quote
;
1444 else if (*ptr
== ',' && !in_quote
&& paren_count
== 0)
1461 if (in_quote
|| paren_count
!= 0)
1463 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION
),
1464 errmsg("improper type name")));
1475 Assert(*ptr
== '\0');
1477 /* Lop off trailing whitespace */
1478 while (--ptr2
>= typename
)
1480 if (!isspace((unsigned char) *ptr2
))
1485 if (allowNone
&& pg_strcasecmp(typename
, "none") == 0)
1487 /* Special case for NONE */
1488 typeid = InvalidOid
;
1493 /* Use full parser to resolve the type name */
1494 parseTypeString(typename
, &typeid, &typmod
);
1496 if (*nargs
>= FUNC_MAX_ARGS
)
1498 (errcode(ERRCODE_TOO_MANY_ARGUMENTS
),
1499 errmsg("too many arguments")));
1501 argtypes
[*nargs
] = typeid;