JDBC Driver
SoftClient4ES provides a JDBC Type 4 driver that lets you connect any JDBC-compatible tool to Elasticsearch — DBeaver, IntelliJ DataGrip, Apache Superset, Tableau, and custom Java/Scala applications.
Connection Details
| Property | Value |
|---|---|
| JDBC URL | jdbc:elastic://localhost:9200 |
| Driver class | app.softnetwork.elastic.jdbc.ElasticDriver |
| Group ID | app.softnetwork.elastic |
Driver JARs
Download the self-contained fat JAR for your Elasticsearch version. The JARs are Scala-version-independent and include all required dependencies.
| Elasticsearch | Artifact |
|---|---|
| ES 6.x | softclient4es6-jdbc-driver-0.2.4.jar |
| ES 7.x | softclient4es7-jdbc-driver-0.2.4.jar |
| ES 8.x | softclient4es8-jdbc-driver-0.2.4.jar |
| ES 9.x | softclient4es9-jdbc-driver-0.2.4.jar |
The driver requires Java 11+ (17+ for ES 9.x) — the embedded JOIN engine is built on Apache Arrow 18.x, which ships Java-11 bytecode. See Cross-Index JOIN.
Build Tool Integration
Maven
<dependency> <groupId>app.softnetwork.elastic</groupId> <artifactId>softclient4es8-jdbc-driver</artifactId> <version>0.2.4</version></dependency>Gradle
implementation 'app.softnetwork.elastic:softclient4es8-jdbc-driver:0.2.4'sbt
libraryDependencies += "app.softnetwork.elastic" % "softclient4es8-jdbc-driver" % "0.2.4"JDBC URL Format
jdbc:elastic://host:port[?param=value&...]Authentication Parameters
| Parameter | Description |
|---|---|
user | Username for basic authentication |
password | Password for basic authentication |
api-key | Elasticsearch API key |
bearer | OAuth/JWT bearer token |
scheme | Connection scheme (http or https, default: http) |
Examples
# Basic connectionjdbc:elastic://localhost:9200
# With authenticationjdbc:elastic://es.example.com:9200?user=elastic&password=changeme
# HTTPS with API keyjdbc:elastic://es.example.com:9243?scheme=https&api-key=your-api-keyJava Example
import java.sql.*;
String url = "jdbc:elastic://localhost:9200";try (Connection conn = DriverManager.getConnection(url)) { try (Statement stmt = conn.createStatement()) { // DDL stmt.execute("CREATE TABLE IF NOT EXISTS demo (id INT, name VARCHAR, PRIMARY KEY (id))");
// DML stmt.execute("INSERT INTO demo (id, name) VALUES (1, 'Alice'), (2, 'Bob')");
// DQL try (ResultSet rs = stmt.executeQuery("SELECT * FROM demo ORDER BY id")) { while (rs.next()) { System.out.printf("id=%d, name=%s%n", rs.getInt("id"), rs.getString("name")); } }
// Cleanup stmt.execute("DROP TABLE IF EXISTS demo"); }}Your first query
A plain SELECT is the fastest way to confirm the connection works:
SELECT * FROM my_index LIMIT 10;try (Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("SELECT * FROM my_index LIMIT 10")) { while (rs.next()) { System.out.println(rs.getString(1)); }}Your first JOIN
Elasticsearch SQL can’t JOIN across indices — SoftClient4ES does. Free in Community: up to 2 cross-index JOINs per query (a 3-table JOIN). The JOIN runs in an embedded DuckDB engine; your existing single ES cluster needs no extra infrastructure.
A cross-index INNER JOIN over two ES indices — jdbc_join_emp (employees) and jdbc_join_dept (departments):
SELECT e.name, e.salary, d.dept_nameFROM jdbc_join_emp eJOIN jdbc_join_dept d ON e.dept_id = d.dept_id;-- 5 rows (the orphan employee with dept_id = 99 is dropped by the INNER JOIN)Denormalize the joined result into a brand-new index with CREATE TABLE … AS SELECT (CTAS):
CREATE TABLE jdbc_row1_ctas_join_target ASSELECT e.name, e.salary, d.dept_nameFROM jdbc_join_emp eJOIN jdbc_join_dept d ON e.dept_id = d.dept_id;Upsert the joined rows into an existing index idempotently with INSERT … ON CONFLICT (col) DO UPDATE:
INSERT INTO jdbc_row1_insert_join_upsert_targetSELECT e.emp_id, e.name, e.salary, d.dept_nameFROM jdbc_join_emp eJOIN jdbc_join_dept d ON e.dept_id = d.dept_idON CONFLICT (emp_id) DO UPDATE;Note:
CREATE TABLE … AS … ON CONFLICTandINSERT … ON CONFLICT … DO NOTHINGare rejected at the JDBC boundary — useINSERT … ON CONFLICT … DO UPDATEfor idempotent upserts.
Bind parameters through a JOIN with a PreparedStatement:
PreparedStatement ps = conn.prepareStatement( "SELECT e.name, d.dept_name " + "FROM jdbc_join_emp e " + "JOIN jdbc_join_dept d ON e.dept_id = d.dept_id " + "WHERE e.salary > ?");ps.setDouble(1, 3500.0); // lower threshold → more rowstry (ResultSet rs = ps.executeQuery()) { /* … */ }ps.setDouble(1, 6500.0); // higher threshold → fewer rows (Carol = 8000 survives)try (ResultSet rs = ps.executeQuery()) { /* … */ }For the full JOIN matrix — passthrough, cross-cluster conveyor, and the multi-source coordinator — see the Cross-Index JOIN walkthrough.
Supported SQL
The JDBC driver supports the full SQL Gateway syntax:
- DDL — CREATE/ALTER/DROP TABLE, pipelines, watchers, enrich policies
- DML — INSERT, UPDATE, DELETE, COPY INTO
- DQL — SELECT with WHERE, GROUP BY, HAVING, ORDER BY, LIMIT, UNION ALL, JOIN UNNEST, window functions
- SHOW/DESCRIBE — Tables, pipelines, watchers, enrich policies
BI Tool Setup
DBeaver
- Open Database > New Database Connection
- Choose Driver Manager > New
- Set Driver Name:
SoftClient4ES - Add the fat JAR file
- Set Driver Class:
app.softnetwork.elastic.jdbc.ElasticDriver - Set URL Template:
jdbc:elastic://{host}:{port} - Create a new connection using this driver
See the DBeaver guide for detailed setup instructions.
IntelliJ DataGrip
- Open Database > + > Driver
- Add the fat JAR
- Set Driver Class:
app.softnetwork.elastic.jdbc.ElasticDriver - Create a new data source with URL
jdbc:elastic://localhost:9200
Version compatibility
| Driver | Scala | ES versions | Clients | Process model |
|---|---|---|---|---|
| JDBC | published for Scala 2.13 | ES 6.x / 7.x / 8.x / 9.x | Java/JVM + any JDBC tool (DBeaver, DataGrip, Superset) | In-process |
The fat JARs are Scala-version-independent for consumers — they bundle their own Scala runtime, so a Java application (or a Scala 2.12 project) can use the driver without matching Scala versions. You almost never need to think about the Scala axis.
Licensing & self-selection
All client drivers (JDBC, ADBC, and the REPL) plus the Arrow Flight SQL sidecar are free in Community, including up to 2 cross-index JOINs per query (a 3-table JOIN). A 4-table JOIN (a 3rd cross-index JOIN in one query) is rejected by the planner with a message ending … Upgrade to Pro … See: https://portal.softclient4es.com/pricing.
Multi-cluster federation — joining across separate ES clusters — is Pro+ (maxClusters 1 / 5 / ∞). These quickstarts cover the single-cluster shape, which is free. See the pricing & licensing page for the full quota matrix.
What does NOT work yet
Subqueries (IN (SELECT …), EXISTS, scalar, derived tables) and CTEs (WITH) are not supported in the current release — they arrive in a later release. Write the JOIN explicitly instead. See Known Limitations & Roadmap for the full list.
Going further
- Cross-Index JOIN walkthrough — the full JOIN matrix (rows 1/2/3) with worked examples.
- Multi-cluster federation operator guide — the Pro+ path: JOIN across separate ES clusters.
- Known Limitations & Roadmap — what works in the current release vs what’s coming.
Telemetry
The JDBC driver sends one anonymous usage ping per day (no IP, no SQL, no PII). Opt out either on the JDBC URL — jdbc:elastic://localhost:9200?telemetry=false — or with softclient4es.telemetry.enabled = false on your application classpath. See Telemetry & Privacy for the full field list and per-surface details.
Known limitations
Subqueries, CTEs (WITH), and set operators beyond UNION ALL are not in this release — and some BI tools auto-generate them. See Known Limitations & Roadmap for exactly what works today, what’s coming in the next release (Quarter 4 2026), and the per-tool workaround.
License
The JDBC driver is licensed under the Elastic License 2.0 — free to use, not open source.