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

Vladimir Sitnikov commented on CALCITE-1054:
--------------------------------------------

JdbcTest.testBooleansInWhere:
{code:java}
/* 252 */               if (((Object[]) inputEnumerator.current())[0] != null 
&& org.apache.calcite.runtime.SqlFunctions.toInt(((Object[]) 
inputEnumerator.current())[0]) != 1 && ((Object[]) 
inputEnumerator.current())[1] != null && 
org.apache.calcite.runtime.SqlFunctions.toInt(((Object[]) 
inputEnumerator.current())[1]) != 1) {
{code}

It is a bit strange that {{((Object[\]) inputEnumerator.current())\[0\]}} is 
not factored out to a local variable.

Same for testWhereNullable:
{code:java}
/*  16 */                 if ((Object) 
((org.apache.calcite.test.JdbcTest.Employee) 
inputEnumerator.current()).commission != null && 
((org.apache.calcite.test.JdbcTest.Employee) 
inputEnumerator.current()).commission.intValue() > 800) {{code}

JdbcTest.testWhereOrAndNullable is even more surprising: it creates write-only 
locals:
{code:java}/* 238 */             public boolean moveNext() {
/* 239 */               while (inputEnumerator.moveNext()) {
/* 240 */                 final Object[] current1;
/* 241 */                 final Object[] current2;
/* 242 */                 final Object[] current3;
/* 243 */                 final Object[] current4;
/* 244 */
    if (((Object[]) inputEnumerator.current())[1] != null
        && ((Object[]) inputEnumerator.current())[0] != null && (
        org.apache.calcite.runtime.SqlFunctions
            .eq((current1 = (Object[]) inputEnumerator.current())[0] == null ? 
(String) null
                : (current1 = (Object[]) 
inputEnumerator.current())[0].toString(), "a")
            && org.apache.calcite.runtime.SqlFunctions
            .eq((current2 = (Object[]) inputEnumerator.current())[1] == null ? 
(String) null
                : (current2 = (Object[]) 
inputEnumerator.current())[1].toString(), "b") ||
            org.apache.calcite.runtime.SqlFunctions
                .eq((current3 = (Object[]) inputEnumerator.current())[0] == 
null ? (String) null
                    : (current3 = (Object[]) 
inputEnumerator.current())[0].toString(), "b")
                && org.apache.calcite.runtime.SqlFunctions
                .eq((current4 = (Object[]) inputEnumerator.current())[1] == 
null ? (String) null
                    : (current4 = (Object[]) 
inputEnumerator.current())[1].toString(), "c"))) {
/* 245 */                   return true;
/* 246 */                 }
/* 247 */               }
/* 248 */               return false;
/* 249 */             }
{code}

org.apache.calcite.test.JdbcTest#testAggregateEmpty
Before:
{code:java}
/* 135 */               final Object[] current = (Object[]) 
inputEnumerator.current();
/* 136 */               final Object inp0_ = current[0];
/* 137 */               final int inp1_ = 
org.apache.calcite.runtime.SqlFunctions.toInt(current[1]);
/* 138 */               final long inp0_0 = 
org.apache.calcite.runtime.SqlFunctions.toLong(current[0]);
/* 139 */               final boolean v0 = inp0_0 == 0L;
/* 140 */               return new Object[] {
/* 141 */                   inp0_,
/* 142 */                   inp0_,
/* 143 */                   v0 ? (Integer) null : Integer.valueOf(inp1_),
/* 144 */                   v0 ? (Integer) null : Integer.valueOf((int) ((long) 
inp1_ / inp0_0))};
{code}

After:
{code:java}
/* 136 */             public Object current() {
/* 137 */               final Object[] current = (Object[]) 
inputEnumerator.current();
/* 138 */               final Object inp0_ = current[0];
/* 139 */               final long inp0_0 = 
org.apache.calcite.runtime.SqlFunctions.toLong(current[0]);
/* 140 */               final boolean v = inp0_0 == 0L;
/* 141 */               return new Object[] {
/* 142 */                   inp0_,
/* 143 */                   inp0_,
/* 144 */                   v ? (Integer) null : (Integer) current[1],
/* 145 */                   v || (Integer) current[1] == null ? (Integer) null 
: Integer.valueOf((int) ((long) (v ? (Integer) null : (Integer) 
current[1]).intValue() / inp0_0))};
/* 146 */             }{code}


testReuseExpressionWhenNullChecking5
Before:
{code:java}
/*  22 */             public Object current() {
/*  23 */               final org.apache.calcite.test.JdbcTest.Employee current 
= (org.apache.calcite.test.JdbcTest.Employee) inputEnumerator.current();
/*  24 */               final String inp2_ = current.name;
/*  25 */               final int inp1_ = current.deptno;
/*  26 */               return inp2_ == null || 
$L4J$C$_org_apache_calcite_runtime_SqlFunctions_eq_sa_sa_ || current.empid <= 
inp1_ && inp1_ * 8 <= 8 ? (String) null : 
org.apache.calcite.runtime.SqlFunctions.substring(org.apache.calcite.runtime.SqlFunctions.trim(true,
 true, " ", org.apache.calcite.runtime.SqlFunctions.substring(inp2_, inp1_ * 0 
+ 1)), $L4J$C$5_2);
/*  27 */             }
/*  28 */ 
/*  29 */             static final boolean 
$L4J$C$org_apache_calcite_runtime_SqlFunctions_eq_sa_sa_ = 
org.apache.calcite.runtime.SqlFunctions.eq("sa", "sa");
/*  30 */             static final boolean 
$L4J$C$_org_apache_calcite_runtime_SqlFunctions_eq_sa_sa_ = 
!$L4J$C$org_apache_calcite_runtime_SqlFunctions_eq_sa_sa_;
/*  31 */             static final int $L4J$C$5_2 = 5 - 2;{code}

After:
Notes:
1) {{Integer.valueOf(1)==null}} check is produced. "before" variation seemed to 
optimize that.
2) {{: (Integer) null).intValue() - 2)}} at the end looks dangerous. It might 
produce NPE.
{code:java}
/*  22 */             public Object current() {
/*  23 */               final org.apache.calcite.test.JdbcTest.Employee current 
= (org.apache.calcite.test.JdbcTest.Employee) inputEnumerator.current();
/*  24 */               return (Object) current.name == null ? (String) null : 
$L4J$C$_org_apache_calcite_runtime_SqlFunctions_eq_sa_sa_Integer_valueabc5caed 
? (String) null : (current.empid > current.deptno ? $L4J$C$Integer_valueOf_5_ : 
current.deptno * 8 > 8 ? $L4J$C$Integer_valueOf_5_ : (Integer) null) == null ? 
(String) null : 
org.apache.calcite.runtime.SqlFunctions.substring(org.apache.calcite.runtime.SqlFunctions.trim(true,
 true, " ", org.apache.calcite.runtime.SqlFunctions.substring(current.name, 
current.deptno * 0 + 
$L4J$C$org_apache_calcite_runtime_SqlFunctions_eq_sa_sa_Integer_valueO102161ff.intValue())),
 (current.empid > current.deptno ? $L4J$C$Integer_valueOf_5_ : current.deptno * 
8 > 8 ? $L4J$C$Integer_valueOf_5_ : (Integer) null).intValue() - 2);
/*  25 */             }
/*  26 */ 
/*  27 */             static final boolean 
$L4J$C$org_apache_calcite_runtime_SqlFunctions_eq_sa_sa_ = 
org.apache.calcite.runtime.SqlFunctions.eq("sa", "sa");
/*  28 */             static final boolean 
$L4J$C$_org_apache_calcite_runtime_SqlFunctions_eq_sa_sa_ = 
!$L4J$C$org_apache_calcite_runtime_SqlFunctions_eq_sa_sa_;
/*  29 */             static final Integer $L4J$C$Integer_valueOf_1_ = 
Integer.valueOf(1);
/*  30 */             static final boolean $L4J$C$Integer_valueOf_1_null = 
$L4J$C$Integer_valueOf_1_ == null;
/*  31 */             static final boolean 
$L4J$C$_org_apache_calcite_runtime_SqlFunctions_eq_sa_sa_Integer_valueabc5caed 
= $L4J$C$_org_apache_calcite_runtime_SqlFunctions_eq_sa_sa_ || 
$L4J$C$Integer_valueOf_1_null;
/*  32 */             static final Integer $L4J$C$Integer_valueOf_5_ = 
Integer.valueOf(5);
/*  33 */             static final Integer 
$L4J$C$org_apache_calcite_runtime_SqlFunctions_eq_sa_sa_Integer_valueO102161ff 
= $L4J$C$org_apache_calcite_runtime_SqlFunctions_eq_sa_sa_ ? 
$L4J$C$Integer_valueOf_1_ : (Integer) null;
/*  34 */           };
/*  35 */       }{code}


{code:sql}
select  case when 1>2 then 10 else case when 3>4 then 20 end end-2
  from "hr"."emps"
{code}

Before:
{code:java}
/*  22 */             public Object current() {
/*  23 */               final boolean v1 = $L4J$C$1_2;
/*  24 */               return !v1 && $L4J$C$3_4 ? (Integer) null : 
Integer.valueOf((v1 ? 10 : 20) - 2);
/*  25 */             }
/*  26 */ 
/*  27 */             static final boolean $L4J$C$1_2 = 1 > 2;
/*  28 */             static final boolean $L4J$C$3_4 = 3 <= 4;{code}

After:
Notes: *strange reboxing* {{(v ? $L4J$C$Integer_valueOf_10_ : 
$L4J$C$3_4_Integer_valueOf_20_Integer_null).intValue()}}
{code:java}
/*  22 */             public Object current() {
/*  23 */               final boolean v = $L4J$C$1_2;
/*  24 */               return (v ? $L4J$C$Integer_valueOf_10_ : 
$L4J$C$3_4_Integer_valueOf_20_Integer_null) == null ? (Integer) null : 
Integer.valueOf((v ? $L4J$C$Integer_valueOf_10_ : 
$L4J$C$3_4_Integer_valueOf_20_Integer_null).intValue() - 2);
/*  25 */             }
/*  26 */ 
/*  27 */             static final boolean $L4J$C$1_2 = 1 > 2;
/*  28 */             static final Integer $L4J$C$Integer_valueOf_10_ = 
Integer.valueOf(10);
/*  29 */             static final boolean $L4J$C$3_4 = 3 > 4;
/*  30 */             static final Integer $L4J$C$Integer_valueOf_20_ = 
Integer.valueOf(20);
/*  31 */             static final Integer 
$L4J$C$3_4_Integer_valueOf_20_Integer_null = $L4J$C$3_4 ? 
$L4J$C$Integer_valueOf_20_ : (Integer) null;
{code}


Test (testTrivialSort with slight modification of a query):
{code:java}
    final String sql = "select a.\"value\"||b.\"value\"\n"
        + "  from \"bools\" a\n"
        + "     , \"bools\" b\n"
        + " offset 0";
    CalciteAssert.that()
        .withSchema("s",
            new ReflectiveSchema(
                new ReflectiveSchemaTest.CatchallSchema())){code}

Before:
{code:java}
/* 101 */             public Object current() {
/* 102 */               final Object[] current = (Object[]) 
inputEnumerator.current();
/* 103 */               final String inp0_ = current[0] == null ? (String) null 
: current[0].toString();
/* 104 */               final String inp1_ = current[1] == null ? (String) null 
: current[1].toString();
/* 105 */               return inp0_ == null || inp1_ == null ? (String) null : 
org.apache.calcite.runtime.SqlFunctions.concat(inp0_, inp1_);
/* 106 */             }
{code}

After:
Note: {{current[0] == null }} is redundant in concat argument
{code:java}
/* 101 */             public Object current() {
/* 102 */               final Object[] current = (Object[]) 
inputEnumerator.current();
/* 103 */               return current[0] == null ? 
$L4J$C$org_apache_calcite_runtime_SqlFunctions_truncate_String_null_1_ : 
current[1] == null ? 
$L4J$C$org_apache_calcite_runtime_SqlFunctions_truncate_String_null_1_ : 
org.apache.calcite.runtime.SqlFunctions.concat(current[0] == null ? (String) 
null : current[0].toString(), current[1] == null ? (String) null : 
current[1].toString());
/* 104 */             }
/* 105 */ 
/* 106 */             static final String 
$L4J$C$org_apache_calcite_runtime_SqlFunctions_truncate_String_null_1_ = 
org.apache.calcite.runtime.SqlFunctions.truncate((String) null, 1);{code}

> NPE caused by wrong code generation for Timestamp fields
> --------------------------------------------------------
>
>                 Key: CALCITE-1054
>                 URL: https://issues.apache.org/jira/browse/CALCITE-1054
>             Project: Calcite
>          Issue Type: Bug
>          Components: core
>    Affects Versions: 1.6.0, 1.5.0, 1.4.0-incubating
>            Reporter: Frankie Bollaert
>            Assignee: Julian Hyde
>            Priority: Minor
>
> Problem occurs when:
> - Execute a query containing 2 checks on a Timestamp field
> - Table contains records which have NULL values for this field 
> Example query:
> {code}
> select * from aTable where aTimestamp > timestamp '2015-1-1 00:00:00' and 
> aTimestamp < timestamp '2015-2-1 00:00:00';
> {code}
> {code}
> /*  48 */   public boolean moveNext() {
> /*  49 */     while (inputEnumerator.moveNext()) {
> /*  50 */       final java.sql.Timestamp inp23_ = (java.sql.Timestamp) 
> ((Object[]) inputEnumerator.current())[23];
> /*  51 */       final long v = 
> org.apache.calcite.runtime.SqlFunctions.toLong(inp23_);
> /*  52 */       if (inp23_ != null && v > 1420070400000L && (inp23_ != null 
> && v < 1422748800000L)) {
> /*  53 */         return true;
> /*  54 */       }
> /*  55 */     }
> /*  56 */     return false;
> /*  57 */   }
> {code}
> Stack trace snippet
> {code}
> Caused by: java.lang.NullPointerException
>       at 
> org.apache.calcite.runtime.SqlFunctions.toLong(SqlFunctions.java:1094)
>       at 
> org.apache.calcite.runtime.SqlFunctions.toLong(SqlFunctions.java:1089)
>       at Baz$1$1.moveNext(ANONYMOUS.java:51)
>       at 
> org.apache.calcite.linq4j.Linq4j$EnumeratorIterator.<init>(Linq4j.java:677)
>       at org.apache.calcite.linq4j.Linq4j.enumeratorIterator(Linq4j.java:103)
> {code}
> The generated code also looks wrong for date fields.
> {code}
> /*  15 */   public boolean moveNext() {
> /*  16 */     while (inputEnumerator.moveNext()) {
> /*  17 */       final java.sql.Date current = (java.sql.Date) 
> inputEnumerator.current();
> /*  18 */       final int v = 
> org.apache.calcite.runtime.SqlFunctions.toInt(current);
> /*  19 */       if (current != null && v > 2780 && (current != null && v < 
> 5290)) {
> /*  20 */         return true;
> /*  21 */       }
> /*  22 */     }
> /*  23 */     return false;
> /*  24 */   }
> {code}
> \\
> Other types of fields do not have this problem.  Below is what the generated 
> code looks like in the case of a String field.  *On line 20 there is a null 
> check.*  This is the type of check that needs to be generated for Timestamp 
> fields as well. 
> {code}
> select empno from sales.emps where gender > 'A' and gender < 'Z';
> {code}
> {code}
> /*  17 */  public boolean moveNext() {
> /*  18 */    while (inputEnumerator.moveNext()) {
> /*  19 */      final Object[] current = (Object[]) inputEnumerator.current();
> /*  20 */      final String inp3_ = current[3] == null ? (String) null : 
> current[3].toString();
> /*  21 */      if (inp3_ != null && 
> org.apache.calcite.runtime.SqlFunctions.gt(inp3_, 
> $L4J$C$org_apache_calcite_runtime_SqlFunctions_rtrim_A_) && (inp3_ != null && 
> org.apache.calcite.runtime.SqlFunctions.lt(inp3_, 
> $L4J$C$org_apache_calcite_runtime_SqlFunctions_rtrim_Z_))) {
> /*  22 */        return true;
> /*  23 */      }
> /*  24 */    }
> /*  25 */    return false;
> /*  26 */  }
> {code}



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to