1
/******************************************************************************
2
This file contains routines that can be bound to a Postgres backend and
3
called by the backend in the process of processing queries. The calling
4
format for these routines is dictated by Postgres architecture.
5
******************************************************************************/
10
#include "libpq/pqformat.h" /* needed for send/recv functions */
13
typedef struct Complex
20
* Since we use V1 function calling convention, all these functions have
21
* the same signature as far as C is concerned. We provide these prototypes
22
* just to forestall warnings when compiled with gcc -Wmissing-prototypes.
24
Datum complex_in(PG_FUNCTION_ARGS);
25
Datum complex_out(PG_FUNCTION_ARGS);
26
Datum complex_recv(PG_FUNCTION_ARGS);
27
Datum complex_send(PG_FUNCTION_ARGS);
28
Datum complex_add(PG_FUNCTION_ARGS);
29
Datum complex_abs_lt(PG_FUNCTION_ARGS);
30
Datum complex_abs_le(PG_FUNCTION_ARGS);
31
Datum complex_abs_eq(PG_FUNCTION_ARGS);
32
Datum complex_abs_ge(PG_FUNCTION_ARGS);
33
Datum complex_abs_gt(PG_FUNCTION_ARGS);
34
Datum complex_abs_cmp(PG_FUNCTION_ARGS);
37
/*****************************************************************************
38
* Input/Output functions
39
*****************************************************************************/
41
PG_FUNCTION_INFO_V1(complex_in);
44
complex_in(PG_FUNCTION_ARGS)
46
char *str = PG_GETARG_CSTRING(0);
51
if (sscanf(str, " ( %lf , %lf )", &x, &y) != 2)
53
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
54
errmsg("invalid input syntax for complex: \"%s\"",
57
result = (Complex *) palloc(sizeof(Complex));
60
PG_RETURN_POINTER(result);
63
PG_FUNCTION_INFO_V1(complex_out);
66
complex_out(PG_FUNCTION_ARGS)
68
Complex *complex = (Complex *) PG_GETARG_POINTER(0);
71
result = (char *) palloc(100);
72
snprintf(result, 100, "(%g,%g)", complex->x, complex->y);
73
PG_RETURN_CSTRING(result);
76
/*****************************************************************************
77
* Binary Input/Output functions
80
*****************************************************************************/
82
PG_FUNCTION_INFO_V1(complex_recv);
85
complex_recv(PG_FUNCTION_ARGS)
87
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
90
result = (Complex *) palloc(sizeof(Complex));
91
result->x = pq_getmsgfloat8(buf);
92
result->y = pq_getmsgfloat8(buf);
93
PG_RETURN_POINTER(result);
96
PG_FUNCTION_INFO_V1(complex_send);
99
complex_send(PG_FUNCTION_ARGS)
101
Complex *complex = (Complex *) PG_GETARG_POINTER(0);
104
pq_begintypsend(&buf);
105
pq_sendfloat8(&buf, complex->x);
106
pq_sendfloat8(&buf, complex->y);
107
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
110
/*****************************************************************************
113
* A practical Complex datatype would provide much more than this, of course.
114
*****************************************************************************/
116
PG_FUNCTION_INFO_V1(complex_add);
119
complex_add(PG_FUNCTION_ARGS)
121
Complex *a = (Complex *) PG_GETARG_POINTER(0);
122
Complex *b = (Complex *) PG_GETARG_POINTER(1);
125
result = (Complex *) palloc(sizeof(Complex));
126
result->x = a->x + b->x;
127
result->y = a->y + b->y;
128
PG_RETURN_POINTER(result);
132
/*****************************************************************************
133
* Operator class for defining B-tree index
135
* It's essential that the comparison operators and support function for a
136
* B-tree index opclass always agree on the relative ordering of any two
137
* data values. Experience has shown that it's depressingly easy to write
138
* unintentionally inconsistent functions. One way to reduce the odds of
139
* making a mistake is to make all the functions simple wrappers around
140
* an internal three-way-comparison function, as we do here.
141
*****************************************************************************/
143
#define Mag(c) ((c)->x*(c)->x + (c)->y*(c)->y)
146
complex_abs_cmp_internal(Complex * a, Complex * b)
148
double amag = Mag(a),
159
PG_FUNCTION_INFO_V1(complex_abs_lt);
162
complex_abs_lt(PG_FUNCTION_ARGS)
164
Complex *a = (Complex *) PG_GETARG_POINTER(0);
165
Complex *b = (Complex *) PG_GETARG_POINTER(1);
167
PG_RETURN_BOOL(complex_abs_cmp_internal(a, b) < 0);
170
PG_FUNCTION_INFO_V1(complex_abs_le);
173
complex_abs_le(PG_FUNCTION_ARGS)
175
Complex *a = (Complex *) PG_GETARG_POINTER(0);
176
Complex *b = (Complex *) PG_GETARG_POINTER(1);
178
PG_RETURN_BOOL(complex_abs_cmp_internal(a, b) <= 0);
181
PG_FUNCTION_INFO_V1(complex_abs_eq);
184
complex_abs_eq(PG_FUNCTION_ARGS)
186
Complex *a = (Complex *) PG_GETARG_POINTER(0);
187
Complex *b = (Complex *) PG_GETARG_POINTER(1);
189
PG_RETURN_BOOL(complex_abs_cmp_internal(a, b) == 0);
192
PG_FUNCTION_INFO_V1(complex_abs_ge);
195
complex_abs_ge(PG_FUNCTION_ARGS)
197
Complex *a = (Complex *) PG_GETARG_POINTER(0);
198
Complex *b = (Complex *) PG_GETARG_POINTER(1);
200
PG_RETURN_BOOL(complex_abs_cmp_internal(a, b) >= 0);
203
PG_FUNCTION_INFO_V1(complex_abs_gt);
206
complex_abs_gt(PG_FUNCTION_ARGS)
208
Complex *a = (Complex *) PG_GETARG_POINTER(0);
209
Complex *b = (Complex *) PG_GETARG_POINTER(1);
211
PG_RETURN_BOOL(complex_abs_cmp_internal(a, b) > 0);
214
PG_FUNCTION_INFO_V1(complex_abs_cmp);
217
complex_abs_cmp(PG_FUNCTION_ARGS)
219
Complex *a = (Complex *) PG_GETARG_POINTER(0);
220
Complex *b = (Complex *) PG_GETARG_POINTER(1);
222
PG_RETURN_INT32(complex_abs_cmp_internal(a, b));