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