Skip to main content

Working with Multiple Connectors

A profile in ~/.wvlet/profiles.json describes a working environment and can activate several connectors at once — for example a production Trino cluster next to a local DuckDB database:

~/.wvlet/profiles.json
{
"profiles": [
{
"name": "dev",
"connectors": [
{
"name": "td",
"type": "trino",
"default": true,
"host": "api-presto.treasuredata.com",
"user": "${TD_API_KEY}",
"catalog": "td",
"schema": "sample_datasets"
},
{ "name": "local", "type": "duckdb", "catalog": "memory", "schema": "main" }
]
}
]
}

The connector marked "default": true (or the first one) is the engine your queries run on when the session starts.

Referencing tables through a connector name

Table references can name a connector explicitly. The first identifier is checked against the connector names of the active profile:

-- <connector>.<table>: uses the connector's configured schema
from td.www_access

-- <connector>.<schema>.<table>
from td.sample_datasets.www_access

-- <connector>.<catalog>.<schema>.<table>: addresses a catalog other than the
-- configured one, for engines spanning multiple catalogs (e.g. Trino)
from trino.tpch.tiny.nation

Models, CTEs, and query aliases take precedence over connector names, and connector names take precedence over schema names of the default catalog. Since you choose connector names yourself, rename the connector if it collides with a schema you need to address.

Queries execute on one SQL engine at a time: referencing another engine connector reports an error suggesting use <connector>. Tables of source connectors (services without a SQL engine, like Slack) are staged into the active engine automatically, so from slack.channels works from any engine. Inside flows, cross-connector references are staged automatically too, and each stage can pick its engine with stage <name> on <connector>. Cross-engine joins in ad-hoc queries are planned as a follow-up.

Switching connectors with use

The use statement switches the active connector for subsequent statements. Its catalog then drives table resolution and the SQL dialect:

use td -- switch to the td connector
use local -- switch to the local DuckDB connector
use connector td -- explicit form, for when a name collides with a schema
use td.sample_datasets -- switch connector and schema in one statement

Bare names are resolved connector-first: use analytics switches to a connector named analytics when the profile defines one, and otherwise behaves like use schema analytics (see CLI reference for the schema forms).

The switch is scoped to your session: in the web UI each browser page is its own session, so use statements of one client never change the engine, catalog, or schema of another.

Calling connector tools

Connectors can expose callable tools (MCP-shaped methods) beyond tables and SQL execution. The call statement invokes a tool ad hoc, outside of a flow:

call slack.post_message(channel: '#reports', text: 'daily report done')

Arguments are named and take literal values, following the tool's input schema. The statement returns a single-row summary (connector, tool, status, content) that composes with query operators and test statements like any query:

call slack.post_message(channel: '#reports', text: 'ping')
test _.columns should contain 'status'

Inside flows, use activate('<connector>', tool: ...) instead to deliver a stage's output through a tool (see Flows).