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