Queries as fallback
The primary way to feed a Plot block is a database view: the database team owns the SQL, the dashboard references the view name, and PlotPress runs SELECT * FROM <view> WHERE .... That’s the path you should use whenever it’s available.
When it isn’t — when you can’t get the view created in time, when you’re prototyping, or when the database doesn’t support views (e.g. an S3 bucket via DuckDB) — PlotPress falls back to a SQL file in the dashboard’s queries/ folder. Treat this as a workaround: it pulls data-shape decisions out of the database and into the dashboard, where they’re harder to reuse and harder to audit.
When to use it
Section titled “When to use it”✅ Acceptable:
- The database doesn’t expose views (S3, raw Parquet, some MongoDB collections).
- You’re prototyping and the view will be created next sprint.
- The query needs a parameter the view can’t express.
❌ Not acceptable as a long-term home for:
- Business-logic SQL that other dashboards or tools also need. Push it into a view.
- Joins across many tables that change often. Push them into a view.
- Anything you’d want to test in a dbt project.
File shape
Section titled “File shape”-- queries/monthly_revenue.sql-- @param year int default 2026
select date_trunc('month', invoice_date) as month, sum(amount) as revenue, currencyfrom invoiceswhere extract(year from invoice_date) = :yeargroup by 1, 3order by 1;Two conventions:
- Parameters are declared in
-- @paramheaders. Each line gives a name, a type, and a default. - Bind syntax is
:name. The backend rewrites these to the driver’s native placeholder ($1for Postgres,?for SQLite/MySQL,{name}for ClickHouse).
Parameter types
Section titled “Parameter types”| Type | Validated as | Bound as |
|---|---|---|
int | safe integer | int |
float | finite number | float |
string | UTF-8 string | string |
date | YYYY-MM-DD | date |
timestamp | RFC 3339 | timestamp |
bool | true/false | bool |
enum(a,b,c) | one of the listed values | string |
Reference from a Plot block
Section titled “Reference from a Plot block”```plot query=monthly_revenuePlot.barY(data, { x: "month", y: "revenue" })```query= instead of view=. The runtime knows which to look up.
What you can’t do
Section titled “What you can’t do”- No string interpolation.
:yearis a parameter;${year}is a typo. Anything that looks like dynamic SQL must be a parameter or a separate query file. - No DDL, no DML. Queries are select-only. The backend rejects any non-SELECT at parser level.
- No multi-statement queries. One statement per file.
These constraints exist to keep the security model small. The set of things a viewer can cause to happen is exactly the set of -- @param permutations across queries/*.sql.