diff options
author | Alvaro Herrera <alvherre@alvh.no-ip.org> | 2015-05-05 15:22:24 -0300 |
---|---|---|
committer | Alvaro Herrera <alvherre@alvh.no-ip.org> | 2015-05-05 15:22:24 -0300 |
commit | 3b6db1f445e14bd189ebc99ce1e5535a1c624613 (patch) | |
tree | 0b2f037f21af6ed3ae5334c29491bc9ebe5f8e3f /src/backend/utils/adt/network.c | |
parent | 456ff0863851d70dce679ca3f631392589e31a33 (diff) | |
download | postgresql-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.c | 52 |
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. |