2 * src/tutorial/complex.c
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 */
17 typedef struct Complex
24 /*****************************************************************************
25 * Input/Output functions
26 *****************************************************************************/
28 PG_FUNCTION_INFO_V1(complex_in
);
31 complex_in(PG_FUNCTION_ARGS
)
33 char *str
= PG_GETARG_CSTRING(0);
38 if (sscanf(str
, " ( %lf , %lf )", &x
, &y
) != 2)
40 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION
),
41 errmsg("invalid input syntax for type %s: \"%s\"",
44 result
= (Complex
*) palloc(sizeof(Complex
));
47 PG_RETURN_POINTER(result
);
50 PG_FUNCTION_INFO_V1(complex_out
);
53 complex_out(PG_FUNCTION_ARGS
)
55 Complex
*complex = (Complex
*) PG_GETARG_POINTER(0);
58 result
= psprintf("(%g,%g)", complex->x
, complex->y
);
59 PG_RETURN_CSTRING(result
);
62 /*****************************************************************************
63 * Binary Input/Output functions
66 *****************************************************************************/
68 PG_FUNCTION_INFO_V1(complex_recv
);
71 complex_recv(PG_FUNCTION_ARGS
)
73 StringInfo buf
= (StringInfo
) PG_GETARG_POINTER(0);
76 result
= (Complex
*) palloc(sizeof(Complex
));
77 result
->x
= pq_getmsgfloat8(buf
);
78 result
->y
= pq_getmsgfloat8(buf
);
79 PG_RETURN_POINTER(result
);
82 PG_FUNCTION_INFO_V1(complex_send
);
85 complex_send(PG_FUNCTION_ARGS
)
87 Complex
*complex = (Complex
*) PG_GETARG_POINTER(0);
90 pq_begintypsend(&buf
);
91 pq_sendfloat8(&buf
, complex->x
);
92 pq_sendfloat8(&buf
, complex->y
);
93 PG_RETURN_BYTEA_P(pq_endtypsend(&buf
));
96 /*****************************************************************************
99 * A practical Complex datatype would provide much more than this, of course.
100 *****************************************************************************/
102 PG_FUNCTION_INFO_V1(complex_add
);
105 complex_add(PG_FUNCTION_ARGS
)
107 Complex
*a
= (Complex
*) PG_GETARG_POINTER(0);
108 Complex
*b
= (Complex
*) PG_GETARG_POINTER(1);
111 result
= (Complex
*) palloc(sizeof(Complex
));
112 result
->x
= a
->x
+ b
->x
;
113 result
->y
= a
->y
+ b
->y
;
114 PG_RETURN_POINTER(result
);
118 /*****************************************************************************
119 * Operator class for defining B-tree index
121 * It's essential that the comparison operators and support function for a
122 * B-tree index opclass always agree on the relative ordering of any two
123 * data values. Experience has shown that it's depressingly easy to write
124 * unintentionally inconsistent functions. One way to reduce the odds of
125 * making a mistake is to make all the functions simple wrappers around
126 * an internal three-way-comparison function, as we do here.
127 *****************************************************************************/
129 #define Mag(c) ((c)->x*(c)->x + (c)->y*(c)->y)
132 complex_abs_cmp_internal(Complex
* a
, Complex
* b
)
134 double amag
= Mag(a
),
145 PG_FUNCTION_INFO_V1(complex_abs_lt
);
148 complex_abs_lt(PG_FUNCTION_ARGS
)
150 Complex
*a
= (Complex
*) PG_GETARG_POINTER(0);
151 Complex
*b
= (Complex
*) PG_GETARG_POINTER(1);
153 PG_RETURN_BOOL(complex_abs_cmp_internal(a
, b
) < 0);
156 PG_FUNCTION_INFO_V1(complex_abs_le
);
159 complex_abs_le(PG_FUNCTION_ARGS
)
161 Complex
*a
= (Complex
*) PG_GETARG_POINTER(0);
162 Complex
*b
= (Complex
*) PG_GETARG_POINTER(1);
164 PG_RETURN_BOOL(complex_abs_cmp_internal(a
, b
) <= 0);
167 PG_FUNCTION_INFO_V1(complex_abs_eq
);
170 complex_abs_eq(PG_FUNCTION_ARGS
)
172 Complex
*a
= (Complex
*) PG_GETARG_POINTER(0);
173 Complex
*b
= (Complex
*) PG_GETARG_POINTER(1);
175 PG_RETURN_BOOL(complex_abs_cmp_internal(a
, b
) == 0);
178 PG_FUNCTION_INFO_V1(complex_abs_ge
);
181 complex_abs_ge(PG_FUNCTION_ARGS
)
183 Complex
*a
= (Complex
*) PG_GETARG_POINTER(0);
184 Complex
*b
= (Complex
*) PG_GETARG_POINTER(1);
186 PG_RETURN_BOOL(complex_abs_cmp_internal(a
, b
) >= 0);
189 PG_FUNCTION_INFO_V1(complex_abs_gt
);
192 complex_abs_gt(PG_FUNCTION_ARGS
)
194 Complex
*a
= (Complex
*) PG_GETARG_POINTER(0);
195 Complex
*b
= (Complex
*) PG_GETARG_POINTER(1);
197 PG_RETURN_BOOL(complex_abs_cmp_internal(a
, b
) > 0);
200 PG_FUNCTION_INFO_V1(complex_abs_cmp
);
203 complex_abs_cmp(PG_FUNCTION_ARGS
)
205 Complex
*a
= (Complex
*) PG_GETARG_POINTER(0);
206 Complex
*b
= (Complex
*) PG_GETARG_POINTER(1);
208 PG_RETURN_INT32(complex_abs_cmp_internal(a
, b
));