mirror of
https://github.com/postgres/postgres.git
synced 2025-05-06 19:59:18 +03:00
Rearrange pseudotypes.c to get rid of duplicative code.
Commit a5954de10 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
This commit is contained in:
parent
4dbcb3f844
commit
87c9c2571c
@ -29,362 +29,11 @@
|
||||
|
||||
|
||||
/*
|
||||
* cstring_in - input routine for pseudo-type CSTRING.
|
||||
*
|
||||
* We might as well allow this to support constructs like "foo_in('blah')".
|
||||
* 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.)
|
||||
*/
|
||||
Datum
|
||||
cstring_in(PG_FUNCTION_ARGS)
|
||||
{
|
||||
char *str = PG_GETARG_CSTRING(0);
|
||||
|
||||
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
|
||||
cstring_out(PG_FUNCTION_ARGS)
|
||||
{
|
||||
char *str = PG_GETARG_CSTRING(0);
|
||||
|
||||
PG_RETURN_CSTRING(pstrdup(str));
|
||||
}
|
||||
|
||||
/*
|
||||
* cstring_recv - binary input routine for pseudo-type CSTRING.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
* cstring_send - binary output routine for pseudo-type CSTRING.
|
||||
*/
|
||||
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_in - input routine for pseudo-type ANYARRAY.
|
||||
*/
|
||||
Datum
|
||||
anyarray_in(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_out - output routine for pseudo-type ANYARRAY.
|
||||
*
|
||||
* We may as well allow this, since array_out will in fact work.
|
||||
*/
|
||||
Datum
|
||||
anyarray_out(PG_FUNCTION_ARGS)
|
||||
{
|
||||
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
|
||||
anyarray_send(PG_FUNCTION_ARGS)
|
||||
{
|
||||
return array_send(fcinfo);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* anyenum_in - input routine for pseudo-type 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.
|
||||
*/
|
||||
Datum
|
||||
anyenum_out(PG_FUNCTION_ARGS)
|
||||
{
|
||||
return enum_out(fcinfo);
|
||||
}
|
||||
|
||||
/*
|
||||
* anyrange_in - input routine for pseudo-type 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.
|
||||
*/
|
||||
Datum
|
||||
anyrange_out(PG_FUNCTION_ARGS)
|
||||
{
|
||||
return range_out(fcinfo);
|
||||
}
|
||||
|
||||
/*
|
||||
* void_in - input routine for pseudo-type VOID.
|
||||
*
|
||||
* We allow this 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.
|
||||
*/
|
||||
Datum
|
||||
void_in(PG_FUNCTION_ARGS)
|
||||
{
|
||||
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
|
||||
void_out(PG_FUNCTION_ARGS)
|
||||
{
|
||||
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
|
||||
void_recv(PG_FUNCTION_ARGS)
|
||||
{
|
||||
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
|
||||
void_send(PG_FUNCTION_ARGS)
|
||||
{
|
||||
StringInfoData buf;
|
||||
|
||||
/* send an empty string */
|
||||
pq_begintypsend(&buf);
|
||||
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
|
||||
}
|
||||
|
||||
/*
|
||||
* shell_in - input routine for "shell" types (those not yet filled in).
|
||||
*/
|
||||
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 */
|
||||
}
|
||||
|
||||
/*
|
||||
* shell_out - output routine for "shell" types.
|
||||
*/
|
||||
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_in - input routine for type 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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
Datum
|
||||
pg_node_tree_out(PG_FUNCTION_ARGS)
|
||||
{
|
||||
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
|
||||
pg_node_tree_send(PG_FUNCTION_ARGS)
|
||||
{
|
||||
return textsend(fcinfo);
|
||||
}
|
||||
|
||||
/*
|
||||
* pg_ddl_command_in - input routine for type 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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
Datum
|
||||
pg_ddl_command_out(PG_FUNCTION_ARGS)
|
||||
{
|
||||
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
|
||||
* input and output attempts.
|
||||
*/
|
||||
#define PSEUDOTYPE_DUMMY_IO_FUNCS(typname) \
|
||||
\
|
||||
#define PSEUDOTYPE_DUMMY_INPUT_FUNC(typname) \
|
||||
Datum \
|
||||
typname##_in(PG_FUNCTION_ARGS) \
|
||||
{ \
|
||||
@ -395,6 +44,11 @@ typname##_in(PG_FUNCTION_ARGS) \
|
||||
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) \
|
||||
{ \
|
||||
@ -407,14 +61,258 @@ typname##_out(PG_FUNCTION_ARGS) \
|
||||
\
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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(table_am_handler);
|
||||
|
Loading…
x
Reference in New Issue
Block a user