This is an automated email from the ASF dual-hosted git repository.
jacktengg 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 9a5f86ec82b [fix](lead) Limit LEAD and LAG offsets to INT32_MAX
(#68455)
9a5f86ec82b is described below
commit 9a5f86ec82be6f5fb7662fcce08dd58b3bfcd7da
Author: TengJianPing <[email protected]>
AuthorDate: Fri Oct 9 10:44:47 2026 +0800
[fix](lead) Limit LEAD and LAG offsets to INT32_MAX (#68455)
Issue Number: N/A
Related PR: N/A
Problem Summary: LEAD with an offset of 9223372036854775807 on a two-row
input can overflow BE's signed int64 exclusive frame end and abort the
process. Restrict LEAD and LAG offsets to 2147483647 in the shared FE
validation, both before type coercion and after expression rewriting so
arithmetic expressions and explicit casts cannot bypass the limit. Keep
zero offsets and the existing BIGINT signatures. Replace disabled crash
examples with executable rejection cases and cover the accepted
boundary, default values, and expression offsets.
LEAD and LAG now reject offsets greater than 2147483647 during query
planning, including previously accepted very large offsets that returned
default values. This prevents extreme LEAD offsets from crashing BE.
- Test: Unit Test / Regression test / Manual test
- 24 FE unit tests passed (LeadLagOffsetTest and
CheckAndStandardizeWindowFunctionTest).
- build.sh --fe -j8 passed, including Checkstyle.
- test_lead_lag_large_offset and test_lead_lag_nullable regression
suites passed.
- Generated and verified regression output with run-regression-test.sh.
- Original reproducer returns an FE error; BE remains alive with
unchanged start time.
- Behavior changed: Yes (LEAD/LAG offsets must be between 0 and
2147483647).
- Does this need documentation: Yes (document the LEAD/LAG offset limit;
no doc PR yet).
### What problem does this PR solve?
Issue Number: close #xxx
Related PR: #xxx
Problem Summary:
### Release note
None
### Check List (For Author)
- Test <!-- At least one of them must be included. -->
- [ ] Regression test
- [ ] Unit Test
- [ ] Manual test (add detailed scripts or steps below)
- [ ] No need to test or manual test. Explain why:
- [ ] This is a refactor/code format and no logic has been changed.
- [ ] Previous test can cover this change.
- [ ] No code files have been changed.
- [ ] Other reason <!-- Add your reason? -->
- Behavior changed:
- [ ] No.
- [ ] Yes. <!-- Explain the behavior change -->
- Does this need documentation?
- [ ] No.
- [ ] Yes. <!-- Add document PR link here. eg:
https://github.com/apache/doris-website/pull/1214 -->
### Check List (For Reviewer who merge this PR)
- [ ] Confirm the release note
- [ ] Confirm test cases
- [ ] Confirm document
- [ ] Add branch pick label <!-- Add branch pick label that this PR
should merge into -->
---
.../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 5325fb07d0a..01135010250 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
@@ -20,6 +20,7 @@
package org.apache.doris.analysis;
+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;
@@ -35,8 +36,6 @@ import java.util.Objects;
* Both left and right boundaries are always non-null after analyze().
*/
public class AnalyticWindow {
- private static final BigDecimal MAX_ROWS_OFFSET_VALUE =
BigDecimal.valueOf(Long.MAX_VALUE);
-
public enum Type {
ROWS("ROWS"),
RANGE("RANGE");
@@ -141,8 +140,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());
}
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 b2503aa0bc6..515a959bc64 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) {
@@ -236,8 +234,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]