Connect your data
Connectors for PostgreSQL, MySQL, MariaDB, ClickHouse, SQLite and DuckDB, and the model check.
A connector points the model at a database. Admins manage them on Settings > Connectors. One connector is active at a time; with none, the built-in demo database is used.
| Kind | Notes |
|---|---|
| PostgreSQL | Recommended. Structure, keys and small value sets read from the catalog and planner statistics, without scanning tables. SSL mode: disable, prefer, require, verify-ca, verify-full. |
| MySQL, MariaDB | Databases act as schemas; works with accounts that only have SELECT. |
| ClickHouse | No foreign keys: relationships are inferred from column names and marked unreliable. |
| SQLite, DuckDB | A file under CONNECTOR_FILES_DIR (default /app/data). DuckDB's access to other files is switched off. |
Workflow for each connector:
- Test: database version, account, readable tables, and a warning if the account can write or administer.
- Read structure: schemas (pick which), tables, columns, keys, row counts.
- Generate draft model (pick the tables): entities from tables, fields from columns, relationships from foreign keys (or names), sensitivity guessed from column names on the safe side. Everything generated is marked needs review: it is a starting point to which modellers add meaning, filters, calculated fields and knowledge.
- Use for data: makes it the active database. The app first reads the structure again and compares it with the published model; when tables of the model are missing, it shows the coverage and asks you to confirm.
Options per connector: statement timeout (default 15 s), row limit (default 500, also caps the console and agents), and whether agents may read rows at all (rows go to a language model; when off, query_data refuses and agents can still plan).
Passwords are stored encrypted and never shown again. A connector cannot point at the app's own database or at link-local or cloud-metadata addresses. Connections are read-only at the session level, with statement and idle timeouts. Activating, deactivating and every change go to the audit log.
What to enter for each kind#
| Field | PostgreSQL | MySQL, MariaDB | ClickHouse | SQLite, DuckDB |
|---|---|---|---|---|
| Name | any label | any label | any label | any label |
| Host | required | required | required | not used |
| Port | 5432 | 3306 | 8123 (HTTP) | not used |
| Database | the database name | optional (a MySQL server holds several databases; each acts as a schema) | optional, default default | not used |
| User, password | a read-only account | a read-only account | a read-only account | not used |
| SSL mode | disable, prefer (default), require, verify-ca, verify-full | same | require and above use HTTPS | not used |
| Schemas | optional list to restrict what is read | optional | optional | optional |
| Path | not used | not used | not used | the file, under CONNECTOR_FILES_DIR (default /app/data, which is the ./data folder next to your compose file) |
The host must be reachable from inside the app container: localhost there means the container itself. A connector cannot point at the app's own database or at link-local or cloud-metadata addresses.
Prepare a read-only account#
Connections are read-only at the session level, but a read-only account is the real protection, and the connector test warns if the account can write. Create one per database, with access to only the tables you want to describe. Adapt the names:
-- PostgreSQL
CREATE ROLE curltale_ro LOGIN PASSWORD '<a long random password>';
GRANT CONNECT ON DATABASE mydb TO curltale_ro;
GRANT USAGE ON SCHEMA public TO curltale_ro;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO curltale_ro;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO curltale_ro;
-- MySQL and MariaDB
CREATE USER 'curltale_ro'@'%' IDENTIFIED BY '<a long random password>';
GRANT SELECT ON mydb.* TO 'curltale_ro'@'%';
-- ClickHouse
CREATE USER curltale_ro IDENTIFIED BY '<a long random password>';
GRANT SELECT ON mydb.* TO curltale_ro;
For SQLite and DuckDB, put a copy of the file under ./data (or mount it read-only): the connection is read-only, but the test warns when the file is writable.
Sensitive columns need no special account: you mark them in the model (sensitivity, agent_access) and the server enforces it for every query. See Users, roles and access.
Step by step#
- Settings > Connectors > Add: choose the kind and fill in the fields above. The password is stored encrypted and never shown again.
- Test: it reports the database version, the account, how many tables it can read, and a warning if the account can write or administer.
- Read structure: schemas, tables, columns, keys and row counts. Pick which schemas to describe.
- Generate draft model: pick the tables. You get a draft in which every entity, field and relationship is marked needs review. Open Ontology > Entities, add meaning, filters, calculated fields and sensitivity, validate and publish.
- Use for data: makes the connector the active database. The app reads the structure again and compares it with the published model. If tables of the model are missing it shows the coverage and asks you to confirm.
- Open Data > Browse and Data > Model check to see the model against your real data.
Only one connector is active at a time. With none, the built-in demo database is used.
Checking the model against the data#
The Model check (Data menu) runs the published model against the database in use and reports per group:
- Structure: every model column exists; every table has data; foreign keys as expected.
- Relationships: each join, how many rows link and how many are orphans.
- Data-quality rules: each entity check's violations.
- Examples: each worked example is run with sampled parameters until it returns rows.
Every result carries the SQL that produced it. Results show counts and statuses, never values. "Attention" items are usually questions for the modellers (the rule text and the physical schema do not fully line up) rather than data bugs.
On the demo database the result is stored with each build, the build's own findings are included, and a modeller can run it again; structure and joins always hold, while your data-quality rules may not (generated data does not know your business rules). On a connector the check runs live every time. On databases other than PostgreSQL, a statement the model's SQL cannot be translated into is reported as a warning.