On Tue, Dec 13, 2011 at 2:16 PM, Brendan Jurd <dire...@gmail.com> wrote: > On 12 December 2011 15:59, Pavel Stehule <pavel.steh...@gmail.com> wrote: >> 2011/12/12 Brendan Jurd <dire...@gmail.com>: >>> I just bumped into a situation where I wanted to do a little macaddr >>> arithmetic in postgres. I note that the inet type has support for >>> bitwise AND, OR and NOT, as well as subtraction, but macaddr has none >>> of the above. >> >> +1 >> > > Here is a patch for $SUBJECT. I merely added support for ~, & and | > operators for the macaddr type. The patch itself is rather trivial, > and includes regression tests and a doc update.
The patch looks fine except that it uses the OIDs already used in pg_proc.h. Attached is the updated version of the patch, which fixes the above problem. > For the documentation, I did think about adding a new table for the > macaddr operators, but in the end decided it would probably be an > overkill. Agreed. Regards, -- Fujii Masao NIPPON TELEGRAPH AND TELEPHONE CORPORATION NTT Open Source Software Center
*** a/doc/src/sgml/func.sgml --- b/doc/src/sgml/func.sgml *************** *** 8300,8306 **** 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. </para> </sect1> --- 8300,8308 ---- <para> The <type>macaddr</type> type also supports the standard relational operators (<literal>></literal>, <literal><=</literal>, etc.) for ! lexicographical ordering, and the bitwise arithmetic operators ! (<literal>~</literal>, <literal>&</literal> and <literal>|</literal>) ! for NOT, AND and OR. </para> </sect1> *** a/src/backend/utils/adt/mac.c --- b/src/backend/utils/adt/mac.c *************** *** 242,247 **** hashmacaddr(PG_FUNCTION_ARGS) --- 242,300 ---- } /* + * 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 <a...@pilosoft.com> */ *** a/src/include/catalog/pg_operator.h --- b/src/include/catalog/pg_operator.h *************** *** 1116,1121 **** DESCR("greater than"); --- 1116,1128 ---- 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 = 3141 ( "~" PGNSP PGUID l f f 0 829 829 0 0 macaddr_not - - )); + DESCR("bitwise not"); + DATA(insert OID = 3142 ( "&" PGNSP PGUID b f f 829 829 829 0 0 macaddr_and - - )); + DESCR("bitwise and"); + DATA(insert OID = 3143 ( "|" 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"); *** a/src/include/catalog/pg_proc.h --- b/src/include/catalog/pg_proc.h *************** *** 2039,2044 **** DATA(insert OID = 834 ( macaddr_ge PGNSP PGUID 12 1 0 0 0 f f f t f i 2 0 16 --- 2039,2047 ---- 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_ )); *** a/src/include/utils/builtins.h --- b/src/include/utils/builtins.h *************** *** 900,905 **** extern Datum macaddr_eq(PG_FUNCTION_ARGS); --- 900,908 ---- 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); *** a/src/test/regress/expected/macaddr.out --- b/src/test/regress/expected/macaddr.out *************** *** 103,106 **** SELECT b <> '08:00:2b:01:02:03' FROM macaddr_data WHERE a = 1; -- false --- 103,154 ---- 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; *** a/src/test/regress/sql/macaddr.sql --- b/src/test/regress/sql/macaddr.sql *************** *** 35,38 **** SELECT b = '08:00:2b:01:02:03' FROM macaddr_data WHERE a = 1; -- true --- 35,42 ---- 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;
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers