Skip to content

[SEA-NodeJS] Surface operation-status fields (displayMessage/diagnosticInfo/errorDetailsJson, numModifiedRows) on getOperationStatus#422

Closed
msrathore-db wants to merge 1 commit into
msrathore/sea-async-tls-options-mainfrom
msrathore/sea-statement-status
Closed

[SEA-NodeJS] Surface operation-status fields (displayMessage/diagnosticInfo/errorDetailsJson, numModifiedRows) on getOperationStatus#422
msrathore-db wants to merge 1 commit into
msrathore/sea-async-tls-options-mainfrom
msrathore/sea-statement-status

Conversation

@msrathore-db
Copy link
Copy Markdown
Contributor

What

Replaces the SEA backend's neutral, synthesized operation status with the real fields the napi kernel handle exposes on a terminal statement. Before this change, SeaOperationLifecycle.synthesizeFinishedStatus() returned a fixed { state: Succeeded, hasResultSet: true } with a comment that numModifiedRows / displayMessage / etc. were "deferred to M1", so getOperationStatus() on SEA reported nothing beyond the state. The napi Statement already exposes numModifiedRows() / displayMessage() / diagnosticInfo() / errorDetailsJson(); the JS side now reads and surfaces them.

Changes

  • lib/contracts/OperationStatus.ts — the backend-neutral OperationStatus carries the four rich fields (numModifiedRows, displayMessage, diagnosticInfo, errorDetailsJson).
  • lib/sea/SeaOperationBackend.ts — new readRichStatusFields() reads the accessors off the terminal sync Statement (the metadata path, and the sync runAsync:false path once result() has resolved). Null-safe: the async submit path never produces a terminal Statement (the AsyncStatement / AsyncResultHandle don't expose these accessors), and older bindings that predate the accessors both degrade to all-null rather than throwing. Wired into status() and the sync/cancellable completion tick. A failed individual accessor read is swallowed to null so a successful operation's status query never turns into a throw.
  • lib/sea/SeaOperationLifecycle.tsseaFinished() merges the rich fields into the synthesized completion tick via a lazy thunk, so finished({ callback }) consumers see the same surface as a subsequent getOperationStatus() call.
  • lib/thrift-backend/wireSynthesis.tssynthesizeThriftStatus() maps the rich fields into TGetOperationStatusResp (numModifiedRows re-boxed as a node-int64 Int64 to match the Thrift deserializer's wire shape; nullundefined so the synthesized response matches the Thrift path, where an absent field is simply not set).

numModifiedRows note

numModifiedRows is currently null on SEA, by server behavior: the SEA /statements REST API does not populate num_modified_rows in the status object — verified live against pecotesting across dispositions/wait_timeout/user-agent. Instead, the server delivers a DML's modified-row count as result-set data (the result has columns num_affected_rows / num_inserted_rows). The kernel's Statement.numModifiedRows() reads StatementStatus.num_modified_rows, which the server never sets, so it returns null.

A companion kernel change (made in the single kernel PR) derives num_modified_rows from the DML result row. Once that lands, this driver wiring surfaces numModifiedRows with no further driver change — the title lists it as part of the operation-status surface this PR completes, not a value demonstrable today.

The other three fields (displayMessage, diagnosticInfo, errorDetailsJson) have legitimate server population paths (terminal-error states; admin-enabled workspaces for errorDetailsJson) and are surfaced by this wiring where the server provides them.

Testing

  • Unit: 101 passing across tests/unit/sea/operation-lifecycle.test.ts, tests/unit/sea/SeaOperationBackend.test.ts, tests/unit/sea/execution.test.ts, and tests/unit/thrift-backend/wireSynthesis.test.ts.
  • Live (pecotesting, useSEA: true): CREATE TABLE + INSERT INTO ... VALUES (1),(2),(3) + SELECT 1 all execute and report status cleanly through the full chain; getOperationStatus() returns the rich-field shape (values reflect exactly what the kernel returns — numModifiedRows null today per the server note above), and the table is dropped after.

This pull request and its description were written by Isaac.

Replace the SEA backend's neutral synthesized operation status with the
real fields the napi kernel handle exposes on a terminal statement:
numModifiedRows, displayMessage, diagnosticInfo, errorDetailsJson.

- OperationStatus (neutral contract) carries the four rich fields.
- SeaOperationBackend.readRichStatusFields() reads them off the terminal
  sync Statement (metadata path + sync runAsync:false path once result()
  resolves); null-safe and degrades to all-null on the async path and on
  bindings predating the accessors. Wired into status() and the
  sync/cancellable completion tick.
- SeaOperationLifecycle.seaFinished merges the rich fields into the
  synthesized completion tick (lazy thunk) so finished({callback})
  consumers see the same surface as getOperationStatus().
- wireSynthesis.synthesizeThriftStatus maps them into
  TGetOperationStatusResp (numModifiedRows re-boxed as node-int64;
  null -> undefined for Thrift parity).

numModifiedRows is currently null on SEA: the server delivers DML counts
as result-set data (num_affected_rows) rather than in the status object.
A companion kernel change derives it; this wiring surfaces it then with
no further driver change.

Co-authored-by: Isaac
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 5, 2026

Thanks for your contribution! To satisfy the DCO policy in our contributing guide every commit message must include a sign-off message. One or more of your commits is missing this message. You can reword previous commit messages with an interactive rebase (git rebase -i main).

msrathore-db added a commit that referenced this pull request Jun 6, 2026
…essage, diagnosticInfo, errorDetailsJson)

Ports the async rich-status work (was #422) onto the consolidated branch: the
napi Statement.status() fields the kernel already exposes are now surfaced
through getOperationStatus instead of a flat Succeeded (M1 item).

Co-authored-by: Isaac
Signed-off-by: Madhavendra Rathore <madhavendra.rathore@databricks.com>
@msrathore-db
Copy link
Copy Markdown
Contributor Author

Folded into #420 (consolidated kernel-parity batch). The operation-status fields are now commits on #420's branch. This reply was written by Isaac.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant