mirror of
https://github.com/postgres/postgres.git
synced 2025-05-09 18:21:05 +03:00
Remove a bunch of "extern Datum foo(PG_FUNCTION_ARGS);" declarations that are no longer needed now that PG_FUNCTION_INFO_V1(foo) provides that. Some of these were evidently missed in commit e7128e8dbb305059, but others were cargo-culted in in code added since then. Possibly that can be blamed in part on the fact that we'd not fixed relevant documentation examples, which I've now done.
210 lines
5.0 KiB
C
210 lines
5.0 KiB
C
/*
|
|
* src/tutorial/complex.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 "postgres.h"
|
|
|
|
#include "fmgr.h"
|
|
#include "libpq/pqformat.h" /* needed for send/recv functions */
|
|
|
|
PG_MODULE_MAGIC;
|
|
|
|
typedef struct Complex
|
|
{
|
|
double x;
|
|
double y;
|
|
} Complex;
|
|
|
|
|
|
/*****************************************************************************
|
|
* Input/Output functions
|
|
*****************************************************************************/
|
|
|
|
PG_FUNCTION_INFO_V1(complex_in);
|
|
|
|
Datum
|
|
complex_in(PG_FUNCTION_ARGS)
|
|
{
|
|
char *str = PG_GETARG_CSTRING(0);
|
|
double x,
|
|
y;
|
|
Complex *result;
|
|
|
|
if (sscanf(str, " ( %lf , %lf )", &x, &y) != 2)
|
|
ereport(ERROR,
|
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
|
errmsg("invalid input syntax for complex: \"%s\"",
|
|
str)));
|
|
|
|
result = (Complex *) palloc(sizeof(Complex));
|
|
result->x = x;
|
|
result->y = y;
|
|
PG_RETURN_POINTER(result);
|
|
}
|
|
|
|
PG_FUNCTION_INFO_V1(complex_out);
|
|
|
|
Datum
|
|
complex_out(PG_FUNCTION_ARGS)
|
|
{
|
|
Complex *complex = (Complex *) PG_GETARG_POINTER(0);
|
|
char *result;
|
|
|
|
result = psprintf("(%g,%g)", complex->x, complex->y);
|
|
PG_RETURN_CSTRING(result);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Binary Input/Output functions
|
|
*
|
|
* These are optional.
|
|
*****************************************************************************/
|
|
|
|
PG_FUNCTION_INFO_V1(complex_recv);
|
|
|
|
Datum
|
|
complex_recv(PG_FUNCTION_ARGS)
|
|
{
|
|
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
|
|
Complex *result;
|
|
|
|
result = (Complex *) palloc(sizeof(Complex));
|
|
result->x = pq_getmsgfloat8(buf);
|
|
result->y = pq_getmsgfloat8(buf);
|
|
PG_RETURN_POINTER(result);
|
|
}
|
|
|
|
PG_FUNCTION_INFO_V1(complex_send);
|
|
|
|
Datum
|
|
complex_send(PG_FUNCTION_ARGS)
|
|
{
|
|
Complex *complex = (Complex *) PG_GETARG_POINTER(0);
|
|
StringInfoData buf;
|
|
|
|
pq_begintypsend(&buf);
|
|
pq_sendfloat8(&buf, complex->x);
|
|
pq_sendfloat8(&buf, complex->y);
|
|
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* New Operators
|
|
*
|
|
* A practical Complex datatype would provide much more than this, of course.
|
|
*****************************************************************************/
|
|
|
|
PG_FUNCTION_INFO_V1(complex_add);
|
|
|
|
Datum
|
|
complex_add(PG_FUNCTION_ARGS)
|
|
{
|
|
Complex *a = (Complex *) PG_GETARG_POINTER(0);
|
|
Complex *b = (Complex *) PG_GETARG_POINTER(1);
|
|
Complex *result;
|
|
|
|
result = (Complex *) palloc(sizeof(Complex));
|
|
result->x = a->x + b->x;
|
|
result->y = a->y + b->y;
|
|
PG_RETURN_POINTER(result);
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
* Operator class for defining B-tree index
|
|
*
|
|
* It's essential that the comparison operators and support function for a
|
|
* B-tree index opclass always agree on the relative ordering of any two
|
|
* data values. Experience has shown that it's depressingly easy to write
|
|
* unintentionally inconsistent functions. One way to reduce the odds of
|
|
* making a mistake is to make all the functions simple wrappers around
|
|
* an internal three-way-comparison function, as we do here.
|
|
*****************************************************************************/
|
|
|
|
#define Mag(c) ((c)->x*(c)->x + (c)->y*(c)->y)
|
|
|
|
static int
|
|
complex_abs_cmp_internal(Complex * a, Complex * b)
|
|
{
|
|
double amag = Mag(a),
|
|
bmag = Mag(b);
|
|
|
|
if (amag < bmag)
|
|
return -1;
|
|
if (amag > bmag)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
|
|
PG_FUNCTION_INFO_V1(complex_abs_lt);
|
|
|
|
Datum
|
|
complex_abs_lt(PG_FUNCTION_ARGS)
|
|
{
|
|
Complex *a = (Complex *) PG_GETARG_POINTER(0);
|
|
Complex *b = (Complex *) PG_GETARG_POINTER(1);
|
|
|
|
PG_RETURN_BOOL(complex_abs_cmp_internal(a, b) < 0);
|
|
}
|
|
|
|
PG_FUNCTION_INFO_V1(complex_abs_le);
|
|
|
|
Datum
|
|
complex_abs_le(PG_FUNCTION_ARGS)
|
|
{
|
|
Complex *a = (Complex *) PG_GETARG_POINTER(0);
|
|
Complex *b = (Complex *) PG_GETARG_POINTER(1);
|
|
|
|
PG_RETURN_BOOL(complex_abs_cmp_internal(a, b) <= 0);
|
|
}
|
|
|
|
PG_FUNCTION_INFO_V1(complex_abs_eq);
|
|
|
|
Datum
|
|
complex_abs_eq(PG_FUNCTION_ARGS)
|
|
{
|
|
Complex *a = (Complex *) PG_GETARG_POINTER(0);
|
|
Complex *b = (Complex *) PG_GETARG_POINTER(1);
|
|
|
|
PG_RETURN_BOOL(complex_abs_cmp_internal(a, b) == 0);
|
|
}
|
|
|
|
PG_FUNCTION_INFO_V1(complex_abs_ge);
|
|
|
|
Datum
|
|
complex_abs_ge(PG_FUNCTION_ARGS)
|
|
{
|
|
Complex *a = (Complex *) PG_GETARG_POINTER(0);
|
|
Complex *b = (Complex *) PG_GETARG_POINTER(1);
|
|
|
|
PG_RETURN_BOOL(complex_abs_cmp_internal(a, b) >= 0);
|
|
}
|
|
|
|
PG_FUNCTION_INFO_V1(complex_abs_gt);
|
|
|
|
Datum
|
|
complex_abs_gt(PG_FUNCTION_ARGS)
|
|
{
|
|
Complex *a = (Complex *) PG_GETARG_POINTER(0);
|
|
Complex *b = (Complex *) PG_GETARG_POINTER(1);
|
|
|
|
PG_RETURN_BOOL(complex_abs_cmp_internal(a, b) > 0);
|
|
}
|
|
|
|
PG_FUNCTION_INFO_V1(complex_abs_cmp);
|
|
|
|
Datum
|
|
complex_abs_cmp(PG_FUNCTION_ARGS)
|
|
{
|
|
Complex *a = (Complex *) PG_GETARG_POINTER(0);
|
|
Complex *b = (Complex *) PG_GETARG_POINTER(1);
|
|
|
|
PG_RETURN_INT32(complex_abs_cmp_internal(a, b));
|
|
}
|