JDBC sources

Introduction

A source can front any database that ships a JDBC driver: NetSuite, Snowflake, Databricks, BigQuery, SQL Server, Oracle, Trino, and the thirty-odd others in the preset list below. You bring the driver jar; swarmvia loads it in an isolated Java runtime that belongs to your organization alone, dials the database with a login that never leaves swarmvia, and serves the result over the same endpoint every database source has.

To a caller a JDBC source is a database source: the same POST / query body, the same /structure, the same job handles, the same MCP tools, the same concurrency limit and access log. Only the leg after admission differs, and nothing about it is specific to a vendor. Presets are data. A vendor swarmvia has never heard of works with the generic preset.

Use the native Postgres and MySQL backends for those engines. A JDBC source exists for everything else, and for the rare case where a driver feature matters more than the lighter native path.

The endpoints

POST  https://{source}.swarmvia.cloud
GET   https://{source}.swarmvia.cloud/structure
GET   https://{source}.swarmvia.cloud/__nth/jobs/{jobId}

Identical to a database source: X-Swarmvia-Key, queries with bound parameters, maxRows, waitMs, rowFormat. Two differences a caller sees:

  • Placeholders are ?, never $1. JDBC drivers take positional ? markers and every vendor agrees on that.
  • Every cell is text. The driver's getString() of each value is returned as the JSON string it printed, or null. Column types are the driver's own names (NUMBER, varchar, TIMESTAMP_NTZ). Nothing is cast on the way out, because the vendor's text form is the one its users recognize.

Drivers

A driver is the jar a source loads. There are two ways to set it, both on the source:

  • Maven coordinates (group:artifact:version) for drivers published on Maven Central, which most are. Vendor templates fill these in. swarmvia fetches the jar when you save, verifies its SHA-1 against Central, and stores it, so a query never depends on Central being up. Sources with the same coordinates share one stored jar.
  • Upload the jar for drivers a vendor only hands out from its own site (NetSuite, BigQuery's Simba driver, Dremio, Sybase, Netezza, Denodo).

If a vendor's download page asks for an operating system, choose Linux 64-bit (x86-64, glibc). Every source runs there, on Java 21, so take a build for Java 8 through 21; a build for a newer Java will not load. Take the JDBC download, not ODBC.

Every jar is inspected before it is accepted: it must be a real jar and declare at least one java.sql.Driver in META-INF/services. Up to 150 MB per jar and 1 GB per organization.

To upgrade one source, change its coordinates. To upgrade every source on a driver, use Change version (or Replace, for an upload) under Drivers in the sidebar. Each source picks the new jar up on its next connection; the old version is removed once every source has been told about the new one. A driver still used by a source cannot be deleted; point those sources elsewhere first.

The jar runs only in your organization's runtime, with your sources' logins, which it receives per request. It never shares a process with another customer's code and never sees another organization's secret.

Presets

A preset fills the form: the driver to fetch, the URL template, the property rows the driver expects, and where an access token goes. Pick one under Sources → New source → JDBC data source, then fill the placeholders. The JDBC URL and the public properties stay editable, so a preset is a head start, not a cage.

Preset Driver Auth
NetSuite SuiteAnalytics Connect upload from the vendor password, OAuth 2.0
Snowflake net.snowflake:snowflake-jdbc (Maven Central) password, key or service-account file, OAuth 2.0
Databricks SQL com.databricks:databricks-jdbc (Maven Central) token or key, OAuth 2.0
Google BigQuery upload from the vendor key or service-account file
Google Cloud Spanner com.google.cloud:google-cloud-spanner-jdbc (Maven Central) key or service-account file
Amazon Redshift com.amazon.redshift:redshift-jdbc42 (Maven Central) password
Amazon Athena com.amazonaws.athena:athena-jdbc (Maven Central) password
Microsoft SQL Server / Azure SQL / Synapse com.microsoft.sqlserver:mssql-jdbc (Maven Central) password, OAuth 2.0
Oracle Database / Autonomous Database com.oracle.database.jdbc:ojdbc11 (Maven Central) password, OAuth 2.0
IBM Db2 com.ibm.db2:jcc (Maven Central) password
IBM Informix com.ibm.informix:jdbc (Maven Central) password
SAP HANA com.sap.cloud.db.jdbc:ngdbc (Maven Central) password, OAuth 2.0
Teradata com.teradata.jdbc:terajdbc (Maven Central) password
Trino / Starburst io.trino:trino-jdbc (Maven Central) password, OAuth 2.0
Presto com.facebook.presto:presto-jdbc (Maven Central) password
ClickHouse com.clickhouse:clickhouse-jdbc (Maven Central) password, OAuth 2.0
SingleStore com.singlestore:singlestore-jdbc-client (Maven Central) password
Vertica com.vertica.jdbc:vertica-jdbc (Maven Central) password, OAuth 2.0
Exasol com.exasol:exasol-jdbc (Maven Central) password, OAuth 2.0
Firebolt io.firebolt:firebolt-jdbc (Maven Central) token or key
MotherDuck org.duckdb:duckdb_jdbc (Maven Central) token or key
Dremio upload from the vendor password, token or key
Apache Hive / Spark Thrift org.apache.hive:hive-jdbc (Maven Central) password
Apache Druid org.apache.calcite.avatica:avatica-core (Maven Central) password
Apache Phoenix org.apache.phoenix:phoenix-queryserver-client (Maven Central) password
CrateDB io.crate:crate-jdbc (Maven Central) password
Elasticsearch SQL upload from the vendor password, token or key
OpenSearch SQL org.opensearch.driver:opensearch-sql-jdbc (Maven Central) password, token or key
Sybase / SAP ASE upload from the vendor password
IBM Netezza upload from the vendor password
Denodo upload from the vendor password
PostgreSQL-compatible via JDBC org.postgresql:postgresql (Maven Central) password, OAuth 2.0
MySQL-compatible via JDBC com.mysql:mysql-connector-j (Maven Central) password, OAuth 2.0

Other (generic JDBC) takes any driver, any jdbc: URL, and any property bag. It is how a vendor not listed here is connected, and the list above is nothing more than this form with the fields filled in.

Properties and secrets

A JDBC driver is configured by a flat bag of named strings. swarmvia splits that bag by who may see it:

  • Public properties live on the source: account, warehouse, role, application name, TLS mode. They appear in the dashboard and in the source's settings.
  • Secret properties live in the credential: password, token, client secret, passphrase. They are written once and never shown back.
  • Files live in the credential too: a private key, a service-account JSON, a wallet. Up to eight, 64 KB each. Reference one as ${file:name} in a property value or in the URL; it is written to a private directory for the connection and removed when the connection ends. ${files} is that directory, for a driver that wants one (an Oracle wallet location, TNS_ADMIN).

The secret bag wins. A name set in both places takes the credential's value, so a value typed into the source form can never override a secret, and a JDBC URL is refused if it carries a property the credential marks secret. Secrets go in the credential; the URL is shown and logged.

A JDBC login is one credential, reusable across sources like any other. Rotating it walks every source on it back to needs connectivity until Test connection passes again.

OAuth2 access tokens

Drivers that take a short-lived access token (Snowflake, Databricks, Azure SQL and Synapse, Oracle, Trino, Vertica, Exasol, HANA, ClickHouse) get one from swarmvia. Give the credential an OAuth 2.0 client-credentials grant and name where the driver wants the token: a property (token, Auth_AccessToken, accessToken, OAuth2Token) or a file (Oracle reads one from oracle.jdbc.tokenLocation).

swarmvia mints the token at the identity provider, caches it until shortly before it expires, and hands it to the driver on every connection. The driver never refreshes anything itself, which matters because every query is a fresh connection and a driver left to its own devices would hit your identity provider per query. Sources that share a credential share the token.

A rejected client is answered the way an HTTP source answers one: 503 with the identity provider's error, a reconnect link, and no secret in the body.

Limits and sizing

Query limits are the database-source limits:

Setting Default Ceiling
Statement timeout 30s 10m
Max rows 10,000 50,000
Max result bytes 8 MiB 16 MiB
Result TTL 1h 24h

Two things are JDBC's own:

Runtime memory. A JDBC source runs in a Java runtime with 1 GB, which fits a JVM, a driver, and sixteen concurrent queries at the 8 MiB result ceiling. A driver that buffers wide results can still exhaust it; lower maxRows first, and if queries against the source keep failing, contact [email protected].

When no runtime is available. The runtimes come from a shared pool of instances. When none can be started, a source either fails the query with 503 dialer_at_capacity and a Retry-After the caller should honour, or queues it as a job to run when an instance frees up. Queueing needs Async on. Choose under Concurrency; the default is to fail, because a hidden queue is the one thing an operator cannot budget for.

Plan limits on JDBC sources, separate from the source count:

Plan JDBC sources
Free 0
Starter 1
Team 3
Business 10

A scheduled job against a JDBC source keeps a runtime awake for as long as it runs; the per-plan cap is what keeps a dozen hourly crons from becoming a bill nobody meant to run.

Read-only, and what that means here

swarmvia asks the driver for a read-only connection and runs each statement in a transaction it rolls back. What that is worth depends entirely on the driver: some enforce it, some record it as a hint, some ignore it. Test connection reports what the driver said (readOnly: true or false), and the honest statement is this: the login's grants are the whole boundary. Connect as a role that can read what it should and nothing else, the same discipline a Postgres source asks for, and treat a read-only connection as a convenience, not a control.

Test connection

Sources → Settings → Test connection opens a real connection through the driver and reports which stage failed:

Reason Meaning
driver_not_found The driver jar could not be fetched. Check the driver under JDBC drivers.
driver_load_failed The jar was fetched but failed to load, or its checksum did not match. Replace it.
driver_class_missing The jar declares no java.sql.Driver. It is not a JDBC driver, or not the right jar from the vendor's bundle.
not_jdbc No loaded driver accepts this URL's jdbc: subprotocol. The URL and the driver disagree.
unreachable, tls_refused, tls_verify_failed The network and TLS stages, as for any database source.
auth_failed, database_missing, insufficient_privilege The login, the database name, or the grants.

On success it records the product the driver reported (NetSuite, Snowflake, Microsoft SQL Server) and the driver's own identifier quoting, which the MCP source_count_rows tool uses to quote names for an engine it has never seen.

Errors

Failures carry the driver's SQLSTATE where the driver provides one, in the same db_error shape as every database source. Statement timeouts and cancellations are 57014. A failure before any statement ran (a driver that would not load, a connection that would not open) is a 502 or 503 naming the stage, never a 400: it is the source's configuration, not the caller's statement.

Cancelled queries are cancelled in the driver, not just dropped, so a runaway statement stops at the database when the caller gives up.

From an agent

The same tools as any database source: source_schema, source_query, get_query_result, source_count_rows. source_schema reads the driver's own catalog (DatabaseMetaData), so engines without information_schema work. A JDBC source lists in list_sources as backend: jdbc · <product>.

What this is not

Not ODBC. ODBC drivers are native code for a specific operating system and architecture, and every vendor's build is different; there is no way to load one safely in a shared runtime. Every vendor that ships ODBC also ships JDBC, and the JDBC driver is the portable one. If a system only has an ODBC driver, it will not connect here.

Not a driver host for your application. The runtime opens one connection per query and sleeps when idle. It is for agents, analysts and scheduled analytical work, like every other database source.

Not Kerberos. Drivers that can only authenticate with a Kerberos ticket have no keytab here. Use the vendor's password, token or OAuth2 path.