LCOV - code coverage report
Current view: top level - src/backend/utils/adt - regproc.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 79.1 % 855 676
Test Date: 2026-01-26 10:56:24 Functions: 62.5 % 72 45
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 57.5 % 445 256

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

Generated by: LCOV version 2.3.2-1