Home Explore Blog CI



postgresql

2nd chunk of `doc/src/sgml/xtypes.sgml`
792d634e426eea7c79b666e3235e9f7869ce8cb43602991f0000000100000fa0
                 errmsg("invalid input syntax for type %s: \"%s\"",
                        "complex", str)));

    result = (Complex *) palloc(sizeof(Complex));
    result->x = x;
    result->y = y;
    PG_RETURN_POINTER(result);
}
]]>
</programlisting>

  The output function can simply be:

<programlisting><![CDATA[
PG_FUNCTION_INFO_V1(complex_out);

Datum
complex_out(PG_FUNCTION_ARGS)
{
    Complex    *complex = (Complex *) PG_GETARG_POINTER(0);
    char       *result;

    result = psprintf("(%g,%g)", complex->x, complex->y);
    PG_RETURN_CSTRING(result);
}
]]>
</programlisting>
 </para>

 <para>
  You should be careful to make the input and output functions inverses of
  each other.  If you do not, you will have severe problems when you
  need to dump your data into a file and then read it back in.  This
  is a particularly common problem when floating-point numbers are
  involved.
 </para>

 <para>
  Optionally, a user-defined type can provide binary input and output
  routines.  Binary I/O is normally faster but less portable than textual
  I/O.  As with textual I/O, it is up to you to define exactly what the
  external binary representation is.  Most of the built-in data types
  try to provide a machine-independent binary representation.  For
  <type>complex</type>, we will piggy-back on the binary I/O converters
  for type <type>float8</type>:

<programlisting><![CDATA[
PG_FUNCTION_INFO_V1(complex_recv);

Datum
complex_recv(PG_FUNCTION_ARGS)
{
    StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
    Complex    *result;

    result = (Complex *) palloc(sizeof(Complex));
    result->x = pq_getmsgfloat8(buf);
    result->y = pq_getmsgfloat8(buf);
    PG_RETURN_POINTER(result);
}

PG_FUNCTION_INFO_V1(complex_send);

Datum
complex_send(PG_FUNCTION_ARGS)
{
    Complex    *complex = (Complex *) PG_GETARG_POINTER(0);
    StringInfoData buf;

    pq_begintypsend(&buf);
    pq_sendfloat8(&buf, complex->x);
    pq_sendfloat8(&buf, complex->y);
    PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
}
]]>
</programlisting>
 </para>

 <para>
  Once we have written the I/O functions and compiled them into a shared
  library, we can define the <type>complex</type> type in SQL.
  First we declare it as a shell type:

<programlisting>
CREATE TYPE complex;
</programlisting>

  This serves as a placeholder that allows us to reference the type while
  defining its I/O functions.  Now we can define the I/O functions:

<programlisting>
CREATE FUNCTION complex_in(cstring)
    RETURNS complex
    AS '<replaceable>filename</replaceable>'
    LANGUAGE C IMMUTABLE STRICT;

CREATE FUNCTION complex_out(complex)
    RETURNS cstring
    AS '<replaceable>filename</replaceable>'
    LANGUAGE C IMMUTABLE STRICT;

CREATE FUNCTION complex_recv(internal)
   RETURNS complex
   AS '<replaceable>filename</replaceable>'
   LANGUAGE C IMMUTABLE STRICT;

CREATE FUNCTION complex_send(complex)
   RETURNS bytea
   AS '<replaceable>filename</replaceable>'
   LANGUAGE C IMMUTABLE STRICT;
</programlisting>
 </para>

 <para>
  Finally, we can provide the full definition of the data type:
<programlisting>
CREATE TYPE complex (
   internallength = 16,
   input = complex_in,
   output = complex_out,
   receive = complex_recv,
   send = complex_send,
   alignment = double
);
</programlisting>
 </para>

 <para>
  <indexterm>
    <primary>array</primary>
    <secondary>of user-defined type</secondary>
  </indexterm>
  When you define a new base type,
  <productname>PostgreSQL</productname> automatically provides support
  for arrays of that type.  The array type typically
  has the same name as the base type with the underscore character
  (<literal>_</literal>) prepended.
 </para>

 <para>
  Once the data type exists, we can declare additional functions to
  provide useful operations on the data type.  Operators can then be
  defined atop the functions, and if needed, operator classes can be
  created to support indexing of the data type.  These additional
  layers are discussed

Title: Implementing Input and Output Functions for a Complex Number Type
Summary
This section details the implementation of input and output functions for the 'complex' number type in PostgreSQL, including both text-based and binary I/O routines. It demonstrates the creation of `complex_in`, `complex_out`, `complex_recv`, and `complex_send` functions. It also shows how to register the type and its functions in SQL, including creating a shell type and defining the complete data type with input, output, send, and receive functions. PostgreSQL automatically supports arrays of the new type. Finally, the section mentions the possibility of defining operators and operator classes for the data type.