taka-2628 opened a new issue, #177:
URL: https://github.com/apache/iotdb-client-go/issues/177

   ### Summary
   
   When a `Session` loses its transport (e.g. the server it is connected to 
restarts) and the client transparently reconnects, the reconnected session is 
opened **without** the `sql_dialect`, `db`, and `version` values the original 
`Open()` negotiated. The session silently reverts to server defaults. For 
table-model sessions this is severe: every subsequent statement fails to parse, 
because the session is now speaking the tree dialect while the caller keeps 
sending table-dialect SQL. It also affects any session that relied on a bound 
database (`db`).
   
   ### Affected versions
   
   Present on current `main`, and on released `v2.0.3-1` and `v2.0.8`. The code 
path is unchanged across all three.
   
   ### Root cause
   
   The session-open request is hand-built in three places, and only two 
populate `TSOpenSessionReq.Configuration`:
   
   - `Session.Open()` — sets `Configuration["sql_dialect"]`, `["version"]`, and 
(when non-empty) `["db"]` (`client/session.go`, the block after the 
`TSOpenSessionReq` literal in `Open`).
   - `Session.OpenCluster()` — sets the same three.
   - `Session.initClusterConn()` — builds `TSOpenSessionReq` with **no 
`Configuration` map at all**.
   
   `reconnect()` is written purely in terms of `initClusterConn()`, and it is 
the sole transparent-reconnect path — invoked from every insert/query/execute 
method on a transport-level error (`err != nil && resp == nil`), ~29 call 
sites. So *any* session, single-host or cluster, that survives a server restart 
and then issues a statement reconnects through `initClusterConn()` and loses 
its dialect/db/version. The values needed to rebuild `Configuration` are 
already on the session (`s.config`) at reconnect time — they are simply not 
used.
   
   ### The reference (Java) client does this correctly
   
   In `apache/iotdb`, `SessionConnection.reconnect()` routes through `init()`, 
which re-sends the configuration on every (re)open — 
`putToConfiguration("version", ...)`, `("sql_dialect", ...)`, `("db", ...)`. 
The Go client's omission looks like an oversight (one of three copies of the 
same block was missed), not an intentional difference.
   
   ### Why it's hard to diagnose
   
   - The failure surfaces as a **valid server response** (`TSStatus` code 700 
`SqlParseError`, or 701 `SemanticError` "database is not specified"), converted 
into an `*ExecutionError` — not a Go transport error.
   - `TableSessionPool` therefore keeps the poisoned session: 
`isConnectionError` returns `false` for `*ExecutionError`/`*BatchError`, so the 
session is never dropped and `Close()` returns it to the pool. Every subsequent 
caller that draws it fails the same way until the process is restarted.
   - It only manifests when a server actually restarts mid-session — invisible 
to unit tests and to any deployment that doesn't bounce a server under load.
   
   ### Reproduction (verified against a live server)
   
   Server: `apache/iotdb:2.0.3-standalone`. Client: `iotdb-client-go/v2 
v2.0.8`, `TableSessionPool` (size 1), session bound to a database.
   
   1. Open a table-model session bound to a database; create a table; `INSERT` 
a row (succeeds).
   2. Return the session to the pool.
   3. Restart the server (`docker restart`) so the socket drops but the 
endpoint returns.
   4. `GetSession()` (reuses the pooled session, which reconnects) and `INSERT` 
again.
   
   **Expected:** the client reconnects transparently and the insert succeeds.
   **Actual (stock v2.0.8):**
   ```
   error code: 700, message: Error occurred while parsing SQL to physical plan: 
line 1:12 mismatched input 't' expecting ROOT
   ```
   The reconnected session reverted to the tree dialect, so the tree parser 
expects a `root.`-prefixed path and rejects the table name. Every subsequent 
statement on that session keeps failing. (A session relying on a bound `db` 
with the dialect intact would instead see code 701, "database is not 
specified".)
   
   ### Suggested fix
   
   Populate `TSOpenSessionReq.Configuration` on the reconnect path the same way 
`Open()`/`OpenCluster()` do, from `s.config`. Because the same block is now 
hand-duplicated across all three open paths — and this bug exists precisely 
because one copy was missed — a clean fix extracts a single helper and wires 
all three sites through it. I verified locally that adding the `Configuration` 
map to `initClusterConn` makes the reproduction above succeed after the 
restart, with no other change. A PR follows.
   
   A smaller, related gap for maintainers' awareness: `initClusterConn` also 
never sets `s.timeFactor` via `getTimeFactor(resp)`, which `Open`/`OpenCluster` 
do — a reconnected session keeps a stale `timeFactor`. Benign on homogeneous 
clusters; happy to include it if wanted.
   
   ### Environment
   
   - iotdb-client-go: `main` (also reproduced on `v2.0.8`, `v2.0.3-1`)
   - IoTDB server: `2.0.3-standalone`
   - Go: 1.25
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to