A source tells sqldash how to reach a database. It goes under the source: key of a
dashboard or of metrics.yaml, and it is always a flat list of fields. There are no
nested auth blocks and no driver-specific sub-schemas, so every engine is configured
the same way.
source:
type: snowflake
account: acme-prod
warehouse: WH
database: ANALYTICS
schema: PUBLIC
username: ${env:SNOWFLAKE_USER}
authentication: externalbrowser
Never write a password or token into the file. Reference it with ${env:VAR} or keep
it in a local profile, as described in Setup. sqldash lint warns about
a plaintext secret, and --strict turns that warning into a failure for CI. It also
flags unknown fields with a did-you-mean hint and tells you which extra to install when
a driver is missing.
Snowflake
source:
type: snowflake
account: acme-prod
warehouse: WH
database: ANALYTICS
schema: PUBLIC
role: ANALYST
username: ${env:SNOWFLAKE_USER}
authentication: externalbrowser
| field | required | what it is |
|---|---|---|
type |
yes | snowflake |
account |
yes | Your account identifier, such as acme-prod or xy12345.us-east-1. |
warehouse |
The virtual warehouse queries run on. | |
database |
The default database. | |
schema |
The default schema. | |
role |
The role to use after signing in. | |
username |
The user to sign in as. Usually ${env:VAR} or a profile. |
|
authentication |
externalbrowser, password, pat, or keypair. |
|
password |
Used with authentication: password. |
|
token |
A programmatic access token, used with authentication: pat. |
|
private_ |
Path to a private key file, used with authentication: keypair. |
|
private_ |
The key’s passphrase, if it has one. | |
connect_args |
Extra settings passed straight to the Snowflake driver. |
externalbrowser opens your SSO login in a browser and is the default when no secret is
set. Install the snowflake extra.
A role turns secondary roles off
Snowflake users get DEFAULT_SECONDARY_ROLES = ALL unless an admin changed it, and while
secondary roles are active every role granted to the user adds its privileges. Left that
way, role: REPORTING_READER would narrow nothing, and a table only your owner role can
read would still be readable through the source.
So when a source sets role:, or you pick a role in the query workspace, sqldash runs
USE SECONDARY ROLES NONE on every connection right after USE ROLE, and the source
gets exactly that role’s grants. A source with no role keeps your defaults. If the data
access really comes from secondary roles, such as a primary role that only grants the
warehouse, keep them on explicitly.
source: {type: snowflake, account: acme-prod, role: ANALYST, secondary_roles: true}
secondary_roles: false turns them off even without a role:.
Pick a role, database, and warehouse
The query workspace behind + Explore has a Sources section in its sidebar. For a Snowflake connection it shows three pickers, and each choice applies to the current query tab only.
- Primary role lists the roles your user can switch to, with their comments, and notes which secondary roles are active and that picking a role turns them off.
- Database lists the databases the role can see and sets where unqualified table
names resolve. The schema browser follows it. A table in another database is still
reachable as
DATABASE.SCHEMA.TABLE. - Warehouse lists the warehouses the role can see, with their sizes, and sets where the tab’s queries run.
Snowflake keeps the session’s warehouse and database across USE ROLE but only uses
them while the new role has a privilege on them, so switching to a role that lacks one
would quietly leave the session with no warehouse or no database. sqldash checks after
every switch. When the role cannot use the configured warehouse, it tries up to three
warehouses the role can see, keeps the first that works, and says so under the picker,
as in “ANALYST cannot use warehouse WH, so queries run on REPORTING_WH.” The database
falls back the same way, trying the account’s own databases before shared and
application ones. When nothing the role can see works, the picker says so and asks you
to pick another role.
A tile added from that tab keeps the choice. See Explore for how it is written into the dashboard.
Other engines get a Role picker where they have session roles, which covers Postgres, MySQL 8.0.19 and newer, MariaDB, Trino, and ClickHouse 24.4 and newer over its HTTP driver. SQL Server and Redshift apply all granted roles together, so the picker lists them without offering a switch. DuckDB, SQLite, BigQuery, Athena, and Databricks have no session roles, and the sidebar names what governs access instead, such as Google Cloud IAM or Unity Catalog grants. The database and warehouse pickers are Snowflake only.
BigQuery
source:
type: bigquery
project: acme-analytics
database: warehouse
| field | required | what it is |
|---|---|---|
type |
yes | bigquery |
project |
yes | The Google Cloud project that runs and bills the queries. |
database |
The default dataset. | |
options |
Extra connection settings, such as credentials_ for a service account key. |
sqldash signs in with Google Application Default Credentials, so run gcloud auth application-default login once,
or point at a service account key with options: {credentials_path: /path/to/key.json}.
Install the bigquery extra.
Databricks
source:
type: databricks
host: dbc-1234.cloud.databricks.com
http_path: /sql/1.0/warehouses/abc123
catalog: main
schema: analytics
token: ${env:DATABRICKS_TOKEN}
| field | required | what it is |
|---|---|---|
type |
yes | databricks |
host |
yes | The workspace host, without https://. |
http_path |
yes | The SQL warehouse’s HTTP path. |
token |
yes | A personal access token. Use ${env:VAR} or a profile. |
catalog |
The default Unity Catalog catalog. | |
schema |
The default schema. | |
port |
Defaults to 443. |
Copy the host and HTTP path from the SQL warehouse’s connection details page in
Databricks. Install the databricks extra.
Redshift
source:
type: redshift
host: acme.abc123.us-east-1.redshift.amazonaws.com
port: 5439
database: analytics
username: ${env:REDSHIFT_USER}
password: ${env:REDSHIFT_PASSWORD}
| field | required | what it is |
|---|---|---|
type |
yes | redshift |
host |
yes | The cluster or workgroup endpoint. |
port |
Usually 5439. | |
database |
yes | The database to connect to. |
username |
yes | The database user. |
password |
yes | The user’s password. |
Install the redshift extra.
Athena
source:
type: athena
host: us-east-1
schema: analytics
options: {s3_staging_dir: "s3://acme-athena-results/"}
| field | required | what it is |
|---|---|---|
type |
yes | athena |
host |
yes | The AWS region, such as us-east-1, or a full Athena endpoint. |
schema |
yes | The Athena database to query. |
options |
yes | Must include s3_staging_dir, the S3 location for query results. |
username |
An AWS access key id. Leave it out to use your default AWS credentials. | |
password |
The matching secret access key. |
Install the athena extra.
Postgres, MySQL, and MariaDB
source:
type: postgres
host: db.internal
port: 5432
database: analytics
username: ${env:PGUSER}
password: ${env:PGPASSWORD}
| field | required | what it is |
|---|---|---|
type |
yes | postgres, mysql, or mariadb |
host |
yes | The database host. |
port |
Defaults to the engine’s usual port. | |
database |
yes | The database to connect to. |
username |
yes | The database user. |
password |
The user’s password. | |
options |
Extra URL settings, such as sslmode: require for Postgres. |
Use type: mysql or type: mariadb with the same fields. Install the postgres or
mysql extra.
SQL Server
source:
type: mssql
host: sql.internal
port: 1433
database: analytics
username: ${env:MSSQL_USER}
password: ${env:MSSQL_PASSWORD}
options: {driver: "ODBC Driver 18 for SQL Server"}
| field | required | what it is |
|---|---|---|
type |
yes | mssql |
host |
yes | The server host. |
port |
Usually 1433. | |
database |
yes | The database to connect to. |
username |
yes | The database user. |
password |
The user’s password. | |
options |
yes | Must include driver, the name of the installed ODBC driver. |
SQL Server connects through pyodbc, so install pyodbc alongside sqldash along with
an ODBC driver for SQL Server.
Trino and ClickHouse
source:
type: trino
host: trino.internal
port: 8080
database: hive
username: ${env:TRINO_USER}
| field | required | what it is |
|---|---|---|
type |
yes | trino or clickhouse |
host |
yes | The server host. |
port |
The server port. | |
database |
For Trino the catalog, for ClickHouse the database. | |
username |
The user to connect as. | |
password |
The user’s password, if the server requires one. |
Install the trino or clickhouse extra.
DuckDB and SQLite
source:
type: duckdb
database: analytics.duckdb
| field | required | what it is |
|---|---|---|
type |
yes | duckdb or sqlite |
database |
A file path relative to the project, or :memory:, which is the default. |
|
attach_files |
DuckDB only. true turns local CSV and Parquet files into views. |
|
base_dir |
DuckDB only. The folder the source’s files resolve against, instead of the dashboard’s own folder. | |
external_ |
DuckDB only. true lets SQL read files outside the project. Off by default. |
Neither needs an extra.
Query local CSV and Parquet files
source: {type: duckdb, attach_files: true}
With attach_files: true, every .csv and .parquet file next to the dashboard, and
in its data/ folder, becomes a view named after the file. You can then query it
directly.
SELECT category, SUM(amount) FROM orders GROUP BY 1
That is how the demo works. Commit a small extract next to a dashboard and anyone who clones the repo can reproduce it. Only local folders are scanned. Remote object storage is not attached.
DuckDB reads only the project
A warehouse source is bounded by the credential it connects with. A DuckDB source has no
credential, and anyone who can load a served dashboard can type SQL into the query
workspace, so sqldash confines a DuckDB source to two folders and everything under them,
the folder holding its database: file and the folder its files resolve against. That
second one is base_dir when the source sets it and the dashboard’s own folder
otherwise. read_csv, read_text, read_blob, and glob outside them fail with a
permission error that names what the source is confined to.
If a project genuinely reads files from elsewhere, such as a shared drive or a .duckdb
file in another tree, say so on the source.
source: {type: duckdb, database: app.duckdb, external_access: true}
That switch is not narrow. It hands every viewer of every dashboard on that source the
full file access of whoever runs the server, so prefer pointing base_dir at the folder
you want read.
Any other database
If SQLAlchemy has a dialect for it, sqldash can connect with a raw connection URL. Write the whole source as the URL.
source: "trino://analyst@trino.internal:8080/hive"
Keep secrets out of the URL with ${env:VAR}, as in
"postgresql+psycopg://${env:PGUSER}:${env:PGPASSWORD}@db.internal/analytics".
Inside a map of several sources, give the URL its own field.
source:
warehouse: {type: snowflake, account: acme-prod, default: true}
events: {url: "duckdb:///events.duckdb"}
Several sources in one dashboard
A dashboard that reads two databases names each connection.
source:
warehouse:
type: snowflake
account: acme-prod
default: true
app_db:
type: postgres
host: db.internal
database: app
A tile picks one with source: app_db. A tile that names none runs against the entry
marked default: true. A map with a single entry needs no mark, but with several
entries and no mark sqldash refuses to guess, because picking by file order would let
a reordering quietly repoint every tile.
sources: is the older spelling of this map. Files that use it still load, but new
files should use source:.
Inspect and test
sqldash source list --json # every source, credentials redacted
sqldash source test # connect and SELECT 1 on each, report latency
sqldash source describe --json # tables and columns, the raw material for metrics
Who can see what
sqldash has no login of its own today. sqldash serve runs on your machine with your
credentials, so the warehouse’s grants, masking, and audit apply to every query, for
every person. Anyone who can reach the served page can run SQL in the query workspace
with those credentials, which is why serve binds to 127.0.0.1 by default.