Fix xslt_process() to ensure that it inserts a NULL terminator after the
[PostgreSQL.git] / src / tutorial / complex.c
blobda43488db17d747a334545db4dc8750f28c0142b
1 /*
2 * $PostgreSQL$
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 ******************************************************************************/
10 #include "postgres.h"
12 #include "fmgr.h"
13 #include "libpq/pqformat.h" /* needed for send/recv functions */
16 PG_MODULE_MAGIC;
18 typedef struct Complex
20 double x;
21 double y;
22 } 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);
48 Datum
49 complex_in(PG_FUNCTION_ARGS)
51 char *str = PG_GETARG_CSTRING(0);
52 double x,
54 Complex *result;
56 if (sscanf(str, " ( %lf , %lf )", &x, &y) != 2)
57 ereport(ERROR,
58 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
59 errmsg("invalid input syntax for complex: \"%s\"",
60 str)));
62 result = (Complex *) palloc(sizeof(Complex));
63 result->x = x;
64 result->y = y;
65 PG_RETURN_POINTER(result);
68 PG_FUNCTION_INFO_V1(complex_out);
70 Datum
71 complex_out(PG_FUNCTION_ARGS)
73 Complex *complex = (Complex *) PG_GETARG_POINTER(0);
74 char *result;
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
84 * These are optional.
85 *****************************************************************************/
87 PG_FUNCTION_INFO_V1(complex_recv);
89 Datum
90 complex_recv(PG_FUNCTION_ARGS)
92 StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
93 Complex *result;
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);
103 Datum
104 complex_send(PG_FUNCTION_ARGS)
106 Complex *complex = (Complex *) PG_GETARG_POINTER(0);
107 StringInfoData buf;
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 /*****************************************************************************
116 * New Operators
118 * A practical Complex datatype would provide much more than this, of course.
119 *****************************************************************************/
121 PG_FUNCTION_INFO_V1(complex_add);
123 Datum
124 complex_add(PG_FUNCTION_ARGS)
126 Complex *a = (Complex *) PG_GETARG_POINTER(0);
127 Complex *b = (Complex *) PG_GETARG_POINTER(1);
128 Complex *result;
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)
150 static int
151 complex_abs_cmp_internal(Complex * a, Complex * b)
153 double amag = Mag(a),
154 bmag = Mag(b);
156 if (amag < bmag)
157 return -1;
158 if (amag > bmag)
159 return 1;
160 return 0;
164 PG_FUNCTION_INFO_V1(complex_abs_lt);
166 Datum
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);
177 Datum
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);
188 Datum
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);
199 Datum
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);
210 Datum
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);
221 Datum
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));