LCOV - differential code coverage report
Current view: top level - src/backend/utils/adt - regproc.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GBC GIC GNC CBC EUB ECB DUB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 76.6 % 625 479 18 30 87 11 29 259 118 73 83 305 23 71
Current Date: 2023-04-08 15:15:32 Functions: 63.6 % 66 42 24 39 3 17 39 7 3
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

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

Generated by: LCOV version v1.16-55-g56c0a2a