aboutsummaryrefslogtreecommitdiff
path: root/src/tutorial/complex.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tutorial/complex.c')
-rw-r--r--src/tutorial/complex.c186
1 files changed, 186 insertions, 0 deletions
diff --git a/src/tutorial/complex.c b/src/tutorial/complex.c
new file mode 100644
index 00000000000..e5bea2d1134
--- /dev/null
+++ b/src/tutorial/complex.c
@@ -0,0 +1,186 @@
+/******************************************************************************
+ This file contains routines that can be bound to a Postgres backend and
+ called by the backend in the process of processing queries. The calling
+ format for these routines is dictated by Postgres architecture.
+******************************************************************************/
+
+#include <stdio.h>
+/* do not include libpq-fe.h for backend-loaded functions*/
+/* #include "libpq-fe.h" */
+#include "postgres.h"
+#include "utils/elog.h"
+#include "utils/palloc.h"
+#include "utils/mcxt.h"
+
+typedef struct Complex
+{
+ double x;
+ double y;
+} Complex;
+
+/* These prototypes declare the requirements that Postgres places on these
+ user written functions.
+*/
+Complex *complex_in(char *str);
+char *complex_out(Complex * complex);
+Complex *complex_add(Complex * a, Complex * b);
+bool complex_abs_lt(Complex * a, Complex * b);
+bool complex_abs_le(Complex * a, Complex * b);
+bool complex_abs_eq(Complex * a, Complex * b);
+bool complex_abs_ge(Complex * a, Complex * b);
+bool complex_abs_gt(Complex * a, Complex * b);
+int4 complex_abs_cmp(Complex * a, Complex * b);
+
+
+/*****************************************************************************
+ * Input/Output functions
+ *****************************************************************************/
+
+Complex *
+complex_in(char *str)
+{
+ double x,
+ y;
+ Complex *result;
+
+ if (sscanf(str, " ( %lf , %lf )", &x, &y) != 2)
+ {
+ elog(ERROR, "complex_in: error in parsing \"%s\"", str);
+ return NULL;
+ }
+ result = (Complex *) palloc(sizeof(Complex));
+ result->x = x;
+ result->y = y;
+ return (result);
+}
+
+/*
+ * You might have noticed a slight inconsistency between the following
+ * declaration and the SQL definition:
+ * CREATE FUNCTION complex_out(opaque) RETURNS opaque ...
+ * The reason is that the argument pass into complex_out is really just a
+ * pointer. POSTGRES thinks all output functions are:
+ * char *out_func(char *);
+ */
+char *
+complex_out(Complex * complex)
+{
+ char *result;
+
+ if (complex == NULL)
+ return (NULL);
+
+ result = (char *) palloc(60);
+ sprintf(result, "(%g,%g)", complex->x, complex->y);
+ return (result);
+}
+
+/*****************************************************************************
+ * New Operators
+ *****************************************************************************/
+
+Complex *
+complex_add(Complex * a, Complex * b)
+{
+ Complex *result;
+
+ result = (Complex *) palloc(sizeof(Complex));
+ result->x = a->x + b->x;
+ result->y = a->y + b->y;
+ return (result);
+}
+
+
+/*****************************************************************************
+ * Operator class for defining B-tree index
+ *****************************************************************************/
+
+#define Mag(c) ((c)->x*(c)->x + (c)->y*(c)->y)
+
+bool
+complex_abs_lt(Complex * a, Complex * b)
+{
+ double amag = Mag(a),
+ bmag = Mag(b);
+
+ return (amag < bmag);
+}
+
+bool
+complex_abs_le(Complex * a, Complex * b)
+{
+ double amag = Mag(a),
+ bmag = Mag(b);
+
+ return (amag <= bmag);
+}
+
+bool
+complex_abs_eq(Complex * a, Complex * b)
+{
+ double amag = Mag(a),
+ bmag = Mag(b);
+
+ return (amag == bmag);
+}
+
+bool
+complex_abs_ge(Complex * a, Complex * b)
+{
+ double amag = Mag(a),
+ bmag = Mag(b);
+
+ return (amag >= bmag);
+}
+
+bool
+complex_abs_gt(Complex * a, Complex * b)
+{
+ double amag = Mag(a),
+ bmag = Mag(b);
+
+ return (amag > bmag);
+}
+
+int4
+complex_abs_cmp(Complex * a, Complex * b)
+{
+ double amag = Mag(a),
+ bmag = Mag(b);
+
+ if (amag < bmag)
+ return -1;
+ else if (amag > bmag)
+ return 1;
+ else
+ return 0;
+}
+
+/*****************************************************************************
+ * test code
+ *****************************************************************************/
+
+/*
+ * You should always test your code separately. Trust me, using POSTGRES to
+ * debug your C function will be very painful and unproductive. In case of
+ * POSTGRES crashing, it is impossible to tell whether the bug is in your
+ * code or POSTGRES's.
+ */
+void test_main(void);
+void
+test_main()
+{
+ Complex *a;
+ Complex *b;
+
+ a = complex_in("(4.01, 3.77 )");
+ printf("a = %s\n", complex_out(a));
+ b = complex_in("(1.0,2.0)");
+ printf("b = %s\n", complex_out(b));
+ printf("a + b = %s\n", complex_out(complex_add(a, b)));
+ printf("a < b = %d\n", complex_abs_lt(a, b));
+ printf("a <= b = %d\n", complex_abs_le(a, b));
+ printf("a = b = %d\n", complex_abs_eq(a, b));
+ printf("a >= b = %d\n", complex_abs_ge(a, b));
+ printf("a > b = %d\n", complex_abs_gt(a, b));
+}