Hi all, I found an issue in the Java client's handling of the tree-model time column. The fix is open as:
- Master: https://github.com/apache/iotdb/pull/17408 Bug description --------------- In the tree model, a result set's time pseudo-column is addressed by a negative TsBlock column index. getLong, getString and getObject handle that and return the timestamp. getBoolean, getInt, getFloat, getDouble and getBinary do not: they reach TsBlock.getColumn(-1) and throw java.lang.ArrayIndexOutOfBoundsException: Index -1 out of bounds for length 3 getDate is affected as well, since it delegates to getInt. Root cause ---------- - isNull(index, rowNum) is "index >= 0 && ...", so it returns false for the time column. Execution therefore enters the value branch rather than the null branch. - The five strictly-typed ByTsBlockColumnIndex getters have no tsBlockColumnIndex < 0 guard before that point, unlike getLong and getString, which handle the negative index explicitly. Why this matters beyond the exception type ------------------------------------------ java.sql.ResultSet.getInt and its siblings declare "throws SQLException", and IoTDBJDBCResultSet only catches StatementExecutionException. The ArrayIndexOutOfBoundsException is unchecked, so it crosses the JDBC boundary uncaught and a caller writing the documented "catch (SQLException)" cannot handle it. The Session API is affected the same way: SessionDataSet.DataIterator returns ioTDBRpcDataSet.getInt(columnIndex) directly, so the exception propagates unwrapped there too. The fix ------- - A tsBlockColumnIndex < 0 guard in the five strictly-typed getters, throwing StatementExecutionException, placed after checkRecord() and before isNull(...). - Messages routed through RpcMessages in both en and zh rather than string literals. - A regression test in IoTDBJDBCResultSetTest. Against master (219332dacb8) it fails with the exception above; it asserts that the time column surfaces as SQLException rather than merely that something was thrown. Relation to the C++ client -------------------------- The same defect in the C++ client was fixed in #17400, approved by @jt2594838 and merged on 2026-04-01. This change uses the same five getters, the same guard position, and the same five message texts, so a user meeting this through either client sees the same message. I would rather state one thing than let it be assumed: that review does not settle the Java side. @CritasWang wrote there that a fast-fail exception "aligns perfectly with our Java client which typically throws IndexOutOfBoundsException or ClassCastException for mismatched types on the Time column" -- that is, the current Java behaviour was cited as the model for the C++ change, and it was described accurately. So the argument above has to stand on the JDBC contract on its own. It is a new argument rather than a decision already taken, and an objection to it is welcome. Status ------ The PR was opened on 2026-03-31 and has had no review since. @HTHou suggested the list back in April for exactly this reason and I did not follow up, which was my mistake. At the time of writing the branch also has twelve workflow runs sitting at action_required and no CI has ever run on it, so an approval there would help. Thanks, Zihan Dai
