You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@calcite.apache.org by "Dominik Labuda (Jira)" <ji...@apache.org> on 2020/11/13 14:43:00 UTC

[jira] [Updated] (CALCITE-4401) SqlJoin toString throws RuntimeException

     [ https://issues.apache.org/jira/browse/CALCITE-4401?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Dominik Labuda updated CALCITE-4401:
------------------------------------
    Description: 
Hi,

In our project we use Kotlin along with [Strikt assertion library|https://strikt.io/] in tests. The thing is that Strikt calls `.toString()` method on failing asserted objects to provide users with a nicely formatted output.

Lets say the test looks like this: 
{code:java}
    @Test
    fun `test correct type of JOIN in the root of generated SQL without neighboring JOINs`() {
        // Generates SqlSelect that fails one of the conditions below
        val rootSelect: SqlSelect = generateRootSql()
        
        expectThat(rootSelect.from) {
            // Passes - from is a SqlJoin
            val join = isA<SqlJoin>()

            // Passes - joinType is FULL
            join.get { joinType }.isEqualTo(JoinType.FULL)

            // Fails - left is a SqlJoin, calls .toString() on rootSelect.from to provide output info
            join.get { left }.isNotA<SqlJoin>()
            join.get { right }.isNotA<SqlJoin>()
        }
    }
{code}
This can be inherently reduced to this example:
{code:java}
fun main() {
    val frameworkConfig = initSchema()
    val relBuilder: RelBuilder = RelBuilder.create(frameworkConfig)

    val rootRelationalNode = relBuilder
        .scan("tpch", "out_tpch_vw__customer")
        .project(
            relBuilder.field("c_custkey"),
            relBuilder.field("region_name")
        )
        .scan("tpch", "out_tpch_vw__orders")
        .project(
            relBuilder.field("o_custkey"),
            relBuilder.field("o_totalprice")
        )
        .join(
            JoinRelType.INNER,
            relBuilder.call(
                SqlStdOperatorTable.EQUALS,
                relBuilder.field(2, 0, "c_custkey"),
                relBuilder.field(2, 1, "o_custkey")
            )
        )
        .build()

    val sqlNode = RelToSqlConverter(PostgresqlSqlDialect.DEFAULT)
        .visitRoot(rootRelationalNode)
        .asStatement()

    println("SQL:")
    println(sqlNode)
    println()

    println("sqlNode root is SqlSelect: ${sqlNode is SqlSelect}")
    // Treat sqlNode as SqlSelect
    sqlNode as SqlSelect

    println("sqlNode.from field is a SqlJoin: ${sqlNode.from is SqlJoin}")
    println("Printing out the SqlJoin: ${sqlNode.from}")
}
{code}
Which results in:
{code:java}
SQL:
SELECT *
FROM (SELECT `c_custkey`, `region_name`
FROM `tpch`.`out_tpch_vw__customer`) AS `t`
INNER JOIN (SELECT `o_custkey`, `o_totalprice`
FROM `tpch`.`out_tpch_vw__orders`) AS `t0` ON `t`.`c_custkey` = `t0`.`o_custkey`

sqlNode root is SqlSelect: true
sqlNode.from field is a SqlJoin: true

Exception in thread "main" java.lang.RuntimeException: No list started
  at org.apache.calcite.sql.pretty.SqlPrettyWriter.sep(SqlPrettyWriter.java:1079)
  at org.apache.calcite.sql.pretty.SqlPrettyWriter.sep(SqlPrettyWriter.java:1074)
  at org.apache.calcite.sql.SqlJoin$SqlJoinOperator.unparse(SqlJoin.java:214)
  at org.apache.calcite.sql.SqlDialect.unparseCall(SqlDialect.java:453)
  at org.apache.calcite.sql.SqlCall.unparse(SqlCall.java:104)
  at org.apache.calcite.sql.SqlNode.toSqlString(SqlNode.java:154)
  at org.apache.calcite.sql.SqlNode.toString(SqlNode.java:129)
  at java.base/java.lang.String.valueOf(String.java:2951)
  at java.base/java.lang.StringBuilder.append(StringBuilder.java:168)
  ...{code}
 

  was:
Hi,

In our project we use Kotlin along with [Strikt assertion library|https://strikt.io/] in tests. The thing is that Strikt calls `.toString()` method on failing asserted objects to provide users with a nicely formatted output.

Lets say the test looks like this:

 
{code:java}
    @Test
    fun `test correct type of JOIN in the root of generated SQL without neighboring JOINs`() {
        // Generates SqlSelect that fails one of the conditions below
        val rootSelect: SqlSelect = generateRootSql()
        
        expectThat(rootSelect.from) {
            // Passes - from is a SqlJoin
            val join = isA<SqlJoin>()

            // Passes - joinType is FULL
            join.get { joinType }.isEqualTo(JoinType.FULL)

            // Fails - left is a SqlJoin, calls .toString() on rootSelect.from to provide output info
            join.get { left }.isNotA<SqlJoin>()
            join.get { right }.isNotA<SqlJoin>()
        }
    }
{code}
This can be inherently reduced to this example:
{code:java}
fun main() {
    val frameworkConfig = initSchema()
    val relBuilder: RelBuilder = RelBuilder.create(frameworkConfig)

    val rootRelationalNode = relBuilder
        .scan("tpch", "out_tpch_vw__customer")
        .project(
            relBuilder.field("c_custkey"),
            relBuilder.field("region_name")
        )
        .scan("tpch", "out_tpch_vw__orders")
        .project(
            relBuilder.field("o_custkey"),
            relBuilder.field("o_totalprice")
        )
        .join(
            JoinRelType.INNER,
            relBuilder.call(
                SqlStdOperatorTable.EQUALS,
                relBuilder.field(2, 0, "c_custkey"),
                relBuilder.field(2, 1, "o_custkey")
            )
        )
        .build()

    val sqlNode = RelToSqlConverter(PostgresqlSqlDialect.DEFAULT)
        .visitRoot(rootRelationalNode)
        .asStatement()

    println("SQL:")
    println(sqlNode)
    println()

    println("sqlNode root is SqlSelect: ${sqlNode is SqlSelect}")
    // Treat sqlNode as SqlSelect
    sqlNode as SqlSelect

    println("sqlNode.from field is a SqlJoin: ${sqlNode.from is SqlJoin}")
    println("Printing out the SqlJoin: ${sqlNode.from}")
}
{code}
Which results in:
{code:java}
SQL:
SELECT *
FROM (SELECT `c_custkey`, `region_name`
FROM `tpch`.`out_tpch_vw__customer`) AS `t`
INNER JOIN (SELECT `o_custkey`, `o_totalprice`
FROM `tpch`.`out_tpch_vw__orders`) AS `t0` ON `t`.`c_custkey` = `t0`.`o_custkey`

sqlNode root is SqlSelect: true
sqlNode.from field is a SqlJoin: true

Exception in thread "main" java.lang.RuntimeException: No list started
  at org.apache.calcite.sql.pretty.SqlPrettyWriter.sep(SqlPrettyWriter.java:1079)
  at org.apache.calcite.sql.pretty.SqlPrettyWriter.sep(SqlPrettyWriter.java:1074)
  at org.apache.calcite.sql.SqlJoin$SqlJoinOperator.unparse(SqlJoin.java:214)
  at org.apache.calcite.sql.SqlDialect.unparseCall(SqlDialect.java:453)
  at org.apache.calcite.sql.SqlCall.unparse(SqlCall.java:104)
  at org.apache.calcite.sql.SqlNode.toSqlString(SqlNode.java:154)
  at org.apache.calcite.sql.SqlNode.toString(SqlNode.java:129)
  at java.base/java.lang.String.valueOf(String.java:2951)
  at java.base/java.lang.StringBuilder.append(StringBuilder.java:168)
  ...{code}
 


> SqlJoin toString throws RuntimeException
> ----------------------------------------
>
>                 Key: CALCITE-4401
>                 URL: https://issues.apache.org/jira/browse/CALCITE-4401
>             Project: Calcite
>          Issue Type: Bug
>          Components: core
>    Affects Versions: 1.25.0, 1.26.0
>            Reporter: Dominik Labuda
>            Priority: Minor
>
> Hi,
> In our project we use Kotlin along with [Strikt assertion library|https://strikt.io/] in tests. The thing is that Strikt calls `.toString()` method on failing asserted objects to provide users with a nicely formatted output.
> Lets say the test looks like this: 
> {code:java}
>     @Test
>     fun `test correct type of JOIN in the root of generated SQL without neighboring JOINs`() {
>         // Generates SqlSelect that fails one of the conditions below
>         val rootSelect: SqlSelect = generateRootSql()
>         
>         expectThat(rootSelect.from) {
>             // Passes - from is a SqlJoin
>             val join = isA<SqlJoin>()
>             // Passes - joinType is FULL
>             join.get { joinType }.isEqualTo(JoinType.FULL)
>             // Fails - left is a SqlJoin, calls .toString() on rootSelect.from to provide output info
>             join.get { left }.isNotA<SqlJoin>()
>             join.get { right }.isNotA<SqlJoin>()
>         }
>     }
> {code}
> This can be inherently reduced to this example:
> {code:java}
> fun main() {
>     val frameworkConfig = initSchema()
>     val relBuilder: RelBuilder = RelBuilder.create(frameworkConfig)
>     val rootRelationalNode = relBuilder
>         .scan("tpch", "out_tpch_vw__customer")
>         .project(
>             relBuilder.field("c_custkey"),
>             relBuilder.field("region_name")
>         )
>         .scan("tpch", "out_tpch_vw__orders")
>         .project(
>             relBuilder.field("o_custkey"),
>             relBuilder.field("o_totalprice")
>         )
>         .join(
>             JoinRelType.INNER,
>             relBuilder.call(
>                 SqlStdOperatorTable.EQUALS,
>                 relBuilder.field(2, 0, "c_custkey"),
>                 relBuilder.field(2, 1, "o_custkey")
>             )
>         )
>         .build()
>     val sqlNode = RelToSqlConverter(PostgresqlSqlDialect.DEFAULT)
>         .visitRoot(rootRelationalNode)
>         .asStatement()
>     println("SQL:")
>     println(sqlNode)
>     println()
>     println("sqlNode root is SqlSelect: ${sqlNode is SqlSelect}")
>     // Treat sqlNode as SqlSelect
>     sqlNode as SqlSelect
>     println("sqlNode.from field is a SqlJoin: ${sqlNode.from is SqlJoin}")
>     println("Printing out the SqlJoin: ${sqlNode.from}")
> }
> {code}
> Which results in:
> {code:java}
> SQL:
> SELECT *
> FROM (SELECT `c_custkey`, `region_name`
> FROM `tpch`.`out_tpch_vw__customer`) AS `t`
> INNER JOIN (SELECT `o_custkey`, `o_totalprice`
> FROM `tpch`.`out_tpch_vw__orders`) AS `t0` ON `t`.`c_custkey` = `t0`.`o_custkey`
> sqlNode root is SqlSelect: true
> sqlNode.from field is a SqlJoin: true
> Exception in thread "main" java.lang.RuntimeException: No list started
>   at org.apache.calcite.sql.pretty.SqlPrettyWriter.sep(SqlPrettyWriter.java:1079)
>   at org.apache.calcite.sql.pretty.SqlPrettyWriter.sep(SqlPrettyWriter.java:1074)
>   at org.apache.calcite.sql.SqlJoin$SqlJoinOperator.unparse(SqlJoin.java:214)
>   at org.apache.calcite.sql.SqlDialect.unparseCall(SqlDialect.java:453)
>   at org.apache.calcite.sql.SqlCall.unparse(SqlCall.java:104)
>   at org.apache.calcite.sql.SqlNode.toSqlString(SqlNode.java:154)
>   at org.apache.calcite.sql.SqlNode.toString(SqlNode.java:129)
>   at java.base/java.lang.String.valueOf(String.java:2951)
>   at java.base/java.lang.StringBuilder.append(StringBuilder.java:168)
>   ...{code}
>  



--
This message was sent by Atlassian Jira
(v8.3.4#803005)