This is an automated email from the ASF dual-hosted git repository.
yiguolei pushed a commit to branch branch-4.2
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/branch-4.2 by this push:
new ee255cb12ae branch-4.2: [fix](lead) Limit LEAD and LAG offsets to
INT32_MAX #68455 (#70095)
ee255cb12ae is described below
commit ee255cb12ae0c90671d50e891751d0a9d7caedef
Author: morrySnow <[email protected]>
AuthorDate: Thu Nov 5 14:04:25 2026 +0800
branch-4.2: [fix](lead) Limit LEAD and LAG offsets to INT32_MAX #68455
(#70095)
picked from master #68455
Co-authored-by: TengJianPing <[email protected]>
---
.../org/apache/doris/analysis/AnalyticWindow.java | 7 +-
.../rules/analysis/WindowFunctionChecker.java | 6 +-
.../nereids/trees/expressions/WindowFrame.java | 4 +
.../trees/expressions/functions/window/Lag.java | 7 +-
.../trees/expressions/functions/window/Lead.java | 7 +-
.../functions/window/WindowFunction.java | 9 +-
.../apache/doris/analysis/AnalyticWindowTest.java | 37 +--
.../CheckAndStandardizeWindowFunctionTest.java | 54 +++++
.../functions/window/LeadLagOffsetTest.java | 45 +++-
.../test_lead_lag_large_offset.out | 9 +
.../test_lead_lag_large_offset.groovy | 269 +++------------------
11 files changed, 175 insertions(+), 279 deletions(-)
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/analysis/AnalyticWindow.java
b/fe/fe-core/src/main/java/org/apache/doris/analysis/AnalyticWindow.java
index edfb3c4251b..5e64db045ec 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/AnalyticWindow.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/AnalyticWindow.java
@@ -22,6 +22,7 @@ package org.apache.doris.analysis;
import org.apache.doris.catalog.TableIf;
import org.apache.doris.catalog.TableIf.TableType;
+import org.apache.doris.nereids.trees.expressions.WindowFrame;
import org.apache.doris.thrift.TAnalyticWindow;
import org.apache.doris.thrift.TAnalyticWindowBoundary;
import org.apache.doris.thrift.TAnalyticWindowBoundaryType;
@@ -41,7 +42,6 @@ public class AnalyticWindow {
public static final AnalyticWindow DEFAULT_WINDOW = new
AnalyticWindow(Type.RANGE,
new Boundary(BoundaryType.UNBOUNDED_PRECEDING, null),
new Boundary(BoundaryType.CURRENT_ROW, null));
- private static final BigDecimal MAX_ROWS_OFFSET_VALUE =
BigDecimal.valueOf(Long.MAX_VALUE);
public enum Type {
ROWS("ROWS"),
@@ -201,8 +201,8 @@ public class AnalyticWindow {
TAnalyticWindowBoundary result = new
TAnalyticWindowBoundary(type.toThrift());
if (type.isOffset() && windowType == Type.ROWS) {
-
Preconditions.checkState(offsetValue.compareTo(MAX_ROWS_OFFSET_VALUE) <= 0,
- "ROWS window offset must not exceed " +
Long.MAX_VALUE);
+
Preconditions.checkState(offsetValue.compareTo(WindowFrame.MAX_ROWS_OFFSET) <=
0,
+ "ROWS window offset must not exceed " +
WindowFrame.MAX_ROWS_OFFSET);
result.setRowsOffsetValue(offsetValue.longValueExact());
}
@@ -364,7 +364,6 @@ public class AnalyticWindow {
return sb.toString();
}
-
public TAnalyticWindow toThrift() {
TAnalyticWindow result = new TAnalyticWindow(type.toThrift());
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/WindowFunctionChecker.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/WindowFunctionChecker.java
index b2d17a34ca0..637a2e5333d 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/WindowFunctionChecker.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/WindowFunctionChecker.java
@@ -68,8 +68,6 @@ import java.util.stream.Collectors;
* window frame (RANGE between UNBOUNDED PRECEDING and CURRENT ROW)
*/
public class WindowFunctionChecker extends
DefaultExpressionVisitor<Expression, Void> {
- private static final BigDecimal MAX_ROWS_OFFSET_VALUE =
BigDecimal.valueOf(Long.MAX_VALUE);
-
private WindowExpression windowExpression;
public WindowFunctionChecker(WindowExpression window) {
@@ -234,8 +232,8 @@ public class WindowFunctionChecker extends
DefaultExpressionVisitor<Expression,
Preconditions.checkArgument(isPositive, "BoundOffset of WindowFrame
must be positive");
if (frameUnits == FrameUnitsType.ROWS) {
-
Preconditions.checkArgument(offsetValue.compareTo(MAX_ROWS_OFFSET_VALUE) <= 0,
- "BoundOffset of ROWS WindowFrame must not exceed " +
Long.MAX_VALUE);
+
Preconditions.checkArgument(offsetValue.compareTo(WindowFrame.MAX_ROWS_OFFSET)
<= 0,
+ "BoundOffset of ROWS WindowFrame must not exceed " +
WindowFrame.MAX_ROWS_OFFSET);
}
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/WindowFrame.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/WindowFrame.java
index b61b3ef1a43..4445f01bf3a 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/WindowFrame.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/WindowFrame.java
@@ -23,6 +23,7 @@ import
org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
import com.google.common.collect.ImmutableList;
+import java.math.BigDecimal;
import java.util.Objects;
import java.util.Optional;
@@ -31,6 +32,9 @@ import java.util.Optional;
*/
public class WindowFrame extends Expression implements PropagateNullable,
LeafExpression {
+ // Bound explicit ROWS and LEAD/LAG offsets to leave headroom for BE
row-position and exclusive-end arithmetic.
+ public static final BigDecimal MAX_ROWS_OFFSET =
BigDecimal.valueOf(Integer.MAX_VALUE);
+
private final FrameUnitsType frameUnits;
private final FrameBoundary leftBoundary;
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/window/Lag.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/window/Lag.java
index cee27a2fa21..4d1c33e7436 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/window/Lag.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/window/Lag.java
@@ -94,7 +94,7 @@ public class Lag extends WindowFunction implements
TernaryExpression, Explicitly
@Override
public void checkLegalityBeforeTypeCoercion() {
- checkOffsetBeforeTypeCoercion(getArgument(1), "LAG");
+ checkLeadLagOffset(getArgument(1), "LAG");
}
@Override
@@ -105,10 +105,7 @@ public class Lag extends WindowFunction implements
TernaryExpression, Explicitly
if (children().size() >= 2) {
checkValidParams(getOffset());
if (getOffset() instanceof Literal) {
- if (((Literal) getOffset()).getDouble() < 0) {
- throw new AnalysisException(
- "The offset parameter of LAG must be a constant
positive integer: " + this.toSql());
- }
+ checkLeadLagOffset(getOffset(), "LAG");
} else {
throw new AnalysisException(
"The offset parameter of LAG must be a constant positive
integer: " + this.toSql());
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/window/Lead.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/window/Lead.java
index b222215507d..048106da942 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/window/Lead.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/window/Lead.java
@@ -95,7 +95,7 @@ public class Lead extends WindowFunction implements
TernaryExpression, Explicitl
@Override
public void checkLegalityBeforeTypeCoercion() {
- checkOffsetBeforeTypeCoercion(getArgument(1), "LEAD");
+ checkLeadLagOffset(getArgument(1), "LEAD");
}
@Override
@@ -106,10 +106,7 @@ public class Lead extends WindowFunction implements
TernaryExpression, Explicitl
if (children().size() >= 2) {
checkValidParams(getOffset());
if (getOffset() instanceof Literal) {
- if (((Literal) getOffset()).getDouble() < 0) {
- throw new AnalysisException(
- "The offset parameter of LEAD must be a constant
positive integer: " + this.toSql());
- }
+ checkLeadLagOffset(getOffset(), "LEAD");
} else {
throw new AnalysisException(
"The offset parameter of LEAD must be a constant positive
integer: " + this.toSql());
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/window/WindowFunction.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/window/WindowFunction.java
index 7f5b8052a1f..2493f1b8a73 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/window/WindowFunction.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/window/WindowFunction.java
@@ -19,6 +19,7 @@ package
org.apache.doris.nereids.trees.expressions.functions.window;
import org.apache.doris.nereids.exceptions.AnalysisException;
import org.apache.doris.nereids.trees.expressions.Expression;
+import org.apache.doris.nereids.trees.expressions.WindowFrame;
import org.apache.doris.nereids.trees.expressions.functions.BoundFunction;
import org.apache.doris.nereids.trees.expressions.literal.Literal;
import org.apache.doris.nereids.types.DataType;
@@ -32,8 +33,6 @@ import java.util.Objects;
*/
public abstract class WindowFunction extends BoundFunction implements
SupportWindowAnalytic {
- private static final BigDecimal MAX_BIGINT_OFFSET =
BigDecimal.valueOf(Long.MAX_VALUE);
-
public WindowFunction(String name, Expression... arguments) {
super(name, arguments);
}
@@ -84,7 +83,7 @@ public abstract class WindowFunction extends BoundFunction
implements SupportWin
}
}
- protected void checkOffsetBeforeTypeCoercion(Expression offset, String
functionName) {
+ protected void checkLeadLagOffset(Expression offset, String functionName) {
if (!offset.getDataType().isIntegralType()) {
throw new AnalysisException("The offset parameter of " +
functionName
+ " must be a constant positive integer: " + this.toSql());
@@ -95,9 +94,9 @@ public abstract class WindowFunction extends BoundFunction
implements SupportWin
throw new AnalysisException("The offset parameter of " +
functionName
+ " must be a constant positive integer: " +
this.toSql());
}
- if (offsetValue.compareTo(MAX_BIGINT_OFFSET) > 0) {
+ if (offsetValue.compareTo(WindowFrame.MAX_ROWS_OFFSET) > 0) {
throw new AnalysisException("The offset parameter of " +
functionName
- + " must not exceed " + Long.MAX_VALUE + ": " +
this.toSql());
+ + " must not exceed " + WindowFrame.MAX_ROWS_OFFSET +
": " + this.toSql());
}
}
}
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/analysis/AnalyticWindowTest.java
b/fe/fe-core/src/test/java/org/apache/doris/analysis/AnalyticWindowTest.java
index 2fc61903a9b..cbe092c1ef2 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/AnalyticWindowTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/AnalyticWindowTest.java
@@ -18,40 +18,47 @@
package org.apache.doris.analysis;
import org.apache.doris.nereids.trees.expressions.WindowFrame.FrameBoundary;
+import org.apache.doris.nereids.trees.expressions.literal.BigIntLiteral;
import org.apache.doris.nereids.trees.expressions.literal.LargeIntLiteral;
+import org.apache.doris.nereids.trees.expressions.literal.Literal;
import org.apache.doris.nereids.trees.plans.algebra.Window;
import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Collections;
class AnalyticWindowTest {
- @Test
- void testNereidsRowsOffsetKeepsInt64Precision() {
+ @ParameterizedTest
+ @ValueSource(longs = {0L, 1L, 2147483646L, Integer.MAX_VALUE})
+ void testNereidsRowsOffsetWithinMaxIntIsSerialized(long offset) {
Window window = Collections::emptyList;
- FrameBoundary frameBoundary = FrameBoundary.newPrecedingBoundary(
- new LargeIntLiteral(BigInteger.valueOf(Long.MAX_VALUE)));
-
- AnalyticWindow.Boundary boundary =
window.withFrameBoundary(frameBoundary, null);
-
- Assertions.assertEquals(Long.MAX_VALUE,
-
boundary.toThrift(AnalyticWindow.Type.ROWS).getRowsOffsetValue());
+ for (Literal literal : new Literal[] {new BigIntLiteral(offset),
+ new LargeIntLiteral(BigInteger.valueOf(offset))}) {
+ for (FrameBoundary frameBoundary : new FrameBoundary[] {
+ FrameBoundary.newPrecedingBoundary(literal),
FrameBoundary.newFollowingBoundary(literal)}) {
+ AnalyticWindow.Boundary boundary =
window.withFrameBoundary(frameBoundary, null);
+ Assertions.assertEquals(offset,
+
boundary.toThrift(AnalyticWindow.Type.ROWS).getRowsOffsetValue());
+ }
+ }
}
- @Test
- void testRowsOffsetOverMaxInt64IsRejected() {
- BigDecimal offset =
BigDecimal.valueOf(Long.MAX_VALUE).add(BigDecimal.ONE);
+ @ParameterizedTest
+ @ValueSource(strings = {"2147483648", "9223372036854775805",
"9223372036854775806",
+ "9223372036854775807", "9223372036854775808"})
+ void testRowsOffsetOverMaxIntIsRejected(String offset) {
for (AnalyticWindow.BoundaryType boundaryType : new
AnalyticWindow.BoundaryType[] {
AnalyticWindow.BoundaryType.PRECEDING,
AnalyticWindow.BoundaryType.FOLLOWING}) {
AnalyticWindow.Boundary boundary = new AnalyticWindow.Boundary(
- boundaryType, new IntLiteral(1L), offset);
+ boundaryType, new IntLiteral(1L), new BigDecimal(offset));
IllegalStateException exception =
Assertions.assertThrows(IllegalStateException.class,
() -> boundary.toThrift(AnalyticWindow.Type.ROWS));
- Assertions.assertEquals("ROWS window offset must not exceed " +
Long.MAX_VALUE,
+ Assertions.assertEquals("ROWS window offset must not exceed " +
Integer.MAX_VALUE,
exception.getMessage());
}
}
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/CheckAndStandardizeWindowFunctionTest.java
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/CheckAndStandardizeWindowFunctionTest.java
index 2f01267140a..3b1dbca87e2 100644
---
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/CheckAndStandardizeWindowFunctionTest.java
+++
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/CheckAndStandardizeWindowFunctionTest.java
@@ -18,6 +18,7 @@
package org.apache.doris.nereids.rules.rewrite;
import org.apache.doris.nereids.properties.OrderKey;
+import org.apache.doris.nereids.rules.analysis.WindowFunctionChecker;
import org.apache.doris.nereids.trees.expressions.Alias;
import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.expressions.NamedExpression;
@@ -27,6 +28,7 @@ import
org.apache.doris.nereids.trees.expressions.WindowExpression;
import org.apache.doris.nereids.trees.expressions.WindowFrame;
import org.apache.doris.nereids.trees.expressions.WindowFrame.FrameBoundary;
import org.apache.doris.nereids.trees.expressions.WindowFrame.FrameUnitsType;
+import org.apache.doris.nereids.trees.expressions.functions.agg.Sum;
import org.apache.doris.nereids.trees.expressions.functions.window.DenseRank;
import org.apache.doris.nereids.trees.expressions.functions.window.FirstValue;
import org.apache.doris.nereids.trees.expressions.functions.window.Lag;
@@ -35,9 +37,11 @@ import
org.apache.doris.nereids.trees.expressions.functions.window.Lead;
import org.apache.doris.nereids.trees.expressions.functions.window.Rank;
import org.apache.doris.nereids.trees.expressions.functions.window.RowNumber;
import
org.apache.doris.nereids.trees.expressions.functions.window.WindowFunction;
+import org.apache.doris.nereids.trees.expressions.literal.BigIntLiteral;
import org.apache.doris.nereids.trees.expressions.literal.BooleanLiteral;
import org.apache.doris.nereids.trees.expressions.literal.DoubleLiteral;
import org.apache.doris.nereids.trees.expressions.literal.IntegerLiteral;
+import org.apache.doris.nereids.trees.expressions.literal.LargeIntLiteral;
import org.apache.doris.nereids.trees.plans.Plan;
import org.apache.doris.nereids.trees.plans.logical.LogicalOlapScan;
import org.apache.doris.nereids.trees.plans.logical.LogicalPlan;
@@ -54,7 +58,10 @@ import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+import java.math.BigInteger;
import java.util.List;
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@@ -266,6 +273,53 @@ public class CheckAndStandardizeWindowFunctionTest
implements MemoPatternMatchSu
);
}
+ @ParameterizedTest
+ @ValueSource(strings = {"2147483648", "9223372036854775805",
"9223372036854775806",
+ "9223372036854775807", "9223372036854775808"})
+ public void testRowsOffsetOverMaxIntIsRejected(String offset) {
+ for (WindowFrame frame : rowsFrames(new LargeIntLiteral(new
BigInteger(offset)))) {
+ WindowExpression window = new WindowExpression(new Sum(age),
partitionKeyList, orderKeyList, frame);
+ forCheckWindowFrameBeforeFunc(window,
+ "BoundOffset of ROWS WindowFrame must not exceed
2147483647");
+ }
+ }
+
+ @ParameterizedTest
+ @ValueSource(longs = {1L, 2147483646L, Integer.MAX_VALUE})
+ public void testValidRowsOffsetIsAccepted(long offset) {
+ for (WindowFrame frame : rowsFrames(new BigIntLiteral(offset))) {
+ WindowExpression window = new WindowExpression(new Sum(age),
partitionKeyList, orderKeyList, frame);
+ WindowFunctionChecker checker = new WindowFunctionChecker(window);
+ Assertions.assertDoesNotThrow(checker::checkWindowBeforeFunc);
+ WindowFrame expected = frame.getRightBoundary().isNull()
+ ?
frame.withRightBoundary(FrameBoundary.newCurrentRowBoundary()) : frame;
+ Assertions.assertEquals(expected,
checker.getWindow().getWindowFrame().get());
+ Assertions.assertDoesNotThrow(checker::checkWindowFunction);
+ Assertions.assertDoesNotThrow(checker::checkWindowAfterFunc);
+ }
+ }
+
+ private List<WindowFrame> rowsFrames(Expression offset) {
+ return ImmutableList.of(
+ new WindowFrame(FrameUnitsType.ROWS,
FrameBoundary.newPrecedingBoundary(),
+ FrameBoundary.newFollowingBoundary(offset)),
+ new WindowFrame(FrameUnitsType.ROWS,
FrameBoundary.newCurrentRowBoundary(),
+ FrameBoundary.newFollowingBoundary(offset)),
+ new WindowFrame(FrameUnitsType.ROWS,
FrameBoundary.newFollowingBoundary(offset),
+ FrameBoundary.newFollowingBoundary(offset)),
+ new WindowFrame(FrameUnitsType.ROWS,
FrameBoundary.newFollowingBoundary(offset),
+ FrameBoundary.newFollowingBoundary()),
+ new WindowFrame(FrameUnitsType.ROWS,
FrameBoundary.newPrecedingBoundary(offset),
+ FrameBoundary.newCurrentRowBoundary()),
+ new WindowFrame(FrameUnitsType.ROWS,
FrameBoundary.newPrecedingBoundary(),
+ FrameBoundary.newPrecedingBoundary(offset)),
+ new WindowFrame(FrameUnitsType.ROWS,
FrameBoundary.newPrecedingBoundary(offset),
+ FrameBoundary.newFollowingBoundary(offset)),
+ new WindowFrame(FrameUnitsType.ROWS,
FrameBoundary.newPrecedingBoundary(offset),
+ FrameBoundary.newFollowingBoundary()),
+ new WindowFrame(FrameUnitsType.ROWS,
FrameBoundary.newPrecedingBoundary(offset)));
+ }
+
private void forCheckWindowFrameBeforeFunc(WindowFrame windowFrame, String
errorMsg) {
WindowExpression window = new WindowExpression(new Rank(),
partitionKeyList, orderKeyList, windowFrame);
forCheckWindowFrameBeforeFunc(window, errorMsg);
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/functions/window/LeadLagOffsetTest.java
b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/functions/window/LeadLagOffsetTest.java
index 660de69208a..3909fd3e20b 100644
---
a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/functions/window/LeadLagOffsetTest.java
+++
b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/functions/window/LeadLagOffsetTest.java
@@ -25,6 +25,8 @@ import
org.apache.doris.nereids.trees.expressions.literal.LargeIntLiteral;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
import java.math.BigDecimal;
import java.math.BigInteger;
@@ -33,7 +35,6 @@ public class LeadLagOffsetTest {
private static final DecimalV3Literal NON_INTEGER_OFFSET =
new DecimalV3Literal(new BigDecimal("922337203685477580.1"));
- private static final BigIntLiteral MAX_BIGINT_OFFSET = new
BigIntLiteral(Long.MAX_VALUE);
private static final LargeIntLiteral OVER_MAX_BIGINT_OFFSET =
new
LargeIntLiteral(BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.ONE));
@@ -64,7 +65,7 @@ public class LeadLagOffsetTest {
AnalysisException exception = Assertions.assertThrows(
AnalysisException.class, lag::checkLegalityBeforeTypeCoercion);
Assertions.assertTrue(exception.getMessage().contains(
- "The offset parameter of LAG must not exceed " +
Long.MAX_VALUE));
+ "The offset parameter of LAG must not exceed " +
Integer.MAX_VALUE));
}
@Test
@@ -74,15 +75,45 @@ public class LeadLagOffsetTest {
AnalysisException exception = Assertions.assertThrows(
AnalysisException.class,
lead::checkLegalityBeforeTypeCoercion);
Assertions.assertTrue(exception.getMessage().contains(
- "The offset parameter of LEAD must not exceed " +
Long.MAX_VALUE));
+ "The offset parameter of LEAD must not exceed " +
Integer.MAX_VALUE));
}
- @Test
- public void testMaxBigintOffsetIsAcceptedBeforeTypeCoercion() {
- Lag lag = new Lag(new IntegerLiteral(1), MAX_BIGINT_OFFSET);
- Lead lead = new Lead(new IntegerLiteral(1), MAX_BIGINT_OFFSET);
+ @ParameterizedTest
+ @ValueSource(longs = {2147483648L, 9223372036854775805L,
9223372036854775806L, Long.MAX_VALUE})
+ public void testOffsetOverMaxIntIsRejected(long offset) {
+ Lag lag = new Lag(new IntegerLiteral(1), new BigIntLiteral(offset));
+ Lead lead = new Lead(new IntegerLiteral(1), new BigIntLiteral(offset));
+
+ for (WindowFunction function : new WindowFunction[] {lag, lead}) {
+ AnalysisException beforeCoercion = Assertions.assertThrows(
+ AnalysisException.class,
function::checkLegalityBeforeTypeCoercion);
+ Assertions.assertTrue(beforeCoercion.getMessage().contains("must
not exceed " + Integer.MAX_VALUE));
+ AnalysisException afterRewrite = Assertions.assertThrows(
+ AnalysisException.class,
function::checkLegalityAfterRewrite);
+ Assertions.assertTrue(afterRewrite.getMessage().contains("must not
exceed " + Integer.MAX_VALUE));
+ }
+ }
+
+ @ParameterizedTest
+ @ValueSource(longs = {0L, 1L, 2147483646L, Integer.MAX_VALUE})
+ public void testValidOffsetIsAccepted(long offset) {
+ Lag lag = new Lag(new IntegerLiteral(1), new BigIntLiteral(offset));
+ Lead lead = new Lead(new IntegerLiteral(1), new BigIntLiteral(offset));
Assertions.assertDoesNotThrow(lag::checkLegalityBeforeTypeCoercion);
Assertions.assertDoesNotThrow(lead::checkLegalityBeforeTypeCoercion);
+ Assertions.assertDoesNotThrow(lag::checkLegalityAfterRewrite);
+ Assertions.assertDoesNotThrow(lead::checkLegalityAfterRewrite);
+ }
+
+ @Test
+ public void testNegativeOffsetIsRejected() {
+ Lag lag = new Lag(new IntegerLiteral(1), new BigIntLiteral(-1));
+ Lead lead = new Lead(new IntegerLiteral(1), new BigIntLiteral(-1));
+
+ for (WindowFunction function : new WindowFunction[] {lag, lead}) {
+ Assertions.assertThrows(AnalysisException.class,
function::checkLegalityBeforeTypeCoercion);
+ Assertions.assertThrows(AnalysisException.class,
function::checkLegalityAfterRewrite);
+ }
}
}
diff --git
a/regression-test/data/query_p0/sql_functions/window_functions/test_lead_lag_large_offset.out
b/regression-test/data/query_p0/sql_functions/window_functions/test_lead_lag_large_offset.out
new file mode 100644
index 00000000000..a7c03b7d5b8
--- /dev/null
+++
b/regression-test/data/query_p0/sql_functions/window_functions/test_lead_lag_large_offset.out
@@ -0,0 +1,9 @@
+-- This file is automatically generated. You should know what you did if you
want to edit this
+-- !max_int --
+1 z \N z z a b
+2 z \N z z b \N
+
+-- !max_int --
+1 z \N z z a \N
+2 z \N z z b a
+
diff --git
a/regression-test/suites/query_p0/sql_functions/window_functions/test_lead_lag_large_offset.groovy
b/regression-test/suites/query_p0/sql_functions/window_functions/test_lead_lag_large_offset.groovy
index 712c3f48da3..d1b67271091 100644
---
a/regression-test/suites/query_p0/sql_functions/window_functions/test_lead_lag_large_offset.groovy
+++
b/regression-test/suites/query_p0/sql_functions/window_functions/test_lead_lag_large_offset.groovy
@@ -16,225 +16,42 @@
// under the License.
suite("test_lead_lag_large_offset") {
- sql "SET enable_nereids_planner = true"
- sql "SET enable_fallback_to_original_planner = false"
-
- /*
- Note: offset value is not likely to be such big as 9223372036854775807,
- so currently BE does not check for int64 overflow, and BE will crash:
- ```
-../src/exec/operator/analytic_sink_operator.cpp:229:76: runtime error: signed
integer overflow: 9223372036854775807 + 1 cannot be represented in type
'int64_t' (aka 'long')
- #0 0x55efa53c8f4f in
doris::AnalyticSinkLocalState::_get_next_for_unbounded_rows(long, long)
be/build_ASAN/../src/exec/operator/analytic_sink_operator.cpp:229:76
- #1 0x55efa53d827a in
doris::AnalyticSinkLocalState::_execute_impl(doris::RuntimeState*)
be/build_ASAN/../src/exec/operator/analytic_sink_operator.cpp:358:33
- #2 0x55efa53e9e33 in
doris::AnalyticSinkOperatorX::sink_impl(doris::RuntimeState*, doris::Block*,
bool) be/build_ASAN/../src/exec/operator/analytic_sink_operator.cpp:754:5
- #3 0x55efa0a2b660 in
doris::DataSinkOperatorXBase::sink(doris::RuntimeState*, doris::Block*, bool)
be/build_ASAN/../src/exec/operator/operator.h:621:16
- #4 0x55efa09f2649 in doris::PipelineTask::execute(bool*)
be/build_ASAN/../src/exec/pipeline/pipeline_task.cpp:726:29
- #5 0x55efa85d9abf in doris::TaskScheduler::_do_work(int)
be/build_ASAN/../src/exec/pipeline/task_scheduler.cpp:151:13
- #6 0x55efa85ddf3c in doris::TaskScheduler::start()::$_0::operator()()
const be/build_ASAN/../src/exec/pipeline/task_scheduler.cpp:64:9
- #7 0x55efa85dde2c in void std::__invoke_impl<void,
doris::TaskScheduler::start()::$_0&>(std::__invoke_other,
doris::TaskScheduler::start()::$_0&)
/mnt/disk2/tengjianping/local/ldb_toolchain/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/bits/invoke.h:63:14
- #8 0x55efa85ddd4c in std::enable_if<is_invocable_r_v<void,
doris::TaskScheduler::start()::$_0&>, void>::type std::__invoke_r<void,
doris::TaskScheduler::start()::$_0&>(doris::TaskScheduler::start()::$_0&)
/mnt/disk2/tengjianping/local/ldb_toolchain/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/bits/invoke.h:113:2
- #9 0x55efa85dda24 in std::_Function_handler<void (),
doris::TaskScheduler::start()::$_0>::_M_invoke(std::_Any_data const&)
/mnt/disk2/tengjianping/local/ldb_toolchain/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/bits/std_function.h:292:9
- #10 0x55ef7d4bf9ad in std::function<void ()>::operator()() const
/mnt/disk2/tengjianping/local/ldb_toolchain/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/bits/std_function.h:593:9
- #11 0x55efa9f150b0 in doris::FunctionRunnable::run()
be/build_ASAN/../src/util/threadpool.cpp:60:27
- #12 0x55efa9ef6ced in doris::ThreadPool::dispatch_thread()
be/build_ASAN/../src/util/threadpool.cpp:621:24
- #13 0x55efa9f356fc in void std::__invoke_impl<void, void
(doris::ThreadPool::*&)(), doris::ThreadPool*&>(std::__invoke_memfun_deref,
void (doris::ThreadPool::*&)(), doris::ThreadPool*&)
/mnt/disk2/tengjianping/local/ldb_toolchain/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/bits/invoke.h:76:14
- #14 0x55efa9f354b4 in std::__invoke_result<void (doris::ThreadPool::*&)(),
doris::ThreadPool*&>::type std::__invoke<void (doris::ThreadPool::*&)(),
doris::ThreadPool*&>(void (doris::ThreadPool::*&)(), doris::ThreadPool*&)
/mnt/disk2/tengjianping/local/ldb_toolchain/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/bits/invoke.h:98:14
- #15 0x55efa9f353e0 in void std::_Bind<void (doris::ThreadPool::*
(doris::ThreadPool*))()>::__call<void, 0ul>(std::tuple<>&&,
std::_Index_tuple<0ul>)
/mnt/disk2/tengjianping/local/ldb_toolchain/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/functional:515:11
- #16 0x55efa9f3519b in void std::_Bind<void (doris::ThreadPool::*
(doris::ThreadPool*))()>::operator()<void>()
/mnt/disk2/tengjianping/local/ldb_toolchain/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/functional:600:17
- #17 0x55efa9f3508c in void std::__invoke_impl<void, std::_Bind<void
(doris::ThreadPool::* (doris::ThreadPool*))()>&>(std::__invoke_other,
std::_Bind<void (doris::ThreadPool::* (doris::ThreadPool*))()>&)
/mnt/disk2/tengjianping/local/ldb_toolchain/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/bits/invoke.h:63:14
- #18 0x55efa9f34f8c in std::enable_if<is_invocable_r_v<void,
std::_Bind<void (doris::ThreadPool::* (doris::ThreadPool*))()>&>, void>::type
std::__invoke_r<void, std::_Bind<void (doris::ThreadPool::*
(doris::ThreadPool*))()>&>(std::_Bind<void (doris::ThreadPool::*
(doris::ThreadPool*))()>&)
/mnt/disk2/tengjianping/local/ldb_toolchain/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/bits/invoke.h:113:2
- #19 0x55efa9f34864 in std::_Function_handler<void (), std::_Bind<void
(doris::ThreadPool::* (doris::ThreadPool*))()>>::_M_invoke(std::_Any_data
const&)
/mnt/disk2/tengjianping/local/ldb_toolchain/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/bits/std_function.h:292:9
- #20 0x55ef7d4bf9ad in std::function<void ()>::operator()() const
/mnt/disk2/tengjianping/local/ldb_toolchain/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/bits/std_function.h:593:9
- #21 0x55efa9eafd98 in doris::Thread::supervise_thread(void*)
be/build_ASAN/../src/util/thread.cpp:460:5
- #22 0x55ef7d205d26 in asan_thread_start(void*)
(/mnt/disk2/tengjianping/wt-master/wt-memleak3/output/be/lib/doris_be+0x4b80dd26)
- #23 0x7f96c0c8b698 in start_thread (/lib64/libc.so.6+0x8b698) (BuildId:
65d7e434cec6326711148d1465614ba5c96649c1)
- #24 0x7f96c0d1089f in __GI___clone3 (/lib64/libc.so.6+0x11089f) (BuildId:
65d7e434cec6326711148d1465614ba5c96649c1)
-
-SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior
../src/exec/operator/analytic_sink_operator.cpp:229:76
-../src/exec/operator/analytic_sink_operator.cpp:240:77: runtime error: signed
integer overflow: -9223372036854775808 - 1 cannot be represented in type
'int64_t' (aka 'long')
- #0 0x55efa53c96e5 in
doris::AnalyticSinkLocalState::_get_next_for_unbounded_rows(long, long)
be/build_ASAN/../src/exec/operator/analytic_sink_operator.cpp:240:77
- #1 0x55efa53d827a in
doris::AnalyticSinkLocalState::_execute_impl(doris::RuntimeState*)
be/build_ASAN/../src/exec/operator/analytic_sink_operator.cpp:358:33
- #2 0x55efa53e9e33 in
doris::AnalyticSinkOperatorX::sink_impl(doris::RuntimeState*, doris::Block*,
bool) be/build_ASAN/../src/exec/operator/analytic_sink_operator.cpp:754:5
- #3 0x55efa0a2b660 in
doris::DataSinkOperatorXBase::sink(doris::RuntimeState*, doris::Block*, bool)
be/build_ASAN/../src/exec/operator/operator.h:621:16
- #4 0x55efa09f2649 in doris::PipelineTask::execute(bool*)
be/build_ASAN/../src/exec/pipeline/pipeline_task.cpp:726:29
- #5 0x55efa85d9abf in doris::TaskScheduler::_do_work(int)
be/build_ASAN/../src/exec/pipeline/task_scheduler.cpp:151:13
- #6 0x55efa85ddf3c in doris::TaskScheduler::start()::$_0::operator()()
const be/build_ASAN/../src/exec/pipeline/task_scheduler.cpp:64:9
- #7 0x55efa85dde2c in void std::__invoke_impl<void,
doris::TaskScheduler::start()::$_0&>(std::__invoke_other,
doris::TaskScheduler::start()::$_0&)
/mnt/disk2/tengjianping/local/ldb_toolchain/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/bits/invoke.h:63:14
- #8 0x55efa85ddd4c in std::enable_if<is_invocable_r_v<void,
doris::TaskScheduler::start()::$_0&>, void>::type std::__invoke_r<void,
doris::TaskScheduler::start()::$_0&>(doris::TaskScheduler::start()::$_0&)
/mnt/disk2/tengjianping/local/ldb_toolchain/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/bits/invoke.h:113:2
- #9 0x55efa85dda24 in std::_Function_handler<void (),
doris::TaskScheduler::start()::$_0>::_M_invoke(std::_Any_data const&)
/mnt/disk2/tengjianping/local/ldb_toolchain/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/bits/std_function.h:292:9
- #10 0x55ef7d4bf9ad in std::function<void ()>::operator()() const
/mnt/disk2/tengjianping/local/ldb_toolchain/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/bits/std_function.h:593:9
- #11 0x55efa9f150b0 in doris::FunctionRunnable::run()
be/build_ASAN/../src/util/threadpool.cpp:60:27
- #12 0x55efa9ef6ced in doris::ThreadPool::dispatch_thread()
be/build_ASAN/../src/util/threadpool.cpp:621:24
- #13 0x55efa9f356fc in void std::__invoke_impl<void, void
(doris::ThreadPool::*&)(), doris::ThreadPool*&>(std::__invoke_memfun_deref,
void (doris::ThreadPool::*&)(), doris::ThreadPool*&)
/mnt/disk2/tengjianping/local/ldb_toolchain/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/bits/invoke.h:76:14
- #14 0x55efa9f354b4 in std::__invoke_result<void (doris::ThreadPool::*&)(),
doris::ThreadPool*&>::type std::__invoke<void (doris::ThreadPool::*&)(),
doris::ThreadPool*&>(void (doris::ThreadPool::*&)(), doris::ThreadPool*&)
/mnt/disk2/tengjianping/local/ldb_toolchain/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/bits/invoke.h:98:14
- #15 0x55efa9f353e0 in void std::_Bind<void (doris::ThreadPool::*
(doris::ThreadPool*))()>::__call<void, 0ul>(std::tuple<>&&,
std::_Index_tuple<0ul>)
/mnt/disk2/tengjianping/local/ldb_toolchain/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/functional:515:11
- #16 0x55efa9f3519b in void std::_Bind<void (doris::ThreadPool::*
(doris::ThreadPool*))()>::operator()<void>()
/mnt/disk2/tengjianping/local/ldb_toolchain/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/functional:600:17
- #17 0x55efa9f3508c in void std::__invoke_impl<void, std::_Bind<void
(doris::ThreadPool::* (doris::ThreadPool*))()>&>(std::__invoke_other,
std::_Bind<void (doris::ThreadPool::* (doris::ThreadPool*))()>&)
/mnt/disk2/tengjianping/local/ldb_toolchain/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/bits/invoke.h:63:14
- #18 0x55efa9f34f8c in std::enable_if<is_invocable_r_v<void,
std::_Bind<void (doris::ThreadPool::* (doris::ThreadPool*))()>&>, void>::type
std::__invoke_r<void, std::_Bind<void (doris::ThreadPool::*
(doris::ThreadPool*))()>&>(std::_Bind<void (doris::ThreadPool::*
(doris::ThreadPool*))()>&)
/mnt/disk2/tengjianping/local/ldb_toolchain/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/bits/invoke.h:113:2
- #19 0x55efa9f34864 in std::_Function_handler<void (), std::_Bind<void
(doris::ThreadPool::* (doris::ThreadPool*))()>>::_M_invoke(std::_Any_data
const&)
/mnt/disk2/tengjianping/local/ldb_toolchain/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/bits/std_function.h:292:9
- #20 0x55ef7d4bf9ad in std::function<void ()>::operator()() const
/mnt/disk2/tengjianping/local/ldb_toolchain/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/bits/std_function.h:593:9
- #21 0x55efa9eafd98 in doris::Thread::supervise_thread(void*)
be/build_ASAN/../src/util/thread.cpp:460:5
- #22 0x55ef7d205d26 in asan_thread_start(void*)
(/mnt/disk2/tengjianping/wt-master/wt-memleak3/output/be/lib/doris_be+0x4b80dd26)
- #23 0x7f96c0c8b698 in start_thread (/lib64/libc.so.6+0x8b698) (BuildId:
65d7e434cec6326711148d1465614ba5c96649c1)
- #24 0x7f96c0d1089f in __GI___clone3 (/lib64/libc.so.6+0x11089f) (BuildId:
65d7e434cec6326711148d1465614ba5c96649c1)
-
-SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior
../src/exec/operator/analytic_sink_operator.cpp:240:77
-../src/exec/operator/analytic_sink_operator.cpp:242:97: runtime error: signed
integer overflow: -9223372036854775808 - 1 cannot be represented in type
'int64_t' (aka 'long')
- #0 0x55efa53c993a in
doris::AnalyticSinkLocalState::_get_next_for_unbounded_rows(long, long)
be/build_ASAN/../src/exec/operator/analytic_sink_operator.cpp:242:97
- #1 0x55efa53d827a in
doris::AnalyticSinkLocalState::_execute_impl(doris::RuntimeState*)
be/build_ASAN/../src/exec/operator/analytic_sink_operator.cpp:358:33
- #2 0x55efa53e9e33 in
doris::AnalyticSinkOperatorX::sink_impl(doris::RuntimeState*, doris::Block*,
bool) be/build_ASAN/../src/exec/operator/analytic_sink_operator.cpp:754:5
- #3 0x55efa0a2b660 in
doris::DataSinkOperatorXBase::sink(doris::RuntimeState*, doris::Block*, bool)
be/build_ASAN/../src/exec/operator/operator.h:621:16
- #4 0x55efa09f2649 in doris::PipelineTask::execute(bool*)
be/build_ASAN/../src/exec/pipeline/pipeline_task.cpp:726:29
- #5 0x55efa85d9abf in doris::TaskScheduler::_do_work(int)
be/build_ASAN/../src/exec/pipeline/task_scheduler.cpp:151:13
- #6 0x55efa85ddf3c in doris::TaskScheduler::start()::$_0::operator()()
const be/build_ASAN/../src/exec/pipeline/task_scheduler.cpp:64:9
- #7 0x55efa85dde2c in void std::__invoke_impl<void,
doris::TaskScheduler::start()::$_0&>(std::__invoke_other,
doris::TaskScheduler::start()::$_0&)
/mnt/disk2/tengjianping/local/ldb_toolchain/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/bits/invoke.h:63:14
- #8 0x55efa85ddd4c in std::enable_if<is_invocable_r_v<void,
doris::TaskScheduler::start()::$_0&>, void>::type std::__invoke_r<void,
doris::TaskScheduler::start()::$_0&>(doris::TaskScheduler::start()::$_0&)
/mnt/disk2/tengjianping/local/ldb_toolchain/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/bits/invoke.h:113:2
- #9 0x55efa85dda24 in std::_Function_handler<void (),
doris::TaskScheduler::start()::$_0>::_M_invoke(std::_Any_data const&)
/mnt/disk2/tengjianping/local/ldb_toolchain/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/bits/std_function.h:292:9
- #10 0x55ef7d4bf9ad in std::function<void ()>::operator()() const
/mnt/disk2/tengjianping/local/ldb_toolchain/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/bits/std_function.h:593:9
- #11 0x55efa9f150b0 in doris::FunctionRunnable::run()
be/build_ASAN/../src/util/threadpool.cpp:60:27
- #12 0x55efa9ef6ced in doris::ThreadPool::dispatch_thread()
be/build_ASAN/../src/util/threadpool.cpp:621:24
- #13 0x55efa9f356fc in void std::__invoke_impl<void, void
(doris::ThreadPool::*&)(), doris::ThreadPool*&>(std::__invoke_memfun_deref,
void (doris::ThreadPool::*&)(), doris::ThreadPool*&)
/mnt/disk2/tengjianping/local/ldb_toolchain/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/bits/invoke.h:76:14
- #14 0x55efa9f354b4 in std::__invoke_result<void (doris::ThreadPool::*&)(),
doris::ThreadPool*&>::type std::__invoke<void (doris::ThreadPool::*&)(),
doris::ThreadPool*&>(void (doris::ThreadPool::*&)(), doris::ThreadPool*&)
/mnt/disk2/tengjianping/local/ldb_toolchain/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/bits/invoke.h:98:14
- #15 0x55efa9f353e0 in void std::_Bind<void (doris::ThreadPool::*
(doris::ThreadPool*))()>::__call<void, 0ul>(std::tuple<>&&,
std::_Index_tuple<0ul>)
/mnt/disk2/tengjianping/local/ldb_toolchain/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/functional:515:11
- #16 0x55efa9f3519b in void std::_Bind<void (doris::ThreadPool::*
(doris::ThreadPool*))()>::operator()<void>()
/mnt/disk2/tengjianping/local/ldb_toolchain/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/functional:600:17
- #17 0x55efa9f3508c in void std::__invoke_impl<void, std::_Bind<void
(doris::ThreadPool::* (doris::ThreadPool*))()>&>(std::__invoke_other,
std::_Bind<void (doris::ThreadPool::* (doris::ThreadPool*))()>&)
/mnt/disk2/tengjianping/local/ldb_toolchain/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/bits/invoke.h:63:14
- #18 0x55efa9f34f8c in std::enable_if<is_invocable_r_v<void,
std::_Bind<void (doris::ThreadPool::* (doris::ThreadPool*))()>&>, void>::type
std::__invoke_r<void, std::_Bind<void (doris::ThreadPool::*
(doris::ThreadPool*))()>&>(std::_Bind<void (doris::ThreadPool::*
(doris::ThreadPool*))()>&)
/mnt/disk2/tengjianping/local/ldb_toolchain/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/bits/invoke.h:113:2
- #19 0x55efa9f34864 in std::_Function_handler<void (), std::_Bind<void
(doris::ThreadPool::* (doris::ThreadPool*))()>>::_M_invoke(std::_Any_data
const&)
/mnt/disk2/tengjianping/local/ldb_toolchain/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/bits/std_function.h:292:9
- #20 0x55ef7d4bf9ad in std::function<void ()>::operator()() const
/mnt/disk2/tengjianping/local/ldb_toolchain/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/bits/std_function.h:593:9
- #21 0x55efa9eafd98 in doris::Thread::supervise_thread(void*)
be/build_ASAN/../src/util/thread.cpp:460:5
- #22 0x55ef7d205d26 in asan_thread_start(void*)
(/mnt/disk2/tengjianping/wt-master/wt-memleak3/output/be/lib/doris_be+0x4b80dd26)
- #23 0x7f96c0c8b698 in start_thread (/lib64/libc.so.6+0x8b698) (BuildId:
65d7e434cec6326711148d1465614ba5c96649c1)
- #24 0x7f96c0d1089f in __GI___clone3 (/lib64/libc.so.6+0x11089f) (BuildId:
65d7e434cec6326711148d1465614ba5c96649c1)
-
-SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior
../src/exec/operator/analytic_sink_operator.cpp:242:97
-../src/exprs/aggregate/aggregate_function_window.h:512:44: runtime error:
signed integer overflow: -9223372036854775808 - 1 cannot be represented in type
'int64_t' (aka 'long')
- #0 0x55ef89702528 in
doris::WindowFunctionLeadImpl<doris::LeadLagData<true, false>,
false>::add_range_single_place(long, long, long, long, doris::IColumn const**)
be/build_ASAN/../src/exprs/aggregate/aggregate_function_window.h:512:44
- #1 0x55ef896f9914 in
doris::WindowFunctionData<doris::WindowFunctionLeadImpl<doris::LeadLagData<true,
false>, false>>::add_range_single_place(long, long, long, long, char*,
doris::IColumn const**, doris::Arena&, unsigned char*, unsigned char*) const
be/build_ASAN/../src/exprs/aggregate/aggregate_function_window.h:674:27
- #2 0x55efa542f314 in doris::AggFnEvaluator::add_range_single_place(long,
long, long, long, char*, doris::IColumn const**, doris::Arena&, unsigned char*,
unsigned char*) be/build_ASAN/../src/exprs/vectorized_agg_fn.cpp:325:16
- #3 0x55efa5402ce6 in void
doris::AnalyticSinkLocalState::_execute_for_function<false>(long, long, long,
long) be/build_ASAN/../src/exec/operator/analytic_sink_operator.cpp:391:32
- #4 0x55efa53c995c in
doris::AnalyticSinkLocalState::_get_next_for_unbounded_rows(long, long)
be/build_ASAN/../src/exec/operator/analytic_sink_operator.cpp:242:9
- #5 0x55efa53d827a in
doris::AnalyticSinkLocalState::_execute_impl(doris::RuntimeState*)
be/build_ASAN/../src/exec/operator/analytic_sink_operator.cpp:358:33
- #6 0x55efa53e9e33 in
doris::AnalyticSinkOperatorX::sink_impl(doris::RuntimeState*, doris::Block*,
bool) be/build_ASAN/../src/exec/operator/analytic_sink_operator.cpp:754:5
- #7 0x55efa0a2b660 in
doris::DataSinkOperatorXBase::sink(doris::RuntimeState*, doris::Block*, bool)
be/build_ASAN/../src/exec/operator/operator.h:621:16
- #8 0x55efa09f2649 in doris::PipelineTask::execute(bool*)
be/build_ASAN/../src/exec/pipeline/pipeline_task.cpp:726:29
- #9 0x55efa85d9abf in doris::TaskScheduler::_do_work(int)
be/build_ASAN/../src/exec/pipeline/task_scheduler.cpp:151:13
- #10 0x55efa85ddf3c in doris::TaskScheduler::start()::$_0::operator()()
const be/build_ASAN/../src/exec/pipeline/task_scheduler.cpp:64:9
- #11 0x55efa85dde2c in void std::__invoke_impl<void,
doris::TaskScheduler::start()::$_0&>(std::__invoke_other,
doris::TaskScheduler::start()::$_0&)
/mnt/disk2/tengjianping/local/ldb_toolchain/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/bits/invoke.h:63:14
- #12 0x55efa85ddd4c in std::enable_if<is_invocable_r_v<void,
doris::TaskScheduler::start()::$_0&>, void>::type std::__invoke_r<void,
doris::TaskScheduler::start()::$_0&>(doris::TaskScheduler::start()::$_0&)
/mnt/disk2/tengjianping/local/ldb_toolchain/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/bits/invoke.h:113:2
- #13 0x55efa85dda24 in std::_Function_handler<void (),
doris::TaskScheduler::start()::$_0>::_M_invoke(std::_Any_data const&)
/mnt/disk2/tengjianping/local/ldb_toolchain/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/bits/std_function.h:292:9
- #14 0x55ef7d4bf9ad in std::function<void ()>::operator()() const
/mnt/disk2/tengjianping/local/ldb_toolchain/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/bits/std_function.h:593:9
- #15 0x55efa9f150b0 in doris::FunctionRunnable::run()
be/build_ASAN/../src/util/threadpool.cpp:60:27
- #16 0x55efa9ef6ced in doris::ThreadPool::dispatch_thread()
be/build_ASAN/../src/util/threadpool.cpp:621:24
- #17 0x55efa9f356fc in void std::__invoke_impl<void, void
(doris::ThreadPool::*&)(), doris::ThreadPool*&>(std::__invoke_memfun_deref,
void (doris::ThreadPool::*&)(), doris::ThreadPool*&)
/mnt/disk2/tengjianping/local/ldb_toolchain/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/bits/invoke.h:76:14
- #18 0x55efa9f354b4 in std::__invoke_result<void (doris::ThreadPool::*&)(),
doris::ThreadPool*&>::type std::__invoke<void (doris::ThreadPool::*&)(),
doris::ThreadPool*&>(void (doris::ThreadPool::*&)(), doris::ThreadPool*&)
/mnt/disk2/tengjianping/local/ldb_toolchain/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/bits/invoke.h:98:14
- #19 0x55efa9f353e0 in void std::_Bind<void (doris::ThreadPool::*
(doris::ThreadPool*))()>::__call<void, 0ul>(std::tuple<>&&,
std::_Index_tuple<0ul>)
/mnt/disk2/tengjianping/local/ldb_toolchain/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/functional:515:11
- #20 0x55efa9f3519b in void std::_Bind<void (doris::ThreadPool::*
(doris::ThreadPool*))()>::operator()<void>()
/mnt/disk2/tengjianping/local/ldb_toolchain/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/functional:600:17
- #21 0x55efa9f3508c in void std::__invoke_impl<void, std::_Bind<void
(doris::ThreadPool::* (doris::ThreadPool*))()>&>(std::__invoke_other,
std::_Bind<void (doris::ThreadPool::* (doris::ThreadPool*))()>&)
/mnt/disk2/tengjianping/local/ldb_toolchain/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/bits/invoke.h:63:14
- #22 0x55efa9f34f8c in std::enable_if<is_invocable_r_v<void,
std::_Bind<void (doris::ThreadPool::* (doris::ThreadPool*))()>&>, void>::type
std::__invoke_r<void, std::_Bind<void (doris::ThreadPool::*
(doris::ThreadPool*))()>&>(std::_Bind<void (doris::ThreadPool::*
(doris::ThreadPool*))()>&)
/mnt/disk2/tengjianping/local/ldb_toolchain/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/bits/invoke.h:113:2
- #23 0x55efa9f34864 in std::_Function_handler<void (), std::_Bind<void
(doris::ThreadPool::* (doris::ThreadPool*))()>>::_M_invoke(std::_Any_data
const&)
/mnt/disk2/tengjianping/local/ldb_toolchain/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/bits/std_function.h:292:9
- #24 0x55ef7d4bf9ad in std::function<void ()>::operator()() const
/mnt/disk2/tengjianping/local/ldb_toolchain/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/bits/std_function.h:593:9
- #25 0x55efa9eafd98 in doris::Thread::supervise_thread(void*)
be/build_ASAN/../src/util/thread.cpp:460:5
- #26 0x55ef7d205d26 in asan_thread_start(void*)
(/mnt/disk2/tengjianping/wt-master/wt-memleak3/output/be/lib/doris_be+0x4b80dd26)
- #27 0x7f96c0c8b698 in start_thread (/lib64/libc.so.6+0x8b698) (BuildId:
65d7e434cec6326711148d1465614ba5c96649c1)
- #28 0x7f96c0d1089f in __GI___clone3 (/lib64/libc.so.6+0x11089f) (BuildId:
65d7e434cec6326711148d1465614ba5c96649c1)
-
-SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior
../src/exprs/aggregate/aggregate_function_window.h:512:44
-F 2026-07-27 11:47:15,677 252267 pod_array.h:370] Check failed: n <=
static_cast<ssize_t>(this->size()) (9223372036854775807 vs. 2)
-*** Check failure stack trace: ***
- @ 0x55efaefc1366 google::LogMessageFatal::~LogMessageFatal()
- @ 0x55ef7ec42fe8 doris::PODArray<>::operator[]()
- @ 0x55ef7ed21415 doris::ColumnVector<>::get_data_at()
- @ 0x55ef896d7ada doris::BaseValue<>::get_value()
- @ 0x55ef897010b3 doris::LeadLagData<>::insert_result_into()
- @ 0x55ef896f86d4 doris::WindowFunctionData<>::insert_result_into()
- @ 0x55ef815c7d46 doris::IAggregateFunction::insert_result_into_range()
- @ 0x55efa5430265 doris::AggFnEvaluator::insert_result_info_range()
- @ 0x55efa53d4467 doris::AnalyticSinkLocalState::_insert_result_info()
- @ 0x55efa53c9a81
doris::AnalyticSinkLocalState::_get_next_for_unbounded_rows()
- @ 0x55efa53d827b doris::AnalyticSinkLocalState::_execute_impl()
- @ 0x55efa53e9e34 doris::AnalyticSinkOperatorX::sink_impl()
- @ 0x55efa0a2b661 doris::DataSinkOperatorXBase::sink()
- @ 0x55efa09f264a doris::PipelineTask::execute()
- @ 0x55efa85d9ac0 doris::TaskScheduler::_do_work()
- @ 0x55efa85ddf3d doris::TaskScheduler::start()::$_0::operator()()
- @ 0x55efa85dde2d std::__invoke_impl<>()
- @ 0x55efa85ddd4d
_ZSt10__invoke_rIvRZN5doris13TaskScheduler5startEvE3$_0JEENSt9enable_ifIX16is_invocable_r_vIT_T0_DpT1_EES5_E4typeEOS6_DpOS7_
- @ 0x55efa85dda25 std::_Function_handler<>::_M_invoke()
- @ 0x55ef7d4bf9ae std::function<>::operator()()
- @ 0x55efa9f150b1 doris::FunctionRunnable::run()
- @ 0x55efa9ef6cee doris::ThreadPool::dispatch_thread()
- @ 0x55efa9f356fd std::__invoke_impl<>()
- @ 0x55efa9f354b5 std::__invoke<>()
- @ 0x55efa9f353e1
_ZNSt5_BindIFMN5doris10ThreadPoolEFvvEPS1_EE6__callIvJEJLm0EEEET_OSt5tupleIJDpT0_EESt12_Index_tupleIJXspT1_EEE
- @ 0x55efa9f3519c std::_Bind<>::operator()<>()
- @ 0x55efa9f3508d std::__invoke_impl<>()
- @ 0x55efa9f34f8d
_ZSt10__invoke_rIvRSt5_BindIFMN5doris10ThreadPoolEFvvEPS2_EEJEENSt9enable_ifIX16is_invocable_r_vIT_T0_DpT1_EESA_E4typeEOSB_DpOSC_
- @ 0x55efa9f34865 std::_Function_handler<>::_M_invoke()
- @ 0x55ef7d4bf9ae std::function<>::operator()()
- @ 0x55efa9eafd99 doris::Thread::supervise_thread()
- @ 0x55ef7d205d27 asan_thread_start()
-*** Query id: 8689a709882f431d-9c24d9d0d8a35473 ***
-*** tablet id: 0 ***
-*** Aborted at 1785124036 (unix time) try "date -d @1785124036" if you are
using GNU date ***
-*** Current BE git commitID: 5e673d5a4a3 ***
-*** SIGABRT unknown detail explain (@0x3eb0003c20c) received by PID 246284
(TID 252267 OR 0x77fbc810d640) from PID 246284; stack trace: ***
- 0# doris::signal::(anonymous namespace)::FailureSignalHandler(int,
siginfo_t*, void*) at ../src/common/signal_handler.h:417
- 1# 0x00007F96C0C3FC60 in /lib64/libc.so.6
- 2# __pthread_kill_implementation in /lib64/libc.so.6
- 3# gsignal in /lib64/libc.so.6
- 4# abort in /lib64/libc.so.6
- 5# 0x000055EFAEFC8CED in
/mnt/disk2/tengjianping/wt-master/wt-memleak3/output/be/lib/doris_be
- 6# google::LogMessage::SendToLog() in
/mnt/disk2/tengjianping/wt-master/wt-memleak3/output/be/lib/doris_be
- 7# google::LogMessage::Flush() in
/mnt/disk2/tengjianping/wt-master/wt-memleak3/output/be/lib/doris_be
- 8# google::LogMessageFatal::~LogMessageFatal() in
/mnt/disk2/tengjianping/wt-master/wt-memleak3/output/be/lib/doris_be
- 9# doris::PODArray<signed char, 4096ul, doris::Allocator<false, false, false,
doris::DefaultMemoryAllocator, true>, 16ul, 15ul>::operator[](long) const at
../src/core/pod_array.h:370
-10# doris::ColumnVector<(doris::PrimitiveType)3>::get_data_at(unsigned long)
const at ../src/core/column/column_vector.h:102
-11# doris::BaseValue<false>::get_value() const at
../src/exprs/aggregate/aggregate_function_window.h:426
-12# doris::LeadLagData<true, false>::insert_result_into(doris::IColumn&) const
at ../src/exprs/aggregate/aggregate_function_window.h:446
-13#
doris::WindowFunctionData<doris::WindowFunctionLeadImpl<doris::LeadLagData<true,
false>, false> >::insert_result_into(char const*, doris::IColumn&) const at
../src/exprs/aggregate/aggregate_function_window.h:682
-14# doris::IAggregateFunction::insert_result_into_range(char const*,
doris::IColumn&, unsigned long, unsigned long) const at
../src/exprs/aggregate/aggregate_function.h:270
-15# doris::AggFnEvaluator::insert_result_info_range(char const*,
doris::IColumn*, unsigned long, unsigned long) at
./be/build_ASAN/../src/exprs/vectorized_agg_fn.cpp:354
-16# doris::AnalyticSinkLocalState::_insert_result_info(long, long) at
./be/build_ASAN/../src/exec/operator/analytic_sink_operator.cpp:419
-17# doris::AnalyticSinkLocalState::_get_next_for_unbounded_rows(long, long) at
./be/build_ASAN/../src/exec/operator/analytic_sink_operator.cpp:245
-18# doris::AnalyticSinkLocalState::_execute_impl(doris::RuntimeState*) at
./be/build_ASAN/../src/exec/operator/analytic_sink_operator.cpp:358
-19# doris::AnalyticSinkOperatorX::sink_impl(doris::RuntimeState*,
doris::Block*, bool) at
./be/build_ASAN/../src/exec/operator/analytic_sink_operator.cpp:754
-20# doris::DataSinkOperatorXBase::sink(doris::RuntimeState*, doris::Block*,
bool) in /mnt/disk2/tengjianping/wt-master/wt-memleak3/output/be/lib/doris_be
-21# doris::PipelineTask::execute(bool*) at
./be/build_ASAN/../src/exec/pipeline/pipeline_task.cpp:726
-22# doris::TaskScheduler::_do_work(int) at
./be/build_ASAN/../src/exec/pipeline/task_scheduler.cpp:151
- ```
- // RQG test cases
- order_qt_lead_max_int64 """
- SELECT k, LEAD(k, 9223372036854775807) OVER (ORDER BY k) AS lag_big
- FROM (SELECT 1 AS k UNION ALL SELECT 2) t
- """
-
- order_qt_lag_max_int64 """
- SELECT k, LAG(k, 9223372036854775807) OVER (ORDER BY k) AS lag_big
- FROM (SELECT 1 AS k UNION ALL SELECT 2) t
- """
-
- order_qt_lag_max_int64_with_default """
- SELECT k, LAG(k, 9223372036854775807, k * 10) OVER (ORDER BY k) AS
lag_big
- FROM (SELECT 1 AS k UNION ALL SELECT 2) t
- """
+ // Extreme LEAD offsets used to overflow BE's exclusive frame end and
crash the process.
+ ["LEAD", "LAG"].each { function ->
+ ["2147483648", "9223372036854775805", "9223372036854775806",
"9223372036854775807",
+ "9223372036854775808", "2147483647 + 1", "CAST('9223372036854775807'
AS BIGINT)"].each { offset ->
+ ["", ", 'z'"].each { defaultValue ->
+ test {
+ sql """
+ SELECT id, ${function}(v, ${offset}${defaultValue})
OVER (ORDER BY id)
+ FROM (SELECT 1 AS id, 'a' AS v UNION ALL SELECT 2,
'b') t
+ """
+ exception "The offset parameter of ${function} must not
exceed 2147483647"
+ }
+ }
+ }
- multi_sql """
- DROP TABLE IF EXISTS tmp_window_offset_extreme_probe;
- CREATE TABLE tmp_window_offset_extreme_probe (
- k INT
- )
- DUPLICATE KEY(k)
- DISTRIBUTED BY HASH(k) BUCKETS 1
- PROPERTIES('replication_num'='1');
+ ["-1", "CAST('-1' AS BIGINT)"].each { offset ->
+ test {
+ sql """
+ SELECT id, ${function}(v, ${offset}, 'z') OVER (ORDER BY
id)
+ FROM (SELECT 1 AS id, 'a' AS v UNION ALL SELECT 2, 'b') t
+ """
+ exception "The offset parameter of ${function} must be a
constant positive integer"
+ }
+ }
- INSERT INTO tmp_window_offset_extreme_probe VALUES (1), (2), (3);
- """
- order_qt_lead_big_int64 """
- SELECT k,
- LEAD(k, 9223372036854775800) OVER(ORDER BY k) AS lead_near
- FROM tmp_window_offset_extreme_probe
- """
- */
+ order_qt_max_int """
+ SELECT id,
+ ${function}(v, 2147483647, 'z') OVER (ORDER BY id) AS
max_offset,
+ ${function}(v, 2147483647) OVER (ORDER BY id) AS
null_default,
+ ${function}(v, 2147483646 + 1, 'z') OVER (ORDER BY id) AS
folded_offset,
+ ${function}(v, CAST('2147483647' AS BIGINT), 'z') OVER
(ORDER BY id) AS cast_offset,
+ ${function}(v, 0, 'z') OVER (ORDER BY id) AS zero_offset,
+ ${function}(v) OVER (ORDER BY id) AS implicit_offset
+ FROM (SELECT 1 AS id, 'a' AS v UNION ALL SELECT 2, 'b') t
+ """
+ }
test {
sql """
@@ -243,7 +60,7 @@ F 2026-07-27 11:47:15,677 252267 pod_array.h:370] Check
failed: n <= static_cast
) AS sum_big
FROM (SELECT 1 AS k UNION ALL SELECT 2) t
"""
- exception "BoundOffset of ROWS WindowFrame must not exceed
9223372036854775807"
+ exception "BoundOffset of ROWS WindowFrame must not exceed 2147483647"
}
["'abc'", "NULL", "TRUE", "DATE '2026-07-27'"].each { invalidOffset ->
@@ -258,22 +75,6 @@ F 2026-07-27 11:47:15,677 252267 pod_array.h:370] Check
failed: n <= static_cast
}
}
- test {
- sql """
- SELECT k, LAG(k, 9223372036854775808) OVER (ORDER BY k) AS lag_big
- FROM (SELECT 1 AS k UNION ALL SELECT 2) t
- """
- exception "The offset parameter of LAG must not exceed
9223372036854775807"
- }
-
- test {
- sql """
- SELECT k, LEAD(k, 9223372036854775808) OVER (ORDER BY k) AS
lead_big
- FROM (SELECT 1 AS k UNION ALL SELECT 2) t
- """
- exception "The offset parameter of LEAD must not exceed
9223372036854775807"
- }
-
test {
sql """
SELECT k, LAG(k, 922337203685477580.1) OVER (ORDER BY k) AS lag_big
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]