OQ — Q00 · Query engine
OnchainQueries accepts OnchainQL over typed Solana tables, translates the forms it can execute safely, and refuses the ones whose namesakes behave differently. A query that runs is a query whose semantics were checked — not one that happened to parse.
- Engine classes
- 3
- Explicit translations
- 11
- Parameter types
- 13
- Result expiry
- 24h
Every request must be exactly one query beginning with SELECT or WITH. Data modification, schema changes, session configuration, system tables and external table functions are rejected before a source query is ever issued.
One statement
Multiple statements and misplaced semicolons are refused. There is no batch mode, so there is no ambiguity about what ran.
No writes, ever
Data and schema modification, grants and administrative statements are all rejected. The source database is never mutated.
No escape hatches
External table functions and the execution layer's internal tables are unavailable, as are user-controlled FORMAT and SETTINGS.
OnchainQueries reads the shape of your query and gives it the resources it needs. A filtered lookup gets a small share and returns fast; a windowed join over a CTE gets the room and the hours to finish. There is no dial to tune and no capacity to plan.
| OnchainQueries assigns | SmallFiltered read | MediumGrouped aggregate | LargeWindow over a CTE |
|---|---|---|---|
| Chosen when your query has | A filtered read with no grouping or ordering | GROUP BY, ORDER BY, or a long statement | A join, a window function, or UNNEST |
| Execution limit | 2 minutes | 30 minutes | 6 hours |
| Suited to | Filtered lookups and simple scans | Grouping, ordering and moderate analytics | Joins, windows, unnesting and heavy analytics |
- Chosen when your query has
- A filtered read with no grouping or ordering
- Execution limit
- 2 minutes
- Suited to
- Filtered lookups and simple scans
- Chosen when your query has
- GROUP BY, ORDER BY, or a long statement
- Execution limit
- 30 minutes
- Suited to
- Grouping, ordering and moderate analytics
- Chosen when your query has
- A join, a window function, or UNNEST
- Execution limit
- 6 hours
- Suited to
- Joins, windows, unnesting and heavy analytics
OnchainQL rewrites these forms explicitly. Other function names pass through untranslated — which is not the same as being supported, and the docs say so.
- date_trunc→dateTrunc
- count_if→countIf
- approx_percentile→quantileTDigest
- from_base58 / to_base58→base58Decode / base58Encode
- json_extract→JSON_QUERY
- json_extract_scalar→JSON_VALUE
- CAST(x AS VARBINARY)→CAST(x AS String)
- UNNEST→ARRAY JOIN
These have same-named functions underneath with different semantics. OnchainQueries fails loudly rather than returning a different number than you expect.
- element_at
- filter
- reduce
- transform
- zip_with
- map
- map_filter
- map_transform_keys
- map_transform_values
- json_parse
- json_array_length
OnchainQueries records the catalog hash and high-watermark slot used to plan a query, then fingerprints source partitions before and after execution. If anything relevant changed mid-flight, it retries rather than publishing a mixed result.
{ "state": "complete", "selected_engine": "medium", "row_count": 128441, "source_coverage": { "tables": ["prod_solana_eventstream.pump_fun_trade_event"] }, "catalog_hash": "9f2c...a41e", "high_watermark_slot": 372140688, "parts": [ { "name": "part-00000.parquet", "bytes": 6488064, "sha256": "..." } ], "expires_at": "2026-08-29T09:14:22Z"}The manifest is written last, so a directory containing it is a complete result. Every part is checksummed before it gets its final name, and rerunning against the same directory reuses parts that already match.
source_coverage.tables is the honest answer to “what did this number actually come from”. Read it whenever coverage matters.
Can I bring a query over from another SQL platform?
For the core analytical surface, usually. If you know analytical SQL you already know OnchainQL. Higher-order array functions, map constructors, ASOF JOIN, MATCH_RECOGNIZE, PIVOT, recursive CTEs and LATERAL are not implemented and will fail explicitly. Port incrementally and add features one at a time.
Why refuse a function instead of just running it?
Because element_at, filter, reduce, map and friends all exist underneath with different semantics. Running them would produce a number that looks right and is wrong. An explicit error costs you five minutes; a silently different result costs you the analysis.
Can I use SHOW TABLES or DESCRIBE?
Not currently. There is no catalog browser in the CLI. Use the dataset pages here, or ask the service operator for the table list and schemas. Only tables in the live catalog are queryable, and unknown names fail before a source query is issued.
How large can a query be?
Submit requests, including SQL and parameter JSON, are limited to 2 MiB. Execution is bounded by the engine class: 2 minutes on small, 30 minutes on medium, 6 hours on large.
The SQL contract, the translation table and every error shape are documented in full.