LCOV - code coverage report
Current view: top level - src/backend/utils/adt - regproc.c (source / functions) Hit Total Coverage
Test: PostgreSQL 13beta1 Lines: 459 633 72.5 %
Date: 2020-06-03 08:06:29 Functions: 41 64 64.1 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13