Adapters
The core knows nothing about DuckDB or Databricks. Adapters are separate
packages, discovered through the ontologiq.adapters entry point group, so
installing one is all it takes to use it.
pip install ontologiq-duckdb
# ontologiq.yml
adapter: duckdb
connection:
path: ecommerce.duckdb
Available adapters
| Package | Status |
|---|---|
ontologiq-duckdb | Working. Powers ontologiq init — zero credentials, zero setup. |
ontologiq-databricks | Placeholder. Reserves the name and validates the abstraction; every method raises. Real support is planned. |
One project uses one adapter. source.adapter is reserved in the format for
per-object overrides, but a value differing from the project adapter is a
validate error today rather than a half-working feature.
Connection settings
The connection block is adapter-specific and its values interpolate
{{ env.VAR }} at load time, so credentials never belong in git:
connection:
host: "{{ env.DATABRICKS_HOST }}"
token: "{{ env.DATABRICKS_TOKEN }}"
A referenced variable that is not set is an error naming the variable, not a silent empty string.
The word is connection, not profile, on purpose: to a dbt user “profile”
means an entry in ~/.dbt/profiles.yml, which this is not. Multi-target
(dev/prod) configuration is reserved for a later version.
Writing an adapter
Implement three methods. The protocol lives in
ontologiq.adapters.base:
from pathlib import Path
from typing import Any
class MyAdapter:
name = "mywarehouse"
sqlglot_dialect = "postgres" # any dialect sqlglot knows
def connect(self, connection: dict[str, str], project_root: Path) -> None:
"""Open a connection from the resolved `connection` block.
project_root lets you resolve relative paths against the project
rather than the current working directory.
"""
def execute(self, sql: str) -> list[dict[str, Any]]:
"""Run a query, return rows as dicts."""
def create_view(self, name: str, sql: str) -> None:
"""Create or replace a view in the target catalog."""
Register it in your package’s pyproject.toml:
[project.entry-points."ontologiq.adapters"]
mywarehouse = "ontologiq_mywarehouse:MyAdapter"
That is the whole contract. sqlglot_dialect is what the compiler uses to
render SQL, so the generated views come out in your dialect for free.
Things an adapter should know
- Quoting is not your problem. The compiler emits every identifier
quoted, because objects get called
order. servenever writes. The serving runtime wraps your adapter in a read-only proxy whosecreate_viewraises. Do not rely on being able to write from a query path.- Print nothing to stdout. During
serve, stdout is the JSON-RPC channel. The runtime redirects it around adapter calls, but a driver that spawns threads can still escape that. - Types are not introspected yet. Ontologiq does not know a column’s
type at compile time, so identity values are compared with a conservative
heuristic. Schema introspection (
validate --with-db) is on the roadmap and is where an adapter would contribute adescribe_table.
If you write one, please open an issue — the abstraction has only been proven against two warehouses, and the third will teach us something.