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

Generated by: LCOV version 1.14