[
https://issues.apache.org/jira/browse/CALCITE-5296?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17610888#comment-17610888
]
Xurenhe commented on CALCITE-5296:
----------------------------------
[~libenchao]
I think second method need more changed code.
By the way, my original thought that let node_rel's cache be invalid, which
*selectScope* is {*}AggregatingSelectScope{*}, as follows:
{code:java}
//...
inferUnknownTypes(targetType, scope, expanded);
if (selectScope instanceof AggregatingSelectScope) {
removeInferErrorNodeType((AggregatingSelectScope) selectScope, expanded);
}
RelDataType type = deriveType(selectScope, expanded);
//...
/**
* Remove infer-error {@link SqlNode}
*/
private void removeInferErrorNodeType(AggregatingSelectScope scope, SqlNode
targetNode) {
final AggregatingSelectScope.Resolved r = scope.resolved.get();
final SqlBasicVisitor<Boolean> visitor = new SqlBasicVisitor<Boolean>() {
private boolean needRemove(SqlNode node) {
final RelDataType relDataType = nodeToTypeMap.get(node);
if (relDataType == null) {
return false;
}
if (relDataType.isNullable()) {
return false;
}
for (Ord<SqlNode> groupExpr : Ord.zip(r.groupExprList)) {
if (groupExpr.e.equalsDeep(node, Litmus.IGNORE)) {
if (r.isNullable(groupExpr.i)) {
return true;
}
}
}
return false;
}
@Override
public Boolean visit(SqlLiteral literal) {
final boolean needRemove = needRemove(literal);
if (needRemove) {
nodeToTypeMap.remove(literal);
}
return needRemove;
}
@Override
public Boolean visit(SqlCall call) {
boolean needRemove = false;
for (SqlNode operand : call.getOperandList()) {
if (operand != null && operand.accept(this)) {
needRemove = true;
}
}
if (needRemove) {
nodeToTypeMap.remove(call);
}
return needRemove;
}
@Override
public Boolean visit(SqlNodeList nodeList) {
boolean needRemove = false;
for (SqlNode sqlNode : nodeList) {
if (sqlNode != null && sqlNode.accept(this)) {
needRemove = true;
}
}
if (needRemove) {
nodeToTypeMap.remove(nodeList);
}
return needRemove;
}
@Override
public Boolean visit(SqlIdentifier id) {
final boolean needRemove = needRemove(id);
if (needRemove) {
nodeToTypeMap.remove(id);
}
return needRemove;
}
@Override
public Boolean visit(SqlDataTypeSpec type) {
final boolean needRemove = needRemove(type);
if (needRemove) {
nodeToTypeMap.remove(type);
}
return needRemove;
}
@Override
public Boolean visit(SqlDynamicParam param) {
final boolean needRemove = needRemove(param);
if (needRemove) {
nodeToTypeMap.remove(param);
}
return needRemove;
}
@Override
public Boolean visit(SqlIntervalQualifier intervalQualifier) {
final boolean needRemove = needRemove(intervalQualifier);
if (needRemove) {
nodeToTypeMap.remove(intervalQualifier);
}
return needRemove;
}
};
targetNode.accept(visitor);
}
{code}
> In a query with ROLLUP, validator wrongly infers that a column is NOT NULL
> --------------------------------------------------------------------------
>
> Key: CALCITE-5296
> URL: https://issues.apache.org/jira/browse/CALCITE-5296
> Project: Calcite
> Issue Type: Bug
> Components: core
> Reporter: Xurenhe
> Assignee: Xurenhe
> Priority: Major
> Labels: pull-request-available
> Attachments: image-2022-09-29-16-31-04-642.png, screenshot-1.png
>
> Time Spent: 10m
> Remaining Estimate: 0h
>
> CALCITE throws exception during the stage of sql_to_rel, when executing
> *SELECT* statement after the statement of {*}ROLLUP{*}, and grouping's item
> exists in the *SELECT* statement.
>
> {*}Error message{*}:
> {code:java}
> Conversion to relational algebra failed to preserve datatypes:
> validated type:
> RecordType(INTEGER DEPTNO, INTEGER NOT NULL EXPR$1) NOT NULL
> converted type:
> RecordType(INTEGER DEPTNO, INTEGER EXPR$1) NOT NULL
> rel:
> LogicalProject(DEPTNO=[$0], EXPR$1=[CASE(=($2, 0), $0, 1)])
> LogicalAggregate(group=[{0, 1}], groups=[[{0, 1}, {0}, {}]],
> agg#0=[GROUPING($0)])
> LogicalProject(DEPTNO=[$7], JOB=[$2])
> LogicalTableScan(table=[[CATALOG, SALES,
> EMP]])java.lang.AssertionError: Conversion to relational algebra failed to
> preserve datatypes:
> validated type:
> RecordType(INTEGER DEPTNO, INTEGER NOT NULL EXPR$1) NOT NULL
> converted type:
> RecordType(INTEGER DEPTNO, INTEGER EXPR$1) NOT NULL
> rel:
> LogicalProject(DEPTNO=[$0], EXPR$1=[CASE(=($2, 0), $0, 1)])
> LogicalAggregate(group=[{0, 1}], groups=[[{0, 1}, {0}, {}]],
> agg#0=[GROUPING($0)])
> LogicalProject(DEPTNO=[$7], JOB=[$2])
> LogicalTableScan(table=[[CATALOG, SALES, EMP]]) at
> org.apache.calcite.sql2rel.SqlToRelConverter.checkConvertedType(SqlToRelConverter.java:492)
> at
> org.apache.calcite.sql2rel.SqlToRelConverter.convertQuery(SqlToRelConverter.java:607)
> at
> org.apache.calcite.sql.test.AbstractSqlTester.convertSqlToRel2(AbstractSqlTester.java:536)
> at
> org.apache.calcite.sql.test.AbstractSqlTester.assertSqlConvertsTo(AbstractSqlTester.java:477)
> at
> org.apache.calcite.sql.test.AbstractSqlTester.assertConvertsTo(AbstractSqlTester.java:455)
> at
> org.apache.calcite.test.SqlToRelFixture.convertsTo(SqlToRelFixture.java:106)
> at org.apache.calcite.test.SqlToRelFixture.ok(SqlToRelFixture.java:94)
> at
> org.apache.calcite.test.SqlToRelConverterTest.testCaseWhenGroupingSet(SqlToRelConverterTest.java:4687)
> {code}
>
> {*}Test
> case{*}:(org.apache.calcite.test.SqlToRelConverterTest#testCaseWhenGroupingSet)
> {code:java}
> // JAVA: org.apache.calcite.test.SqlToRelConverterTest#testCaseWhenGroupingSet
> @Test void testCaseWhenGroupingSet() {
> final String sql = "select deptno, case when grouping(deptno) = 0 then
> deptno else 1 end\n"
> + "from emp\n"
> + "group by rollup(deptno, job)";
> sql(sql).ok();
> }
> // XML: org/apache/calcite/test/SqlToRelConverterTest.xml:456
> <TestCase name="testCaseWhenGroupingSet">
> <Resource name="sql">
> <![CDATA[SELECT deptno, CASE WHEN grouping(deptno) = 0 THEN deptno ELSE
> 1 END
> FROM emp
> GROUP BY ROLLUP(deptno, job)]]>
> </Resource>
> <Resource name="plan">
> <![CDATA[
> LogicalProject(DEPTNO=[$0], EXPR$1=[CASE(=($2, 0), $0, 1)])
> LogicalAggregate(group=[{0, 1}], groups=[[{0, 1}, {0}, {}]],
> agg#0=[GROUPING($0)])
> LogicalProject(DEPTNO=[$7], JOB=[$2])
> LogicalTableScan(table=[[CATALOG, SALES, EMP]])
> ]]>
> </Resource>
> </TestCase>{code}
>
>
--
This message was sent by Atlassian Jira
(v8.20.10#820010)