This is an automated email from the ASF dual-hosted git repository.
lijibing pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push:
new 1fb21bafdc1 [fix](nereids) fix cast ipv4 to string (#51546)
1fb21bafdc1 is described below
commit 1fb21bafdc15b60b84a01b8a09c8521ee94e162e
Author: yujun <[email protected]>
AuthorDate: Mon Jun 16 10:08:16 2025 +0800
[fix](nereids) fix cast ipv4 to string (#51546)
### What problem does this PR solve?
when cast a literal L to string, it will call `new
StringLiteral(L.getValue().toString())`, for a ipv4, its getValue return
a long value.
Then we will have:
before this PR:
```
MySQL [email protected]:db1> select cast(cast("192.168.1.10" as ipv4) as
string)
+----------------------------------------------+
| cast(cast("192.168.1.10" as ipv4) as string) |
+----------------------------------------------+
| 3232235786 |
+----------------------------------------------+
```
this PR fix this, it will change ipv4 getValue return a ipv4 class.
after this PR:
```
MySQL [email protected]:db1> SELECT cast(cast('192.168.1.10' as ipv4) as
string);
+----------------------------------------------+
| cast(cast('192.168.1.10' as ipv4) as string) |
+----------------------------------------------+
| 192.168.1.10 |
+----------------------------------------------+
```
---
.../org/apache/doris/common/util/NetUtils.java | 28 ++++++++
.../trees/expressions/literal/IPv4Literal.java | 72 ++++++++++++++++++---
.../org/apache/doris/common/util/NetUtilsTest.java | 39 +++++++++++
.../infer_predicate/pull_up_predicate_literal.out | Bin 102268 -> 102267 bytes
.../fold_constant/fold_constant_ip.groovy | 32 +++++++++
5 files changed, 163 insertions(+), 8 deletions(-)
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/common/util/NetUtils.java
b/fe/fe-core/src/main/java/org/apache/doris/common/util/NetUtils.java
index 9b787f52bf4..13fa4fbaf9c 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/common/util/NetUtils.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/common/util/NetUtils.java
@@ -26,6 +26,7 @@ import org.apache.logging.log4j.Logger;
import java.io.IOException;
import java.net.DatagramSocket;
+import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
@@ -161,4 +162,31 @@ public class NetUtils {
return new SystemInfoService.HostInfo(pair[0],
Integer.valueOf(pair[1]));
}
+ /**
+ * Convert IPv4 address to long
+ * @param inet4Address IPv4 address
+ * @return The corresponding long value
+ */
+ public static long inet4AddressToLong(Inet4Address inet4Address) {
+ byte[] bytes = inet4Address.getAddress();
+ long result = 0;
+ for (byte b : bytes) {
+ result = result << 8 | (b & 0xFF);
+ }
+ return result;
+ }
+
+ /**
+ * Convert long value back to IPv4 address
+ * @param value IP address as a long value
+ * @return The corresponding IPv4 address
+ */
+ public static Inet4Address longToInet4Address(long value) throws Exception
{
+ byte[] bytes = new byte[4];
+ bytes[0] = (byte) ((value >> 24) & 0xFF);
+ bytes[1] = (byte) ((value >> 16) & 0xFF);
+ bytes[2] = (byte) ((value >> 8) & 0xFF);
+ bytes[3] = (byte) (value & 0xFF);
+ return (Inet4Address) Inet4Address.getByAddress(bytes);
+ }
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/IPv4Literal.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/IPv4Literal.java
index 6843bdd9007..448a1fd748f 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/IPv4Literal.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/IPv4Literal.java
@@ -18,10 +18,13 @@
package org.apache.doris.nereids.trees.expressions.literal;
import org.apache.doris.analysis.LiteralExpr;
+import org.apache.doris.common.util.NetUtils;
import org.apache.doris.nereids.exceptions.AnalysisException;
import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
import org.apache.doris.nereids.types.IPv4Type;
+import java.net.Inet4Address;
+import java.util.Objects;
import java.util.regex.Pattern;
/**
@@ -32,26 +35,73 @@ public class IPv4Literal extends Literal implements
ComparableLiteral {
private static final Pattern IPV4_STD_REGEX =
Pattern.compile("^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$");
- private long value;
+ /**
+ * Add a class Inet4Addr wrap in Inet4Address,
+ * When cast ipv4 literal to string, it will call `new
StringLiteral(ipv4Literal.getValue().toString())`,
+ * but Inet4Address.toString() contains a prefix "/", like "/192.168.1.10".
+ * Use Inet4Addr can solve this problem.
+ */
+ public static class Inet4Addr {
+ final Inet4Address address;
+
+ public Inet4Addr(Inet4Address addr) {
+ this.address = addr;
+ }
+
+ public Inet4Address getAddress() {
+ return this.address;
+ }
+
+ public long toLong() {
+ return NetUtils.inet4AddressToLong(address);
+ }
+
+ @Override
+ public String toString() {
+ return address.getHostAddress();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(address);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (!(other instanceof Inet4Addr)) {
+ return false;
+ }
+ Inet4Addr otherAddr = (Inet4Addr) other;
+ return address.equals(otherAddr.address);
+ }
+ }
+
+ private Inet4Addr value;
public IPv4Literal(String ipv4) throws AnalysisException {
super(IPv4Type.INSTANCE);
init(ipv4);
}
- protected IPv4Literal(long value) {
+ protected IPv4Literal(long value) throws AnalysisException {
super(IPv4Type.INSTANCE);
- this.value = value;
+ Inet4Address address;
+ try {
+ address = NetUtils.longToInet4Address(value);
+ } catch (Exception e) {
+ throw new AnalysisException(e.getMessage());
+ }
+ this.value = new Inet4Addr(address);
}
@Override
- public Long getValue() {
+ public Inet4Addr getValue() {
return value;
}
@Override
public double getDouble() {
- return (double) value;
+ return (double) value.toLong();
}
@Override
@@ -61,13 +111,13 @@ public class IPv4Literal extends Literal implements
ComparableLiteral {
@Override
public LiteralExpr toLegacyLiteral() {
- return new org.apache.doris.analysis.IPv4Literal(value);
+ return new org.apache.doris.analysis.IPv4Literal(value.toLong());
}
@Override
public int compareTo(ComparableLiteral other) {
if (other instanceof IPv4Literal) {
- return Long.compare(value, ((IPv4Literal) other).value);
+ return Long.compare(value.toLong(), ((IPv4Literal)
other).value.toLong());
}
if (other instanceof NullLiteral) {
return 1;
@@ -100,7 +150,13 @@ public class IPv4Literal extends Literal implements
ComparableLiteral {
}
value = (value << 8) | octet;
}
- this.value = value;
+ Inet4Address address;
+ try {
+ address = NetUtils.longToInet4Address(value);
+ } catch (Exception e) {
+ throw new AnalysisException(e.getMessage());
+ }
+ this.value = new Inet4Addr(address);
}
private void checkValueValid(String ipv4) throws AnalysisException {
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/common/util/NetUtilsTest.java
b/fe/fe-core/src/test/java/org/apache/doris/common/util/NetUtilsTest.java
new file mode 100644
index 00000000000..4b23a13832b
--- /dev/null
+++ b/fe/fe-core/src/test/java/org/apache/doris/common/util/NetUtilsTest.java
@@ -0,0 +1,39 @@
+// 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.common.util;
+
+import com.google.common.net.InetAddresses;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.net.Inet4Address;
+import java.net.InetAddress;
+
+public class NetUtilsTest {
+
+ @Test
+ public void testConvertIp() throws Exception {
+ long ipValue = 3232235786L;
+ InetAddress ip = InetAddress.getByName("192.168.1.10");
+ Assert.assertTrue(ip instanceof Inet4Address);
+ Assert.assertEquals(ipValue,
NetUtils.inet4AddressToLong((Inet4Address) ip));
+ Inet4Address convertIp = NetUtils.longToInet4Address(ipValue);
+ Assert.assertEquals(ip, convertIp);
+ System.out.println(InetAddresses.forString("192.168.1.10").toString());
+ }
+}
diff --git
a/regression-test/data/nereids_rules_p0/infer_predicate/pull_up_predicate_literal.out
b/regression-test/data/nereids_rules_p0/infer_predicate/pull_up_predicate_literal.out
index 6db062bdd8e..cc7e99a0603 100644
Binary files
a/regression-test/data/nereids_rules_p0/infer_predicate/pull_up_predicate_literal.out
and
b/regression-test/data/nereids_rules_p0/infer_predicate/pull_up_predicate_literal.out
differ
diff --git
a/regression-test/suites/nereids_p0/expression/fold_constant/fold_constant_ip.groovy
b/regression-test/suites/nereids_p0/expression/fold_constant/fold_constant_ip.groovy
new file mode 100644
index 00000000000..cd4ce8f9920
--- /dev/null
+++
b/regression-test/suites/nereids_p0/expression/fold_constant/fold_constant_ip.groovy
@@ -0,0 +1,32 @@
+// 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("fold_constant_ip") {
+ // cast function
+ for (def ipv4 : ["1", "256.256.256.256", "192.168.1.10"]) {
+ testFoldConst("SELECT cast('${ipv4}' as ipv4)")
+ testFoldConst("SELECT cast(cast('${ipv4}' as ipv4) as string)")
+ testFoldConst("SELECT cast(cast(cast('${ipv4}' as ipv4) as string) as
ipv4)")
+ testFoldConst("SELECT cast(cast(cast('${ipv4}' as ipv4) as string) as
ipv4)")
+ }
+ for (def ipv6 : ["1", "ef8d:3d6a:869b:2582:7200:aa46:4dcd:2bd4"]) {
+ testFoldConst("SELECT cast('${ipv6}' as ipv6)")
+ testFoldConst("SELECT cast(cast('${ipv6}' as ipv6) as string)")
+ testFoldConst("SELECT cast(cast(cast('${ipv6}' as ipv6) as string) as
ipv6)")
+ testFoldConst("SELECT cast(cast(cast('${ipv6}' as ipv6) as string) as
ipv6)")
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]