Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 6fbb14a

Browse files
committed
Update the complex-datatype example to V1 function calling conventions,
and add binary send/receive functions. Fix some other grottiness such as failure to mark the C functions STRICT.
1 parent 6c7c493 commit 6fbb14a

File tree

4 files changed

+311
-136
lines changed

4 files changed

+311
-136
lines changed

doc/src/sgml/xoper.sgml

+18-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$Header: /cvsroot/pgsql/doc/src/sgml/xoper.sgml,v 1.26 2003/08/31 17:32:21 petere Exp $
2+
$Header: /cvsroot/pgsql/doc/src/sgml/xoper.sgml,v 1.27 2003/10/21 22:51:14 tgl Exp $
33
-->
44

55
<sect1 id="xoper">
@@ -120,6 +120,23 @@ SELECT (a + b) AS c FROM test_complex;
120120
be provided in the <literal>COMMUTATOR</> clause.
121121
</para>
122122

123+
<para>
124+
It's critical to provide commutator information for operators that
125+
will be used in indexes and join clauses, because this allows the
126+
query optimizer to <quote>flip around</> such a clause to the forms
127+
needed for different plan types. For example, consider a query with
128+
a WHERE clause like <literal>tab1.x = tab2.y</>, where <literal>tab1.x</>
129+
and <literal>tab2.y</> are of a user-defined type, and suppose that
130+
<literal>tab2.y</> is indexed. The optimizer cannot generate an
131+
indexscan unless it can determine how to flip the clause around to
132+
<literal>tab2.y = tab1.x</>, because the indexscan machinery expects
133+
to see the indexed column on the left of the operator it is given.
134+
<ProductName>PostgreSQL</ProductName> will <emphasis>not</> simply
135+
assume that this is a valid transformation --- the definer of the
136+
<literal>=</> operator must specify that it is valid, by marking the
137+
operator with commutator information.
138+
</para>
139+
123140
<para>
124141
When you are defining a self-commutative operator, you just do it.
125142
When you are defining a pair of commutative operators, things are

doc/src/sgml/xtypes.sgml

+112-36
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
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 $
33
-->
44

55
<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
1010
<secondary>user-defined</secondary>
1111
</indexterm>
1212

13-
<comment>
14-
This section needs to be updated for the version-1 function manager
15-
interface.
16-
</comment>
17-
1813
<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.
2220
</para>
2321

2422
<para>
2523
The examples in this section can be found in
2624
<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.
2828
</para>
2929

3030
<para>
@@ -44,12 +44,14 @@ $Header: /cvsroot/pgsql/doc/src/sgml/xtypes.sgml,v 1.20 2003/08/31 17:32:21 pete
4444
as its argument and returns the internal (in memory) representation
4545
of the type. The output function takes the internal representation
4646
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.
4850
</para>
4951

5052
<para>
5153
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
5355
memory would be the following C structure:
5456

5557
<programlisting>
@@ -59,6 +61,11 @@ typedef struct Complex {
5961
} Complex;
6062
</programlisting>
6163

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>
6269
As the external string representation of the type, we choose a
6370
string of the form <literal>(x,y)</literal>.
6471
</para>
@@ -71,79 +78,137 @@ typedef struct Complex {
7178
input function. For instance:
7279

7380
<programlisting>
74-
Complex *
75-
complex_in(char *str)
81+
PG_FUNCTION_INFO_V1(complex_in);
82+
83+
Datum
84+
complex_in(PG_FUNCTION_ARGS)
7685
{
86+
char *str = PG_GETARG_CSTRING(0);
7787
double x,
7888
y;
7989
Complex *result;
8090

8191
if (sscanf(str, " ( %lf , %lf )", &amp;x, &amp;y) != 2)
8292
ereport(ERROR,
8393
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
84-
errmsg("invalid input syntax for complex: \"%s\"", str)));
94+
errmsg("invalid input syntax for complex: \"%s\"",
95+
str)));
8596

8697
result = (Complex *) palloc(sizeof(Complex));
8798
result-&gt;x = x;
8899
result-&gt;y = y;
89-
return result;
100+
PG_RETURN_POINTER(result);
90101
}
91102
</programlisting>
92103

93104
The output function can simply be:
94105

95106
<programlisting>
96-
char *
97-
complex_out(Complex *complex)
107+
PG_FUNCTION_INFO_V1(complex_out);
108+
109+
Datum
110+
complex_out(PG_FUNCTION_ARGS)
98111
{
99-
char *result;
112+
Complex *complex = (Complex *) PG_GETARG_POINTER(0);
113+
char *result;
100114

101-
if (complex == NULL)
102-
return(NULL);
103-
result = (char *) palloc(60);
104-
sprintf(result, "(%g,%g)", complex-&gt;x, complex-&gt;y);
105-
return result;
115+
result = (char *) palloc(100);
116+
snprintf(result, 100, "(%g,%g)", complex-&gt;x, complex-&gt;y);
117+
PG_RETURN_CSTRING(result);
106118
}
107119
</programlisting>
108120
</para>
109121

110122
<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
112124
each other. If you do not, you will have severe problems when you
113125
need to dump your data into a file and then read it back in. This
114126
is a particularly common problem when floating-point numbers are
115127
involved.
116128
</para>
117129

118130
<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-&gt;x = pq_getmsgfloat8(buf);
150+
result-&gt;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(&amp;buf);
163+
pq_sendfloat8(&amp;buf, complex-&gt;x);
164+
pq_sendfloat8(&amp;buf, complex-&gt;y);
165+
PG_RETURN_BYTEA_P(pq_endtypsend(&amp;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:
122173

123174
<programlisting>
124175
CREATE FUNCTION complex_in(cstring)
125176
RETURNS complex
126177
AS '<replaceable>filename</replaceable>'
127-
LANGUAGE C;
178+
LANGUAGE C IMMUTABLE STRICT;
128179

129180
CREATE FUNCTION complex_out(complex)
130181
RETURNS cstring
131182
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;
133194
</programlisting>
134195

135196
Notice that the declarations of the input and output functions must
136197
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.
138200
</para>
139201

140202
<para>
141203
Finally, we can declare the data type:
142204
<programlisting>
143205
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
147212
);
148213
</programlisting>
149214
</para>
@@ -158,14 +223,25 @@ CREATE TYPE complex (
158223
(<literal>_</>) prepended.
159224
</para>
160225

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+
161234
<para>
162235
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
164237
TOAST-able.<indexterm><primary>TOAST</primary><secondary>and
165238
user-defined types</secondary></indexterm> To do this, the internal
166239
representation must follow the standard layout for variable-length
167240
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,
169245
when running the <command>CREATE TYPE</command> command, specify the
170246
internal length as <literal>variable</> and select the appropriate
171247
storage option.

0 commit comments

Comments
 (0)