This is an automated email from the ASF dual-hosted git repository.

dataroaring pushed a commit to branch branch-3.0
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/branch-3.0 by this push:
     new 32eb7bbca8d branch-30: [Bug](ipv6) fix fe can't parse ipv4-mapped type 
to ipv6 (#54391) (#54686)
32eb7bbca8d is described below

commit 32eb7bbca8d35fcd57d655162833e9a4ed80b105
Author: zhangstar333 <[email protected]>
AuthorDate: Wed Aug 13 22:29:19 2025 +0800

    branch-30: [Bug](ipv6) fix fe can't parse ipv4-mapped type to ipv6 (#54391) 
(#54686)
    
    ### What problem does this PR solve?
    Problem Summary:
    cherry-pick from master (#54391)
---
 .../org/apache/doris/analysis/IPv6Literal.java     |   6 ++-
 .../trees/expressions/literal/IPv6Literal.java     |  23 +++++++++--
 .../trees/expressions/literal/IPV6LiteralTest.java |  43 +++++++++++++++++++++
 .../data/datatype_p0/ip/test_ip_crud.out           | Bin 1367 -> 1763 bytes
 .../suites/datatype_p0/ip/test_ip_crud.groovy      |  34 ++++++++++++++++
 5 files changed, 102 insertions(+), 4 deletions(-)

diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/analysis/IPv6Literal.java 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/IPv6Literal.java
index 7d719720442..8648b2be867 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/IPv6Literal.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/IPv6Literal.java
@@ -41,6 +41,9 @@ public class IPv6Literal extends LiteralExpr {
             Pattern.compile("^([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$");
     private static final Pattern IPV6_COMPRESS_REGEX =
             
Pattern.compile("^(([0-9A-Fa-f]{1,4}(:[0-9A-Fa-f]{1,4})*)?)::((([0-9A-Fa-f]{1,4}:)*[0-9A-Fa-f]{1,4})?)$");
+    private static final String IPV4_PART = 
"(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)";
+    private static final Pattern IPV6_MAPPED_REGEX =
+            Pattern.compile("^::[fF]{4}:(" + IPV4_PART + "\\.){3}" + IPV4_PART 
+ "$");
 
     @SerializedName("v")
     private String value;
@@ -75,7 +78,8 @@ public class IPv6Literal extends LiteralExpr {
     private void checkValueValid(String ipv6) throws AnalysisException {
         if (ipv6.length() > 39) {
             throw new AnalysisException("The length of IPv6 must not exceed 
39. type: " + Type.IPV6);
-        } else if (!IPV6_STD_REGEX.matcher(ipv6).matches() && 
!IPV6_COMPRESS_REGEX.matcher(ipv6).matches()) {
+        } else if (!IPV6_STD_REGEX.matcher(ipv6).matches() && 
!IPV6_COMPRESS_REGEX.matcher(ipv6).matches()
+                && !IPV6_MAPPED_REGEX.matcher(ipv6).matches()) {
             throw new AnalysisException("Invalid IPv6 format: " + ipv6 + ". 
type: " + Type.IPV6);
         }
     }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/IPv6Literal.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/IPv6Literal.java
index 0ac12ae85e4..a869541a417 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/IPv6Literal.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/IPv6Literal.java
@@ -22,6 +22,8 @@ import org.apache.doris.nereids.exceptions.AnalysisException;
 import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
 import org.apache.doris.nereids.types.IPv6Type;
 
+import com.google.common.annotations.VisibleForTesting;
+
 import java.util.regex.Pattern;
 
 /**
@@ -33,6 +35,9 @@ public class IPv6Literal extends Literal {
             Pattern.compile("^([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$");
     private static final Pattern IPV6_COMPRESS_REGEX =
             
Pattern.compile("^(([0-9A-Fa-f]{1,4}(:[0-9A-Fa-f]{1,4})*)?)::((([0-9A-Fa-f]{1,4}:)*[0-9A-Fa-f]{1,4})?)$");
+    private static final String IPV4_PART = 
"(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)";
+    private static final Pattern IPV6_MAPPED_REGEX =
+            Pattern.compile("^::[fF]{4}:(" + IPV4_PART + "\\.){3}" + IPV4_PART 
+ "$");
 
     private final String value;
 
@@ -61,11 +66,23 @@ public class IPv6Literal extends Literal {
         }
     }
 
+    /**
+     * check IPv6 is valid
+     */
     public void checkValueValid(String ipv6) throws AnalysisException {
         if (ipv6.length() > 39) {
-            throw new AnalysisException("The length of IPv6 must not exceed 
39.");
-        } else if (!IPV6_STD_REGEX.matcher(ipv6).matches() && 
!IPV6_COMPRESS_REGEX.matcher(ipv6).matches()) {
-            throw new AnalysisException("Invalid IPv6 format.");
+            throw new AnalysisException("The length of IPv6 must not exceed 
39: " + ipv6);
+        } else if (!isValidIPv6(ipv6)) {
+            throw new AnalysisException("Invalid IPv6 format: " + ipv6);
+        }
+    }
+
+    @VisibleForTesting
+    public static boolean isValidIPv6(String ipv6) {
+        if (IPV6_STD_REGEX.matcher(ipv6).matches() || 
IPV6_COMPRESS_REGEX.matcher(ipv6).matches()
+                || IPV6_MAPPED_REGEX.matcher(ipv6).matches()) {
+            return true;
         }
+        return false;
     }
 }
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/IPV6LiteralTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/IPV6LiteralTest.java
new file mode 100644
index 00000000000..038608608c6
--- /dev/null
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/IPV6LiteralTest.java
@@ -0,0 +1,43 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.doris.nereids.trees.expressions.literal;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+class IPV6LiteralTest {
+
+    @Test
+    public void testValidIPv6() {
+        
Assertions.assertTrue(IPv6Literal.isValidIPv6("2001:0db8:85a3:0000:0000:8a2e:0370:7334"));
+        Assertions.assertTrue(IPv6Literal.isValidIPv6("fe80::1"));
+        
Assertions.assertTrue(IPv6Literal.isValidIPv6("2001:db8::8a2e:370:7334"));
+        Assertions.assertTrue(IPv6Literal.isValidIPv6("::1"));
+        Assertions.assertTrue(IPv6Literal.isValidIPv6("::ffff:192.168.1.1"));
+        Assertions.assertTrue(IPv6Literal.isValidIPv6("::FFFF:10.0.0.255"));
+    }
+
+    @Test
+    public void testInvalidIPv6() {
+        Assertions.assertFalse(IPv6Literal.isValidIPv6("2001:db8::8a2e::370"));
+        Assertions.assertFalse(IPv6Literal.isValidIPv6("2001:db8:xyz::1"));
+        Assertions.assertFalse(IPv6Literal.isValidIPv6("192.168.1.1"));
+        Assertions.assertFalse(IPv6Literal.isValidIPv6("::aaaa:192.168.1.1"));
+        Assertions.assertFalse(IPv6Literal.isValidIPv6("::FFFF:10.0.0.256"));
+    }
+}
diff --git a/regression-test/data/datatype_p0/ip/test_ip_crud.out 
b/regression-test/data/datatype_p0/ip/test_ip_crud.out
index 07323da29e5..60297af9226 100644
Binary files a/regression-test/data/datatype_p0/ip/test_ip_crud.out and 
b/regression-test/data/datatype_p0/ip/test_ip_crud.out differ
diff --git a/regression-test/suites/datatype_p0/ip/test_ip_crud.groovy 
b/regression-test/suites/datatype_p0/ip/test_ip_crud.groovy
index 255457fd2cf..4cb5f1df9a0 100644
--- a/regression-test/suites/datatype_p0/ip/test_ip_crud.groovy
+++ b/regression-test/suites/datatype_p0/ip/test_ip_crud.groovy
@@ -98,4 +98,38 @@ suite("test_ip_crud") {
     qt_sql14 "select * from test_dup_ip_crud order by id"
     sql "delete from test_dup_ip_crud where ip_v6='2001:4888:1f:e891:161:26::'"
     qt_sql15 "select * from test_dup_ip_crud order by id"
+
+    sql "DROP TABLE IF EXISTS log"
+    sql """
+      CREATE TABLE IF NOT EXISTS log
+      (
+          type INT,
+          day DATE NOT NULL,
+          timestamp BIGINT NOT NULL,
+          sip IPV6,
+          dip IPV6
+      )
+      DUPLICATE KEY (`type`, `day`, `timestamp`)
+      DISTRIBUTED BY HASH(`type`) BUCKETS 8
+      PROPERTIES (
+          "replication_num" = "1"
+      );
+    """
+    sql "INSERT INTO log VALUES (1, '2025-08-05', 1754386200, 
'::ffff:10.20.136.244', '::ffff:192.168.1.1');"
+    sql "INSERT INTO log VALUES (2, '2025-08-05', 1754386200, 
'::ffff:11.20.136.244', '::ffff:192.168.1.2');"
+    sql "INSERT INTO log VALUES (3, '2025-08-05', 1754386200, 
'::ffff:12.20.136.244', '::1');"
+    qt_sql16 "select * from log order by type;"
+    sql "delete from log where sip='::ffff:10.20.136.244';"
+    qt_sql17 "select * from log order by type;"
+
+    sql "delete from log where sip='0000:0000:0000:0000:0000:FFFF:0B14:88F4';"
+    qt_sql17 "select * from log order by type;"
+
+    sql "delete from log where dip='0000:0000:0000:0000:0000:0000:0000:0001';"
+    qt_sql17 "select * from log order by type;"
+
+    sql "DROP TABLE test_unique_ip_crud"
+    sql "DROP TABLE test_agg_ip_crud"
+    sql "DROP TABLE test_dup_ip_crud"
+    sql "DROP TABLE log"
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to