# Trino Integration (/docs/integrations/trino-integration)

## Overview [#overview]

[Trino](https://trino.io/) is a distributed SQL query engine, not a data store. Transcend connects to your Trino coordinator over the HTTPS REST API and runs data subject request (DSR) SQL against catalogs Trino can reach — for example Iceberg on object storage, Hive, or operational databases.

Queries are routed through [Sombra](../sombra/introduction.mdx) so credentials stay in your environment. Self-host Sombra for production. The Trino integration requires Sombra `7.516.1` or later.

## Prerequisites [#prerequisites]

- Coordinator URL (host and port; default port is 8080) and HTTPS in production.
- Authentication: PASSWORD (username and password) or JWT (pre-issued Bearer token).
- A Trino user with `SELECT` on tables used for ACCESS, and `DELETE` (or `INSERT` and `DELETE` for `MERGE`) on tables used for ERASURE.

<Callout type="warn" title="Connection succeeds without table grants">
  Trino accepts the connection when authentication succeeds, even if the user has no catalog or table access. A successful connection test does not prove DSRs will return rows.
</Callout>

## Connect the integration [#connect-the-integration]

1. In the Admin Dashboard, go to Infrastructure → Integrations, search for Trino, and add it.
2. Enter the coordinator URL, choose PASSWORD or JWT, and optionally set a default catalog and schema. If you omit those, fully qualify table names in DSR SQL.
3. If the coordinator uses a private CA, paste the CA certificate PEM into the CA Certificate field.
4. Save and run a connection test.

## Configure DSR SQL [#configure-dsr-sql]

Run a Discovery Scan to recommend datapoints from catalogs, schemas, and tables (built-in catalogs such as `system`, `tpch`, `tpcds`, `jmx`, and `memory` are excluded). Content classification is not available yet — after discovery (or if you create datapoints by hand), write ACCESS and ERASURE prepared statements yourself under Manage Datapoints.

### Identifier placeholders [#identifier-placeholders]

Use unquoted placeholders. Prefer `@email` (named) or `{{email}}` (template). Do not wrap them in SQL quotes. Quoted `'{{email}}'` looks up the literal string `{{email}}`, returns zero rows, and makes erasure look like it never ran. See [SQL statement variables](./custom/database-integration-set-up-for-dsr-automation.mdx) for the full variable set.

```sql
SELECT first_name, last_name, street, email
FROM iceberg.privacy.customers
WHERE email = @email;
```

### Erasure runs ACCESS first [#erasure-runs-access-first]

A Delete request does not skip ACCESS. Transcend runs the datapoint’s ACCESS SQL first. If that query returns no rows, ERASURE SQL often never reaches Trino — especially when the integration is set to skip secondary erasure when access found no files. A successful standalone Access request does not prove the ACCESS phase of this Delete request found rows.

<Callout type="info" title="Fix ACCESS before debugging DELETE">
  If Trino logs show no DELETE, MERGE, or UPDATE for a Delete DSR, inspect the ACCESS prepared statement on the same datapoint. Confirm identifiers are unquoted and that ACCESS returns files for that request ID.
</Callout>

## Mutations and Iceberg [#mutations-and-iceberg]

Trino mutations depend on the connector. Iceberg commonly supports `DELETE` and `MERGE INTO`; a plain `UPDATE` can fail even when the same service account can mutate in the Trino CLI. Put redaction or overwrite logic in `MERGE INTO` (or `DELETE`) on the ERASURE prepared statement. Review [Trino DELETE limitations](https://trino.io/docs/current/sql/delete.html#limitations).

```sql
MERGE INTO iceberg.privacy.customers AS t
USING (SELECT @email AS email) AS s
ON t.email = s.email
WHEN MATCHED THEN UPDATE SET
  first_name = 'REDACTED',
  last_name = 'REDACTED',
  street = 'REDACTED';
```

Each DSR action is one statement. Do not rely on a prior `SET` session command; ERASURE uses a transaction and session state does not carry across Transcend calls.

### Matching on more than one identifier [#matching-on-more-than-one-identifier]

A datapoint query is keyed by one identifier type. To AND email with another identifier, combine them in a SQL or custom-function preflight into a single identifier (for example a JSON object), then decompose that value in the Trino SQL.

## Troubleshooting [#troubleshooting]

| Symptom                                            | Check                                                                                               |
| -------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
| No DELETE/MERGE in Trino logs for a Delete request | ACCESS SQL on that datapoint: unquoted placeholders, and ACCESS returned files for this request.    |
| ACCESS works; ERASURE SQL never selected           | The ERASURE prepared statement must be stored as request type `ERASURE`, not `DELETE`.              |
| SQL works in the Trino CLI, fails from Transcend   | Same service account; prefer MERGE INTO or DELETE over UPDATE; one statement, no SET session setup. |

## Related documentation [#related-documentation]

- [Database Integration Set Up for DSR Automation](./custom/database-integration-set-up-for-dsr-automation.mdx)
- [Sombra introduction](../sombra/introduction.mdx)
