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]

Reply via email to