/*------------------------------------------------------------------------- * * pseudotypes.c * Functions for the system pseudo-types. * * A pseudo-type isn't really a type and never has any operations, but * we do need to supply input and output functions to satisfy the links * in the pseudo-type's entry in pg_type. In most cases the functions * just throw an error if invoked. (XXX the error messages here cover * the most common case, but might be confusing in some contexts. Can * we do better?) * * * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION * src/backend/utils/adt/pseudotypes.c * *------------------------------------------------------------------------- */ #include "postgres.h" #include "libpq/pqformat.h" #include "utils/array.h" #include "utils/builtins.h" #include "utils/rangetypes.h" #include "utils/multirangetypes.h" /* * These macros generate input and output functions for a pseudo-type that * will reject all input and output attempts. (But for some types, only * the input function need be dummy.) */ #define PSEUDOTYPE_DUMMY_INPUT_FUNC(typname) \ Datum \ typname##_in(PG_FUNCTION_ARGS) \ { \ ereport(ERROR, \ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), \ errmsg("cannot accept a value of type %s", #typname))); \ \ PG_RETURN_VOID(); /* keep compiler quiet */ \ } \ \ extern int no_such_variable #define PSEUDOTYPE_DUMMY_IO_FUNCS(typname) \ PSEUDOTYPE_DUMMY_INPUT_FUNC(typname); \ \ Datum \ typname##_out(PG_FUNCTION_ARGS) \ { \ ereport(ERROR, \ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), \ errmsg("cannot display a value of type %s", #typname))); \ \ PG_RETURN_VOID(); /* keep compiler quiet */ \ } \ \ extern int no_such_variable /* * Likewise for binary send/receive functions. We don't bother with these * at all for many pseudotypes, but some have them. (By convention, if * a type has a send function it should have a receive function, even if * that's only dummy.) */ #define PSEUDOTYPE_DUMMY_RECEIVE_FUNC(typname) \ Datum \ typname##_recv(PG_FUNCTION_ARGS) \ { \ ereport(ERROR, \ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), \ errmsg("cannot accept a value of type %s", #typname))); \ \ PG_RETURN_VOID(); /* keep compiler quiet */ \ } \ \ extern int no_such_variable #define PSEUDOTYPE_DUMMY_BINARY_IO_FUNCS(typname) \ PSEUDOTYPE_DUMMY_RECEIVE_FUNC(typname); \ \ Datum \ typname##_send(PG_FUNCTION_ARGS) \ { \ ereport(ERROR, \ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), \ errmsg("cannot display a value of type %s", #typname))); \ \ PG_RETURN_VOID(); /* keep compiler quiet */ \ } \ \ extern int no_such_variable /* * cstring * * cstring is marked as a pseudo-type because we don't want people using it * in tables. But it's really a perfectly functional type, so provide * a full set of working I/O functions for it. Among other things, this * allows manual invocation of datatype I/O functions, along the lines of * "SELECT foo_in('blah')" or "SELECT foo_out(some-foo-value)". */ Datum cstring_in(PG_FUNCTION_ARGS) { char *str = PG_GETARG_CSTRING(0); PG_RETURN_CSTRING(pstrdup(str)); } Datum cstring_out(PG_FUNCTION_ARGS) { char *str = PG_GETARG_CSTRING(0); PG_RETURN_CSTRING(pstrdup(str)); } Datum cstring_recv(PG_FUNCTION_ARGS) { StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); char *str; int nbytes; str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes); PG_RETURN_CSTRING(str); } Datum cstring_send(PG_FUNCTION_ARGS) { char *str = PG_GETARG_CSTRING(0); StringInfoData buf; pq_begintypsend(&buf); pq_sendtext(&buf, str, strlen(str)); PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); } /* * anyarray * * We need to allow output of anyarray so that, e.g., pg_statistic columns * can be printed. Input has to be disallowed, however. * * XXX anyarray_recv could actually be made to work, since the incoming * array data would contain the element type OID. It seems unlikely that * it'd be sufficiently type-safe, though. */ PSEUDOTYPE_DUMMY_INPUT_FUNC(anyarray); PSEUDOTYPE_DUMMY_RECEIVE_FUNC(anyarray); Datum anyarray_out(PG_FUNCTION_ARGS) { return array_out(fcinfo); } Datum anyarray_send(PG_FUNCTION_ARGS) { return array_send(fcinfo); } /* * anycompatiblearray * * We may as well allow output, since we do for anyarray. */ PSEUDOTYPE_DUMMY_INPUT_FUNC(anycompatiblearray); PSEUDOTYPE_DUMMY_RECEIVE_FUNC(anycompatiblearray); Datum anycompatiblearray_out(PG_FUNCTION_ARGS) { return array_out(fcinfo); } Datum anycompatiblearray_send(PG_FUNCTION_ARGS) { return array_send(fcinfo); } /* * anyenum * * We may as well allow output, since enum_out will in fact work. */ PSEUDOTYPE_DUMMY_INPUT_FUNC(anyenum); Datum anyenum_out(PG_FUNCTION_ARGS) { return enum_out(fcinfo); } /* * anyrange * * We may as well allow output, since range_out will in fact work. */ PSEUDOTYPE_DUMMY_INPUT_FUNC(anyrange); Datum anyrange_out(PG_FUNCTION_ARGS) { return range_out(fcinfo); } /* * anycompatiblerange * * We may as well allow output, since range_out will in fact work. */ PSEUDOTYPE_DUMMY_INPUT_FUNC(anycompatiblerange); Datum anycompatiblerange_out(PG_FUNCTION_ARGS) { return range_out(fcinfo); } /* * anymultirange * * We may as well allow output, since multirange_out will in fact work. */ PSEUDOTYPE_DUMMY_INPUT_FUNC(anymultirange); Datum anymultirange_out(PG_FUNCTION_ARGS) { return multirange_out(fcinfo); } /* * anycompatiblemultirange * * We may as well allow output, since multirange_out will in fact work. */ PSEUDOTYPE_DUMMY_INPUT_FUNC(anycompatiblemultirange); Datum anycompatiblemultirange_out(PG_FUNCTION_ARGS) { return multirange_out(fcinfo); } /* * void * * We support void_in so that PL functions can return VOID without any * special hack in the PL handler. Whatever value the PL thinks it's * returning will just be ignored. Conversely, void_out and void_send * are needed so that "SELECT function_returning_void(...)" works. */ Datum void_in(PG_FUNCTION_ARGS) { PG_RETURN_VOID(); /* you were expecting something different? */ } Datum void_out(PG_FUNCTION_ARGS) { PG_RETURN_CSTRING(pstrdup("")); } Datum void_recv(PG_FUNCTION_ARGS) { /* * Note that since we consume no bytes, an attempt to send anything but an * empty string will result in an "invalid message format" error. */ PG_RETURN_VOID(); } Datum void_send(PG_FUNCTION_ARGS) { StringInfoData buf; /* send an empty string */ pq_begintypsend(&buf); PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); } /* * shell * * shell_in and shell_out are entered in pg_type for "shell" types * (those not yet filled in). They should be unreachable, but we * set them up just in case some code path tries to do I/O without * having checked pg_type.typisdefined anywhere along the way. */ Datum shell_in(PG_FUNCTION_ARGS) { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cannot accept a value of a shell type"))); PG_RETURN_VOID(); /* keep compiler quiet */ } Datum shell_out(PG_FUNCTION_ARGS) { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cannot display a value of a shell type"))); PG_RETURN_VOID(); /* keep compiler quiet */ } /* * pg_node_tree * * pg_node_tree isn't really a pseudotype --- it's real enough to be a table * column --- but it presently has no operations of its own, and disallows * input too, so its I/O functions seem to fit here as much as anywhere. * * We must disallow input of pg_node_tree values because the SQL functions * that operate on the type are not secure against malformed input. * We do want to allow output, though. */ PSEUDOTYPE_DUMMY_INPUT_FUNC(pg_node_tree); PSEUDOTYPE_DUMMY_RECEIVE_FUNC(pg_node_tree); Datum pg_node_tree_out(PG_FUNCTION_ARGS) { return textout(fcinfo); } Datum pg_node_tree_send(PG_FUNCTION_ARGS) { return textsend(fcinfo); } /* * pg_ddl_command * * Like pg_node_tree, pg_ddl_command isn't really a pseudotype; it's here * for the same reasons as that one. * * We don't have any good way to output this type directly, so punt * for output as well as input. */ PSEUDOTYPE_DUMMY_IO_FUNCS(pg_ddl_command); PSEUDOTYPE_DUMMY_BINARY_IO_FUNCS(pg_ddl_command); /* * Dummy I/O functions for various other pseudotypes. */ PSEUDOTYPE_DUMMY_IO_FUNCS(any); PSEUDOTYPE_DUMMY_IO_FUNCS(trigger); PSEUDOTYPE_DUMMY_IO_FUNCS(event_trigger); PSEUDOTYPE_DUMMY_IO_FUNCS(language_handler); PSEUDOTYPE_DUMMY_IO_FUNCS(fdw_handler); PSEUDOTYPE_DUMMY_IO_FUNCS(table_am_handler); PSEUDOTYPE_DUMMY_IO_FUNCS(index_am_handler); PSEUDOTYPE_DUMMY_IO_FUNCS(tsm_handler); PSEUDOTYPE_DUMMY_IO_FUNCS(internal); PSEUDOTYPE_DUMMY_IO_FUNCS(anyelement); PSEUDOTYPE_DUMMY_IO_FUNCS(anynonarray); PSEUDOTYPE_DUMMY_IO_FUNCS(anycompatible); PSEUDOTYPE_DUMMY_IO_FUNCS(anycompatiblenonarray);