Commit 87c9c257 authored by Tom Lane's avatar Tom Lane

Rearrange pseudotypes.c to get rid of duplicative code.

Commit a5954de1 replaced a lot of manually-coded stub I/O routines
with code generated by macros.  That was a good idea but it didn't
go far enough, because there were still manually-coded stub input
routines for types that had live output routines.  Refactor the
macro so that we can generate just a stub input routine at need.

Also create similar macros to generate stub binary I/O routines,
since we have some of those now.  The only stub functions that remain
hand-coded are shell_in() and shell_out(), which need to be separate
because they use different error messages.

While here, rearrange the commentary to discuss each type not each
function.  This provides a better way to explain the *why* of which
types need which support, rather than just duplicatively annotating
the functions.

Discussion: https://postgr.es/m/24137.1584139352@sss.pgh.pa.us
parent 4dbcb3f8
...@@ -29,9 +29,81 @@ ...@@ -29,9 +29,81 @@
/* /*
* cstring_in - input routine for pseudo-type CSTRING. * 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
* *
* We might as well allow this to support constructs like "foo_in('blah')". * 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 Datum
cstring_in(PG_FUNCTION_ARGS) cstring_in(PG_FUNCTION_ARGS)
...@@ -41,12 +113,6 @@ cstring_in(PG_FUNCTION_ARGS) ...@@ -41,12 +113,6 @@ cstring_in(PG_FUNCTION_ARGS)
PG_RETURN_CSTRING(pstrdup(str)); PG_RETURN_CSTRING(pstrdup(str));
} }
/*
* cstring_out - output routine for pseudo-type CSTRING.
*
* We allow this mainly so that "SELECT some_output_function(...)" does
* what the user will expect.
*/
Datum Datum
cstring_out(PG_FUNCTION_ARGS) cstring_out(PG_FUNCTION_ARGS)
{ {
...@@ -55,9 +121,6 @@ cstring_out(PG_FUNCTION_ARGS) ...@@ -55,9 +121,6 @@ cstring_out(PG_FUNCTION_ARGS)
PG_RETURN_CSTRING(pstrdup(str)); PG_RETURN_CSTRING(pstrdup(str));
} }
/*
* cstring_recv - binary input routine for pseudo-type CSTRING.
*/
Datum Datum
cstring_recv(PG_FUNCTION_ARGS) cstring_recv(PG_FUNCTION_ARGS)
{ {
...@@ -69,9 +132,6 @@ cstring_recv(PG_FUNCTION_ARGS) ...@@ -69,9 +132,6 @@ cstring_recv(PG_FUNCTION_ARGS)
PG_RETURN_CSTRING(str); PG_RETURN_CSTRING(str);
} }
/*
* cstring_send - binary output routine for pseudo-type CSTRING.
*/
Datum Datum
cstring_send(PG_FUNCTION_ARGS) cstring_send(PG_FUNCTION_ARGS)
{ {
...@@ -84,76 +144,37 @@ cstring_send(PG_FUNCTION_ARGS) ...@@ -84,76 +144,37 @@ cstring_send(PG_FUNCTION_ARGS)
} }
/* /*
* anyarray_in - input routine for pseudo-type ANYARRAY. * anyarray
*/ *
Datum * We need to allow output of anyarray so that, e.g., pg_statistic columns
anyarray_in(PG_FUNCTION_ARGS) * can be printed. Input has to be disallowed, however.
{
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot accept a value of type %s", "anyarray")));
PG_RETURN_VOID(); /* keep compiler quiet */
}
/*
* anyarray_out - output routine for pseudo-type ANYARRAY.
* *
* We may as well allow this, since array_out will in fact work. * 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 Datum
anyarray_out(PG_FUNCTION_ARGS) anyarray_out(PG_FUNCTION_ARGS)
{ {
return array_out(fcinfo); return array_out(fcinfo);
} }
/*
* anyarray_recv - binary input routine for pseudo-type ANYARRAY.
*
* XXX this could actually be made to work, since the incoming array
* data will contain the element type OID. Need to think through
* type-safety issues before allowing it, however.
*/
Datum
anyarray_recv(PG_FUNCTION_ARGS)
{
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot accept a value of type %s", "anyarray")));
PG_RETURN_VOID(); /* keep compiler quiet */
}
/*
* anyarray_send - binary output routine for pseudo-type ANYARRAY.
*
* We may as well allow this, since array_send will in fact work.
*/
Datum Datum
anyarray_send(PG_FUNCTION_ARGS) anyarray_send(PG_FUNCTION_ARGS)
{ {
return array_send(fcinfo); return array_send(fcinfo);
} }
/* /*
* anyenum_in - input routine for pseudo-type ANYENUM. * anyenum
*/
Datum
anyenum_in(PG_FUNCTION_ARGS)
{
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot accept a value of type %s", "anyenum")));
PG_RETURN_VOID(); /* keep compiler quiet */
}
/*
* anyenum_out - output routine for pseudo-type ANYENUM.
* *
* We may as well allow this, since enum_out will in fact work. * We may as well allow output, since enum_out will in fact work.
*/ */
PSEUDOTYPE_DUMMY_INPUT_FUNC(anyenum);
Datum Datum
anyenum_out(PG_FUNCTION_ARGS) anyenum_out(PG_FUNCTION_ARGS)
{ {
...@@ -161,23 +182,12 @@ anyenum_out(PG_FUNCTION_ARGS) ...@@ -161,23 +182,12 @@ anyenum_out(PG_FUNCTION_ARGS)
} }
/* /*
* anyrange_in - input routine for pseudo-type ANYRANGE. * anyrange
*/
Datum
anyrange_in(PG_FUNCTION_ARGS)
{
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot accept a value of type %s", "anyrange")));
PG_RETURN_VOID(); /* keep compiler quiet */
}
/*
* anyrange_out - output routine for pseudo-type ANYRANGE.
* *
* We may as well allow this, since range_out will in fact work. * We may as well allow output, since range_out will in fact work.
*/ */
PSEUDOTYPE_DUMMY_INPUT_FUNC(anyrange);
Datum Datum
anyrange_out(PG_FUNCTION_ARGS) anyrange_out(PG_FUNCTION_ARGS)
{ {
...@@ -185,11 +195,12 @@ anyrange_out(PG_FUNCTION_ARGS) ...@@ -185,11 +195,12 @@ anyrange_out(PG_FUNCTION_ARGS)
} }
/* /*
* void_in - input routine for pseudo-type VOID. * void
* *
* We allow this so that PL functions can return VOID without any special * We support void_in so that PL functions can return VOID without any
* hack in the PL handler. Whatever value the PL thinks it's returning * special hack in the PL handler. Whatever value the PL thinks it's
* will just be ignored. * returning will just be ignored. Conversely, void_out and void_send
* are needed so that "SELECT function_returning_void(...)" works.
*/ */
Datum Datum
void_in(PG_FUNCTION_ARGS) void_in(PG_FUNCTION_ARGS)
...@@ -197,35 +208,22 @@ void_in(PG_FUNCTION_ARGS) ...@@ -197,35 +208,22 @@ void_in(PG_FUNCTION_ARGS)
PG_RETURN_VOID(); /* you were expecting something different? */ PG_RETURN_VOID(); /* you were expecting something different? */
} }
/*
* void_out - output routine for pseudo-type VOID.
*
* We allow this so that "SELECT function_returning_void(...)" works.
*/
Datum Datum
void_out(PG_FUNCTION_ARGS) void_out(PG_FUNCTION_ARGS)
{ {
PG_RETURN_CSTRING(pstrdup("")); PG_RETURN_CSTRING(pstrdup(""));
} }
/*
* void_recv - binary input routine for pseudo-type VOID.
*
* Note that since we consume no bytes, an attempt to send anything but
* an empty string will result in an "invalid message format" error.
*/
Datum Datum
void_recv(PG_FUNCTION_ARGS) 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(); PG_RETURN_VOID();
} }
/*
* void_send - binary output routine for pseudo-type VOID.
*
* We allow this so that "SELECT function_returning_void(...)" works
* even when binary output is requested.
*/
Datum Datum
void_send(PG_FUNCTION_ARGS) void_send(PG_FUNCTION_ARGS)
{ {
...@@ -237,7 +235,12 @@ void_send(PG_FUNCTION_ARGS) ...@@ -237,7 +235,12 @@ void_send(PG_FUNCTION_ARGS)
} }
/* /*
* shell_in - input routine for "shell" types (those not yet filled in). * 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 Datum
shell_in(PG_FUNCTION_ARGS) shell_in(PG_FUNCTION_ARGS)
...@@ -249,9 +252,6 @@ shell_in(PG_FUNCTION_ARGS) ...@@ -249,9 +252,6 @@ shell_in(PG_FUNCTION_ARGS)
PG_RETURN_VOID(); /* keep compiler quiet */ PG_RETURN_VOID(); /* keep compiler quiet */
} }
/*
* shell_out - output routine for "shell" types.
*/
Datum Datum
shell_out(PG_FUNCTION_ARGS) shell_out(PG_FUNCTION_ARGS)
{ {
...@@ -264,54 +264,25 @@ shell_out(PG_FUNCTION_ARGS) ...@@ -264,54 +264,25 @@ shell_out(PG_FUNCTION_ARGS)
/* /*
* pg_node_tree_in - input routine for type PG_NODE_TREE. * pg_node_tree
* *
* pg_node_tree isn't really a pseudotype --- it's real enough to be a table * 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 * 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. * input too, so its I/O functions seem to fit here as much as anywhere.
*/
Datum
pg_node_tree_in(PG_FUNCTION_ARGS)
{
/*
* We disallow input of pg_node_tree values because the SQL functions that
* operate on the type are not secure against malformed input.
*/
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot accept a value of type %s", "pg_node_tree")));
PG_RETURN_VOID(); /* keep compiler quiet */
}
/*
* pg_node_tree_out - output routine for type PG_NODE_TREE.
* *
* The internal representation is the same as TEXT, so just pass it off. * 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 Datum
pg_node_tree_out(PG_FUNCTION_ARGS) pg_node_tree_out(PG_FUNCTION_ARGS)
{ {
return textout(fcinfo); return textout(fcinfo);
} }
/*
* pg_node_tree_recv - binary input routine for type PG_NODE_TREE.
*/
Datum
pg_node_tree_recv(PG_FUNCTION_ARGS)
{
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot accept a value of type %s", "pg_node_tree")));
PG_RETURN_VOID(); /* keep compiler quiet */
}
/*
* pg_node_tree_send - binary output routine for type PG_NODE_TREE.
*/
Datum Datum
pg_node_tree_send(PG_FUNCTION_ARGS) pg_node_tree_send(PG_FUNCTION_ARGS)
{ {
...@@ -319,102 +290,29 @@ pg_node_tree_send(PG_FUNCTION_ARGS) ...@@ -319,102 +290,29 @@ pg_node_tree_send(PG_FUNCTION_ARGS)
} }
/* /*
* pg_ddl_command_in - input routine for type PG_DDL_COMMAND. * pg_ddl_command
* *
* Like pg_node_tree, pg_ddl_command isn't really a pseudotype; it's here for * Like pg_node_tree, pg_ddl_command isn't really a pseudotype; it's here
* the same reasons as that one. * for the same reasons as that one.
*/
Datum
pg_ddl_command_in(PG_FUNCTION_ARGS)
{
/*
* Disallow input of pg_ddl_command value.
*/
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot accept a value of type %s", "pg_ddl_command")));
PG_RETURN_VOID(); /* keep compiler quiet */
}
/*
* pg_ddl_command_out - output routine for type PG_DDL_COMMAND.
* *
* We don't have any good way to output this type directly, so punt. * We don't have any good way to output this type directly, so punt
* for output as well as input.
*/ */
Datum PSEUDOTYPE_DUMMY_IO_FUNCS(pg_ddl_command);
pg_ddl_command_out(PG_FUNCTION_ARGS) PSEUDOTYPE_DUMMY_BINARY_IO_FUNCS(pg_ddl_command);
{
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot output a value of type %s", "pg_ddl_command")));
PG_RETURN_VOID();
}
/*
* pg_ddl_command_recv - binary input routine for type PG_DDL_COMMAND.
*/
Datum
pg_ddl_command_recv(PG_FUNCTION_ARGS)
{
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot accept a value of type %s", "pg_ddl_command")));
PG_RETURN_VOID();
}
/*
* pg_ddl_command_send - binary output routine for type PG_DDL_COMMAND.
*/
Datum
pg_ddl_command_send(PG_FUNCTION_ARGS)
{
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot output a value of type %s", "pg_ddl_command")));
PG_RETURN_VOID();
}
/* /*
* Generate input and output functions for a pseudotype that will reject all * Dummy I/O functions for various other pseudotypes.
* input and output attempts.
*/ */
#define PSEUDOTYPE_DUMMY_IO_FUNCS(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 */ \
} \
\
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
PSEUDOTYPE_DUMMY_IO_FUNCS(any); PSEUDOTYPE_DUMMY_IO_FUNCS(any);
PSEUDOTYPE_DUMMY_IO_FUNCS(trigger); PSEUDOTYPE_DUMMY_IO_FUNCS(trigger);
PSEUDOTYPE_DUMMY_IO_FUNCS(event_trigger); PSEUDOTYPE_DUMMY_IO_FUNCS(event_trigger);
PSEUDOTYPE_DUMMY_IO_FUNCS(language_handler); PSEUDOTYPE_DUMMY_IO_FUNCS(language_handler);
PSEUDOTYPE_DUMMY_IO_FUNCS(fdw_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(index_am_handler);
PSEUDOTYPE_DUMMY_IO_FUNCS(tsm_handler); PSEUDOTYPE_DUMMY_IO_FUNCS(tsm_handler);
PSEUDOTYPE_DUMMY_IO_FUNCS(internal); PSEUDOTYPE_DUMMY_IO_FUNCS(internal);
PSEUDOTYPE_DUMMY_IO_FUNCS(anyelement); PSEUDOTYPE_DUMMY_IO_FUNCS(anyelement);
PSEUDOTYPE_DUMMY_IO_FUNCS(anynonarray); PSEUDOTYPE_DUMMY_IO_FUNCS(anynonarray);
PSEUDOTYPE_DUMMY_IO_FUNCS(table_am_handler);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment