[ 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)