Queries

Data blocks work through SQL queries to the connected sources. A query is described in the block configuration, validated before execution, and its result is cached.

Execution and validation

  • execution — POST /api/query/execute against any connected source;
  • validation before execution — POST /api/query/validate: syntax, columns, sources;
  • every query is capped at 30 seconds and 10,000 rows — protection from accidental “SELECT * FROM huge_table”;
  • the query description supports Scriban document variables.

Caching

  • cached results speed up reopening a report;
  • cached result statistics — GET /api/query/cache/statistics;
  • cleanup — POST /api/query/cache/clear.

Server-side calculations

Heavy analytics is computed on the server: histograms (POST /api/query/histogram) and box plots (POST /api/query/boxplot) do not ship the raw data to the client — only the finished result travels.

Processing the result with a script

A query result can be additionally processed by your own Python script: rename columns, convert amounts into another currency, filter rows, compute an extra metric. The script receives the finished table and returns the same kind of table — only reworked.

  • the processing runs after the query but before styling: a block’s styling overrides are manual corrections, and they stay stronger;
  • the same processing applies everywhere: on screen, in validation, in the PDF export and in alert rules — the numbers match everywhere;
  • if the script fails, the query counts as failed and shows the reason: wrong data never gets into the report.

How to set up scripts — in the Python Scripts section.

Binding to a block

A query lives in the block configuration and is bound by queryId. The validator checks that the query and its source exist — details in the Validation & Auto-Fix section.

Values in a query

  • placeholders like @name and :name are passed to the database as query parameters — not by gluing text, so a stray value cannot “append” SQL;
  • the value comes from document variables, the report’s reader settings, header filters and a click on a chart; if the name is set in the report’s address, it wins;
  • when no value is set, the parameter is empty (NULL): the query doesn’t crash — the “no filter selected” condition simply doesn’t trigger;
  • a list of values is also passed as a single parameter — each database receives it its own way.

AI and performance

Don’t want to write SQL? Describe in words what you need — the AI will write or fix the query (details in the agent in the report). Performance tips: filter by dates, compute aggregates in SQL rather than in the block, and use a row limit.

← Back to the documentation index