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