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

Generated by: LCOV version 1.14