Changeset: a2cd93851a0f for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/a2cd93851a0f
Modified Files:
monetdb5/modules/atoms/inet-46.c
monetdb5/modules/atoms/inet.c
sql/scripts/44_inet46.sql
Branch: inet4+6
Log Message:
Started implementation on contains for inet addresses.
diffs (truncated from 562 to 300 lines):
diff --git a/monetdb5/modules/atoms/inet-46.c b/monetdb5/modules/atoms/inet-46.c
--- a/monetdb5/modules/atoms/inet-46.c
+++ b/monetdb5/modules/atoms/inet-46.c
@@ -43,6 +43,100 @@ INETinet42inet4(inet4 *ret, const inet4
return MAL_SUCCEED;
}
+static inline uint32_t
+inet42int(const inet4 *ip)
+{
+ return (ip->quad[0] << 24) | (ip->quad[1] << 16) |
+ (ip->quad[2] << 8) | ip->quad[3];
+}
+
+static bte
+inet4containsinet4(const inet4 *ip1, const bte *msk1, const inet4 *ip2, const
bte *msk2, bool strict, bool symmetric)
+{
+ if (is_inet4_nil(*ip1) || is_inet4_nil(*ip2)) {
+ /* something is nil, so result is nil as well */
+ return bte_nil;
+ }
+ bte m1 = msk1 ? *msk1 : 32;
+ bte m2 = msk2 ? *msk2 : 32;
+ if (is_bte_nil(m1) || is_bte_nil(m2)) {
+ /* something is nil, so result is nil as well */
+ return bte_nil;
+ }
+ if (m1 < 0 || m1 > 32 || m2 < 0 || m2 > 32)
+ return -1; /* indicate error */
+ if (symmetric && m1 < m2) {
+ /* switch the arguments, so more specific is "1" */
+ m2 = m1;
+ /* old value of m2 is not needed anymore */
+ const inet4 *ip = ip1;
+ ip1 = ip2;
+ ip2 = ip;
+ } else if (m1 < m2 || (strict && m1 == m2)) {
+ /* a less specific address (fewer bits used, i.e. smaller mask
+ * value) cannot be contained in a more specific one */
+ return 0;
+ }
+ uint32_t netmask2 = m2 == 0 ? 0 :
+ m2 >= 32 ? ~UINT32_C(0) : ~((UINT32_C(1) << (32 - m2)) - 1);
+ return (inet42int(ip1) & netmask2) == (inet42int(ip2) & netmask2);
+}
+
+static str
+INETinet4containsinet4(bit *ret, const inet4 *ip1, const bte *msk1, const
inet4 *ip2, const bte *msk2)
+{
+ bte r = inet4containsinet4(ip1, msk1, ip2, msk2, true, false);
+ if (r == -1)
+ throw(MAL, "inet46.inet4contains", "Network mask value out of
range.\n");
+ assert(is_bit_nil(r) || r == 0 || r == 1);
+ *ret = (bit) r;
+ return MAL_SUCCEED;
+}
+
+static str
+INETinet4containsinet4nomask(bit *ret, const inet4 *ip1, const inet4 *ip2,
const bte *msk2)
+{
+ bte r = inet4containsinet4(ip1, &(bte){32}, ip2, msk2, true, false);
+ if (r == -1)
+ throw(MAL, "inet46.inet4contains", "Network mask value out of
range.\n");
+ assert(is_bit_nil(r) || r == 0 || r == 1);
+ *ret = (bit) r;
+ return MAL_SUCCEED;
+}
+
+static str
+INETinet4containsorequalinet4(bit *ret, const inet4 *ip1, const bte *msk1,
const inet4 *ip2, const bte *msk2)
+{
+ bte r = inet4containsinet4(ip1, msk1, ip2, msk2, false, false);
+ if (r == -1)
+ throw(MAL, "inet46.inet4containsorequal", "Network mask value
out of range.\n");
+ assert(is_bit_nil(r) || r == 0 || r == 1);
+ *ret = (bit) r;
+ return MAL_SUCCEED;
+}
+
+static str
+INETinet4containsorequalinet4nomask(bit *ret, const inet4 *ip1, const inet4
*ip2, const bte *msk2)
+{
+ bte r = inet4containsinet4(ip1, &(bte){32}, ip2, msk2, false, false);
+ if (r == -1)
+ throw(MAL, "inet46.inet4containsorequal", "Network mask value
out of range.\n");
+ assert(is_bit_nil(r) || r == 0 || r == 1);
+ *ret = (bit) r;
+ return MAL_SUCCEED;
+}
+
+static str
+INETinet4containssymmetricinet4(bit *ret, const inet4 *ip1, const bte *msk1,
const inet4 *ip2, const bte *msk2)
+{
+ bte r = inet4containsinet4(ip1, msk1, ip2, msk2, false, true);
+ if (r == -1)
+ throw(MAL, "inet46.inet4containssymmetric", "Network mask value
out of range.\n");
+ assert(is_bit_nil(r) || r == 0 || r == 1);
+ *ret = (bit) r;
+ return MAL_SUCCEED;
+}
+
static str
INETstr2inet4_bulk(bat *ret, const bat *bid, const bat *sid)
{
@@ -290,6 +384,146 @@ INETinet42str_bulk(bat *ret, const bat *
}
static str
+inet4containsinet4_bulk(bat *ret, const bat *bip1, const bat *bmsk1, const bat
*sid1,
+ const bat *bip2, const bat
*bmsk2, const bat *sid2,
+ bool strict, bool symmetric)
+{
+ BAT *ip1 = NULL, *msk1 = NULL, *ip2 = NULL, *msk2 = NULL, *s1 = NULL,
*s2 = NULL, *dst = NULL;
+ struct canditer c1, c2;
+ str msg = MAL_SUCCEED;
+ QryCtx *qry_ctx = MT_thread_get_qry_ctx();
+
+ if ((ip1 = BATdescriptor(*bip1)) == NULL) {
+ msg = createException(MAL, "batinet46.contains",
+ SQLSTATE(HY002)
RUNTIME_OBJECT_MISSING);
+ goto bailout;
+ }
+ if ((symmetric || (bmsk1 && !is_bat_nil(*bmsk1))) &&
+ (msk2 = BATdescriptor(*bmsk1)) == NULL) {
+ msg = createException(MAL, "batinet46.contains",
+ SQLSTATE(HY002)
RUNTIME_OBJECT_MISSING);
+ goto bailout;
+ }
+ if (msk1 && (ip1->batCount != msk1->batCount || ip1->hseqbase !=
msk1->hseqbase)) {
+ msg = createException(MAL, "batinet46.contains", "Alignment
error");
+ goto bailout;
+ }
+ if (sid1 && !is_bat_nil(*sid1) && (s1 = BATdescriptor(*sid1)) == NULL) {
+ msg = createException(MAL, "batinet46.contains",
+ SQLSTATE(HY002)
RUNTIME_OBJECT_MISSING);
+ goto bailout;
+ }
+ if ((ip2 = BATdescriptor(*bip2)) == NULL) {
+ msg = createException(MAL, "batinet46.contains",
+ SQLSTATE(HY002)
RUNTIME_OBJECT_MISSING);
+ goto bailout;
+ }
+ if ((msk2 = BATdescriptor(*bmsk2)) == NULL) {
+ msg = createException(MAL, "batinet46.contains",
+ SQLSTATE(HY002)
RUNTIME_OBJECT_MISSING);
+ goto bailout;
+ }
+ if (ip2->batCount != msk2->batCount || ip2->hseqbase != msk2->hseqbase)
{
+ msg = createException(MAL, "batinet46.contains", "Alignment
error");
+ goto bailout;
+ }
+ if (sid2 && !is_bat_nil(*sid2) && (s2 = BATdescriptor(*sid2)) == NULL) {
+ msg = createException(MAL, "batinet46.contains",
+ SQLSTATE(HY002)
RUNTIME_OBJECT_MISSING);
+ goto bailout;
+ }
+
+ canditer_init(&c1, ip1, s1);
+ canditer_init(&c2, ip2, s2);
+
+ if (c1.ncand != c2.ncand) {
+ msg = createException(MAL, "batinet46.contains", "Alignment
error");
+ goto bailout;
+ }
+
+ if ((dst = COLnew(c1.hseq, TYPE_bit, c1.ncand, TRANSIENT)) == NULL) {
+ msg = createException(MAL, "batinet46.contains",
+ SQLSTATE(HY013)
MAL_MALLOC_FAIL);
+ goto bailout;
+ }
+
+ BATiter ip1i = bat_iterator(ip1);
+ BATiter ip2i = bat_iterator(ip2);
+ BATiter msk2i = bat_iterator(msk2);
+ bit *dstp = Tloc(dst, 0);
+ bool nils = false;
+ if (msk1) {
+ BATiter msk1i = bat_iterator(msk1);
+ TIMEOUT_LOOP(c1.ncand, qry_ctx) {
+ oid o1 = canditer_next(&c1);
+ oid o2 = canditer_next(&c2);
+ bte v = inet4containsinet4(BUNtloc(ip1i, o1 -
ip1->hseqbase),
+
BUNtloc(msk1i, o1 - msk1->hseqbase),
+
BUNtloc(ip2i, o2 - ip2->hseqbase),
+
BUNtloc(msk2i, o2 - msk2->hseqbase),
+
strict, symmetric);
+ if (v == -1) {
+ msg = createException(MAL, "batinet46.contains",
+
SQLSTATE(22003) "mask value out of range");
+ goto bailout;
+ }
+ *dstp++ = (bit) v;
+ nils |= is_bte_nil(v);
+ }
+ bat_iterator_end(&msk1i);
+ } else {
+ assert(!symmetric);
+ TIMEOUT_LOOP(c1.ncand, qry_ctx) {
+ oid o1 = canditer_next(&c1);
+ oid o2 = canditer_next(&c2);
+ bte v = inet4containsinet4(BUNtloc(ip1i, o1 -
ip1->hseqbase),
+
&(bte){32},
+
BUNtloc(ip2i, o2 - ip2->hseqbase),
+
BUNtloc(msk2i, o2 - msk2->hseqbase),
+
strict, false);
+ if (v == -1) {
+ msg = createException(MAL, "batinet46.contains",
+
SQLSTATE(22003) "mask value out of range");
+ goto bailout;
+ }
+ *dstp++ = (bit) v;
+ nils |= is_bte_nil(v);
+ }
+ }
+ bat_iterator_end(&ip1i);
+ bat_iterator_end(&ip2i);
+ bat_iterator_end(&msk2i);
+ TIMEOUT_CHECK(qry_ctx, GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
+ dst->tnil = nils;
+ dst->tnonil = !nils;
+ dst->tsorted = false;
+ dst->trevsorted = false;
+ dst->tkey = false;
+ BATsetcount(dst, c1.ncand);
+ *ret = dst->batCacheid;
+ BBPkeepref(dst);
+
+ bailout:
+ BBPreclaim(ip1);
+ BBPreclaim(ip2);
+ BBPreclaim(msk1);
+ BBPreclaim(msk2);
+ BBPreclaim(s1);
+ BBPreclaim(s2);
+ if (msg) /* only reclaim if
there was an error */
+ BBPreclaim(dst);
+ return msg;
+}
+
+static str
+INETinet4containsinet4_bulk(bat *ret, const bat *bip1, const bat *bmsk1, const
bat *sid1,
+ const bat *bip2, const
bat *bmsk2, const bat *sid2)
+{
+ return inet4containsinet4_bulk(ret, bip1, bmsk1, sid1, bip2, bmsk2,
sid2,
+ false,
false);
+}
+
+static str
INETstr2inet6(inet6 *ret, const char *const *s)
{
size_t l = sizeof(inet6);
@@ -324,6 +558,100 @@ INETinet42inet6(inet6 *ret, const inet4
return MAL_SUCCEED;
}
+static bte
+inet6containsinet6(const inet6 *ip1, const sht *msk1, const inet6 *ip2, const
sht *msk2, bool strict, bool symmetric)
+{
+ if (is_inet6_nil(*ip1) || is_inet6_nil(*ip2)) {
+ /* something is nil, so result is nil as well */
+ return bte_nil;
+ }
+ sht m1 = msk1 ? *msk1 : 128;
+ sht m2 = msk2 ? *msk2 : 128;
+ if (is_sht_nil(m1) || is_sht_nil(m2)) {
+ /* something is nil, so result is nil as well */
+ return bte_nil;
+ }
+ if (m1 < 0 || m1 > 128 || m2 < 0 || m2 > 128)
+ return -1; /* indicate error */
+ if (symmetric && m1 < m2) {
+ /* switch the arguments, so more specific is "1" */
+ m2 = m1;
+ /* old value of m2 is not needed anymore */
+ const inet6 *ip = ip1;
+ ip1 = ip2;
+ ip2 = ip;
+ } else if (m1 < m2 || (strict && m1 == m2)) {
+ /* a less specific address (fewer bits used, i.e. smaller mask
+ * value) cannot be contained in a more specific one */
+ return 0;
+ }
+ sht n = m2 / 16;
+ sht r = m2 % 16;
+ for (sht i = 0; i < n; i++) {
+ if (ip1->oct[i] != ip2->oct[i])
+ return 0;
+ }
+ if (r == 0)
+ return 1;
+ uint16_t m = (UINT16_C(1) << (16 - r)) - 1;
+ return (ip1->oct[n] & m) == (ip2->oct[n] & m);
+}
+
+static str
+INETinet6containsinet6(bit *ret, const inet6 *ip1, const sht *msk1, const
inet6 *ip2, const sht *msk2)
+{
+ bte r = inet6containsinet6(ip1, msk1, ip2, msk2, true, false);
+ if (r == -1)
+ throw(MAL, "inet46.inet6contains", "Network mask value out of
range.\n");
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]