> For the complete documentation index, see [llms.txt](https://v2.dataos.info/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://v2.dataos.info/references/v1/engine-guide/trino-1.md).

# Trino

Trino is a distributed SQL query engine for analytics across data lakes, databases, and object storage. Vulcan connects to Trino with the `trino` engine adapter, federating reads across many catalogs and materializing output into a lakehouse catalog. This page is the shared reference; the three deployment shapes each get their own page because cluster ownership changes how you connect, configure, and operate.

| Property                  | Value                                                    |
| ------------------------- | -------------------------------------------------------- |
| Engine adapter type       | `trino`                                                  |
| Model dialect             | `trino`                                                  |
| Identifier casing         | Lowercase for unquoted names, unlike Snowflake and Spark |
| Tested Vulcan image       | `tmdcio/vulcan-trino:0.228.1.26`                         |
| Tested Trino server image | `tmdcio/trino:5.1.12` for a dedicated cluster            |
| Stack                     | `vulcan+trino:1.0`                                       |

## When to use Trino

Reach for Trino when you need to query across multiple source systems, such as an Iceberg lakehouse, Postgres, and Snowflake, in one engine. Materialize the result into a lakehouse catalog. Trino is a massively parallel processing query engine, not a storage engine: persisted tables live in external systems, and performance is shaped by source latency, federation width (how many catalogs a query spans), and shuffle/exchange size, not by row count alone.

**Supported model kinds:** `VIEW`, `FULL`, `SEED`, `INCREMENTAL_BY_TIME_RANGE`, and `INCREMENTAL_BY_PARTITION`. Federated sources are the Iceberg lakehouse, Postgres, and Snowflake, plus Databricks as a read-only source (via Iceberg REST against Unity Catalog).

## The three deployment shapes

| Shape                               | Page                                                                          | Cluster ownership                                                                                                                             | Connect via                                                                                                                   |
| ----------------------------------- | ----------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| Dedicated cluster                   | [Dedicated cluster](/references/v1/engine-guide/trino-1/dedicated-cluster.md) | Vulcan provisions and owns a coordinator and workers, one cluster per Data Product.                                                           | A `vulcan` resource with `spec.engine: trino` and a `spec.trino` block.                                                       |
| Minerva (shared) / external cluster | [Minerva](/references/v1/engine-guide/trino-1/minerva-1.md)                   | A shared, DataOS-managed Minerva cluster, or a pre-existing Trino/Starburst cluster outside DataOS. In either case, Vulcan doesn't manage it. | A `vulcan` resource with `spec.engine: trino` and **no** `spec.trino` block, pointing at the cluster's endpoint via a secret. |
| External cluster                    | [External cluster](/references/v1/engine-guide/trino-1/external-trino.md)     | A pre-existing Trino, Starburst, or self-hosted cluster outside DataOS.                                                                       | A `vulcan` resource pointing at the cluster's host and port.                                                                  |

All three shapes run the same model, semantic, metric, and data-quality code. Only `config.yaml`, the deploy resource, and the connection secrets differ.

## Common rules across three shapes

These hold no matter which shape you deploy:

* Use `type: trino` in the gateway connection and `dialect: trino` in `model_defaults`.
* Identifiers are lowercase. Quote with `"` only when a name collides with a reserved word. Use fully qualified three-part names (`catalog.schema.table`) for every model name, source read, and DQ `depends_on` reference.
* Prefer `TIMESTAMP(6)` for Iceberg-backed timestamp columns: declare the precision your catalog expects.
* Use a half-open window (`>= @start_dt AND < @end_dt`), not `BETWEEN`, on time-range incremental, to avoid reprocessing or duplicating rows at the window boundary.
* Store passwords and tokens in environment variables locally, and in DataOS secrets when deploying.
* Declare cross-catalog sources the linter can't resolve in `external_models.yaml`, or it throws `Table not found` and lineage stops at the model boundary:

  ```yaml
  - name: <catalog>.<schema>.<table>
    columns:
      <column_1>: <TYPE>
      <column_2>: <TYPE>
  ```
* Add the deploy manifest filename to `ignore_patterns` in `config.yaml` so Vulcan never parses it as a model.

## Models, semantics, and federation

SQL models compile to Trino SQL. The coordinator plans queries; workers execute them. Materialized output (`FULL` and incremental kinds) lands in the default catalog. This is the first entry in `spec.depots[]` on a dedicated cluster, or whatever `TRINO_CATALOG` resolves to on Minerva/external. Source reads, meanwhile, can federate across every mounted catalog.

The federated `VIEW` is Trino's superpower. A staging view can read directly from a remote source catalog:

```sql
MODEL (
  name lakehouse.staging.customers,
  kind VIEW,
  grain customer_id,
  columns (customer_id BIGINT, name VARCHAR, email VARCHAR, region VARCHAR)
);
SELECT customer_id, name, email, region
FROM abfsslhdepot.azure_spark_dp_bronze.customers;   -- reads the Iceberg source catalog
```

| Model kind                   | Trino operation                    | Notes                                                            |
| ---------------------------- | ---------------------------------- | ---------------------------------------------------------------- |
| VIEW                         | `CREATE VIEW` (or logical staging) | Federated staging layer. Read across mounted catalogs here       |
| FULL                         | `CREATE TABLE AS` / replace        | Good for dimensions, derived aggregates, rebuildable marts       |
| SEED                         | File-backed reference data         | Small reference tables                                           |
| INCREMENTAL\_BY\_TIME\_RANGE | Insert/overwrite by time window    | Keep `time_column` set; filter with `>= @start_dt AND < @end_dt` |
| INCREMENTAL\_BY\_PARTITION   | Insert/overwrite by partition key  | Best when the partition key is the natural restatement boundary  |

Declare explicit joins in semantic models. Trino broadcasts or redistributes for joins, and an unconstrained cross-catalog join is the biggest avoidable latency risk on a federated cluster. Identifiers in semantics and metrics follow the same lowercase rule as models.

For metrics, `COUNT(DISTINCT …)` often requires distributed aggregation and can be one of the most expensive operations on large, high-cardinality data. Pre-aggregate into a mart, or use `approx_distinct` where an exact count isn't required (it introduces estimation error).

## Data quality

Vulcan quality runs as Trino SQL against the catalogs: model `assertions` and `profiles` during materialization, standalone `AUDIT(...)` after materialization, and `kind: dq` rules after the run or on a schedule.

| Layer                       | Where it runs                       | Trino cost           | Catches                        |
| --------------------------- | ----------------------------------- | -------------------- | ------------------------------ |
| Linter                      | Locally, before execution           | None                 | Authoring-time mistakes        |
| Assertions (`MODEL(...)`)   | Trino, during materialization       | Counted in the run   | Every run                      |
| Profiles (`profiles (...)`) | Trino, during the run               | One scan per column  | Distribution issues            |
| Unit tests (`tests/`)       | Locally (DuckDB)                    | No cluster cost      | Pre-deploy regressions         |
| Audits (`AUDIT(...)`)       | Trino, after materialization        | One query per audit  | Post-run relationship failures |
| Data quality (`kind: dq`)   | Trino SQL, after run or on schedule | One or more queries. | Drift, freshness, accuracy     |

Use fully qualified `catalog.schema.table` names in all DQ and audit SQL, keep `failed rows` queries narrow with a `samples limit`, and only profile operationally useful columns. Profiling high-cardinality columns on a remote Postgres or Snowflake catalog pushes load onto the source.

## Endpoints

The Trino stack serves REST, GraphQL, and MySQL-wire endpoints. Endpoint queries push execution to Trino, so size the API track separately from the cluster. Expensive semantic queries still consume cluster compute. Keep API memory at or above 2 GiB for large result sets; the MySQL-wire sidecar enforces `VULCAN_API_QUERY_TIMEOUT` (default 300 seconds).

## Metadata scanning

DataOS scans the depots behind the Trino catalogs (not Trino itself), plus Vulcan's parsed model graph, for lineage. On a dedicated cluster, grant the scanner principal `purpose: scan` on each source depot in `spec.depots[]`. On Minerva/external, the DP owns no depots. The catalogs are already mounted by whoever manages the shared or external cluster, so scanning is their responsibility. Coordinate with that team if lineage is missing for a catalog you read from. The scanner runs every 6 to 12 hours; lineage from model runs is available immediately after a successful `vulcan run`.

## Troubleshooting that applies to all three shapes

| Symptom                                       | Likely cause                                                                           | Fix                                                                                                                   |
| --------------------------------------------- | -------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
| `Table not found` for a source                | Cross-catalog source not declared, or wrong catalog name                               | Add it to `external_models.yaml`; use `catalog.schema.table`                                                          |
| `vulcan plan` works locally, fails in DataOS  | Depot/catalog missing or misnamed, or the wrong default catalog                        | Verify with `SHOW CATALOGS`; check what resolves as the default                                                       |
| Iceberg timestamp precision mismatch          | `TIMESTAMP` precision differs from what the catalog expects                            | Declare the precision the catalog expects (`TIMESTAMP(6)` preferred)                                                  |
| Catalog present but queries fail              | Missing credentials, or permission/schema/warehouse issues that only surface on access | `SHOW SCHEMAS FROM <catalog>;` then `SELECT 1 FROM <catalog>.<schema>.<table> LIMIT 1;`. Fix credentials and re-apply |
| Time-range incremental reprocesses everything | Missing/wrong `time_column`, or no `@start_dt`/`@end_dt` filter                        | Set `time_column` and filter the source with the interval macros                                                      |
| Deploy manifest parsed as a model             | `*-deploy.yaml` not ignored                                                            | Add it to `ignore_patterns` in `config.yaml`                                                                          |
| Production `vulcan migrate` fails             | Platform-managed state store not provisioned or unreachable                            | Escalate to the SRE/platform team to check the state store, then re-run                                               |

Shape-specific failure modes (cluster formation, JVM heap, plugin loading, connector setup) live on the [Dedicated cluster](/references/v1/engine-guide/trino-1/dedicated-cluster.md) and [Minerva](/references/v1/engine-guide/trino-1/minerva-1.md) pages.

## Related

* [Dedicated cluster](/references/v1/engine-guide/trino-1/dedicated-cluster.md) for the Vulcan-managed cluster.
* [Minerva](/references/v1/engine-guide/trino-1/minerva-1.md) for the shared DataOS Minerva cluster or a bring-your-own Trino/Starburst cluster.
* [Engine guide overview](/references/v1/engine-guide/engine-guide.md) for the cross-engine rules.
* [Trino properties reference](https://trino.io/docs/current/admin/properties.html) · [Resource management](https://trino.io/docs/current/admin/properties-resource-management.html) · [Query management](https://trino.io/docs/current/admin/properties-query-management.html) · [Trino functions](https://trino.io/docs/current/functions.html)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://v2.dataos.info/references/v1/engine-guide/trino-1.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
