Skip to content

API Reference

Selected internal modules, generated from docstrings.

Ports

Database ports: what the application needs from a SQL database.

DatabaseGateway

Bases: Protocol

Full database port: connection lifecycle, introspection and CRUD.

is_connected property

Whether the underlying pool is open.

connect() async

Open the connection pool.

delete(table, key) async

Delete one record; True when a row was removed.

disconnect() async

Close the connection pool.

execute_query(query, params=None) async

Run a SQL statement (:name placeholders) and return rows as dicts.

get_table_schema(table) async

Describe a table (columns, primary key, foreign keys, indexes).

get_tables() async

List base tables.

insert(table, data) async

Insert a record and return it.

row_estimates(tables) async

Planner row-count statistics per table (never a COUNT(*)).

Returns None for a table whose statistics are unknown (never analyzed) or that does not exist.

select(table, columns=None, filters=None, pagination=None, sort=None) async

Select records and the total count.

select_by_id(table, key, columns=None) async

Select one record by primary key.

stream_select(table, columns=None, filters=None, sort=None, batch_size=5000, limit=None, statement_timeout_ms=0)

Stream matching rows in batches (no COUNT, no OFFSET; flat memory).

update(table, key, data) async

Update one record and return it, or None when it does not exist.

DatabaseGatewayFactory

Bases: Protocol

Builds a gateway for a configured database (the adapter picks the driver).

create(config)

Instantiate (but do not connect) a gateway for config.

get_supported_types()

Database type names this factory can build.

SqlReader

Bases: Protocol

The narrow read port used by metadata readers and the raw-query use case.

execute_query(query, params=None) async

Run a SQL statement (:name placeholders) and return rows as dicts.

Catalog persistence port.

CatalogRepository

Bases: Protocol

Stores and retrieves whole catalogs by database name.

delete(db_name)

Remove a catalog; True when it existed.

get_index()

Summary index of stored catalogs.

list_catalogs()

Names of every stored catalog.

load(db_name)

Load a catalog, or None when it does not exist.

load_or_raise(db_name)

Load a catalog or raise CatalogNotFoundError.

save(catalog, format=None)

Persist a catalog; returns where it was written.

Text-generation port (an LLM behind a provider-agnostic interface).

TextGenerator

Bases: Protocol

Generates text/JSON from prompts; closed when the use case is done.

close() async

Release provider resources.

generate(prompt, system_prompt=None, temperature=None, max_tokens=None, response_format=None) async

Generate a completion.

generate_json(prompt, system_prompt=None) async

Generate a completion expected to be a JSON document.

Port: checking the joins a query writes against the keys that really exist.

Probe = Callable[[TableRef, str, TableRef, str], float | None] module-attribute

(table, column, table, column) -> the share of sampled values the two columns have in common, or None when it cannot be measured.

SqlGrounder

Bases: Protocol

ground(sql, tables, graph, probe, repair=False)

Verdicts on the column-to-column joins of sql.

tables is keyed by the reference as the query writes it (an unqualified name has an empty source). Only joins where a column is a known key are judged; a join on anything else is business logic the graph was never meant to model. A column that cannot be attributed to exactly one table is left alone: missing information never flags.

With repair, a verdict that has exactly one safe fix is applied and marked repaired, and the returned SQL is checked again. What is left in unresolved could not be fixed; the caller decides whether such a query may run.

Ports: reading what a database was asked before, and mining it for expressions.

ExpressionChecker

Bases: Protocol

Holds an expression a reviewer wrote to what a measure may be.

check(expression, columns)

expression as the engine will run it, and the columns it reads.

columns maps the table's column names to their kinds (type_kind: int, float, bool, str, date, ...). The expression is what goes inside an aggregate, over those columns only: no subquery, aggregate, window or parameter, and something that can be added up.

Raises:

Type Description
MeasureError

Saying what is wrong with it.

ExpressionMiner

Bases: Protocol

Finds the reusable scalar expressions in a statement.

mine(sql, dialect, columns)

Expressions in sql (written in dialect) over one known table each.

columns maps each table of the catalog to its column names; an expression is returned only when every column it reads can be placed in exactly one of them, and when it holds no parameter, subquery, aggregate or window. A statement that does not parse yields nothing.

QueryHistorySource

Bases: Protocol

A database's own record of the statements it ran and the views it holds.

recent_statements(limit=500) async

The most-run SELECT statements, most frequent first.

Raises:

Type Description
HistoryUnavailableError

The engine keeps no such record, or this user may not read it.

view_definitions() async

The definition of every view in the configured schema.

Raises:

Type Description
HistoryUnavailableError

As above.

Port: turning a semantic query into SQL.

SemanticCompiler

Bases: Protocol

Generates the SQL that answers a semantic query.

compile(query, tables=None)

SQL for query, reading each table from tables or its own name.

tables maps a table to where it actually lives in the store — a slice, usually, whose name encodes the rows it holds. The compiler writes those names in directly rather than emitting the original name and having someone rewrite it afterwards: the SQL is generated for the store's dialect, and re-parsing it under a neutral one rewrites string literals and drops quoting.

Implementations must emit a single SELECT statement that passes SqlValidator.validate, quote every identifier, and never inline a value that did not come from the query's own literals.

compile_joined(query)

SQL for a query whose dimensions or filters read referenced tables.

One flat SELECT joining along query.joins, naming every table by its own name: unlike compile, the result goes through the query pipeline, which loads what it reads, applies the caller's row rules and masks to each table and records the access.

Composition root

Services and port implementations for one configuration.

database(name)

Configuration of the database called name (404-style error if unknown).

open_analysis(db_name, *, gateway=None) async

Yield an analysis service for db_name.

A gateway passed in is reused (and not closed); otherwise one is opened for the duration. The text generator is always created and closed here.

Raises:

Type Description
DatabaseNotConfiguredError

If db_name is not configured.

open_gateway(db_config) async

Create, connect and finally disconnect a gateway for db_config.

open_light_model() async

Yield the model for small jobs (the light one when configured), closed after.

open_mining(db_name) async

Yield a history-mining service for db_name, with its own gateway and model.

Raises:

Type Description
DatabaseNotConfiguredError

If db_name is not configured.

RuntimeError

If this container was built without a miner.

pipeline()

Pipeline service bound to this container.

Wire the default adapters; any of them can be replaced (tests, embedding).

Build a ready-to-use FusionApp from settings (defaults: DuckDB in-memory, in-process cache, threading scheduler, Warp source registry).

Configuration

Check security-sensitive configuration for production deployments.

Returns a list of human-readable violation messages. The list is only populated when app_env == "production"; in any other environment the same options are legitimate defaults and no violations are reported.

The caller is expected to refuse startup (fail-safe) when the returned list is non-empty.

Parameters:

Name Type Description Default
settings Settings

Loaded application settings.

required
app_env str

The current APP_ENV value.

required
cors_origins list[str] | None

The effective CORS allowlist (e.g. from CORS_ORIGINS).

None

Returns:

Type Description
list[str]

A list of violation messages (empty when the configuration is safe).

SQL identifiers and parameters

Centralized SQL identifier validation and quoting.

Every dynamic identifier (table or column name) that gets interpolated into a SQL string MUST pass through :func:sanitize_identifier / :func:quote_identifier. Values are always sent as bound parameters and must never go through these helpers. Keeping this logic in one place avoids divergent, weaker copies (e.g. str.replace-based "sanitizers") across adapters.

quote_identifier(name, dialect='postgresql')

Validate and quote an identifier for the given SQL dialect.

Parameters:

Name Type Description Default
name str

The identifier to validate and quote.

required
dialect str | Dialect

Target dialect name or :class:Dialect (mysql/mariadb use backticks, mssql/sqlserver square brackets, everything else ANSI double quotes).

'postgresql'

Returns:

Type Description
str

The safely quoted identifier.

Raises:

Type Description
ValueError

If the identifier is not valid (see :func:sanitize_identifier).

sanitize_identifier(name, extra_chars='')

Validate a SQL identifier (table/column name).

Parameters:

Name Type Description Default
name str

The identifier to validate.

required
extra_chars str

Characters this engine additionally allows after the first one. Oracle passes "$#", because they are legal there and the data dictionary generates them (an identity column's sequence is named ISEQ$$_73346). The double quote is never allowed for any engine, which is what keeps a quoted identifier unescapable.

''

Returns:

Type Description
str

The identifier unchanged when it is safe.

Raises:

Type Description
ValueError

If the identifier contains anything other than ASCII letters, digits, underscores and extra_chars (and does not start with a digit). This is what prevents identifier/SQL injection through dynamic table and column names.

Rewrite :name placeholders into the dialect's positional form.

Parameters:

Name Type Description Default
query str

SQL text with :name placeholders.

required
params dict[str, Any] | None

Values by name. None/empty leaves the query untouched.

required
dialect str | Dialect

Dialect name or :class:Dialect: postgresql ($N), mysql (%s), mssql/odbc (?).

required

Returns:

Type Description
tuple[str, list[Any]]

The rewritten SQL and the positional values.

Raises:

Type Description
ValueError

On an unknown dialect, a placeholder without a value, or a value without a placeholder.

What a reviewer certifies

Business terms: what people call a table, its columns and the values they hold.

A term is written by a model once per table and then reviewed, like the rest of the catalog. Until someone certifies it, nothing reads it: the semantic model, the question planner and the published context all take certified terms of an approved catalog and nothing else.

ColumnAttribute

Bases: BaseModel

The words for one column, and for the values it stores.

MeasureError

Bases: ValueError

A measure a reviewer wrote that cannot be one, with the reason why.

SqlAttribute

Bases: BaseModel

A measure that is an expression over one table's columns.

Certified separately from its term: an expression decides what a number means, which is a bigger claim than a synonym.

Term

Bases: BaseModel

One business concept: a name, the words for it, and where it lives.

attribute(table, column)

The words for table.column, if the term has any.

certified_sql(table)

The expressions on table a reviewer signed off.

carry_over(fresh, previous, columns)

fresh terms, with the certified ones of an earlier catalog kept as they were.

A certified term is a reviewer's work, and re-analysing the database must not replace it with a new guess. It is kept when every table it covers is still there, minus the columns that are not. columns maps each table of the new catalog to its column names.

clean_words(words, *avoid)

Words as a model or a person wrote them, made usable.

Not a list becomes none; blanks, repeats and the name itself are dropped.

The proof gate: a repaired statement differs from the original by one literal.

When a condition compares a column with a value it does not hold ('Premium' where the data says 'premium'), the fix is to swap that one string. Whoever proposes the fix, a rewriter here or a model elsewhere, is not trusted to have changed only that: the candidate runs only if this proves it. After the literal-repair gate in NVIDIA Auto Ontology.

Parser-free, like the rest of sql_text: the check must not depend on a candidate being something a particular parser round-trips.

prove_substitution(original_sql, candidate_sql, absent, present, validate)

Whether candidate_sql is original_sql with absent replaced by present.

True only when all of these hold: the original had the literal absent; the candidate has present everywhere the original had absent and is otherwise the same literals in the same order; with literals blanked the two statements are identical; and validate (the guardrails every query passes) accepts the candidate. Only string literals are covered.

split_literals(sql)

sql with every string literal blanked, and the literals in order.

Quoted identifiers stay in the skeleton: a candidate that renamed a column is not the same statement.