]> granicus.if.org Git - postgresql/blobdiff - src/backend/utils/adt/pseudotypes.c
Add support for EUI-64 MAC addresses as macaddr8
[postgresql] / src / backend / utils / adt / pseudotypes.c
index b214186a1a7dfd6133921a85ce959283c1f25200..be793539a3c84e60ff60e21bf07280403fa94f80 100644 (file)
@@ -6,17 +6,17 @@
  * 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
+ * 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-2003, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/adt/pseudotypes.c,v 1.11 2003/08/04 02:40:05 momjian Exp $
+ *       src/backend/utils/adt/pseudotypes.c
  *
  *-------------------------------------------------------------------------
  */
 #include "libpq/pqformat.h"
 #include "utils/array.h"
 #include "utils/builtins.h"
-
-
-/*
- * record_in           - input routine for pseudo-type RECORD.
- */
-Datum
-record_in(PG_FUNCTION_ARGS)
-{
-       ereport(ERROR,
-                       (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                        errmsg("cannot accept a value of type record")));
-
-       PG_RETURN_VOID();                       /* keep compiler quiet */
-}
-
-/*
- * record_out          - output routine for pseudo-type RECORD.
- */
-Datum
-record_out(PG_FUNCTION_ARGS)
-{
-       ereport(ERROR,
-                       (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                        errmsg("cannot display a value of type record")));
-
-       PG_RETURN_VOID();                       /* keep compiler quiet */
-}
-
-/*
- * record_recv         - binary input routine for pseudo-type RECORD.
- */
-Datum
-record_recv(PG_FUNCTION_ARGS)
-{
-       ereport(ERROR,
-                       (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                        errmsg("cannot accept a value of type record")));
-
-       PG_RETURN_VOID();                       /* keep compiler quiet */
-}
-
-/*
- * record_send         - binary output routine for pseudo-type RECORD.
- */
-Datum
-record_send(PG_FUNCTION_ARGS)
-{
-       ereport(ERROR,
-                       (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                        errmsg("cannot display a value of type record")));
-
-       PG_RETURN_VOID();                       /* keep compiler quiet */
-}
+#include "utils/rangetypes.h"
 
 
 /*
@@ -135,92 +83,112 @@ cstring_send(PG_FUNCTION_ARGS)
        PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
 }
 
-
 /*
- * any_in              - input routine for pseudo-type ANY.
+ * anyarray_in         - input routine for pseudo-type ANYARRAY.
  */
 Datum
-any_in(PG_FUNCTION_ARGS)
+anyarray_in(PG_FUNCTION_ARGS)
 {
        ereport(ERROR,
                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                        errmsg("cannot accept a value of type any")));
+                        errmsg("cannot accept a value of type %s", "anyarray")));
 
        PG_RETURN_VOID();                       /* keep compiler quiet */
 }
 
 /*
- * any_out             - output routine for pseudo-type ANY.
+ * anyarray_out                - output routine for pseudo-type ANYARRAY.
+ *
+ * We may as well allow this, since array_out will in fact work.
  */
 Datum
-any_out(PG_FUNCTION_ARGS)
+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 display a value of type any")));
+                        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);
+}
+
 
 /*
- * anyarray_in         - input routine for pseudo-type ANYARRAY.
+ * anyenum_in          - input routine for pseudo-type ANYENUM.
  */
 Datum
-anyarray_in(PG_FUNCTION_ARGS)
+anyenum_in(PG_FUNCTION_ARGS)
 {
        ereport(ERROR,
                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                        errmsg("cannot accept a value of type anyarray")));
+                        errmsg("cannot accept a value of type %s", "anyenum")));
 
        PG_RETURN_VOID();                       /* keep compiler quiet */
 }
 
 /*
- * anyarray_out                - output routine for pseudo-type ANYARRAY.
+ * anyenum_out         - output routine for pseudo-type ANYENUM.
  *
- * We may as well allow this, since array_out will in fact work.
+ * We may as well allow this, since enum_out will in fact work.
  */
 Datum
-anyarray_out(PG_FUNCTION_ARGS)
+anyenum_out(PG_FUNCTION_ARGS)
 {
-       return array_out(fcinfo);
+       return enum_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.
+ * anyrange_in         - input routine for pseudo-type ANYRANGE.
  */
 Datum
-anyarray_recv(PG_FUNCTION_ARGS)
+anyrange_in(PG_FUNCTION_ARGS)
 {
        ereport(ERROR,
                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                        errmsg("cannot accept a value of type anyarray")));
+                        errmsg("cannot accept a value of type %s", "anyrange")));
 
        PG_RETURN_VOID();                       /* keep compiler quiet */
 }
 
 /*
- * anyarray_send               - binary output routine for pseudo-type ANYARRAY.
+ * anyrange_out                - output routine for pseudo-type ANYRANGE.
  *
- * We may as well allow this, since array_send will in fact work.
+ * We may as well allow this, since range_out will in fact work.
  */
 Datum
-anyarray_send(PG_FUNCTION_ARGS)
+anyrange_out(PG_FUNCTION_ARGS)
 {
-       return array_send(fcinfo);
+       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
+ * hack in the PL handler.  Whatever value the PL thinks it's returning
  * will just be ignored.
  */
 Datum
@@ -240,137 +208,213 @@ 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();
+}
 
 /*
- * trigger_in          - input routine for pseudo-type TRIGGER.
+ * 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
-trigger_in(PG_FUNCTION_ARGS)
+void_send(PG_FUNCTION_ARGS)
 {
-       ereport(ERROR,
-                       (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                        errmsg("cannot accept a value of type trigger")));
+       StringInfoData buf;
 
-       PG_RETURN_VOID();                       /* keep compiler quiet */
+       /* send an empty string */
+       pq_begintypsend(&buf);
+       PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
 }
 
 /*
- * trigger_out         - output routine for pseudo-type TRIGGER.
+ * shell_in            - input routine for "shell" types (those not yet filled in).
  */
 Datum
-trigger_out(PG_FUNCTION_ARGS)
+shell_in(PG_FUNCTION_ARGS)
 {
        ereport(ERROR,
                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                        errmsg("cannot display a value of type trigger")));
+                        errmsg("cannot accept a value of a shell type")));
 
        PG_RETURN_VOID();                       /* keep compiler quiet */
 }
 
-
 /*
- * language_handler_in         - input routine for pseudo-type LANGUAGE_HANDLER.
+ * shell_out           - output routine for "shell" types.
  */
 Datum
-language_handler_in(PG_FUNCTION_ARGS)
+shell_out(PG_FUNCTION_ARGS)
 {
        ereport(ERROR,
                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                        errmsg("cannot accept a value of type language_handler")));
+                        errmsg("cannot display a value of a shell type")));
 
        PG_RETURN_VOID();                       /* keep compiler quiet */
 }
 
+
 /*
- * language_handler_out                - output routine for pseudo-type LANGUAGE_HANDLER.
+ * 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
-language_handler_out(PG_FUNCTION_ARGS)
+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 display a value of type language_handler")));
+                        errmsg("cannot accept a value of type %s", "pg_node_tree")));
 
        PG_RETURN_VOID();                       /* keep compiler quiet */
 }
 
 
 /*
- * internal_in         - input routine for pseudo-type INTERNAL.
+ * 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
-internal_in(PG_FUNCTION_ARGS)
+pg_node_tree_out(PG_FUNCTION_ARGS)
 {
-       ereport(ERROR,
-                       (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                        errmsg("cannot accept a value of type internal")));
-
-       PG_RETURN_VOID();                       /* keep compiler quiet */
+       return textout(fcinfo);
 }
 
 /*
- * internal_out                - output routine for pseudo-type INTERNAL.
+ * pg_node_tree_recv           - binary input routine for type PG_NODE_TREE.
  */
 Datum
-internal_out(PG_FUNCTION_ARGS)
+pg_node_tree_recv(PG_FUNCTION_ARGS)
 {
        ereport(ERROR,
                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                        errmsg("cannot display a value of type internal")));
+                        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);
+}
 
 /*
- * opaque_in           - input routine for pseudo-type OPAQUE.
+ * 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
-opaque_in(PG_FUNCTION_ARGS)
+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 opaque")));
+                        errmsg("cannot accept a value of type %s", "pg_ddl_command")));
 
        PG_RETURN_VOID();                       /* keep compiler quiet */
 }
 
 /*
- * opaque_out          - output routine for pseudo-type OPAQUE.
+ * 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
-opaque_out(PG_FUNCTION_ARGS)
+pg_ddl_command_out(PG_FUNCTION_ARGS)
 {
        ereport(ERROR,
                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                        errmsg("cannot display a value of type opaque")));
+                        errmsg("cannot output a value of type %s", "pg_ddl_command")));
 
-       PG_RETURN_VOID();                       /* keep compiler quiet */
+       PG_RETURN_VOID();
 }
 
-
 /*
- * anyelement_in               - input routine for pseudo-type ANYELEMENT.
+ * pg_ddl_command_recv         - binary input routine for type PG_DDL_COMMAND.
  */
 Datum
-anyelement_in(PG_FUNCTION_ARGS)
+pg_ddl_command_recv(PG_FUNCTION_ARGS)
 {
        ereport(ERROR,
                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                        errmsg("cannot accept a value of type anyelement")));
+                        errmsg("cannot accept a value of type %s", "pg_ddl_command")));
 
-       PG_RETURN_VOID();                       /* keep compiler quiet */
+       PG_RETURN_VOID();
 }
 
 /*
- * anyelement_out              - output routine for pseudo-type ANYELEMENT.
+ * pg_ddl_command_send         - binary output routine for type PG_DDL_COMMAND.
  */
 Datum
-anyelement_out(PG_FUNCTION_ARGS)
+pg_ddl_command_send(PG_FUNCTION_ARGS)
 {
        ereport(ERROR,
                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                        errmsg("cannot display a value of type anyelement")));
+                        errmsg("cannot output a value of type %s", "pg_ddl_command")));
 
-       PG_RETURN_VOID();                       /* keep compiler quiet */
+       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) \
+\
+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(trigger);
+PSEUDOTYPE_DUMMY_IO_FUNCS(event_trigger);
+PSEUDOTYPE_DUMMY_IO_FUNCS(language_handler);
+PSEUDOTYPE_DUMMY_IO_FUNCS(fdw_handler);
+PSEUDOTYPE_DUMMY_IO_FUNCS(index_am_handler);
+PSEUDOTYPE_DUMMY_IO_FUNCS(tsm_handler);
+PSEUDOTYPE_DUMMY_IO_FUNCS(internal);
+PSEUDOTYPE_DUMMY_IO_FUNCS(opaque);
+PSEUDOTYPE_DUMMY_IO_FUNCS(anyelement);
+PSEUDOTYPE_DUMMY_IO_FUNCS(anynonarray);