postgres/src/tutorial/complex.c
Marc G. Fournier 207acd86d7 From: Darren King <darrenk@insightdist.com>
1. Make 'all' works without complaint.  Don't have to add the .exp
   files to the files list.  They are made automagically when
   making the respective shared lib file.

   Only port that actually uses EXPSUFF (from makefiles/Makefile.*)
   is Aix, so if this breaks anybody else, let me know, asap.

2. Make 'clean' actually cleans up correctly.  Previously, it would
   leave the .o files in C-code directory.

3. Changed references to reflect new location of .c files.

4. Added DELETE statements to complex.source so that it tidies up
   when done.  Previously, it would leave things in pg_amop,
   pg_amproc and pg_opclass.  Only possible to do this with the
   new SUBSELECT code in 6.3.  Nice work, fellas...

   Not deleting the index entries would cause a non-fatal error if
   complex.sql was run again on the same database.  Much tidier now.

5. Corrected the README.  obj directory hasn't existed since Bryan
   redid the make way back when.  Also changed the snipet from psql
   to match the current version. POSTGRES95?!?  I don't think so. :)
1998-03-01 04:52:59 +00:00

185 lines
4.4 KiB
C

/******************************************************************************
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/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));
}