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

Generated by: LCOV version 1.14