LCOV - code coverage report
Current view: top level - src/backend/utils/adt - pseudotypes.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 25.0 % 76 19
Test Date: 2026-03-04 01:14:59 Functions: 14.5 % 62 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-2026, 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         2916 : cstring_in(PG_FUNCTION_ARGS)
     108              : {
     109         2916 :     char       *str = PG_GETARG_CSTRING(0);
     110              : 
     111         2916 :     PG_RETURN_CSTRING(pstrdup(str));
     112              : }
     113              : 
     114              : Datum
     115          138 : cstring_out(PG_FUNCTION_ARGS)
     116              : {
     117          138 :     char       *str = PG_GETARG_CSTRING(0);
     118              : 
     119          138 :     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         4534 : anyarray_out(PG_FUNCTION_ARGS)
     159              : {
     160         4534 :     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            3 : PSEUDOTYPE_DUMMY_INPUT_FUNC(anyrange);
     208              : 
     209              : Datum
     210          160 : anyrange_out(PG_FUNCTION_ARGS)
     211              : {
     212          160 :     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           42 : anymultirange_out(PG_FUNCTION_ARGS)
     237              : {
     238           42 :     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           14 : void_in(PG_FUNCTION_ARGS)
     264              : {
     265           14 :     PG_RETURN_VOID();           /* you were expecting something different? */
     266              : }
     267              : 
     268              : Datum
     269        11759 : void_out(PG_FUNCTION_ARGS)
     270              : {
     271        11759 :     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         7094 : pg_node_tree_out(PG_FUNCTION_ARGS)
     339              : {
     340         7094 :     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 2.0-1