LCOV - code coverage report
Current view: top level - src/backend/utils/adt - pseudotypes.c (source / functions) Hit Total Coverage
Test: PostgreSQL 16beta1 Lines: 17 76 22.4 %
Date: 2023-05-31 02:11:47 Functions: 8 62 12.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * pseudotypes.c
       4             :  *    Functions for the system pseudo-types.
       5             :  *
       6             :  * A pseudo-type isn't really a type and never has any operations, but
       7             :  * we do need to supply input and output functions to satisfy the links
       8             :  * in the pseudo-type's entry in pg_type.  In most cases the functions
       9             :  * just throw an error if invoked.  (XXX the error messages here cover
      10             :  * the most common case, but might be confusing in some contexts.  Can
      11             :  * we do better?)
      12             :  *
      13             :  *
      14             :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
      15             :  * Portions Copyright (c) 1994, Regents of the University of California
      16             :  *
      17             :  *
      18             :  * IDENTIFICATION
      19             :  *    src/backend/utils/adt/pseudotypes.c
      20             :  *
      21             :  *-------------------------------------------------------------------------
      22             :  */
      23             : #include "postgres.h"
      24             : 
      25             : #include "libpq/pqformat.h"
      26             : #include "utils/array.h"
      27             : #include "utils/builtins.h"
      28             : #include "utils/rangetypes.h"
      29             : #include "utils/multirangetypes.h"
      30             : 
      31             : 
      32             : /*
      33             :  * These macros generate input and output functions for a pseudo-type that
      34             :  * will reject all input and output attempts.  (But for some types, only
      35             :  * the input function need be dummy.)
      36             :  */
      37             : #define PSEUDOTYPE_DUMMY_INPUT_FUNC(typname) \
      38             : Datum \
      39             : typname##_in(PG_FUNCTION_ARGS) \
      40             : { \
      41             :     ereport(ERROR, \
      42             :             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), \
      43             :              errmsg("cannot accept a value of type %s", #typname))); \
      44             : \
      45             :     PG_RETURN_VOID();           /* keep compiler quiet */ \
      46             : } \
      47             : \
      48             : extern int no_such_variable
      49             : 
      50             : #define PSEUDOTYPE_DUMMY_IO_FUNCS(typname) \
      51             : PSEUDOTYPE_DUMMY_INPUT_FUNC(typname); \
      52             : \
      53             : Datum \
      54             : typname##_out(PG_FUNCTION_ARGS) \
      55             : { \
      56             :     ereport(ERROR, \
      57             :             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), \
      58             :              errmsg("cannot display a value of type %s", #typname))); \
      59             : \
      60             :     PG_RETURN_VOID();           /* keep compiler quiet */ \
      61             : } \
      62             : \
      63             : extern int no_such_variable
      64             : 
      65             : /*
      66             :  * Likewise for binary send/receive functions.  We don't bother with these
      67             :  * at all for many pseudotypes, but some have them.  (By convention, if
      68             :  * a type has a send function it should have a receive function, even if
      69             :  * that's only dummy.)
      70             :  */
      71             : #define PSEUDOTYPE_DUMMY_RECEIVE_FUNC(typname) \
      72             : Datum \
      73             : typname##_recv(PG_FUNCTION_ARGS) \
      74             : { \
      75             :     ereport(ERROR, \
      76             :             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), \
      77             :              errmsg("cannot accept a value of type %s", #typname))); \
      78             : \
      79             :     PG_RETURN_VOID();           /* keep compiler quiet */ \
      80             : } \
      81             : \
      82             : extern int no_such_variable
      83             : 
      84             : #define PSEUDOTYPE_DUMMY_BINARY_IO_FUNCS(typname) \
      85             : PSEUDOTYPE_DUMMY_RECEIVE_FUNC(typname); \
      86             : \
      87             : Datum \
      88             : typname##_send(PG_FUNCTION_ARGS) \
      89             : { \
      90             :     ereport(ERROR, \
      91             :             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), \
      92             :              errmsg("cannot display a value of type %s", #typname))); \
      93             : \
      94             :     PG_RETURN_VOID();           /* keep compiler quiet */ \
      95             : } \
      96             : \
      97             : extern int no_such_variable
      98             : 
      99             : 
     100             : /*
     101             :  * cstring
     102             :  *
     103             :  * cstring is marked as a pseudo-type because we don't want people using it
     104             :  * in tables.  But it's really a perfectly functional type, so provide
     105             :  * a full set of working I/O functions for it.  Among other things, this
     106             :  * allows manual invocation of datatype I/O functions, along the lines of
     107             :  * "SELECT foo_in('blah')" or "SELECT foo_out(some-foo-value)".
     108             :  */
     109             : Datum
     110          18 : cstring_in(PG_FUNCTION_ARGS)
     111             : {
     112          18 :     char       *str = PG_GETARG_CSTRING(0);
     113             : 
     114          18 :     PG_RETURN_CSTRING(pstrdup(str));
     115             : }
     116             : 
     117             : Datum
     118         246 : cstring_out(PG_FUNCTION_ARGS)
     119             : {
     120         246 :     char       *str = PG_GETARG_CSTRING(0);
     121             : 
     122         246 :     PG_RETURN_CSTRING(pstrdup(str));
     123             : }
     124             : 
     125             : Datum
     126           0 : cstring_recv(PG_FUNCTION_ARGS)
     127             : {
     128           0 :     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
     129             :     char       *str;
     130             :     int         nbytes;
     131             : 
     132           0 :     str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
     133           0 :     PG_RETURN_CSTRING(str);
     134             : }
     135             : 
     136             : Datum
     137           0 : cstring_send(PG_FUNCTION_ARGS)
     138             : {
     139           0 :     char       *str = PG_GETARG_CSTRING(0);
     140             :     StringInfoData buf;
     141             : 
     142           0 :     pq_begintypsend(&buf);
     143           0 :     pq_sendtext(&buf, str, strlen(str));
     144           0 :     PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
     145             : }
     146             : 
     147             : /*
     148             :  * anyarray
     149             :  *
     150             :  * We need to allow output of anyarray so that, e.g., pg_statistic columns
     151             :  * can be printed.  Input has to be disallowed, however.
     152             :  *
     153             :  * XXX anyarray_recv could actually be made to work, since the incoming
     154             :  * array data would contain the element type OID.  It seems unlikely that
     155             :  * it'd be sufficiently type-safe, though.
     156             :  */
     157           0 : PSEUDOTYPE_DUMMY_INPUT_FUNC(anyarray);
     158           0 : PSEUDOTYPE_DUMMY_RECEIVE_FUNC(anyarray);
     159             : 
     160             : Datum
     161          44 : anyarray_out(PG_FUNCTION_ARGS)
     162             : {
     163          44 :     return array_out(fcinfo);
     164             : }
     165             : 
     166             : Datum
     167           0 : anyarray_send(PG_FUNCTION_ARGS)
     168             : {
     169           0 :     return array_send(fcinfo);
     170             : }
     171             : 
     172             : /*
     173             :  * anycompatiblearray
     174             :  *
     175             :  * We may as well allow output, since we do for anyarray.
     176             :  */
     177           0 : PSEUDOTYPE_DUMMY_INPUT_FUNC(anycompatiblearray);
     178           0 : PSEUDOTYPE_DUMMY_RECEIVE_FUNC(anycompatiblearray);
     179             : 
     180             : Datum
     181           0 : anycompatiblearray_out(PG_FUNCTION_ARGS)
     182             : {
     183           0 :     return array_out(fcinfo);
     184             : }
     185             : 
     186             : Datum
     187           0 : anycompatiblearray_send(PG_FUNCTION_ARGS)
     188             : {
     189           0 :     return array_send(fcinfo);
     190             : }
     191             : 
     192             : /*
     193             :  * anyenum
     194             :  *
     195             :  * We may as well allow output, since enum_out will in fact work.
     196             :  */
     197           0 : PSEUDOTYPE_DUMMY_INPUT_FUNC(anyenum);
     198             : 
     199             : Datum
     200           0 : anyenum_out(PG_FUNCTION_ARGS)
     201             : {
     202           0 :     return enum_out(fcinfo);
     203             : }
     204             : 
     205             : /*
     206             :  * anyrange
     207             :  *
     208             :  * We may as well allow output, since range_out will in fact work.
     209             :  */
     210           6 : PSEUDOTYPE_DUMMY_INPUT_FUNC(anyrange);
     211             : 
     212             : Datum
     213          60 : anyrange_out(PG_FUNCTION_ARGS)
     214             : {
     215          60 :     return range_out(fcinfo);
     216             : }
     217             : 
     218             : /*
     219             :  * anycompatiblerange
     220             :  *
     221             :  * We may as well allow output, since range_out will in fact work.
     222             :  */
     223           0 : PSEUDOTYPE_DUMMY_INPUT_FUNC(anycompatiblerange);
     224             : 
     225             : Datum
     226           0 : anycompatiblerange_out(PG_FUNCTION_ARGS)
     227             : {
     228           0 :     return range_out(fcinfo);
     229             : }
     230             : 
     231             : /*
     232             :  * anymultirange
     233             :  *
     234             :  * We may as well allow output, since multirange_out will in fact work.
     235             :  */
     236           0 : PSEUDOTYPE_DUMMY_INPUT_FUNC(anymultirange);
     237             : 
     238             : Datum
     239           0 : anymultirange_out(PG_FUNCTION_ARGS)
     240             : {
     241           0 :     return multirange_out(fcinfo);
     242             : }
     243             : 
     244             : /*
     245             :  * anycompatiblemultirange
     246             :  *
     247             :  * We may as well allow output, since multirange_out will in fact work.
     248             :  */
     249           0 : PSEUDOTYPE_DUMMY_INPUT_FUNC(anycompatiblemultirange);
     250             : 
     251             : Datum
     252           0 : anycompatiblemultirange_out(PG_FUNCTION_ARGS)
     253             : {
     254           0 :     return multirange_out(fcinfo);
     255             : }
     256             : 
     257             : /*
     258             :  * void
     259             :  *
     260             :  * We support void_in so that PL functions can return VOID without any
     261             :  * special hack in the PL handler.  Whatever value the PL thinks it's
     262             :  * returning will just be ignored.  Conversely, void_out and void_send
     263             :  * are needed so that "SELECT function_returning_void(...)" works.
     264             :  */
     265             : Datum
     266          28 : void_in(PG_FUNCTION_ARGS)
     267             : {
     268          28 :     PG_RETURN_VOID();           /* you were expecting something different? */
     269             : }
     270             : 
     271             : Datum
     272       17852 : void_out(PG_FUNCTION_ARGS)
     273             : {
     274       17852 :     PG_RETURN_CSTRING(pstrdup(""));
     275             : }
     276             : 
     277             : Datum
     278           0 : void_recv(PG_FUNCTION_ARGS)
     279             : {
     280             :     /*
     281             :      * Note that since we consume no bytes, an attempt to send anything but an
     282             :      * empty string will result in an "invalid message format" error.
     283             :      */
     284           0 :     PG_RETURN_VOID();
     285             : }
     286             : 
     287             : Datum
     288           0 : void_send(PG_FUNCTION_ARGS)
     289             : {
     290             :     StringInfoData buf;
     291             : 
     292             :     /* send an empty string */
     293           0 :     pq_begintypsend(&buf);
     294           0 :     PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
     295             : }
     296             : 
     297             : /*
     298             :  * shell
     299             :  *
     300             :  * shell_in and shell_out are entered in pg_type for "shell" types
     301             :  * (those not yet filled in).  They should be unreachable, but we
     302             :  * set them up just in case some code path tries to do I/O without
     303             :  * having checked pg_type.typisdefined anywhere along the way.
     304             :  */
     305             : Datum
     306           0 : shell_in(PG_FUNCTION_ARGS)
     307             : {
     308           0 :     ereport(ERROR,
     309             :             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
     310             :              errmsg("cannot accept a value of a shell type")));
     311             : 
     312             :     PG_RETURN_VOID();           /* keep compiler quiet */
     313             : }
     314             : 
     315             : Datum
     316           0 : shell_out(PG_FUNCTION_ARGS)
     317             : {
     318           0 :     ereport(ERROR,
     319             :             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
     320             :              errmsg("cannot display a value of a shell type")));
     321             : 
     322             :     PG_RETURN_VOID();           /* keep compiler quiet */
     323             : }
     324             : 
     325             : 
     326             : /*
     327             :  * pg_node_tree
     328             :  *
     329             :  * pg_node_tree isn't really a pseudotype --- it's real enough to be a table
     330             :  * column --- but it presently has no operations of its own, and disallows
     331             :  * input too, so its I/O functions seem to fit here as much as anywhere.
     332             :  *
     333             :  * We must disallow input of pg_node_tree values because the SQL functions
     334             :  * that operate on the type are not secure against malformed input.
     335             :  * We do want to allow output, though.
     336             :  */
     337           0 : PSEUDOTYPE_DUMMY_INPUT_FUNC(pg_node_tree);
     338           0 : PSEUDOTYPE_DUMMY_RECEIVE_FUNC(pg_node_tree);
     339             : 
     340             : Datum
     341        6544 : pg_node_tree_out(PG_FUNCTION_ARGS)
     342             : {
     343        6544 :     return textout(fcinfo);
     344             : }
     345             : 
     346             : Datum
     347           0 : pg_node_tree_send(PG_FUNCTION_ARGS)
     348             : {
     349           0 :     return textsend(fcinfo);
     350             : }
     351             : 
     352             : /*
     353             :  * pg_ddl_command
     354             :  *
     355             :  * Like pg_node_tree, pg_ddl_command isn't really a pseudotype; it's here
     356             :  * for the same reasons as that one.
     357             :  *
     358             :  * We don't have any good way to output this type directly, so punt
     359             :  * for output as well as input.
     360             :  */
     361           0 : PSEUDOTYPE_DUMMY_IO_FUNCS(pg_ddl_command);
     362           0 : PSEUDOTYPE_DUMMY_BINARY_IO_FUNCS(pg_ddl_command);
     363             : 
     364             : 
     365             : /*
     366             :  * Dummy I/O functions for various other pseudotypes.
     367             :  */
     368           0 : PSEUDOTYPE_DUMMY_IO_FUNCS(any);
     369           0 : PSEUDOTYPE_DUMMY_IO_FUNCS(trigger);
     370           0 : PSEUDOTYPE_DUMMY_IO_FUNCS(event_trigger);
     371           0 : PSEUDOTYPE_DUMMY_IO_FUNCS(language_handler);
     372           0 : PSEUDOTYPE_DUMMY_IO_FUNCS(fdw_handler);
     373           0 : PSEUDOTYPE_DUMMY_IO_FUNCS(table_am_handler);
     374           0 : PSEUDOTYPE_DUMMY_IO_FUNCS(index_am_handler);
     375           0 : PSEUDOTYPE_DUMMY_IO_FUNCS(tsm_handler);
     376           0 : PSEUDOTYPE_DUMMY_IO_FUNCS(internal);
     377           0 : PSEUDOTYPE_DUMMY_IO_FUNCS(anyelement);
     378           0 : PSEUDOTYPE_DUMMY_IO_FUNCS(anynonarray);
     379           0 : PSEUDOTYPE_DUMMY_IO_FUNCS(anycompatible);
     380           0 : PSEUDOTYPE_DUMMY_IO_FUNCS(anycompatiblenonarray);

Generated by: LCOV version 1.14