#4261·keploy

[bug]: COM_STMT_FETCH / useCursorFetch=true not supported — cursor rows never recorded, replay drops the connection

Author: slayerjainCreated Jun 9, 2026Updated Sep 2, 2026
Labelsbug

Is there an existing issue for this?

  • Searched; this tracks a gap noted in #4260.

Current behavior

With MySQL Connector/J on a JDBC URL that has useCursorFetch=true and a statement with setFetchSize(n) > 0, the driver opens a server-side cursor on COM_STMT_EXECUTE (response = column-defs + EOF, no rows) and pages the rows with repeated COM_STMT_FETCH (0x1C) commands.

keploy does not support this:

  1. COM_STMT_FETCH is not decoded — pkg/models/mysql/const.go:177 has the constant commented out (and the old value 0x19 was wrong; 0x19 is COM_STMT_CLOSE, real FETCH is 0x1C), and the decode case at pkg/agent/proxy/integrations/mysql/wire/decode.go:397 is commented out. So FETCH falls to the default branch and is recorded as an unknown base64 packet with packet_type: "0x1c".
  2. The recorder never captures the FETCH response. Unknown 0x-prefixed packets are recorded as no-response mocks at pkg/agent/proxy/integrations/mysql/recorder/query.go:503-512 (responses: [], responseOperation: NO Response Packet), so the cursor's row chunks are lost at record time.
  3. On replay, the live COM_STMT_FETCH has no matcher case, so matchCommand returns ok=false and query.go drops the connection with "no matching mock found" (since FETCH is a response command, this is fatal). This also tears down a pooled HikariCP connection, cascading 500s onto unrelated requests that reuse it.

pkg/models/mysql/comm.go:145 already documents this: "COM_STMT_FETCH packet is not currently supported because its response involves multi-resultset."

Steps to Replicate

Against the tidb-stmt-cache sample (add useCursorFetch=true to the JDBC URL and an endpoint that setFetchSize(2) on a multi-row SELECT):

  1. keploy record the cursor endpoint → recorded mocks contain packet_type: "0x1c" with responses: [].
  2. keploy test with the DB down → connection drops on 0x1c: Connection closing due to no matching mock found … request_type: "0x1c".

Proposed scope

This is a feature, not a one-line fix. Needs:

  • define COM_STMT_FETCH byte = 0x1C (+ string map) and wire the existing preparedstmt.DecodeStmtFetch;
  • recorder: treat FETCH as a response command and capture each binary result-set chunk (rows + EOF with cursor-status flags);
  • replayer: a matchCommand case that resolves FETCH by stmtID→query and serves the recorded chunks in FIFO order;
  • handle the cursor EXECUTE response (col-defs + EOF, zero rows).

Environment

  • keploy: v3 (main); MySQL integration matcher path.
  • Driver: mysql-connector-j 8.x; server: TiDB :4000 (MySQL wire protocol).
  • Repro: native (eBPF) on Linux; would also repro in Docker.

Tracked alongside #4260.