SQL Query Stream v1
Dieser Inhalt ist noch nicht in deiner Sprache verfügbar.
Summary
Section titled “Summary”Version 1 streams bounded, read-only Query Workbench previews. Implementation has landed; local and beta certification remain open. Existing compatibility JSON wire contracts remain unchanged; this is not a bulk-export API.
Endpoint
Section titled “Endpoint”POST /api/sql/api/query/stream/v1The request uses Content-Type: application/json. Accept and a successful response
use exactly:
application/vnd.rokks.sql-query-stream+json; version=1Authentication
Section titled “Authentication”Authenticate with the browser’s HttpOnly session cookie or the supported Bearer alternative. Explicit environment and tenant scope are required.
| Name | Type | Description |
|---|---|---|
| Session cookie | Authentication | Automatic browser session; HttpOnly and unreadable by JavaScript. |
Authorization |
Alternative | Bearer <session> for supported clients. |
x-env-id |
Header | Analytical environment. |
x-tenant-id |
Header | Governed tenant. |
x-priority |
Header | Deployment query priority. |
x-req-id |
Header | Required request UUID; equals body requestId. |
x-db-read |
Optional header | primary, strong, replica, or eventual. |
Accept |
Header | Exact v1 media type above. |
Content-Type |
Header | application/json. |
Request
Section titled “Request”| Name | Type | Description |
|---|---|---|
protocolVersion |
1 |
Required protocol discriminator. |
requestId |
UUID string | Equals x-req-id, hello, and terminal. |
sql |
string | One safe, read-only SQL statement. |
params |
optional array | Positional parameters. |
limit |
positive safe integer | Requested retained-row maximum. |
The raw JSON body is limited to 256 KiB before generic JSON middleware. SQL is
limited to 64 KiB. Serialized parameters are limited to 128 KiB, 1,024
top-level entries, 8,192 structural nodes, depth 16, and 256 UTF-8 bytes per
object key. The route rejects non-POST methods, compressed bodies,
Expect: 100-continue, duplicate protocol headers, and unsupported media
variants. Authentication is checked before the body is read.
Response
Section titled “Response”The response body is not a JSON envelope. It is a sequence of framed JSON records:
| Offset | Size | Meaning |
|---|---|---|
0 |
4 bytes | Unsigned big-endian length N. |
4 |
N bytes |
Exactly one UTF-8 JSON payload. |
N must be positive; zero is invalid. hello must fit the browser’s 64 KiB bootstrap
bound. The browser rejects advertised frame or Worker-batch limits above 16 MiB and a
byteLimit above the hard 64 MiB preview ceiling.
maxFrameBytes excludes the prefix. byteLimit covers the entire body—including every
prefix, payload, and terminal record.
| Record | Required fields | Contract |
|---|---|---|
hello |
v, type, requestId, limits, servedBy |
First and once; id and limit match the request. |
schema |
v, type, fields |
Once before rows/success. Error-before-schema may omit it. Names are non-empty, case-sensitive unique, and not __proto__; each field has non-negative dataTypeID. |
row |
v, type, seq, values |
Sequence starts at zero without gaps; width equals schema. |
terminal |
v, type, requestId, outcome, counts, timing, servedBy, error |
Last and once; nothing follows. |
Counts are non-negative safe integers. retainedRowCount equals delivered rows;
rowCountLowerBound is at least that count.
| Outcome | Count and null invariants |
|---|---|
complete |
completeRowCount, rowCountLowerBound, and retainedRowCount are equal; truncationReason and error are null. |
truncated |
completeRowCount is null; truncationReason is row_limit or byte_limit; error is null; the lower bound is at least the retained count. |
error |
completeRowCount and truncationReason are null; error is required; the lower bound is at least the retained count. |
Errors expose only code, message, optional position, and optional retryable.
Timings are finite and non-negative; terminal servedBy matches hello.
Rows remain provisional. Only valid complete or truncated commits them. Error,
cancellation, protocol failure, partial frame, or terminal-less EOF discards them.
Unknown fields/types, mismatched ids or servedBy, invalid sequence/counts, trailing
bytes, partial frames, and terminal-less EOF are rejected.
Fields / Parameters
Section titled “Fields / Parameters”| Name | Type | Description |
|---|---|---|
maxFrameBytes |
positive integer | JSON payload ceiling. |
workerBatchBytes |
positive integer | Worker row-batch ceiling. |
byteLimit |
positive integer | Whole-body wire ceiling. |
servedBy |
enum | primary or replica. |
downstreamWaitMs |
duration | Query-service drain wait. |
Bounded cursor reads wait for downstream writes. The edge relays incrementally. One browser transfer remains outstanding until the parser Worker acknowledges it; the main thread owns lifecycle, final state, and rendering. Before the Worker reply is structured-cloned, arrays, objects, and bytea cells become small typed preview descriptors; scalar strings are clipped at 2,048 characters. Framing preserves the values already produced by the analytical query service’s PostgreSQL type parsers within the advertised limits; database-driver type conversion happens before framing. Query Workbench intentionally retains only the bounded display projection.
Errors
Section titled “Errors”Pre-stream failures use HTTP errors; in-stream query failures use error terminal.
Cancellation propagates toward the query. There is no resume, replay, exactly-once, or
durable-delivery contract; do not retry blindly. The browser’s five-second cleanup
settlement deadline starts only after a body is rejected or aborted; it does not cap a
healthy stream, but prevents a broken body-cancel implementation from stranding the UI.
| HTTP status | Typical v1 meaning |
|---|---|
400 |
Invalid correlation, fields, parameter shape, or ambiguous protocol header. |
405 |
Method other than POST. |
406 |
Exact v1 Accept value missing. |
413 |
Pre-header request/admission limit, or a compatibility JSON response limit, was exceeded. After v1 hello, an oversized row/frame is reported by an error terminal when transport permits, otherwise by incomplete-stream failure. |
415 |
Content type or content encoding is unsupported. |
417 |
Expect is unsupported. |
503 |
Execution/lifecycle service is unavailable; inspect the stable error code. |
504 |
Initial header or bounded database phase timed out. |
Example
Section titled “Example”This supported Bearer example stores the framed response:
curl --no-buffer \ --request POST 'https://host.example.com/api/sql/api/query/stream/v1' \ --header 'Authorization: Bearer <session>' \ --header 'x-env-id: production' \ --header 'x-tenant-id: tenant-a' \ --header 'x-priority: high' \ --header 'x-req-id: 019c2f41-89d5-7a33-a6be-2a7115814f62' \ --header 'Content-Type: application/json' \ --header 'Accept: application/vnd.rokks.sql-query-stream+json; version=1' \ --data '{"protocolVersion":1,"requestId":"019c2f41-89d5-7a33-a6be-2a7115814f62","sql":"SELECT recorded_at, value FROM measurements ORDER BY recorded_at DESC","limit":100}' \ --output preview.streamThe decoded record order is:
hello → schema → row(0) → row(1) → … → terminal