Arrow Flight SQL JDBC Driver
IOMETE provides a custom release of the Apache Arrow Flight SQL JDBC driver. It's functionally identical to the upstream driver, with three additions:
- HTTP CONNECT proxy tunneling: routes gRPC/Flight connections through an enterprise HTTP proxy ›
- Connection-level query timeout: sets a per-connection default timeout applied to every statement ›
- Named parameters: allows
:namesyntax as an alternative to positional?markers ›
It also supports standard mutual TLS, presenting a client certificate when your endpoint requires one. See Client Certificates (mTLS).
Download the Driver
Download the latest release from the iomete-artifacts GitHub repository.
Driver artifacts follow the naming convention flight-sql-jdbc-driver-<upstream>-iomete.<release>.jar,
where <upstream> is the Arrow Flight SQL version
and <release> is the IOMETE release number
(e.g. flight-sql-jdbc-driver-19.0.0-iomete.2.jar).
Query Timeout
Requires IOMETE ≥ 3.17.1.
Without a timeout, a slow or stuck query can hold a connection open indefinitely. To cap that, set a default timeout for all statements on a connection: add queryTimeout=<seconds> to the JDBC URL, or pass it as a connection property if your client supports one.
jdbc:arrow-flight-sql://<host>:<port>?user=<username>&password=<token>&queryTimeout=30
The timeout applies to every statement executed on that connection. A value of 0 (the default) means no timeout.
Individual statements can still override this via the standard Statement.setQueryTimeout() method.
Named Parameters
Requires IOMETE ≥ 3.16.0.
Named parameters keep prepared statements readable when a query has many bind variables. Instead of counting ? positions, you reference each value by name. Prepared statements support :name syntax as an alternative to positional ? markers.
The driver automatically translates named parameters to positional placeholders before sending the query.
NamedPreparedStatement ps = (NamedPreparedStatement)
conn.prepareStatement("SELECT * FROM orders WHERE status = :status AND region = :region");
ps.setString("status", "active");
ps.setString("region", "europe");
ResultSet rs = ps.executeQuery();
The same name can appear multiple times in a query, and the driver binds the value to every occurrence.
Positional ? and named :name markers cannot be mixed in the same statement.
HTTP Proxy Configuration
Proxy settings are passed as query parameters appended to the JDBC URL. No code changes are needed in your application.
The proxy must support HTTP CONNECT tunneling (standard for HTTPS/gRPC traffic). SOCKS proxies are not supported. Proxy authentication (proxy username/password) isn't currently supported, so the proxy must allow unauthenticated CONNECT.
Connection Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
proxyHost | string | — | Hostname or IP of the HTTP proxy |
proxyPort | integer | — | Port of the HTTP proxy |
proxyBypassPattern | string | — | Hosts to connect directly, bypassing the proxy (see format below) |
proxyDisable | string | — | Set to force to disable proxy resolution entirely |
proxyHost and proxyPort must be set together.
If only one is provided, the explicit proxy is ignored and the driver falls back to the JVM's system proxy selector.
Resolution Priority
When establishing a connection, the driver resolves the proxy in this order:
proxyDisable=force→ connect directly, no proxy- Target host matches
proxyBypassPattern→ connect directly proxyHost+proxyPortare both set → use this explicit proxy- JVM system proxy (
java.net.ProxySelector) → use the first non-DIRECT proxy found - No proxy found → connect directly
proxyBypassPattern Format
Uses the same format as the JVM http.nonProxyHosts system property:
- Patterns separated by
| *is a wildcard matching any sequence of characters- Matching is case-insensitive
| Pattern | Matches |
|---|---|
localhost | localhost only |
*.internal | db.internal, api.internal, etc. |
localhost|*.internal|10.0.* | any of the above |
JVM System Proxy Fallback
If proxyHost/proxyPort are not set, the driver automatically falls back to the JVM's proxy selector.
Standard JVM proxy properties are respected:
java -Dhttps.proxyHost=proxy.corp.internal -Dhttps.proxyPort=3128 -jar your-app.jar
You can also set proxyHost/proxyPort directly in the JDBC URL to use a connection-specific proxy, independently of the JVM-level proxy.
This means it is possible to route general Java traffic through one proxy and IOMETE JDBC connections through another.
To suppress JVM proxy resolution for a specific connection without changing JVM properties, add proxyDisable=force to the JDBC URL.
Examples
All examples use the base JDBC URL format:
jdbc:arrow-flight-sql://<host>:<port>?user=<username>&password=<token>
Replace <host>, <port>, <username>, and <token> with your cluster's connection details from the IOMETE console.
Route all traffic through a proxy
Uses proxyHost and proxyPort.
jdbc:arrow-flight-sql://<host>:<port>?user=<username>&password=<token>&proxyHost=proxy.corp.internal&proxyPort=3128
Bypass proxy for internal hosts
Uses proxyHost, proxyPort, and proxyBypassPattern to route internal traffic directly.
jdbc:arrow-flight-sql://<host>:<port>?user=<username>&password=<token>&proxyHost=proxy.corp.internal&proxyPort=3128&proxyBypassPattern=*.internal|localhost
Disable proxy entirely
Uses proxyDisable=force to override any JVM-level proxy configuration for this connection.
jdbc:arrow-flight-sql://<host>:<port>?user=<username>&password=<token>&proxyDisable=force
Client Certificates (mTLS)
If your IOMETE endpoint requires mutual TLS, the driver can present a client certificate during the handshake. It does so only when all three properties below are set, so a missing useEncryption=true silently drops the certificate.
| Purpose | Property | Value |
|---|---|---|
| Enable TLS | useEncryption | true (required, or the certificate is never attached) |
| Client certificate | clientCertificate | Filesystem path to the client certificate PEM |
| Client key | clientKey | Filesystem path to the client key PEM |
jdbc:arrow-flight-sql://<host>:<port>?user=<username>&password=<token>&useEncryption=true&clientCertificate=/path/to/client-cert.pem&clientKey=/path/to/client-key.pem