diff options
author | Stephen Frost <sfrost@snowman.net> | 2017-03-15 11:16:25 -0400 |
---|---|---|
committer | Stephen Frost <sfrost@snowman.net> | 2017-03-15 11:16:25 -0400 |
commit | c7a9fa399d557c6366222e90b35db31e45d25678 (patch) | |
tree | 1c66b20d56331d8ab5160eb75ba37c9e6b8d929e /src | |
parent | 42bdaebf161841c8e248b197b7319779b8730323 (diff) | |
download | postgresql-c7a9fa399d557c6366222e90b35db31e45d25678.tar.gz postgresql-c7a9fa399d557c6366222e90b35db31e45d25678.zip |
Add support for EUI-64 MAC addresses as macaddr8
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.com
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/utils/adt/Makefile | 2 | ||||
-rw-r--r-- | src/backend/utils/adt/mac.c | 13 | ||||
-rw-r--r-- | src/backend/utils/adt/mac8.c | 560 | ||||
-rw-r--r-- | src/backend/utils/adt/network.c | 10 | ||||
-rw-r--r-- | src/backend/utils/adt/selfuncs.c | 1 | ||||
-rw-r--r-- | src/include/catalog/pg_amop.h | 18 | ||||
-rw-r--r-- | src/include/catalog/pg_amproc.h | 7 | ||||
-rw-r--r-- | src/include/catalog/pg_cast.h | 6 | ||||
-rw-r--r-- | src/include/catalog/pg_opclass.h | 3 | ||||
-rw-r--r-- | src/include/catalog/pg_operator.h | 23 | ||||
-rw-r--r-- | src/include/catalog/pg_opfamily.h | 3 | ||||
-rw-r--r-- | src/include/catalog/pg_proc.h | 37 | ||||
-rw-r--r-- | src/include/catalog/pg_type.h | 4 | ||||
-rw-r--r-- | src/include/utils/inet.h | 22 | ||||
-rw-r--r-- | src/test/regress/expected/macaddr8.out | 354 | ||||
-rw-r--r-- | src/test/regress/expected/opr_sanity.out | 6 | ||||
-rw-r--r-- | src/test/regress/parallel_schedule | 2 | ||||
-rw-r--r-- | src/test/regress/serial_schedule | 1 | ||||
-rw-r--r-- | src/test/regress/sql/macaddr8.sql | 89 |
19 files changed, 1153 insertions, 8 deletions
diff --git a/src/backend/utils/adt/Makefile b/src/backend/utils/adt/Makefile index 0f512753e49..1fb018416ef 100644 --- a/src/backend/utils/adt/Makefile +++ b/src/backend/utils/adt/Makefile @@ -16,7 +16,7 @@ OBJS = acl.o amutils.o arrayfuncs.o array_expanded.o array_selfuncs.o \ float.o format_type.o formatting.o genfile.o \ geo_ops.o geo_selfuncs.o geo_spgist.o inet_cidr_ntop.o inet_net_pton.o \ int.o int8.o json.o jsonb.o jsonb_gin.o jsonb_op.o jsonb_util.o \ - jsonfuncs.o like.o lockfuncs.o mac.o misc.o nabstime.o name.o \ + jsonfuncs.o like.o lockfuncs.o mac.o mac8.o misc.o nabstime.o name.o \ network.o network_gist.o network_selfuncs.o network_spgist.o \ numeric.o numutils.o oid.o oracle_compat.o \ orderedsetaggs.o pg_locale.o pg_lsn.o pg_upgrade_support.o \ diff --git a/src/backend/utils/adt/mac.c b/src/backend/utils/adt/mac.c index 2270b223eab..a1e9c53b730 100644 --- a/src/backend/utils/adt/mac.c +++ b/src/backend/utils/adt/mac.c @@ -1,7 +1,14 @@ -/* - * PostgreSQL type definitions for MAC addresses. +/*------------------------------------------------------------------------- + * + * mac.c + * PostgreSQL type definitions for 6 byte, EUI-48, MAC addresses. + * + * Portions Copyright (c) 1998-2017, PostgreSQL Global Development Group + * + * IDENTIFICATION + * src/backend/utils/adt/mac.c * - * src/backend/utils/adt/mac.c + *------------------------------------------------------------------------- */ #include "postgres.h" diff --git a/src/backend/utils/adt/mac8.c b/src/backend/utils/adt/mac8.c new file mode 100644 index 00000000000..31f57c30479 --- /dev/null +++ b/src/backend/utils/adt/mac8.c @@ -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); +} diff --git a/src/backend/utils/adt/network.c b/src/backend/utils/adt/network.c index dbc557e5838..2459adcf9fd 100644 --- a/src/backend/utils/adt/network.c +++ b/src/backend/utils/adt/network.c @@ -934,6 +934,16 @@ convert_network_to_scalar(Datum value, Oid typid) res += (mac->d << 16) | (mac->e << 8) | (mac->f); return res; } + case MACADDR8OID: + { + macaddr8 *mac = DatumGetMacaddr8P(value); + double res; + + res = (mac->a << 24) | (mac->b << 16) | (mac->c << 8) | (mac->d); + res *= ((double) 256) * 256 * 256 * 256; + res += (mac->e << 24) | (mac->f << 16) | (mac->g << 8) | (mac->h); + return res; + } } /* diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c index 04bd9b95b27..bb9a5446861 100644 --- a/src/backend/utils/adt/selfuncs.c +++ b/src/backend/utils/adt/selfuncs.c @@ -3800,6 +3800,7 @@ convert_to_scalar(Datum value, Oid valuetypid, double *scaledvalue, case INETOID: case CIDROID: case MACADDROID: + case MACADDR8OID: *scaledvalue = convert_network_to_scalar(value, valuetypid); *scaledlobound = convert_network_to_scalar(lobound, boundstypid); *scaledhibound = convert_network_to_scalar(hibound, boundstypid); diff --git a/src/include/catalog/pg_amop.h b/src/include/catalog/pg_amop.h index 0251664e4a1..da0228de6bb 100644 --- a/src/include/catalog/pg_amop.h +++ b/src/include/catalog/pg_amop.h @@ -373,6 +373,16 @@ DATA(insert ( 1984 829 829 4 s 1225 403 0 )); DATA(insert ( 1984 829 829 5 s 1224 403 0 )); /* + * btree macaddr8 + */ + +DATA(insert ( 3371 774 774 1 s 3364 403 0 )); +DATA(insert ( 3371 774 774 2 s 3365 403 0 )); +DATA(insert ( 3371 774 774 3 s 3362 403 0 )); +DATA(insert ( 3371 774 774 4 s 3367 403 0 )); +DATA(insert ( 3371 774 774 5 s 3366 403 0 )); + +/* * btree network */ @@ -553,6 +563,8 @@ DATA(insert ( 1977 20 23 1 s 416 405 0 )); DATA(insert ( 1983 1186 1186 1 s 1330 405 0 )); /* macaddr_ops */ DATA(insert ( 1985 829 829 1 s 1220 405 0 )); +/* macaddr8_ops */ +DATA(insert ( 3372 774 774 1 s 3362 405 0 )); /* name_ops */ DATA(insert ( 1987 19 19 1 s 93 405 0 )); /* oid_ops */ @@ -999,6 +1011,12 @@ DATA(insert ( 4074 829 829 2 s 1223 3580 0 )); DATA(insert ( 4074 829 829 3 s 1220 3580 0 )); DATA(insert ( 4074 829 829 4 s 1225 3580 0 )); DATA(insert ( 4074 829 829 5 s 1224 3580 0 )); +/* minmax macaddr8 */ +DATA(insert ( 4109 774 774 1 s 3364 3580 0 )); +DATA(insert ( 4109 774 774 2 s 3365 3580 0 )); +DATA(insert ( 4109 774 774 3 s 3362 3580 0 )); +DATA(insert ( 4109 774 774 4 s 3367 3580 0 )); +DATA(insert ( 4109 774 774 5 s 3366 3580 0 )); /* minmax inet */ DATA(insert ( 4075 869 869 1 s 1203 3580 0 )); DATA(insert ( 4075 869 869 2 s 1204 3580 0 )); diff --git a/src/include/catalog/pg_amproc.h b/src/include/catalog/pg_amproc.h index f1a52ce3e0a..a87ec423e1c 100644 --- a/src/include/catalog/pg_amproc.h +++ b/src/include/catalog/pg_amproc.h @@ -142,6 +142,7 @@ DATA(insert ( 2968 2950 2950 2 3300 )); DATA(insert ( 2994 2249 2249 1 2987 )); DATA(insert ( 3194 2249 2249 1 3187 )); DATA(insert ( 3253 3220 3220 1 3251 )); +DATA(insert ( 3371 774 774 1 4119 )); DATA(insert ( 3522 3500 3500 1 3514 )); DATA(insert ( 3626 3614 3614 1 3622 )); DATA(insert ( 3683 3615 3615 1 3668 )); @@ -182,6 +183,7 @@ DATA(insert ( 2231 1042 1042 1 1080 )); DATA(insert ( 2235 1033 1033 1 329 )); DATA(insert ( 2969 2950 2950 1 2963 )); DATA(insert ( 3254 3220 3220 1 3252 )); +DATA(insert ( 3372 774 774 1 328 )); DATA(insert ( 3523 3500 3500 1 3515 )); DATA(insert ( 3903 3831 3831 1 3902 )); DATA(insert ( 4034 3802 3802 1 4045 )); @@ -414,6 +416,11 @@ DATA(insert ( 4074 829 829 1 3383 )); DATA(insert ( 4074 829 829 2 3384 )); DATA(insert ( 4074 829 829 3 3385 )); DATA(insert ( 4074 829 829 4 3386 )); +/* minmax macaddr8 */ +DATA(insert ( 4109 774 774 1 3383 )); +DATA(insert ( 4109 774 774 2 3384 )); +DATA(insert ( 4109 774 774 3 3385 )); +DATA(insert ( 4109 774 774 4 3386 )); /* minmax inet */ DATA(insert ( 4075 869 869 1 3383 )); DATA(insert ( 4075 869 869 2 3384 )); diff --git a/src/include/catalog/pg_cast.h b/src/include/catalog/pg_cast.h index 80a40ab1284..ce8dc59e5af 100644 --- a/src/include/catalog/pg_cast.h +++ b/src/include/catalog/pg_cast.h @@ -304,6 +304,12 @@ DATA(insert ( 718 603 1480 e f )); DATA(insert ( 718 604 1544 e f )); /* + * MAC address category + */ +DATA(insert ( 829 774 4123 i f )); +DATA(insert ( 774 829 4124 i f )); + +/* * INET category */ DATA(insert ( 650 869 0 i b )); diff --git a/src/include/catalog/pg_opclass.h b/src/include/catalog/pg_opclass.h index 0cde14c25dc..5819d5309f1 100644 --- a/src/include/catalog/pg_opclass.h +++ b/src/include/catalog/pg_opclass.h @@ -127,6 +127,8 @@ DATA(insert ( 403 interval_ops PGNSP PGUID 1982 1186 t 0 )); DATA(insert ( 405 interval_ops PGNSP PGUID 1983 1186 t 0 )); DATA(insert ( 403 macaddr_ops PGNSP PGUID 1984 829 t 0 )); DATA(insert ( 405 macaddr_ops PGNSP PGUID 1985 829 t 0 )); +DATA(insert ( 403 macaddr8_ops PGNSP PGUID 3371 774 t 0 )); +DATA(insert ( 405 macaddr8_ops PGNSP PGUID 3372 774 t 0 )); /* * Here's an ugly little hack to save space in the system catalog indexes. * btree doesn't ordinarily allow a storage type different from input type; @@ -224,6 +226,7 @@ DATA(insert ( 3580 float8_minmax_ops PGNSP PGUID 4070 701 t 701 )); DATA(insert ( 3580 abstime_minmax_ops PGNSP PGUID 4072 702 t 702 )); DATA(insert ( 3580 reltime_minmax_ops PGNSP PGUID 4073 703 t 703 )); DATA(insert ( 3580 macaddr_minmax_ops PGNSP PGUID 4074 829 t 829 )); +DATA(insert ( 3580 macaddr8_minmax_ops PGNSP PGUID 4109 774 t 774 )); DATA(insert ( 3580 inet_minmax_ops PGNSP PGUID 4075 869 f 869 )); DATA(insert ( 3580 inet_inclusion_ops PGNSP PGUID 4102 869 t 869 )); DATA(insert ( 3580 bpchar_minmax_ops PGNSP PGUID 4076 1042 t 1042 )); diff --git a/src/include/catalog/pg_operator.h b/src/include/catalog/pg_operator.h index 45feb69b93c..fe8795ac8bf 100644 --- a/src/include/catalog/pg_operator.h +++ b/src/include/catalog/pg_operator.h @@ -1119,7 +1119,7 @@ DESCR("equal"); DATA(insert OID = 1617 ( "#" PGNSP PGUID b f f 628 628 600 1617 0 line_interpt - - )); DESCR("intersection point"); -/* MAC type */ +/* MACADDR type */ DATA(insert OID = 1220 ( "=" PGNSP PGUID b t t 829 829 16 1220 1221 macaddr_eq eqsel eqjoinsel )); DESCR("equal"); DATA(insert OID = 1221 ( "<>" PGNSP PGUID b f f 829 829 16 1221 1220 macaddr_ne neqsel neqjoinsel )); @@ -1140,6 +1140,27 @@ DESCR("bitwise and"); DATA(insert OID = 3149 ( "|" PGNSP PGUID b f f 829 829 829 0 0 macaddr_or - - )); DESCR("bitwise or"); +/* MACADDR8 type */ +DATA(insert OID = 3362 ( "=" PGNSP PGUID b t t 774 774 16 3362 3363 macaddr8_eq eqsel eqjoinsel )); +DESCR("equal"); +DATA(insert OID = 3363 ( "<>" PGNSP PGUID b f f 774 774 16 3363 3362 macaddr8_ne neqsel neqjoinsel )); +DESCR("not equal"); +DATA(insert OID = 3364 ( "<" PGNSP PGUID b f f 774 774 16 3366 3367 macaddr8_lt scalarltsel scalarltjoinsel )); +DESCR("less than"); +DATA(insert OID = 3365 ( "<=" PGNSP PGUID b f f 774 774 16 3367 3366 macaddr8_le scalarltsel scalarltjoinsel )); +DESCR("less than or equal"); +DATA(insert OID = 3366 ( ">" PGNSP PGUID b f f 774 774 16 3364 3365 macaddr8_gt scalargtsel scalargtjoinsel )); +DESCR("greater than"); +DATA(insert OID = 3367 ( ">=" PGNSP PGUID b f f 774 774 16 3365 3364 macaddr8_ge scalargtsel scalargtjoinsel )); +DESCR("greater than or equal"); + +DATA(insert OID = 3368 ( "~" PGNSP PGUID l f f 0 774 774 0 0 macaddr8_not - - )); +DESCR("bitwise not"); +DATA(insert OID = 3369 ( "&" PGNSP PGUID b f f 774 774 774 0 0 macaddr8_and - - )); +DESCR("bitwise and"); +DATA(insert OID = 3370 ( "|" PGNSP PGUID b f f 774 774 774 0 0 macaddr8_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_opfamily.h b/src/include/catalog/pg_opfamily.h index bd673fe59ba..546527aa8e3 100644 --- a/src/include/catalog/pg_opfamily.h +++ b/src/include/catalog/pg_opfamily.h @@ -87,6 +87,8 @@ DATA(insert OID = 1982 ( 403 interval_ops PGNSP PGUID )); DATA(insert OID = 1983 ( 405 interval_ops PGNSP PGUID )); DATA(insert OID = 1984 ( 403 macaddr_ops PGNSP PGUID )); DATA(insert OID = 1985 ( 405 macaddr_ops PGNSP PGUID )); +DATA(insert OID = 3371 ( 403 macaddr8_ops PGNSP PGUID )); +DATA(insert OID = 3372 ( 405 macaddr8_ops PGNSP PGUID )); DATA(insert OID = 1986 ( 403 name_ops PGNSP PGUID )); #define NAME_BTREE_FAM_OID 1986 DATA(insert OID = 1987 ( 405 name_ops PGNSP PGUID )); @@ -171,6 +173,7 @@ DATA(insert OID = 4070 ( 3580 float_minmax_ops PGNSP PGUID )); DATA(insert OID = 4072 ( 3580 abstime_minmax_ops PGNSP PGUID )); DATA(insert OID = 4073 ( 3580 reltime_minmax_ops PGNSP PGUID )); DATA(insert OID = 4074 ( 3580 macaddr_minmax_ops PGNSP PGUID )); +DATA(insert OID = 4109 ( 3580 macaddr8_minmax_ops PGNSP PGUID )); DATA(insert OID = 4075 ( 3580 network_minmax_ops PGNSP PGUID )); DATA(insert OID = 4102 ( 3580 network_inclusion_ops PGNSP PGUID )); DATA(insert OID = 4076 ( 3580 bpchar_minmax_ops PGNSP PGUID )); diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index ec4aedb8516..3d5d8660718 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -692,6 +692,8 @@ DATA(insert OID = 422 ( hashinet PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 DESCR("hash"); DATA(insert OID = 432 ( hash_numeric PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 23 "1700" _null_ _null_ _null_ _null_ _null_ hash_numeric _null_ _null_ _null_ )); DESCR("hash"); +DATA(insert OID = 328 ( hashmacaddr8 PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 23 "774" _null_ _null_ _null_ _null_ _null_ hashmacaddr8 _null_ _null_ _null_ )); +DESCR("hash"); DATA(insert OID = 438 ( num_nulls PGNSP PGUID 12 1 0 2276 0 f f f f f f i s 1 0 23 "2276" "{2276}" "{v}" _null_ _null_ _null_ pg_num_nulls _null_ _null_ _null_ )); DESCR("count the number of NULL arguments"); @@ -2098,14 +2100,14 @@ DESCR("get bit"); DATA(insert OID = 3033 ( set_bit PGNSP PGUID 12 1 0 0 0 f f f f t f i s 3 0 1560 "1560 23 23" _null_ _null_ _null_ _null_ _null_ bitsetbit _null_ _null_ _null_ )); DESCR("set bit"); -/* for mac type support */ +/* for macaddr type support */ DATA(insert OID = 436 ( macaddr_in PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 829 "2275" _null_ _null_ _null_ _null_ _null_ macaddr_in _null_ _null_ _null_ )); DESCR("I/O"); DATA(insert OID = 437 ( macaddr_out PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 2275 "829" _null_ _null_ _null_ _null_ _null_ macaddr_out _null_ _null_ _null_ )); DESCR("I/O"); DATA(insert OID = 753 ( trunc PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 829 "829" _null_ _null_ _null_ _null_ _null_ macaddr_trunc _null_ _null_ _null_ )); -DESCR("MAC manufacturer fields"); +DESCR("MACADDR manufacturer fields"); DATA(insert OID = 830 ( macaddr_eq PGNSP PGUID 12 1 0 0 0 f f f t t f i s 2 0 16 "829 829" _null_ _null_ _null_ _null_ _null_ macaddr_eq _null_ _null_ _null_ )); DATA(insert OID = 831 ( macaddr_lt PGNSP PGUID 12 1 0 0 0 f f f t t f i s 2 0 16 "829 829" _null_ _null_ _null_ _null_ _null_ macaddr_lt _null_ _null_ _null_ )); @@ -2119,6 +2121,33 @@ DATA(insert OID = 3144 ( macaddr_not PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 DATA(insert OID = 3145 ( macaddr_and PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 829 "829 829" _null_ _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 f t f i s 2 0 829 "829 829" _null_ _null_ _null_ _null_ _null_ macaddr_or _null_ _null_ _null_ )); +/* for macaddr8 type support */ +DATA(insert OID = 4110 ( macaddr8_in PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 774 "2275" _null_ _null_ _null_ _null_ _null_ macaddr8_in _null_ _null_ _null_ )); +DESCR("I/O"); +DATA(insert OID = 4111 ( macaddr8_out PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 2275 "774" _null_ _null_ _null_ _null_ _null_ macaddr8_out _null_ _null_ _null_ )); +DESCR("I/O"); + +DATA(insert OID = 4112 ( trunc PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 774 "774" _null_ _null_ _null_ _null_ _null_ macaddr8_trunc _null_ _null_ _null_ )); +DESCR("MACADDR8 manufacturer fields"); + +DATA(insert OID = 4113 ( macaddr8_eq PGNSP PGUID 12 1 0 0 0 f f f t t f i s 2 0 16 "774 774" _null_ _null_ _null_ _null_ _null_ macaddr8_eq _null_ _null_ _null_ )); +DATA(insert OID = 4114 ( macaddr8_lt PGNSP PGUID 12 1 0 0 0 f f f t t f i s 2 0 16 "774 774" _null_ _null_ _null_ _null_ _null_ macaddr8_lt _null_ _null_ _null_ )); +DATA(insert OID = 4115 ( macaddr8_le PGNSP PGUID 12 1 0 0 0 f f f t t f i s 2 0 16 "774 774" _null_ _null_ _null_ _null_ _null_ macaddr8_le _null_ _null_ _null_ )); +DATA(insert OID = 4116 ( macaddr8_gt PGNSP PGUID 12 1 0 0 0 f f f t t f i s 2 0 16 "774 774" _null_ _null_ _null_ _null_ _null_ macaddr8_gt _null_ _null_ _null_ )); +DATA(insert OID = 4117 ( macaddr8_ge PGNSP PGUID 12 1 0 0 0 f f f t t f i s 2 0 16 "774 774" _null_ _null_ _null_ _null_ _null_ macaddr8_ge _null_ _null_ _null_ )); +DATA(insert OID = 4118 ( macaddr8_ne PGNSP PGUID 12 1 0 0 0 f f f t t f i s 2 0 16 "774 774" _null_ _null_ _null_ _null_ _null_ macaddr8_ne _null_ _null_ _null_ )); +DATA(insert OID = 4119 ( macaddr8_cmp PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 23 "774 774" _null_ _null_ _null_ _null_ _null_ macaddr8_cmp _null_ _null_ _null_ )); +DESCR("less-equal-greater"); +DATA(insert OID = 4120 ( macaddr8_not PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 774 "774" _null_ _null_ _null_ _null_ _null_ macaddr8_not _null_ _null_ _null_ )); +DATA(insert OID = 4121 ( macaddr8_and PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 774 "774 774" _null_ _null_ _null_ _null_ _null_ macaddr8_and _null_ _null_ _null_ )); +DATA(insert OID = 4122 ( macaddr8_or PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 774 "774 774" _null_ _null_ _null_ _null_ _null_ macaddr8_or _null_ _null_ _null_ )); +DATA(insert OID = 4123 ( macaddr8 PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 774 "829" _null_ _null_ _null_ _null_ _null_ macaddrtomacaddr8 _null_ _null_ _null_ )); +DESCR("convert macaddr to macaddr8"); +DATA(insert OID = 4124 ( macaddr PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 829 "774" _null_ _null_ _null_ _null_ _null_ macaddr8tomacaddr _null_ _null_ _null_ )); +DESCR("convert macaddr8 to macaddr"); +DATA(insert OID = 4125 ( macaddr8_set7bit PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 774 "774" _null_ _null_ _null_ _null_ _null_ macaddr8_set7bit _null_ _null_ _null_ )); +DESCR("set 7th bit in macaddr8"); + /* for inet type support */ DATA(insert OID = 910 ( inet_in PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 869 "2275" _null_ _null_ _null_ _null_ _null_ inet_in _null_ _null_ _null_ )); DESCR("I/O"); @@ -4056,6 +4085,10 @@ DATA(insert OID = 3120 ( void_recv PGNSP PGUID 12 1 0 0 0 f f f f t f i s DESCR("I/O"); DATA(insert OID = 3121 ( void_send PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 17 "2278" _null_ _null_ _null_ _null_ _null_ void_send _null_ _null_ _null_ )); DESCR("I/O"); +DATA(insert OID = 3446 ( macaddr8_recv PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 774 "2281" _null_ _null_ _null_ _null_ _null_ macaddr8_recv _null_ _null_ _null_ )); +DESCR("I/O"); +DATA(insert OID = 3447 ( macaddr8_send PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 17 "774" _null_ _null_ _null_ _null_ _null_ macaddr8_send _null_ _null_ _null_ )); +DESCR("I/O"); /* System-view support functions with pretty-print option */ DATA(insert OID = 2504 ( pg_get_ruledef PGNSP PGUID 12 1 0 0 0 f f f f t f s s 2 0 25 "26 16" _null_ _null_ _null_ _null_ _null_ pg_get_ruledef_ext _null_ _null_ _null_ )); diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h index 6e4c65e6ad3..9f61238179b 100644 --- a/src/include/catalog/pg_type.h +++ b/src/include/catalog/pg_type.h @@ -441,6 +441,9 @@ DESCR("IP address/netmask, host address, netmask optional"); DATA(insert OID = 650 ( cidr PGNSP PGUID -1 f b I f t \054 0 0 651 cidr_in cidr_out cidr_recv cidr_send - - - i m f 0 -1 0 0 _null_ _null_ _null_ )); DESCR("network IP address/netmask, network address"); #define CIDROID 650 +DATA(insert OID = 774 ( macaddr8 PGNSP PGUID 8 f b U f t \054 0 0 775 macaddr8_in macaddr8_out macaddr8_recv macaddr8_send - - - i p f 0 -1 0 0 _null_ _null_ _null_ )); +DESCR("XX:XX:XX:XX:XX:XX:XX:XX, MAC address"); +#define MACADDR8OID 774 /* OIDS 900 - 999 */ @@ -482,6 +485,7 @@ DESCR("access control list"); #define ACLITEMOID 1033 DATA(insert OID = 1034 ( _aclitem PGNSP PGUID -1 f b A f t \054 0 1033 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ )); DATA(insert OID = 1040 ( _macaddr PGNSP PGUID -1 f b A f t \054 0 829 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ )); +DATA(insert OID = 775 ( _macaddr8 PGNSP PGUID -1 f b A f t \054 0 774 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ )); DATA(insert OID = 1041 ( _inet PGNSP PGUID -1 f b A f t \054 0 869 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ )); DATA(insert OID = 651 ( _cidr PGNSP PGUID -1 f b A f t \054 0 650 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ )); DATA(insert OID = 1263 ( _cstring PGNSP PGUID -1 f b A f t \054 0 2275 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ )); diff --git a/src/include/utils/inet.h b/src/include/utils/inet.h index b4d7359f19e..7dc179e2556 100644 --- a/src/include/utils/inet.h +++ b/src/include/utils/inet.h @@ -102,6 +102,21 @@ typedef struct macaddr } macaddr; /* + * This is the internal storage format for MAC8 addresses: + */ +typedef struct macaddr8 +{ + unsigned char a; + unsigned char b; + unsigned char c; + unsigned char d; + unsigned char e; + unsigned char f; + unsigned char g; + unsigned char h; +} macaddr8; + +/* * fmgr interface macros */ #define DatumGetInetPP(X) ((inet *) PG_DETOAST_DATUM_PACKED(X)) @@ -111,12 +126,19 @@ typedef struct macaddr /* obsolescent variants */ #define DatumGetInetP(X) ((inet *) PG_DETOAST_DATUM(X)) #define PG_GETARG_INET_P(n) DatumGetInetP(PG_GETARG_DATUM(n)) + /* macaddr is a fixed-length pass-by-reference datatype */ #define DatumGetMacaddrP(X) ((macaddr *) DatumGetPointer(X)) #define MacaddrPGetDatum(X) PointerGetDatum(X) #define PG_GETARG_MACADDR_P(n) DatumGetMacaddrP(PG_GETARG_DATUM(n)) #define PG_RETURN_MACADDR_P(x) return MacaddrPGetDatum(x) +/* macaddr8 is a fixed-length pass-by-reference datatype */ +#define DatumGetMacaddr8P(X) ((macaddr8 *) DatumGetPointer(X)) +#define Macaddr8PGetDatum(X) PointerGetDatum(X) +#define PG_GETARG_MACADDR8_P(n) DatumGetMacaddr8P(PG_GETARG_DATUM(n)) +#define PG_RETURN_MACADDR8_P(x) return Macaddr8PGetDatum(x) + /* * Support functions in network.c */ diff --git a/src/test/regress/expected/macaddr8.out b/src/test/regress/expected/macaddr8.out new file mode 100644 index 00000000000..74f53a121f2 --- /dev/null +++ b/src/test/regress/expected/macaddr8.out @@ -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; diff --git a/src/test/regress/expected/opr_sanity.out b/src/test/regress/expected/opr_sanity.out index 0bcec136c53..64d9dd605fd 100644 --- a/src/test/regress/expected/opr_sanity.out +++ b/src/test/regress/expected/opr_sanity.out @@ -685,6 +685,12 @@ uuid_gt(uuid,uuid) uuid_ne(uuid,uuid) xidneq(xid,xid) xidneqint4(xid,integer) +macaddr8_eq(macaddr8,macaddr8) +macaddr8_lt(macaddr8,macaddr8) +macaddr8_le(macaddr8,macaddr8) +macaddr8_gt(macaddr8,macaddr8) +macaddr8_ge(macaddr8,macaddr8) +macaddr8_ne(macaddr8,macaddr8) -- restore normal output mode \a\t -- List of functions used by libpq's fe-lobj.c diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 9f38349e90f..ea7b5b4aa26 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -23,7 +23,7 @@ test: numerology # ---------- # The second group of parallel tests # ---------- -test: point lseg line box path polygon circle date time timetz timestamp timestamptz interval abstime reltime tinterval inet macaddr tstypes comments +test: point lseg line box path polygon circle date time timetz timestamp timestamptz interval abstime reltime tinterval inet macaddr macaddr8 tstypes comments # ---------- # Another group of parallel tests diff --git a/src/test/regress/serial_schedule b/src/test/regress/serial_schedule index 2987b24ebb4..cf48ea7cc8d 100644 --- a/src/test/regress/serial_schedule +++ b/src/test/regress/serial_schedule @@ -41,6 +41,7 @@ test: reltime test: tinterval test: inet test: macaddr +test: macaddr8 test: tstypes test: comments test: geometry diff --git a/src/test/regress/sql/macaddr8.sql b/src/test/regress/sql/macaddr8.sql new file mode 100644 index 00000000000..57a227c5ab7 --- /dev/null +++ b/src/test/regress/sql/macaddr8.sql @@ -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; |