aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/network.c
diff options
context:
space:
mode:
authorAlvaro Herrera <alvherre@alvh.no-ip.org>2015-05-05 15:22:24 -0300
committerAlvaro Herrera <alvherre@alvh.no-ip.org>2015-05-05 15:22:24 -0300
commit3b6db1f445e14bd189ebc99ce1e5535a1c624613 (patch)
tree0b2f037f21af6ed3ae5334c29491bc9ebe5f8e3f /src/backend/utils/adt/network.c
parent456ff0863851d70dce679ca3f631392589e31a33 (diff)
downloadpostgresql-3b6db1f445e14bd189ebc99ce1e5535a1c624613.tar.gz
postgresql-3b6db1f445e14bd189ebc99ce1e5535a1c624613.zip
Add geometry/range functions to support BRIN inclusion
This commit adds the following functions: box(point) -> box bound_box(box, box) -> box inet_same_family(inet, inet) -> bool inet_merge(inet, inet) -> cidr range_merge(anyrange, anyrange) -> anyrange The first of these is also used to implement a new assignment cast from point to box. These functions are the first part of a base to implement an "inclusion" operator class for BRIN, for multidimensional data types. Author: Emre Hasegeli Reviewed by: Andreas Karlsson
Diffstat (limited to 'src/backend/utils/adt/network.c')
-rw-r--r--src/backend/utils/adt/network.c52
1 files changed, 52 insertions, 0 deletions
diff --git a/src/backend/utils/adt/network.c b/src/backend/utils/adt/network.c
index 3a705da6197..1f8469a2cbc 100644
--- a/src/backend/utils/adt/network.c
+++ b/src/backend/utils/adt/network.c
@@ -888,6 +888,58 @@ network_hostmask(PG_FUNCTION_ARGS)
}
/*
+ * Returns true if the addresses are from the same family, or false. Used to
+ * check that we can create a network which contains both of the networks.
+ */
+Datum
+inet_same_family(PG_FUNCTION_ARGS)
+{
+ inet *a1 = PG_GETARG_INET_PP(0);
+ inet *a2 = PG_GETARG_INET_PP(1);
+
+ PG_RETURN_BOOL(ip_family(a1) == ip_family(a2));
+}
+
+/*
+ * Returns the smallest CIDR which contains both of the inputs.
+ */
+Datum
+inet_merge(PG_FUNCTION_ARGS)
+{
+ inet *a1 = PG_GETARG_INET_PP(0),
+ *a2 = PG_GETARG_INET_PP(1),
+ *result;
+ int commonbits;
+
+ if (ip_family(a1) != ip_family(a2))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("cannot merge addresses from different families")));
+
+ commonbits = bitncommon(ip_addr(a1), ip_addr(a2),
+ Min(ip_bits(a1), ip_bits(a2)));
+
+ /* Make sure any unused bits are zeroed. */
+ result = (inet *) palloc0(sizeof(inet));
+
+ ip_family(result) = ip_family(a1);
+ ip_bits(result) = commonbits;
+
+ /* Clone appropriate bytes of the address. */
+ if (commonbits > 0)
+ memcpy(ip_addr(result), ip_addr(a1), (commonbits + 7) / 8);
+
+ /* Clean any unwanted bits in the last partial byte. */
+ if (commonbits % 8 != 0)
+ ip_addr(result)[commonbits / 8] &= ~(0xFF >> (commonbits % 8));
+
+ /* Set varlena header correctly. */
+ SET_INET_VARSIZE(result);
+
+ PG_RETURN_INET_P(result);
+}
+
+/*
* Convert a value of a network datatype to an approximate scalar value.
* This is used for estimating selectivities of inequality operators
* involving network types.