Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Padding for TABLESWITCH can be applied multiple times due to grow on relocatables #113

Closed
HeartSaVioR opened this issue Mar 5, 2020 · 11 comments

Comments

@HeartSaVioR
Copy link
Contributor

HeartSaVioR commented Mar 5, 2020

I have observed some compilation error on generated code for Spark, which is around switch statement.
(The generated code is compiled against Janino 3.0.8 but upgrading version to Janino 3.0.15 didn't seem to fix the issue.)

org.codehaus.janino.InternalCompilerException: Compiling "GeneratedClass": Compiling "expand_doConsume(short expand_expr_0, boolean expand_exprIsNull_0, int expand_expr_1, boolean expand_exprIsNull_1, Decimal expand_expr_2, boolean expand_exprIsNull_2, Decimal expand_expr_3, boolean expand_exprIsNull_3, Decimal expand_expr_4, boolean expand_exprIsNull_4, Decimal expand_expr_5, boolean expand_exprIsNull_5, Decimal expand_expr_6, boolean expand_exprIsNull_6, Decimal expand_expr_7, boolean expand_exprIsNull_7, Decimal expand_expr_8, boolean expand_exprIsNull_8, Decimal expand_expr_9, boolean expand_exprIsNull_9, long expand_expr_10, boolean expand_exprIsNull_10, long expand_expr_11, boolean expand_exprIsNull_11, long expand_expr_12, boolean expand_exprIsNull_12, long expand_expr_13, boolean expand_exprIsNull_13, long expand_expr_14, boolean expand_exprIsNull_14, long expand_expr_15, boolean expand_exprIsNull_15, long expand_expr_16, boolean expand_exprIsNull_16, long expand_expr_17, boolean expand_exprIsNull_17, long expand_expr_18, boolean expand_exprIsNull_18, long expand_expr_19, boolean expand_exprIsNull_19, Decimal expand_expr_20, boolean expand_exprIsNull_20, Decimal expand_expr_21, boolean expand_exprIsNull_21, Decimal expand_expr_22, boolean expand_exprIsNull_22, Decimal expand_expr_23, boolean expand_exprIsNull_23, Decimal expand_expr_24, boolean expand_exprIsNull_24, Decimal expand_expr_25, boolean expand_exprIsNull_25, Decimal expand_expr_26, boolean expand_exprIsNull_26, Decimal expand_expr_27, boolean expand_exprIsNull_27, Decimal expand_expr_28, boolean expand_exprIsNull_28, Decimal expand_expr_29, boolean expand_exprIsNull_29, Decimal expand_expr_30, boolean expand_exprIsNull_30, Decimal expand_expr_31, boolean expand_exprIsNull_31, Decimal expand_expr_32, boolean expand_exprIsNull_32, Decimal expand_expr_33, boolean expand_exprIsNull_33, Decimal expand_expr_34, boolean expand_exprIsNull_34, Decimal expand_expr_35, boolean expand_exprIsNull_35, Decimal expand_expr_36, boolean expand_exprIsNull_36, Decimal expand_expr_37, boolean expand_exprIsNull_37, Decimal expand_expr_38, boolean expand_exprIsNull_38, Decimal expand_expr_39, boolean expand_exprIsNull_39, Decimal expand_expr_40, boolean expand_exprIsNull_40, Decimal expand_expr_41, boolean expand_exprIsNull_41, long expand_expr_42, boolean expand_exprIsNull_42, long expand_expr_43, boolean expand_exprIsNull_43, long expand_expr_44, boolean expand_exprIsNull_44, long expand_expr_45, boolean expand_exprIsNull_45, long expand_expr_46, boolean expand_exprIsNull_46, long expand_expr_47, boolean expand_exprIsNull_47, long expand_expr_48, boolean expand_exprIsNull_48, long expand_expr_49, boolean expand_exprIsNull_49, long expand_expr_50, boolean expand_exprIsNull_50, long expand_expr_51, boolean expand_exprIsNull_51, long expand_expr_52, boolean expand_exprIsNull_52, long expand_expr_53, boolean expand_exprIsNull_53, long expand_expr_54, boolean expand_exprIsNull_54, long expand_expr_55, boolean expand_exprIsNull_55, long expand_expr_56, boolean expand_exprIsNull_56, long expand_expr_57, boolean expand_exprIsNull_57, long expand_expr_58, boolean expand_exprIsNull_58, long expand_expr_59, boolean expand_exprIsNull_59, long expand_expr_60, boolean expand_exprIsNull_60, long expand_expr_61, boolean expand_exprIsNull_61, long expand_expr_62, boolean expand_exprIsNull_62, long expand_expr_63, boolean expand_exprIsNull_63)"; expand_doConsume(short expand_expr_0, boolean expand_exprIsNull_0, int expand_expr_1, boolean expand_exprIsNull_1, Decimal expand_expr_2, boolean expand_exprIsNull_2, Decimal expand_expr_3, boolean expand_exprIsNull_3, Decimal expand_expr_4, boolean expand_exprIsNull_4, Decimal expand_expr_5, boolean expand_exprIsNull_5, Decimal expand_expr_6, boolean expand_exprIsNull_6, Decimal expand_expr_7, boolean expand_exprIsNull_7, Decimal expand_expr_8, boolean expand_exprIsNull_8, Decimal expand_expr_9, boolean expand_exprIsNull_9, long expand_expr_10, boolean expand_exprIsNull_10, long expand_expr_11, boolean expand_exprIsNull_11, long expand_expr_12, boolean expand_exprIsNull_12, long expand_expr_13, boolean expand_exprIsNull_13, long expand_expr_14, boolean expand_exprIsNull_14, long expand_expr_15, boolean expand_exprIsNull_15, long expand_expr_16, boolean expand_exprIsNull_16, long expand_expr_17, boolean expand_exprIsNull_17, long expand_expr_18, boolean expand_exprIsNull_18, long expand_expr_19, boolean expand_exprIsNull_19, Decimal expand_expr_20, boolean expand_exprIsNull_20, Decimal expand_expr_21, boolean expand_exprIsNull_21, Decimal expand_expr_22, boolean expand_exprIsNull_22, Decimal expand_expr_23, boolean expand_exprIsNull_23, Decimal expand_expr_24, boolean expand_exprIsNull_24, Decimal expand_expr_25, boolean expand_exprIsNull_25, Decimal expand_expr_26, boolean expand_exprIsNull_26, Decimal expand_expr_27, boolean expand_exprIsNull_27, Decimal expand_expr_28, boolean expand_exprIsNull_28, Decimal expand_expr_29, boolean expand_exprIsNull_29, Decimal expand_expr_30, boolean expand_exprIsNull_30, Decimal expand_expr_31, boolean expand_exprIsNull_31, Decimal expand_expr_32, boolean expand_exprIsNull_32, Decimal expand_expr_33, boolean expand_exprIsNull_33, Decimal expand_expr_34, boolean expand_exprIsNull_34, Decimal expand_expr_35, boolean expand_exprIsNull_35, Decimal expand_expr_36, boolean expand_exprIsNull_36, Decimal expand_expr_37, boolean expand_exprIsNull_37, Decimal expand_expr_38, boolean expand_exprIsNull_38, Decimal expand_expr_39, boolean expand_exprIsNull_39, Decimal expand_expr_40, boolean expand_exprIsNull_40, Decimal expand_expr_41, boolean expand_exprIsNull_41, long expand_expr_42, boolean expand_exprIsNull_42, long expand_expr_43, boolean expand_exprIsNull_43, long expand_expr_44, boolean expand_exprIsNull_44, long expand_expr_45, boolean expand_exprIsNull_45, long expand_expr_46, boolean expand_exprIsNull_46, long expand_expr_47, boolean expand_exprIsNull_47, long expand_expr_48, boolean expand_exprIsNull_48, long expand_expr_49, boolean expand_exprIsNull_49, long expand_expr_50, boolean expand_exprIsNull_50, long expand_expr_51, boolean expand_exprIsNull_51, long expand_expr_52, boolean expand_exprIsNull_52, long expand_expr_53, boolean expand_exprIsNull_53, long expand_expr_54, boolean expand_exprIsNull_54, long expand_expr_55, boolean expand_exprIsNull_55, long expand_expr_56, boolean expand_exprIsNull_56, long expand_expr_57, boolean expand_exprIsNull_57, long expand_expr_58, boolean expand_exprIsNull_58, long expand_expr_59, boolean expand_exprIsNull_59, long expand_expr_60, boolean expand_exprIsNull_60, long expand_expr_61, boolean expand_exprIsNull_61, long expand_expr_62, boolean expand_exprIsNull_62, long expand_expr_63, boolean expand_exprIsNull_63): Operand stack inconsistent at offset 578: Previous size 1, now 0

With some investigation I found that there's a "branch" before TABLESWITCH OP which requires "growing" - so below situation is happening:

  1. In the first loop of fixUpAndRelocate
    1.1) The padding for TABLESWITCH is applied first in fixUp.
    1.2) In relocate, some branch requires "growing" and insert some spaces "before" TABLESWITCH. In result, TABLESWITCH OP and padded offsets are shifted, which "may" break padding.
  2. In the second loop of fixUpAndRelocate
    2.1) The padding for TABLESWITCH is applied AGAIN in fixUp, which adds more spaces if padding was broken in 1.2)
  3. fixUpAndRelocate is finished and flowAnalysis runs
  4. flowAnalysis reads the part of default for TABLESWITCH which is 0 due to "double padding", hence the offset has been same as TABLESWITCH OP, and error is thrown.

Janino 3.0.8

error-codegen.log
disassembled-gencode.log

@HeartSaVioR
Copy link
Contributor Author

HeartSaVioR commented Mar 5, 2020

Actually I've crafted a patch but I'm not expert of JVM (just dug up with JLS only on TABLESWITCH) so not sure I assumed correctly.

My assumptions are:

  1. growing code only requires one stage - once all Relocatables check for grow and ensure the space, it will not require another growing
    (Branch.relocate() seems to be the only thing requiring grow, and it requires growing only once, at least based on the code implementation.)
  2. after the stage for growing, fixUp is the only thing requiring grow - this can be also done in one stage
  3. after running fixUp, there's no need for growing, hence relocation would also be done in another one stage

If my assumptions are all correct, fixUpAndRelocate can just execute three phases instead of loop - 1) grow 2) fixUp 3) relocate - and then we can add grow in Relocatable interface to insert the space "if needed". (Looks like Branch only needed this.)

If these all make sense I'll propose the PR. If there's something major I am missing here, I'd love to see your fix being landed to Janino and released.

Thanks in advance!

@HeartSaVioR
Copy link
Contributor Author

disassembled-gencode-janino-3-1-1-snapshot.log

Also attached the disassembled gencode while running the code with Janino 3.1.1-SNAPSHOT. It doesn't throw exception (as flowAnalysis has been removed), but there's no code in "expand_doConsume" as well as no "tableswitch" is presented in the log.

It would be nice to avoid crashing in runtime - is there any chance to bring flowAnalysis back, or put alternative verification?

@aunkrig
Copy link
Member

aunkrig commented Mar 8, 2020

Your disagnosis is exactly right, and I just merged your PR #114 that fixes the problem.

Lucky me that my recent massive refactoring was complete before you started developing the fix ;-) ...

@aunkrig aunkrig closed this as completed Mar 8, 2020
@HeartSaVioR
Copy link
Contributor Author

HeartSaVioR commented Mar 8, 2020

Great! Do you have any remaining works before releasing? Since we've affected by this, I'd like to see the new release sooner. (Honestly Spark community is depending on 3.0.x and new 3.0.x release would be easier to consume, but looks like Janino does linear release with single version line so OK.)

Btw, I like the way Janino does some verification and throws compilation error, like flowAnalysis for this case. Could we please reconsider restoring verification logic on the new code?

@aunkrig
Copy link
Member

aunkrig commented Mar 9, 2020

A release would not be a problem at all... maybe I can do it today!

@aunkrig aunkrig reopened this Mar 9, 2020
@aunkrig
Copy link
Member

aunkrig commented Mar 9, 2020

Regarding "flowAnalysis()": Its sole purpose was to calculate the max_stack field of a method's code attribute. That field is totally redundant because the JVM that loads the class must calculate the maximum operand stack size anyway (if only to compare it with the value of the max_stack field). The same holds true for the cursed StackMapTable attribute, which is mandatory for Java 7+ .class files and cost me hours and hours to implement.

The new StackMapTable logic supersedes flowAnalysis(), which was always sort of foreign matter, because it runs after code generation and has thus only very little context information. My observation is also that the VerifyError messages produced by recent JVMs are much more helpful than those of flowAnalysis().

Which reasons do you see why flowAnalysis() should come back?

@HeartSaVioR
Copy link
Contributor Author

HeartSaVioR commented Mar 9, 2020

Please refer my previous comment:
#113 (comment)

I've even observed the case where the operation(s) is(are) silently removed due to bad case, Janino bug. (In above case, the content of static method expand_doConsume looks to be "empty".) It was throwing exception on flowAnalysis as there's some minimal assertion (and hopefully this case it hits the assertion) and user query will simply fail to run for Spark case, but now there's a possible chance the compiled code runs as normal but no longer be the same as input source code, leading wrong result and negative impact on business.

I'm not sure where it "drops" the operations (and #114 would have fixed it so we should find the place without applying #114) but I'd like to see Janino throw error instead of producing unintended output. "Fail to compile" is the thing we can be noticed early and try to investigate. "Run and produce wrong result" is hard to find out and once we find out it have been already impacting the business badly.

@HeartSaVioR
Copy link
Contributor Author

The compiler is the one we heavily rely on while we use static type languages to avoid as many possible errors as possible in runtime. This was from Janino bug so may not easy to assert from itself, but whenever possible or in doubt it would be nice to throw out error instead of taking risk of going forward. I'll recheck whether my comment is a red-herring; if it's not a red-herring then I'd like to see how we can assert it and prevent dropping out operations.

@aunkrig
Copy link
Member

aunkrig commented Mar 9, 2020

Version 3.1.1 is out the door!

@aunkrig
Copy link
Member

aunkrig commented Mar 9, 2020

Producing loadable but incorrect code is certainly a no-no. Can you provide a unit test that reproduces the problem with JANINO 3.1.1? And in a new issue, please...

@HeartSaVioR
Copy link
Contributor Author

HeartSaVioR commented Mar 9, 2020

Version 3.1.1 is out the door!

Great! Thanks for the quick release! I guess it would be seen in couple of days afterwards in Nexus; once search.maven.org reflects it I'll test it again with Spark.

Producing loadable but incorrect code is certainly a no-no. Can you provide a unit test that reproduces the problem with JANINO 3.1.1? And in a new issue, please...

Sure! I didn't intend to extend this issue. I'll close this and file a new issue.

I'm not sure I can find a new reproducer though - for now I still need to trigger a bug #113 to reproduce the case, which means it cannot be provided with unit test. (And then not against Janino 3.1.1... I don't think it becomes to be invalid - it may be the way we prevent another possible bugs.)

aunkrig added a commit that referenced this issue Mar 16, 2020
…(or one time release for 3.0.16)

Backported PR #114 (the fix for issue #113) into the "3.0.x" branch.
dongjoon-hyun pushed a commit to apache/spark that referenced this issue Mar 22, 2020
### What changes were proposed in this pull request?

This PR(SPARK-31101) proposes to upgrade Janino to 3.0.16 which is released recently.

* Merged pull request janino-compiler/janino#114 "Grow the code for relocatables, and do fixup, and relocate".

Please see the commit log.
- https://github.com/janino-compiler/janino/commits/3.0.16

You can see the changelog from the link: http://janino-compiler.github.io/janino/changelog.html / though release note for Janino 3.0.16 is actually incorrect.

### Why are the changes needed?

We got some report on failure on user's query which Janino throws error on compiling generated code. The issue is here: janino-compiler/janino#113 It contains the information of generated code, symptom (error), and analysis of the bug, so please refer the link for more details.
Janino 3.0.16 contains the PR janino-compiler/janino#114 which would enable Janino to succeed to compile user's query properly.

### Does this PR introduce any user-facing change?

No.

### How was this patch tested?

Existing UTs.

Closes #27932 from HeartSaVioR/SPARK-31101-janino-3.0.16.

Authored-by: Jungtaek Lim (HeartSaVioR) <kabhwan.opensource@gmail.com>
Signed-off-by: Dongjoon Hyun <dongjoon@apache.org>
HeartSaVioR added a commit to HeartSaVioR/spark that referenced this issue Mar 24, 2020
### What changes were proposed in this pull request?

This PR(SPARK-31101) proposes to upgrade Janino to 3.0.16 which is released recently.

* Merged pull request janino-compiler/janino#114 "Grow the code for relocatables, and do fixup, and relocate".

Please see the commit log.
- https://github.com/janino-compiler/janino/commits/3.0.16

You can see the changelog from the link: http://janino-compiler.github.io/janino/changelog.html / though release note for Janino 3.0.16 is actually incorrect.

### Why are the changes needed?

We got some report on failure on user's query which Janino throws error on compiling generated code. The issue is here: janino-compiler/janino#113 It contains the information of generated code, symptom (error), and analysis of the bug, so please refer the link for more details.
Janino 3.0.16 contains the PR janino-compiler/janino#114 which would enable Janino to succeed to compile user's query properly.

### Does this PR introduce any user-facing change?

No.

### How was this patch tested?

Existing UTs.

Closes apache#27932 from HeartSaVioR/SPARK-31101-janino-3.0.16.

Authored-by: Jungtaek Lim (HeartSaVioR) <kabhwan.opensource@gmail.com>
Signed-off-by: Dongjoon Hyun <dongjoon@apache.org>
HeartSaVioR added a commit to HeartSaVioR/spark that referenced this issue Mar 24, 2020
This PR(SPARK-31101) proposes to upgrade Janino to 3.0.16 which is released recently.

* Merged pull request janino-compiler/janino#114 "Grow the code for relocatables, and do fixup, and relocate".

Please see the commit log.
- https://github.com/janino-compiler/janino/commits/3.0.16

You can see the changelog from the link: http://janino-compiler.github.io/janino/changelog.html / though release note for Janino 3.0.16 is actually incorrect.

We got some report on failure on user's query which Janino throws error on compiling generated code. The issue is here: janino-compiler/janino#113 It contains the information of generated code, symptom (error), and analysis of the bug, so please refer the link for more details.
Janino 3.0.16 contains the PR janino-compiler/janino#114 which would enable Janino to succeed to compile user's query properly.

No.

Existing UTs.

Closes apache#27932 from HeartSaVioR/SPARK-31101-janino-3.0.16.

Authored-by: Jungtaek Lim (HeartSaVioR) <kabhwan.opensource@gmail.com>
Signed-off-by: Dongjoon Hyun <dongjoon@apache.org>
dongjoon-hyun pushed a commit to apache/spark that referenced this issue Mar 25, 2020
### What changes were proposed in this pull request?

This PR(SPARK-31101) proposes to upgrade Janino to 3.0.16 which is released recently.

* Merged pull request janino-compiler/janino#114 "Grow the code for relocatables, and do fixup, and relocate".

Please see the commit log.
- https://github.com/janino-compiler/janino/commits/3.0.16

You can see the changelog from the link: http://janino-compiler.github.io/janino/changelog.html / though release note for Janino 3.0.16 is actually incorrect.

### Why are the changes needed?

We got some report on failure on user's query which Janino throws error on compiling generated code. The issue is here: janino-compiler/janino#113 It contains the information of generated code, symptom (error), and analysis of the bug, so please refer the link for more details.
Janino 3.0.16 contains the PR janino-compiler/janino#114 which would enable Janino to succeed to compile user's query properly.

### Does this PR introduce any user-facing change?

No.

### How was this patch tested?

Existing UTs.

Below test code fails on branch-3.0 and passes with this patch.

```
  /**
   * NOTE: The test code tries to control the size of for/switch statement in expand_doConsume,
   * as well as the overall size of expand_doConsume, so that the query triggers known Janino
   * bug - janino-compiler/janino#113.
   *
   * The expected exception message from Janino when we use switch statement for "ExpandExec":
   * - "Operand stack inconsistent at offset xxx: Previous size 1, now 0"
   * which will not happen when we use if-else-if statement for "ExpandExec".
   *
   * "The number of fields" and "The number of distinct aggregation functions" are the major
   * factors to increase the size of generated code: while these values should be large enough
   * to trigger the Janino bug, these values should not also too big; otherwise one of below
   * exceptions might be thrown:
   * - "expand_doConsume would be beyond 64KB"
   * - "java.lang.ClassFormatError: Too many arguments in method signature in class file"
   */
  test("SPARK-31115 Lots of columns and distinct aggregations shouldn't break code generation") {
    withSQLConf(
      (SQLConf.WHOLESTAGE_CODEGEN_ENABLED.key, "true"),
      (SQLConf.WHOLESTAGE_MAX_NUM_FIELDS.key, "10000"),
      (SQLConf.CODEGEN_FALLBACK.key, "false"),
      (SQLConf.CODEGEN_LOGGING_MAX_LINES.key, "-1")
    ) {
      var df = Seq(("1", "2", 1), ("1", "2", 2), ("2", "3", 3), ("2", "3", 4)).toDF("a", "b", "c")

      // The value is tested under commit "e807118eef9e0214170ff62c828524d237bd58e3":
      // the query fails with switch statement, whereas it passes with if-else statement.
      // Note that the value depends on the Spark logic as well - different Spark versions may
      // require different value to ensure the test failing with switch statement.
      val numNewFields = 100

      df = df.withColumns(
        (1 to numNewFields).map { idx => s"a$idx" },
        (1 to numNewFields).map { idx =>
          when(col("c").mod(lit(2)).===(lit(0)), lit(idx)).otherwise(col("c"))
        }
      )

      val aggExprs: Array[Column] = Range(1, numNewFields).map { idx =>
        if (idx % 2 == 0) {
          coalesce(countDistinct(s"a$idx"), lit(0))
        } else {
          coalesce(count(s"a$idx"), lit(0))
        }
      }.toArray

      val aggDf = df
        .groupBy("a", "b")
        .agg(aggExprs.head, aggExprs.tail: _*)

      // We are only interested in whether the code compilation fails or not, so skipping
      // verification on outputs.
      aggDf.collect()
    }
  }
```

Closes #27996 from HeartSaVioR/SPARK-31101-branch-3.0.

Authored-by: Jungtaek Lim (HeartSaVioR) <kabhwan.opensource@gmail.com>
Signed-off-by: Dongjoon Hyun <dongjoon@apache.org>
dongjoon-hyun pushed a commit to apache/spark that referenced this issue Mar 30, 2020
### What changes were proposed in this pull request?

This PR(SPARK-31101) proposes to upgrade Janino to 3.0.16 which is released recently.

* Merged pull request janino-compiler/janino#114 "Grow the code for relocatables, and do fixup, and relocate".

Please see the commit log.
- https://github.com/janino-compiler/janino/commits/3.0.16

You can see the changelog from the link: http://janino-compiler.github.io/janino/changelog.html / though release note for Janino 3.0.16 is actually incorrect.

### Why are the changes needed?

We got some report on failure on user's query which Janino throws error on compiling generated code. The issue is here: janino-compiler/janino#113 It contains the information of generated code, symptom (error), and analysis of the bug, so please refer the link for more details.
Janino 3.0.16 contains the PR janino-compiler/janino#114 which would enable Janino to succeed to compile user's query properly.

### Does this PR introduce any user-facing change?

No.

### How was this patch tested?

Existing UTs.

Below test code fails on branch-2.4 and passes with this patch.

(Note that there seems to be the case where another UT affects this UT to not fail - adding this to SQLQuerySuite won't fail this UT, but adding this to DateFunctionsSuite will fail this UT, and if you run this UT solely in SQLQuerySuite via `build/sbt "sql/testOnly *.SQLQuerySuite -- -z SPARK-31115"` then it fails.)

```
  /**
   * NOTE: The test code tries to control the size of for/switch statement in expand_doConsume,
   * as well as the overall size of expand_doConsume, so that the query triggers known Janino
   * bug - janino-compiler/janino#113.
   *
   * The expected exception message from Janino when we use switch statement for "ExpandExec":
   * - "Operand stack inconsistent at offset xxx: Previous size 1, now 0"
   * which will not happen when we use if-else-if statement for "ExpandExec".
   *
   * "The number of fields" and "The number of distinct aggregation functions" are the major
   * factors to increase the size of generated code: while these values should be large enough
   * to trigger the Janino bug, these values should not also too big; otherwise one of below
   * exceptions might be thrown:
   * - "expand_doConsume would be beyond 64KB"
   * - "java.lang.ClassFormatError: Too many arguments in method signature in class file"
   */
  test("SPARK-31115 Lots of columns and distinct aggregations shouldn't break code generation") {
    withSQLConf(
      (SQLConf.WHOLESTAGE_CODEGEN_ENABLED.key, "true"),
      (SQLConf.WHOLESTAGE_MAX_NUM_FIELDS.key, "10000"),
      (SQLConf.CODEGEN_FALLBACK.key, "false"),
      (SQLConf.CODEGEN_LOGGING_MAX_LINES.key, "-1")
    ) {
      var df = Seq(("1", "2", 1), ("1", "2", 2), ("2", "3", 3), ("2", "3", 4)).toDF("a", "b", "c")

      // The value is tested under commit "244405fe57d7737d81c34ba9e8917df6285889eb":
      // the query fails with switch statement, whereas it passes with if-else statement.
      // Note that the value depends on the Spark logic as well - different Spark versions may
      // require different value to ensure the test failing with switch statement.
      val numNewFields = 100

      df = df.withColumns(
        (1 to numNewFields).map { idx => s"a$idx" },
        (1 to numNewFields).map { idx =>
          when(col("c").mod(lit(2)).===(lit(0)), lit(idx)).otherwise(col("c"))
        }
      )

      val aggExprs: Array[Column] = Range(1, numNewFields).map { idx =>
        if (idx % 2 == 0) {
          coalesce(countDistinct(s"a$idx"), lit(0))
        } else {
          coalesce(count(s"a$idx"), lit(0))
        }
      }.toArray

      val aggDf = df
        .groupBy("a", "b")
        .agg(aggExprs.head, aggExprs.tail: _*)

      // We are only interested in whether the code compilation fails or not, so skipping
      // verification on outputs.
      aggDf.collect()
    }
  }
```

Closes #27997 from HeartSaVioR/SPARK-31101-branch-2.4.

Authored-by: Jungtaek Lim (HeartSaVioR) <kabhwan.opensource@gmail.com>
Signed-off-by: Dongjoon Hyun <dongjoon@apache.org>
sjincho pushed a commit to sjincho/spark that referenced this issue Apr 15, 2020
### What changes were proposed in this pull request?

This PR(SPARK-31101) proposes to upgrade Janino to 3.0.16 which is released recently.

* Merged pull request janino-compiler/janino#114 "Grow the code for relocatables, and do fixup, and relocate".

Please see the commit log.
- https://github.com/janino-compiler/janino/commits/3.0.16

You can see the changelog from the link: http://janino-compiler.github.io/janino/changelog.html / though release note for Janino 3.0.16 is actually incorrect.

### Why are the changes needed?

We got some report on failure on user's query which Janino throws error on compiling generated code. The issue is here: janino-compiler/janino#113 It contains the information of generated code, symptom (error), and analysis of the bug, so please refer the link for more details.
Janino 3.0.16 contains the PR janino-compiler/janino#114 which would enable Janino to succeed to compile user's query properly.

### Does this PR introduce any user-facing change?

No.

### How was this patch tested?

Existing UTs.

Closes apache#27932 from HeartSaVioR/SPARK-31101-janino-3.0.16.

Authored-by: Jungtaek Lim (HeartSaVioR) <kabhwan.opensource@gmail.com>
Signed-off-by: Dongjoon Hyun <dongjoon@apache.org>
dongjoon-hyun pushed a commit to apache/spark that referenced this issue May 29, 2020
### What changes were proposed in this pull request?

This PR proposes to upgrade Janino to 3.1.2 which is released recently.

Major changes were done for refactoring, as well as there're lots of "no commit message". Belows are the pairs of (commit title, commit) which seem to deal with some bugs or specific improvements (not purposed to refactor) after 3.0.15.

* Issue #119: Guarantee executing popOperand() in popUninitializedVariableOperand() via moving popOperand() out of "assert"
* Issue #116: replace operand to final target type if boxing conversion and widening reference conversion happen together
* Merged pull request `#114` "Grow the code for relocatables, and do fixup, and relocate".
  * janino-compiler/janino@367c58e
* issue `#107`: Janino requires "org.codehaus.commons.compiler.io", but commons-compiler does not export this package
  * janino-compiler/janino@f7d9959
* Throw an NYI CompileException when a static interface method is invoked.
  * janino-compiler/janino@efd3884
* Fixed the promotion of the array access index expression (see JLS7 15.13 Array Access Expressions)
  * janino-compiler/janino@32fdb5f
* Issue `#104`: ClassLoaderIClassLoader 's ClassNotFoundException handle mechanism enhancement
  * janino-compiler/janino@6e8a97d

You can see the changelog from the link: http://janino-compiler.github.io/janino/changelog.html

### Why are the changes needed?

We got some report on failure on user's query which Janino throws error on compiling generated code. The issue is here: janino-compiler/janino#113 It contains the information of generated code, symptom (error), and analysis of the bug, so please refer the link for more details.
Janino 3.1.1 contains the PR janino-compiler/janino#114 which would enable Janino to succeed to compile user's query properly. I've also fixed a couple of more bugs as 3.1.1 made Spark UTs fail - hence we need to upgrade to 3.1.2.

Furthermore, from my testing, janino-compiler/janino#90 (which Josh Rosen filed before) seems to be also resolved in 3.1.2 as well.

Looks like Janino is maintained by one person and there's no even version branches and releases/tags so we can't expect Janino maintainer to release a new bugfix version - hence have to try out new minor version.

### Does this PR introduce any user-facing change?

No.

### How was this patch tested?

Existing UTs.

Closes #27860 from HeartSaVioR/SPARK-31101.

Authored-by: Jungtaek Lim (HeartSaVioR) <kabhwan.opensource@gmail.com>
Signed-off-by: Dongjoon Hyun <dongjoon@apache.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants