PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
regproc.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * regproc.c
4 * Functions for the built-in types regproc, regclass, regtype, etc.
5 *
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.
9 *
10 *
11 * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
12 * Portions Copyright (c) 1994, Regents of the University of California
13 *
14 *
15 * IDENTIFICATION
16 * src/backend/utils/adt/regproc.c
17 *
18 *-------------------------------------------------------------------------
19 */
20#include "postgres.h"
21
22#include <ctype.h>
23
24#include "access/htup_details.h"
25#include "catalog/namespace.h"
26#include "catalog/pg_class.h"
28#include "catalog/pg_operator.h"
29#include "catalog/pg_proc.h"
31#include "catalog/pg_ts_dict.h"
32#include "catalog/pg_type.h"
33#include "lib/stringinfo.h"
34#include "mb/pg_wchar.h"
35#include "miscadmin.h"
36#include "nodes/miscnodes.h"
37#include "parser/parse_type.h"
38#include "parser/scansup.h"
39#include "utils/acl.h"
40#include "utils/builtins.h"
41#include "utils/lsyscache.h"
42#include "utils/regproc.h"
43#include "utils/syscache.h"
44#include "utils/varlena.h"
45
46static bool parseNumericOid(char *string, Oid *result, Node *escontext);
47static bool parseDashOrOid(char *string, Oid *result, Node *escontext);
48static bool parseNameAndArgTypes(const char *string, bool allowNone,
49 List **names, int *nargs, Oid *argtypes,
50 Node *escontext);
51
52
53/*****************************************************************************
54 * USER I/O ROUTINES *
55 *****************************************************************************/
56
57/*
58 * regprocin - converts "proname" to proc OID
59 *
60 * We also accept a numeric OID, for symmetry with the output routine.
61 *
62 * '-' signifies unknown (OID 0). In all other cases, the input must
63 * match an existing pg_proc entry.
64 */
67{
68 char *pro_name_or_oid = PG_GETARG_CSTRING(0);
69 Node *escontext = fcinfo->context;
70 RegProcedure result;
71 List *names;
73
74 /* Handle "-" or numeric OID */
75 if (parseDashOrOid(pro_name_or_oid, &result, escontext))
76 PG_RETURN_OID(result);
77
78 /* Else it's a name, possibly schema-qualified */
79
80 /*
81 * We should never get here in bootstrap mode, as all references should
82 * have been resolved by genbki.pl.
83 */
85 elog(ERROR, "regproc values must be OIDs in bootstrap mode");
86
87 /*
88 * Normal case: parse the name into components and see if it matches any
89 * pg_proc entries in the current search path.
90 */
91 names = stringToQualifiedNameList(pro_name_or_oid, escontext);
92 if (names == NIL)
94
95 clist = FuncnameGetCandidates(names, -1, NIL, false, false, false, true);
96
97 if (clist == NULL)
98 ereturn(escontext, (Datum) 0,
99 (errcode(ERRCODE_UNDEFINED_FUNCTION),
100 errmsg("function \"%s\" does not exist", pro_name_or_oid)));
101 else if (clist->next != NULL)
102 ereturn(escontext, (Datum) 0,
103 (errcode(ERRCODE_AMBIGUOUS_FUNCTION),
104 errmsg("more than one function named \"%s\"",
105 pro_name_or_oid)));
106
107 result = clist->oid;
108
109 PG_RETURN_OID(result);
110}
111
112/*
113 * to_regproc - converts "proname" to proc OID
114 *
115 * If the name is not found, we return NULL.
116 */
117Datum
119{
120 char *pro_name = text_to_cstring(PG_GETARG_TEXT_PP(0));
121 Datum result;
122 ErrorSaveContext escontext = {T_ErrorSaveContext};
123
125 InvalidOid, -1,
126 (Node *) &escontext,
127 &result))
129 PG_RETURN_DATUM(result);
130}
131
132/*
133 * regprocout - converts proc OID to "pro_name"
134 */
135Datum
137{
138 RegProcedure proid = PG_GETARG_OID(0);
139 char *result;
140 HeapTuple proctup;
141
142 if (proid == InvalidOid)
143 {
144 result = pstrdup("-");
145 PG_RETURN_CSTRING(result);
146 }
147
148 proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(proid));
149
150 if (HeapTupleIsValid(proctup))
151 {
152 Form_pg_proc procform = (Form_pg_proc) GETSTRUCT(proctup);
153 char *proname = NameStr(procform->proname);
154
155 /*
156 * In bootstrap mode, skip the fancy namespace stuff and just return
157 * the proc name. (This path is only needed for debugging output
158 * anyway.)
159 */
161 result = pstrdup(proname);
162 else
163 {
164 char *nspname;
165 FuncCandidateList clist;
166
167 /*
168 * Would this proc be found (uniquely!) by regprocin? If not,
169 * qualify it.
170 */
172 -1, NIL, false, false, false, false);
173 if (clist != NULL && clist->next == NULL &&
174 clist->oid == proid)
175 nspname = NULL;
176 else
177 nspname = get_namespace_name(procform->pronamespace);
178
179 result = quote_qualified_identifier(nspname, proname);
180 }
181
182 ReleaseSysCache(proctup);
183 }
184 else
185 {
186 /* If OID doesn't match any pg_proc entry, return it numerically */
187 result = (char *) palloc(NAMEDATALEN);
188 snprintf(result, NAMEDATALEN, "%u", proid);
189 }
190
191 PG_RETURN_CSTRING(result);
192}
193
194/*
195 * regprocrecv - converts external binary format to regproc
196 */
197Datum
199{
200 /* Exactly the same as oidrecv, so share code */
201 return oidrecv(fcinfo);
202}
203
204/*
205 * regprocsend - converts regproc to binary format
206 */
207Datum
209{
210 /* Exactly the same as oidsend, so share code */
211 return oidsend(fcinfo);
212}
213
214
215/*
216 * regprocedurein - converts "proname(args)" to proc OID
217 *
218 * We also accept a numeric OID, for symmetry with the output routine.
219 *
220 * '-' signifies unknown (OID 0). In all other cases, the input must
221 * match an existing pg_proc entry.
222 */
223Datum
225{
226 char *pro_name_or_oid = PG_GETARG_CSTRING(0);
227 Node *escontext = fcinfo->context;
228 RegProcedure result;
229 List *names;
230 int nargs;
231 Oid argtypes[FUNC_MAX_ARGS];
232 FuncCandidateList clist;
233
234 /* Handle "-" or numeric OID */
235 if (parseDashOrOid(pro_name_or_oid, &result, escontext))
236 PG_RETURN_OID(result);
237
238 /* The rest of this wouldn't work in bootstrap mode */
240 elog(ERROR, "regprocedure values must be OIDs in bootstrap mode");
241
242 /*
243 * Else it's a name and arguments. Parse the name and arguments, look up
244 * potential matches in the current namespace search list, and scan to see
245 * which one exactly matches the given argument types. (There will not be
246 * more than one match.)
247 */
248 if (!parseNameAndArgTypes(pro_name_or_oid, false,
249 &names, &nargs, argtypes,
250 escontext))
252
253 clist = FuncnameGetCandidates(names, nargs, NIL, false, false,
254 false, true);
255
256 for (; clist; clist = clist->next)
257 {
258 if (memcmp(clist->args, argtypes, nargs * sizeof(Oid)) == 0)
259 break;
260 }
261
262 if (clist == NULL)
263 ereturn(escontext, (Datum) 0,
264 (errcode(ERRCODE_UNDEFINED_FUNCTION),
265 errmsg("function \"%s\" does not exist", pro_name_or_oid)));
266
267 result = clist->oid;
268
269 PG_RETURN_OID(result);
270}
271
272/*
273 * to_regprocedure - converts "proname(args)" to proc OID
274 *
275 * If the name is not found, we return NULL.
276 */
277Datum
279{
280 char *pro_name = text_to_cstring(PG_GETARG_TEXT_PP(0));
281 Datum result;
282 ErrorSaveContext escontext = {T_ErrorSaveContext};
283
285 InvalidOid, -1,
286 (Node *) &escontext,
287 &result))
289 PG_RETURN_DATUM(result);
290}
291
292/*
293 * format_procedure - converts proc OID to "pro_name(args)"
294 *
295 * This exports the useful functionality of regprocedureout for use
296 * in other backend modules. The result is a palloc'd string.
297 */
298char *
299format_procedure(Oid procedure_oid)
300{
301 return format_procedure_extended(procedure_oid, 0);
302}
303
304char *
306{
308}
309
310/*
311 * format_procedure_extended - converts procedure OID to "pro_name(args)"
312 *
313 * This exports the useful functionality of regprocedureout for use
314 * in other backend modules. The result is a palloc'd string, or NULL.
315 *
316 * Routine to produce regprocedure names; see format_procedure above.
317 *
318 * The following bits in 'flags' modify the behavior:
319 * - FORMAT_PROC_INVALID_AS_NULL
320 * if the procedure OID is invalid or unknown, return NULL instead
321 * of the numeric OID.
322 * - FORMAT_PROC_FORCE_QUALIFY
323 * always schema-qualify procedure names, regardless of search_path
324 */
325char *
327{
328 char *result;
329 HeapTuple proctup;
330
331 proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(procedure_oid));
332
333 if (HeapTupleIsValid(proctup))
334 {
335 Form_pg_proc procform = (Form_pg_proc) GETSTRUCT(proctup);
336 char *proname = NameStr(procform->proname);
337 int nargs = procform->pronargs;
338 int i;
339 char *nspname;
341
342 /* XXX no support here for bootstrap mode */
344
346
347 /*
348 * Would this proc be found (given the right args) by regprocedurein?
349 * If not, or if caller requests it, we need to qualify it.
350 */
351 if ((flags & FORMAT_PROC_FORCE_QUALIFY) == 0 &&
352 FunctionIsVisible(procedure_oid))
353 nspname = NULL;
354 else
355 nspname = get_namespace_name(procform->pronamespace);
356
357 appendStringInfo(&buf, "%s(",
359 for (i = 0; i < nargs; i++)
360 {
361 Oid thisargtype = procform->proargtypes.values[i];
362
363 if (i > 0)
366 (flags & FORMAT_PROC_FORCE_QUALIFY) != 0 ?
367 format_type_be_qualified(thisargtype) :
368 format_type_be(thisargtype));
369 }
371
372 result = buf.data;
373
374 ReleaseSysCache(proctup);
375 }
376 else if ((flags & FORMAT_PROC_INVALID_AS_NULL) != 0)
377 {
378 /* If object is undefined, return NULL as wanted by caller */
379 result = NULL;
380 }
381 else
382 {
383 /* If OID doesn't match any pg_proc entry, return it numerically */
384 result = (char *) palloc(NAMEDATALEN);
385 snprintf(result, NAMEDATALEN, "%u", procedure_oid);
386 }
387
388 return result;
389}
390
391/*
392 * Output an objname/objargs representation for the procedure with the
393 * given OID. If it doesn't exist, an error is thrown.
394 *
395 * This can be used to feed get_object_address.
396 */
397void
398format_procedure_parts(Oid procedure_oid, List **objnames, List **objargs,
399 bool missing_ok)
400{
401 HeapTuple proctup;
402 Form_pg_proc procform;
403 int nargs;
404 int i;
405
406 proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(procedure_oid));
407
408 if (!HeapTupleIsValid(proctup))
409 {
410 if (!missing_ok)
411 elog(ERROR, "cache lookup failed for procedure with OID %u", procedure_oid);
412 return;
413 }
414
415 procform = (Form_pg_proc) GETSTRUCT(proctup);
416 nargs = procform->pronargs;
417
418 *objnames = list_make2(get_namespace_name_or_temp(procform->pronamespace),
419 pstrdup(NameStr(procform->proname)));
420 *objargs = NIL;
421 for (i = 0; i < nargs; i++)
422 {
423 Oid thisargtype = procform->proargtypes.values[i];
424
425 *objargs = lappend(*objargs, format_type_be_qualified(thisargtype));
426 }
427
428 ReleaseSysCache(proctup);
429}
430
431/*
432 * regprocedureout - converts proc OID to "pro_name(args)"
433 */
434Datum
436{
437 RegProcedure proid = PG_GETARG_OID(0);
438 char *result;
439
440 if (proid == InvalidOid)
441 result = pstrdup("-");
442 else
443 result = format_procedure(proid);
444
445 PG_RETURN_CSTRING(result);
446}
447
448/*
449 * regprocedurerecv - converts external binary format to regprocedure
450 */
451Datum
453{
454 /* Exactly the same as oidrecv, so share code */
455 return oidrecv(fcinfo);
456}
457
458/*
459 * regproceduresend - converts regprocedure to binary format
460 */
461Datum
463{
464 /* Exactly the same as oidsend, so share code */
465 return oidsend(fcinfo);
466}
467
468
469/*
470 * regoperin - converts "oprname" to operator OID
471 *
472 * We also accept a numeric OID, for symmetry with the output routine.
473 *
474 * '0' signifies unknown (OID 0). In all other cases, the input must
475 * match an existing pg_operator entry.
476 */
477Datum
479{
480 char *opr_name_or_oid = PG_GETARG_CSTRING(0);
481 Node *escontext = fcinfo->context;
482 Oid result;
483 List *names;
484 FuncCandidateList clist;
485
486 /* Handle "0" or numeric OID */
487 if (parseNumericOid(opr_name_or_oid, &result, escontext))
488 PG_RETURN_OID(result);
489
490 /* Else it's a name, possibly schema-qualified */
491
492 /* The rest of this wouldn't work in bootstrap mode */
494 elog(ERROR, "regoper values must be OIDs in bootstrap mode");
495
496 /*
497 * Normal case: parse the name into components and see if it matches any
498 * pg_operator entries in the current search path.
499 */
500 names = stringToQualifiedNameList(opr_name_or_oid, escontext);
501 if (names == NIL)
503
504 clist = OpernameGetCandidates(names, '\0', true);
505
506 if (clist == NULL)
507 ereturn(escontext, (Datum) 0,
508 (errcode(ERRCODE_UNDEFINED_FUNCTION),
509 errmsg("operator does not exist: %s", opr_name_or_oid)));
510 else if (clist->next != NULL)
511 ereturn(escontext, (Datum) 0,
512 (errcode(ERRCODE_AMBIGUOUS_FUNCTION),
513 errmsg("more than one operator named %s",
514 opr_name_or_oid)));
515
516 result = clist->oid;
517
518 PG_RETURN_OID(result);
519}
520
521/*
522 * to_regoper - converts "oprname" to operator OID
523 *
524 * If the name is not found, we return NULL.
525 */
526Datum
528{
529 char *opr_name = text_to_cstring(PG_GETARG_TEXT_PP(0));
530 Datum result;
531 ErrorSaveContext escontext = {T_ErrorSaveContext};
532
534 InvalidOid, -1,
535 (Node *) &escontext,
536 &result))
538 PG_RETURN_DATUM(result);
539}
540
541/*
542 * regoperout - converts operator OID to "opr_name"
543 */
544Datum
546{
548 char *result;
549 HeapTuple opertup;
550
551 if (oprid == InvalidOid)
552 {
553 result = pstrdup("0");
554 PG_RETURN_CSTRING(result);
555 }
556
557 opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(oprid));
558
559 if (HeapTupleIsValid(opertup))
560 {
561 Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup);
562 char *oprname = NameStr(operform->oprname);
563
564 /*
565 * In bootstrap mode, skip the fancy namespace stuff and just return
566 * the oper name. (This path is only needed for debugging output
567 * anyway.)
568 */
570 result = pstrdup(oprname);
571 else
572 {
573 FuncCandidateList clist;
574
575 /*
576 * Would this oper be found (uniquely!) by regoperin? If not,
577 * qualify it.
578 */
580 '\0', false);
581 if (clist != NULL && clist->next == NULL &&
582 clist->oid == oprid)
583 result = pstrdup(oprname);
584 else
585 {
586 const char *nspname;
587
588 nspname = get_namespace_name(operform->oprnamespace);
589 nspname = quote_identifier(nspname);
590 result = (char *) palloc(strlen(nspname) + strlen(oprname) + 2);
591 sprintf(result, "%s.%s", nspname, oprname);
592 }
593 }
594
595 ReleaseSysCache(opertup);
596 }
597 else
598 {
599 /*
600 * If OID doesn't match any pg_operator entry, return it numerically
601 */
602 result = (char *) palloc(NAMEDATALEN);
603 snprintf(result, NAMEDATALEN, "%u", oprid);
604 }
605
606 PG_RETURN_CSTRING(result);
607}
608
609/*
610 * regoperrecv - converts external binary format to regoper
611 */
612Datum
614{
615 /* Exactly the same as oidrecv, so share code */
616 return oidrecv(fcinfo);
617}
618
619/*
620 * regopersend - converts regoper to binary format
621 */
622Datum
624{
625 /* Exactly the same as oidsend, so share code */
626 return oidsend(fcinfo);
627}
628
629
630/*
631 * regoperatorin - converts "oprname(args)" to operator OID
632 *
633 * We also accept a numeric OID, for symmetry with the output routine.
634 *
635 * '0' signifies unknown (OID 0). In all other cases, the input must
636 * match an existing pg_operator entry.
637 */
638Datum
640{
641 char *opr_name_or_oid = PG_GETARG_CSTRING(0);
642 Node *escontext = fcinfo->context;
643 Oid result;
644 List *names;
645 int nargs;
646 Oid argtypes[FUNC_MAX_ARGS];
647
648 /* Handle "0" or numeric OID */
649 if (parseNumericOid(opr_name_or_oid, &result, escontext))
650 PG_RETURN_OID(result);
651
652 /* The rest of this wouldn't work in bootstrap mode */
654 elog(ERROR, "regoperator values must be OIDs in bootstrap mode");
655
656 /*
657 * Else it's a name and arguments. Parse the name and arguments, look up
658 * potential matches in the current namespace search list, and scan to see
659 * which one exactly matches the given argument types. (There will not be
660 * more than one match.)
661 */
662 if (!parseNameAndArgTypes(opr_name_or_oid, true,
663 &names, &nargs, argtypes,
664 escontext))
666
667 if (nargs == 1)
668 ereturn(escontext, (Datum) 0,
669 (errcode(ERRCODE_UNDEFINED_PARAMETER),
670 errmsg("missing argument"),
671 errhint("Use NONE to denote the missing argument of a unary operator.")));
672 if (nargs != 2)
673 ereturn(escontext, (Datum) 0,
674 (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
675 errmsg("too many arguments"),
676 errhint("Provide two argument types for operator.")));
677
678 result = OpernameGetOprid(names, argtypes[0], argtypes[1]);
679
680 if (!OidIsValid(result))
681 ereturn(escontext, (Datum) 0,
682 (errcode(ERRCODE_UNDEFINED_FUNCTION),
683 errmsg("operator does not exist: %s", opr_name_or_oid)));
684
685 PG_RETURN_OID(result);
686}
687
688/*
689 * to_regoperator - converts "oprname(args)" to operator OID
690 *
691 * If the name is not found, we return NULL.
692 */
693Datum
695{
696 char *opr_name_or_oid = text_to_cstring(PG_GETARG_TEXT_PP(0));
697 Datum result;
698 ErrorSaveContext escontext = {T_ErrorSaveContext};
699
700 if (!DirectInputFunctionCallSafe(regoperatorin, opr_name_or_oid,
701 InvalidOid, -1,
702 (Node *) &escontext,
703 &result))
705 PG_RETURN_DATUM(result);
706}
707
708/*
709 * format_operator_extended - converts operator OID to "opr_name(args)"
710 *
711 * This exports the useful functionality of regoperatorout for use
712 * in other backend modules. The result is a palloc'd string, or NULL.
713 *
714 * The following bits in 'flags' modify the behavior:
715 * - FORMAT_OPERATOR_INVALID_AS_NULL
716 * if the operator OID is invalid or unknown, return NULL instead
717 * of the numeric OID.
718 * - FORMAT_OPERATOR_FORCE_QUALIFY
719 * always schema-qualify operator names, regardless of search_path
720 */
721char *
723{
724 char *result;
725 HeapTuple opertup;
726
727 opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operator_oid));
728
729 if (HeapTupleIsValid(opertup))
730 {
731 Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup);
732 char *oprname = NameStr(operform->oprname);
733 char *nspname;
735
736 /* XXX no support here for bootstrap mode */
738
740
741 /*
742 * Would this oper be found (given the right args) by regoperatorin?
743 * If not, or if caller explicitly requests it, we need to qualify it.
744 */
745 if ((flags & FORMAT_OPERATOR_FORCE_QUALIFY) != 0 ||
746 !OperatorIsVisible(operator_oid))
747 {
748 nspname = get_namespace_name(operform->oprnamespace);
749 appendStringInfo(&buf, "%s.",
750 quote_identifier(nspname));
751 }
752
753 appendStringInfo(&buf, "%s(", oprname);
754
755 if (operform->oprleft)
756 appendStringInfo(&buf, "%s,",
757 (flags & FORMAT_OPERATOR_FORCE_QUALIFY) != 0 ?
758 format_type_be_qualified(operform->oprleft) :
759 format_type_be(operform->oprleft));
760 else
761 appendStringInfoString(&buf, "NONE,");
762
763 if (operform->oprright)
764 appendStringInfo(&buf, "%s)",
765 (flags & FORMAT_OPERATOR_FORCE_QUALIFY) != 0 ?
766 format_type_be_qualified(operform->oprright) :
767 format_type_be(operform->oprright));
768 else
769 appendStringInfoString(&buf, "NONE)");
770
771 result = buf.data;
772
773 ReleaseSysCache(opertup);
774 }
775 else if ((flags & FORMAT_OPERATOR_INVALID_AS_NULL) != 0)
776 {
777 /* If object is undefined, return NULL as wanted by caller */
778 result = NULL;
779 }
780 else
781 {
782 /*
783 * If OID doesn't match any pg_operator entry, return it numerically
784 */
785 result = (char *) palloc(NAMEDATALEN);
786 snprintf(result, NAMEDATALEN, "%u", operator_oid);
787 }
788
789 return result;
790}
791
792char *
793format_operator(Oid operator_oid)
794{
795 return format_operator_extended(operator_oid, 0);
796}
797
798char *
800{
801 return format_operator_extended(operator_oid,
803}
804
805void
806format_operator_parts(Oid operator_oid, List **objnames, List **objargs,
807 bool missing_ok)
808{
809 HeapTuple opertup;
810 Form_pg_operator oprForm;
811
812 opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operator_oid));
813 if (!HeapTupleIsValid(opertup))
814 {
815 if (!missing_ok)
816 elog(ERROR, "cache lookup failed for operator with OID %u",
817 operator_oid);
818 return;
819 }
820
821 oprForm = (Form_pg_operator) GETSTRUCT(opertup);
822 *objnames = list_make2(get_namespace_name_or_temp(oprForm->oprnamespace),
823 pstrdup(NameStr(oprForm->oprname)));
824 *objargs = NIL;
825 if (oprForm->oprleft)
826 *objargs = lappend(*objargs,
827 format_type_be_qualified(oprForm->oprleft));
828 if (oprForm->oprright)
829 *objargs = lappend(*objargs,
830 format_type_be_qualified(oprForm->oprright));
831
832 ReleaseSysCache(opertup);
833}
834
835/*
836 * regoperatorout - converts operator OID to "opr_name(args)"
837 */
838Datum
840{
842 char *result;
843
844 if (oprid == InvalidOid)
845 result = pstrdup("0");
846 else
847 result = format_operator(oprid);
848
849 PG_RETURN_CSTRING(result);
850}
851
852/*
853 * regoperatorrecv - converts external binary format to regoperator
854 */
855Datum
857{
858 /* Exactly the same as oidrecv, so share code */
859 return oidrecv(fcinfo);
860}
861
862/*
863 * regoperatorsend - converts regoperator to binary format
864 */
865Datum
867{
868 /* Exactly the same as oidsend, so share code */
869 return oidsend(fcinfo);
870}
871
872
873/*
874 * regclassin - converts "classname" to class OID
875 *
876 * We also accept a numeric OID, for symmetry with the output routine.
877 *
878 * '-' signifies unknown (OID 0). In all other cases, the input must
879 * match an existing pg_class entry.
880 */
881Datum
883{
884 char *class_name_or_oid = PG_GETARG_CSTRING(0);
885 Node *escontext = fcinfo->context;
886 Oid result;
887 List *names;
888
889 /* Handle "-" or numeric OID */
890 if (parseDashOrOid(class_name_or_oid, &result, escontext))
891 PG_RETURN_OID(result);
892
893 /* Else it's a name, possibly schema-qualified */
894
895 /* The rest of this wouldn't work in bootstrap mode */
897 elog(ERROR, "regclass values must be OIDs in bootstrap mode");
898
899 /*
900 * Normal case: parse the name into components and see if it matches any
901 * pg_class entries in the current search path.
902 */
903 names = stringToQualifiedNameList(class_name_or_oid, escontext);
904 if (names == NIL)
906
907 /* We might not even have permissions on this relation; don't lock it. */
908 result = RangeVarGetRelid(makeRangeVarFromNameList(names), NoLock, true);
909
910 if (!OidIsValid(result))
911 ereturn(escontext, (Datum) 0,
913 errmsg("relation \"%s\" does not exist",
914 NameListToString(names))));
915
916 PG_RETURN_OID(result);
917}
918
919/*
920 * to_regclass - converts "classname" to class OID
921 *
922 * If the name is not found, we return NULL.
923 */
924Datum
926{
928 Datum result;
929 ErrorSaveContext escontext = {T_ErrorSaveContext};
930
932 InvalidOid, -1,
933 (Node *) &escontext,
934 &result))
936 PG_RETURN_DATUM(result);
937}
938
939/*
940 * regclassout - converts class OID to "class_name"
941 */
942Datum
944{
945 Oid classid = PG_GETARG_OID(0);
946 char *result;
947 HeapTuple classtup;
948
949 if (classid == InvalidOid)
950 {
951 result = pstrdup("-");
952 PG_RETURN_CSTRING(result);
953 }
954
955 classtup = SearchSysCache1(RELOID, ObjectIdGetDatum(classid));
956
957 if (HeapTupleIsValid(classtup))
958 {
959 Form_pg_class classform = (Form_pg_class) GETSTRUCT(classtup);
960 char *classname = NameStr(classform->relname);
961
962 /*
963 * In bootstrap mode, skip the fancy namespace stuff and just return
964 * the class name. (This path is only needed for debugging output
965 * anyway.)
966 */
968 result = pstrdup(classname);
969 else
970 {
971 char *nspname;
972
973 /*
974 * Would this class be found by regclassin? If not, qualify it.
975 */
976 if (RelationIsVisible(classid))
977 nspname = NULL;
978 else
979 nspname = get_namespace_name(classform->relnamespace);
980
981 result = quote_qualified_identifier(nspname, classname);
982 }
983
984 ReleaseSysCache(classtup);
985 }
986 else
987 {
988 /* If OID doesn't match any pg_class entry, return it numerically */
989 result = (char *) palloc(NAMEDATALEN);
990 snprintf(result, NAMEDATALEN, "%u", classid);
991 }
992
993 PG_RETURN_CSTRING(result);
994}
995
996/*
997 * regclassrecv - converts external binary format to regclass
998 */
999Datum
1001{
1002 /* Exactly the same as oidrecv, so share code */
1003 return oidrecv(fcinfo);
1004}
1005
1006/*
1007 * regclasssend - converts regclass to binary format
1008 */
1009Datum
1011{
1012 /* Exactly the same as oidsend, so share code */
1013 return oidsend(fcinfo);
1014}
1015
1016
1017/*
1018 * regcollationin - converts "collationname" to collation OID
1019 *
1020 * We also accept a numeric OID, for symmetry with the output routine.
1021 *
1022 * '-' signifies unknown (OID 0). In all other cases, the input must
1023 * match an existing pg_collation entry.
1024 */
1025Datum
1027{
1028 char *collation_name_or_oid = PG_GETARG_CSTRING(0);
1029 Node *escontext = fcinfo->context;
1030 Oid result;
1031 List *names;
1032
1033 /* Handle "-" or numeric OID */
1034 if (parseDashOrOid(collation_name_or_oid, &result, escontext))
1035 PG_RETURN_OID(result);
1036
1037 /* Else it's a name, possibly schema-qualified */
1038
1039 /* The rest of this wouldn't work in bootstrap mode */
1041 elog(ERROR, "regcollation values must be OIDs in bootstrap mode");
1042
1043 /*
1044 * Normal case: parse the name into components and see if it matches any
1045 * pg_collation entries in the current search path.
1046 */
1047 names = stringToQualifiedNameList(collation_name_or_oid, escontext);
1048 if (names == NIL)
1050
1051 result = get_collation_oid(names, true);
1052
1053 if (!OidIsValid(result))
1054 ereturn(escontext, (Datum) 0,
1055 (errcode(ERRCODE_UNDEFINED_OBJECT),
1056 errmsg("collation \"%s\" for encoding \"%s\" does not exist",
1058
1059 PG_RETURN_OID(result);
1060}
1061
1062/*
1063 * to_regcollation - converts "collationname" to collation OID
1064 *
1065 * If the name is not found, we return NULL.
1066 */
1067Datum
1069{
1070 char *collation_name = text_to_cstring(PG_GETARG_TEXT_PP(0));
1071 Datum result;
1072 ErrorSaveContext escontext = {T_ErrorSaveContext};
1073
1074 if (!DirectInputFunctionCallSafe(regcollationin, collation_name,
1075 InvalidOid, -1,
1076 (Node *) &escontext,
1077 &result))
1079 PG_RETURN_DATUM(result);
1080}
1081
1082/*
1083 * regcollationout - converts collation OID to "collation_name"
1084 */
1085Datum
1087{
1088 Oid collationid = PG_GETARG_OID(0);
1089 char *result;
1090 HeapTuple collationtup;
1091
1092 if (collationid == InvalidOid)
1093 {
1094 result = pstrdup("-");
1095 PG_RETURN_CSTRING(result);
1096 }
1097
1098 collationtup = SearchSysCache1(COLLOID, ObjectIdGetDatum(collationid));
1099
1100 if (HeapTupleIsValid(collationtup))
1101 {
1102 Form_pg_collation collationform = (Form_pg_collation) GETSTRUCT(collationtup);
1103 char *collationname = NameStr(collationform->collname);
1104
1105 /*
1106 * In bootstrap mode, skip the fancy namespace stuff and just return
1107 * the collation name. (This path is only needed for debugging output
1108 * anyway.)
1109 */
1111 result = pstrdup(collationname);
1112 else
1113 {
1114 char *nspname;
1115
1116 /*
1117 * Would this collation be found by regcollationin? If not,
1118 * qualify it.
1119 */
1120 if (CollationIsVisible(collationid))
1121 nspname = NULL;
1122 else
1123 nspname = get_namespace_name(collationform->collnamespace);
1124
1125 result = quote_qualified_identifier(nspname, collationname);
1126 }
1127
1128 ReleaseSysCache(collationtup);
1129 }
1130 else
1131 {
1132 /* If OID doesn't match any pg_collation entry, return it numerically */
1133 result = (char *) palloc(NAMEDATALEN);
1134 snprintf(result, NAMEDATALEN, "%u", collationid);
1135 }
1136
1137 PG_RETURN_CSTRING(result);
1138}
1139
1140/*
1141 * regcollationrecv - converts external binary format to regcollation
1142 */
1143Datum
1145{
1146 /* Exactly the same as oidrecv, so share code */
1147 return oidrecv(fcinfo);
1148}
1149
1150/*
1151 * regcollationsend - converts regcollation to binary format
1152 */
1153Datum
1155{
1156 /* Exactly the same as oidsend, so share code */
1157 return oidsend(fcinfo);
1158}
1159
1160
1161/*
1162 * regtypein - converts "typename" to type OID
1163 *
1164 * The type name can be specified using the full type syntax recognized by
1165 * the parser; for example, DOUBLE PRECISION and INTEGER[] will work and be
1166 * translated to the correct type names. (We ignore any typmod info
1167 * generated by the parser, however.)
1168 *
1169 * We also accept a numeric OID, for symmetry with the output routine,
1170 * and for possible use in bootstrap mode.
1171 *
1172 * '-' signifies unknown (OID 0). In all other cases, the input must
1173 * match an existing pg_type entry.
1174 */
1175Datum
1177{
1178 char *typ_name_or_oid = PG_GETARG_CSTRING(0);
1179 Node *escontext = fcinfo->context;
1180 Oid result;
1181 int32 typmod;
1182
1183 /* Handle "-" or numeric OID */
1184 if (parseDashOrOid(typ_name_or_oid, &result, escontext))
1185 PG_RETURN_OID(result);
1186
1187 /* Else it's a type name, possibly schema-qualified or decorated */
1188
1189 /* The rest of this wouldn't work in bootstrap mode */
1191 elog(ERROR, "regtype values must be OIDs in bootstrap mode");
1192
1193 /*
1194 * Normal case: invoke the full parser to deal with special cases such as
1195 * array syntax. We don't need to check for parseTypeString failure,
1196 * since we'll just return anyway.
1197 */
1198 (void) parseTypeString(typ_name_or_oid, &result, &typmod, escontext);
1199
1200 PG_RETURN_OID(result);
1201}
1202
1203/*
1204 * to_regtype - converts "typename" to type OID
1205 *
1206 * If the name is not found, we return NULL.
1207 */
1208Datum
1210{
1211 char *typ_name = text_to_cstring(PG_GETARG_TEXT_PP(0));
1212 Datum result;
1213 ErrorSaveContext escontext = {T_ErrorSaveContext};
1214
1216 InvalidOid, -1,
1217 (Node *) &escontext,
1218 &result))
1220 PG_RETURN_DATUM(result);
1221}
1222
1223/*
1224 * to_regtypemod - converts "typename" to type modifier
1225 *
1226 * If the name is not found, we return NULL.
1227 */
1228Datum
1230{
1231 char *typ_name = text_to_cstring(PG_GETARG_TEXT_PP(0));
1232 Oid typid;
1233 int32 typmod;
1234 ErrorSaveContext escontext = {T_ErrorSaveContext};
1235
1236 /* We rely on parseTypeString to parse the input. */
1237 if (!parseTypeString(typ_name, &typid, &typmod, (Node *) &escontext))
1239
1240 PG_RETURN_INT32(typmod);
1241}
1242
1243/*
1244 * regtypeout - converts type OID to "typ_name"
1245 */
1246Datum
1248{
1249 Oid typid = PG_GETARG_OID(0);
1250 char *result;
1251 HeapTuple typetup;
1252
1253 if (typid == InvalidOid)
1254 {
1255 result = pstrdup("-");
1256 PG_RETURN_CSTRING(result);
1257 }
1258
1259 typetup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
1260
1261 if (HeapTupleIsValid(typetup))
1262 {
1263 Form_pg_type typeform = (Form_pg_type) GETSTRUCT(typetup);
1264
1265 /*
1266 * In bootstrap mode, skip the fancy namespace stuff and just return
1267 * the type name. (This path is only needed for debugging output
1268 * anyway.)
1269 */
1271 {
1272 char *typname = NameStr(typeform->typname);
1273
1274 result = pstrdup(typname);
1275 }
1276 else
1277 result = format_type_be(typid);
1278
1279 ReleaseSysCache(typetup);
1280 }
1281 else
1282 {
1283 /* If OID doesn't match any pg_type entry, return it numerically */
1284 result = (char *) palloc(NAMEDATALEN);
1285 snprintf(result, NAMEDATALEN, "%u", typid);
1286 }
1287
1288 PG_RETURN_CSTRING(result);
1289}
1290
1291/*
1292 * regtyperecv - converts external binary format to regtype
1293 */
1294Datum
1296{
1297 /* Exactly the same as oidrecv, so share code */
1298 return oidrecv(fcinfo);
1299}
1300
1301/*
1302 * regtypesend - converts regtype to binary format
1303 */
1304Datum
1306{
1307 /* Exactly the same as oidsend, so share code */
1308 return oidsend(fcinfo);
1309}
1310
1311
1312/*
1313 * regconfigin - converts "tsconfigname" to tsconfig OID
1314 *
1315 * We also accept a numeric OID, for symmetry with the output routine.
1316 *
1317 * '-' signifies unknown (OID 0). In all other cases, the input must
1318 * match an existing pg_ts_config entry.
1319 */
1320Datum
1322{
1323 char *cfg_name_or_oid = PG_GETARG_CSTRING(0);
1324 Node *escontext = fcinfo->context;
1325 Oid result;
1326 List *names;
1327
1328 /* Handle "-" or numeric OID */
1329 if (parseDashOrOid(cfg_name_or_oid, &result, escontext))
1330 PG_RETURN_OID(result);
1331
1332 /* The rest of this wouldn't work in bootstrap mode */
1334 elog(ERROR, "regconfig values must be OIDs in bootstrap mode");
1335
1336 /*
1337 * Normal case: parse the name into components and see if it matches any
1338 * pg_ts_config entries in the current search path.
1339 */
1340 names = stringToQualifiedNameList(cfg_name_or_oid, escontext);
1341 if (names == NIL)
1343
1344 result = get_ts_config_oid(names, true);
1345
1346 if (!OidIsValid(result))
1347 ereturn(escontext, (Datum) 0,
1348 (errcode(ERRCODE_UNDEFINED_OBJECT),
1349 errmsg("text search configuration \"%s\" does not exist",
1350 NameListToString(names))));
1351
1352 PG_RETURN_OID(result);
1353}
1354
1355/*
1356 * regconfigout - converts tsconfig OID to "tsconfigname"
1357 */
1358Datum
1360{
1361 Oid cfgid = PG_GETARG_OID(0);
1362 char *result;
1363 HeapTuple cfgtup;
1364
1365 if (cfgid == InvalidOid)
1366 {
1367 result = pstrdup("-");
1368 PG_RETURN_CSTRING(result);
1369 }
1370
1371 cfgtup = SearchSysCache1(TSCONFIGOID, ObjectIdGetDatum(cfgid));
1372
1373 if (HeapTupleIsValid(cfgtup))
1374 {
1375 Form_pg_ts_config cfgform = (Form_pg_ts_config) GETSTRUCT(cfgtup);
1376 char *cfgname = NameStr(cfgform->cfgname);
1377 char *nspname;
1378
1379 /*
1380 * Would this config be found by regconfigin? If not, qualify it.
1381 */
1382 if (TSConfigIsVisible(cfgid))
1383 nspname = NULL;
1384 else
1385 nspname = get_namespace_name(cfgform->cfgnamespace);
1386
1387 result = quote_qualified_identifier(nspname, cfgname);
1388
1389 ReleaseSysCache(cfgtup);
1390 }
1391 else
1392 {
1393 /* If OID doesn't match any pg_ts_config row, return it numerically */
1394 result = (char *) palloc(NAMEDATALEN);
1395 snprintf(result, NAMEDATALEN, "%u", cfgid);
1396 }
1397
1398 PG_RETURN_CSTRING(result);
1399}
1400
1401/*
1402 * regconfigrecv - converts external binary format to regconfig
1403 */
1404Datum
1406{
1407 /* Exactly the same as oidrecv, so share code */
1408 return oidrecv(fcinfo);
1409}
1410
1411/*
1412 * regconfigsend - converts regconfig to binary format
1413 */
1414Datum
1416{
1417 /* Exactly the same as oidsend, so share code */
1418 return oidsend(fcinfo);
1419}
1420
1421
1422/*
1423 * regdictionaryin - converts "tsdictionaryname" to tsdictionary OID
1424 *
1425 * We also accept a numeric OID, for symmetry with the output routine.
1426 *
1427 * '-' signifies unknown (OID 0). In all other cases, the input must
1428 * match an existing pg_ts_dict entry.
1429 */
1430Datum
1432{
1433 char *dict_name_or_oid = PG_GETARG_CSTRING(0);
1434 Node *escontext = fcinfo->context;
1435 Oid result;
1436 List *names;
1437
1438 /* Handle "-" or numeric OID */
1439 if (parseDashOrOid(dict_name_or_oid, &result, escontext))
1440 PG_RETURN_OID(result);
1441
1442 /* The rest of this wouldn't work in bootstrap mode */
1444 elog(ERROR, "regdictionary values must be OIDs in bootstrap mode");
1445
1446 /*
1447 * Normal case: parse the name into components and see if it matches any
1448 * pg_ts_dict entries in the current search path.
1449 */
1450 names = stringToQualifiedNameList(dict_name_or_oid, escontext);
1451 if (names == NIL)
1453
1454 result = get_ts_dict_oid(names, true);
1455
1456 if (!OidIsValid(result))
1457 ereturn(escontext, (Datum) 0,
1458 (errcode(ERRCODE_UNDEFINED_OBJECT),
1459 errmsg("text search dictionary \"%s\" does not exist",
1460 NameListToString(names))));
1461
1462 PG_RETURN_OID(result);
1463}
1464
1465/*
1466 * regdictionaryout - converts tsdictionary OID to "tsdictionaryname"
1467 */
1468Datum
1470{
1471 Oid dictid = PG_GETARG_OID(0);
1472 char *result;
1473 HeapTuple dicttup;
1474
1475 if (dictid == InvalidOid)
1476 {
1477 result = pstrdup("-");
1478 PG_RETURN_CSTRING(result);
1479 }
1480
1481 dicttup = SearchSysCache1(TSDICTOID, ObjectIdGetDatum(dictid));
1482
1483 if (HeapTupleIsValid(dicttup))
1484 {
1485 Form_pg_ts_dict dictform = (Form_pg_ts_dict) GETSTRUCT(dicttup);
1486 char *dictname = NameStr(dictform->dictname);
1487 char *nspname;
1488
1489 /*
1490 * Would this dictionary be found by regdictionaryin? If not, qualify
1491 * it.
1492 */
1493 if (TSDictionaryIsVisible(dictid))
1494 nspname = NULL;
1495 else
1496 nspname = get_namespace_name(dictform->dictnamespace);
1497
1498 result = quote_qualified_identifier(nspname, dictname);
1499
1500 ReleaseSysCache(dicttup);
1501 }
1502 else
1503 {
1504 /* If OID doesn't match any pg_ts_dict row, return it numerically */
1505 result = (char *) palloc(NAMEDATALEN);
1506 snprintf(result, NAMEDATALEN, "%u", dictid);
1507 }
1508
1509 PG_RETURN_CSTRING(result);
1510}
1511
1512/*
1513 * regdictionaryrecv - converts external binary format to regdictionary
1514 */
1515Datum
1517{
1518 /* Exactly the same as oidrecv, so share code */
1519 return oidrecv(fcinfo);
1520}
1521
1522/*
1523 * regdictionarysend - converts regdictionary to binary format
1524 */
1525Datum
1527{
1528 /* Exactly the same as oidsend, so share code */
1529 return oidsend(fcinfo);
1530}
1531
1532/*
1533 * regrolein - converts "rolename" to role OID
1534 *
1535 * We also accept a numeric OID, for symmetry with the output routine.
1536 *
1537 * '-' signifies unknown (OID 0). In all other cases, the input must
1538 * match an existing pg_authid entry.
1539 */
1540Datum
1542{
1543 char *role_name_or_oid = PG_GETARG_CSTRING(0);
1544 Node *escontext = fcinfo->context;
1545 Oid result;
1546 List *names;
1547
1548 /* Handle "-" or numeric OID */
1549 if (parseDashOrOid(role_name_or_oid, &result, escontext))
1550 PG_RETURN_OID(result);
1551
1552 /* The rest of this wouldn't work in bootstrap mode */
1554 elog(ERROR, "regrole values must be OIDs in bootstrap mode");
1555
1556 /* Normal case: see if the name matches any pg_authid entry. */
1557 names = stringToQualifiedNameList(role_name_or_oid, escontext);
1558 if (names == NIL)
1560
1561 if (list_length(names) != 1)
1562 ereturn(escontext, (Datum) 0,
1563 (errcode(ERRCODE_INVALID_NAME),
1564 errmsg("invalid name syntax")));
1565
1566 result = get_role_oid(strVal(linitial(names)), true);
1567
1568 if (!OidIsValid(result))
1569 ereturn(escontext, (Datum) 0,
1570 (errcode(ERRCODE_UNDEFINED_OBJECT),
1571 errmsg("role \"%s\" does not exist",
1572 strVal(linitial(names)))));
1573
1574 PG_RETURN_OID(result);
1575}
1576
1577/*
1578 * to_regrole - converts "rolename" to role OID
1579 *
1580 * If the name is not found, we return NULL.
1581 */
1582Datum
1584{
1585 char *role_name = text_to_cstring(PG_GETARG_TEXT_PP(0));
1586 Datum result;
1587 ErrorSaveContext escontext = {T_ErrorSaveContext};
1588
1589 if (!DirectInputFunctionCallSafe(regrolein, role_name,
1590 InvalidOid, -1,
1591 (Node *) &escontext,
1592 &result))
1594 PG_RETURN_DATUM(result);
1595}
1596
1597/*
1598 * regroleout - converts role OID to "role_name"
1599 */
1600Datum
1602{
1603 Oid roleoid = PG_GETARG_OID(0);
1604 char *result;
1605
1606 if (roleoid == InvalidOid)
1607 {
1608 result = pstrdup("-");
1609 PG_RETURN_CSTRING(result);
1610 }
1611
1612 result = GetUserNameFromId(roleoid, true);
1613
1614 if (result)
1615 {
1616 /* pstrdup is not really necessary, but it avoids a compiler warning */
1617 result = pstrdup(quote_identifier(result));
1618 }
1619 else
1620 {
1621 /* If OID doesn't match any role, return it numerically */
1622 result = (char *) palloc(NAMEDATALEN);
1623 snprintf(result, NAMEDATALEN, "%u", roleoid);
1624 }
1625
1626 PG_RETURN_CSTRING(result);
1627}
1628
1629/*
1630 * regrolerecv - converts external binary format to regrole
1631 */
1632Datum
1634{
1635 /* Exactly the same as oidrecv, so share code */
1636 return oidrecv(fcinfo);
1637}
1638
1639/*
1640 * regrolesend - converts regrole to binary format
1641 */
1642Datum
1644{
1645 /* Exactly the same as oidsend, so share code */
1646 return oidsend(fcinfo);
1647}
1648
1649/*
1650 * regnamespacein - converts "nspname" to namespace OID
1651 *
1652 * We also accept a numeric OID, for symmetry with the output routine.
1653 *
1654 * '-' signifies unknown (OID 0). In all other cases, the input must
1655 * match an existing pg_namespace entry.
1656 */
1657Datum
1659{
1660 char *nsp_name_or_oid = PG_GETARG_CSTRING(0);
1661 Node *escontext = fcinfo->context;
1662 Oid result;
1663 List *names;
1664
1665 /* Handle "-" or numeric OID */
1666 if (parseDashOrOid(nsp_name_or_oid, &result, escontext))
1667 PG_RETURN_OID(result);
1668
1669 /* The rest of this wouldn't work in bootstrap mode */
1671 elog(ERROR, "regnamespace values must be OIDs in bootstrap mode");
1672
1673 /* Normal case: see if the name matches any pg_namespace entry. */
1674 names = stringToQualifiedNameList(nsp_name_or_oid, escontext);
1675 if (names == NIL)
1677
1678 if (list_length(names) != 1)
1679 ereturn(escontext, (Datum) 0,
1680 (errcode(ERRCODE_INVALID_NAME),
1681 errmsg("invalid name syntax")));
1682
1683 result = get_namespace_oid(strVal(linitial(names)), true);
1684
1685 if (!OidIsValid(result))
1686 ereturn(escontext, (Datum) 0,
1687 (errcode(ERRCODE_UNDEFINED_SCHEMA),
1688 errmsg("schema \"%s\" does not exist",
1689 strVal(linitial(names)))));
1690
1691 PG_RETURN_OID(result);
1692}
1693
1694/*
1695 * to_regnamespace - converts "nspname" to namespace OID
1696 *
1697 * If the name is not found, we return NULL.
1698 */
1699Datum
1701{
1702 char *nsp_name = text_to_cstring(PG_GETARG_TEXT_PP(0));
1703 Datum result;
1704 ErrorSaveContext escontext = {T_ErrorSaveContext};
1705
1707 InvalidOid, -1,
1708 (Node *) &escontext,
1709 &result))
1711 PG_RETURN_DATUM(result);
1712}
1713
1714/*
1715 * regnamespaceout - converts namespace OID to "nsp_name"
1716 */
1717Datum
1719{
1720 Oid nspid = PG_GETARG_OID(0);
1721 char *result;
1722
1723 if (nspid == InvalidOid)
1724 {
1725 result = pstrdup("-");
1726 PG_RETURN_CSTRING(result);
1727 }
1728
1729 result = get_namespace_name(nspid);
1730
1731 if (result)
1732 {
1733 /* pstrdup is not really necessary, but it avoids a compiler warning */
1734 result = pstrdup(quote_identifier(result));
1735 }
1736 else
1737 {
1738 /* If OID doesn't match any namespace, return it numerically */
1739 result = (char *) palloc(NAMEDATALEN);
1740 snprintf(result, NAMEDATALEN, "%u", nspid);
1741 }
1742
1743 PG_RETURN_CSTRING(result);
1744}
1745
1746/*
1747 * regnamespacerecv - converts external binary format to regnamespace
1748 */
1749Datum
1751{
1752 /* Exactly the same as oidrecv, so share code */
1753 return oidrecv(fcinfo);
1754}
1755
1756/*
1757 * regnamespacesend - converts regnamespace to binary format
1758 */
1759Datum
1761{
1762 /* Exactly the same as oidsend, so share code */
1763 return oidsend(fcinfo);
1764}
1765
1766/*
1767 * text_regclass: convert text to regclass
1768 *
1769 * This could be replaced by CoerceViaIO, except that we need to treat
1770 * text-to-regclass as an implicit cast to support legacy forms of nextval()
1771 * and related functions.
1772 */
1773Datum
1775{
1777 Oid result;
1778 RangeVar *rv;
1779
1781
1782 /* We might not even have permissions on this relation; don't lock it. */
1783 result = RangeVarGetRelid(rv, NoLock, false);
1784
1785 PG_RETURN_OID(result);
1786}
1787
1788
1789/*
1790 * Given a C string, parse it into a qualified-name list.
1791 *
1792 * If escontext is an ErrorSaveContext node, invalid input will be
1793 * reported there instead of being thrown, and we return NIL.
1794 * (NIL is not possible as a success return, since empty-input is an error.)
1795 */
1796List *
1797stringToQualifiedNameList(const char *string, Node *escontext)
1798{
1799 char *rawname;
1800 List *result = NIL;
1801 List *namelist;
1802 ListCell *l;
1803
1804 /* We need a modifiable copy of the input string. */
1805 rawname = pstrdup(string);
1806
1807 if (!SplitIdentifierString(rawname, '.', &namelist))
1808 ereturn(escontext, NIL,
1809 (errcode(ERRCODE_INVALID_NAME),
1810 errmsg("invalid name syntax")));
1811
1812 if (namelist == NIL)
1813 ereturn(escontext, NIL,
1814 (errcode(ERRCODE_INVALID_NAME),
1815 errmsg("invalid name syntax")));
1816
1817 foreach(l, namelist)
1818 {
1819 char *curname = (char *) lfirst(l);
1820
1821 result = lappend(result, makeString(pstrdup(curname)));
1822 }
1823
1824 pfree(rawname);
1825 list_free(namelist);
1826
1827 return result;
1828}
1829
1830/*****************************************************************************
1831 * SUPPORT ROUTINES *
1832 *****************************************************************************/
1833
1834/*
1835 * Given a C string, see if it is all-digits (and not empty).
1836 * If so, convert directly to OID and return true.
1837 * If it is not all-digits, return false.
1838 *
1839 * If escontext is an ErrorSaveContext node, any error in oidin() will be
1840 * reported there instead of being thrown (but we still return true).
1841 */
1842static bool
1843parseNumericOid(char *string, Oid *result, Node *escontext)
1844{
1845 if (string[0] >= '0' && string[0] <= '9' &&
1846 strspn(string, "0123456789") == strlen(string))
1847 {
1848 Datum oid_datum;
1849
1850 /* We need not care here whether oidin() fails or not. */
1851 (void) DirectInputFunctionCallSafe(oidin, string,
1852 InvalidOid, -1,
1853 escontext,
1854 &oid_datum);
1855 *result = DatumGetObjectId(oid_datum);
1856 return true;
1857 }
1858
1859 /* Prevent uninitialized-variable warnings from stupider compilers. */
1860 *result = InvalidOid;
1861 return false;
1862}
1863
1864/*
1865 * As above, but also accept "-" as meaning 0 (InvalidOid).
1866 */
1867static bool
1868parseDashOrOid(char *string, Oid *result, Node *escontext)
1869{
1870 /* '-' ? */
1871 if (strcmp(string, "-") == 0)
1872 {
1873 *result = InvalidOid;
1874 return true;
1875 }
1876
1877 /* Numeric OID? */
1878 return parseNumericOid(string, result, escontext);
1879}
1880
1881/*
1882 * Given a C string, parse it into a qualified function or operator name
1883 * followed by a parenthesized list of type names. Reduce the
1884 * type names to an array of OIDs (returned into *nargs and *argtypes;
1885 * the argtypes array should be of size FUNC_MAX_ARGS). The function or
1886 * operator name is returned to *names as a List of Strings.
1887 *
1888 * If allowNone is true, accept "NONE" and return it as InvalidOid (this is
1889 * for unary operators).
1890 *
1891 * Returns true on success, false on failure (the latter only possible
1892 * if escontext is an ErrorSaveContext node).
1893 */
1894static bool
1895parseNameAndArgTypes(const char *string, bool allowNone, List **names,
1896 int *nargs, Oid *argtypes,
1897 Node *escontext)
1898{
1899 char *rawname;
1900 char *ptr;
1901 char *ptr2;
1902 char *typename;
1903 bool in_quote;
1904 bool had_comma;
1905 int paren_count;
1906 Oid typeid;
1907 int32 typmod;
1908
1909 /* We need a modifiable copy of the input string. */
1910 rawname = pstrdup(string);
1911
1912 /* Scan to find the expected left paren; mustn't be quoted */
1913 in_quote = false;
1914 for (ptr = rawname; *ptr; ptr++)
1915 {
1916 if (*ptr == '"')
1917 in_quote = !in_quote;
1918 else if (*ptr == '(' && !in_quote)
1919 break;
1920 }
1921 if (*ptr == '\0')
1922 ereturn(escontext, false,
1923 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1924 errmsg("expected a left parenthesis")));
1925
1926 /* Separate the name and parse it into a list */
1927 *ptr++ = '\0';
1928 *names = stringToQualifiedNameList(rawname, escontext);
1929 if (*names == NIL)
1930 return false;
1931
1932 /* Check for the trailing right parenthesis and remove it */
1933 ptr2 = ptr + strlen(ptr);
1934 while (--ptr2 > ptr)
1935 {
1936 if (!scanner_isspace(*ptr2))
1937 break;
1938 }
1939 if (*ptr2 != ')')
1940 ereturn(escontext, false,
1941 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1942 errmsg("expected a right parenthesis")));
1943
1944 *ptr2 = '\0';
1945
1946 /* Separate the remaining string into comma-separated type names */
1947 *nargs = 0;
1948 had_comma = false;
1949
1950 for (;;)
1951 {
1952 /* allow leading whitespace */
1953 while (scanner_isspace(*ptr))
1954 ptr++;
1955 if (*ptr == '\0')
1956 {
1957 /* End of string. Okay unless we had a comma before. */
1958 if (had_comma)
1959 ereturn(escontext, false,
1960 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1961 errmsg("expected a type name")));
1962 break;
1963 }
1964 typename = ptr;
1965 /* Find end of type name --- end of string or comma */
1966 /* ... but not a quoted or parenthesized comma */
1967 in_quote = false;
1968 paren_count = 0;
1969 for (; *ptr; ptr++)
1970 {
1971 if (*ptr == '"')
1972 in_quote = !in_quote;
1973 else if (*ptr == ',' && !in_quote && paren_count == 0)
1974 break;
1975 else if (!in_quote)
1976 {
1977 switch (*ptr)
1978 {
1979 case '(':
1980 case '[':
1981 paren_count++;
1982 break;
1983 case ')':
1984 case ']':
1985 paren_count--;
1986 break;
1987 }
1988 }
1989 }
1990 if (in_quote || paren_count != 0)
1991 ereturn(escontext, false,
1992 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1993 errmsg("improper type name")));
1994
1995 ptr2 = ptr;
1996 if (*ptr == ',')
1997 {
1998 had_comma = true;
1999 *ptr++ = '\0';
2000 }
2001 else
2002 {
2003 had_comma = false;
2004 Assert(*ptr == '\0');
2005 }
2006 /* Lop off trailing whitespace */
2007 while (--ptr2 >= typename)
2008 {
2009 if (!scanner_isspace(*ptr2))
2010 break;
2011 *ptr2 = '\0';
2012 }
2013
2014 if (allowNone && pg_strcasecmp(typename, "none") == 0)
2015 {
2016 /* Special case for NONE */
2017 typeid = InvalidOid;
2018 typmod = -1;
2019 }
2020 else
2021 {
2022 /* Use full parser to resolve the type name */
2023 if (!parseTypeString(typename, &typeid, &typmod, escontext))
2024 return false;
2025 }
2026 if (*nargs >= FUNC_MAX_ARGS)
2027 ereturn(escontext, false,
2028 (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
2029 errmsg("too many arguments")));
2030
2031 argtypes[*nargs] = typeid;
2032 (*nargs)++;
2033 }
2034
2035 pfree(rawname);
2036
2037 return true;
2038}
Oid get_role_oid(const char *rolname, bool missing_ok)
Definition: acl.c:5554
#define NameStr(name)
Definition: c.h:700
uint16 bits16
Definition: c.h:493
#define Assert(condition)
Definition: c.h:812
regproc RegProcedure
Definition: c.h:604
int32_t int32
Definition: c.h:481
#define OidIsValid(objectId)
Definition: c.h:729
int nspid
int errhint(const char *fmt,...)
Definition: elog.c:1317
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ereturn(context, dummy_value,...)
Definition: elog.h:277
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
bool DirectInputFunctionCallSafe(PGFunction func, char *str, Oid typioparam, int32 typmod, fmNodePtr escontext, Datum *result)
Definition: fmgr.c:1640
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:362
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:277
#define PG_RETURN_NULL()
Definition: fmgr.h:345
#define PG_RETURN_INT32(x)
Definition: fmgr.h:354
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:353
#define PG_RETURN_OID(x)
Definition: fmgr.h:360
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
char * format_type_be_qualified(Oid type_oid)
Definition: format_type.c:353
char * format_type_be(Oid type_oid)
Definition: format_type.c:343
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
int i
Definition: isn.c:72
List * lappend(List *list, void *datum)
Definition: list.c:339
void list_free(List *list)
Definition: list.c:1546
#define NoLock
Definition: lockdefs.h:34
char * get_namespace_name_or_temp(Oid nspid)
Definition: lsyscache.c:3390
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3366
const char * GetDatabaseEncodingName(void)
Definition: mbutils.c:1267
char * pstrdup(const char *in)
Definition: mcxt.c:1696
void pfree(void *pointer)
Definition: mcxt.c:1521
void * palloc(Size size)
Definition: mcxt.c:1317
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:466
char * GetUserNameFromId(Oid roleid, bool noerr)
Definition: miscinit.c:1036
Oid OpernameGetOprid(List *names, Oid oprleft, Oid oprright)
Definition: namespace.c:1785
char * NameListToString(const List *names)
Definition: namespace.c:3594
bool CollationIsVisible(Oid collid)
Definition: namespace.c:2407
Oid get_collation_oid(List *collname, bool missing_ok)
Definition: namespace.c:3971
FuncCandidateList FuncnameGetCandidates(List *names, int nargs, List *argnames, bool expand_variadic, bool expand_defaults, bool include_out_arguments, bool missing_ok)
Definition: namespace.c:1192
Oid get_namespace_oid(const char *nspname, bool missing_ok)
Definition: namespace.c:3535
bool RelationIsVisible(Oid relid)
Definition: namespace.c:913
bool OperatorIsVisible(Oid oprid)
Definition: namespace.c:2049
bool FunctionIsVisible(Oid funcid)
Definition: namespace.c:1696
Oid get_ts_dict_oid(List *names, bool missing_ok)
Definition: namespace.c:2861
RangeVar * makeRangeVarFromNameList(const List *names)
Definition: namespace.c:3554
Oid get_ts_config_oid(List *names, bool missing_ok)
Definition: namespace.c:3152
FuncCandidateList OpernameGetCandidates(List *names, char oprkind, bool missing_schema_ok)
Definition: namespace.c:1888
bool TSConfigIsVisible(Oid cfgid)
Definition: namespace.c:3210
bool TSDictionaryIsVisible(Oid dictId)
Definition: namespace.c:2919
#define RangeVarGetRelid(relation, lockmode, missing_ok)
Definition: namespace.h:80
Datum oidrecv(PG_FUNCTION_ARGS)
Definition: oid.c:60
Datum oidin(PG_FUNCTION_ARGS)
Definition: oid.c:37
Datum oidsend(PG_FUNCTION_ARGS)
Definition: oid.c:71
Oid oprid(Operator op)
Definition: parse_oper.c:238
bool parseTypeString(const char *str, Oid *typeid_p, int32 *typmod_p, Node *escontext)
Definition: parse_type.c:785
NameData relname
Definition: pg_class.h:38
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
FormData_pg_collation * Form_pg_collation
Definition: pg_collation.h:58
#define NAMEDATALEN
#define FUNC_MAX_ARGS
#define lfirst(lc)
Definition: pg_list.h:172
static int list_length(const List *l)
Definition: pg_list.h:152
#define NIL
Definition: pg_list.h:68
#define list_make1(x1)
Definition: pg_list.h:212
#define linitial(l)
Definition: pg_list.h:178
#define list_make2(x1, x2)
Definition: pg_list.h:214
FormData_pg_operator * Form_pg_operator
Definition: pg_operator.h:83
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:136
NameData proname
Definition: pg_proc.h:35
static char * buf
Definition: pg_test_fsync.c:72
FormData_pg_ts_config * Form_pg_ts_config
Definition: pg_ts_config.h:48
FormData_pg_ts_dict * Form_pg_ts_dict
Definition: pg_ts_dict.h:52
FormData_pg_type * Form_pg_type
Definition: pg_type.h:261
NameData typname
Definition: pg_type.h:41
#define ERRCODE_UNDEFINED_TABLE
Definition: pgbench.c:78
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
#define sprintf
Definition: port.h:240
#define snprintf
Definition: port.h:238
uintptr_t Datum
Definition: postgres.h:64
static Oid DatumGetObjectId(Datum X)
Definition: postgres.h:242
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
static bool parseNameAndArgTypes(const char *string, bool allowNone, List **names, int *nargs, Oid *argtypes, Node *escontext)
Definition: regproc.c:1895
Datum regtypesend(PG_FUNCTION_ARGS)
Definition: regproc.c:1305
Datum regoperout(PG_FUNCTION_ARGS)
Definition: regproc.c:545
Datum regnamespacein(PG_FUNCTION_ARGS)
Definition: regproc.c:1658
Datum regtypein(PG_FUNCTION_ARGS)
Definition: regproc.c:1176
Datum regprocrecv(PG_FUNCTION_ARGS)
Definition: regproc.c:198
Datum to_regoperator(PG_FUNCTION_ARGS)
Definition: regproc.c:694
Datum regnamespaceout(PG_FUNCTION_ARGS)
Definition: regproc.c:1718
char * format_operator_qualified(Oid operator_oid)
Definition: regproc.c:799
Datum regoperatorsend(PG_FUNCTION_ARGS)
Definition: regproc.c:866
char * format_procedure_extended(Oid procedure_oid, bits16 flags)
Definition: regproc.c:326
Datum regoperin(PG_FUNCTION_ARGS)
Definition: regproc.c:478
Datum regoperatorrecv(PG_FUNCTION_ARGS)
Definition: regproc.c:856
Datum regproceduresend(PG_FUNCTION_ARGS)
Definition: regproc.c:462
Datum regdictionarysend(PG_FUNCTION_ARGS)
Definition: regproc.c:1526
Datum regprocout(PG_FUNCTION_ARGS)
Definition: regproc.c:136
Datum to_regoper(PG_FUNCTION_ARGS)
Definition: regproc.c:527
Datum to_regprocedure(PG_FUNCTION_ARGS)
Definition: regproc.c:278
char * format_procedure(Oid procedure_oid)
Definition: regproc.c:299
Datum regcollationrecv(PG_FUNCTION_ARGS)
Definition: regproc.c:1144
Datum regcollationin(PG_FUNCTION_ARGS)
Definition: regproc.c:1026
Datum regprocedureout(PG_FUNCTION_ARGS)
Definition: regproc.c:435
Datum regtyperecv(PG_FUNCTION_ARGS)
Definition: regproc.c:1295
Datum regdictionaryrecv(PG_FUNCTION_ARGS)
Definition: regproc.c:1516
Datum regrolerecv(PG_FUNCTION_ARGS)
Definition: regproc.c:1633
Datum regclassrecv(PG_FUNCTION_ARGS)
Definition: regproc.c:1000
static bool parseDashOrOid(char *string, Oid *result, Node *escontext)
Definition: regproc.c:1868
Datum to_regrole(PG_FUNCTION_ARGS)
Definition: regproc.c:1583
Datum regconfigrecv(PG_FUNCTION_ARGS)
Definition: regproc.c:1405
Datum regdictionaryout(PG_FUNCTION_ARGS)
Definition: regproc.c:1469
Datum regdictionaryin(PG_FUNCTION_ARGS)
Definition: regproc.c:1431
Datum regoperatorout(PG_FUNCTION_ARGS)
Definition: regproc.c:839
Datum regcollationout(PG_FUNCTION_ARGS)
Definition: regproc.c:1086
Datum regprocsend(PG_FUNCTION_ARGS)
Definition: regproc.c:208
Datum regoperatorin(PG_FUNCTION_ARGS)
Definition: regproc.c:639
Datum regconfigsend(PG_FUNCTION_ARGS)
Definition: regproc.c:1415
Datum regclassin(PG_FUNCTION_ARGS)
Definition: regproc.c:882
Datum regconfigin(PG_FUNCTION_ARGS)
Definition: regproc.c:1321
char * format_operator_extended(Oid operator_oid, bits16 flags)
Definition: regproc.c:722
List * stringToQualifiedNameList(const char *string, Node *escontext)
Definition: regproc.c:1797
void format_operator_parts(Oid operator_oid, List **objnames, List **objargs, bool missing_ok)
Definition: regproc.c:806
Datum to_regcollation(PG_FUNCTION_ARGS)
Definition: regproc.c:1068
Datum regconfigout(PG_FUNCTION_ARGS)
Definition: regproc.c:1359
Datum to_regtype(PG_FUNCTION_ARGS)
Definition: regproc.c:1209
Datum regroleout(PG_FUNCTION_ARGS)
Definition: regproc.c:1601
Datum to_regclass(PG_FUNCTION_ARGS)
Definition: regproc.c:925
Datum regopersend(PG_FUNCTION_ARGS)
Definition: regproc.c:623
static bool parseNumericOid(char *string, Oid *result, Node *escontext)
Definition: regproc.c:1843
Datum regoperrecv(PG_FUNCTION_ARGS)
Definition: regproc.c:613
Datum regnamespacesend(PG_FUNCTION_ARGS)
Definition: regproc.c:1760
Datum regprocedurein(PG_FUNCTION_ARGS)
Definition: regproc.c:224
Datum regrolein(PG_FUNCTION_ARGS)
Definition: regproc.c:1541
Datum regcollationsend(PG_FUNCTION_ARGS)
Definition: regproc.c:1154
Datum to_regproc(PG_FUNCTION_ARGS)
Definition: regproc.c:118
Datum regprocin(PG_FUNCTION_ARGS)
Definition: regproc.c:66
Datum regrolesend(PG_FUNCTION_ARGS)
Definition: regproc.c:1643
char * format_procedure_qualified(Oid procedure_oid)
Definition: regproc.c:305
Datum to_regnamespace(PG_FUNCTION_ARGS)
Definition: regproc.c:1700
void format_procedure_parts(Oid procedure_oid, List **objnames, List **objargs, bool missing_ok)
Definition: regproc.c:398
Datum to_regtypemod(PG_FUNCTION_ARGS)
Definition: regproc.c:1229
Datum regclasssend(PG_FUNCTION_ARGS)
Definition: regproc.c:1010
Datum regtypeout(PG_FUNCTION_ARGS)
Definition: regproc.c:1247
char * format_operator(Oid operator_oid)
Definition: regproc.c:793
Datum text_regclass(PG_FUNCTION_ARGS)
Definition: regproc.c:1774
Datum regprocedurerecv(PG_FUNCTION_ARGS)
Definition: regproc.c:452
Datum regnamespacerecv(PG_FUNCTION_ARGS)
Definition: regproc.c:1750
Datum regclassout(PG_FUNCTION_ARGS)
Definition: regproc.c:943
#define FORMAT_OPERATOR_INVALID_AS_NULL
Definition: regproc.h:24
#define FORMAT_OPERATOR_FORCE_QUALIFY
Definition: regproc.h:25
#define FORMAT_PROC_FORCE_QUALIFY
Definition: regproc.h:20
#define FORMAT_PROC_INVALID_AS_NULL
Definition: regproc.h:19
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:12954
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:12870
bool scanner_isspace(char ch)
Definition: scansup.c:117
const char * class_name
Definition: selinux.c:32
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:94
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:179
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:191
void initStringInfo(StringInfo str)
Definition: stringinfo.c:56
Definition: pg_list.h:54
Definition: nodes.h:129
struct _FuncCandidateList * next
Definition: namespace.h:31
Oid args[FLEXIBLE_ARRAY_MEMBER]
Definition: namespace.h:39
Definition: c.h:641
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:269
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:221
String * makeString(char *str)
Definition: value.c:63
#define strVal(v)
Definition: value.h:82
bool SplitIdentifierString(char *rawstring, char separator, List **namelist)
Definition: varlena.c:3432
char * text_to_cstring(const text *t)
Definition: varlena.c:217
List * textToQualifiedNameList(text *textval)
Definition: varlena.c:3374