You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@kylin.apache.org by "Zhong Yanghong (JIRA)" <ji...@apache.org> on 2019/03/19 09:50:00 UTC

[jira] [Commented] (KYLIN-3881) Calcite isolating expression with its condition may throw 'Division Undefined' exception

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

Zhong Yanghong commented on KYLIN-3881:
---------------------------------------

The patch is based on calcite tag *calcite-1.16.0*.

> Calcite isolating expression with its condition may throw 'Division Undefined' exception
> ----------------------------------------------------------------------------------------
>
>                 Key: KYLIN-3881
>                 URL: https://issues.apache.org/jira/browse/KYLIN-3881
>             Project: Kylin
>          Issue Type: Bug
>            Reporter: Zhong Yanghong
>            Assignee: Zhong Yanghong
>            Priority: Major
>             Fix For: v3.0.0
>
>         Attachments: APACHE-KYLIN-3881.patch
>
>
> When invoke the following sql:
> {code:java}
> SELECT LSTG_FORMAT_NAME, (case when sum(PRICE) <> 0 then sum(PRICE)/min(price) else 0 end)
> FROM TEST_KYLIN_FACT
> GROUP BY LSTG_FORMAT_NAME
> HAVING (case when sum(PRICE) <> 0 then sum(PRICE)/min(price) else 0 end >= 0.5
>         and case when sum(PRICE) <> 0 then sum(PRICE)/min(price) else 0 end <= 0.75)
> {code}
> The generated code of moveMext part is as follow:
> {code:java}
> /* 157 */ public boolean moveNext() {
> /* 158 */ while (inputEnumerator.moveNext()) {
> /* 159 */ final Object[] current = (Object[]) inputEnumerator.current();
> /* 160 */ final java.math.BigDecimal inp1_ = current[1] == null ? (java.math.BigDecimal) null : org.apache.calcite.runtime.SqlFunctions.toBigDecimal(current[1]);
> /* 161 */ final java.math.BigDecimal inp2_ = current[2] == null ? (java.math.BigDecimal) null : org.apache.calcite.runtime.SqlFunctions.toBigDecimal(current[2]);
> /* 162 */ final java.math.BigDecimal v0 = org.apache.calcite.runtime.SqlFunctions.divide(inp1_, inp2_);
> /* 163 */ if (inp1_ != null && org.apache.calcite.runtime.SqlFunctions.ne(inp1_, $L4J$C$new_java_math_BigDecimal_0_) && (inp1_ != null && inp2_ != null && org.apache.calcite.runtime.SqlFunctions.ge(v0, $L4J$C$new_java_math_BigDecimal_0_5_)) && (!(inp1_ != null && org.apache.calcite.runtime.SqlFunctions.ne(inp1_, $L4J$C$new_java_math_BigDecimal_0_)) || inp1_ != null && inp2_ != null && org.apache.calcite.runtime.SqlFunctions.le(v0, $L4J$C$new_java_math_BigDecimal_0_75_))) {
> /* 164 */ return true;
> /* 165 */ }
> /* 166 */ }
> /* 167 */ return false;
> /* 168 */ }
> {code}
> line 162, the divide logic should be combined with its condition. Otherwise, the 'Division Undefined' exception will happen.
> The whole generated code is as follows:
> {code:java}
> /*   1 */ public static class Record4_0 implements java.io.Serializable {
> /*   2 */   public java.math.BigDecimal f0;
> /*   3 */   public boolean f1;
> /*   4 */   public java.math.BigDecimal f2;
> /*   5 */   public boolean f3;
> /*   6 */   public Record4_0() {}
> /*   7 */   public boolean equals(Object o) {
> /*   8 */     if (this == o) {
> /*   9 */       return true;
> /*  10 */     }
> /*  11 */     if (!(o instanceof Record4_0)) {
> /*  12 */       return false;
> /*  13 */     }
> /*  14 */     return java.util.Objects.equals(this.f0, ((Record4_0) o).f0) && this.f1 == ((Record4_0) o).f1 && java.util.Objects.equals(this.f2, ((Record4_0) o).f2) && this.f3 == ((Record4_0) o).f3;
> /*  15 */   }
> /*  16 */ 
> /*  17 */   public int hashCode() {
> /*  18 */     int h = 0;
> /*  19 */     h = org.apache.calcite.runtime.Utilities.hash(h, this.f0);
> /*  20 */     h = org.apache.calcite.runtime.Utilities.hash(h, this.f1);
> /*  21 */     h = org.apache.calcite.runtime.Utilities.hash(h, this.f2);
> /*  22 */     h = org.apache.calcite.runtime.Utilities.hash(h, this.f3);
> /*  23 */     return h;
> /*  24 */   }
> /*  25 */ 
> /*  26 */   public int compareTo(Record4_0 that) {
> /*  27 */     int c;
> /*  28 */     c = org.apache.calcite.runtime.Utilities.compareNullsLast(this.f0, that.f0);
> /*  29 */     if (c != 0) {
> /*  30 */       return c;
> /*  31 */     }
> /*  32 */     c = org.apache.calcite.runtime.Utilities.compare(this.f1, that.f1);
> /*  33 */     if (c != 0) {
> /*  34 */       return c;
> /*  35 */     }
> /*  36 */     c = org.apache.calcite.runtime.Utilities.compareNullsLast(this.f2, that.f2);
> /*  37 */     if (c != 0) {
> /*  38 */       return c;
> /*  39 */     }
> /*  40 */     c = org.apache.calcite.runtime.Utilities.compare(this.f3, that.f3);
> /*  41 */     if (c != 0) {
> /*  42 */       return c;
> /*  43 */     }
> /*  44 */     return 0;
> /*  45 */   }
> /*  46 */ 
> /*  47 */   public String toString() {
> /*  48 */     return "{f0=" + this.f0 + ", f1=" + this.f1 + ", f2=" + this.f2 + ", f3=" + this.f3 + "}";
> /*  49 */   }
> /*  50 */ 
> /*  51 */ }
> /*  52 */ 
> /*  53 */ org.apache.calcite.DataContext root;
> /*  54 */ 
> /*  55 */ public org.apache.calcite.linq4j.Enumerable bind(final org.apache.calcite.DataContext root0) {
> /*  56 */   root = root0;
> /*  57 */   final org.apache.calcite.linq4j.Enumerable _inputEnumerable = ((org.apache.kylin.query.schema.OLAPTable) root.getRootSchema().getSubSchema("DEFAULT").getTable("TEST_KYLIN_FACT")).executeOLAPQuery(root, 0);
> /*  58 */   final org.apache.calcite.linq4j.AbstractEnumerable child = new org.apache.calcite.linq4j.AbstractEnumerable(){
> /*  59 */     public org.apache.calcite.linq4j.Enumerator enumerator() {
> /*  60 */       return new org.apache.calcite.linq4j.Enumerator(){
> /*  61 */           public final org.apache.calcite.linq4j.Enumerator inputEnumerator = _inputEnumerable.enumerator();
> /*  62 */           public void reset() {
> /*  63 */             inputEnumerator.reset();
> /*  64 */           }
> /*  65 */ 
> /*  66 */           public boolean moveNext() {
> /*  67 */             return inputEnumerator.moveNext();
> /*  68 */           }
> /*  69 */ 
> /*  70 */           public void close() {
> /*  71 */             inputEnumerator.close();
> /*  72 */           }
> /*  73 */ 
> /*  74 */           public Object current() {
> /*  75 */             final Object[] current = (Object[]) inputEnumerator.current();
> /*  76 */             return new Object[] {
> /*  77 */                 current[3],
> /*  78 */                 current[8],
> /*  79 */                 current[13],
> /*  80 */                 current[14]};
> /*  81 */           }
> /*  82 */ 
> /*  83 */         };
> /*  84 */     }
> /*  85 */ 
> /*  86 */   };
> /*  87 */   final org.apache.calcite.linq4j.Enumerable _inputEnumerable0 = child.groupBy(new org.apache.calcite.linq4j.function.Function1() {
> /*  88 */     public String apply(Object[] a0) {
> /*  89 */       return a0[0] == null ? (String) null : a0[0].toString();
> /*  90 */     }
> /*  91 */     public Object apply(Object a0) {
> /*  92 */       return apply(
> /*  93 */         (Object[]) a0);
> /*  94 */     }
> /*  95 */   }
> /*  96 */   , new org.apache.calcite.linq4j.function.Function0() {
> /*  97 */     public Object apply() {
> /*  98 */       java.math.BigDecimal SUMa0s0;
> /*  99 */       boolean SUMa0s1;
> /* 100 */       SUMa0s1 = false;
> /* 101 */       SUMa0s0 = new java.math.BigDecimal(0L);
> /* 102 */       java.math.BigDecimal MINa1s0;
> /* 103 */       boolean MINa1s1;
> /* 104 */       MINa1s1 = false;
> /* 105 */       MINa1s0 = (java.math.BigDecimal) null;
> /* 106 */       Record4_0 record0;
> /* 107 */       record0 = new Record4_0();
> /* 108 */       record0.f0 = SUMa0s0;
> /* 109 */       record0.f1 = SUMa0s1;
> /* 110 */       record0.f2 = MINa1s0;
> /* 111 */       record0.f3 = MINa1s1;
> /* 112 */       return record0;
> /* 113 */     }
> /* 114 */   }
> /* 115 */   , new org.apache.calcite.linq4j.function.Function2() {
> /* 116 */     public Record4_0 apply(Record4_0 acc, Object[] in) {
> /* 117 */       final java.math.BigDecimal inp2_ = in[2] == null ? (java.math.BigDecimal) null : org.apache.calcite.runtime.SqlFunctions.toBigDecimal(in[2]);
> /* 118 */       if (inp2_ != null) {
> /* 119 */         acc.f1 = true;
> /* 120 */         acc.f0 = acc.f0.add(inp2_);
> /* 121 */       }
> /* 122 */       final java.math.BigDecimal inp3_ = in[3] == null ? (java.math.BigDecimal) null : org.apache.calcite.runtime.SqlFunctions.toBigDecimal(in[3]);
> /* 123 */       if (inp3_ != null) {
> /* 124 */         acc.f3 = true;
> /* 125 */         acc.f2 = (java.math.BigDecimal) org.apache.calcite.runtime.SqlFunctions.lesser(acc.f2, inp3_);
> /* 126 */       }
> /* 127 */       return acc;
> /* 128 */     }
> /* 129 */     public Record4_0 apply(Object acc, Object in) {
> /* 130 */       return apply(
> /* 131 */         (Record4_0) acc,
> /* 132 */         (Object[]) in);
> /* 133 */     }
> /* 134 */   }
> /* 135 */   , new org.apache.calcite.linq4j.function.Function2() {
> /* 136 */     public Object[] apply(String key, Record4_0 acc) {
> /* 137 */       return new Object[] {
> /* 138 */           key,
> /* 139 */           acc.f1 ? acc.f0 : (java.math.BigDecimal) null,
> /* 140 */           acc.f3 ? acc.f2 : (java.math.BigDecimal) null};
> /* 141 */     }
> /* 142 */     public Object[] apply(Object key, Object acc) {
> /* 143 */       return apply(
> /* 144 */         (String) key,
> /* 145 */         (Record4_0) acc);
> /* 146 */     }
> /* 147 */   }
> /* 148 */   );
> /* 149 */   final org.apache.calcite.linq4j.AbstractEnumerable child0 = new org.apache.calcite.linq4j.AbstractEnumerable(){
> /* 150 */     public org.apache.calcite.linq4j.Enumerator enumerator() {
> /* 151 */       return new org.apache.calcite.linq4j.Enumerator(){
> /* 152 */           public final org.apache.calcite.linq4j.Enumerator inputEnumerator = _inputEnumerable0.enumerator();
> /* 153 */           public void reset() {
> /* 154 */             inputEnumerator.reset();
> /* 155 */           }
> /* 156 */ 
> /* 157 */           public boolean moveNext() {
> /* 158 */             while (inputEnumerator.moveNext()) {
> /* 159 */               final Object[] current = (Object[]) inputEnumerator.current();
> /* 160 */               final java.math.BigDecimal inp1_ = current[1] == null ? (java.math.BigDecimal) null : org.apache.calcite.runtime.SqlFunctions.toBigDecimal(current[1]);
> /* 161 */               final java.math.BigDecimal inp2_ = current[2] == null ? (java.math.BigDecimal) null : org.apache.calcite.runtime.SqlFunctions.toBigDecimal(current[2]);
> /* 162 */               final java.math.BigDecimal v0 = org.apache.calcite.runtime.SqlFunctions.divide(inp1_, inp2_);
> /* 163 */               if (inp1_ != null && org.apache.calcite.runtime.SqlFunctions.ne(inp1_, $L4J$C$new_java_math_BigDecimal_0_) && (inp1_ != null && inp2_ != null && org.apache.calcite.runtime.SqlFunctions.ge(v0, $L4J$C$new_java_math_BigDecimal_0_5_)) && (!(inp1_ != null && org.apache.calcite.runtime.SqlFunctions.ne(inp1_, $L4J$C$new_java_math_BigDecimal_0_)) || inp1_ != null && inp2_ != null && org.apache.calcite.runtime.SqlFunctions.le(v0, $L4J$C$new_java_math_BigDecimal_0_75_))) {
> /* 164 */                 return true;
> /* 165 */               }
> /* 166 */             }
> /* 167 */             return false;
> /* 168 */           }
> /* 169 */ 
> /* 170 */           public void close() {
> /* 171 */             inputEnumerator.close();
> /* 172 */           }
> /* 173 */ 
> /* 174 */           public Object current() {
> /* 175 */             final Object[] current = (Object[]) inputEnumerator.current();
> /* 176 */             final java.math.BigDecimal inp1_ = current[1] == null ? (java.math.BigDecimal) null : org.apache.calcite.runtime.SqlFunctions.toBigDecimal(current[1]);
> /* 177 */             final java.math.BigDecimal inp2_ = current[2] == null ? (java.math.BigDecimal) null : org.apache.calcite.runtime.SqlFunctions.toBigDecimal(current[2]);
> /* 178 */             return new Object[] {
> /* 179 */                 current[0],
> /* 180 */                 inp1_ != null && org.apache.calcite.runtime.SqlFunctions.ne(inp1_, $L4J$C$new_java_math_BigDecimal_0_) ? (inp1_ == null || inp2_ == null ? (java.math.BigDecimal) null : org.apache.calcite.runtime.SqlFunctions.divide(inp1_, inp2_)) : $L4J$C$new_java_math_BigDecimal_0_};
> /* 181 */           }
> /* 182 */ 
> /* 183 */           static final java.math.BigDecimal $L4J$C$new_java_math_BigDecimal_0_ = new java.math.BigDecimal(
> /* 184 */             "0");
> /* 185 */           static final java.math.BigDecimal $L4J$C$new_java_math_BigDecimal_0_5_ = new java.math.BigDecimal(
> /* 186 */             "0.5");
> /* 187 */           static final java.math.BigDecimal $L4J$C$new_java_math_BigDecimal_0_75_ = new java.math.BigDecimal(
> /* 188 */             "0.75");
> /* 189 */         };
> /* 190 */     }
> /* 191 */ 
> /* 192 */   };
> /* 193 */   return child0.take(50000);
> /* 194 */ }
> /* 195 */ 
> /* 196 */ 
> /* 197 */ public Class getElementType() {
> /* 198 */   return java.lang.Object[].class;
> /* 199 */ }
> /* 200 */ 
> /* 201 */ 
> {code}



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)