---
title: "Preflight Blockchain SQL Query"
method: POST
path: "/gateway/v1/onchain/sql/preflight"
tags: ["Onchain"]
---

# Preflight Blockchain SQL Query

`POST /gateway/v1/onchain/sql/preflight`

Validate and estimate a read-only ClickHouse query before executing it.

This endpoint runs `EXPLAIN ESTIMATE` and does not execute the submitted query. It returns:
- Logical schema plus bounded physical source metadata
- Partition, sorting, and primary-key expressions
- Estimated parts, rows, marks, and bytes
- The final server-bounded SQL and scan budgets
- Machine-readable guardrail warnings with recommended actions

Use `GET /v1/onchain/schema?table=<name>` for metadata-only discovery. Preflight accepts the same JSON shape and SQL safety rules as `POST /v1/onchain/sql`, but missing pruning filters are returned as structured rejection warnings rather than running the query.

The planner rejects address columns wrapped in `lower()` and transfer-table predicates that combine `from` and `to` with OR. Normalize address literals before submission, compare stored lowercase columns directly, and split incoming/outgoing transfer predicates into projection-friendly `UNION ALL` branches. It also warns when address-hash sharding cannot prune physical data, a leading time ordering key is unbounded, maker/taker UNION branches repeat scans, large joins lack early filters or aggregation, or `ANY JOIN` lacks independent uniqueness proof. The planner never changes JOIN semantics automatically.

## Request body

- HumaOnchainSQLPreflightInputBody
  - `$schema` string, uri — A URL to the JSON Schema for this object.
  - `max_rows` integer — Maximum result rows in the final server-bounded execution plan
  - `sql` string, required — Read-only ClickHouse SELECT/WITH query to validate and estimate without executing it

## Response `200`

OK

- DataObjectResponseOnchainSQLPreflight
  - `$schema` string, uri — A URL to the JSON Schema for this object.
  - `data` OnchainSQLPreflight, required
    - `accepted` boolean, required — Whether the plan remains within required filters and configured scan budgets
    - `budget` OnchainSQLPreflightBudget, required
      - `max_bytes_to_read` integer, required — Maximum ClickHouse bytes the query may read; zero means disabled
      - `max_execution_time_seconds` integer, required — Synchronous execution-time budget in seconds
      - `max_rows_to_read` integer, required — Maximum ClickHouse rows the query may read; zero means disabled
    - `estimate` OnchainSQLPreflightEstimate, required
      - `by_table` OnchainSQLPreflightTableEstimate[], nullable, required — Per-physical-table estimates
        - `bytes` integer, required — Estimated bytes derived from current physical table size
        - `database` string, required — Physical ClickHouse database
        - `marks` integer, required — Estimated index granules to read
        - `parts` integer, required — Estimated active data parts
        - `rows` integer, required — Estimated rows to read
        - `table` string, required — Physical ClickHouse table
      - `bytes` integer, required — Estimated bytes derived from physical table bytes per row
      - `marks` integer, required — Estimated index granules to read
      - `parts` integer, required — Estimated active data parts
      - `rows` integer, required — Estimated rows to read
    - `executed_sql` string, required — Final SQL after server row limits and scan budgets are applied; preflight does not execute it
    - `query_id` string, required — ClickHouse query ID used for this EXPLAIN ESTIMATE operation
    - `request_id` string, required — Request correlation ID echoed in the X-Request-ID response header
    - `sql` string, required — Original submitted SQL
    - `tables` OnchainSchemaTable[], nullable, required — Allowlisted logical tables and bounded physical source metadata used by the plan
      - `columns` OnchainSchemaCol[], nullable, required — List of columns in this table
        - `comment` string — Column comment or description
        - `name` string, required — Column name
        - `type` string, required — Column data type like `UInt64`, `String`, or `DateTime`
      - `database` string, required — Database name (always `agent`)
      - `engine` string — Logical table engine, commonly View
      - `partition_key` string — Logical table PARTITION BY expression when applicable
      - `physical_sources` OnchainPhysicalTable[], nullable — Bounded physical source metadata for a selected logical view
        - `database` string, required — Physical ClickHouse database
        - `engine` string, required — Physical ClickHouse table engine
        - `partition_key` string — Physical PARTITION BY expression
        - `primary_key` string — Physical primary-key expression
        - `sorting_key` string — Physical ORDER BY expression
        - `table` string, required — Physical ClickHouse table
        - `total_bytes` integer — Current compressed bytes from system.tables
        - `total_rows` integer — Current physical row estimate from system.tables
      - `primary_key` string — Logical table primary-key expression when applicable
      - `sorting_key` string — Logical table ORDER BY expression when applicable
      - `table` string, required — Logical table name
      - `total_bytes` integer — Logical table compressed bytes when available
      - `total_rows` integer — Logical table row estimate when available
    - `warnings` OnchainSQLPreflightWarning[], nullable, required — Deterministic guardrail findings and recommended actions
      - `code` string, required — Stable machine-readable warning code
      - `message` string, required — Human-readable explanation
      - `recommended_action` string, required — Concrete action that preserves the requested query semantics
      - `severity` 'warning' | 'error', required — Warning is advisory; error makes accepted false
  - `meta` ObjectResponseMeta, required
    - `cached` boolean, required — Whether this response was served from cache
    - `credits_used` integer, required — Credits deducted for this request
    - `empty_reason` string — Hint explaining why the data array is empty, when applicable

## Other responses

- `default` — Error

---

[API](https://skmtc.dev/asksurf/apis/asksurf-public-rest-api.md) · [All operations](https://skmtc.dev/asksurf/apis/asksurf-public-rest-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/asksurf/asksurf-public-rest-api/revisions/498f461e81c4/schema)
