mirror of https://github.com/postgres/postgres
This adds in support for EUI-64 MAC addresses by adding a new data type called 'macaddr8' (using our usual convention of indicating the number of bytes stored). This was largely a copy-and-paste from the macaddr data type, with appropriate adjustments for having 8 bytes instead of 6 and adding support for converting a provided EUI-48 (6 byte format) to the EUI-64 format. Conversion from EUI-48 to EUI-64 inserts FFFE as the 4th and 5th bytes but does not perform the IPv6 modified EUI-64 action of flipping the 7th bit, but we add a function to perform that specific action for the user as it may be commonly done by users who wish to calculate their IPv6 address based on their network prefix and 48-bit MAC address. Author: Haribabu Kommi, with a good bit of rework of macaddr8_in by me. Reviewed by: Vitaly Burovoy, Kuntal Ghosh Discussion: https://postgr.es/m/CAJrrPGcUi8ZH+KkK+=TctNQ+EfkeCEHtMU_yo1mvX8hsk_ghNQ@mail.gmail.compull/17/merge
parent
42bdaebf16
commit
c7a9fa399d
@ -0,0 +1,35 @@ |
|||||||
|
/* contrib/btree_gin/btree_gin--1.0--1.1.sql */ |
||||||
|
|
||||||
|
-- complain if script is sourced in psql, rather than via CREATE EXTENSION |
||||||
|
\echo Use "ALTER EXTENSION btree_gin UPDATE TO '1.1'" to load this file. \quit |
||||||
|
|
||||||
|
-- macaddr8 datatype support new in 10.0. |
||||||
|
CREATE FUNCTION gin_extract_value_macaddr8(macaddr8, internal) |
||||||
|
RETURNS internal |
||||||
|
AS 'MODULE_PATHNAME' |
||||||
|
LANGUAGE C STRICT IMMUTABLE; |
||||||
|
|
||||||
|
CREATE FUNCTION gin_compare_prefix_macaddr8(macaddr8, macaddr8, int2, internal) |
||||||
|
RETURNS int4 |
||||||
|
AS 'MODULE_PATHNAME' |
||||||
|
LANGUAGE C STRICT IMMUTABLE; |
||||||
|
|
||||||
|
CREATE FUNCTION gin_extract_query_macaddr8(macaddr8, internal, int2, internal, internal) |
||||||
|
RETURNS internal |
||||||
|
AS 'MODULE_PATHNAME' |
||||||
|
LANGUAGE C STRICT IMMUTABLE; |
||||||
|
|
||||||
|
CREATE OPERATOR CLASS macaddr8_ops |
||||||
|
DEFAULT FOR TYPE macaddr8 USING gin |
||||||
|
AS |
||||||
|
OPERATOR 1 <, |
||||||
|
OPERATOR 2 <=, |
||||||
|
OPERATOR 3 =, |
||||||
|
OPERATOR 4 >=, |
||||||
|
OPERATOR 5 >, |
||||||
|
FUNCTION 1 macaddr8_cmp(macaddr8, macaddr8), |
||||||
|
FUNCTION 2 gin_extract_value_macaddr8(macaddr8, internal), |
||||||
|
FUNCTION 3 gin_extract_query_macaddr8(macaddr8, internal, int2, internal, internal), |
||||||
|
FUNCTION 4 gin_btree_consistent(internal, int2, anyelement, int4, internal, internal), |
||||||
|
FUNCTION 5 gin_compare_prefix_macaddr8(macaddr8, macaddr8, int2, internal), |
||||||
|
STORAGE macaddr8; |
@ -1,5 +1,5 @@ |
|||||||
# btree_gin extension |
# btree_gin extension |
||||||
comment = 'support for indexing common datatypes in GIN' |
comment = 'support for indexing common datatypes in GIN' |
||||||
default_version = '1.0' |
default_version = '1.1' |
||||||
module_pathname = '$libdir/btree_gin' |
module_pathname = '$libdir/btree_gin' |
||||||
relocatable = true |
relocatable = true |
||||||
|
@ -0,0 +1,51 @@ |
|||||||
|
set enable_seqscan=off; |
||||||
|
CREATE TABLE test_macaddr8 ( |
||||||
|
i macaddr8 |
||||||
|
); |
||||||
|
INSERT INTO test_macaddr8 VALUES |
||||||
|
( '22:00:5c:03:55:08:01:02' ), |
||||||
|
( '22:00:5c:04:55:08:01:02' ), |
||||||
|
( '22:00:5c:05:55:08:01:02' ), |
||||||
|
( '22:00:5c:08:55:08:01:02' ), |
||||||
|
( '22:00:5c:09:55:08:01:02' ), |
||||||
|
( '22:00:5c:10:55:08:01:02' ) |
||||||
|
; |
||||||
|
CREATE INDEX idx_macaddr8 ON test_macaddr8 USING gin (i); |
||||||
|
SELECT * FROM test_macaddr8 WHERE i<'22:00:5c:08:55:08:01:02'::macaddr8 ORDER BY i; |
||||||
|
i |
||||||
|
------------------------- |
||||||
|
22:00:5c:03:55:08:01:02 |
||||||
|
22:00:5c:04:55:08:01:02 |
||||||
|
22:00:5c:05:55:08:01:02 |
||||||
|
(3 rows) |
||||||
|
|
||||||
|
SELECT * FROM test_macaddr8 WHERE i<='22:00:5c:08:55:08:01:02'::macaddr8 ORDER BY i; |
||||||
|
i |
||||||
|
------------------------- |
||||||
|
22:00:5c:03:55:08:01:02 |
||||||
|
22:00:5c:04:55:08:01:02 |
||||||
|
22:00:5c:05:55:08:01:02 |
||||||
|
22:00:5c:08:55:08:01:02 |
||||||
|
(4 rows) |
||||||
|
|
||||||
|
SELECT * FROM test_macaddr8 WHERE i='22:00:5c:08:55:08:01:02'::macaddr8 ORDER BY i; |
||||||
|
i |
||||||
|
------------------------- |
||||||
|
22:00:5c:08:55:08:01:02 |
||||||
|
(1 row) |
||||||
|
|
||||||
|
SELECT * FROM test_macaddr8 WHERE i>='22:00:5c:08:55:08:01:02'::macaddr8 ORDER BY i; |
||||||
|
i |
||||||
|
------------------------- |
||||||
|
22:00:5c:08:55:08:01:02 |
||||||
|
22:00:5c:09:55:08:01:02 |
||||||
|
22:00:5c:10:55:08:01:02 |
||||||
|
(3 rows) |
||||||
|
|
||||||
|
SELECT * FROM test_macaddr8 WHERE i>'22:00:5c:08:55:08:01:02'::macaddr8 ORDER BY i; |
||||||
|
i |
||||||
|
------------------------- |
||||||
|
22:00:5c:09:55:08:01:02 |
||||||
|
22:00:5c:10:55:08:01:02 |
||||||
|
(2 rows) |
||||||
|
|
@ -0,0 +1,22 @@ |
|||||||
|
set enable_seqscan=off; |
||||||
|
|
||||||
|
CREATE TABLE test_macaddr8 ( |
||||||
|
i macaddr8 |
||||||
|
); |
||||||
|
|
||||||
|
INSERT INTO test_macaddr8 VALUES |
||||||
|
( '22:00:5c:03:55:08:01:02' ), |
||||||
|
( '22:00:5c:04:55:08:01:02' ), |
||||||
|
( '22:00:5c:05:55:08:01:02' ), |
||||||
|
( '22:00:5c:08:55:08:01:02' ), |
||||||
|
( '22:00:5c:09:55:08:01:02' ), |
||||||
|
( '22:00:5c:10:55:08:01:02' ) |
||||||
|
; |
||||||
|
|
||||||
|
CREATE INDEX idx_macaddr8 ON test_macaddr8 USING gin (i); |
||||||
|
|
||||||
|
SELECT * FROM test_macaddr8 WHERE i<'22:00:5c:08:55:08:01:02'::macaddr8 ORDER BY i; |
||||||
|
SELECT * FROM test_macaddr8 WHERE i<='22:00:5c:08:55:08:01:02'::macaddr8 ORDER BY i; |
||||||
|
SELECT * FROM test_macaddr8 WHERE i='22:00:5c:08:55:08:01:02'::macaddr8 ORDER BY i; |
||||||
|
SELECT * FROM test_macaddr8 WHERE i>='22:00:5c:08:55:08:01:02'::macaddr8 ORDER BY i; |
||||||
|
SELECT * FROM test_macaddr8 WHERE i>'22:00:5c:08:55:08:01:02'::macaddr8 ORDER BY i; |
@ -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); |
@ -1,5 +1,5 @@ |
|||||||
# btree_gist extension |
# btree_gist extension |
||||||
comment = 'support for indexing common datatypes in GiST' |
comment = 'support for indexing common datatypes in GiST' |
||||||
default_version = '1.3' |
default_version = '1.4' |
||||||
module_pathname = '$libdir/btree_gist' |
module_pathname = '$libdir/btree_gist' |
||||||
relocatable = true |
relocatable = true |
||||||
|
@ -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); |
||||||
|
} |
@ -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) |
||||||
|
|
@ -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; |
@ -0,0 +1,560 @@ |
|||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
* |
||||||
|
* mac8.c |
||||||
|
* PostgreSQL type definitions for 8 byte (EUI-64) MAC addresses. |
||||||
|
* |
||||||
|
* EUI-48 (6 byte) MAC addresses are accepted as input and are stored in |
||||||
|
* EUI-64 format, with the 4th and 5th bytes set to FF and FE, respectively. |
||||||
|
* |
||||||
|
* Output is always in 8 byte (EUI-64) format. |
||||||
|
* |
||||||
|
* The following code is written with the assumption that the OUI field |
||||||
|
* size is 24 bits. |
||||||
|
* |
||||||
|
* Portions Copyright (c) 1998-2017, PostgreSQL Global Development Group |
||||||
|
* |
||||||
|
* IDENTIFICATION |
||||||
|
* src/backend/utils/adt/mac8.c |
||||||
|
* |
||||||
|
*------------------------------------------------------------------------- |
||||||
|
*/ |
||||||
|
|
||||||
|
#include "postgres.h" |
||||||
|
|
||||||
|
#include "access/hash.h" |
||||||
|
#include "libpq/pqformat.h" |
||||||
|
#include "utils/builtins.h" |
||||||
|
#include "utils/inet.h" |
||||||
|
|
||||||
|
/*
|
||||||
|
* Utility macros used for sorting and comparing: |
||||||
|
*/ |
||||||
|
#define hibits(addr) \ |
||||||
|
((unsigned long)(((addr)->a<<24) | ((addr)->b<<16) | ((addr)->c<<8) | ((addr)->d))) |
||||||
|
|
||||||
|
#define lobits(addr) \ |
||||||
|
((unsigned long)(((addr)->e<<24) | ((addr)->f<<16) | ((addr)->g<<8) | ((addr)->h))) |
||||||
|
|
||||||
|
static unsigned char hex2_to_uchar(const char *str, int offset); |
||||||
|
|
||||||
|
static const int hexlookup[128] = { |
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
||||||
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, |
||||||
|
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
||||||
|
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
||||||
|
}; |
||||||
|
|
||||||
|
static inline unsigned char |
||||||
|
hex2_to_uchar(const char *str, int offset) |
||||||
|
{ |
||||||
|
unsigned char ret = 0; |
||||||
|
int lookup; |
||||||
|
const char *ptr = str + offset; |
||||||
|
|
||||||
|
/* Handle the first character */ |
||||||
|
if (*ptr < 0 || *ptr >= 127) |
||||||
|
goto invalid_input; |
||||||
|
|
||||||
|
lookup = hexlookup[(unsigned char) *ptr]; |
||||||
|
if (lookup < 0 || lookup > 15) |
||||||
|
goto invalid_input; |
||||||
|
|
||||||
|
ret = lookup << 4; |
||||||
|
|
||||||
|
/* Move to the second character */ |
||||||
|
ptr++; |
||||||
|
|
||||||
|
if (*ptr < 0 || *ptr > 127) |
||||||
|
goto invalid_input; |
||||||
|
|
||||||
|
lookup = hexlookup[(unsigned char) *ptr]; |
||||||
|
if (lookup < 0 || lookup > 15) |
||||||
|
goto invalid_input; |
||||||
|
|
||||||
|
ret += lookup; |
||||||
|
|
||||||
|
return ret; |
||||||
|
|
||||||
|
invalid_input: |
||||||
|
ereport(ERROR, |
||||||
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), |
||||||
|
errmsg("invalid input syntax for type %s: \"%s\"", "macaddr8", |
||||||
|
str))); |
||||||
|
|
||||||
|
/* We do not actually reach here */ |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* MAC address (EUI-48 and EUI-64) reader. Accepts several common notations. |
||||||
|
*/ |
||||||
|
Datum |
||||||
|
macaddr8_in(PG_FUNCTION_ARGS) |
||||||
|
{ |
||||||
|
const char *str = PG_GETARG_CSTRING(0); |
||||||
|
const char *ptr = str; |
||||||
|
macaddr8 *result; |
||||||
|
unsigned char a = 0, |
||||||
|
b = 0, |
||||||
|
c = 0, |
||||||
|
d = 0, |
||||||
|
e = 0, |
||||||
|
f = 0, |
||||||
|
g = 0, |
||||||
|
h = 0; |
||||||
|
int count = 0; |
||||||
|
char spacer = '\0'; |
||||||
|
|
||||||
|
/* skip leading spaces */ |
||||||
|
while (*ptr && isspace((unsigned char) *ptr)) |
||||||
|
ptr++; |
||||||
|
|
||||||
|
/* digits must always come in pairs */ |
||||||
|
while (*ptr && *(ptr + 1)) |
||||||
|
{ |
||||||
|
/*
|
||||||
|
* Attempt to decode each byte, which must be 2 hex digits in a row. |
||||||
|
* If either digit is not hex, hex2_to_uchar will throw ereport() for |
||||||
|
* us. Either 6 or 8 byte MAC addresses are supported. |
||||||
|
*/ |
||||||
|
|
||||||
|
/* Attempt to collect a byte */ |
||||||
|
count++; |
||||||
|
|
||||||
|
switch (count) |
||||||
|
{ |
||||||
|
case 1: |
||||||
|
a = hex2_to_uchar(str, ptr - str); |
||||||
|
break; |
||||||
|
case 2: |
||||||
|
b = hex2_to_uchar(str, ptr - str); |
||||||
|
break; |
||||||
|
case 3: |
||||||
|
c = hex2_to_uchar(str, ptr - str); |
||||||
|
break; |
||||||
|
case 4: |
||||||
|
d = hex2_to_uchar(str, ptr - str); |
||||||
|
break; |
||||||
|
case 5: |
||||||
|
e = hex2_to_uchar(str, ptr - str); |
||||||
|
break; |
||||||
|
case 6: |
||||||
|
f = hex2_to_uchar(str, ptr - str); |
||||||
|
break; |
||||||
|
case 7: |
||||||
|
g = hex2_to_uchar(str, ptr - str); |
||||||
|
break; |
||||||
|
case 8: |
||||||
|
h = hex2_to_uchar(str, ptr - str); |
||||||
|
break; |
||||||
|
default: |
||||||
|
/* must be trailing garbage... */ |
||||||
|
ereport(ERROR, |
||||||
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), |
||||||
|
errmsg("invalid input syntax for type %s: \"%s\"", "macaddr8", |
||||||
|
str))); |
||||||
|
} |
||||||
|
|
||||||
|
/* Move forward to where the next byte should be */ |
||||||
|
ptr += 2; |
||||||
|
|
||||||
|
/* Check for a spacer, these are valid, anything else is not */ |
||||||
|
if (*ptr == ':' || *ptr == '-' || *ptr == '.') |
||||||
|
{ |
||||||
|
/* remember the spacer used, if it changes then it isn't valid */ |
||||||
|
if (spacer == '\0') |
||||||
|
spacer = *ptr; |
||||||
|
|
||||||
|
/* Have to use the same spacer throughout */ |
||||||
|
else if (spacer != *ptr) |
||||||
|
ereport(ERROR, |
||||||
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), |
||||||
|
errmsg("invalid input syntax for type %s: \"%s\"", "macaddr8", |
||||||
|
str))); |
||||||
|
|
||||||
|
/* move past the spacer */ |
||||||
|
ptr++; |
||||||
|
} |
||||||
|
|
||||||
|
/* allow trailing whitespace after if we have 6 or 8 bytes */ |
||||||
|
if (count == 6 || count == 8) |
||||||
|
{ |
||||||
|
if (isspace((unsigned char) *ptr)) |
||||||
|
{ |
||||||
|
while (*++ptr && isspace((unsigned char) *ptr)); |
||||||
|
|
||||||
|
/* If we found a space and then non-space, it's invalid */ |
||||||
|
if (*ptr) |
||||||
|
ereport(ERROR, |
||||||
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), |
||||||
|
errmsg("invalid input syntax for type %s: \"%s\"", "macaddr8", |
||||||
|
str))); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/* Convert a 6 byte MAC address to macaddr8 */ |
||||||
|
if (count == 6) |
||||||
|
{ |
||||||
|
h = f; |
||||||
|
g = e; |
||||||
|
f = d; |
||||||
|
|
||||||
|
d = 0xFF; |
||||||
|
e = 0xFE; |
||||||
|
} |
||||||
|
else if (count != 8) |
||||||
|
ereport(ERROR, |
||||||
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), |
||||||
|
errmsg("invalid input syntax for type %s: \"%s\"", "macaddr8", |
||||||
|
str))); |
||||||
|
|
||||||
|
result = (macaddr8 *) palloc0(sizeof(macaddr8)); |
||||||
|
|
||||||
|
result->a = a; |
||||||
|
result->b = b; |
||||||
|
result->c = c; |
||||||
|
result->d = d; |
||||||
|
result->e = e; |
||||||
|
result->f = f; |
||||||
|
result->g = g; |
||||||
|
result->h = h; |
||||||
|
|
||||||
|
PG_RETURN_MACADDR8_P(result); |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* MAC8 address (EUI-64) output function. Fixed format. |
||||||
|
*/ |
||||||
|
Datum |
||||||
|
macaddr8_out(PG_FUNCTION_ARGS) |
||||||
|
{ |
||||||
|
macaddr8 *addr = PG_GETARG_MACADDR8_P(0); |
||||||
|
char *result; |
||||||
|
|
||||||
|
result = (char *) palloc(32); |
||||||
|
|
||||||
|
snprintf(result, 32, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", |
||||||
|
addr->a, addr->b, addr->c, addr->d, |
||||||
|
addr->e, addr->f, addr->g, addr->h); |
||||||
|
|
||||||
|
PG_RETURN_CSTRING(result); |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* macaddr8_recv - converts external binary format(EUI-48 and EUI-64) to macaddr8 |
||||||
|
* |
||||||
|
* The external representation is just the eight bytes, MSB first. |
||||||
|
*/ |
||||||
|
Datum |
||||||
|
macaddr8_recv(PG_FUNCTION_ARGS) |
||||||
|
{ |
||||||
|
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); |
||||||
|
macaddr8 *addr; |
||||||
|
|
||||||
|
addr = (macaddr8 *) palloc0(sizeof(macaddr8)); |
||||||
|
|
||||||
|
addr->a = pq_getmsgbyte(buf); |
||||||
|
addr->b = pq_getmsgbyte(buf); |
||||||
|
addr->c = pq_getmsgbyte(buf); |
||||||
|
|
||||||
|
if (buf->len == 6) |
||||||
|
{ |
||||||
|
addr->d = 0xFF; |
||||||
|
addr->e = 0xFE; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
addr->d = pq_getmsgbyte(buf); |
||||||
|
addr->e = pq_getmsgbyte(buf); |
||||||
|
} |
||||||
|
|
||||||
|
addr->f = pq_getmsgbyte(buf); |
||||||
|
addr->g = pq_getmsgbyte(buf); |
||||||
|
addr->h = pq_getmsgbyte(buf); |
||||||
|
|
||||||
|
PG_RETURN_MACADDR8_P(addr); |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* macaddr8_send - converts macaddr8(EUI-64) to binary format |
||||||
|
*/ |
||||||
|
Datum |
||||||
|
macaddr8_send(PG_FUNCTION_ARGS) |
||||||
|
{ |
||||||
|
macaddr8 *addr = PG_GETARG_MACADDR8_P(0); |
||||||
|
StringInfoData buf; |
||||||
|
|
||||||
|
pq_begintypsend(&buf); |
||||||
|
pq_sendbyte(&buf, addr->a); |
||||||
|
pq_sendbyte(&buf, addr->b); |
||||||
|
pq_sendbyte(&buf, addr->c); |
||||||
|
pq_sendbyte(&buf, addr->d); |
||||||
|
pq_sendbyte(&buf, addr->e); |
||||||
|
pq_sendbyte(&buf, addr->f); |
||||||
|
pq_sendbyte(&buf, addr->g); |
||||||
|
pq_sendbyte(&buf, addr->h); |
||||||
|
|
||||||
|
PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* macaddr8_cmp_internal - comparison function for sorting: |
||||||
|
*/ |
||||||
|
static int32 |
||||||
|
macaddr8_cmp_internal(macaddr8 *a1, macaddr8 *a2) |
||||||
|
{ |
||||||
|
if (hibits(a1) < hibits(a2)) |
||||||
|
return -1; |
||||||
|
else if (hibits(a1) > hibits(a2)) |
||||||
|
return 1; |
||||||
|
else if (lobits(a1) < lobits(a2)) |
||||||
|
return -1; |
||||||
|
else if (lobits(a1) > lobits(a2)) |
||||||
|
return 1; |
||||||
|
else |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
Datum |
||||||
|
macaddr8_cmp(PG_FUNCTION_ARGS) |
||||||
|
{ |
||||||
|
macaddr8 *a1 = PG_GETARG_MACADDR8_P(0); |
||||||
|
macaddr8 *a2 = PG_GETARG_MACADDR8_P(1); |
||||||
|
|
||||||
|
PG_RETURN_INT32(macaddr8_cmp_internal(a1, a2)); |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* Boolean comparison functions. |
||||||
|
*/ |
||||||
|
|
||||||
|
Datum |
||||||
|
macaddr8_lt(PG_FUNCTION_ARGS) |
||||||
|
{ |
||||||
|
macaddr8 *a1 = PG_GETARG_MACADDR8_P(0); |
||||||
|
macaddr8 *a2 = PG_GETARG_MACADDR8_P(1); |
||||||
|
|
||||||
|
PG_RETURN_BOOL(macaddr8_cmp_internal(a1, a2) < 0); |
||||||
|
} |
||||||
|
|
||||||
|
Datum |
||||||
|
macaddr8_le(PG_FUNCTION_ARGS) |
||||||
|
{ |
||||||
|
macaddr8 *a1 = PG_GETARG_MACADDR8_P(0); |
||||||
|
macaddr8 *a2 = PG_GETARG_MACADDR8_P(1); |
||||||
|
|
||||||
|
PG_RETURN_BOOL(macaddr8_cmp_internal(a1, a2) <= 0); |
||||||
|
} |
||||||
|
|
||||||
|
Datum |
||||||
|
macaddr8_eq(PG_FUNCTION_ARGS) |
||||||
|
{ |
||||||
|
macaddr8 *a1 = PG_GETARG_MACADDR8_P(0); |
||||||
|
macaddr8 *a2 = PG_GETARG_MACADDR8_P(1); |
||||||
|
|
||||||
|
PG_RETURN_BOOL(macaddr8_cmp_internal(a1, a2) == 0); |
||||||
|
} |
||||||
|
|
||||||
|
Datum |
||||||
|
macaddr8_ge(PG_FUNCTION_ARGS) |
||||||
|
{ |
||||||
|
macaddr8 *a1 = PG_GETARG_MACADDR8_P(0); |
||||||
|
macaddr8 *a2 = PG_GETARG_MACADDR8_P(1); |
||||||
|
|
||||||
|
PG_RETURN_BOOL(macaddr8_cmp_internal(a1, a2) >= 0); |
||||||
|
} |
||||||
|
|
||||||
|
Datum |
||||||
|
macaddr8_gt(PG_FUNCTION_ARGS) |
||||||
|
{ |
||||||
|
macaddr8 *a1 = PG_GETARG_MACADDR8_P(0); |
||||||
|
macaddr8 *a2 = PG_GETARG_MACADDR8_P(1); |
||||||
|
|
||||||
|
PG_RETURN_BOOL(macaddr8_cmp_internal(a1, a2) > 0); |
||||||
|
} |
||||||
|
|
||||||
|
Datum |
||||||
|
macaddr8_ne(PG_FUNCTION_ARGS) |
||||||
|
{ |
||||||
|
macaddr8 *a1 = PG_GETARG_MACADDR8_P(0); |
||||||
|
macaddr8 *a2 = PG_GETARG_MACADDR8_P(1); |
||||||
|
|
||||||
|
PG_RETURN_BOOL(macaddr8_cmp_internal(a1, a2) != 0); |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* Support function for hash indexes on macaddr8. |
||||||
|
*/ |
||||||
|
Datum |
||||||
|
hashmacaddr8(PG_FUNCTION_ARGS) |
||||||
|
{ |
||||||
|
macaddr8 *key = PG_GETARG_MACADDR8_P(0); |
||||||
|
|
||||||
|
return hash_any((unsigned char *) key, sizeof(macaddr8)); |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* Arithmetic functions: bitwise NOT, AND, OR. |
||||||
|
*/ |
||||||
|
Datum |
||||||
|
macaddr8_not(PG_FUNCTION_ARGS) |
||||||
|
{ |
||||||
|
macaddr8 *addr = PG_GETARG_MACADDR8_P(0); |
||||||
|
macaddr8 *result; |
||||||
|
|
||||||
|
result = (macaddr8 *) palloc0(sizeof(macaddr8)); |
||||||
|
result->a = ~addr->a; |
||||||
|
result->b = ~addr->b; |
||||||
|
result->c = ~addr->c; |
||||||
|
result->d = ~addr->d; |
||||||
|
result->e = ~addr->e; |
||||||
|
result->f = ~addr->f; |
||||||
|
result->g = ~addr->g; |
||||||
|
result->h = ~addr->h; |
||||||
|
|
||||||
|
PG_RETURN_MACADDR8_P(result); |
||||||
|
} |
||||||
|
|
||||||
|
Datum |
||||||
|
macaddr8_and(PG_FUNCTION_ARGS) |
||||||
|
{ |
||||||
|
macaddr8 *addr1 = PG_GETARG_MACADDR8_P(0); |
||||||
|
macaddr8 *addr2 = PG_GETARG_MACADDR8_P(1); |
||||||
|
macaddr8 *result; |
||||||
|
|
||||||
|
result = (macaddr8 *) palloc0(sizeof(macaddr8)); |
||||||
|
result->a = addr1->a & addr2->a; |
||||||
|
result->b = addr1->b & addr2->b; |
||||||
|
result->c = addr1->c & addr2->c; |
||||||
|
result->d = addr1->d & addr2->d; |
||||||
|
result->e = addr1->e & addr2->e; |
||||||
|
result->f = addr1->f & addr2->f; |
||||||
|
result->g = addr1->g & addr2->g; |
||||||
|
result->h = addr1->h & addr2->h; |
||||||
|
|
||||||
|
PG_RETURN_MACADDR8_P(result); |
||||||
|
} |
||||||
|
|
||||||
|
Datum |
||||||
|
macaddr8_or(PG_FUNCTION_ARGS) |
||||||
|
{ |
||||||
|
macaddr8 *addr1 = PG_GETARG_MACADDR8_P(0); |
||||||
|
macaddr8 *addr2 = PG_GETARG_MACADDR8_P(1); |
||||||
|
macaddr8 *result; |
||||||
|
|
||||||
|
result = (macaddr8 *) palloc0(sizeof(macaddr8)); |
||||||
|
result->a = addr1->a | addr2->a; |
||||||
|
result->b = addr1->b | addr2->b; |
||||||
|
result->c = addr1->c | addr2->c; |
||||||
|
result->d = addr1->d | addr2->d; |
||||||
|
result->e = addr1->e | addr2->e; |
||||||
|
result->f = addr1->f | addr2->f; |
||||||
|
result->g = addr1->g | addr2->g; |
||||||
|
result->h = addr1->h | addr2->h; |
||||||
|
|
||||||
|
PG_RETURN_MACADDR8_P(result); |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* Truncation function to allow comparing macaddr8 manufacturers. |
||||||
|
*/ |
||||||
|
Datum |
||||||
|
macaddr8_trunc(PG_FUNCTION_ARGS) |
||||||
|
{ |
||||||
|
macaddr8 *addr = PG_GETARG_MACADDR8_P(0); |
||||||
|
macaddr8 *result; |
||||||
|
|
||||||
|
result = (macaddr8 *) palloc0(sizeof(macaddr8)); |
||||||
|
|
||||||
|
result->a = addr->a; |
||||||
|
result->b = addr->b; |
||||||
|
result->c = addr->c; |
||||||
|
result->d = 0; |
||||||
|
result->e = 0; |
||||||
|
result->f = 0; |
||||||
|
result->g = 0; |
||||||
|
result->h = 0; |
||||||
|
|
||||||
|
PG_RETURN_MACADDR8_P(result); |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* Set 7th bit for modified EUI-64 as used in IPv6. |
||||||
|
*/ |
||||||
|
Datum |
||||||
|
macaddr8_set7bit(PG_FUNCTION_ARGS) |
||||||
|
{ |
||||||
|
macaddr8 *addr = PG_GETARG_MACADDR8_P(0); |
||||||
|
macaddr8 *result; |
||||||
|
|
||||||
|
result = (macaddr8 *) palloc0(sizeof(macaddr8)); |
||||||
|
|
||||||
|
result->a = addr->a | 0x02; |
||||||
|
result->b = addr->b; |
||||||
|
result->c = addr->c; |
||||||
|
result->d = addr->d; |
||||||
|
result->e = addr->e; |
||||||
|
result->f = addr->f; |
||||||
|
result->g = addr->g; |
||||||
|
result->h = addr->h; |
||||||
|
|
||||||
|
PG_RETURN_MACADDR8_P(result); |
||||||
|
} |
||||||
|
|
||||||
|
/*----------------------------------------------------------
|
||||||
|
* Conversion operators. |
||||||
|
*---------------------------------------------------------*/ |
||||||
|
|
||||||
|
Datum |
||||||
|
macaddrtomacaddr8(PG_FUNCTION_ARGS) |
||||||
|
{ |
||||||
|
macaddr *addr6 = PG_GETARG_MACADDR_P(0); |
||||||
|
macaddr8 *result; |
||||||
|
|
||||||
|
result = (macaddr8 *) palloc0(sizeof(macaddr8)); |
||||||
|
|
||||||
|
result->a = addr6->a; |
||||||
|
result->b = addr6->b; |
||||||
|
result->c = addr6->c; |
||||||
|
result->d = 0xFF; |
||||||
|
result->e = 0xFE; |
||||||
|
result->f = addr6->d; |
||||||
|
result->g = addr6->e; |
||||||
|
result->h = addr6->f; |
||||||
|
|
||||||
|
|
||||||
|
PG_RETURN_MACADDR8_P(result); |
||||||
|
} |
||||||
|
|
||||||
|
Datum |
||||||
|
macaddr8tomacaddr(PG_FUNCTION_ARGS) |
||||||
|
{ |
||||||
|
macaddr8 *addr = PG_GETARG_MACADDR8_P(0); |
||||||
|
macaddr *result; |
||||||
|
|
||||||
|
result = (macaddr *) palloc0(sizeof(macaddr)); |
||||||
|
|
||||||
|
if ((addr->d != 0xFF) || (addr->e != 0xFE)) |
||||||
|
ereport(ERROR, |
||||||
|
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
||||||
|
errmsg("macaddr8 data out of range to convert to macaddr"), |
||||||
|
errhint("Only addresses that have FF and FE as values in the " |
||||||
|
"4th and 5th bytes, from the left, for example: " |
||||||
|
"XX-XX-XX-FF-FE-XX-XX-XX, are eligible to be converted " |
||||||
|
"from macaddr8 to macaddr."))); |
||||||
|
|
||||||
|
result->a = addr->a; |
||||||
|
result->b = addr->b; |
||||||
|
result->c = addr->c; |
||||||
|
result->d = addr->f; |
||||||
|
result->e = addr->g; |
||||||
|
result->f = addr->h; |
||||||
|
|
||||||
|
PG_RETURN_MACADDR_P(result); |
||||||
|
} |
@ -0,0 +1,354 @@ |
|||||||
|
-- |
||||||
|
-- macaddr8 |
||||||
|
-- |
||||||
|
-- test various cases of valid and invalid input |
||||||
|
-- valid |
||||||
|
SELECT '08:00:2b:01:02:03 '::macaddr8; |
||||||
|
macaddr8 |
||||||
|
------------------------- |
||||||
|
08:00:2b:ff:fe:01:02:03 |
||||||
|
(1 row) |
||||||
|
|
||||||
|
SELECT ' 08:00:2b:01:02:03 '::macaddr8; |
||||||
|
macaddr8 |
||||||
|
------------------------- |
||||||
|
08:00:2b:ff:fe:01:02:03 |
||||||
|
(1 row) |
||||||
|
|
||||||
|
SELECT ' 08:00:2b:01:02:03'::macaddr8; |
||||||
|
macaddr8 |
||||||
|
------------------------- |
||||||
|
08:00:2b:ff:fe:01:02:03 |
||||||
|
(1 row) |
||||||
|
|
||||||
|
SELECT '08:00:2b:01:02:03:04:05 '::macaddr8; |
||||||
|
macaddr8 |
||||||
|
------------------------- |
||||||
|
08:00:2b:01:02:03:04:05 |
||||||
|
(1 row) |
||||||
|
|
||||||
|
SELECT ' 08:00:2b:01:02:03:04:05 '::macaddr8; |
||||||
|
macaddr8 |
||||||
|
------------------------- |
||||||
|
08:00:2b:01:02:03:04:05 |
||||||
|
(1 row) |
||||||
|
|
||||||
|
SELECT ' 08:00:2b:01:02:03:04:05'::macaddr8; |
||||||
|
macaddr8 |
||||||
|
------------------------- |
||||||
|
08:00:2b:01:02:03:04:05 |
||||||
|
(1 row) |
||||||
|
|
||||||
|
SELECT '123 08:00:2b:01:02:03'::macaddr8; -- invalid |
||||||
|
ERROR: invalid input syntax for type macaddr8: "123 08:00:2b:01:02:03" |
||||||
|
LINE 1: SELECT '123 08:00:2b:01:02:03'::macaddr8; |
||||||
|
^ |
||||||
|
SELECT '08:00:2b:01:02:03 123'::macaddr8; -- invalid |
||||||
|
ERROR: invalid input syntax for type macaddr8: "08:00:2b:01:02:03 123" |
||||||
|
LINE 1: SELECT '08:00:2b:01:02:03 123'::macaddr8; |
||||||
|
^ |
||||||
|
SELECT '123 08:00:2b:01:02:03:04:05'::macaddr8; -- invalid |
||||||
|
ERROR: invalid input syntax for type macaddr8: "123 08:00:2b:01:02:03:04:05" |
||||||
|
LINE 1: SELECT '123 08:00:2b:01:02:03:04:05'::macaddr8; |
||||||
|
^ |
||||||
|
SELECT '08:00:2b:01:02:03:04:05 123'::macaddr8; -- invalid |
||||||
|
ERROR: invalid input syntax for type macaddr8: "08:00:2b:01:02:03:04:05 123" |
||||||
|
LINE 1: SELECT '08:00:2b:01:02:03:04:05 123'::macaddr8; |
||||||
|
^ |
||||||
|
SELECT '08:00:2b:01:02:03:04:05:06:07'::macaddr8; -- invalid |
||||||
|
ERROR: invalid input syntax for type macaddr8: "08:00:2b:01:02:03:04:05:06:07" |
||||||
|
LINE 1: SELECT '08:00:2b:01:02:03:04:05:06:07'::macaddr8; |
||||||
|
^ |
||||||
|
SELECT '08-00-2b-01-02-03-04-05-06-07'::macaddr8; -- invalid |
||||||
|
ERROR: invalid input syntax for type macaddr8: "08-00-2b-01-02-03-04-05-06-07" |
||||||
|
LINE 1: SELECT '08-00-2b-01-02-03-04-05-06-07'::macaddr8; |
||||||
|
^ |
||||||
|
SELECT '08002b:01020304050607'::macaddr8; -- invalid |
||||||
|
ERROR: invalid input syntax for type macaddr8: "08002b:01020304050607" |
||||||
|
LINE 1: SELECT '08002b:01020304050607'::macaddr8; |
||||||
|
^ |
||||||
|
SELECT '08002b01020304050607'::macaddr8; -- invalid |
||||||
|
ERROR: invalid input syntax for type macaddr8: "08002b01020304050607" |
||||||
|
LINE 1: SELECT '08002b01020304050607'::macaddr8; |
||||||
|
^ |
||||||
|
SELECT '0z002b0102030405'::macaddr8; -- invalid |
||||||
|
ERROR: invalid input syntax for type macaddr8: "0z002b0102030405" |
||||||
|
LINE 1: SELECT '0z002b0102030405'::macaddr8; |
||||||
|
^ |
||||||
|
SELECT '08002b010203xyza'::macaddr8; -- invalid |
||||||
|
ERROR: invalid input syntax for type macaddr8: "08002b010203xyza" |
||||||
|
LINE 1: SELECT '08002b010203xyza'::macaddr8; |
||||||
|
^ |
||||||
|
SELECT '08:00-2b:01:02:03:04:05'::macaddr8; -- invalid |
||||||
|
ERROR: invalid input syntax for type macaddr8: "08:00-2b:01:02:03:04:05" |
||||||
|
LINE 1: SELECT '08:00-2b:01:02:03:04:05'::macaddr8; |
||||||
|
^ |
||||||
|
SELECT '08:00-2b:01:02:03:04:05'::macaddr8; -- invalid |
||||||
|
ERROR: invalid input syntax for type macaddr8: "08:00-2b:01:02:03:04:05" |
||||||
|
LINE 1: SELECT '08:00-2b:01:02:03:04:05'::macaddr8; |
||||||
|
^ |
||||||
|
SELECT '08:00:2b:01.02:03:04:05'::macaddr8; -- invalid |
||||||
|
ERROR: invalid input syntax for type macaddr8: "08:00:2b:01.02:03:04:05" |
||||||
|
LINE 1: SELECT '08:00:2b:01.02:03:04:05'::macaddr8; |
||||||
|
^ |
||||||
|
SELECT '08:00:2b:01.02:03:04:05'::macaddr8; -- invalid |
||||||
|
ERROR: invalid input syntax for type macaddr8: "08:00:2b:01.02:03:04:05" |
||||||
|
LINE 1: SELECT '08:00:2b:01.02:03:04:05'::macaddr8; |
||||||
|
^ |
||||||
|
-- test converting a MAC address to modified EUI-64 for inclusion |
||||||
|
-- in an ipv6 address |
||||||
|
SELECT macaddr8_set7bit('00:08:2b:01:02:03'::macaddr8); |
||||||
|
macaddr8_set7bit |
||||||
|
------------------------- |
||||||
|
02:08:2b:ff:fe:01:02:03 |
||||||
|
(1 row) |
||||||
|
|
||||||
|
CREATE TABLE macaddr8_data (a int, b macaddr8); |
||||||
|
INSERT INTO macaddr8_data VALUES (1, '08:00:2b:01:02:03'); |
||||||
|
INSERT INTO macaddr8_data VALUES (2, '08-00-2b-01-02-03'); |
||||||
|
INSERT INTO macaddr8_data VALUES (3, '08002b:010203'); |
||||||
|
INSERT INTO macaddr8_data VALUES (4, '08002b-010203'); |
||||||
|
INSERT INTO macaddr8_data VALUES (5, '0800.2b01.0203'); |
||||||
|
INSERT INTO macaddr8_data VALUES (6, '0800-2b01-0203'); |
||||||
|
INSERT INTO macaddr8_data VALUES (7, '08002b010203'); |
||||||
|
INSERT INTO macaddr8_data VALUES (8, '0800:2b01:0203'); |
||||||
|
INSERT INTO macaddr8_data VALUES (9, 'not even close'); -- invalid |
||||||
|
ERROR: invalid input syntax for type macaddr8: "not even close" |
||||||
|
LINE 1: INSERT INTO macaddr8_data VALUES (9, 'not even close'); |
||||||
|
^ |
||||||
|
INSERT INTO macaddr8_data VALUES (10, '08:00:2b:01:02:04'); |
||||||
|
INSERT INTO macaddr8_data VALUES (11, '08:00:2b:01:02:02'); |
||||||
|
INSERT INTO macaddr8_data VALUES (12, '08:00:2a:01:02:03'); |
||||||
|
INSERT INTO macaddr8_data VALUES (13, '08:00:2c:01:02:03'); |
||||||
|
INSERT INTO macaddr8_data VALUES (14, '08:00:2a:01:02:04'); |
||||||
|
INSERT INTO macaddr8_data VALUES (15, '08:00:2b:01:02:03:04:05'); |
||||||
|
INSERT INTO macaddr8_data VALUES (16, '08-00-2b-01-02-03-04-05'); |
||||||
|
INSERT INTO macaddr8_data VALUES (17, '08002b:0102030405'); |
||||||
|
INSERT INTO macaddr8_data VALUES (18, '08002b-0102030405'); |
||||||
|
INSERT INTO macaddr8_data VALUES (19, '0800.2b01.0203.0405'); |
||||||
|
INSERT INTO macaddr8_data VALUES (20, '08002b01:02030405'); |
||||||
|
INSERT INTO macaddr8_data VALUES (21, '08002b0102030405'); |
||||||
|
SELECT * FROM macaddr8_data ORDER BY 1; |
||||||
|
a | b |
||||||
|
----+------------------------- |
||||||
|
1 | 08:00:2b:ff:fe:01:02:03 |
||||||
|
2 | 08:00:2b:ff:fe:01:02:03 |
||||||
|
3 | 08:00:2b:ff:fe:01:02:03 |
||||||
|
4 | 08:00:2b:ff:fe:01:02:03 |
||||||
|
5 | 08:00:2b:ff:fe:01:02:03 |
||||||
|
6 | 08:00:2b:ff:fe:01:02:03 |
||||||
|
7 | 08:00:2b:ff:fe:01:02:03 |
||||||
|
8 | 08:00:2b:ff:fe:01:02:03 |
||||||
|
10 | 08:00:2b:ff:fe:01:02:04 |
||||||
|
11 | 08:00:2b:ff:fe:01:02:02 |
||||||
|
12 | 08:00:2a:ff:fe:01:02:03 |
||||||
|
13 | 08:00:2c:ff:fe:01:02:03 |
||||||
|
14 | 08:00:2a:ff:fe:01:02:04 |
||||||
|
15 | 08:00:2b:01:02:03:04:05 |
||||||
|
16 | 08:00:2b:01:02:03:04:05 |
||||||
|
17 | 08:00:2b:01:02:03:04:05 |
||||||
|
18 | 08:00:2b:01:02:03:04:05 |
||||||
|
19 | 08:00:2b:01:02:03:04:05 |
||||||
|
20 | 08:00:2b:01:02:03:04:05 |
||||||
|
21 | 08:00:2b:01:02:03:04:05 |
||||||
|
(20 rows) |
||||||
|
|
||||||
|
CREATE INDEX macaddr8_data_btree ON macaddr8_data USING btree (b); |
||||||
|
CREATE INDEX macaddr8_data_hash ON macaddr8_data USING hash (b); |
||||||
|
SELECT a, b, trunc(b) FROM macaddr8_data ORDER BY 2, 1; |
||||||
|
a | b | trunc |
||||||
|
----+-------------------------+------------------------- |
||||||
|
12 | 08:00:2a:ff:fe:01:02:03 | 08:00:2a:00:00:00:00:00 |
||||||
|
14 | 08:00:2a:ff:fe:01:02:04 | 08:00:2a:00:00:00:00:00 |
||||||
|
15 | 08:00:2b:01:02:03:04:05 | 08:00:2b:00:00:00:00:00 |
||||||
|
16 | 08:00:2b:01:02:03:04:05 | 08:00:2b:00:00:00:00:00 |
||||||
|
17 | 08:00:2b:01:02:03:04:05 | 08:00:2b:00:00:00:00:00 |
||||||
|
18 | 08:00:2b:01:02:03:04:05 | 08:00:2b:00:00:00:00:00 |
||||||
|
19 | 08:00:2b:01:02:03:04:05 | 08:00:2b:00:00:00:00:00 |
||||||
|
20 | 08:00:2b:01:02:03:04:05 | 08:00:2b:00:00:00:00:00 |
||||||
|
21 | 08:00:2b:01:02:03:04:05 | 08:00:2b:00:00:00:00:00 |
||||||
|
11 | 08:00:2b:ff:fe:01:02:02 | 08:00:2b:00:00:00:00:00 |
||||||
|
1 | 08:00:2b:ff:fe:01:02:03 | 08:00:2b:00:00:00:00:00 |
||||||
|
2 | 08:00:2b:ff:fe:01:02:03 | 08:00:2b:00:00:00:00:00 |
||||||
|
3 | 08:00:2b:ff:fe:01:02:03 | 08:00:2b:00:00:00:00:00 |
||||||
|
4 | 08:00:2b:ff:fe:01:02:03 | 08:00:2b:00:00:00:00:00 |
||||||
|
5 | 08:00:2b:ff:fe:01:02:03 | 08:00:2b:00:00:00:00:00 |
||||||
|
6 | 08:00:2b:ff:fe:01:02:03 | 08:00:2b:00:00:00:00:00 |
||||||
|
7 | 08:00:2b:ff:fe:01:02:03 | 08:00:2b:00:00:00:00:00 |
||||||
|
8 | 08:00:2b:ff:fe:01:02:03 | 08:00:2b:00:00:00:00:00 |
||||||
|
10 | 08:00:2b:ff:fe:01:02:04 | 08:00:2b:00:00:00:00:00 |
||||||
|
13 | 08:00:2c:ff:fe:01:02:03 | 08:00:2c:00:00:00:00:00 |
||||||
|
(20 rows) |
||||||
|
|
||||||
|
SELECT b < '08:00:2b:01:02:04' FROM macaddr8_data WHERE a = 1; -- true |
||||||
|
?column? |
||||||
|
---------- |
||||||
|
t |
||||||
|
(1 row) |
||||||
|
|
||||||
|
SELECT b > '08:00:2b:ff:fe:01:02:04' FROM macaddr8_data WHERE a = 1; -- false |
||||||
|
?column? |
||||||
|
---------- |
||||||
|
f |
||||||
|
(1 row) |
||||||
|
|
||||||
|
SELECT b > '08:00:2b:ff:fe:01:02:03' FROM macaddr8_data WHERE a = 1; -- false |
||||||
|
?column? |
||||||
|
---------- |
||||||
|
f |
||||||
|
(1 row) |
||||||
|
|
||||||
|
SELECT b::macaddr <= '08:00:2b:01:02:04' FROM macaddr8_data WHERE a = 1; -- true |
||||||
|
?column? |
||||||
|
---------- |
||||||
|
t |
||||||
|
(1 row) |
||||||
|
|
||||||
|
SELECT b::macaddr >= '08:00:2b:01:02:04' FROM macaddr8_data WHERE a = 1; -- false |
||||||
|
?column? |
||||||
|
---------- |
||||||
|
f |
||||||
|
(1 row) |
||||||
|
|
||||||
|
SELECT b = '08:00:2b:ff:fe:01:02:03' FROM macaddr8_data WHERE a = 1; -- true |
||||||
|
?column? |
||||||
|
---------- |
||||||
|
t |
||||||
|
(1 row) |
||||||
|
|
||||||
|
SELECT b::macaddr <> '08:00:2b:01:02:04'::macaddr FROM macaddr8_data WHERE a = 1; -- true |
||||||
|
?column? |
||||||
|
---------- |
||||||
|
t |
||||||
|
(1 row) |
||||||
|
|
||||||
|
SELECT b::macaddr <> '08:00:2b:01:02:03'::macaddr FROM macaddr8_data WHERE a = 1; -- false |
||||||
|
?column? |
||||||
|
---------- |
||||||
|
f |
||||||
|
(1 row) |
||||||
|
|
||||||
|
SELECT b < '08:00:2b:01:02:03:04:06' FROM macaddr8_data WHERE a = 15; -- true |
||||||
|
?column? |
||||||
|
---------- |
||||||
|
t |
||||||
|
(1 row) |
||||||
|
|
||||||
|
SELECT b > '08:00:2b:01:02:03:04:06' FROM macaddr8_data WHERE a = 15; -- false |
||||||
|
?column? |
||||||
|
---------- |
||||||
|
f |
||||||
|
(1 row) |
||||||
|
|
||||||
|
SELECT b > '08:00:2b:01:02:03:04:05' FROM macaddr8_data WHERE a = 15; -- false |
||||||
|
?column? |
||||||
|
---------- |
||||||
|
f |
||||||
|
(1 row) |
||||||
|
|
||||||
|
SELECT b <= '08:00:2b:01:02:03:04:06' FROM macaddr8_data WHERE a = 15; -- true |
||||||
|
?column? |
||||||
|
---------- |
||||||
|
t |
||||||
|
(1 row) |
||||||
|
|
||||||
|
SELECT b >= '08:00:2b:01:02:03:04:06' FROM macaddr8_data WHERE a = 15; -- false |
||||||
|
?column? |
||||||
|
---------- |
||||||
|
f |
||||||
|
(1 row) |
||||||
|
|
||||||
|
SELECT b = '08:00:2b:01:02:03:04:05' FROM macaddr8_data WHERE a = 15; -- true |
||||||
|
?column? |
||||||
|
---------- |
||||||
|
t |
||||||
|
(1 row) |
||||||
|
|
||||||
|
SELECT b <> '08:00:2b:01:02:03:04:06' FROM macaddr8_data WHERE a = 15; -- true |
||||||
|
?column? |
||||||
|
---------- |
||||||
|
t |
||||||
|
(1 row) |
||||||
|
|
||||||
|
SELECT b <> '08:00:2b:01:02:03:04:05' FROM macaddr8_data WHERE a = 15; -- false |
||||||
|
?column? |
||||||
|
---------- |
||||||
|
f |
||||||
|
(1 row) |
||||||
|
|
||||||
|
SELECT ~b FROM macaddr8_data; |
||||||
|
?column? |
||||||
|
------------------------- |
||||||
|
f7:ff:d4:00:01:fe:fd:fc |
||||||
|
f7:ff:d4:00:01:fe:fd:fc |
||||||
|
f7:ff:d4:00:01:fe:fd:fc |
||||||
|
f7:ff:d4:00:01:fe:fd:fc |
||||||
|
f7:ff:d4:00:01:fe:fd:fc |
||||||
|
f7:ff:d4:00:01:fe:fd:fc |
||||||
|
f7:ff:d4:00:01:fe:fd:fc |
||||||
|
f7:ff:d4:00:01:fe:fd:fc |
||||||
|
f7:ff:d4:00:01:fe:fd:fb |
||||||
|
f7:ff:d4:00:01:fe:fd:fd |
||||||
|
f7:ff:d5:00:01:fe:fd:fc |
||||||
|
f7:ff:d3:00:01:fe:fd:fc |
||||||
|
f7:ff:d5:00:01:fe:fd:fb |
||||||
|
f7:ff:d4:fe:fd:fc:fb:fa |
||||||
|
f7:ff:d4:fe:fd:fc:fb:fa |
||||||
|
f7:ff:d4:fe:fd:fc:fb:fa |
||||||
|
f7:ff:d4:fe:fd:fc:fb:fa |
||||||
|
f7:ff:d4:fe:fd:fc:fb:fa |
||||||
|
f7:ff:d4:fe:fd:fc:fb:fa |
||||||
|
f7:ff:d4:fe:fd:fc:fb:fa |
||||||
|
(20 rows) |
||||||
|
|
||||||
|
SELECT b & '00:00:00:ff:ff:ff' FROM macaddr8_data; |
||||||
|
?column? |
||||||
|
------------------------- |
||||||
|
00:00:00:ff:fe:01:02:03 |
||||||
|
00:00:00:ff:fe:01:02:03 |
||||||
|
00:00:00:ff:fe:01:02:03 |
||||||
|
00:00:00:ff:fe:01:02:03 |
||||||
|
00:00:00:ff:fe:01:02:03 |
||||||
|
00:00:00:ff:fe:01:02:03 |
||||||
|
00:00:00:ff:fe:01:02:03 |
||||||
|
00:00:00:ff:fe:01:02:03 |
||||||
|
00:00:00:ff:fe:01:02:04 |
||||||
|
00:00:00:ff:fe:01:02:02 |
||||||
|
00:00:00:ff:fe:01:02:03 |
||||||
|
00:00:00:ff:fe:01:02:03 |
||||||
|
00:00:00:ff:fe:01:02:04 |
||||||
|
00:00:00:01:02:03:04:05 |
||||||
|
00:00:00:01:02:03:04:05 |
||||||
|
00:00:00:01:02:03:04:05 |
||||||
|
00:00:00:01:02:03:04:05 |
||||||
|
00:00:00:01:02:03:04:05 |
||||||
|
00:00:00:01:02:03:04:05 |
||||||
|
00:00:00:01:02:03:04:05 |
||||||
|
(20 rows) |
||||||
|
|
||||||
|
SELECT b | '01:02:03:04:05:06' FROM macaddr8_data; |
||||||
|
?column? |
||||||
|
------------------------- |
||||||
|
09:02:2b:ff:fe:05:07:07 |
||||||
|
09:02:2b:ff:fe:05:07:07 |
||||||
|
09:02:2b:ff:fe:05:07:07 |
||||||
|
09:02:2b:ff:fe:05:07:07 |
||||||
|
09:02:2b:ff:fe:05:07:07 |
||||||
|
09:02:2b:ff:fe:05:07:07 |
||||||
|
09:02:2b:ff:fe:05:07:07 |
||||||
|
09:02:2b:ff:fe:05:07:07 |
||||||
|
09:02:2b:ff:fe:05:07:06 |
||||||
|
09:02:2b:ff:fe:05:07:06 |
||||||
|
09:02:2b:ff:fe:05:07:07 |
||||||
|
09:02:2f:ff:fe:05:07:07 |
||||||
|
09:02:2b:ff:fe:05:07:06 |
||||||
|
09:02:2b:ff:fe:07:05:07 |
||||||
|
09:02:2b:ff:fe:07:05:07 |
||||||
|
09:02:2b:ff:fe:07:05:07 |
||||||
|
09:02:2b:ff:fe:07:05:07 |
||||||
|
09:02:2b:ff:fe:07:05:07 |
||||||
|
09:02:2b:ff:fe:07:05:07 |
||||||
|
09:02:2b:ff:fe:07:05:07 |
||||||
|
(20 rows) |
||||||
|
|
||||||
|
DROP TABLE macaddr8_data; |
@ -0,0 +1,89 @@ |
|||||||
|
-- |
||||||
|
-- macaddr8 |
||||||
|
-- |
||||||
|
|
||||||
|
-- test various cases of valid and invalid input |
||||||
|
-- valid |
||||||
|
SELECT '08:00:2b:01:02:03 '::macaddr8; |
||||||
|
SELECT ' 08:00:2b:01:02:03 '::macaddr8; |
||||||
|
SELECT ' 08:00:2b:01:02:03'::macaddr8; |
||||||
|
SELECT '08:00:2b:01:02:03:04:05 '::macaddr8; |
||||||
|
SELECT ' 08:00:2b:01:02:03:04:05 '::macaddr8; |
||||||
|
SELECT ' 08:00:2b:01:02:03:04:05'::macaddr8; |
||||||
|
|
||||||
|
SELECT '123 08:00:2b:01:02:03'::macaddr8; -- invalid |
||||||
|
SELECT '08:00:2b:01:02:03 123'::macaddr8; -- invalid |
||||||
|
SELECT '123 08:00:2b:01:02:03:04:05'::macaddr8; -- invalid |
||||||
|
SELECT '08:00:2b:01:02:03:04:05 123'::macaddr8; -- invalid |
||||||
|
SELECT '08:00:2b:01:02:03:04:05:06:07'::macaddr8; -- invalid |
||||||
|
SELECT '08-00-2b-01-02-03-04-05-06-07'::macaddr8; -- invalid |
||||||
|
SELECT '08002b:01020304050607'::macaddr8; -- invalid |
||||||
|
SELECT '08002b01020304050607'::macaddr8; -- invalid |
||||||
|
SELECT '0z002b0102030405'::macaddr8; -- invalid |
||||||
|
SELECT '08002b010203xyza'::macaddr8; -- invalid |
||||||
|
|
||||||
|
SELECT '08:00-2b:01:02:03:04:05'::macaddr8; -- invalid |
||||||
|
SELECT '08:00-2b:01:02:03:04:05'::macaddr8; -- invalid |
||||||
|
SELECT '08:00:2b:01.02:03:04:05'::macaddr8; -- invalid |
||||||
|
SELECT '08:00:2b:01.02:03:04:05'::macaddr8; -- invalid |
||||||
|
|
||||||
|
-- test converting a MAC address to modified EUI-64 for inclusion |
||||||
|
-- in an ipv6 address |
||||||
|
SELECT macaddr8_set7bit('00:08:2b:01:02:03'::macaddr8); |
||||||
|
|
||||||
|
CREATE TABLE macaddr8_data (a int, b macaddr8); |
||||||
|
|
||||||
|
INSERT INTO macaddr8_data VALUES (1, '08:00:2b:01:02:03'); |
||||||
|
INSERT INTO macaddr8_data VALUES (2, '08-00-2b-01-02-03'); |
||||||
|
INSERT INTO macaddr8_data VALUES (3, '08002b:010203'); |
||||||
|
INSERT INTO macaddr8_data VALUES (4, '08002b-010203'); |
||||||
|
INSERT INTO macaddr8_data VALUES (5, '0800.2b01.0203'); |
||||||
|
INSERT INTO macaddr8_data VALUES (6, '0800-2b01-0203'); |
||||||
|
INSERT INTO macaddr8_data VALUES (7, '08002b010203'); |
||||||
|
INSERT INTO macaddr8_data VALUES (8, '0800:2b01:0203'); |
||||||
|
INSERT INTO macaddr8_data VALUES (9, 'not even close'); -- invalid |
||||||
|
|
||||||
|
INSERT INTO macaddr8_data VALUES (10, '08:00:2b:01:02:04'); |
||||||
|
INSERT INTO macaddr8_data VALUES (11, '08:00:2b:01:02:02'); |
||||||
|
INSERT INTO macaddr8_data VALUES (12, '08:00:2a:01:02:03'); |
||||||
|
INSERT INTO macaddr8_data VALUES (13, '08:00:2c:01:02:03'); |
||||||
|
INSERT INTO macaddr8_data VALUES (14, '08:00:2a:01:02:04'); |
||||||
|
|
||||||
|
INSERT INTO macaddr8_data VALUES (15, '08:00:2b:01:02:03:04:05'); |
||||||
|
INSERT INTO macaddr8_data VALUES (16, '08-00-2b-01-02-03-04-05'); |
||||||
|
INSERT INTO macaddr8_data VALUES (17, '08002b:0102030405'); |
||||||
|
INSERT INTO macaddr8_data VALUES (18, '08002b-0102030405'); |
||||||
|
INSERT INTO macaddr8_data VALUES (19, '0800.2b01.0203.0405'); |
||||||
|
INSERT INTO macaddr8_data VALUES (20, '08002b01:02030405'); |
||||||
|
INSERT INTO macaddr8_data VALUES (21, '08002b0102030405'); |
||||||
|
|
||||||
|
SELECT * FROM macaddr8_data ORDER BY 1; |
||||||
|
|
||||||
|
CREATE INDEX macaddr8_data_btree ON macaddr8_data USING btree (b); |
||||||
|
CREATE INDEX macaddr8_data_hash ON macaddr8_data USING hash (b); |
||||||
|
|
||||||
|
SELECT a, b, trunc(b) FROM macaddr8_data ORDER BY 2, 1; |
||||||
|
|
||||||
|
SELECT b < '08:00:2b:01:02:04' FROM macaddr8_data WHERE a = 1; -- true |
||||||
|
SELECT b > '08:00:2b:ff:fe:01:02:04' FROM macaddr8_data WHERE a = 1; -- false |
||||||
|
SELECT b > '08:00:2b:ff:fe:01:02:03' FROM macaddr8_data WHERE a = 1; -- false |
||||||
|
SELECT b::macaddr <= '08:00:2b:01:02:04' FROM macaddr8_data WHERE a = 1; -- true |
||||||
|
SELECT b::macaddr >= '08:00:2b:01:02:04' FROM macaddr8_data WHERE a = 1; -- false |
||||||
|
SELECT b = '08:00:2b:ff:fe:01:02:03' FROM macaddr8_data WHERE a = 1; -- true |
||||||
|
SELECT b::macaddr <> '08:00:2b:01:02:04'::macaddr FROM macaddr8_data WHERE a = 1; -- true |
||||||
|
SELECT b::macaddr <> '08:00:2b:01:02:03'::macaddr FROM macaddr8_data WHERE a = 1; -- false |
||||||
|
|
||||||
|
SELECT b < '08:00:2b:01:02:03:04:06' FROM macaddr8_data WHERE a = 15; -- true |
||||||
|
SELECT b > '08:00:2b:01:02:03:04:06' FROM macaddr8_data WHERE a = 15; -- false |
||||||
|
SELECT b > '08:00:2b:01:02:03:04:05' FROM macaddr8_data WHERE a = 15; -- false |
||||||
|
SELECT b <= '08:00:2b:01:02:03:04:06' FROM macaddr8_data WHERE a = 15; -- true |
||||||
|
SELECT b >= '08:00:2b:01:02:03:04:06' FROM macaddr8_data WHERE a = 15; -- false |
||||||
|
SELECT b = '08:00:2b:01:02:03:04:05' FROM macaddr8_data WHERE a = 15; -- true |
||||||
|
SELECT b <> '08:00:2b:01:02:03:04:06' FROM macaddr8_data WHERE a = 15; -- true |
||||||
|
SELECT b <> '08:00:2b:01:02:03:04:05' FROM macaddr8_data WHERE a = 15; -- false |
||||||
|
|
||||||
|
SELECT ~b FROM macaddr8_data; |
||||||
|
SELECT b & '00:00:00:ff:ff:ff' FROM macaddr8_data; |
||||||
|
SELECT b | '01:02:03:04:05:06' FROM macaddr8_data; |
||||||
|
|
||||||
|
DROP TABLE macaddr8_data; |
Loading…
Reference in new issue