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 093d6d1e43b [fix](fe) Reject LARGEINT bucket of NTILE (#68030)
093d6d1e43b is described below
commit 093d6d1e43b0988961b761fe261d965ab6eba405
Author: TengJianPing <[email protected]>
AuthorDate: Wed Sep 16 16:05:32 2026 +0800
[fix](fe) Reject LARGEINT bucket of NTILE (#68030)
Problem Summary:
Frontend declared `NTILE(LARGEINT) -> LARGEINT`, but
`WindowFunctionNTile` in backend always returns BIGINT, since the bucket
index is computed with an int64 value. As a result, a legal-looking
window query
select ntile(170141183460469231731687303715884105727) over (order by k)
from t;
failed in the prepare phase with an internal error instead of a clear
user error:
[INTERNAL_ERROR]Result type of ntile is not matched, planner expect
LARGEINT, but get BIGINT
Fix:
1. remove the LARGEINT signature of NTILE, so that every declared
signature returns BIGINT and keeps consistent with backend;
2. reject a LARGEINT bucket in `checkLegalityBeforeTypeCoercion` with an
explicit AnalysisException, because backend computes the bucket index
with an int64 value and can not handle a LARGEINT bucket;
3. drop the redundant `buckets` field, which duplicated the first child
and was not initialized when the expression is rebuilt by
`withChildren`, and read the first argument through `getArgument(0)`.
After the fix, the query above is rejected during analysis with `The
bucket of NTILE must be an integer within the range of BIGINT, but got
LARGEINT`, while an integer bucket (TINYINT/SMALLINT/INT/BIGINT) keeps
working as before.
None
- Test: Regression test / Unit Test
- `./run-regression-test.sh --run -f
regression-test/suites/query_p0/sql_functions/window_functions/test_ntile_function.groovy`
- Behavior changed: Yes. A LARGEINT bucket of NTILE is rejected during
analysis with an explicit error message, instead of failing in the
prepare phase with an internal type mismatch error.
- Does this need documentation: No
### 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 -->
---
.../trees/expressions/functions/window/Ntile.java | 26 ++++++++++------------
.../window_functions/test_ntile_function.groovy | 11 ++++++++-
2 files changed, 22 insertions(+), 15 deletions(-)
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/window/Ntile.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/window/Ntile.java
index e9ef3b19f5f..bbb915cdcb8 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/window/Ntile.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/window/Ntile.java
@@ -28,7 +28,6 @@ import
org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
import org.apache.doris.nereids.types.BigIntType;
import org.apache.doris.nereids.types.DataType;
import org.apache.doris.nereids.types.IntegerType;
-import org.apache.doris.nereids.types.LargeIntType;
import org.apache.doris.nereids.types.SmallIntType;
import org.apache.doris.nereids.types.TinyIntType;
@@ -46,15 +45,11 @@ public class Ntile extends WindowFunction implements
LeafExpression, AlwaysNotNu
FunctionSignature.ret(BigIntType.INSTANCE).args(TinyIntType.INSTANCE),
FunctionSignature.ret(BigIntType.INSTANCE).args(SmallIntType.INSTANCE),
FunctionSignature.ret(BigIntType.INSTANCE).args(IntegerType.INSTANCE),
-
FunctionSignature.ret(BigIntType.INSTANCE).args(BigIntType.INSTANCE),
-
FunctionSignature.ret(LargeIntType.INSTANCE).args(LargeIntType.INSTANCE)
+
FunctionSignature.ret(BigIntType.INSTANCE).args(BigIntType.INSTANCE)
);
- private Expression buckets;
-
public Ntile(Expression buckets) {
super("ntile", buckets);
- this.buckets = buckets;
}
/** constructor for withChildren and reuse signature */
@@ -62,10 +57,6 @@ public class Ntile extends WindowFunction implements
LeafExpression, AlwaysNotNu
super(functionParams);
}
- public Expression getBuckets() {
- return buckets;
- }
-
@Override
public Ntile withChildren(List<Expression> children) {
Preconditions.checkArgument(children.size() == 1);
@@ -74,16 +65,23 @@ public class Ntile extends WindowFunction implements
LeafExpression, AlwaysNotNu
@Override
public void checkLegalityBeforeTypeCoercion() {
- DataType type = getBuckets().getDataType();
+ Expression buckets = getArgument(0);
+ DataType type = buckets.getDataType();
if (!type.isIntegralType()) {
throw new AnalysisException("The bucket of NTILE must be a
integer: " + this.toSql());
}
- if (!getBuckets().isConstant()) {
+ if (type.isLargeIntType()) {
+ // NTILE always returns BIGINT, and backend computes the bucket
index with an int64 value,
+ // so a LARGEINT bucket can not be handled.
+ throw new AnalysisException("The bucket of NTILE must be an
integer within the range of BIGINT, "
+ + "but got " + type.toSql() + ": " + this.toSql());
+ }
+ if (!buckets.isConstant()) {
throw new AnalysisException(
"The bucket of NTILE must be a constant value: " +
this.toSql());
}
- if (getBuckets() instanceof Literal) {
- if (((Literal) getBuckets()).getDouble() <= 0) {
+ if (buckets instanceof Literal) {
+ if (((Literal) buckets).getDouble() <= 0) {
throw new AnalysisException(
"The bucket parameter of NTILE must be a constant positive
integer: " + this.toSql());
}
diff --git
a/regression-test/suites/query_p0/sql_functions/window_functions/test_ntile_function.groovy
b/regression-test/suites/query_p0/sql_functions/window_functions/test_ntile_function.groovy
index c15535dd41f..124eebfce64 100644
---
a/regression-test/suites/query_p0/sql_functions/window_functions/test_ntile_function.groovy
+++
b/regression-test/suites/query_p0/sql_functions/window_functions/test_ntile_function.groovy
@@ -80,8 +80,17 @@ suite("test_ntile_function") {
sql "select k1, k2, k3, ntile(k1) over (partition by k1 order by k2)
as ntile from ${tableName} order by k1, k2, k3 desc;"
exception "The bucket of NTILE must be a constant value"
}
-}
+ test {
+ sql "select k1, k2, k3, ntile(170141183460469231731687303715884105727)
over (partition by k1 order by k2) as ntile from ${tableName} order by k1, k2,
k3 desc;"
+ exception "The bucket of NTILE must be an integer within the range of
BIGINT, but got LARGEINT"
+ }
+
+ test {
+ sql "select k1, k2, k3, ntile(cast(3 as largeint)) over (partition by
k1 order by k2) as ntile from ${tableName} order by k1, k2, k3 desc;"
+ exception "The bucket of NTILE must be an integer within the range of
BIGINT, but got LARGEINT"
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]