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  * regtypeout - converts type OID to "typ_name"
1225  */
1226 Datum
1228 {
1229  Oid typid = PG_GETARG_OID(0);
1230  char *result;
1231  HeapTuple typetup;
1232 
1233  if (typid == InvalidOid)
1234  {
1235  result = pstrdup("-");
1236  PG_RETURN_CSTRING(result);
1237  }
1238 
1239  typetup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
1240 
1241  if (HeapTupleIsValid(typetup))
1242  {
1243  Form_pg_type typeform = (Form_pg_type) GETSTRUCT(typetup);
1244 
1245  /*
1246  * In bootstrap mode, skip the fancy namespace stuff and just return
1247  * the type name. (This path is only needed for debugging output
1248  * anyway.)
1249  */
1251  {
1252  char *typname = NameStr(typeform->typname);
1253 
1254  result = pstrdup(typname);
1255  }
1256  else
1257  result = format_type_be(typid);
1258 
1259  ReleaseSysCache(typetup);
1260  }
1261  else
1262  {
1263  /* If OID doesn't match any pg_type entry, return it numerically */
1264  result = (char *) palloc(NAMEDATALEN);
1265  snprintf(result, NAMEDATALEN, "%u", typid);
1266  }
1267 
1268  PG_RETURN_CSTRING(result);
1269 }
1270 
1271 /*
1272  * regtyperecv - converts external binary format to regtype
1273  */
1274 Datum
1276 {
1277  /* Exactly the same as oidrecv, so share code */
1278  return oidrecv(fcinfo);
1279 }
1280 
1281 /*
1282  * regtypesend - converts regtype to binary format
1283  */
1284 Datum
1286 {
1287  /* Exactly the same as oidsend, so share code */
1288  return oidsend(fcinfo);
1289 }
1290 
1291 
1292 /*
1293  * regconfigin - converts "tsconfigname" to tsconfig OID
1294  *
1295  * We also accept a numeric OID, for symmetry with the output routine.
1296  *
1297  * '-' signifies unknown (OID 0). In all other cases, the input must
1298  * match an existing pg_ts_config entry.
1299  */
1300 Datum
1302 {
1303  char *cfg_name_or_oid = PG_GETARG_CSTRING(0);
1304  Node *escontext = fcinfo->context;
1305  Oid result;
1306  List *names;
1307 
1308  /* Handle "-" or numeric OID */
1309  if (parseDashOrOid(cfg_name_or_oid, &result, escontext))
1310  PG_RETURN_OID(result);
1311 
1312  /* The rest of this wouldn't work in bootstrap mode */
1314  elog(ERROR, "regconfig values must be OIDs in bootstrap mode");
1315 
1316  /*
1317  * Normal case: parse the name into components and see if it matches any
1318  * pg_ts_config entries in the current search path.
1319  */
1320  names = stringToQualifiedNameList(cfg_name_or_oid, escontext);
1321  if (names == NIL)
1322  PG_RETURN_NULL();
1323 
1324  result = get_ts_config_oid(names, true);
1325 
1326  if (!OidIsValid(result))
1327  ereturn(escontext, (Datum) 0,
1328  (errcode(ERRCODE_UNDEFINED_OBJECT),
1329  errmsg("text search configuration \"%s\" does not exist",
1330  NameListToString(names))));
1331 
1332  PG_RETURN_OID(result);
1333 }
1334 
1335 /*
1336  * regconfigout - converts tsconfig OID to "tsconfigname"
1337  */
1338 Datum
1340 {
1341  Oid cfgid = PG_GETARG_OID(0);
1342  char *result;
1343  HeapTuple cfgtup;
1344 
1345  if (cfgid == InvalidOid)
1346  {
1347  result = pstrdup("-");
1348  PG_RETURN_CSTRING(result);
1349  }
1350 
1351  cfgtup = SearchSysCache1(TSCONFIGOID, ObjectIdGetDatum(cfgid));
1352 
1353  if (HeapTupleIsValid(cfgtup))
1354  {
1355  Form_pg_ts_config cfgform = (Form_pg_ts_config) GETSTRUCT(cfgtup);
1356  char *cfgname = NameStr(cfgform->cfgname);
1357  char *nspname;
1358 
1359  /*
1360  * Would this config be found by regconfigin? If not, qualify it.
1361  */
1362  if (TSConfigIsVisible(cfgid))
1363  nspname = NULL;
1364  else
1365  nspname = get_namespace_name(cfgform->cfgnamespace);
1366 
1367  result = quote_qualified_identifier(nspname, cfgname);
1368 
1369  ReleaseSysCache(cfgtup);
1370  }
1371  else
1372  {
1373  /* If OID doesn't match any pg_ts_config row, return it numerically */
1374  result = (char *) palloc(NAMEDATALEN);
1375  snprintf(result, NAMEDATALEN, "%u", cfgid);
1376  }
1377 
1378  PG_RETURN_CSTRING(result);
1379 }
1380 
1381 /*
1382  * regconfigrecv - converts external binary format to regconfig
1383  */
1384 Datum
1386 {
1387  /* Exactly the same as oidrecv, so share code */
1388  return oidrecv(fcinfo);
1389 }
1390 
1391 /*
1392  * regconfigsend - converts regconfig to binary format
1393  */
1394 Datum
1396 {
1397  /* Exactly the same as oidsend, so share code */
1398  return oidsend(fcinfo);
1399 }
1400 
1401 
1402 /*
1403  * regdictionaryin - converts "tsdictionaryname" to tsdictionary OID
1404  *
1405  * We also accept a numeric OID, for symmetry with the output routine.
1406  *
1407  * '-' signifies unknown (OID 0). In all other cases, the input must
1408  * match an existing pg_ts_dict entry.
1409  */
1410 Datum
1412 {
1413  char *dict_name_or_oid = PG_GETARG_CSTRING(0);
1414  Node *escontext = fcinfo->context;
1415  Oid result;
1416  List *names;
1417 
1418  /* Handle "-" or numeric OID */
1419  if (parseDashOrOid(dict_name_or_oid, &result, escontext))
1420  PG_RETURN_OID(result);
1421 
1422  /* The rest of this wouldn't work in bootstrap mode */
1424  elog(ERROR, "regdictionary values must be OIDs in bootstrap mode");
1425 
1426  /*
1427  * Normal case: parse the name into components and see if it matches any
1428  * pg_ts_dict entries in the current search path.
1429  */
1430  names = stringToQualifiedNameList(dict_name_or_oid, escontext);
1431  if (names == NIL)
1432  PG_RETURN_NULL();
1433 
1434  result = get_ts_dict_oid(names, true);
1435 
1436  if (!OidIsValid(result))
1437  ereturn(escontext, (Datum) 0,
1438  (errcode(ERRCODE_UNDEFINED_OBJECT),
1439  errmsg("text search dictionary \"%s\" does not exist",
1440  NameListToString(names))));
1441 
1442  PG_RETURN_OID(result);
1443 }
1444 
1445 /*
1446  * regdictionaryout - converts tsdictionary OID to "tsdictionaryname"
1447  */
1448 Datum
1450 {
1451  Oid dictid = PG_GETARG_OID(0);
1452  char *result;
1453  HeapTuple dicttup;
1454 
1455  if (dictid == InvalidOid)
1456  {
1457  result = pstrdup("-");
1458  PG_RETURN_CSTRING(result);
1459  }
1460 
1461  dicttup = SearchSysCache1(TSDICTOID, ObjectIdGetDatum(dictid));
1462 
1463  if (HeapTupleIsValid(dicttup))
1464  {
1465  Form_pg_ts_dict dictform = (Form_pg_ts_dict) GETSTRUCT(dicttup);
1466  char *dictname = NameStr(dictform->dictname);
1467  char *nspname;
1468 
1469  /*
1470  * Would this dictionary be found by regdictionaryin? If not, qualify
1471  * it.
1472  */
1473  if (TSDictionaryIsVisible(dictid))
1474  nspname = NULL;
1475  else
1476  nspname = get_namespace_name(dictform->dictnamespace);
1477 
1478  result = quote_qualified_identifier(nspname, dictname);
1479 
1480  ReleaseSysCache(dicttup);
1481  }
1482  else
1483  {
1484  /* If OID doesn't match any pg_ts_dict row, return it numerically */
1485  result = (char *) palloc(NAMEDATALEN);
1486  snprintf(result, NAMEDATALEN, "%u", dictid);
1487  }
1488 
1489  PG_RETURN_CSTRING(result);
1490 }
1491 
1492 /*
1493  * regdictionaryrecv - converts external binary format to regdictionary
1494  */
1495 Datum
1497 {
1498  /* Exactly the same as oidrecv, so share code */
1499  return oidrecv(fcinfo);
1500 }
1501 
1502 /*
1503  * regdictionarysend - converts regdictionary to binary format
1504  */
1505 Datum
1507 {
1508  /* Exactly the same as oidsend, so share code */
1509  return oidsend(fcinfo);
1510 }
1511 
1512 /*
1513  * regrolein - converts "rolename" to role OID
1514  *
1515  * We also accept a numeric OID, for symmetry with the output routine.
1516  *
1517  * '-' signifies unknown (OID 0). In all other cases, the input must
1518  * match an existing pg_authid entry.
1519  */
1520 Datum
1522 {
1523  char *role_name_or_oid = PG_GETARG_CSTRING(0);
1524  Node *escontext = fcinfo->context;
1525  Oid result;
1526  List *names;
1527 
1528  /* Handle "-" or numeric OID */
1529  if (parseDashOrOid(role_name_or_oid, &result, escontext))
1530  PG_RETURN_OID(result);
1531 
1532  /* The rest of this wouldn't work in bootstrap mode */
1534  elog(ERROR, "regrole values must be OIDs in bootstrap mode");
1535 
1536  /* Normal case: see if the name matches any pg_authid entry. */
1537  names = stringToQualifiedNameList(role_name_or_oid, escontext);
1538  if (names == NIL)
1539  PG_RETURN_NULL();
1540 
1541  if (list_length(names) != 1)
1542  ereturn(escontext, (Datum) 0,
1543  (errcode(ERRCODE_INVALID_NAME),
1544  errmsg("invalid name syntax")));
1545 
1546  result = get_role_oid(strVal(linitial(names)), true);
1547 
1548  if (!OidIsValid(result))
1549  ereturn(escontext, (Datum) 0,
1550  (errcode(ERRCODE_UNDEFINED_OBJECT),
1551  errmsg("role \"%s\" does not exist",
1552  strVal(linitial(names)))));
1553 
1554  PG_RETURN_OID(result);
1555 }
1556 
1557 /*
1558  * to_regrole - converts "rolename" to role OID
1559  *
1560  * If the name is not found, we return NULL.
1561  */
1562 Datum
1564 {
1565  char *role_name = text_to_cstring(PG_GETARG_TEXT_PP(0));
1566  Datum result;
1567  ErrorSaveContext escontext = {T_ErrorSaveContext};
1568 
1569  if (!DirectInputFunctionCallSafe(regrolein, role_name,
1570  InvalidOid, -1,
1571  (Node *) &escontext,
1572  &result))
1573  PG_RETURN_NULL();
1574  PG_RETURN_DATUM(result);
1575 }
1576 
1577 /*
1578  * regroleout - converts role OID to "role_name"
1579  */
1580 Datum
1582 {
1583  Oid roleoid = PG_GETARG_OID(0);
1584  char *result;
1585 
1586  if (roleoid == InvalidOid)
1587  {
1588  result = pstrdup("-");
1589  PG_RETURN_CSTRING(result);
1590  }
1591 
1592  result = GetUserNameFromId(roleoid, true);
1593 
1594  if (result)
1595  {
1596  /* pstrdup is not really necessary, but it avoids a compiler warning */
1597  result = pstrdup(quote_identifier(result));
1598  }
1599  else
1600  {
1601  /* If OID doesn't match any role, return it numerically */
1602  result = (char *) palloc(NAMEDATALEN);
1603  snprintf(result, NAMEDATALEN, "%u", roleoid);
1604  }
1605 
1606  PG_RETURN_CSTRING(result);
1607 }
1608 
1609 /*
1610  * regrolerecv - converts external binary format to regrole
1611  */
1612 Datum
1614 {
1615  /* Exactly the same as oidrecv, so share code */
1616  return oidrecv(fcinfo);
1617 }
1618 
1619 /*
1620  * regrolesend - converts regrole to binary format
1621  */
1622 Datum
1624 {
1625  /* Exactly the same as oidsend, so share code */
1626  return oidsend(fcinfo);
1627 }
1628 
1629 /*
1630  * regnamespacein - converts "nspname" to namespace OID
1631  *
1632  * We also accept a numeric OID, for symmetry with the output routine.
1633  *
1634  * '-' signifies unknown (OID 0). In all other cases, the input must
1635  * match an existing pg_namespace entry.
1636  */
1637 Datum
1639 {
1640  char *nsp_name_or_oid = PG_GETARG_CSTRING(0);
1641  Node *escontext = fcinfo->context;
1642  Oid result;
1643  List *names;
1644 
1645  /* Handle "-" or numeric OID */
1646  if (parseDashOrOid(nsp_name_or_oid, &result, escontext))
1647  PG_RETURN_OID(result);
1648 
1649  /* The rest of this wouldn't work in bootstrap mode */
1651  elog(ERROR, "regnamespace values must be OIDs in bootstrap mode");
1652 
1653  /* Normal case: see if the name matches any pg_namespace entry. */
1654  names = stringToQualifiedNameList(nsp_name_or_oid, escontext);
1655  if (names == NIL)
1656  PG_RETURN_NULL();
1657 
1658  if (list_length(names) != 1)
1659  ereturn(escontext, (Datum) 0,
1660  (errcode(ERRCODE_INVALID_NAME),
1661  errmsg("invalid name syntax")));
1662 
1663  result = get_namespace_oid(strVal(linitial(names)), true);
1664 
1665  if (!OidIsValid(result))
1666  ereturn(escontext, (Datum) 0,
1667  (errcode(ERRCODE_UNDEFINED_SCHEMA),
1668  errmsg("schema \"%s\" does not exist",
1669  strVal(linitial(names)))));
1670 
1671  PG_RETURN_OID(result);
1672 }
1673 
1674 /*
1675  * to_regnamespace - converts "nspname" to namespace OID
1676  *
1677  * If the name is not found, we return NULL.
1678  */
1679 Datum
1681 {
1682  char *nsp_name = text_to_cstring(PG_GETARG_TEXT_PP(0));
1683  Datum result;
1684  ErrorSaveContext escontext = {T_ErrorSaveContext};
1685 
1687  InvalidOid, -1,
1688  (Node *) &escontext,
1689  &result))
1690  PG_RETURN_NULL();
1691  PG_RETURN_DATUM(result);
1692 }
1693 
1694 /*
1695  * regnamespaceout - converts namespace OID to "nsp_name"
1696  */
1697 Datum
1699 {
1700  Oid nspid = PG_GETARG_OID(0);
1701  char *result;
1702 
1703  if (nspid == InvalidOid)
1704  {
1705  result = pstrdup("-");
1706  PG_RETURN_CSTRING(result);
1707  }
1708 
1709  result = get_namespace_name(nspid);
1710 
1711  if (result)
1712  {
1713  /* pstrdup is not really necessary, but it avoids a compiler warning */
1714  result = pstrdup(quote_identifier(result));
1715  }
1716  else
1717  {
1718  /* If OID doesn't match any namespace, return it numerically */
1719  result = (char *) palloc(NAMEDATALEN);
1720  snprintf(result, NAMEDATALEN, "%u", nspid);
1721  }
1722 
1723  PG_RETURN_CSTRING(result);
1724 }
1725 
1726 /*
1727  * regnamespacerecv - converts external binary format to regnamespace
1728  */
1729 Datum
1731 {
1732  /* Exactly the same as oidrecv, so share code */
1733  return oidrecv(fcinfo);
1734 }
1735 
1736 /*
1737  * regnamespacesend - converts regnamespace to binary format
1738  */
1739 Datum
1741 {
1742  /* Exactly the same as oidsend, so share code */
1743  return oidsend(fcinfo);
1744 }
1745 
1746 /*
1747  * text_regclass: convert text to regclass
1748  *
1749  * This could be replaced by CoerceViaIO, except that we need to treat
1750  * text-to-regclass as an implicit cast to support legacy forms of nextval()
1751  * and related functions.
1752  */
1753 Datum
1755 {
1757  Oid result;
1758  RangeVar *rv;
1759 
1761 
1762  /* We might not even have permissions on this relation; don't lock it. */
1763  result = RangeVarGetRelid(rv, NoLock, false);
1764 
1765  PG_RETURN_OID(result);
1766 }
1767 
1768 
1769 /*
1770  * Given a C string, parse it into a qualified-name list.
1771  *
1772  * If escontext is an ErrorSaveContext node, invalid input will be
1773  * reported there instead of being thrown, and we return NIL.
1774  * (NIL is not possible as a success return, since empty-input is an error.)
1775  */
1776 List *
1777 stringToQualifiedNameList(const char *string, Node *escontext)
1778 {
1779  char *rawname;
1780  List *result = NIL;
1781  List *namelist;
1782  ListCell *l;
1783 
1784  /* We need a modifiable copy of the input string. */
1785  rawname = pstrdup(string);
1786 
1787  if (!SplitIdentifierString(rawname, '.', &namelist))
1788  ereturn(escontext, NIL,
1789  (errcode(ERRCODE_INVALID_NAME),
1790  errmsg("invalid name syntax")));
1791 
1792  if (namelist == NIL)
1793  ereturn(escontext, NIL,
1794  (errcode(ERRCODE_INVALID_NAME),
1795  errmsg("invalid name syntax")));
1796 
1797  foreach(l, namelist)
1798  {
1799  char *curname = (char *) lfirst(l);
1800 
1801  result = lappend(result, makeString(pstrdup(curname)));
1802  }
1803 
1804  pfree(rawname);
1805  list_free(namelist);
1806 
1807  return result;
1808 }
1809 
1810 /*****************************************************************************
1811  * SUPPORT ROUTINES *
1812  *****************************************************************************/
1813 
1814 /*
1815  * Given a C string, see if it is all-digits (and not empty).
1816  * If so, convert directly to OID and return true.
1817  * If it is not all-digits, return false.
1818  *
1819  * If escontext is an ErrorSaveContext node, any error in oidin() will be
1820  * reported there instead of being thrown (but we still return true).
1821  */
1822 static bool
1823 parseNumericOid(char *string, Oid *result, Node *escontext)
1824 {
1825  if (string[0] >= '0' && string[0] <= '9' &&
1826  strspn(string, "0123456789") == strlen(string))
1827  {
1828  Datum oid_datum;
1829 
1830  /* We need not care here whether oidin() fails or not. */
1831  (void) DirectInputFunctionCallSafe(oidin, string,
1832  InvalidOid, -1,
1833  escontext,
1834  &oid_datum);
1835  *result = DatumGetObjectId(oid_datum);
1836  return true;
1837  }
1838 
1839  /* Prevent uninitialized-variable warnings from stupider compilers. */
1840  *result = InvalidOid;
1841  return false;
1842 }
1843 
1844 /*
1845  * As above, but also accept "-" as meaning 0 (InvalidOid).
1846  */
1847 static bool
1848 parseDashOrOid(char *string, Oid *result, Node *escontext)
1849 {
1850  /* '-' ? */
1851  if (strcmp(string, "-") == 0)
1852  {
1853  *result = InvalidOid;
1854  return true;
1855  }
1856 
1857  /* Numeric OID? */
1858  return parseNumericOid(string, result, escontext);
1859 }
1860 
1861 /*
1862  * Given a C string, parse it into a qualified function or operator name
1863  * followed by a parenthesized list of type names. Reduce the
1864  * type names to an array of OIDs (returned into *nargs and *argtypes;
1865  * the argtypes array should be of size FUNC_MAX_ARGS). The function or
1866  * operator name is returned to *names as a List of Strings.
1867  *
1868  * If allowNone is true, accept "NONE" and return it as InvalidOid (this is
1869  * for unary operators).
1870  *
1871  * Returns true on success, false on failure (the latter only possible
1872  * if escontext is an ErrorSaveContext node).
1873  */
1874 static bool
1875 parseNameAndArgTypes(const char *string, bool allowNone, List **names,
1876  int *nargs, Oid *argtypes,
1877  Node *escontext)
1878 {
1879  char *rawname;
1880  char *ptr;
1881  char *ptr2;
1882  char *typename;
1883  bool in_quote;
1884  bool had_comma;
1885  int paren_count;
1886  Oid typeid;
1887  int32 typmod;
1888 
1889  /* We need a modifiable copy of the input string. */
1890  rawname = pstrdup(string);
1891 
1892  /* Scan to find the expected left paren; mustn't be quoted */
1893  in_quote = false;
1894  for (ptr = rawname; *ptr; ptr++)
1895  {
1896  if (*ptr == '"')
1897  in_quote = !in_quote;
1898  else if (*ptr == '(' && !in_quote)
1899  break;
1900  }
1901  if (*ptr == '\0')
1902  ereturn(escontext, false,
1903  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1904  errmsg("expected a left parenthesis")));
1905 
1906  /* Separate the name and parse it into a list */
1907  *ptr++ = '\0';
1908  *names = stringToQualifiedNameList(rawname, escontext);
1909  if (*names == NIL)
1910  return false;
1911 
1912  /* Check for the trailing right parenthesis and remove it */
1913  ptr2 = ptr + strlen(ptr);
1914  while (--ptr2 > ptr)
1915  {
1916  if (!scanner_isspace(*ptr2))
1917  break;
1918  }
1919  if (*ptr2 != ')')
1920  ereturn(escontext, false,
1921  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1922  errmsg("expected a right parenthesis")));
1923 
1924  *ptr2 = '\0';
1925 
1926  /* Separate the remaining string into comma-separated type names */
1927  *nargs = 0;
1928  had_comma = false;
1929 
1930  for (;;)
1931  {
1932  /* allow leading whitespace */
1933  while (scanner_isspace(*ptr))
1934  ptr++;
1935  if (*ptr == '\0')
1936  {
1937  /* End of string. Okay unless we had a comma before. */
1938  if (had_comma)
1939  ereturn(escontext, false,
1940  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1941  errmsg("expected a type name")));
1942  break;
1943  }
1944  typename = ptr;
1945  /* Find end of type name --- end of string or comma */
1946  /* ... but not a quoted or parenthesized comma */
1947  in_quote = false;
1948  paren_count = 0;
1949  for (; *ptr; ptr++)
1950  {
1951  if (*ptr == '"')
1952  in_quote = !in_quote;
1953  else if (*ptr == ',' && !in_quote && paren_count == 0)
1954  break;
1955  else if (!in_quote)
1956  {
1957  switch (*ptr)
1958  {
1959  case '(':
1960  case '[':
1961  paren_count++;
1962  break;
1963  case ')':
1964  case ']':
1965  paren_count--;
1966  break;
1967  }
1968  }
1969  }
1970  if (in_quote || paren_count != 0)
1971  ereturn(escontext, false,
1972  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1973  errmsg("improper type name")));
1974 
1975  ptr2 = ptr;
1976  if (*ptr == ',')
1977  {
1978  had_comma = true;
1979  *ptr++ = '\0';
1980  }
1981  else
1982  {
1983  had_comma = false;
1984  Assert(*ptr == '\0');
1985  }
1986  /* Lop off trailing whitespace */
1987  while (--ptr2 >= typename)
1988  {
1989  if (!scanner_isspace(*ptr2))
1990  break;
1991  *ptr2 = '\0';
1992  }
1993 
1994  if (allowNone && pg_strcasecmp(typename, "none") == 0)
1995  {
1996  /* Special case for NONE */
1997  typeid = InvalidOid;
1998  typmod = -1;
1999  }
2000  else
2001  {
2002  /* Use full parser to resolve the type name */
2003  if (!parseTypeString(typename, &typeid, &typmod, escontext))
2004  return false;
2005  }
2006  if (*nargs >= FUNC_MAX_ARGS)
2007  ereturn(escontext, false,
2008  (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
2009  errmsg("too many arguments")));
2010 
2011  argtypes[*nargs] = typeid;
2012  (*nargs)++;
2013  }
2014 
2015  pfree(rawname);
2016 
2017  return true;
2018 }
Oid get_role_oid(const char *rolname, bool missing_ok)
Definition: acl.c:5352
#define NameStr(name)
Definition: c.h:733
uint16 bits16
Definition: c.h:501
signed int int32
Definition: c.h:481
regproc RegProcedure
Definition: c.h:637
#define OidIsValid(objectId)
Definition: c.h:762
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_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
Assert(fmt[strlen(fmt) - 1] !='\n')
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:3346
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3322
const char * GetDatabaseEncodingName(void)
Definition: mbutils.c:1267
char * pstrdup(const char *in)
Definition: mcxt.c:1683
void pfree(void *pointer)
Definition: mcxt.c:1508
void * palloc(Size size)
Definition: mcxt.c:1304
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:451
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:1875
Datum regtypesend(PG_FUNCTION_ARGS)
Definition: regproc.c:1285
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:1638
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:1698
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:1506
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:1275
char * format_procedure_qualified(Oid procedure_oid)
Definition: regproc.c:305
Datum regdictionaryrecv(PG_FUNCTION_ARGS)
Definition: regproc.c:1496
Datum regrolerecv(PG_FUNCTION_ARGS)
Definition: regproc.c:1613
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:1848
Datum to_regrole(PG_FUNCTION_ARGS)
Definition: regproc.c:1563
Datum regconfigrecv(PG_FUNCTION_ARGS)
Definition: regproc.c:1385
Datum regdictionaryout(PG_FUNCTION_ARGS)
Definition: regproc.c:1449
Datum regdictionaryin(PG_FUNCTION_ARGS)
Definition: regproc.c:1411
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:1395
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:1301
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:1339
Datum to_regtype(PG_FUNCTION_ARGS)
Definition: regproc.c:1209
Datum regroleout(PG_FUNCTION_ARGS)
Definition: regproc.c:1581
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:1823
Datum regoperrecv(PG_FUNCTION_ARGS)
Definition: regproc.c:613
Datum regnamespacesend(PG_FUNCTION_ARGS)
Definition: regproc.c:1740
Datum regprocedurein(PG_FUNCTION_ARGS)
Definition: regproc.c:224
Datum regrolein(PG_FUNCTION_ARGS)
Definition: regproc.c:1521
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:1623
List * stringToQualifiedNameList(const char *string, Node *escontext)
Definition: regproc.c:1777
Datum to_regnamespace(PG_FUNCTION_ARGS)
Definition: regproc.c:1680
void format_procedure_parts(Oid procedure_oid, List **objnames, List **objargs, bool missing_ok)
Definition: regproc.c:398
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:1227
Datum text_regclass(PG_FUNCTION_ARGS)
Definition: regproc.c:1754
Datum regprocedurerecv(PG_FUNCTION_ARGS)
Definition: regproc.c:452
Datum regnamespacerecv(PG_FUNCTION_ARGS)
Definition: regproc.c:1730
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:11987
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:12071
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:674
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:3398
char * text_to_cstring(const text *t)
Definition: varlena.c:217
bool SplitIdentifierString(char *rawstring, char separator, List **namelist)
Definition: varlena.c:3456