LCOV - code coverage report
Current view: top level - src/backend/utils/adt - regproc.c (source / functions) Hit Total Coverage
Test: PostgreSQL 14devel Lines: 462 644 71.7 %
Date: 2021-01-26 01:06:44 Functions: 39 64 60.9 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13