diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index ff9b8b0853e2ddb229c902d733828d8667f7e93d..43b72f695c2c2aa7723dfb9250849d2626c83fd9 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -8300,7 +8300,9 @@ CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'purple <para> The <type>macaddr</type> type also supports the standard relational operators (<literal>></literal>, <literal><=</literal>, etc.) for - lexicographical ordering. + lexicographical ordering, and the bitwise arithmetic operators + (<literal>~</literal>, <literal>&</literal> and <literal>|</literal>) + for NOT, AND and OR. </para> </sect1> diff --git a/src/backend/utils/adt/mac.c b/src/backend/utils/adt/mac.c index 333f4bca467fef42781c86d6e18b30b7644b9944..958ff54d73ee8b7666db51c7057ad97416066e66 100644 --- a/src/backend/utils/adt/mac.c +++ b/src/backend/utils/adt/mac.c @@ -241,6 +241,59 @@ hashmacaddr(PG_FUNCTION_ARGS) return hash_any((unsigned char *) key, sizeof(macaddr)); } +/* + * Arithmetic functions: bitwise NOT, AND, OR. + */ +Datum +macaddr_not(PG_FUNCTION_ARGS) +{ + macaddr *addr = PG_GETARG_MACADDR_P(0); + macaddr *result; + + result = (macaddr *) palloc(sizeof(macaddr)); + result->a = ~addr->a; + result->b = ~addr->b; + result->c = ~addr->c; + result->d = ~addr->d; + result->e = ~addr->e; + result->f = ~addr->f; + PG_RETURN_MACADDR_P(result); +} + +Datum +macaddr_and(PG_FUNCTION_ARGS) +{ + macaddr *addr1 = PG_GETARG_MACADDR_P(0); + macaddr *addr2 = PG_GETARG_MACADDR_P(1); + macaddr *result; + + result = (macaddr *) palloc(sizeof(macaddr)); + 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; + PG_RETURN_MACADDR_P(result); +} + +Datum +macaddr_or(PG_FUNCTION_ARGS) +{ + macaddr *addr1 = PG_GETARG_MACADDR_P(0); + macaddr *addr2 = PG_GETARG_MACADDR_P(1); + macaddr *result; + + result = (macaddr *) palloc(sizeof(macaddr)); + 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; + PG_RETURN_MACADDR_P(result); +} + /* * Truncation function to allow comparing mac manufacturers. * From suggestion by Alex Pilosov <alex@pilosoft.com> diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 9e799c6a1037f84c322982316ea7d1154ee9ec61..285fae3e4abb804624778279c3f691a6fe5329ad 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 201201191 +#define CATALOG_VERSION_NO 201201192 #endif diff --git a/src/include/catalog/pg_operator.h b/src/include/catalog/pg_operator.h index f19865dd08371970ab412d9d57d99d1e4821eec8..ead5af6d80cde45efaa41fb6540c91cffca2d294 100644 --- a/src/include/catalog/pg_operator.h +++ b/src/include/catalog/pg_operator.h @@ -1116,6 +1116,13 @@ DESCR("greater than"); DATA(insert OID = 1225 ( ">=" PGNSP PGUID b f f 829 829 16 1223 1222 macaddr_ge scalargtsel scalargtjoinsel )); DESCR("greater than or equal"); +DATA(insert OID = 3147 ( "~" PGNSP PGUID l f f 0 829 829 0 0 macaddr_not - - )); +DESCR("bitwise not"); +DATA(insert OID = 3148 ( "&" PGNSP PGUID b f f 829 829 829 0 0 macaddr_and - - )); +DESCR("bitwise and"); +DATA(insert OID = 3149 ( "|" PGNSP PGUID b f f 829 829 829 0 0 macaddr_or - - )); +DESCR("bitwise or"); + /* INET type (these also support CIDR via implicit cast) */ DATA(insert OID = 1201 ( "=" PGNSP PGUID b t t 869 869 16 1201 1202 network_eq eqsel eqjoinsel )); DESCR("equal"); diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index 9994468571c1ab4b6bc914970cb84836d992ea75..b6ac1959cc1583536918fa7e2246ee83f719870b 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -2039,6 +2039,9 @@ DATA(insert OID = 834 ( macaddr_ge PGNSP PGUID 12 1 0 0 0 f f f t f i 2 0 16 DATA(insert OID = 835 ( macaddr_ne PGNSP PGUID 12 1 0 0 0 f f f t f i 2 0 16 "829 829" _null_ _null_ _null_ _null_ macaddr_ne _null_ _null_ _null_ )); DATA(insert OID = 836 ( macaddr_cmp PGNSP PGUID 12 1 0 0 0 f f f t f i 2 0 23 "829 829" _null_ _null_ _null_ _null_ macaddr_cmp _null_ _null_ _null_ )); DESCR("less-equal-greater"); +DATA(insert OID = 3144 ( macaddr_not PGNSP PGUID 12 1 0 0 0 f f f t f i 1 0 829 "829" _null_ _null_ _null_ _null_ macaddr_not _null_ _null_ _null_ )); +DATA(insert OID = 3145 ( macaddr_and PGNSP PGUID 12 1 0 0 0 f f f t f i 2 0 829 "829 829" _null_ _null_ _null_ _null_ macaddr_and _null_ _null_ _null_ )); +DATA(insert OID = 3146 ( macaddr_or PGNSP PGUID 12 1 0 0 0 f f f t f i 2 0 829 "829 829" _null_ _null_ _null_ _null_ macaddr_or _null_ _null_ _null_ )); /* for inet type support */ DATA(insert OID = 910 ( inet_in PGNSP PGUID 12 1 0 0 0 f f f t f i 1 0 869 "2275" _null_ _null_ _null_ _null_ inet_in _null_ _null_ _null_ )); diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index 46b2f3b245224e45452c491ac32a403a3c5f9639..68179d550f899b6989a91f2609837e99312330f6 100644 --- a/src/include/utils/builtins.h +++ b/src/include/utils/builtins.h @@ -900,6 +900,9 @@ extern Datum macaddr_eq(PG_FUNCTION_ARGS); extern Datum macaddr_ge(PG_FUNCTION_ARGS); extern Datum macaddr_gt(PG_FUNCTION_ARGS); extern Datum macaddr_ne(PG_FUNCTION_ARGS); +extern Datum macaddr_not(PG_FUNCTION_ARGS); +extern Datum macaddr_and(PG_FUNCTION_ARGS); +extern Datum macaddr_or(PG_FUNCTION_ARGS); extern Datum macaddr_trunc(PG_FUNCTION_ARGS); extern Datum hashmacaddr(PG_FUNCTION_ARGS); diff --git a/src/test/regress/expected/macaddr.out b/src/test/regress/expected/macaddr.out index 0b2a96d2f7abfcf4359e8b28ea8342990c9b671b..50d0369139a84c00d2ca58c887621097d48281ea 100644 --- a/src/test/regress/expected/macaddr.out +++ b/src/test/regress/expected/macaddr.out @@ -103,4 +103,52 @@ SELECT b <> '08:00:2b:01:02:03' FROM macaddr_data WHERE a = 1; -- false f (1 row) +SELECT ~b FROM macaddr_data; + ?column? +------------------- + f7:ff:d4:fe:fd:fc + f7:ff:d4:fe:fd:fc + f7:ff:d4:fe:fd:fc + f7:ff:d4:fe:fd:fc + f7:ff:d4:fe:fd:fc + f7:ff:d4:fe:fd:fc + f7:ff:d4:fe:fd:fb + f7:ff:d4:fe:fd:fd + f7:ff:d5:fe:fd:fc + f7:ff:d3:fe:fd:fc + f7:ff:d5:fe:fd:fb +(11 rows) + +SELECT b & '00:00:00:ff:ff:ff' FROM macaddr_data; + ?column? +------------------- + 00:00:00:01:02:03 + 00:00:00:01:02:03 + 00:00:00:01:02:03 + 00:00:00:01:02:03 + 00:00:00:01:02:03 + 00:00:00:01:02:03 + 00:00:00:01:02:04 + 00:00:00:01:02:02 + 00:00:00:01:02:03 + 00:00:00:01:02:03 + 00:00:00:01:02:04 +(11 rows) + +SELECT b | '01:02:03:04:05:06' FROM macaddr_data; + ?column? +------------------- + 09:02:2b:05:07:07 + 09:02:2b:05:07:07 + 09:02:2b:05:07:07 + 09:02:2b:05:07:07 + 09:02:2b:05:07:07 + 09:02:2b:05:07:07 + 09:02:2b:05:07:06 + 09:02:2b:05:07:06 + 09:02:2b:05:07:07 + 09:02:2f:05:07:07 + 09:02:2b:05:07:06 +(11 rows) + DROP TABLE macaddr_data; diff --git a/src/test/regress/sql/macaddr.sql b/src/test/regress/sql/macaddr.sql index ce8d920932934f712553c2fa6ce9c184df1be949..1ccf501722f781361b6a8cb5458c5bc04544845d 100644 --- a/src/test/regress/sql/macaddr.sql +++ b/src/test/regress/sql/macaddr.sql @@ -35,4 +35,8 @@ SELECT b = '08:00:2b:01:02:03' FROM macaddr_data WHERE a = 1; -- true SELECT b <> '08:00:2b:01:02:04' FROM macaddr_data WHERE a = 1; -- true SELECT b <> '08:00:2b:01:02:03' FROM macaddr_data WHERE a = 1; -- false +SELECT ~b FROM macaddr_data; +SELECT b & '00:00:00:ff:ff:ff' FROM macaddr_data; +SELECT b | '01:02:03:04:05:06' FROM macaddr_data; + DROP TABLE macaddr_data;