{"schemaVersion":"1.0.0","docId":"trino-client","source":"trino-client","slug":"trino-client","path":"/docs/trino-client","raw_path":"/raw/trino-client.md","title":"Trino Client","headings":[],"documentType":"unknown","contentOrigin":"static-doc","canonicalUrl":"/docs/trino-client/","buildId":"local-1782300281858","generatedAt":"2026-06-24T11:24:41.858Z","content":"---\ntitle: Trino Client\nnavTitle: Trino Client\ndescription: HTTP client for Trino's REST API.\nentrypoint: /docs/trino-client/overview/introduction\n---\n","description":"HTTP client for Trino's REST API.","navTitle":"Trino Client","keywords":["client","trino","trinos"]}
{"schemaVersion":"1.0.0","docId":"trino-client/configuration/client-setup","source":"trino-client","slug":"configuration/client-setup","path":"/docs/trino-client/configuration/client-setup","raw_path":"/raw/trino-client/configuration/client-setup.md","title":"Client Setup","headings":[{"level":2,"text":"Basic Authentication","id":"basic-authentication"},{"level":2,"text":"Bearer Token Authentication","id":"bearer-token-authentication"},{"level":2,"text":"Retry Configuration","id":"retry-configuration"},{"level":2,"text":"Timeout","id":"timeout"},{"level":2,"text":"Default Headers","id":"default-headers"}],"documentType":"unknown","contentOrigin":"static-doc","canonicalUrl":"/docs/trino-client/configuration/client-setup/","buildId":"local-1782300281858","generatedAt":"2026-06-24T11:24:41.858Z","content":"---\ntitle: Client Setup\ndescription: Configuration options and authentication for the Trino client.\n---\n\n## Basic Authentication\n\n```ts\nimport { TrinoClient } from \"@lakeql/trino-client\"\n\nconst client = new TrinoClient({\n  host: \"https://trino.example.com\",\n  port: 8443,\n  auth: {\n    type: \"basic\",\n    username: \"analyst\",\n    password: \"s3cr3t\",\n  },\n  catalog: \"hive\",\n  schema: \"sales\",\n})\n```\n\nThe username and password are Base64-encoded and sent as an `Authorization: Basic ...` header on every request.\n\n## Bearer Token Authentication\n\n```ts\nimport { TrinoClient } from \"@lakeql/trino-client\"\n\nconst client = new TrinoClient({\n  host: \"https://trino.example.com\",\n  port: 8443,\n  auth: {\n    type: \"bearer\",\n    token: \"eyJhbGciOiJSUzI1NiIs...\",\n  },\n  catalog: \"iceberg\",\n  source: \"my-etl-service\",\n})\n```\n\nThe token is sent as an `Authorization: Bearer ...` header.\n\n## Retry Configuration\n\nThe client automatically retries on transient failures (HTTP 429, 500, 502, 503, 504 and network errors). Configure retry behavior via the `retry` option:\n\n```ts\nimport { TrinoClient } from \"@lakeql/trino-client\"\n\nconst client = new TrinoClient({\n  host: \"https://trino.example.com\",\n  port: 8443,\n  auth: { type: \"basic\", username: \"analyst\", password: \"secret\" },\n  catalog: \"hive\",\n  retry: {\n    maxRetries: 5,\n    initialDelay: 500,\n    maxDelay: 30000,\n    backoffMultiplier: 2,\n  },\n})\n```\n\n<InterfaceReference file=\"trino-client/src/retry\" name=\"RetryConfig\" />\n\n## Timeout\n\nSet a default timeout (in milliseconds) for all requests. If a request exceeds this duration, it will be aborted:\n\n```ts\nimport { TrinoClient } from \"@lakeql/trino-client\"\n\nconst client = new TrinoClient({\n  host: \"https://trino.example.com\",\n  port: 8443,\n  auth: { type: \"basic\", username: \"analyst\", password: \"secret\" },\n  catalog: \"hive\",\n  timeout: 30_000, // 30 seconds\n})\n```\n\nYou can also pass a per-query `signal` for more fine-grained control — see [Executing Queries](/docs/trino-client/queries/executing-queries).\n\n## Default Headers\n\nOn construction, the client sets the following Trino headers automatically:\n\n| Header            | Value                                         |\n| ----------------- | --------------------------------------------- |\n| `X-Trino-Source`  | The `source` option, or `\"nodejs\"` if omitted |\n| `X-Trino-Catalog` | The `catalog` option                          |\n| `X-Trino-Schema`  | The `schema` option (only if provided)        |\n\nYou can modify headers after construction using `setHeader()` or `setRawHeader()`:\n\n```ts\nclient.setHeader(\"X-Trino-Schema\", \"production\")\nclient.setRawHeader(\"X-Custom-Header\", \"value\")\n```\n","description":"Configuration options and authentication for the Trino client.","keywords":["authentication","client","configuration","setup","options"]}
{"schemaVersion":"1.0.0","docId":"trino-client/metadata/inspecting-catalogs","source":"trino-client","slug":"metadata/inspecting-catalogs","path":"/docs/trino-client/metadata/inspecting-catalogs","raw_path":"/raw/trino-client/metadata/inspecting-catalogs.md","title":"Inspecting Catalogs","headings":[{"level":2,"text":"Overview","id":"overview"},{"level":2,"text":"schemas","id":"schemas"},{"level":2,"text":"tables","id":"tables"},{"level":2,"text":"views","id":"views"},{"level":2,"text":"columns","id":"columns"},{"level":2,"text":"Full Discovery Example","id":"full-discovery-example"}],"documentType":"unknown","contentOrigin":"static-doc","canonicalUrl":"/docs/trino-client/metadata/inspecting-catalogs/","buildId":"local-1782300281858","generatedAt":"2026-06-24T11:24:41.858Z","content":"---\ntitle: Inspecting Catalogs\ndescription: List schemas, tables, views, and columns from any Trino catalog.\n---\n\n## Overview\n\nThe Trino client provides convenience methods for inspecting catalog metadata. Each method executes a SQL query internally and returns a simplified result — typically an array of strings or tuples.\n\nSee the [API Reference](/docs/trino-client/api-reference) for full method signatures and return types.\n\n## schemas\n\nLists all schemas in a catalog.\n\n```ts\nimport { TrinoClient } from \"@lakeql/trino-client\"\n\nconst client = new TrinoClient({\n  host: \"https://trino.example.com\",\n  port: 8443,\n  auth: { type: \"basic\", username: \"analyst\", password: \"secret\" },\n  catalog: \"hive\",\n})\n\nconst schemas = await client.schemas({ catalog: \"hive\" })\n// [\"default\", \"sales\", \"analytics\", \"information_schema\"]\n```\n\n## tables\n\nLists all base tables in a catalog and schema.\n\n```ts\nimport { TrinoClient } from \"@lakeql/trino-client\"\n\nconst client = new TrinoClient({\n  host: \"https://trino.example.com\",\n  port: 8443,\n  auth: { type: \"basic\", username: \"analyst\", password: \"secret\" },\n  catalog: \"hive\",\n})\n\nconst tables = await client.tables({ catalog: \"hive\", schema: \"sales\" })\n// [\"orders\", \"customers\", \"products\", \"invoices\"]\n```\n\n## views\n\nLists all views in a catalog and schema.\n\n```ts\nimport { TrinoClient } from \"@lakeql/trino-client\"\n\nconst client = new TrinoClient({\n  host: \"https://trino.example.com\",\n  port: 8443,\n  auth: { type: \"basic\", username: \"analyst\", password: \"secret\" },\n  catalog: \"hive\",\n})\n\nconst views = await client.views({ catalog: \"hive\", schema: \"sales\" })\n// [\"monthly_revenue\", \"top_customers\"]\n```\n\n## columns\n\nLists all columns for a specific table, including their types and metadata.\n\n```ts\nimport { TrinoClient } from \"@lakeql/trino-client\"\n\nconst client = new TrinoClient({\n  host: \"https://trino.example.com\",\n  port: 8443,\n  auth: { type: \"basic\", username: \"analyst\", password: \"secret\" },\n  catalog: \"hive\",\n})\n\nconst columns = await client.columns({\n  catalog: \"hive\",\n  schema: \"sales\",\n  table: \"orders\",\n})\n// [\n//   [\"id\", \"varchar\", \"\", \"Order identifier\"],\n//   [\"amount\", \"double\", \"\", \"Total order amount\"],\n//   [\"created_at\", \"timestamp(3)\", \"\", \"When the order was placed\"],\n// ]\n```\n\n### Typed objects with `asObject`\n\nPass `asObject: true` to get `ColumnInfo[]` objects instead of raw tuples:\n\n```ts\nimport { TrinoClient } from \"@lakeql/trino-client\"\n\nconst client = new TrinoClient({\n  host: \"https://trino.example.com\",\n  port: 8443,\n  auth: { type: \"basic\", username: \"analyst\", password: \"secret\" },\n  catalog: \"hive\",\n})\n\nconst columns = await client.columns({\n  catalog: \"hive\",\n  schema: \"sales\",\n  table: \"orders\",\n  asObject: true,\n})\n// [\n//   { name: \"id\", type: \"varchar\", extra: \"\", description: \"Order identifier\" },\n//   { name: \"amount\", type: \"double\", extra: \"\", description: \"Total order amount\" },\n// ]\n\nfor (const col of columns) {\n  console.log(`${col.name}: ${col.type}`)\n}\n```\n\n## Full Discovery Example\n\n```ts\nimport { TrinoClient } from \"@lakeql/trino-client\"\n\nconst client = new TrinoClient({\n  host: \"https://trino.example.com\",\n  port: 8443,\n  auth: { type: \"bearer\", token: \"eyJhbGciOiJSUzI1NiIs...\" },\n  catalog: \"iceberg\",\n})\n\n// Discover all tables across all schemas\nconst schemas = await client.schemas({ catalog: \"iceberg\" })\n\nfor (const schema of schemas) {\n  if (schema === \"information_schema\") {\n    continue\n  }\n\n  const tables = await client.tables({ catalog: \"iceberg\", schema })\n  console.log(`${schema}: ${tables.join(\", \")}`)\n\n  for (const table of tables) {\n    const columns = await client.columns({ catalog: \"iceberg\", schema, table })\n    console.log(\n      `  ${table}: ${columns.map(([name, type]) => `${name} (${type})`).join(\", \")}`\n    )\n  }\n}\n```\n","description":"List schemas, tables, views, and columns from any Trino catalog.","keywords":["schemas","tables","views","columns","inspecting"]}
{"schemaVersion":"1.0.0","docId":"trino-client/overview/introduction","source":"trino-client","slug":"overview/introduction","path":"/docs/trino-client/overview/introduction","raw_path":"/raw/trino-client/overview/introduction.md","title":"Introduction","headings":[{"level":2,"text":"What is the Trino Client?","id":"what-is-the-trino-client"},{"level":2,"text":"Core Capabilities","id":"core-capabilities"},{"level":2,"text":"Quick Example","id":"quick-example"},{"level":2,"text":"How It Works","id":"how-it-works"}],"documentType":"unknown","contentOrigin":"static-doc","canonicalUrl":"/docs/trino-client/overview/introduction/","buildId":"local-1782300281858","generatedAt":"2026-06-24T11:24:41.858Z","content":"---\ntitle: Introduction\ndescription: An HTTP client for executing queries and inspecting metadata on Trino clusters.\n---\n\n## What is the Trino Client?\n\nThe `@lakeql/trino-client` package provides a typed HTTP client for communicating with a Trino cluster via its [REST API](https://trino.io/docs/current/develop/client-protocol.html). It handles authentication, paginated result fetching, query cancellation, and catalog metadata inspection.\n\nBuilt on native `fetch` with zero runtime dependencies. Supports basic and bearer token authentication, automatic pagination through `nextUri` links, configurable retry with exponential backoff, and an async-generator streaming mode for memory-efficient processing of large result sets.\n\n## Core Capabilities\n\n- **Query execution** — Send SQL statements and collect all result pages into a single array\n- **Streaming** — Yield rows one at a time via an async generator for large datasets\n- **Row transforms** — Map raw row arrays to typed objects with a `transform` function\n- **Query cancellation** — Cancel in-flight queries via `AbortSignal` or `cancelQuery()`\n- **Retry with backoff** — Automatic retry on transient failures (429, 5xx, network errors)\n- **Metadata inspection** — List schemas, tables, views, and columns for any catalog\n- **Authentication** — Basic auth (username/password) and bearer token auth\n- **User impersonation** — Execute queries on behalf of another user via the `X-Trino-User` header\n\n## Quick Example\n\n```ts\nimport { TrinoClient } from \"@lakeql/trino-client\"\n\nconst client = new TrinoClient({\n  host: \"https://trino.example.com\",\n  port: 8443,\n  auth: { type: \"basic\", username: \"analyst\", password: \"secret\" },\n  catalog: \"hive\",\n  schema: \"sales\",\n})\n\nconst rows = await client.query<[string, number]>({\n  sql: \"SELECT region, SUM(amount) FROM orders GROUP BY region\",\n})\n\nconsole.log(rows)\n// [[\"us-east\", 42000], [\"eu-west\", 31500], ...]\n```\n\n## How It Works\n\n1. The client sends a `POST` request to `/v1/statement` with the SQL body\n2. Trino responds with an initial result (possibly empty) and a `nextUri`\n3. The client follows `nextUri` links with `GET` requests until no more pages remain\n4. All `data` arrays from each page are concatenated into the final result\n\nThis pagination is handled transparently — you call `query()` and get back the full result set.\n","description":"An HTTP client for executing queries and inspecting metadata on Trino clusters.","keywords":["client","trino","introduction","executing","queries"]}
{"schemaVersion":"1.0.0","docId":"trino-client/queries/executing-queries","source":"trino-client","slug":"queries/executing-queries","path":"/docs/trino-client/queries/executing-queries","raw_path":"/raw/trino-client/queries/executing-queries.md","title":"Executing Queries","headings":[{"level":2,"text":"Basic Usage","id":"basic-usage"},{"level":2,"text":"Row Transforms","id":"row-transforms"},{"level":2,"text":"User Impersonation","id":"user-impersonation"},{"level":2,"text":"Query Cancellation","id":"query-cancellation"},{"level":2,"text":"Error Handling","id":"error-handling"},{"level":2,"text":"How Pagination Works","id":"how-pagination-works"},{"level":2,"text":"QueryProps Reference","id":"query-props-reference"}],"documentType":"unknown","contentOrigin":"static-doc","canonicalUrl":"/docs/trino-client/queries/executing-queries/","buildId":"local-1782300281858","generatedAt":"2026-06-24T11:24:41.858Z","content":"---\ntitle: Executing Queries\ndescription: Run SQL statements against Trino and collect all result pages into a single array.\n---\n\n## Basic Usage\n\nThe `query` method executes a SQL statement and automatically follows Trino's `nextUri` pagination links until all result pages have been collected.\n\n```ts\nimport { TrinoClient } from \"@lakeql/trino-client\"\n\nconst client = new TrinoClient({\n  host: \"https://trino.example.com\",\n  port: 8443,\n  auth: { type: \"basic\", username: \"analyst\", password: \"secret\" },\n  catalog: \"hive\",\n  schema: \"sales\",\n})\n\nconst rows = await client.query<[string, string, number]>({\n  sql: \"SELECT id, region, amount FROM orders WHERE status = 'shipped'\",\n})\n\nfor (const [id, region, amount] of rows) {\n  console.log(`Order ${id}: ${region} - $${amount}`)\n}\n```\n\n## Row Transforms\n\nUse the `transform` option to map raw row arrays into typed objects:\n\n```ts\nimport { TrinoClient } from \"@lakeql/trino-client\"\nimport type { Column } from \"@lakeql/trino-client\"\n\nconst client = new TrinoClient({\n  host: \"https://trino.example.com\",\n  port: 8443,\n  auth: { type: \"basic\", username: \"analyst\", password: \"secret\" },\n  catalog: \"hive\",\n  schema: \"sales\",\n})\n\ninterface Order {\n  id: string\n  region: string\n  amount: number\n}\n\nconst orders = await client.query<Order>({\n  sql: \"SELECT id, region, amount FROM orders\",\n  transform: (row: unknown[], columns: Column[]) => ({\n    id: row[0] as string,\n    region: row[1] as string,\n    amount: row[2] as number,\n  }),\n})\n\n// orders: Order[]\nconsole.log(orders[0].region)\n```\n\nThe `transform` function receives the raw row array and the column metadata, and returns the desired shape.\n\n## User Impersonation\n\nPass `impersonateAs` to execute the query as a different Trino user. This sets the `X-Trino-User` header for that request only:\n\n```ts\nimport { TrinoClient } from \"@lakeql/trino-client\"\n\nconst client = new TrinoClient({\n  host: \"https://trino.example.com\",\n  port: 8443,\n  auth: { type: \"basic\", username: \"analyst\", password: \"secret\" },\n  catalog: \"hive\",\n})\n\nconst rows = await client.query<[string]>({\n  sql: \"SELECT current_user\",\n  impersonateAs: \"data-team-service\",\n})\n// rows: [[\"data-team-service\"]]\n```\n\n## Query Cancellation\n\nCancel a running query using an `AbortSignal`:\n\n```ts\nimport { TrinoClient, TrinoCancellationError } from \"@lakeql/trino-client\"\n\nconst client = new TrinoClient({\n  host: \"https://trino.example.com\",\n  port: 8443,\n  auth: { type: \"basic\", username: \"analyst\", password: \"secret\" },\n  catalog: \"hive\",\n})\n\nconst controller = new AbortController()\n\n// Cancel after 10 seconds\nsetTimeout(() => controller.abort(), 10_000)\n\ntry {\n  const rows = await client.query({\n    sql: \"SELECT * FROM very_large_table\",\n    signal: controller.signal,\n  })\n} catch (error) {\n  if (error instanceof TrinoCancellationError) {\n    console.log(\"Query was cancelled\")\n  }\n}\n```\n\nYou can also cancel queries by ID:\n\n```ts\nimport { TrinoClient } from \"@lakeql/trino-client\"\n\nconst client = new TrinoClient({\n  host: \"https://trino.example.com\",\n  port: 8443,\n  auth: { type: \"basic\", username: \"analyst\", password: \"secret\" },\n  catalog: \"hive\",\n})\n\n// Cancel a specific query\nawait client.cancelQuery(\"20240101_123456_00001_abcde\")\n\n// Cancel all active queries\nawait client.cancelAllQueries()\n\n// Check what's currently running\nconst active = client.getActiveQueries()\n```\n\n## Error Handling\n\nThe client throws typed errors depending on the failure:\n\n```ts\nimport {\n  TrinoClient,\n  TrinoClientError,\n  TrinoQueryError,\n  TrinoCancellationError,\n} from \"@lakeql/trino-client\"\n\nconst client = new TrinoClient({\n  host: \"https://trino.example.com\",\n  port: 8443,\n  auth: { type: \"basic\", username: \"analyst\", password: \"secret\" },\n  catalog: \"hive\",\n})\n\ntry {\n  const rows = await client.query({ sql: \"SELECT * FROM nonexistent_table\" })\n} catch (error) {\n  if (error instanceof TrinoQueryError) {\n    // Trino returned an error in the response body\n    console.error(error.errorName) // e.g. \"TABLE_NOT_FOUND\"\n    console.error(error.errorType) // e.g. \"USER_ERROR\"\n    console.error(error.queryId)\n  } else if (error instanceof TrinoClientError) {\n    // HTTP-level error (non-2xx status)\n    console.error(error.statusCode) // e.g. 503\n    console.error(error.message)\n  } else if (error instanceof TrinoCancellationError) {\n    // Query was cancelled via AbortSignal\n    console.log(\"Cancelled:\", error.queryId)\n  }\n}\n```\n\n## How Pagination Works\n\n1. A `POST` is sent to `/v1/statement` with the SQL body\n2. Trino returns an initial response with (optionally) data and a `nextUri`\n3. The client follows `nextUri` with `GET` requests, collecting `data` arrays\n4. When no `nextUri` is returned, all pages have been fetched\n5. The concatenated result array is returned\n\nThis is entirely transparent — you call `query()` and get the complete result regardless of how many pages Trino needed internally.\n\n## QueryProps Reference\n\n<InterfaceReference file=\"trino-client/src/types\" name=\"QueryProps\" />\n","description":"Run SQL statements against Trino and collect all result pages into a single array.","keywords":["executing","queries","statements","against","trino"]}
{"schemaVersion":"1.0.0","docId":"trino-client/queries/streaming","source":"trino-client","slug":"queries/streaming","path":"/docs/trino-client/queries/streaming","raw_path":"/raw/trino-client/queries/streaming.md","title":"Streaming","headings":[{"level":2,"text":"Basic Usage","id":"basic-usage"},{"level":2,"text":"Streaming with Transforms","id":"streaming-with-transforms"},{"level":2,"text":"Cancelling a Stream","id":"cancelling-a-stream"},{"level":2,"text":"When to Use stream vs query","id":"when-to-use-stream-vs-query"},{"level":2,"text":"Memory Efficiency","id":"memory-efficiency"}],"documentType":"unknown","contentOrigin":"static-doc","canonicalUrl":"/docs/trino-client/queries/streaming/","buildId":"local-1782300281858","generatedAt":"2026-06-24T11:24:41.858Z","content":"---\ntitle: Streaming\ndescription: Stream query results row-by-row using an async generator for memory-efficient processing.\n---\n\n## Basic Usage\n\nThe `stream` method executes a SQL statement and returns an async generator that yields rows one at a time as pages are fetched. Ideal for large result sets where holding all data in memory would be impractical.\n\n```ts\nimport { TrinoClient } from \"@lakeql/trino-client\"\n\nconst client = new TrinoClient({\n  host: \"https://trino.example.com\",\n  port: 8443,\n  auth: { type: \"basic\", username: \"analyst\", password: \"secret\" },\n  catalog: \"hive\",\n  schema: \"logs\",\n})\n\nconst stream = await client.stream<[string, string, number]>({\n  sql: \"SELECT timestamp, level, duration FROM request_logs\",\n})\n\nfor await (const [timestamp, level, duration] of stream) {\n  if (duration > 5000) {\n    console.warn(`Slow request at ${timestamp}: ${duration}ms`)\n  }\n}\n```\n\n## Streaming with Transforms\n\nCombine streaming with `transform` to get typed objects:\n\n```ts\nimport { TrinoClient } from \"@lakeql/trino-client\"\nimport type { Column } from \"@lakeql/trino-client\"\n\nconst client = new TrinoClient({\n  host: \"https://trino.example.com\",\n  port: 8443,\n  auth: { type: \"basic\", username: \"analyst\", password: \"secret\" },\n  catalog: \"hive\",\n  schema: \"logs\",\n})\n\ninterface LogEntry {\n  timestamp: string\n  level: string\n  duration: number\n}\n\nconst stream = await client.stream<LogEntry>({\n  sql: \"SELECT timestamp, level, duration FROM request_logs\",\n  transform: (row: unknown[], columns: Column[]) => ({\n    timestamp: row[0] as string,\n    level: row[1] as string,\n    duration: row[2] as number,\n  }),\n})\n\nfor await (const entry of stream) {\n  if (entry.level === \"ERROR\") {\n    console.error(`Error at ${entry.timestamp}: ${entry.duration}ms`)\n  }\n}\n```\n\n## Cancelling a Stream\n\nPass an `AbortSignal` to cancel a stream mid-flight:\n\n```ts\nimport { TrinoClient } from \"@lakeql/trino-client\"\n\nconst client = new TrinoClient({\n  host: \"https://trino.example.com\",\n  port: 8443,\n  auth: { type: \"basic\", username: \"analyst\", password: \"secret\" },\n  catalog: \"hive\",\n  schema: \"logs\",\n})\n\nconst controller = new AbortController()\n\nconst stream = await client.stream({\n  sql: \"SELECT * FROM events\",\n  signal: controller.signal,\n})\n\nlet count = 0\nfor await (const row of stream) {\n  count += 1\n  if (count >= 1000) {\n    controller.abort()\n    break\n  }\n}\n```\n\n## When to Use stream vs query\n\n| Scenario                          | Method   |\n| --------------------------------- | -------- |\n| Result fits comfortably in memory | `query`  |\n| Large or unbounded result sets    | `stream` |\n| Need all rows before processing   | `query`  |\n| Can process rows incrementally    | `stream` |\n| ETL pipelines / file exports      | `stream` |\n\n## Memory Efficiency\n\nWith `query`, all pages are collected into a single array before the promise resolves. With `stream`, each page is fetched on-demand and rows are yielded immediately — only one page of data is held in memory at a time.\n\n```ts\nimport { TrinoClient } from \"@lakeql/trino-client\"\n\nconst client = new TrinoClient({\n  host: \"https://trino.example.com\",\n  port: 8443,\n  auth: { type: \"basic\", username: \"analyst\", password: \"secret\" },\n  catalog: \"hive\",\n  schema: \"analytics\",\n})\n\n// Processing millions of rows without loading them all into memory\nconst stream = await client.stream<[string, number]>({\n  sql: \"SELECT user_id, event_count FROM daily_aggregates\",\n})\n\nlet processed = 0\nfor await (const [userId, count] of stream) {\n  console.log(`${userId}: ${count}`)\n  processed += 1\n}\n\nconsole.log(`Processed ${processed} rows`)\n```\n","description":"Stream query results row-by-row using an async generator for memory-efficient processing.","keywords":["stream","streaming","query","results","row-by-row"]}