1
1
<!--
2
- $Header: /cvsroot/pgsql/doc/src/sgml/xtypes.sgml,v 1.20 2003/08/31 17:32:21 petere Exp $
2
+ $Header: /cvsroot/pgsql/doc/src/sgml/xtypes.sgml,v 1.21 2003/10/21 22:51:14 tgl Exp $
3
3
-->
4
4
5
5
<sect1 id="xtypes">
@@ -10,21 +10,21 @@ $Header: /cvsroot/pgsql/doc/src/sgml/xtypes.sgml,v 1.20 2003/08/31 17:32:21 pete
10
10
<secondary>user-defined</secondary>
11
11
</indexterm>
12
12
13
- <comment>
14
- This section needs to be updated for the version-1 function manager
15
- interface.
16
- </comment>
17
-
18
13
<para>
19
- As described above, there are two kinds of data types in
20
- <productname>PostgreSQL</productname>: base types and composite
21
- types. This section describes how to define new base types.
14
+ As described in <xref linkend="extend-type-system">,
15
+ <productname>PostgreSQL</productname> can be extended to support new
16
+ data types. This section describes how to define new base types,
17
+ which are data types defined below the level of the <acronym>SQL</>
18
+ language. Creating a new base type requires implementing functions
19
+ to operate on the type in a low-level language, usually C.
22
20
</para>
23
21
24
22
<para>
25
23
The examples in this section can be found in
26
24
<filename>complex.sql</filename> and <filename>complex.c</filename>
27
- in the tutorial directory.
25
+ in the <filename>src/tutorial</> directory of the source distribution.
26
+ See the <filename>README</> file in that directory for instructions
27
+ about running the examples.
28
28
</para>
29
29
30
30
<para>
@@ -44,12 +44,14 @@ $Header: /cvsroot/pgsql/doc/src/sgml/xtypes.sgml,v 1.20 2003/08/31 17:32:21 pete
44
44
as its argument and returns the internal (in memory) representation
45
45
of the type. The output function takes the internal representation
46
46
of the type as argument and returns a null-terminated character
47
- string.
47
+ string. If we want to do anything more with the type than merely
48
+ store it, we must provide additional functions to implement whatever
49
+ operations we'd like to have for the type.
48
50
</para>
49
51
50
52
<para>
51
53
Suppose we want to define a type <type>complex</> that represents
52
- complex numbers. A natural way to to represent a complex number in
54
+ complex numbers. A natural way to represent a complex number in
53
55
memory would be the following C structure:
54
56
55
57
<programlisting>
@@ -59,6 +61,11 @@ typedef struct Complex {
59
61
} Complex;
60
62
</programlisting>
61
63
64
+ We will need to make this a pass-by-reference type, since it's too
65
+ large to fit into a single <type>Datum</> value.
66
+ </para>
67
+
68
+ <para>
62
69
As the external string representation of the type, we choose a
63
70
string of the form <literal>(x,y)</literal>.
64
71
</para>
@@ -71,79 +78,137 @@ typedef struct Complex {
71
78
input function. For instance:
72
79
73
80
<programlisting>
74
- Complex *
75
- complex_in(char *str)
81
+ PG_FUNCTION_INFO_V1(complex_in);
82
+
83
+ Datum
84
+ complex_in(PG_FUNCTION_ARGS)
76
85
{
86
+ char *str = PG_GETARG_CSTRING(0);
77
87
double x,
78
88
y;
79
89
Complex *result;
80
90
81
91
if (sscanf(str, " ( %lf , %lf )", &x, &y) != 2)
82
92
ereport(ERROR,
83
93
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
84
- errmsg("invalid input syntax for complex: \"%s\"", str)));
94
+ errmsg("invalid input syntax for complex: \"%s\"",
95
+ str)));
85
96
86
97
result = (Complex *) palloc(sizeof(Complex));
87
98
result->x = x;
88
99
result->y = y;
89
- return result;
100
+ PG_RETURN_POINTER( result) ;
90
101
}
91
102
</programlisting>
92
103
93
104
The output function can simply be:
94
105
95
106
<programlisting>
96
- char *
97
- complex_out(Complex *complex)
107
+ PG_FUNCTION_INFO_V1(complex_out);
108
+
109
+ Datum
110
+ complex_out(PG_FUNCTION_ARGS)
98
111
{
99
- char *result;
112
+ Complex *complex = (Complex *) PG_GETARG_POINTER(0);
113
+ char *result;
100
114
101
- if (complex == NULL)
102
- return(NULL);
103
- result = (char *) palloc(60);
104
- sprintf(result, "(%g,%g)", complex->x, complex->y);
105
- return result;
115
+ result = (char *) palloc(100);
116
+ snprintf(result, 100, "(%g,%g)", complex->x, complex->y);
117
+ PG_RETURN_CSTRING(result);
106
118
}
107
119
</programlisting>
108
120
</para>
109
121
110
122
<para>
111
- You should try to make the input and output functions inverses of
123
+ You should be careful to make the input and output functions inverses of
112
124
each other. If you do not, you will have severe problems when you
113
125
need to dump your data into a file and then read it back in. This
114
126
is a particularly common problem when floating-point numbers are
115
127
involved.
116
128
</para>
117
129
118
130
<para>
119
- To define the <type>complex</type> type, we need to create the two
120
- user-defined functions <function>complex_in</function> and
121
- <function>complex_out</function> before creating the type:
131
+ Optionally, a user-defined type can provide binary input and output
132
+ routines. Binary I/O is normally faster but less portable than textual
133
+ I/O. As with textual I/O, it is up to you to define exactly what the
134
+ external binary representation is. Most of the built-in datatypes
135
+ try to provide a machine-independent binary representation. For
136
+ <type>complex</type>, we will piggy-back on the binary I/O converters
137
+ for type <type>float8</>:
138
+
139
+ <programlisting>
140
+ PG_FUNCTION_INFO_V1(complex_recv);
141
+
142
+ Datum
143
+ complex_recv(PG_FUNCTION_ARGS)
144
+ {
145
+ StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
146
+ Complex *result;
147
+
148
+ result = (Complex *) palloc(sizeof(Complex));
149
+ result->x = pq_getmsgfloat8(buf);
150
+ result->y = pq_getmsgfloat8(buf);
151
+ PG_RETURN_POINTER(result);
152
+ }
153
+
154
+ PG_FUNCTION_INFO_V1(complex_send);
155
+
156
+ Datum
157
+ complex_send(PG_FUNCTION_ARGS)
158
+ {
159
+ Complex *complex = (Complex *) PG_GETARG_POINTER(0);
160
+ StringInfoData buf;
161
+
162
+ pq_begintypsend(&buf);
163
+ pq_sendfloat8(&buf, complex->x);
164
+ pq_sendfloat8(&buf, complex->y);
165
+ PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
166
+ }
167
+ </programlisting>
168
+ </para>
169
+
170
+ <para>
171
+ To define the <type>complex</type> type, we need to create the
172
+ user-defined I/O functions before creating the type:
122
173
123
174
<programlisting>
124
175
CREATE FUNCTION complex_in(cstring)
125
176
RETURNS complex
126
177
AS '<replaceable>filename</replaceable>'
127
- LANGUAGE C;
178
+ LANGUAGE C IMMUTABLE STRICT ;
128
179
129
180
CREATE FUNCTION complex_out(complex)
130
181
RETURNS cstring
131
182
AS '<replaceable>filename</replaceable>'
132
- LANGUAGE C;
183
+ LANGUAGE C IMMUTABLE STRICT;
184
+
185
+ CREATE FUNCTION complex_recv(internal)
186
+ RETURNS complex
187
+ AS '<replaceable>filename</replaceable>'
188
+ LANGUAGE C IMMUTABLE STRICT;
189
+
190
+ CREATE FUNCTION complex_send(complex)
191
+ RETURNS bytea
192
+ AS '<replaceable>filename</replaceable>'
193
+ LANGUAGE C IMMUTABLE STRICT;
133
194
</programlisting>
134
195
135
196
Notice that the declarations of the input and output functions must
136
197
reference the not-yet-defined type. This is allowed, but will draw
137
- warning messages that may be ignored.
198
+ warning messages that may be ignored. The input function must
199
+ appear first.
138
200
</para>
139
201
140
202
<para>
141
203
Finally, we can declare the data type:
142
204
<programlisting>
143
205
CREATE TYPE complex (
144
- internallength = 16,
145
- input = complex_in,
146
- output = complex_out
206
+ internallength = 16,
207
+ input = complex_in,
208
+ output = complex_out,
209
+ receive = complex_recv,
210
+ send = complex_send,
211
+ alignment = double
147
212
);
148
213
</programlisting>
149
214
</para>
@@ -158,14 +223,25 @@ CREATE TYPE complex (
158
223
(<literal>_</>) prepended.
159
224
</para>
160
225
226
+ <para>
227
+ Once the data type exists, we can declare additional functions to
228
+ provide useful operations on the data type. Operators can then be
229
+ defined atop the functions, and if needed, operator classes can be
230
+ created to support indexing of the data type. These additional
231
+ layers are discussed in following sections.
232
+ </para>
233
+
161
234
<para>
162
235
If the values of your data type might exceed a few hundred bytes in
163
- size (in internal form), you should mark them
236
+ size (in internal form), you should make the data type
164
237
TOAST-able.<indexterm><primary>TOAST</primary><secondary>and
165
238
user-defined types</secondary></indexterm> To do this, the internal
166
239
representation must follow the standard layout for variable-length
167
240
data: the first four bytes must be an <type>int32</type> containing
168
- the total length in bytes of the datum (including itself). Also,
241
+ the total length in bytes of the datum (including itself). The C
242
+ functions operating on the data type must be careful to unpack any
243
+ toasted values they are handed (this detail can normally be hidden in the
244
+ GETARG macros). Then,
169
245
when running the <command>CREATE TYPE</command> command, specify the
170
246
internal length as <literal>variable</> and select the appropriate
171
247
storage option.
0 commit comments