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