first commit for openGauss server
This commit is contained in:
213
src/common/tutorial/complex.cpp
Executable file
213
src/common/tutorial/complex.cpp
Executable file
@ -0,0 +1,213 @@
|
||||
/*
|
||||
* src/common/tutorial/complex.cpp
|
||||
*
|
||||
******************************************************************************
|
||||
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 "knl/knl_variable.h"
|
||||
|
||||
#include "fmgr.h"
|
||||
#include "libpq/pqformat.h" /* needed for send/recv functions */
|
||||
|
||||
PG_MODULE_MAGIC;
|
||||
|
||||
typedef struct Complex {
|
||||
double x;
|
||||
double y;
|
||||
} Complex;
|
||||
|
||||
/*
|
||||
* Since we use V1 function calling convention, all these functions have
|
||||
* the same signature as far as C is concerned. We provide these prototypes
|
||||
* just to forestall warnings when compiled with gcc -Wmissing-prototypes.
|
||||
*/
|
||||
Datum complex_in(PG_FUNCTION_ARGS);
|
||||
Datum complex_out(PG_FUNCTION_ARGS);
|
||||
Datum complex_recv(PG_FUNCTION_ARGS);
|
||||
Datum complex_send(PG_FUNCTION_ARGS);
|
||||
Datum complex_add(PG_FUNCTION_ARGS);
|
||||
Datum complex_abs_lt(PG_FUNCTION_ARGS);
|
||||
Datum complex_abs_le(PG_FUNCTION_ARGS);
|
||||
Datum complex_abs_eq(PG_FUNCTION_ARGS);
|
||||
Datum complex_abs_ge(PG_FUNCTION_ARGS);
|
||||
Datum complex_abs_gt(PG_FUNCTION_ARGS);
|
||||
Datum complex_abs_cmp(PG_FUNCTION_ARGS);
|
||||
|
||||
/*****************************************************************************
|
||||
* 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 = NULL;
|
||||
|
||||
if (sscanf_s(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 = NULL;
|
||||
|
||||
result = (char*)palloc(100);
|
||||
int rc = snprintf_s(result, 100, 99, "(%g,%g)", complex->x, complex->y);
|
||||
securec_check_ss(rc, "\0", "\0");
|
||||
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 = NULL;
|
||||
|
||||
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 = NULL;
|
||||
|
||||
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);
|
||||
double 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));
|
||||
}
|
||||
Reference in New Issue
Block a user