Skip to content

Trino ODBC Driver #835

@lfrancke

Description

@lfrancke

Trino ODBC Driver (Rust)

Description

Build a read-only Rust-based ODBC driver for Trino, targeting PowerBI on Windows.

Authentication scope: Basic Auth only for all three milestones.

The driver will be built using the trino-rust-client rather than implementing a Trino Rust REST client from scratch.

Reusability note
The FFI scaffolding must be designed for reuse so a second ODBC driver can later be built without duplicating the boilerplate.
This will need some brainstorming. During my implementation of our odbc-rs-sqlite experiment I learned that any Trait or whatever based systems will not work as the FFI methods have to have an exact name and signature and their handling code can also not be general but needs to be specific. I believe the only way we can do this is to have a macro-based crate. One idea I had was a kind of "Backend" trait. A macro generates all the required extern "system" entry points and then forwards to a type implementing the trait.
This is not necessarily an immediate goal of this project but it'd be nice if we could already design it in a similar way (i.e. already decouple the database logic from the ODBC wrapper stuff by e.g. already using a trait).

Tip

We have an existing experiment (odbc-rs-sqlite) that serve as reference material, but it probably makes sense to start from scratch.

Important

We may eventually need to contribute a step-by-step polling API (advance()) to trino-rust-client to avoid buffering entire result sets in memory. This is not needed for Import mode but will matter for large datasets and DirectQuery. Out of scope for now.

Out of Scope

  • Write operations (architecture should support it eventually, but no implementation here)
  • OIDC / OAuth -> Basic Auth only, but design for the possibility of having more than one auth system
  • Spooling protocol
  • DSN setup GUI or Windows installer
  • A second ODBC driver using the reusable framework
  • Publishing the reusable crate separately
  • advance() / streaming API contribution to trino-rust-client

Milestone 1: Foundation DLL — "Does it load?"

Expected effort: 2–3 weeks. If it takes longer, stop and flag.

A Windows DLL that can be registered in the ODBC Driver Manager and entered into PowerBI Gateway. It does not need to connect to anything. Every function call may return SQL_ERROR. The goal is to validate the build and delivery pipeline end-to-end.

  • Cargo workspace setup: odbc-core crate (generic FFI infrastructure) + odbc-driver-trino crate (cdylib)
  • Github Actions workflows
  • Port reusable scaffolding from odbc-rs-sqlite: HandleWrapper, FFI utilities, error/SQLSTATE types
  • Backend trait abstraction separating ODBC protocol logic from database-specific logic, including the macro that generates all ODBC entry points
  • All required ODBC entry points exported as stubs (return SQL_ERROR)
  • extern "system" calling convention throughout (not extern "C")
  • Cross-compile to Windows DLL (x86_64-pc-windows-gnu or MSVC via xwin) -> verify it loads
  • Configuration via env vars or .ini file - this needs research: I have no idea how to configure ODBC drivers in Windows

Decision point: Customer confirms the DLL registers and appears in PowerBI Gateway without errors. Don't start Milestone 2 until this is confirmed.

Milestone 2: Import Mode — "PowerBI can pull a table"

Expected effort: 4–5 weeks. If it takes longer, stop and flag.

PowerBI Import mode can connect to Trino, browse tables, and import data.

  • Integrate trino-rust-client with tokio (one Runtime per connection, block_on() at FFI boundaries)
  • SQLDriverConnect with Basic Auth + TLS
  • SQLGetInfo (~50 info type values -> start from Trino's C++ driver as reference but will need to test against PowerBI)
  • SQLGetFunctions report only what is actually implemented
  • SQLExecDirect (use get_all())
  • SQLFetch + SQLGetData with type conversion for: varchar, char, bigint, integer, smallint, tinyint, double, real, boolean, decimal, uuid, date, time, timestamp, timestamp with time zone
  • NULL handling throughout
  • SQLNumResultCols, SQLDescribeCol, SQLColAttribute
  • SQLTables + SQLColumns via system.jdbc.* queries
  • SQLGetTypeInfo, SQLStatistics
  • SQLGetDiagRec, SQLGetDiagField
  • SQLMoreResults, SQLRowCount, SQLCloseCursor
  • Full connection string parameters: Host, Port, Catalog, Schema, User, Password, SSL, SSLVerify, Timeout, Retries
  • Panic safety: every FFI entry point wrapped in std::panic::catch_unwind
  • Memory safety audit: no use-after-free when connection freed while statements exist

Decision point: Customer successfully imports at least one Trino table into PowerBI. Sign off before starting Milestone 3.


Milestone 3: DirectQuery Mode — "Live queries from PowerBI"

Expected effort: 4–7 weeks. If it takes longer, stop and flag.

PowerBI DirectQuery works. This requires both driver changes and a Power Query custom connector (.mez file). The .mez is a separate deliverable written in M language. Nobody on the team has done this before. Will require research. Flag if this becomes a blocker

  • Power Query custom connector (.mez): SqlCapabilities overrides, AstVisitor to emit LIMIT/OFFSET instead of TOP N, double-quote identifiers instead of square brackets
  • SQLGetInfo capability tuning for DirectQuery: SQL_SQL_CONFORMANCE, predicate support, aggregate functions, subquery support
  • SQLPrepare + SQLExecute
  • SQLFetchScroll (forward-only)
  • SQLCancel via Trino's partialCancelUri
  • Streaming result delivery (no full buffering)
  • Integration testing: filters, grouping, aggregations, joins — verify all fold to SQL

Decision point: Customer confirms an interactive PowerBI dashboard with filters and aggregations works against live Trino data, with queries folding to SQL.


Acceptance Criteria

These points are awaiting user feedback:

  • Milestone 1: DLL registers in ODBC Driver Manager and appears in PowerBI Gateway on customer's Windows machine
  • Milestone 2: Customer imports a Trino table into PowerBI Import mode successfully
  • Milestone 3: Customer builds a live dashboard using DirectQuery with filters and aggregations folding to SQL

Metadata

Metadata

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

Status
Development: In Progress
Status
In Progress

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions