aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/utils/adt/Makefile2
-rw-r--r--src/backend/utils/adt/mac.c13
-rw-r--r--src/backend/utils/adt/mac8.c560
-rw-r--r--src/backend/utils/adt/network.c10
-rw-r--r--src/backend/utils/adt/selfuncs.c1
-rw-r--r--src/include/catalog/pg_amop.h18
-rw-r--r--src/include/catalog/pg_amproc.h7
-rw-r--r--src/include/catalog/pg_cast.h6
-rw-r--r--src/include/catalog/pg_opclass.h3
-rw-r--r--src/include/catalog/pg_operator.h23
-rw-r--r--src/include/catalog/pg_opfamily.h3
-rw-r--r--src/include/catalog/pg_proc.h37
-rw-r--r--src/include/catalog/pg_type.h4
-rw-r--r--src/include/utils/inet.h22
-rw-r--r--src/test/regress/expected/macaddr8.out354
-rw-r--r--src/test/regress/expected/opr_sanity.out6
-rw-r--r--src/test/regress/parallel_schedule2
-rw-r--r--src/test/regress/serial_schedule1
-rw-r--r--src/test/regress/sql/macaddr8.sql89
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;