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));