4 ******************************************************************************
5 This file contains routines that can be bound to a Postgres backend and
6 called by the backend in the process of processing queries. The calling
7 format for these routines is dictated by Postgres architecture.
8 ******************************************************************************/
13 #include "libpq/pqformat.h" /* needed for send/recv functions */
18 typedef struct Complex
25 * Since we use V1 function calling convention, all these functions have
26 * the same signature as far as C is concerned. We provide these prototypes
27 * just to forestall warnings when compiled with gcc -Wmissing-prototypes.
29 Datum
complex_in(PG_FUNCTION_ARGS
);
30 Datum
complex_out(PG_FUNCTION_ARGS
);
31 Datum
complex_recv(PG_FUNCTION_ARGS
);
32 Datum
complex_send(PG_FUNCTION_ARGS
);
33 Datum
complex_add(PG_FUNCTION_ARGS
);
34 Datum
complex_abs_lt(PG_FUNCTION_ARGS
);
35 Datum
complex_abs_le(PG_FUNCTION_ARGS
);
36 Datum
complex_abs_eq(PG_FUNCTION_ARGS
);
37 Datum
complex_abs_ge(PG_FUNCTION_ARGS
);
38 Datum
complex_abs_gt(PG_FUNCTION_ARGS
);
39 Datum
complex_abs_cmp(PG_FUNCTION_ARGS
);
42 /*****************************************************************************
43 * Input/Output functions
44 *****************************************************************************/
46 PG_FUNCTION_INFO_V1(complex_in
);
49 complex_in(PG_FUNCTION_ARGS
)
51 char *str
= PG_GETARG_CSTRING(0);
56 if (sscanf(str
, " ( %lf , %lf )", &x
, &y
) != 2)
58 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION
),
59 errmsg("invalid input syntax for complex: \"%s\"",
62 result
= (Complex
*) palloc(sizeof(Complex
));
65 PG_RETURN_POINTER(result
);
68 PG_FUNCTION_INFO_V1(complex_out
);
71 complex_out(PG_FUNCTION_ARGS
)
73 Complex
*complex = (Complex
*) PG_GETARG_POINTER(0);
76 result
= (char *) palloc(100);
77 snprintf(result
, 100, "(%g,%g)", complex->x
, complex->y
);
78 PG_RETURN_CSTRING(result
);
81 /*****************************************************************************
82 * Binary Input/Output functions
85 *****************************************************************************/
87 PG_FUNCTION_INFO_V1(complex_recv
);
90 complex_recv(PG_FUNCTION_ARGS
)
92 StringInfo buf
= (StringInfo
) PG_GETARG_POINTER(0);
95 result
= (Complex
*) palloc(sizeof(Complex
));
96 result
->x
= pq_getmsgfloat8(buf
);
97 result
->y
= pq_getmsgfloat8(buf
);
98 PG_RETURN_POINTER(result
);
101 PG_FUNCTION_INFO_V1(complex_send
);
104 complex_send(PG_FUNCTION_ARGS
)
106 Complex
*complex = (Complex
*) PG_GETARG_POINTER(0);
109 pq_begintypsend(&buf
);
110 pq_sendfloat8(&buf
, complex->x
);
111 pq_sendfloat8(&buf
, complex->y
);
112 PG_RETURN_BYTEA_P(pq_endtypsend(&buf
));
115 /*****************************************************************************
118 * A practical Complex datatype would provide much more than this, of course.
119 *****************************************************************************/
121 PG_FUNCTION_INFO_V1(complex_add
);
124 complex_add(PG_FUNCTION_ARGS
)
126 Complex
*a
= (Complex
*) PG_GETARG_POINTER(0);
127 Complex
*b
= (Complex
*) PG_GETARG_POINTER(1);
130 result
= (Complex
*) palloc(sizeof(Complex
));
131 result
->x
= a
->x
+ b
->x
;
132 result
->y
= a
->y
+ b
->y
;
133 PG_RETURN_POINTER(result
);
137 /*****************************************************************************
138 * Operator class for defining B-tree index
140 * It's essential that the comparison operators and support function for a
141 * B-tree index opclass always agree on the relative ordering of any two
142 * data values. Experience has shown that it's depressingly easy to write
143 * unintentionally inconsistent functions. One way to reduce the odds of
144 * making a mistake is to make all the functions simple wrappers around
145 * an internal three-way-comparison function, as we do here.
146 *****************************************************************************/
148 #define Mag(c) ((c)->x*(c)->x + (c)->y*(c)->y)
151 complex_abs_cmp_internal(Complex
* a
, Complex
* b
)
153 double amag
= Mag(a
),
164 PG_FUNCTION_INFO_V1(complex_abs_lt
);
167 complex_abs_lt(PG_FUNCTION_ARGS
)
169 Complex
*a
= (Complex
*) PG_GETARG_POINTER(0);
170 Complex
*b
= (Complex
*) PG_GETARG_POINTER(1);
172 PG_RETURN_BOOL(complex_abs_cmp_internal(a
, b
) < 0);
175 PG_FUNCTION_INFO_V1(complex_abs_le
);
178 complex_abs_le(PG_FUNCTION_ARGS
)
180 Complex
*a
= (Complex
*) PG_GETARG_POINTER(0);
181 Complex
*b
= (Complex
*) PG_GETARG_POINTER(1);
183 PG_RETURN_BOOL(complex_abs_cmp_internal(a
, b
) <= 0);
186 PG_FUNCTION_INFO_V1(complex_abs_eq
);
189 complex_abs_eq(PG_FUNCTION_ARGS
)
191 Complex
*a
= (Complex
*) PG_GETARG_POINTER(0);
192 Complex
*b
= (Complex
*) PG_GETARG_POINTER(1);
194 PG_RETURN_BOOL(complex_abs_cmp_internal(a
, b
) == 0);
197 PG_FUNCTION_INFO_V1(complex_abs_ge
);
200 complex_abs_ge(PG_FUNCTION_ARGS
)
202 Complex
*a
= (Complex
*) PG_GETARG_POINTER(0);
203 Complex
*b
= (Complex
*) PG_GETARG_POINTER(1);
205 PG_RETURN_BOOL(complex_abs_cmp_internal(a
, b
) >= 0);
208 PG_FUNCTION_INFO_V1(complex_abs_gt
);
211 complex_abs_gt(PG_FUNCTION_ARGS
)
213 Complex
*a
= (Complex
*) PG_GETARG_POINTER(0);
214 Complex
*b
= (Complex
*) PG_GETARG_POINTER(1);
216 PG_RETURN_BOOL(complex_abs_cmp_internal(a
, b
) > 0);
219 PG_FUNCTION_INFO_V1(complex_abs_cmp
);
222 complex_abs_cmp(PG_FUNCTION_ARGS
)
224 Complex
*a
= (Complex
*) PG_GETARG_POINTER(0);
225 Complex
*b
= (Complex
*) PG_GETARG_POINTER(1);
227 PG_RETURN_INT32(complex_abs_cmp_internal(a
, b
));