Skip to content

Commit 314f9c1

Browse files
csun5285claude
andauthored
branch-4.1: [fix](planner) align legacy literal compareLiteral with Nereids ComparableLiteral semantics (#63481) (#63874)
pick from master #63481 Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent c0f0d2d commit 314f9c1

10 files changed

Lines changed: 1409 additions & 5 deletions

File tree

fe/fe-core/src/main/java/org/apache/doris/analysis/IPv4Literal.java

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,36 @@ public boolean isMinValue() {
127127

128128
@Override
129129
public int compareLiteral(LiteralExpr expr) {
130-
return 0;
130+
if (expr instanceof PlaceHolderExpr) {
131+
return this.compareLiteral(((PlaceHolderExpr) expr).getLiteral());
132+
}
133+
if (expr instanceof NullLiteral) {
134+
return 1;
135+
}
136+
if (expr == MaxLiteral.MAX_VALUE) {
137+
return -1;
138+
}
139+
if (expr instanceof IPv4Literal) {
140+
return Long.compare(this.value, ((IPv4Literal) expr).value);
141+
}
142+
throw new RuntimeException("Cannot compare two values with different data types: "
143+
+ this + " (" + this.type + ") vs " + expr + " (" + expr.type + ")");
144+
}
145+
146+
@Override
147+
public boolean equals(Object obj) {
148+
if (this == obj) {
149+
return true;
150+
}
151+
if (!(obj instanceof IPv4Literal)) {
152+
return false;
153+
}
154+
return this.value == ((IPv4Literal) obj).value;
155+
}
156+
157+
@Override
158+
public int hashCode() {
159+
return 31 * super.hashCode() + Long.hashCode(value);
131160
}
132161

133162
@Override

fe/fe-core/src/main/java/org/apache/doris/analysis/IPv6Literal.java

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.apache.doris.thrift.TIPv6Literal;
2828

2929
import com.google.gson.annotations.SerializedName;
30+
import com.googlecode.ipv6.IPv6Address;
3031

3132
import java.util.regex.Pattern;
3233

@@ -108,7 +109,49 @@ public boolean isMinValue() {
108109

109110
@Override
110111
public int compareLiteral(LiteralExpr expr) {
111-
return 0;
112+
if (expr instanceof PlaceHolderExpr) {
113+
return this.compareLiteral(((PlaceHolderExpr) expr).getLiteral());
114+
}
115+
if (expr instanceof NullLiteral) {
116+
return 1;
117+
}
118+
if (expr == MaxLiteral.MAX_VALUE) {
119+
return -1;
120+
}
121+
if (expr instanceof IPv6Literal) {
122+
return parseAddress(this.value).compareTo(parseAddress(((IPv6Literal) expr).value));
123+
}
124+
throw new RuntimeException("Cannot compare two values with different data types: "
125+
+ this + " (" + this.type + ") vs " + expr + " (" + expr.type + ")");
126+
}
127+
128+
@Override
129+
public boolean equals(Object obj) {
130+
if (this == obj) {
131+
return true;
132+
}
133+
if (!(obj instanceof IPv6Literal)) {
134+
return false;
135+
}
136+
return parseAddress(this.value).equals(parseAddress(((IPv6Literal) obj).value));
137+
}
138+
139+
@Override
140+
public int hashCode() {
141+
return 31 * super.hashCode() + parseAddress(this.value).hashCode();
142+
}
143+
144+
// IPv6Address keeps the full 128-bit value for IPv4-mapped literals
145+
// (e.g. ::ffff:0.0.0.1, ::ffff:0:1) and matches the canonicalization used by
146+
// the Nereids IPv6Literal, so dedup/range logic stays consistent across both
147+
// planners. InetAddress.getByName would otherwise collapse mapped forms to a
148+
// 4-byte Inet4Address and hash-collide with addresses like ::1.
149+
private static IPv6Address parseAddress(String ipv6) {
150+
try {
151+
return IPv6Address.fromString(ipv6);
152+
} catch (Exception e) {
153+
throw new IllegalStateException("Invalid IPv6 literal: " + ipv6, e);
154+
}
112155
}
113156

114157
@Override

fe/fe-core/src/main/java/org/apache/doris/analysis/MapLiteral.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ public boolean isMinValue() {
143143

144144
@Override
145145
public int compareLiteral(LiteralExpr expr) {
146-
return 0;
146+
throw new RuntimeException("Not support comparison between MAP literals");
147147
}
148148

149149
@Override

fe/fe-core/src/main/java/org/apache/doris/analysis/StructLiteral.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ public boolean isMinValue() {
163163

164164
@Override
165165
public int compareLiteral(LiteralExpr expr) {
166-
return 0;
166+
throw new RuntimeException("Not support comparison between STRUCT literals");
167167
}
168168

169169
@Override

fe/fe-core/src/main/java/org/apache/doris/analysis/TimeV2Literal.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,27 @@ public boolean isMinValue() {
103103

104104
@Override
105105
public int compareLiteral(LiteralExpr expr) {
106-
return 0;
106+
throw new RuntimeException("Not support comparison between TIMEV2 literals");
107+
}
108+
109+
@Override
110+
public boolean equals(Object obj) {
111+
if (this == obj) {
112+
return true;
113+
}
114+
if (!(obj instanceof TimeV2Literal)) {
115+
return false;
116+
}
117+
return Double.compare(this.getValue(), ((TimeV2Literal) obj).getValue()) == 0;
118+
}
119+
120+
@Override
121+
public int hashCode() {
122+
// Must mirror equals(), which only compares getValue(). super.hashCode()
123+
// mixes in the ScalarType, so TIMEV2(0) and TIMEV2(6) would otherwise
124+
// produce different hashes for the same logical time value and break the
125+
// equals/hashCode contract — predicate dedup would bucket them apart.
126+
return Double.hashCode(getValue());
107127
}
108128

109129
@Override

0 commit comments

Comments
 (0)