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

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


The following commit(s) were added to refs/heads/branch-2.1 by this push:
     new 8ff4ae879e4 branch-2.1: [fix](nereids) fix compare ipv4 / ipv6 always 
equals (#47514)
8ff4ae879e4 is described below

commit 8ff4ae879e4b9a1d96d68af9f363c4e8beb4e4de
Author: yujun <yu...@selectdb.com>
AuthorDate: Sun Feb 9 04:43:07 2025 +0800

    branch-2.1: [fix](nereids) fix compare ipv4 / ipv6 always equals (#47514)
    
    ### What problem does this PR solve?
    
    fix compare ipv4 and ipv6 always equals.
    
    for example, `select cast('127.0.0.1' as ipv4) = cast('192.168.10.10' as
    ipv4)'` will return 1, but it should return 0;
    
    Issue Number: close #xxx
---
 fe/fe-core/pom.xml                                 |   6 +
 .../org/apache/doris/analysis/DateLiteral.java     |   2 +-
 .../org/apache/doris/analysis/DecimalLiteral.java  |   3 +
 .../org/apache/doris/analysis/FloatLiteral.java    |   3 +
 .../org/apache/doris/analysis/IPv4Literal.java     |  14 +-
 .../org/apache/doris/analysis/IPv6Literal.java     |  20 ++-
 .../java/org/apache/doris/analysis/IntLiteral.java |  10 +-
 .../trees/expressions/ComparisonPredicate.java     |   2 +
 .../doris/common/proc/IndexesProcNodeTest.java     |   2 +-
 .../expressions/literal/CompareLiteralTest.java    |  97 +++++++++++++
 .../apache/doris/utframe/TestWithFeService.java    |  10 ++
 .../nereids_p0/literal/test_compare_literal.groovy | 153 +++++++++++++++++++++
 12 files changed, 309 insertions(+), 13 deletions(-)

diff --git a/fe/fe-core/pom.xml b/fe/fe-core/pom.xml
index 049044f62d7..7a4feba0d4f 100644
--- a/fe/fe-core/pom.xml
+++ b/fe/fe-core/pom.xml
@@ -157,6 +157,12 @@ under the License.
             <artifactId>guava-testlib</artifactId>
             <scope>test</scope>
         </dependency>
+        <!-- 
https://mvnrepository.com/artifact/com.googlecode.java-ipv6/java-ipv6 -->
+        <dependency>
+            <groupId>com.googlecode.java-ipv6</groupId>
+            <artifactId>java-ipv6</artifactId>
+            <version>0.17</version>
+        </dependency>
         <!-- 
https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
         <dependency>
             <groupId>com.fasterxml.jackson.core</groupId>
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/analysis/DateLiteral.java 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/DateLiteral.java
index 67d99b1b06e..0b90d2da2e0 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/DateLiteral.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/DateLiteral.java
@@ -666,7 +666,7 @@ public class DateLiteral extends LiteralExpr {
             return diff < 0 ? -1 : (diff == 0 ? 0 : 1);
         }
         // date time will not overflow when doing addition and subtraction
-        return getStringValue().compareTo(expr.getStringValue());
+        return 
Integer.signum(getStringValue().compareTo(expr.getStringValue()));
     }
 
     @Override
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/analysis/DecimalLiteral.java 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/DecimalLiteral.java
index 8343836f6a6..feb1e2f91b7 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/DecimalLiteral.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/DecimalLiteral.java
@@ -245,6 +245,9 @@ public class DecimalLiteral extends NumericLiteralExpr {
         if (expr instanceof NullLiteral) {
             return 1;
         }
+        if (expr == MaxLiteral.MAX_VALUE) {
+            return -1;
+        }
         if (expr instanceof DecimalLiteral) {
             return this.value.compareTo(((DecimalLiteral) expr).value);
         } else {
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/analysis/FloatLiteral.java 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/FloatLiteral.java
index fed50db14c5..743cf3da82a 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/FloatLiteral.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/FloatLiteral.java
@@ -121,6 +121,9 @@ public class FloatLiteral extends NumericLiteralExpr {
         if (expr instanceof NullLiteral) {
             return 1;
         }
+        if (expr == MaxLiteral.MAX_VALUE) {
+            return -1;
+        }
         return Double.compare(value, expr.getDoubleValue());
     }
 
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/analysis/IPv4Literal.java 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/IPv4Literal.java
index 11bf73569c1..2d83a247ff9 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/IPv4Literal.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/IPv4Literal.java
@@ -127,8 +127,18 @@ public class IPv4Literal extends LiteralExpr {
     }
 
     @Override
-    public int compareLiteral(LiteralExpr expr) {
-        return 0;
+    public int compareLiteral(LiteralExpr other) {
+        if (other instanceof IPv4Literal) {
+            return Long.compare(value, ((IPv4Literal) other).value);
+        }
+        if (other instanceof NullLiteral) {
+            return 1;
+        }
+        if (other instanceof MaxLiteral) {
+            return -1;
+        }
+        throw new RuntimeException("Cannot compare two values with different 
data types: "
+                + this + " (" + getClass() + ") vs " + other + " (" + 
other.getClass() + ")");
     }
 
     @Override
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 4b4f99cfd73..ad5023934ce 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
@@ -24,6 +24,10 @@ import org.apache.doris.thrift.TExprNode;
 import org.apache.doris.thrift.TExprNodeType;
 import org.apache.doris.thrift.TIPv6Literal;
 
+import com.google.common.base.Suppliers;
+import com.googlecode.ipv6.IPv6Address;
+
+import java.util.function.Supplier;
 import java.util.regex.Pattern;
 
 public class IPv6Literal extends LiteralExpr {
@@ -37,6 +41,8 @@ public class IPv6Literal extends LiteralExpr {
 
     private String value;
 
+    private Supplier<IPv6Address> ipv6Value = Suppliers.memoize(() -> 
IPv6Address.fromString(value));
+
     /**
      * C'tor forcing type, e.g., due to implicit cast
      */
@@ -92,8 +98,18 @@ public class IPv6Literal extends LiteralExpr {
     }
 
     @Override
-    public int compareLiteral(LiteralExpr expr) {
-        return 0;
+    public int compareLiteral(LiteralExpr other) {
+        if (other instanceof IPv6Literal) {
+            return ipv6Value.get().compareTo(((IPv6Literal) 
other).ipv6Value.get());
+        }
+        if (other instanceof NullLiteral) {
+            return 1;
+        }
+        if (other instanceof MaxLiteral) {
+            return -1;
+        }
+        throw new RuntimeException("Cannot compare two values with different 
data types: "
+                + this + " (" + getClass() + ") vs " + other + " (" + 
other.getClass() + ")");
     }
 
     @Override
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/IntLiteral.java 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/IntLiteral.java
index 0ec61f31203..3c0d9abc344 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/IntLiteral.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/IntLiteral.java
@@ -257,17 +257,13 @@ public class IntLiteral extends NumericLiteralExpr {
         if (expr instanceof NullLiteral) {
             return 1;
         }
-        if (expr instanceof StringLiteral) {
-            return ((StringLiteral) expr).compareLiteral(this);
-        }
         if (expr == MaxLiteral.MAX_VALUE) {
             return -1;
         }
-        if (value == expr.getLongValue()) {
-            return 0;
-        } else {
-            return value > expr.getLongValue() ? 1 : -1;
+        if (expr instanceof StringLiteral) {
+            return - ((StringLiteral) expr).compareLiteral(this);
         }
+        return Long.compare(value, expr.getLongValue());
     }
 
     @Override
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/ComparisonPredicate.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/ComparisonPredicate.java
index d343f6f9356..8c760ed55c7 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/ComparisonPredicate.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/ComparisonPredicate.java
@@ -64,6 +64,8 @@ public abstract class ComparisonPredicate extends 
BinaryOperator {
         for (Expression c : children) {
             if (c.getDataType().isComplexType() && 
!c.getDataType().isArrayType()) {
                 throw new AnalysisException("comparison predicate could not 
contains complex type: " + this.toSql());
+            } else if (c.getDataType().isJsonType()) {
+                throw new AnalysisException("comparison predicate could not 
contains json type: " + this.toSql());
             }
         }
     }
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/common/proc/IndexesProcNodeTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/common/proc/IndexesProcNodeTest.java
index 966f6c38b5b..273915a2d20 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/common/proc/IndexesProcNodeTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/common/proc/IndexesProcNodeTest.java
@@ -96,7 +96,7 @@ public class IndexesProcNodeTest {
         Assert.assertEquals(procResult.getRows().get(3).get(5), "col_4");
         Assert.assertEquals(procResult.getRows().get(3).get(11), "NGRAM_BF");
         Assert.assertEquals(procResult.getRows().get(3).get(12), "ngram_bf 
index on col_4");
-        Assert.assertEquals(procResult.getRows().get(3).get(13), 
"(\"gram_size\" = \"3\", \"bf_size\" = \"256\")");
+        Assert.assertEquals(procResult.getRows().get(3).get(13), "(\"bf_size\" 
= \"256\", \"gram_size\" = \"3\")");
 
     }
 }
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/CompareLiteralTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/CompareLiteralTest.java
new file mode 100644
index 00000000000..36b8369db6b
--- /dev/null
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/CompareLiteralTest.java
@@ -0,0 +1,97 @@
+// 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.apache.doris.common.ExceptionChecker;
+import org.apache.doris.utframe.TestWithFeService;
+
+import com.google.common.collect.ImmutableList;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+class CompareLiteralTest extends TestWithFeService {
+
+    @Test
+    public void testScalar() {
+        // ip type
+        checkCompareSameType(0, new IPv4Literal("170.0.0.100"), new 
IPv4Literal("170.0.0.100"));
+        checkCompareSameType(1, new IPv4Literal("170.0.0.100"), new 
IPv4Literal("160.0.0.200"));
+        checkCompareDiffType(new IPv4Literal("172.0.0.100"), new 
IPv6Literal("1080:0:0:0:8:800:200C:417A"));
+        checkCompareSameType(0, new IPv6Literal("1080:0:0:0:8:800:200C:417A"), 
new IPv6Literal("1080:0:0:0:8:800:200C:417A"));
+        checkCompareSameType(1, new IPv6Literal("1080:0:0:0:8:800:200C:417A"), 
new IPv6Literal("1000:0:0:0:8:800:200C:41AA"));
+        IPv4Literal ipv4 = new IPv4Literal("170.0.0.100");
+        Assertions.assertEquals(ipv4, new 
IPv4Literal(ipv4.toLegacyLiteral().getStringValue()));
+        IPv6Literal ipv6 = new IPv6Literal("1080:0:0:0:8:800:200C:417A");
+        Assertions.assertEquals(ipv6, new 
IPv6Literal(ipv6.toLegacyLiteral().getStringValue()));
+    }
+
+    @Test
+    public void testComplex() throws Exception {
+        // array type
+        checkCompareSameType(0,
+                new ArrayLiteral(ImmutableList.of(new IntegerLiteral(100), new 
IntegerLiteral(200))),
+                new ArrayLiteral(ImmutableList.of(new IntegerLiteral(100), new 
IntegerLiteral(200))));
+        checkCompareSameType(1,
+                new ArrayLiteral(ImmutableList.of(new IntegerLiteral(200))),
+                new ArrayLiteral(ImmutableList.of(new IntegerLiteral(100), new 
IntegerLiteral(200))));
+        checkCompareSameType(1,
+                new ArrayLiteral(ImmutableList.of(new IntegerLiteral(100), new 
IntegerLiteral(200), new IntegerLiteral(1))),
+                new ArrayLiteral(ImmutableList.of(new IntegerLiteral(100), new 
IntegerLiteral(200))));
+        checkComparableNoException("select array(1,2) = array(1, 2)");
+        checkComparableNoException("select array(1,2) > array(1, 2)");
+
+        // json type
+        // checkNotComparable("select cast ('[1, 2]' as json) = cast('[1, 2]' 
as json)",
+        //        "comparison predicate could not contains json type");
+        // checkNotComparable("select cast('[1, 2]' as json) > cast('[1, 2]' 
as json)",
+        //        "comparison predicate could not contains json type");
+
+        // map type
+        checkNotComparable("select map(1, 2) = map(1, 2)",
+                "can not cast from origin type map<tinyint,tinyint> to target 
type=double");
+        checkNotComparable("select map(1, 2) > map(1, 2)",
+                "can not cast from origin type map<tinyint,tinyint> to target 
type=double");
+        checkNotComparable("select cast('(1, 2)' as map<int, int>) = cast('(1, 
2)' as map<int, int>)",
+                "can not cast from origin type map<int,int> to target 
type=double");
+
+        // struct type
+        checkNotComparable("select struct(1, 2) = struct(1, 2)",
+                "can not cast from origin type struct<col:tinyint,col:tinyint> 
to target type=double");
+        checkNotComparable("select struct(1, 2) > struct(1, 2)",
+                "can not cast from origin type struct<col:tinyint,col:tinyint> 
to target type=double");
+    }
+
+    private void checkCompareSameType(int expect, Literal left, Literal right) 
{
+        Assertions.assertEquals(expect, left.compareTo(right));
+        Assertions.assertEquals(- expect, right.compareTo(left));
+    }
+
+    private void checkCompareDiffType(Literal left, Literal right) {
+        Assertions.assertThrowsExactly(RuntimeException.class, () -> 
left.compareTo(right));
+        Assertions.assertThrowsExactly(RuntimeException.class, () -> 
right.compareTo(left));
+    }
+
+    private void checkComparableNoException(String sql) throws Exception {
+        ExceptionChecker.expectThrowsNoException(() -> executeSql(sql));
+    }
+
+    private void checkNotComparable(String sql, String expectErrMsg) throws 
Exception {
+        ExceptionChecker.expectThrowsWithMsg(IllegalStateException.class, 
expectErrMsg,
+                () -> executeSql(sql));
+    }
+}
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/utframe/TestWithFeService.java 
b/fe/fe-core/src/test/java/org/apache/doris/utframe/TestWithFeService.java
index fd3db68e071..c716c273c1b 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/utframe/TestWithFeService.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/utframe/TestWithFeService.java
@@ -611,6 +611,16 @@ public abstract class TestWithFeService {
         }
     }
 
+    public void executeSql(String queryStr) throws Exception {
+        connectContext.getState().reset();
+        StmtExecutor stmtExecutor = new StmtExecutor(connectContext, queryStr);
+        stmtExecutor.execute();
+        if (connectContext.getState().getStateType() == 
QueryState.MysqlStateType.ERR
+                || connectContext.getState().getErrorCode() != null) {
+            throw new 
IllegalStateException(connectContext.getState().getErrorMessage());
+        }
+    }
+
     public void createDatabase(String db) throws Exception {
         String createDbStmtStr = "CREATE DATABASE " + db;
         CreateDbStmt createDbStmt = (CreateDbStmt) 
parseAndAnalyzeStmt(createDbStmtStr);
diff --git 
a/regression-test/suites/nereids_p0/literal/test_compare_literal.groovy 
b/regression-test/suites/nereids_p0/literal/test_compare_literal.groovy
new file mode 100644
index 00000000000..1463d1c29c5
--- /dev/null
+++ b/regression-test/suites/nereids_p0/literal/test_compare_literal.groovy
@@ -0,0 +1,153 @@
+// 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.
+
+suite('test_compare_literal') {
+    for (def val in [true, false]) {
+        sql "set debug_skip_fold_constant=${val}"
+
+        // ipv4
+        test {
+            sql "select cast('170.0.0.100' as ipv4) = cast('170.0.0.100' as 
ipv4)"
+            result([[true]])
+        }
+        test {
+            sql "select cast('170.0.0.100' as ipv4) >= cast('170.0.0.100' as 
ipv4)"
+            result([[true]])
+        }
+        test {
+            sql "select cast('170.0.0.100' as ipv4) > cast('170.0.0.100' as 
ipv4)"
+            result([[false]])
+        }
+        test {
+            sql "select cast('170.0.0.100' as ipv4) = cast('160.0.0.200' as 
ipv4)"
+            result([[false]])
+        }
+        test {
+            sql "select cast('170.0.0.100' as ipv4) >= cast('160.0.0.200' as 
ipv4)"
+            result([[true]])
+        }
+        test {
+            sql "select cast('170.0.0.100' as ipv4) > cast('160.0.0.200' as 
ipv4)"
+            result([[true]])
+        }
+        test {
+            sql "select cast('170.0.0.100' as ipv4) < cast('160.0.0.200' as 
ipv4)"
+            result([[false]])
+        }
+
+        // ipv6
+        test {
+            sql "select cast('1080:0:0:0:8:800:200C:417A' as ipv6) = 
cast('1080:0:0:0:8:800:200C:417A' as ipv6)"
+            result([[true]])
+        }
+        test {
+            sql "select cast('1080:0:0:0:8:800:200C:417A' as ipv6) >= 
cast('1080:0:0:0:8:800:200C:417A' as ipv6)"
+            result([[true]])
+        }
+        test {
+            sql "select cast('1080:0:0:0:8:800:200C:417A' as ipv6) > 
cast('1080:0:0:0:8:800:200C:417A' as ipv6)"
+            result([[false]])
+        }
+        test {
+            sql "select cast('1080:0:0:0:8:800:200C:417A' as ipv6) = 
cast('1000:0:0:0:8:800:200C:41AA' as ipv6)"
+            result([[false]])
+        }
+        test {
+            sql "select cast('1080:0:0:0:8:800:200C:417A' as ipv6) >= 
cast('1000:0:0:0:8:800:200C:41AA' as ipv6)"
+            result([[true]])
+        }
+        test {
+            sql "select cast('1080:0:0:0:8:800:200C:417A' as ipv6) > 
cast('1000:0:0:0:8:800:200C:41AA' as ipv6)"
+            result([[true]])
+        }
+        test {
+            sql "select cast('1080:0:0:0:8:800:200C:417A' as ipv6) < 
cast('1000:0:0:0:8:800:200C:41AA' as ipv6)"
+            result([[false]])
+        }
+
+        // array
+        test {
+            sql 'select array(5, 6) = array(5, 6)'
+            result([[true]])
+        }
+        test {
+            sql 'select array(5, 6) >= array(5, 6)'
+            result([[true]])
+        }
+        test {
+            sql 'select array(5, 6) > array(5, 6)'
+            result([[false]])
+        }
+        test {
+            sql 'select array(5, 6) = array(5, 7)'
+            result([[false]])
+        }
+        test {
+            sql 'select array(5, 6) >= array(5, 7)'
+            result([[false]])
+        }
+        test {
+            sql 'select array(5, 6) > array(5, 7)'
+            result([[false]])
+        }
+        test {
+            sql 'select array(5, 6) < array(5, 7)'
+            result([[true]])
+        }
+        test {
+            sql 'select array(5, 6) < array(5, 6, 1)'
+            result([[true]])
+        }
+        test {
+            sql 'select array(5, 6) < array(6)'
+            result([[true]])
+        }
+    }
+
+    // test not comparable
+    sql 'set debug_skip_fold_constant=false'
+
+    // json
+    // test {
+    //     sql "select cast('[1, 2]' as json) = cast('[1, 2]' as json)"
+    //     exception 'comparison predicate could not contains json type'
+    // }
+    // test {
+    //     sql "select cast('[1, 2]' as json) > cast('[1, 2]' as json)"
+    //     exception 'comparison predicate could not contains json type'
+    // }
+
+    // map
+    test {
+        sql 'select map(1, 2) = map(1, 2)'
+        exception 'can not cast from origin type map<tinyint,tinyint> to 
target type=double'
+    }
+    test {
+        sql 'select map(1, 2) > map(1, 2)'
+        exception 'can not cast from origin type map<tinyint,tinyint> to 
target type=double'
+    }
+
+    // struct
+    test {
+        sql 'select struct(1, 2) = struct(1, 2)'
+        exception 'can not cast from origin type 
struct<col:tinyint,col:tinyint> to target type=double'
+    }
+    test {
+        sql 'select struct(1, 2) > struct(1, 2)'
+        exception 'can not cast from origin type 
struct<col:tinyint,col:tinyint> to target type=double'
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org
For additional commands, e-mail: commits-h...@doris.apache.org

Reply via email to