mirror of
https://github.com/postgres/postgres.git
synced 2025-05-06 19:59:18 +03:00
Previously a lot of the error messages referenced the type in the error message itself. That requires that the message is translated separately for each type. Note that currently a few smallint cases continue to reference the integer, rather than smallint, type. A later patch will create a separate routine for 16bit input. Author: Andres Freund Discussion: https://postgr.es/m/20180707200158.wpqkd7rjr4jxq5g7@alap3.anarazel.de
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 = (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));
|
|
}
|