mirror of
https://github.com/postgres/postgres.git
synced 2025-12-12 02:37:31 +03:00
The idea is to encourage more the use of these new routines across the
tree, as these offer stronger type safety guarantees than palloc().
The following paths are included in this batch, treating all the areas
proposed by the author for the most trivial changes, except src/backend
(by far the largest batch):
src/bin/
src/common/
src/fe_utils/
src/include/
src/pl/
src/test/
src/tutorial/
Similar work has been done in 31d3847a37.
The code compiles the same before and after this commit, with the
following exceptions due to changes in line numbers because some of the
new allocation formulas are shorter:
blkreftable.c
pgfnames.c
pl_exec.c
Author: David Geier <geidav.pg@gmail.com>
Discussion: https://postgr.es/m/ad0748d4-3080-436e-b0bc-ac8f86a3466a@gmail.com
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 type %s: \"%s\"",
|
|
"complex", str)));
|
|
|
|
result = palloc_object(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 = palloc_object(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 = palloc_object(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));
|
|
}
|