Hi zihan, after the CI passed, I'll merge it.
On Tue, Sep 8, 2026 at 7:51 PM Zh D <[email protected]> wrote: > 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 >
