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]