mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-09-16 15:20:59 +02:00
b663f3443b
with OPAQUE, as per recent pghackers discussion. I still want to do some more work on the 'cstring' pseudo-type, but I'm going to commit the bulk of the changes now before the tree starts shifting under me ...
212 lines
6.0 KiB
Plaintext
212 lines
6.0 KiB
Plaintext
<chapter id="xtypes">
|
|
<title>Extending <acronym>SQL</acronym>: Types</title>
|
|
|
|
<indexterm zone="xtypes">
|
|
<primary>data types</primary>
|
|
<secondary>extending</secondary>
|
|
</indexterm>
|
|
|
|
<comment>
|
|
This chapter needs to be updated for the version-1 function manager
|
|
interface.
|
|
</comment>
|
|
|
|
<para>
|
|
As previously mentioned, there are two kinds of types in
|
|
<productname>PostgreSQL</productname>: base types (defined in a
|
|
programming language) and composite types. This chapter describes
|
|
how to define new base types.
|
|
</para>
|
|
|
|
<para>
|
|
The examples in this section can be found in
|
|
<filename>complex.sql</filename> and <filename>complex.c</filename>
|
|
in the tutorial directory. Composite examples are in
|
|
<filename>funcs.sql</filename>.
|
|
</para>
|
|
|
|
<para>
|
|
<indexterm>
|
|
<primary>input function</primary>
|
|
</indexterm>
|
|
<indexterm>
|
|
<primary>output function</primary>
|
|
</indexterm>
|
|
A user-defined type must always have input and output functions.
|
|
These functions determine how the type appears in strings (for input
|
|
by the user and output to the user) and how the type is organized in
|
|
memory. The input function takes a null-terminated character string
|
|
as its input and returns the internal (in memory) representation of
|
|
the type. The output function takes the internal representation of
|
|
the type and returns a null-terminated character string.
|
|
</para>
|
|
|
|
<para>
|
|
Suppose we want to define a complex type which represents complex
|
|
numbers. Naturally, we would choose to represent a complex in memory
|
|
as the following <acronym>C</acronym> structure:
|
|
|
|
<programlisting>
|
|
typedef struct Complex {
|
|
double x;
|
|
double y;
|
|
} Complex;
|
|
</programlisting>
|
|
|
|
and a string of the form <literal>(x,y)</literal> as the external string
|
|
representation.
|
|
</para>
|
|
|
|
<para>
|
|
The functions are usually not hard to write, especially the output
|
|
function. However, there are a number of points to remember:
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>
|
|
When defining your external (string) representation, remember
|
|
that you must eventually write a complete and robust parser for
|
|
that representation as your input function!
|
|
</para>
|
|
|
|
<para>
|
|
For instance:
|
|
|
|
<programlisting>
|
|
Complex *
|
|
complex_in(char *str)
|
|
{
|
|
double x, y;
|
|
Complex *result;
|
|
if (sscanf(str, " ( %lf , %lf )", &x, &y) != 2) {
|
|
elog(ERROR, "complex_in: error in parsing %s", str);
|
|
return NULL;
|
|
}
|
|
result = (Complex *)palloc(sizeof(Complex));
|
|
result->x = x;
|
|
result->y = y;
|
|
return (result);
|
|
}
|
|
</programlisting>
|
|
</para>
|
|
|
|
<para>
|
|
The output function can simply be:
|
|
|
|
<programlisting>
|
|
char *
|
|
complex_out(Complex *complex)
|
|
{
|
|
char *result;
|
|
if (complex == NULL)
|
|
return(NULL);
|
|
result = (char *) palloc(60);
|
|
sprintf(result, "(%g,%g)", complex->x, complex->y);
|
|
return(result);
|
|
}
|
|
</programlisting>
|
|
|
|
</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>
|
|
You should try 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
|
|
(say, into someone else's database on another computer). This is
|
|
a particularly common problem when floating-point numbers are
|
|
involved.
|
|
</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</para>
|
|
|
|
<para>
|
|
To define the <type>complex</type> type, we need to create the two
|
|
user-defined functions <function>complex_in</function> and
|
|
<function>complex_out</function> before creating the type:
|
|
|
|
<programlisting>
|
|
CREATE FUNCTION complex_in(cstring)
|
|
RETURNS complex
|
|
AS '<replaceable>PGROOT</replaceable>/tutorial/complex'
|
|
LANGUAGE C;
|
|
|
|
CREATE FUNCTION complex_out(complex)
|
|
RETURNS cstring
|
|
AS '<replaceable>PGROOT</replaceable>/tutorial/complex'
|
|
LANGUAGE C;
|
|
</programlisting>
|
|
</para>
|
|
|
|
<para>
|
|
Finally, we can declare the data type:
|
|
<programlisting>
|
|
CREATE TYPE complex (
|
|
internallength = 16,
|
|
input = complex_in,
|
|
output = complex_out
|
|
);
|
|
</programlisting>
|
|
|
|
Notice that the declarations of the input and output functions must
|
|
reference the not-yet-defined type. This is allowed, but will draw
|
|
warning messages that may be ignored.
|
|
</para>
|
|
|
|
<para>
|
|
<indexterm>
|
|
<primary>arrays</primary>
|
|
</indexterm>
|
|
As discussed earlier, <productname>PostgreSQL</productname> fully
|
|
supports arrays of base types. Additionally,
|
|
<productname>PostgreSQL</productname> supports arrays of
|
|
user-defined types as well. When you define a type,
|
|
<productname>PostgreSQL</productname> automatically provides support
|
|
for arrays of that type. For historical reasons, the array type has
|
|
the same name as the user-defined type with the underscore character
|
|
<literal>_</> prepended.
|
|
</para>
|
|
|
|
<para>
|
|
Composite types do not need any function defined on them, since the
|
|
system already understands what they look like inside.
|
|
</para>
|
|
|
|
<para>
|
|
<indexterm>
|
|
<primary>TOAST</primary>
|
|
<secondary>and user-defined types</secondary>
|
|
</indexterm>
|
|
If the values of your data type might exceed a few hundred bytes in
|
|
size (in internal form), you should be careful to mark them
|
|
TOAST-able. To do this, the internal representation must follow the
|
|
standard layout for variable-length data: the first four bytes must
|
|
be an <type>int32</type> containing the total length in bytes of the
|
|
datum (including itself). Then, all your functions that accept
|
|
values of the type must be careful to call
|
|
<function>pg_detoast_datum()</function> on the supplied values ---
|
|
after checking that the value is not NULL, if your function is not
|
|
strict. Finally, select the appropriate storage option when giving
|
|
the <command>CREATE TYPE</command> command.
|
|
</para>
|
|
</chapter>
|
|
|
|
<!-- Keep this comment at the end of the file
|
|
Local variables:
|
|
mode:sgml
|
|
sgml-omittag:nil
|
|
sgml-shorttag:t
|
|
sgml-minimize-attributes:nil
|
|
sgml-always-quote-attributes:t
|
|
sgml-indent-step:1
|
|
sgml-indent-data:t
|
|
sgml-parent-document:nil
|
|
sgml-default-dtd-file:"./reference.ced"
|
|
sgml-exposed-tags:nil
|
|
sgml-local-catalogs:("/usr/lib/sgml/catalog")
|
|
sgml-local-ecat-files:nil
|
|
End:
|
|
-->
|