diff options
Diffstat (limited to 'contrib/btree_gist')
-rw-r--r-- | contrib/btree_gist/Makefile | 11 | ||||
-rw-r--r-- | contrib/btree_gist/btree_gist--1.3--1.4.sql | 64 | ||||
-rw-r--r-- | contrib/btree_gist/btree_gist.control | 2 | ||||
-rw-r--r-- | contrib/btree_gist/btree_gist.h | 1 | ||||
-rw-r--r-- | contrib/btree_gist/btree_macaddr8.c | 200 | ||||
-rw-r--r-- | contrib/btree_gist/expected/macaddr8.out | 89 | ||||
-rw-r--r-- | contrib/btree_gist/sql/macaddr8.sql | 37 |
7 files changed, 398 insertions, 6 deletions
diff --git a/contrib/btree_gist/Makefile b/contrib/btree_gist/Makefile index d36f51795d0..c70f17869a2 100644 --- a/contrib/btree_gist/Makefile +++ b/contrib/btree_gist/Makefile @@ -5,17 +5,18 @@ MODULE_big = btree_gist OBJS = btree_gist.o btree_utils_num.o btree_utils_var.o btree_int2.o \ btree_int4.o btree_int8.o btree_float4.o btree_float8.o btree_cash.o \ btree_oid.o btree_ts.o btree_time.o btree_date.o btree_interval.o \ - btree_macaddr.o btree_inet.o btree_text.o btree_bytea.o btree_bit.o \ - btree_numeric.o btree_uuid.o $(WIN32RES) + btree_macaddr.o btree_macaddr8.o btree_inet.o btree_text.o btree_bytea.o \ + btree_bit.o btree_numeric.o btree_uuid.o $(WIN32RES) EXTENSION = btree_gist DATA = btree_gist--unpackaged--1.0.sql btree_gist--1.0--1.1.sql \ - btree_gist--1.1--1.2.sql btree_gist--1.2.sql btree_gist--1.2--1.3.sql + btree_gist--1.1--1.2.sql btree_gist--1.2.sql btree_gist--1.2--1.3.sql \ + btree_gist--1.3--1.4.sql PGFILEDESC = "btree_gist - B-tree equivalent GiST operator classes" REGRESS = init int2 int4 int8 float4 float8 cash oid timestamp timestamptz \ - time timetz date interval macaddr inet cidr text varchar char bytea \ - bit varbit numeric uuid not_equal + time timetz date interval macaddr macaddr8 inet cidr text varchar char \ + bytea bit varbit numeric uuid not_equal SHLIB_LINK += $(filter -lm, $(LIBS)) diff --git a/contrib/btree_gist/btree_gist--1.3--1.4.sql b/contrib/btree_gist/btree_gist--1.3--1.4.sql new file mode 100644 index 00000000000..f77f6c8380b --- /dev/null +++ b/contrib/btree_gist/btree_gist--1.3--1.4.sql @@ -0,0 +1,64 @@ +/* contrib/btree_gist/btree_gist--1.3--1.4.sql */ + +-- complain if script is sourced in psql, rather than via ALTER EXTENSION +\echo Use "ALTER EXTENSION btree_gist UPDATE TO '1.4'" to load this file. \quit + +-- Add support for indexing macaddr8 columns + +-- define the GiST support methods +CREATE FUNCTION gbt_macad8_consistent(internal,macaddr8,int2,oid,internal) +RETURNS bool +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION gbt_macad8_compress(internal) +RETURNS internal +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION gbt_macad8_fetch(internal) +RETURNS internal +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION gbt_macad8_penalty(internal,internal,internal) +RETURNS internal +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION gbt_macad8_picksplit(internal, internal) +RETURNS internal +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION gbt_macad8_union(internal, internal) +RETURNS gbtreekey16 +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION gbt_macad8_same(gbtreekey16, gbtreekey16, internal) +RETURNS internal +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE STRICT; + +-- Create the operator class +CREATE OPERATOR CLASS gist_macaddr8_ops +DEFAULT FOR TYPE macaddr8 USING gist +AS + OPERATOR 1 < , + OPERATOR 2 <= , + OPERATOR 3 = , + OPERATOR 4 >= , + OPERATOR 5 > , + FUNCTION 1 gbt_macad8_consistent (internal, macaddr8, int2, oid, internal), + FUNCTION 2 gbt_macad8_union (internal, internal), + FUNCTION 3 gbt_macad8_compress (internal), + FUNCTION 4 gbt_decompress (internal), + FUNCTION 5 gbt_macad8_penalty (internal, internal, internal), + FUNCTION 6 gbt_macad8_picksplit (internal, internal), + FUNCTION 7 gbt_macad8_same (gbtreekey16, gbtreekey16, internal), + STORAGE gbtreekey16; + +ALTER OPERATOR FAMILY gist_macaddr8_ops USING gist ADD + OPERATOR 6 <> (macaddr8, macaddr8) , + FUNCTION 9 (macaddr8, macaddr8) gbt_macad8_fetch (internal); diff --git a/contrib/btree_gist/btree_gist.control b/contrib/btree_gist/btree_gist.control index ddbf83dc32f..fdf0e6ad9ee 100644 --- a/contrib/btree_gist/btree_gist.control +++ b/contrib/btree_gist/btree_gist.control @@ -1,5 +1,5 @@ # btree_gist extension comment = 'support for indexing common datatypes in GiST' -default_version = '1.3' +default_version = '1.4' module_pathname = '$libdir/btree_gist' relocatable = true diff --git a/contrib/btree_gist/btree_gist.h b/contrib/btree_gist/btree_gist.h index 9b3e22c4692..f759299bb2d 100644 --- a/contrib/btree_gist/btree_gist.h +++ b/contrib/btree_gist/btree_gist.h @@ -27,6 +27,7 @@ enum gbtree_type gbt_t_date, gbt_t_intv, gbt_t_macad, + gbt_t_macad8, gbt_t_text, gbt_t_bpchar, gbt_t_bytea, diff --git a/contrib/btree_gist/btree_macaddr8.c b/contrib/btree_gist/btree_macaddr8.c new file mode 100644 index 00000000000..13238efe328 --- /dev/null +++ b/contrib/btree_gist/btree_macaddr8.c @@ -0,0 +1,200 @@ +/* + * contrib/btree_gist/btree_macaddr8.c + */ +#include "postgres.h" + +#include "btree_gist.h" +#include "btree_utils_num.h" +#include "utils/builtins.h" +#include "utils/inet.h" + +typedef struct +{ + macaddr8 lower; + macaddr8 upper; + /* make struct size = sizeof(gbtreekey16) */ +} mac8KEY; + +/* +** OID ops +*/ +PG_FUNCTION_INFO_V1(gbt_macad8_compress); +PG_FUNCTION_INFO_V1(gbt_macad8_fetch); +PG_FUNCTION_INFO_V1(gbt_macad8_union); +PG_FUNCTION_INFO_V1(gbt_macad8_picksplit); +PG_FUNCTION_INFO_V1(gbt_macad8_consistent); +PG_FUNCTION_INFO_V1(gbt_macad8_penalty); +PG_FUNCTION_INFO_V1(gbt_macad8_same); + + +static bool +gbt_macad8gt(const void *a, const void *b) +{ + return DatumGetBool(DirectFunctionCall2(macaddr8_gt, PointerGetDatum(a), PointerGetDatum(b))); +} +static bool +gbt_macad8ge(const void *a, const void *b) +{ + return DatumGetBool(DirectFunctionCall2(macaddr8_ge, PointerGetDatum(a), PointerGetDatum(b))); +} + +static bool +gbt_macad8eq(const void *a, const void *b) +{ + return DatumGetBool(DirectFunctionCall2(macaddr8_eq, PointerGetDatum(a), PointerGetDatum(b))); +} + +static bool +gbt_macad8le(const void *a, const void *b) +{ + return DatumGetBool(DirectFunctionCall2(macaddr8_le, PointerGetDatum(a), PointerGetDatum(b))); +} + +static bool +gbt_macad8lt(const void *a, const void *b) +{ + return DatumGetBool(DirectFunctionCall2(macaddr8_lt, PointerGetDatum(a), PointerGetDatum(b))); +} + + +static int +gbt_macad8key_cmp(const void *a, const void *b) +{ + mac8KEY *ia = (mac8KEY *) (((const Nsrt *) a)->t); + mac8KEY *ib = (mac8KEY *) (((const Nsrt *) b)->t); + int res; + + res = DatumGetInt32(DirectFunctionCall2(macaddr8_cmp, Macaddr8PGetDatum(&ia->lower), Macaddr8PGetDatum(&ib->lower))); + if (res == 0) + return DatumGetInt32(DirectFunctionCall2(macaddr8_cmp, Macaddr8PGetDatum(&ia->upper), Macaddr8PGetDatum(&ib->upper))); + + return res; +} + + +static const gbtree_ninfo tinfo = +{ + gbt_t_macad8, + sizeof(macaddr8), + 16, /* sizeof(gbtreekey16) */ + gbt_macad8gt, + gbt_macad8ge, + gbt_macad8eq, + gbt_macad8le, + gbt_macad8lt, + gbt_macad8key_cmp, + NULL +}; + + +/************************************************** + * macaddr ops + **************************************************/ + + + +static uint64 +mac8_2_uint64(macaddr8 *m) +{ + unsigned char *mi = (unsigned char *) m; + uint64 res = 0; + int i; + + for (i = 0; i < 8; i++) + res += (((uint64) mi[i]) << ((uint64) ((7 - i) * 8))); + return res; +} + + + +Datum +gbt_macad8_compress(PG_FUNCTION_ARGS) +{ + GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); + + PG_RETURN_POINTER(gbt_num_compress(entry, &tinfo)); +} + +Datum +gbt_macad8_fetch(PG_FUNCTION_ARGS) +{ + GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); + + PG_RETURN_POINTER(gbt_num_fetch(entry, &tinfo)); +} + +Datum +gbt_macad8_consistent(PG_FUNCTION_ARGS) +{ + GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); + macaddr8 *query = (macaddr8 *) PG_GETARG_POINTER(1); + StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2); + + /* Oid subtype = PG_GETARG_OID(3); */ + bool *recheck = (bool *) PG_GETARG_POINTER(4); + mac8KEY *kkk = (mac8KEY *) DatumGetPointer(entry->key); + GBT_NUMKEY_R key; + + /* All cases served by this function are exact */ + *recheck = false; + + key.lower = (GBT_NUMKEY *) &kkk->lower; + key.upper = (GBT_NUMKEY *) &kkk->upper; + + PG_RETURN_BOOL( + gbt_num_consistent(&key, (void *) query, &strategy, GIST_LEAF(entry), &tinfo) + ); +} + + +Datum +gbt_macad8_union(PG_FUNCTION_ARGS) +{ + GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0); + void *out = palloc0(sizeof(mac8KEY)); + + *(int *) PG_GETARG_POINTER(1) = sizeof(mac8KEY); + PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo)); +} + + +Datum +gbt_macad8_penalty(PG_FUNCTION_ARGS) +{ + mac8KEY *origentry = (mac8KEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key); + mac8KEY *newentry = (mac8KEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key); + float *result = (float *) PG_GETARG_POINTER(2); + uint64 iorg[2], + inew[2]; + + iorg[0] = mac8_2_uint64(&origentry->lower); + iorg[1] = mac8_2_uint64(&origentry->upper); + inew[0] = mac8_2_uint64(&newentry->lower); + inew[1] = mac8_2_uint64(&newentry->upper); + + penalty_num(result, iorg[0], iorg[1], inew[0], inew[1]); + + PG_RETURN_POINTER(result); + +} + +Datum +gbt_macad8_picksplit(PG_FUNCTION_ARGS) +{ + PG_RETURN_POINTER(gbt_num_picksplit( + (GistEntryVector *) PG_GETARG_POINTER(0), + (GIST_SPLITVEC *) PG_GETARG_POINTER(1), + &tinfo + )); +} + +Datum +gbt_macad8_same(PG_FUNCTION_ARGS) +{ + mac8KEY *b1 = (mac8KEY *) PG_GETARG_POINTER(0); + mac8KEY *b2 = (mac8KEY *) PG_GETARG_POINTER(1); + bool *result = (bool *) PG_GETARG_POINTER(2); + + *result = gbt_num_same((void *) b1, (void *) b2, &tinfo); + PG_RETURN_POINTER(result); +} diff --git a/contrib/btree_gist/expected/macaddr8.out b/contrib/btree_gist/expected/macaddr8.out new file mode 100644 index 00000000000..e5ec6a5deab --- /dev/null +++ b/contrib/btree_gist/expected/macaddr8.out @@ -0,0 +1,89 @@ +-- macaddr check +CREATE TABLE macaddr8tmp (a macaddr8); +\copy macaddr8tmp from 'data/macaddr.data' +SET enable_seqscan=on; +SELECT count(*) FROM macaddr8tmp WHERE a < '22:00:5c:e5:9b:0d'; + count +------- + 56 +(1 row) + +SELECT count(*) FROM macaddr8tmp WHERE a <= '22:00:5c:e5:9b:0d'; + count +------- + 60 +(1 row) + +SELECT count(*) FROM macaddr8tmp WHERE a = '22:00:5c:e5:9b:0d'; + count +------- + 4 +(1 row) + +SELECT count(*) FROM macaddr8tmp WHERE a >= '22:00:5c:e5:9b:0d'; + count +------- + 544 +(1 row) + +SELECT count(*) FROM macaddr8tmp WHERE a > '22:00:5c:e5:9b:0d'; + count +------- + 540 +(1 row) + +CREATE INDEX macaddr8idx ON macaddr8tmp USING gist ( a ); +SET enable_seqscan=off; +SELECT count(*) FROM macaddr8tmp WHERE a < '22:00:5c:e5:9b:0d'::macaddr8; + count +------- + 56 +(1 row) + +SELECT count(*) FROM macaddr8tmp WHERE a <= '22:00:5c:e5:9b:0d'::macaddr8; + count +------- + 60 +(1 row) + +SELECT count(*) FROM macaddr8tmp WHERE a = '22:00:5c:e5:9b:0d'::macaddr8; + count +------- + 4 +(1 row) + +SELECT count(*) FROM macaddr8tmp WHERE a >= '22:00:5c:e5:9b:0d'::macaddr8; + count +------- + 544 +(1 row) + +SELECT count(*) FROM macaddr8tmp WHERE a > '22:00:5c:e5:9b:0d'::macaddr8; + count +------- + 540 +(1 row) + +-- Test index-only scans +SET enable_bitmapscan=off; +EXPLAIN (COSTS OFF) +SELECT * FROM macaddr8tmp WHERE a < '02:03:04:05:06:07'::macaddr8; + QUERY PLAN +--------------------------------------------------------- + Index Only Scan using macaddr8idx on macaddr8tmp + Index Cond: (a < '02:03:04:ff:fe:05:06:07'::macaddr8) +(2 rows) + +SELECT * FROM macaddr8tmp WHERE a < '02:03:04:05:06:07'::macaddr8; + a +------------------------- + 01:02:37:ff:fe:05:4f:36 + 01:02:37:ff:fe:05:4f:36 + 01:02:37:ff:fe:05:4f:36 + 01:02:37:ff:fe:05:4f:36 + 01:43:b5:ff:fe:79:eb:0f + 01:43:b5:ff:fe:79:eb:0f + 01:43:b5:ff:fe:79:eb:0f + 01:43:b5:ff:fe:79:eb:0f +(8 rows) + diff --git a/contrib/btree_gist/sql/macaddr8.sql b/contrib/btree_gist/sql/macaddr8.sql new file mode 100644 index 00000000000..61e7d7af405 --- /dev/null +++ b/contrib/btree_gist/sql/macaddr8.sql @@ -0,0 +1,37 @@ +-- macaddr check + +CREATE TABLE macaddr8tmp (a macaddr8); + +\copy macaddr8tmp from 'data/macaddr.data' + +SET enable_seqscan=on; + +SELECT count(*) FROM macaddr8tmp WHERE a < '22:00:5c:e5:9b:0d'; + +SELECT count(*) FROM macaddr8tmp WHERE a <= '22:00:5c:e5:9b:0d'; + +SELECT count(*) FROM macaddr8tmp WHERE a = '22:00:5c:e5:9b:0d'; + +SELECT count(*) FROM macaddr8tmp WHERE a >= '22:00:5c:e5:9b:0d'; + +SELECT count(*) FROM macaddr8tmp WHERE a > '22:00:5c:e5:9b:0d'; + +CREATE INDEX macaddr8idx ON macaddr8tmp USING gist ( a ); + +SET enable_seqscan=off; + +SELECT count(*) FROM macaddr8tmp WHERE a < '22:00:5c:e5:9b:0d'::macaddr8; + +SELECT count(*) FROM macaddr8tmp WHERE a <= '22:00:5c:e5:9b:0d'::macaddr8; + +SELECT count(*) FROM macaddr8tmp WHERE a = '22:00:5c:e5:9b:0d'::macaddr8; + +SELECT count(*) FROM macaddr8tmp WHERE a >= '22:00:5c:e5:9b:0d'::macaddr8; + +SELECT count(*) FROM macaddr8tmp WHERE a > '22:00:5c:e5:9b:0d'::macaddr8; + +-- Test index-only scans +SET enable_bitmapscan=off; +EXPLAIN (COSTS OFF) +SELECT * FROM macaddr8tmp WHERE a < '02:03:04:05:06:07'::macaddr8; +SELECT * FROM macaddr8tmp WHERE a < '02:03:04:05:06:07'::macaddr8; |