Uploaded image for project: 'Calcite'
  1. Calcite
  2. CALCITE-4401

SqlJoin.toString() throws RuntimeException, "No list started"

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Minor
    • Resolution: Fixed
    • 1.25.0, 1.26.0
    • 1.31.0
    • core

    Description

      Hi,

      In our project we use Kotlin along with Strikt assertion library 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: 

          @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>()
              }
          }
      

      This can be inherently reduced to this example:

      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}")
      }
      

      Which results in:

      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)
        ...

       

      Attachments

        Issue Links

          Activity

            People

              abhishek.dasgupta Abhishek Dasgupta
              dominik.labuda Dominik Labuda
              Votes:
              0 Vote for this issue
              Watchers:
              6 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Time Tracking

                  Estimated:
                  Original Estimate - Not Specified
                  Not Specified
                  Remaining:
                  Remaining Estimate - 0h
                  0h
                  Logged:
                  Time Spent - 1h 40m
                  1h 40m