[Fix](Planner) change non boolean return type to boolean (#20599)

Problem: When using no boolean type as return type in where or having clause, the analyzer will check the return type and throw an error. But in some other databases, this usage is enable.

Solved: Cast return type to boolean in where clause and having clause. select *** from *** where case when *** then 1 else 0 end;
This commit is contained in:
LiBinfeng
2023-07-07 17:12:41 +08:00
committed by GitHub
parent 0b7b5dc991
commit dc44345ee4
3 changed files with 69 additions and 2 deletions

View File

@ -26,6 +26,7 @@ import org.apache.doris.catalog.Column;
import org.apache.doris.catalog.DatabaseIf;
import org.apache.doris.catalog.FunctionSet;
import org.apache.doris.catalog.OlapTable;
import org.apache.doris.catalog.PrimitiveType;
import org.apache.doris.catalog.Table;
import org.apache.doris.catalog.TableIf;
import org.apache.doris.catalog.TableIf.TableType;
@ -601,8 +602,8 @@ public class SelectStmt extends QueryStmt {
}
}
whereClauseRewrite();
if (whereClause != null) {
whereClauseRewrite();
if (checkGroupingFn(whereClause)) {
throw new AnalysisException("grouping operations are not allowed in WHERE.");
}
@ -851,6 +852,9 @@ public class SelectStmt extends QueryStmt {
} else {
whereClause = new BoolLiteral(true);
}
} else if (!whereClause.getType().isBoolean()) {
whereClause = new CastExpr(TypeDef.create(PrimitiveType.BOOLEAN), whereClause);
whereClause.setType(Type.BOOLEAN);
}
}
@ -1263,6 +1267,9 @@ public class SelectStmt extends QueryStmt {
havingClauseAfterAnalyzed = havingClause.substitute(aliasSMap, analyzer, false);
}
havingClauseAfterAnalyzed = rewriteQueryExprByMvColumnExpr(havingClauseAfterAnalyzed, analyzer);
if (!havingClauseAfterAnalyzed.getType().isBoolean()) {
havingClauseAfterAnalyzed = havingClauseAfterAnalyzed.castTo(Type.BOOLEAN);
}
havingClauseAfterAnalyzed.checkReturnsBool("HAVING clause", true);
if (groupingInfo != null) {
groupingInfo.substituteGroupingFn(Arrays.asList(havingClauseAfterAnalyzed), analyzer);

View File

@ -22,6 +22,7 @@ package org.apache.doris.analysis;
import org.apache.doris.catalog.Env;
import org.apache.doris.catalog.TableIf;
import org.apache.doris.catalog.Type;
import org.apache.doris.catalog.external.HMSExternalTable;
import org.apache.doris.common.AnalysisException;
import org.apache.doris.common.ErrorCode;
@ -651,6 +652,9 @@ public class TableRef implements ParseNode, Writable {
analyzer.setVisibleSemiJoinedTuple(semiJoinedTupleId);
onClause.analyze(analyzer);
analyzer.setVisibleSemiJoinedTuple(null);
if (!onClause.getType().isBoolean()) {
onClause = onClause.castTo(Type.BOOLEAN);
}
onClause.checkReturnsBool("ON clause", true);
if (onClause.contains(Expr.isAggregatePredicate())) {
throw new AnalysisException(

View File

@ -31,4 +31,60 @@ suite('test_cast') {
sql "select cast(${datetime} as int), cast(${datetime} as bigint), cast(${datetime} as float), cast(${datetime} as double)"
result([[869930357, 20200101123445l, ((float) 20200101123445l), ((double) 20200101123445l)]])
}
}
def tbl = "test_cast"
sql """ DROP TABLE IF EXISTS ${tbl}"""
sql """
CREATE TABLE IF NOT EXISTS ${tbl} (
`k0` int
)
DISTRIBUTED BY HASH(`k0`) BUCKETS 5 properties("replication_num" = "1")
"""
sql """ INSERT INTO ${tbl} VALUES (101);"""
test {
sql "select * from ${tbl} where case when k0 = 101 then 1 else 0 end"
result([[101]])
}
test {
sql "select * from ${tbl} where case when k0 = 101 then 12 else 0 end"
result([[101]])
}
test {
sql "select * from ${tbl} where case when k0 = 101 then -12 else 0 end"
result([[101]])
}
test {
sql "select * from ${tbl} where case when k0 = 101 then 0 else 1 end"
result([])
}
test {
sql "select * from ${tbl} where case when k0 != 101 then 0 else 1 end"
result([[101]])
}
test {
sql "select * from ${tbl} where case when k0 = 101 then '1' else 0 end"
result([[101]])
}
test {
sql "select * from ${tbl} where case when k0 = 101 then '12' else 0 end"
result([])
}
test {
sql "select * from ${tbl} where case when k0 = 101 then 'false' else 0 end"
result([])
}
test {
sql "select * from ${tbl} where case when k0 = 101 then 'true' else 1 end"
result([[101]])
}
}