[bugfix](fe) add check for leg/lead function params (#29617)

This commit is contained in:
zhangstar333
2024-01-12 18:26:58 +08:00
committed by yiguolei
parent c92648cb27
commit 115815739c
5 changed files with 67 additions and 31 deletions

View File

@ -21,6 +21,7 @@ import org.apache.doris.catalog.FunctionSignature;
import org.apache.doris.nereids.exceptions.AnalysisException;
import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature;
import org.apache.doris.nereids.trees.expressions.literal.Literal;
import org.apache.doris.nereids.trees.expressions.literal.NullLiteral;
import org.apache.doris.nereids.trees.expressions.shape.TernaryExpression;
import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
@ -89,9 +90,18 @@ public class Lag extends WindowFunction implements TernaryExpression, Explicitly
return;
}
if (children().size() >= 2) {
DataType offsetType = getOffset().getDataType();
if (!offsetType.isNumericType()) {
throw new AnalysisException("The offset of LEAD must be a number:" + this.toSql());
checkValidParams(getOffset(), true);
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());
}
} else {
throw new AnalysisException(
"The offset parameter of LAG must be a constant positive integer: " + this.toSql());
}
if (children().size() >= 3) {
checkValidParams(getDefaultValue(), false);
}
}
}

View File

@ -21,6 +21,7 @@ import org.apache.doris.catalog.FunctionSignature;
import org.apache.doris.nereids.exceptions.AnalysisException;
import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature;
import org.apache.doris.nereids.trees.expressions.literal.Literal;
import org.apache.doris.nereids.trees.expressions.literal.NullLiteral;
import org.apache.doris.nereids.trees.expressions.shape.TernaryExpression;
import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
@ -90,9 +91,18 @@ public class Lead extends WindowFunction implements TernaryExpression, Explicitl
return;
}
if (children().size() >= 2) {
DataType offsetType = getOffset().getDataType();
if (!offsetType.isNumericType()) {
throw new AnalysisException("The offset of LEAD must be a number:" + this.toSql());
checkValidParams(getOffset(), true);
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());
}
} else {
throw new AnalysisException(
"The offset parameter of LAG must be a constant positive integer: " + this.toSql());
}
if (children().size() >= 3) {
checkValidParams(getDefaultValue(), false);
}
}
}

View File

@ -17,8 +17,10 @@
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.functions.BoundFunction;
import org.apache.doris.nereids.types.DataType;
import java.util.List;
import java.util.Objects;
@ -46,11 +48,25 @@ public abstract class WindowFunction extends BoundFunction implements SupportWin
}
WindowFunction that = (WindowFunction) o;
return Objects.equals(getName(), that.getName())
&& Objects.equals(children, that.children);
&& Objects.equals(children, that.children);
}
@Override
public int hashCode() {
return Objects.hash(getName(), children);
}
/**
* LAG/LEAD param must be const, and offset must be number
*/
protected void checkValidParams(Expression param, boolean isOffset) {
DataType type = param.getDataType();
if (isOffset == true && !type.isNumericType()) {
throw new AnalysisException("The offset of LAG/LEAD must be a number: " + this.toSql());
}
if (!param.isConstant()) {
throw new AnalysisException(
"The parameter 2 or parameter 3 of LAG/LEAD must be a constant value: " + this.toSql());
}
}
}