Это всплыло в моем связанном проекте, и это, кажется, лучший результат Google для вопроса, так что вы получили ответ!
create function get_lowest_ipv4(cidr char(18)) returns bigint deterministic return INET_ATON(SUBSTRING_INDEX(cidr, '/', 1));
create function get_highest_ipv4(cidr char(18)) returns bigint deterministic return get_lowest_ipv4(cidr) + (0x100000000 >> SUBSTRING_INDEX(cidr,'/', -1)) - 1;
Затем вы можете сделать ... from ip_map where INET_ATON("ip.add.re.ss") between get_lowest_ipv4(ip) AND get_highest_ipv4(ip)
Поскольку вы объявляете функции детерминированными, они будут кэшироваться внутри mysql, и вычисление нужно будет запустить только один раз. Тогда это будет просто «целое число больше y и меньше x», что будет фактически мгновенным.
MySQL [astpp]> set @cidr="10.11.0.0/16";
Query OK, 0 rows affected (0.00 sec)
MySQL [astpp]> select get_lowest_ipv4(@cidr), get_highest_ipv4(@cidr), INET_NTOA(get_lowest_ipv4(@cidr)), INET_NTOA(get_highest_ipv4(@cidr));
+------------------------+-------------------------+-----------------------------------+------------------------------------+
| get_lowest_ipv4(@cidr) | get_highest_ipv4(@cidr) | INET_NTOA(get_lowest_ipv4(@cidr)) | INET_NTOA(get_highest_ipv4(@cidr)) |
+------------------------+-------------------------+-----------------------------------+------------------------------------+
| 168493056 | 168558591 | 10.11.0.0 | 10.11.255.255 |
+------------------------+-------------------------+-----------------------------------+------------------------------------+
1 row in set (0.00 sec)
MySQL [astpp]> set @cidr="10.11.12.1/32";
Query OK, 0 rows affected (0.00 sec)
MySQL [astpp]> select get_lowest_ipv4(@cidr), get_highest_ipv4(@cidr), INET_NTOA(get_lowest_ipv4(@cidr)), INET_NTOA(get_highest_ipv4(@cidr));
+------------------------+-------------------------+-----------------------------------+------------------------------------+
| get_lowest_ipv4(@cidr) | get_highest_ipv4(@cidr) | INET_NTOA(get_lowest_ipv4(@cidr)) | INET_NTOA(get_highest_ipv4(@cidr)) |
+------------------------+-------------------------+-----------------------------------+------------------------------------+
| 168496129 | 168496129 | 10.11.12.1 | 10.11.12.1 |
+------------------------+-------------------------+-----------------------------------+------------------------------------+
1 row in set (0.01 sec)
MySQL [astpp]>
Единственное важное предостережение заключается в том, что вы должны вставлять ДЕЙСТВИТЕЛЬНЫЕ CIDR. Например, 10.11.12.13/24 недопустимо. Это IP-адрес ВНУТРИ сети 10.11.12.0/24.
Если вы не можете проверить CIDR перед их вставкой (по какой-то безумной причине), вы можете изменить get_lowest_ipv4, чтобы выполнить побитовое сравнение с источником, но это гораздо менее элегантно.
INET_ATON(SUBSTRING_INDEX(`ip`, '/', 1)) & 0xffffffff ^((0x1 <<(32 - SUBSTRING_INDEX(`ip`, '/', -1))) -1 )
Является (непроверенным) способом сопоставления недействительных CIDR.
person
xrobau
schedule
10.06.2018