-
Notifications
You must be signed in to change notification settings - Fork 49
[SEA-NodeJS] Sync execute via directResults (executeStatementDirect): fix CREATE, drop close-drives, keep cancel #426
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
bb749d6
c1d66dc
d29e675
8f1b268
11f0576
82e549b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -33,7 +33,7 @@ import InfoValue from '../dto/InfoValue'; | |
| import HiveDriverError from '../errors/HiveDriverError'; | ||
| import ParameterError from '../errors/ParameterError'; | ||
| import { LogLevel } from '../contracts/IDBSQLLogger'; | ||
| import { SeaConnection, SeaNativeExecuteOptions, SeaStatement } from './SeaNativeLoader'; | ||
| import { SeaConnection, SeaNativeExecuteOptions, SeaStatement, SeaNativeAsyncStatement } from './SeaNativeLoader'; | ||
| import { decodeNapiKernelError } from './SeaErrorMapping'; | ||
| import { numberToInt64 } from '../thrift-backend/ThriftSessionBackend'; | ||
| import SeaOperationBackend from './SeaOperationBackend'; | ||
|
|
@@ -183,24 +183,34 @@ export default class SeaSessionBackend implements ISessionBackend { | |
| options.queryTimeout !== undefined ? numberToInt64(options.queryTimeout).toNumber() : undefined; | ||
|
|
||
| if (!runAsync) { | ||
| // Sync path: forward `queryTimeoutSecs` to the napi options — the kernel | ||
| // `execute()` honours it (server statement timeout). | ||
| // DEFAULT — directResults (the Thrift/JDBC model). The kernel's | ||
| // `executeStatementDirect` runs ExecuteStatement with a bounded server | ||
| // inline wait and returns WITHOUT polling past it: | ||
| // - a terminal `Statement` (result inline) for a fast query, or | ||
| // - an `AsyncStatement` (a poll/cancel handle) for a slow one. | ||
| // Either way the handle is tied to a server-owned statement, so a long | ||
| // query stays cancellable via `op.cancel()` and `close()` is a clean | ||
| // release (no client-side drive-to-terminal). Fire-and-forget DDL/DML | ||
| // commits because the server runs it inline during the POST. | ||
| const execOptions = this.buildExecuteOptions(options, queryTimeoutSecs); | ||
| let cancellableExecution; | ||
| let direct; | ||
| try { | ||
| cancellableExecution = | ||
| direct = | ||
| execOptions === undefined | ||
| ? await this.connection.executeStatementCancellable(statement) | ||
| : await this.connection.executeStatementCancellable(statement, execOptions); | ||
| ? await this.connection.executeStatementDirect(statement) | ||
| : await this.connection.executeStatementDirect(statement, execOptions); | ||
| } catch (err) { | ||
| throw this.logAndMapError('executeStatement', err); | ||
| } | ||
| // Feature-detect the arm: only `AsyncStatement` (the Running arm) exposes | ||
| // `awaitResult`; the terminal `Statement` (Completed arm) does not. | ||
| const asAsync = direct as unknown as SeaNativeAsyncStatement; | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 F4 —
function isAsyncStatement(x: SeaStatement | SeaNativeAsyncStatement): x is SeaNativeAsyncStatement {
return typeof (x as SeaNativeAsyncStatement).awaitResult === 'function';
}Then: |
||
| if (direct !== null && typeof asAsync.awaitResult === 'function') { | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 F5 — Inconsistent null/undefined defensive handling (Moderate confidence — security, devils-advocate, language; verified) The kernel contract ( Fix (optional): reject a non-object |
||
| return new SeaOperationBackend({ asyncStatement: asAsync, context: this.context, queryTimeoutSecs }); | ||
| } | ||
| return new SeaOperationBackend({ | ||
| cancellableExecution: cancellableExecution!, | ||
| statement: direct as unknown as SeaStatement, | ||
| context: this.context, | ||
| // The kernel honours `queryTimeoutSecs` on the sync `execute` path, so | ||
| // it is forwarded via the napi options (see `buildExecuteOptions`); the | ||
| // backend also keeps it as a deadline guard for parity with async. | ||
| queryTimeoutSecs, | ||
| }); | ||
| } | ||
|
|
||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -234,6 +234,26 @@ class FakeNativeConnection implements SeaConnection { | |
| return this.lastCancellableExecution; | ||
| } | ||
|
|
||
| // directResults (`runAsync: false`, the DEFAULT) query path: records sql + | ||
| // options and returns either a terminal `Statement` (Completed arm) or — when | ||
| // `directReturnsRunning` is set — a pending `AsyncStatement` (Running arm), | ||
| // the two arms `SeaSessionBackend.executeStatement` feature-detects via | ||
| // `awaitResult`. | ||
| public directReturnsRunning = false; | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔴 F1 — The AsyncStatement (slow-query) arm is completely untested (High confidence — flagged by all 5 reviewers; verified) This PR adds As a result, the branch this entire PR exists to add — Suggested fix: add ≥1 test that sets |
||
|
|
||
| public async executeStatementDirect(sql: string, options?: unknown): Promise<any> { | ||
| if (this.throwOnExecute) { | ||
| throw this.throwOnExecute; | ||
| } | ||
| this.lastSql = sql; | ||
| this.lastOptions = options; | ||
| if (this.directReturnsRunning) { | ||
| this.lastAsyncStatement = new FakeAsyncStatement(this.submitStatusValue); | ||
| return this.lastAsyncStatement; | ||
| } | ||
| return this.statementToReturn; | ||
| } | ||
|
|
||
| // Async-submit path: records sql + per-statement options (for forwarding | ||
| // assertions) and returns a pending AsyncStatement. | ||
| public async submitStatement(sql: string, options?: unknown): Promise<any> { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🟡 F3 — Stale block comment contradicts the new code (Moderate confidence — 2 reviewers; verified)
This new inline comment correctly describes directResults, but the
runAsyncselector comment block just above (lines ~166–173) still says the DEFAULT path "Route[s] throughexecuteStatementCancellable: the kernel blocks onexecute()… The blocking drive runs in the operation backend'sresult()" — exactly the behavior this PR removes. The two comments in the same method now contradict each other.Fix: update the 166–173 block to describe directResults. (There's also a trivially stale comment at
execution.test.ts:699still referencingexecuteStatementCancellable.)