Skip to content

questdb/questdb-jdbc

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 

Repository files navigation

questdb-jdbc

JDBC 4.2 driver for QuestDB on top of the QuestDB Wire Protocol (QWP) egress. The driver wraps org.questdb:questdb-client and exposes a standard java.sql.Driver so QuestDB plugs into JDBC tooling (DataGrip, DBeaver, Spring Data, JOOQ, JDBI, etc.) without going through the Postgres-wire compatibility layer.

Status: alpha. The driver compiles, the unit suite is green, but it has not yet been exercised against a running QuestDB end-to-end. Expect rough edges. See the Known gaps section before adopting it for anything load-bearing.

Why a native JDBC driver?

QuestDB already ships a Postgres wire protocol implementation that any PostgreSQL JDBC driver can talk to. This driver exists for cases where:

  • You want native QuestDB types (SYMBOL, GEOHASH, LONG256, IPv4, TIMESTAMP_NS, DECIMAL64/128/256, arrays) without the Postgres-wire compatibility translations.
  • You want to take advantage of QWP's column-major streaming, zstd compression, multi-endpoint failover, and credit-based flow control.
  • You want a smaller wire footprint than Postgres protocol on chatty workloads.

It is not a drop-in replacement for the Postgres wire protocol. SQL is the same; metadata, transactions, and tooling expectations are not.

Install

<!-- Coordinates are not yet published to Maven Central.
     Build locally with `mvn install` until the first release. -->
<dependency>
    <groupId>org.questdb</groupId>
    <artifactId>questdb-jdbc</artifactId>
    <version>0.1.0-SNAPSHOT</version>
</dependency>

Quick start

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

String url = "jdbc:questdb://localhost:9000";

try (Connection conn = DriverManager.getConnection(url);
     PreparedStatement ps = conn.prepareStatement(
             "SELECT ts, sym, price FROM trades WHERE sym = $1 LIMIT 100")) {
    ps.setString(1, "AAPL");
    try (ResultSet rs = ps.executeQuery()) {
        while (rs.next()) {
            System.out.printf("%s %s %.4f%n",
                    rs.getTimestamp(1), rs.getString(2), rs.getDouble(3));
        }
    }
}

DriverManager.getConnection auto-loads io.questdb.jdbc.QuestDBDriver via the META-INF/services/java.sql.Driver SPI entry; no Class.forName call is required on JDK 9+.

Connection URL

jdbc:questdb://host[:port][,host[:port]...][/path][?key=value&...]
jdbc:questdb:ws://...     # explicit plain WebSocket
jdbc:questdb:wss://...    # WebSocket over TLS

The default port is 9000 (QuestDB's HTTP / WebSocket port). The default path is /read/v1.

URL query parameters and Properties entries pass straight through to QwpQueryClient. Properties wins over the URL when both set the same key. The most useful keys:

Key Meaning Default
path WebSocket endpoint /read/v1
target any / primary / replica endpoint filter any
failover Transparent failover on transport faults: on / off on
username HTTP Basic auth username (paired with password) -
password HTTP Basic auth password -
token OIDC bearer token -
auth Verbatim Authorization header value -
client_id Sent as the X-QWP-Client-Id header -
compression raw / zstd / auto raw
compression_level zstd level [1, 22] 3
max_batch_rows Per-batch row cap hint sent to the server server-side
tls_verify on / unsafe_off (only with wss) on
tls_roots Path to a custom trust store (PKCS12 or JKS) -
tls_roots_password Trust store password -

Multiple endpoints separated by commas are walked in order at connect time and used as failover targets.

Type mapping

QuestDB / QWP type JDBC Types Java class returned
BOOLEAN BOOLEAN Boolean
BYTE TINYINT Byte
SHORT SMALLINT Short
CHAR CHAR Character
INT INTEGER Integer
LONG BIGINT Long
FLOAT REAL Float
DOUBLE DOUBLE Double
STRING / VARCHAR VARCHAR String
SYMBOL VARCHAR String
DATE DATE java.sql.Date
TIMESTAMP TIMESTAMP (us) java.sql.Timestamp
TIMESTAMP_NS TIMESTAMP (ns) java.sql.Timestamp
BINARY VARBINARY byte[]
UUID OTHER java.util.UUID
LONG256 OTHER hex String (0x...)
GEOHASH OTHER base32 / binary String
IPv4 OTHER dotted-quad String
DECIMAL64/128/256 DECIMAL BigDecimal (server scale)
DOUBLE_ARRAY ARRAY java.sql.Array of Double
LONG_ARRAY ARRAY placeholder (see TODO)

PreparedStatement setters cover the symmetric set: setBoolean, setByte, setShort, setInt, setLong, setFloat, setDouble, setBigDecimal (auto-picks DECIMAL64/128/256), setString, setTimestamp, setDate, setTime, setObject(UUID). JDBC type codes in setNull(idx, sqlType) are translated to the matching QWP wire type.

Build

mvn clean package
mvn test

Java 11+ and Maven 3 required. The QWP client jar is pulled from Maven Central; no local QuestDB checkout is needed for the build.

Known gaps

  • Streaming ResultSet: results are materialised into the heap up front. Large queries can OOM the client. Replacing the materialiser with a bounded blocking queue between the QWP I/O thread and the user thread is the obvious next step.
  • LONG_ARRAY decoding: client 1.2.0 only exposes getDoubleArrayElements; LONG_ARRAY returns a placeholder string until the upstream accessor lands.
  • getTypeInfo: returns an empty result. Tools that introspect type metadata at connect time (DBeaver, IntelliJ Database) will fall back to defaults.
  • getPrimaryKeys / getIndexInfo: empty. QuestDB has no primary keys; symbol-indexed columns could surface through getIndexInfo but that wiring is not done yet.
  • PreparedStatement.getMetaData / ParameterMetaData: not implemented; QWP does not yet expose a server-side prepare/describe.
  • Statement.setQueryTimeout: accepted but not enforced. Plumb a per-call scheduler that calls cancel() on expiry.
  • Auto-generated keys, CallableStatement, savepoints, client-driven transactions: intentionally unsupported. QuestDB has no row-id, no procedures, and QWP does not expose explicit transactions.
  • Integration tests: the suite covers URL parsing, type mapping, ResultSet mechanics, and driver registration. End-to-end coverage against a running QuestDB is not yet wired.

License

Apache License 2.0. See LICENSE.txt.

Related

About

JDBC 4.2 driver for QuestDB on top of the QWP egress wire protocol

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages