From 1492718f9b76cad25a1deb1b487840f56336a8f3 Mon Sep 17 00:00:00 2001 From: Alex Kasko Date: Tue, 6 Oct 2026 13:32:30 +0100 Subject: [PATCH] Implement javax.sql.DataSource (2.0) This is a backport of the PR #895 to `v2.0-cyanoptera` branch. Co-Authored-By: Nnnes --- .../java/org/duckdb/DuckDBDataSource.java | 68 +++++++++++++++++++ src/test/java/org/duckdb/TestDuckDBJDBC.java | 16 +++++ 2 files changed, 84 insertions(+) create mode 100644 src/main/java/org/duckdb/DuckDBDataSource.java diff --git a/src/main/java/org/duckdb/DuckDBDataSource.java b/src/main/java/org/duckdb/DuckDBDataSource.java new file mode 100644 index 000000000..61e9d9a90 --- /dev/null +++ b/src/main/java/org/duckdb/DuckDBDataSource.java @@ -0,0 +1,68 @@ +package org.duckdb; + +import java.io.PrintWriter; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.sql.SQLFeatureNotSupportedException; +import java.util.Properties; +import java.util.logging.Logger; +import javax.sql.DataSource; + +public class DuckDBDataSource implements DataSource { + private final String url; + private final Properties props; + private PrintWriter logWriter = null; + + public DuckDBDataSource() { + this(DuckDBDriver.DUCKDB_URL_PREFIX, null); + } + + public DuckDBDataSource(String url) { + this(url, null); + } + + public DuckDBDataSource(String url, Properties info) { + this.url = url; + props = info; + } + + public Connection getConnection() throws SQLException { + return DriverManager.getDriver(url).connect(url, props); + } + + public Connection getConnection(String username, String password) throws SQLException { + return getConnection(); + } + + public PrintWriter getLogWriter() throws SQLException { + return logWriter; + } + + public void setLogWriter(PrintWriter out) throws SQLException { + logWriter = out; + } + + public void setLoginTimeout(int seconds) throws SQLException { + } + + public int getLoginTimeout() throws SQLException { + return 0; + } + + public Logger getParentLogger() throws SQLFeatureNotSupportedException { + throw new SQLFeatureNotSupportedException("no logger"); + } + + public T unwrap(Class iface) throws SQLException { + try { + return iface.cast(this); + } catch (ClassCastException e) { + throw new SQLException(e); + } + } + + public boolean isWrapperFor(Class iface) throws SQLException { + return iface.isInstance(this); + } +} diff --git a/src/test/java/org/duckdb/TestDuckDBJDBC.java b/src/test/java/org/duckdb/TestDuckDBJDBC.java index 74818181b..a2aeb750b 100644 --- a/src/test/java/org/duckdb/TestDuckDBJDBC.java +++ b/src/test/java/org/duckdb/TestDuckDBJDBC.java @@ -47,6 +47,7 @@ import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; +import javax.sql.DataSource; import javax.sql.rowset.CachedRowSet; import javax.sql.rowset.RowSetProvider; import org.duckdb.test.TempDirectory; @@ -137,6 +138,21 @@ public static void test_connection() throws Exception { assertThrows(conn::createStatement, SQLException.class); } + public static void test_datasource_connection() throws Exception { + DataSource source = new DuckDBDataSource(JDBC_URL); + Connection conn = source.getConnection(); + Statement stmt = conn.createStatement(); + + ResultSet rs = stmt.executeQuery("SELECT 42 as a"); + assertTrue(rs.next()); + int res = rs.getInt(1); + assertEquals(res, 42); + + rs.close(); + stmt.close(); + conn.close(); + } + public static void test_execute_exception() throws Exception { Connection conn = DriverManager.getConnection(JDBC_URL); Statement stmt = conn.createStatement();