[ 
https://issues.apache.org/jira/browse/CALCITE-7062?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18009950#comment-18009950
 ] 

Zhen Chen commented on CALCITE-7062:
------------------------------------

Fixed in 
https://github.com/apache/calcite/commit/3719447e125982aaa47f0a7b2564f94b9900539e
Thanks for contribution [~alex_pl]
Thanks for reviews [~mbudiu] [~julianhyde] [~xuzifu666] [~nobigo]

> Row type of SetOp may ignore a column's nullability
> ---------------------------------------------------
>
>                 Key: CALCITE-7062
>                 URL: https://issues.apache.org/jira/browse/CALCITE-7062
>             Project: Calcite
>          Issue Type: Bug
>    Affects Versions: 1.39.0, 1.40.0
>            Reporter: Vladimir Steshin
>            Assignee: Aleksey Plekhanov
>            Priority: Minor
>              Labels: pull-request-available
>
> Reproducer:
> {code:java}
> package org.apache.calcite.test;
> class ServerTest {  
>     @Test void testNullableCoercionInUnion() throws Exception {
>       try (Connection c = connect(); Statement s = c.createStatement()) {
>         s.execute("create table t(a DATE)");
>         try (ResultSet r = s.executeQuery("SELECT a FROM t UNION ALL select 
> CURRENT_TIMESTAMP")) {
>           assertTrue(r.next());
>           assertFalse(r.next());
>         }
>       }
>    }
>    // Or
>    @Test void test2() throws Exception {
>    try (Connection c = connect(); Statement s = c.createStatement()) {
>      s.execute("create table t1(id int not null, test TIMESTAMP NOT NULL)");
>      s.execute("create table t2(id int not null, test VARCHAR)");
>      s.execute("insert into t1 values (1, SYSTIMESTAMP)");
>      s.execute("insert into t2 values (1, CAST(SYSDATE AS VARCHAR))");
>      String query = "SELECT cast(test as date) as test FROM t2 " +
>          "UNION ALL " +
>          "select test from t1";
>      s.execute(query);
>    }
> }{code}
> Failure:
> {code:java}
> Conversion to relational algebra failed to preserve datatypes:
> validated type:
> RecordType(TIMESTAMP(0) NOT NULL A) NOT NULL
> converted type:
> RecordType(TIMESTAMP(0) A) NOT NULL
> rel:
> LogicalUnion(all=[true])
>   LogicalProject(A=[CAST($0):TIMESTAMP(0)])
>     LogicalTableScan(table=[[T]])
>   LogicalProject(CURRENT_TIMESTAMP=[CURRENT_TIMESTAMP])
>     LogicalValues(tuples=[[{ 0 }]])
> at 
> org.apache.calcite.sql2rel.SqlToRelConverter.checkConvertedType(SqlToRelConverter.java:524)
>  at 
> org.apache.calcite.sql2rel.SqlToRelConverter.convertQuery(SqlToRelConverter.java:643)
>  at org.apache.calcite.prepare.Prepare.prepareSql(Prepare.java:258) at 
> org.apache.calcite.prepare.Prepare.prepareSql(Prepare.java:221) at 
> org.apache.calcite.prepare.CalcitePrepareImpl.prepare2_(CalcitePrepareImpl.java:673)
>  at 
> org.apache.calcite.prepare.CalcitePrepareImpl.prepare_(CalcitePrepareImpl.java:524)
>  at 
> org.apache.calcite.prepare.CalcitePrepareImpl.prepareSql(CalcitePrepareImpl.java:492)
>  at 
> org.apache.calcite.jdbc.CalciteConnectionImpl.parseQuery(CalciteConnectionImpl.java:246)
>  at 
> org.apache.calcite.jdbc.CalciteMetaImpl.prepareAndExecute(CalciteMetaImpl.java:654){code}
> Regarding my research, the nullability is lost somewhere around  
> {code:java}
> class AbstractTypeCoercion
> RelDataType syncAttributes(
>     RelDataType fromType,
>     RelDataType toType) {
>   RelDataType syncedType = toType;
>   if (fromType != null) {
>     syncedType = factory.createTypeWithNullability(syncedType, 
> fromType.isNullable());
>    ...
> }{code}
> It doesn't take in account {_}toType.isNullable(){_}.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to