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