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
>

Reply via email to