LCOV - code coverage report
Current view: top level - src/test/modules/plsample - plsample.c (source / functions) Hit Total Coverage
Test: PostgreSQL 14devel Lines: 45 50 90.0 %
Date: 2020-10-28 18:07:10 Functions: 4 4 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * plsample.c
       4             :  *    Handler for the PL/Sample procedural language
       5             :  *
       6             :  * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
       7             :  * Portions Copyright (c) 1994, Regents of the University of California
       8             :  *
       9             :  *
      10             :  * IDENTIFICATION
      11             :  *      src/test/modules/plsample/plsample.c
      12             :  *
      13             :  *-------------------------------------------------------------------------
      14             :  */
      15             : 
      16             : #include "postgres.h"
      17             : 
      18             : #include "catalog/pg_proc.h"
      19             : #include "catalog/pg_type.h"
      20             : #include "commands/event_trigger.h"
      21             : #include "commands/trigger.h"
      22             : #include "funcapi.h"
      23             : #include "utils/builtins.h"
      24             : #include "utils/lsyscache.h"
      25             : #include "utils/syscache.h"
      26             : 
      27           2 : PG_MODULE_MAGIC;
      28             : 
      29           4 : PG_FUNCTION_INFO_V1(plsample_call_handler);
      30             : 
      31             : static Datum plsample_func_handler(PG_FUNCTION_ARGS);
      32             : 
      33             : /*
      34             :  * Handle function, procedure, and trigger calls.
      35             :  */
      36             : Datum
      37           4 : plsample_call_handler(PG_FUNCTION_ARGS)
      38             : {
      39           4 :     Datum       retval = (Datum) 0;
      40             : 
      41           4 :     PG_TRY();
      42             :     {
      43             :         /*
      44             :          * Determine if called as function or trigger and call appropriate
      45             :          * subhandler.
      46             :          */
      47           4 :         if (CALLED_AS_TRIGGER(fcinfo))
      48             :         {
      49             :             /*
      50             :              * This function has been called as a trigger function, where
      51             :              * (TriggerData *) fcinfo->context includes the information of the
      52             :              * context.
      53             :              */
      54             :         }
      55           4 :         else if (CALLED_AS_EVENT_TRIGGER(fcinfo))
      56             :         {
      57             :             /*
      58             :              * This function is called as an event trigger function, where
      59             :              * (EventTriggerData *) fcinfo->context includes the information
      60             :              * of the context.
      61             :              */
      62             :         }
      63             :         else
      64             :         {
      65             :             /* Regular function handler */
      66           4 :             retval = plsample_func_handler(fcinfo);
      67             :         }
      68             :     }
      69           0 :     PG_FINALLY();
      70             :     {
      71             :     }
      72           4 :     PG_END_TRY();
      73             : 
      74           4 :     return retval;
      75             : }
      76             : 
      77             : /*
      78             :  * plsample_func_handler
      79             :  *
      80             :  * Function called by the call handler for function execution.
      81             :  */
      82             : static Datum
      83           4 : plsample_func_handler(PG_FUNCTION_ARGS)
      84             : {
      85             :     HeapTuple   pl_tuple;
      86             :     Datum       ret;
      87             :     char       *source;
      88             :     bool        isnull;
      89             :     FmgrInfo   *arg_out_func;
      90             :     Form_pg_type type_struct;
      91             :     HeapTuple   type_tuple;
      92             :     Form_pg_proc pl_struct;
      93           4 :     volatile MemoryContext proc_cxt = NULL;
      94             :     Oid        *argtypes;
      95             :     char      **argnames;
      96             :     char       *argmodes;
      97             :     char       *proname;
      98             :     Form_pg_type pg_type_entry;
      99             :     Oid         result_typioparam;
     100             :     Oid         prorettype;
     101             :     FmgrInfo    result_in_func;
     102             :     int         numargs;
     103             : 
     104             :     /* Fetch the source text of the function. */
     105           4 :     pl_tuple = SearchSysCache(PROCOID,
     106           4 :                               ObjectIdGetDatum(fcinfo->flinfo->fn_oid), 0, 0, 0);
     107           4 :     if (!HeapTupleIsValid(pl_tuple))
     108           0 :         elog(ERROR, "cache lookup failed for function %u",
     109             :              fcinfo->flinfo->fn_oid);
     110             : 
     111             :     /*
     112             :      * Extract and print the source text of the function.  This can be used as
     113             :      * a base for the function validation and execution.
     114             :      */
     115           4 :     pl_struct = (Form_pg_proc) GETSTRUCT(pl_tuple);
     116           4 :     proname = pstrdup(NameStr(pl_struct->proname));
     117           4 :     ret = SysCacheGetAttr(PROCOID, pl_tuple, Anum_pg_proc_prosrc, &isnull);
     118           4 :     if (isnull)
     119           0 :         elog(ERROR, "could not find source text of function \"%s\"",
     120             :              proname);
     121           4 :     source = DatumGetCString(DirectFunctionCall1(textout, ret));
     122           4 :     ereport(NOTICE,
     123             :             (errmsg("source text of function \"%s\": %s",
     124             :                     proname, source)));
     125             : 
     126             :     /*
     127             :      * Allocate a context that will hold all the Postgres data for the
     128             :      * procedure.
     129             :      */
     130           4 :     proc_cxt = AllocSetContextCreate(TopMemoryContext,
     131             :                                      "PL/Sample function",
     132             :                                      ALLOCSET_SMALL_SIZES);
     133             : 
     134           4 :     arg_out_func = (FmgrInfo *) palloc0(fcinfo->nargs * sizeof(FmgrInfo));
     135           4 :     numargs = get_func_arg_info(pl_tuple, &argtypes, &argnames, &argmodes);
     136             : 
     137             :     /*
     138             :      * Iterate through all of the function arguments, printing each input
     139             :      * value.
     140             :      */
     141          12 :     for (int i = 0; i < numargs; i++)
     142             :     {
     143           8 :         Oid         argtype = pl_struct->proargtypes.values[i];
     144             :         char       *value;
     145             : 
     146           8 :         type_tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(argtype));
     147           8 :         if (!HeapTupleIsValid(type_tuple))
     148           0 :             elog(ERROR, "cache lookup failed for type %u", argtype);
     149             : 
     150           8 :         type_struct = (Form_pg_type) GETSTRUCT(type_tuple);
     151           8 :         fmgr_info_cxt(type_struct->typoutput, &(arg_out_func[i]), proc_cxt);
     152           8 :         ReleaseSysCache(type_tuple);
     153             : 
     154           8 :         value = OutputFunctionCall(&arg_out_func[i], fcinfo->args[i].value);
     155           8 :         ereport(NOTICE,
     156             :                 (errmsg("argument: %d; name: %s; value: %s",
     157             :                         i, argnames[i], value)));
     158             :     }
     159             : 
     160             :     /* Type of the result */
     161           4 :     prorettype = pl_struct->prorettype;
     162           4 :     ReleaseSysCache(pl_tuple);
     163             : 
     164             :     /*
     165             :      * Get the required information for input conversion of the return value.
     166             :      *
     167             :      * If the function uses VOID as result, it is better to return NULL.
     168             :      * Anyway, let's be honest.  This is just a template, so there is not much
     169             :      * we can do here.  This returns NULL except if the result type is text,
     170             :      * where the result is the source text of the function.
     171             :      */
     172           4 :     if (prorettype != TEXTOID)
     173           2 :         PG_RETURN_NULL();
     174             : 
     175           2 :     type_tuple = SearchSysCache1(TYPEOID,
     176             :                                  ObjectIdGetDatum(prorettype));
     177           2 :     if (!HeapTupleIsValid(type_tuple))
     178           0 :         elog(ERROR, "cache lookup failed for type %u", prorettype);
     179           2 :     pg_type_entry = (Form_pg_type) GETSTRUCT(type_tuple);
     180           2 :     result_typioparam = getTypeIOParam(type_tuple);
     181             : 
     182           2 :     fmgr_info_cxt(pg_type_entry->typinput, &result_in_func, proc_cxt);
     183           2 :     ReleaseSysCache(type_tuple);
     184             : 
     185           2 :     ret = InputFunctionCall(&result_in_func, source, result_typioparam, -1);
     186           2 :     PG_RETURN_DATUM(ret);
     187             : }

Generated by: LCOV version 1.13