Connect a warehouse
Read-only connection steps for Snowflake, BigQuery, PostgreSQL, and MySQL, plus the other warehouse engines.
Updated
Query Runner connects to your database with a native driver. It needs read-only access. It runs parameterized SELECT queries that the engine compiled.
The engine value is postgresql, mysql, clickhouse, redshift, sqlserver, databricks, snowflake, bigquery, or duckdb. The steps below show four of them. The same keys apply to the rest.
Table, field, and value rules run on PostgreSQL only. For every other engine, set allow_unpoliced_backends: true on the key’s policy. That policy then allows every table the database user can read.
All database credentials stay in the Query Runner environment. They never go to the engine.
1. Snowflake
Create a read-only role and user
Run this script in Snowflake Worksheets:
-- 1. Create a dedicated role and warehouse
CREATE ROLE datahashi_runner_role;
CREATE WAREHOUSE datahashi_wh WITH WAREHOUSE_SIZE = 'XSMALL' AUTO_SUSPEND = 60 AUTO_RESUME = TRUE;
GRANT USAGE ON WAREHOUSE datahashi_wh TO ROLE datahashi_runner_role;
-- 2. Grant read access to the database and schema
GRANT USAGE ON DATABASE analytics_db TO ROLE datahashi_runner_role;
GRANT USAGE ON SCHEMA analytics_db.public TO ROLE datahashi_runner_role;
GRANT SELECT ON ALL TABLES IN SCHEMA analytics_db.public TO ROLE datahashi_runner_role;
GRANT SELECT ON FUTURE TABLES IN SCHEMA analytics_db.public TO ROLE datahashi_runner_role;
-- 3. Create runner user
CREATE USER datahashi_runner PASSWORD = 'secure_password_here' DEFAULT_ROLE = datahashi_runner_role DEFAULT_WAREHOUSE = datahashi_wh;
GRANT ROLE datahashi_runner_role TO USER datahashi_runner;
Query Runner configuration
In config.yaml:
warehouses:
snowflake_main:
engine: snowflake
dsn_env: SNOWFLAKE_DSN
Set the environment variable:
SNOWFLAKE_DSN="datahashi_runner:secure_password_here@xy12345.us-east-1/analytics_db/public?warehouse=datahashi_wh&role=datahashi_runner_role"
The key’s policy must set allow_unpoliced_backends: true. Snowflake does not apply table, field, or value rules.
2. Google BigQuery
Create a service account
- In the Google Cloud Console, go to IAM & Admin → Service Accounts.
- Create a service account named
datahashi-query-runner. - Assign these roles:
- BigQuery User (to run query jobs)
- BigQuery Data Viewer (to read table contents)
- Create a JSON service account key. Download it.
Query Runner configuration
In config.yaml:
warehouses:
bigquery_main:
engine: bigquery
dsn_env: BIGQUERY_DSN
schemas: [analytics, marketing]
Set BIGQUERY_DSN to the connection string the BigQuery driver accepts. Do not add a project key. The runner rejects unknown keys. The policy for this key must set allow_unpoliced_backends: true.
3. PostgreSQL
Create a read-only user
Connect to PostgreSQL as a superuser:
-- 1. Create runner user
CREATE USER datahashi_runner WITH PASSWORD 'secure_password_here';
-- 2. Grant connect and schema usage
GRANT CONNECT ON DATABASE analytics_db TO datahashi_runner;
\c analytics_db
GRANT USAGE ON SCHEMA public TO datahashi_runner;
-- 3. Grant SELECT on existing and future tables
GRANT SELECT ON ALL TABLES IN SCHEMA public TO datahashi_runner;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO datahashi_runner;
Query Runner configuration
In config.yaml:
warehouses:
postgres_main:
engine: postgresql
dsn_env: POSTGRES_DSN
schemas: [public]
Set the DSN:
POSTGRES_DSN="postgres://datahashi_runner:secure_password_here@db.internal:5432/analytics_db?sslmode=require"
4. MySQL
Create a read-only user
Connect to MySQL as an administrator:
CREATE USER 'datahashi_runner'@'%' IDENTIFIED BY 'secure_password_here';
GRANT SELECT, SHOW VIEW ON analytics_db.* TO 'datahashi_runner'@'%';
FLUSH PRIVILEGES;
Query Runner configuration
In config.yaml:
warehouses:
mysql_main:
engine: mysql
dsn_env: MYSQL_DSN
schemas: [analytics_db]
Set the DSN. Keep parseTime=true:
MYSQL_DSN="datahashi_runner:secure_password_here@tcp(db.internal:3306)/analytics_db?parseTime=true&sslmode=preferred"
The key’s policy must set allow_unpoliced_backends: true. MySQL does not apply table, field, or value rules.
Test connectivity
Verify that the runner can reach your warehouse:
curl -X POST http://localhost:8443/v1/ping \
-H "Authorization: Bearer <your-runner-key>" \
-H "Content-Type: application/json" \
-d '{"request_id":"ping-1","tenant_id":"local","source":"postgres_main"}'
There is no GET /v1/ping. Use GET /v1/readyz?source=postgres_main for the same check. source is required when the runner has more than one warehouse.
Expected response:
{
"status": "ok"
}