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 */
15 typedef struct Complex
22 * Since we use V1 function calling convention, all these functions have
23 * the same signature as far as C is concerned. We provide these prototypes
24 * just to forestall warnings when compiled with gcc -Wmissing-prototypes.
26 Datum complex_in(PG_FUNCTION_ARGS);
27 Datum complex_out(PG_FUNCTION_ARGS);
28 Datum complex_recv(PG_FUNCTION_ARGS);
29 Datum complex_send(PG_FUNCTION_ARGS);
30 Datum complex_add(PG_FUNCTION_ARGS);
31 Datum complex_abs_lt(PG_FUNCTION_ARGS);
32 Datum complex_abs_le(PG_FUNCTION_ARGS);
33 Datum complex_abs_eq(PG_FUNCTION_ARGS);
34 Datum complex_abs_ge(PG_FUNCTION_ARGS);
35 Datum complex_abs_gt(PG_FUNCTION_ARGS);
36 Datum complex_abs_cmp(PG_FUNCTION_ARGS);
39 /*****************************************************************************
40 * Input/Output functions
41 *****************************************************************************/
43 PG_FUNCTION_INFO_V1(complex_in);
46 complex_in(PG_FUNCTION_ARGS)
48 char *str = PG_GETARG_CSTRING(0);
53 if (sscanf(str, " ( %lf , %lf )", &x, &y) != 2)
55 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
56 errmsg("invalid input syntax for complex: \"%s\"",
59 result = (Complex *) palloc(sizeof(Complex));
62 PG_RETURN_POINTER(result);
65 PG_FUNCTION_INFO_V1(complex_out);
68 complex_out(PG_FUNCTION_ARGS)
70 Complex *complex = (Complex *) PG_GETARG_POINTER(0);
73 result = (char *) palloc(100);
74 snprintf(result, 100, "(%g,%g)", complex->x, complex->y);
75 PG_RETURN_CSTRING(result);
78 /*****************************************************************************
79 * Binary Input/Output functions
82 *****************************************************************************/
84 PG_FUNCTION_INFO_V1(complex_recv);
87 complex_recv(PG_FUNCTION_ARGS)
89 StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
92 result = (Complex *) palloc(sizeof(Complex));
93 result->x = pq_getmsgfloat8(buf);
94 result->y = pq_getmsgfloat8(buf);
95 PG_RETURN_POINTER(result);
98 PG_FUNCTION_INFO_V1(complex_send);
101 complex_send(PG_FUNCTION_ARGS)
103 Complex *complex = (Complex *) PG_GETARG_POINTER(0);
106 pq_begintypsend(&buf);
107 pq_sendfloat8(&buf, complex->x);
108 pq_sendfloat8(&buf, complex->y);
109 PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
112 /*****************************************************************************
115 * A practical Complex datatype would provide much more than this, of course.
116 *****************************************************************************/
118 PG_FUNCTION_INFO_V1(complex_add);
121 complex_add(PG_FUNCTION_ARGS)
123 Complex *a = (Complex *) PG_GETARG_POINTER(0);
124 Complex *b = (Complex *) PG_GETARG_POINTER(1);
127 result = (Complex *) palloc(sizeof(Complex));
128 result->x = a->x + b->x;
129 result->y = a->y + b->y;
130 PG_RETURN_POINTER(result);
134 /*****************************************************************************
135 * Operator class for defining B-tree index
137 * It's essential that the comparison operators and support function for a
138 * B-tree index opclass always agree on the relative ordering of any two
139 * data values. Experience has shown that it's depressingly easy to write
140 * unintentionally inconsistent functions. One way to reduce the odds of
141 * making a mistake is to make all the functions simple wrappers around
142 * an internal three-way-comparison function, as we do here.
143 *****************************************************************************/
145 #define Mag(c) ((c)->x*(c)->x + (c)->y*(c)->y)
148 complex_abs_cmp_internal(Complex * a, Complex * b)
150 double amag = Mag(a),
161 PG_FUNCTION_INFO_V1(complex_abs_lt);
164 complex_abs_lt(PG_FUNCTION_ARGS)
166 Complex *a = (Complex *) PG_GETARG_POINTER(0);
167 Complex *b = (Complex *) PG_GETARG_POINTER(1);
169 PG_RETURN_BOOL(complex_abs_cmp_internal(a, b) < 0);
172 PG_FUNCTION_INFO_V1(complex_abs_le);
175 complex_abs_le(PG_FUNCTION_ARGS)
177 Complex *a = (Complex *) PG_GETARG_POINTER(0);
178 Complex *b = (Complex *) PG_GETARG_POINTER(1);
180 PG_RETURN_BOOL(complex_abs_cmp_internal(a, b) <= 0);
183 PG_FUNCTION_INFO_V1(complex_abs_eq);
186 complex_abs_eq(PG_FUNCTION_ARGS)
188 Complex *a = (Complex *) PG_GETARG_POINTER(0);
189 Complex *b = (Complex *) PG_GETARG_POINTER(1);
191 PG_RETURN_BOOL(complex_abs_cmp_internal(a, b) == 0);
194 PG_FUNCTION_INFO_V1(complex_abs_ge);
197 complex_abs_ge(PG_FUNCTION_ARGS)
199 Complex *a = (Complex *) PG_GETARG_POINTER(0);
200 Complex *b = (Complex *) PG_GETARG_POINTER(1);
202 PG_RETURN_BOOL(complex_abs_cmp_internal(a, b) >= 0);
205 PG_FUNCTION_INFO_V1(complex_abs_gt);
208 complex_abs_gt(PG_FUNCTION_ARGS)
210 Complex *a = (Complex *) PG_GETARG_POINTER(0);
211 Complex *b = (Complex *) PG_GETARG_POINTER(1);
213 PG_RETURN_BOOL(complex_abs_cmp_internal(a, b) > 0);
216 PG_FUNCTION_INFO_V1(complex_abs_cmp);
219 complex_abs_cmp(PG_FUNCTION_ARGS)
221 Complex *a = (Complex *) PG_GETARG_POINTER(0);
222 Complex *b = (Complex *) PG_GETARG_POINTER(1);
224 PG_RETURN_INT32(complex_abs_cmp_internal(a, b));