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)