Multiple query results
Multiple query results
The query workspace displays a separate result tab for each executable statement.
Statements execute sequentially in script order. Rows appear while the current
statement runs. A let declaration defines a reusable expression and does not
create a result tab.
let events = MyTable | where Timestamp > ago(1h);
events | take 100;
events | count;Each result has its own columns and chart hint. Select a result tab to inspect its rows or chart. Charts become available when their result completes. Cancelling or encountering an error preserves received rows and marks unfinished results as partial. Export filenames identify partial results.
Streaming API
Send Accept: application/x-ndjson to POST /search/{accountId}/kusto to receive
newline-delimited JSON. The request body and authentication are unchanged.
Requests without this header retain the existing single-result JSON response.
| Event | Fields | Meaning |
|---|---|---|
resultStart | resultId, header, columns, optional render, sourceStart, sourceLength | Create a result with its own schema; source offsets refer to the submitted script. |
rows | resultId, rows | Append positional row arrays matching the result's ordered columns. |
message | resultId, timestamp, message | Execution diagnostic. |
resultComplete | resultId, rowCount | The result completed successfully, including empty results. |
queryComplete | — | All statements completed successfully. |
queryError | optional resultId, message | Terminal execution failure. Received rows remain partial. |
Result IDs start at zero and increase in script order. Do not assume that network
chunks align with JSON lines or UTF-8 characters. A connection ending without queryComplete or queryError is interrupted, not successful.
Validation and permission errors before streaming use the existing HTTP error
response. Once streaming starts, errors use queryError rather than changing
the HTTP status. The schema is flushed immediately; pending rows are flushed at
approximately 64 KiB, 4,096 rows, or 100 ms while waiting for more executor output.
Operators that need all their input, such as sorting, may delay the first row.
Each statement uses the existing bounded executor and memory/spill admission. The script shares cancellation and the caller's maximum timeout. Completed pipelines release resources before the next statement starts. Streaming avoids waiting for a complete JSON document, but the workspace still retains received rows in browser memory.
Deploy updated executor nodes before enabling the streaming workspace on query hosts: the additive executor request field selects an explicit output stream, including the command output stream. Existing executor requests remain compatible.
Statement permission checks run for the whole script before execution begins. Each statement then selects its current files and executor after the previous statement has finished and released its resources. For example, .truncate table 'logs'; logs | count counts the table after truncation. Statement plans include only their own work and referenced let declarations; bindings remain lazy query expressions rather than materialized results.
After cancellation or failure, completed results remain complete and unfinished results are marked partial. Data, charts, copy, and export remain available for the selected retained result, including an empty result. Exports contain only the rows received so far; the error and partial status remain visible.