문제

I am using MySQL 5.6, experimenting with the new features, like INET6_ATON and IS_IPV6. When the script reads IPV4, it inserts the data into the table perfectly. But when it comes to IPv6, one of the rows (ipTo) fails, even though the INET6_ATON works alone.

My Table: 4 fileds

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

A script, which loads the text files into table:

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
    );

The IPV4.csv file, like this:

"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"

The IPV6.csv file, like this:

"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"

My problem:

In case I load the IPv6, the second row (ipTo) is NULL. Why? All the values in the files are valid, still, MySQL does not convert them.

도움이 되었습니까?

해결책

The problem not in INET6_ATON but in your IPV6.csv file. Unlike IPV4.csv you have extra spaces after commas and that makes LOAD DATA read your second field like this

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

and that is why INET6_ATON returns NULL.

To fix this:

  1. either remove extra spaces in your csv file
  2. or change delimiter to FIELDS TERMINATED BY ', '

Besides you can simplify your query and just use INET6_ATON instead of conditionally switching between INET_ATON and INET6_ATON. The latter works just fine with both IPV4 and IPV6.

That being said your query might look like this (assuming that you don't have extra spaces in csv file)

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
    );

To test things out I've removed extra spaces, combined both of your files, and loaded them into ipv6 table. Here is the result

mysql> select geoIPID, HEX(ipfrom), HEX(ipto) from ipv6;
+---------+----------------------------------+----------------------------------+
| geoIPID | HEX(ipfrom)                      | HEX(ipto)                        |
+---------+----------------------------------+----------------------------------+
|       1 | 20010200000000000000000000000000 | 20010200FFFFFFFFFFFFFFFFFFFFFFFF |
|       2 | 20010208000000000000000000000000 | 20010208FFFFFFFFFFFFFFFFFFFFFFFF |
|       3 | 20010218000000000000000000000000 | 20010218FFFFFFFFFFFFFFFFFFFFFFFF |
|       4 | 01000000                         | 010000FF                         |
|       5 | 01000100                         | 010003FF                         |
|       6 | 01000400                         | 010007FF                         |
+---------+----------------------------------+----------------------------------+
6 rows in set (0.00 sec)

mysql> select geoIPID, INET6_NTOA(ipfrom), INET6_NTOA(ipto) from ipv6;
+---------+--------------------+----------------------------------------+
| geoIPID | INET6_NTOA(ipfrom) | INET6_NTOA(ipto)                       |
+---------+--------------------+----------------------------------------+
|       1 | 2001:200::         | 2001:200:ffff:ffff:ffff:ffff:ffff:ffff |
|       2 | 2001:208::         | 2001:208:ffff:ffff:ffff:ffff:ffff:ffff |
|       3 | 2001:218::         | 2001:218:ffff:ffff:ffff:ffff:ffff:ffff |
|       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 rows in set (0.00 sec)

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top