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

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

Dominik Labuda created CALCITE-4401:
---------------------------------------

             Summary: 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.26.0, 1.25.0
            Reporter: Dominik Labuda


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)