Возвращает нуль при использовании INET6_ATON в LOAD DATA LOCAL INFILE

Я использую MySQL 5.6, экспериментирую с новыми функциями, такими как INET6_ATON а также IS_IPV6, Когда сценарий читает IPV4, он вставляет данные в таблицу отлично. Но когда дело доходит до IPv6один из рядов (ipTo) не удается, даже если INET6_ATON работает в одиночку

Моя таблица: 4 поля

`geoIPID` INT NOT NULL AUTO_INCREMENT ,
`IPFrom` VARBINARY(16) NOT NULL ,
`IPTo` VARBINARY(16) NOT NULL ,
`countries_countryID` INT NOT NULL

Скрипт, который загружает текстовые файлы в таблицу:

LOAD DATA LOCAL INFILE '/Users/Invictus/Documents/htdocs/overkill/etcs/IPV6.csv' 
INTO TABLE `overkill`.`geoIP` 
   FIELDS TERMINATED BY ',' ENCLOSED BY '"' 
   LINES TERMINATED BY '\n' 
(@IPFrom, @IPTo, @dummy, @dummy, @countryAbbreviation, @dummy) 
SET IPFrom = IF(IS_IPV4(@IPFrom), 
                 INET_ATON(@IPFrom), 
                 INET6_ATON(@IPFrom)), 
    IPTo = IF(IS_IPV4(@IPTo), 
              INET_ATON(@IPTo), 
              INET6_ATON(@IPTo)), 
    countries_countryID = 
    (
      SELECT IF (COUNT(*) != 0, `countries`.`countryID`, 999) 
        FROM `countries` 
       WHERE `countries`.`countryAbbreviation` = @countryAbbreviation 
       LIMIT 1
    );

Файл IPV4.csv, вот так:

"1.0.0.0","1.0.0.255","16777216","16777471","AU","Australia"
"1.0.1.0","1.0.3.255","16777472","16778239","CN","China"
"1.0.4.0","1.0.7.255","16778240","16779263","AU","Australia"

Файл IPV6.csv, вот так:

"2001:200::", "2001:200:ffff:ffff:ffff:ffff:ffff:ffff", "42540528726795050063891204319802818560", "42540528806023212578155541913346768895", "JP", "Japan"
"2001:208::", "2001:208:ffff:ffff:ffff:ffff:ffff:ffff", "42540529360620350178005905068154421248", "42540529439848512692270242661698371583", "SG", "Singapore"
"2001:218::", "2001:218:ffff:ffff:ffff:ffff:ffff:ffff", "42540530628270950406235306564857626624", "42540530707499112920499644158401576959", "JP", "Japan"

Моя проблема:

В случае, если я загружаю IPv6, второй ряд (ipTo) является NULL, Зачем? Все значения в файлах действительны, но MySQL не преобразует их.

1 ответ

Решение

Проблема не в INET6_ATON но в вашем IPV6.csv файл. В отличие от IPV4.csv у вас есть лишние пробелы после запятых, и это делает LOAD DATA прочитайте свое второе поле, как это

 "2001:200:ffff:ffff:ffff:ffff:ffff:ffff" 
^^                                      ^

и вот почему INET6_ATON возвращается NULL,

Чтобы исправить это:

  1. либо удалите лишние пробелы в вашем CSV-файле
  2. или измените разделитель на FIELDS TERMINATED BY ', '

Кроме того, вы можете упростить ваш запрос и просто использовать INET6_ATON вместо условного переключения между INET_ATON а также INET6_ATON, Последний прекрасно работает как с IPV4, так и с IPV6.

При этом ваш запрос может выглядеть следующим образом (при условии, что у вас нет лишних пробелов в CSV-файле)

LOAD DATA LOCAL INFILE '/Users/Invictus/Documents/htdocs/overkill/etcs/IPV6.csv' 
INTO TABLE `overkill`.`geoIP` 
   FIELDS TERMINATED BY ',' ENCLOSED BY '"' 
   LINES TERMINATED BY '\n' 
(@ipfrom, @ipto, @dummy, @dummy, @abbr, @dummy) 
SET IPFrom = INET6_ATON(@ipfrom), 
    IPTo   = INET6_ATON(@ipto), 
    countries_countryID = 
    (
      SELECT IF(COUNT(*) != 0, `countries`.`countryID`, 999) 
        FROM `countries` 
       WHERE `countries`.`countryAbbreviation` = @abbr 
       LIMIT 1
    );

Чтобы проверить это, я удалил лишние пробелы, объединил оба ваших файла и загрузил их в ipv6 Таблица. Вот результат

mysql> выбрать geoIPID, HEX(ipfrom), HEX(ipto) из ipv6;
+---------+----------------------------------+----------------------------------+
| geoIPID | HEX(ipfrom)                      | HEX(ипто)                        |
+---------+----------------------------------+----------------------------------+
|       1 | 20010200000000000000000000000000 | 20010200FFFFFFFFFFFFFFFFFFFFFFFF |
|       2 | 20010208000000000000000000000000 | 20010208FFFFFFFFFFFFFFFFFFFFFFFF |
|       3 | 20010218000000000000000000000000 | 20010218FFFFFFFFFFFFFFFFFFFFFFFF |
|       4 | 01000000                         | 010000FF                         |
|       5 | 01000100                         | 010003FF                         |
|       6 | 01000400                         | 010007FF                         |
+---------+----------------------------------+----------------------------------+
6 рядов в наборе (0,00 сек)

mysql> выбрать geoIPID, INET6_NTOA(ipfrom), INET6_NTOA(ipto) из ipv6;
+---------+--------------------+----------------------------------------+
| geoIPID | INET6_NTOA(ipfrom) | INET6_NTOA(ipto)                       |
+---------+--------------------+----------------------------------------+
|       1 | 2001:200::         | 2001:200: фффф: фффф: фффф: фффф: фффф: фффф |
|       2 | 2001:208::         | 2001:208: фффф: фффф: фффф: фффф: фффф: фффф |
|       3 | 2001:218::         | 2001:218: фффф: фффф: фффф: фффф: фффф: фффф |
|       4 | 1.0.0.0            | 1.0.0.255                              |
|       5 | 1.0.1.0            | 1.0.3.255                              |
|       6 | 1.0.4.0            | 1.0.7.255                              |
+---------+--------------------+----------------------------------------+
6 рядов в наборе (0,00 сек)
Другие вопросы по тегам