@@ -18,6 +18,7 @@ public class DuckDBDriver implements java.sql.Driver {
1818 public static final String JDBC_STREAM_RESULTS = "jdbc_stream_results" ;
1919 public static final String JDBC_AUTO_COMMIT = "jdbc_auto_commit" ;
2020 public static final String JDBC_PIN_DB = "jdbc_pin_db" ;
21+ public static final String JDBC_IGNORE_UNSUPPORTED_OPTIONS = "jdbc_ignore_unsupported_options" ;
2122
2223 static final String DUCKDB_URL_PREFIX = "jdbc:duckdb:" ;
2324 static final String MEMORY_DB = ":memory:" ;
@@ -37,6 +38,9 @@ public class DuckDBDriver implements java.sql.Driver {
3738 private static boolean pinnedDbRefsShutdownHookRegistered = false ;
3839 private static boolean pinnedDbRefsShutdownHookRun = false ;
3940
41+ private static final Set <String > supportedOptions = new LinkedHashSet <>();
42+ private static final ReentrantLock supportedOptionsLock = new ReentrantLock ();
43+
4044 static {
4145 try {
4246 DriverManager .registerDriver (new DuckDBDriver ());
@@ -59,13 +63,20 @@ public Connection connect(String url, Properties info) throws SQLException {
5963 props = (Properties ) info .clone ();
6064 }
6165
66+ // URL options
6267 ParsedProps pp = parsePropsFromUrl (url );
6368 for (Map .Entry <String , String > en : pp .props .entrySet ()) {
6469 props .put (en .getKey (), en .getValue ());
6570 }
6671
72+ // Ignore unsupported
73+ removeUnsupportedOptions (props );
74+
75+ // Read-only option
6776 String readOnlyStr = removeOption (props , DUCKDB_READONLY_PROPERTY );
6877 boolean readOnly = isStringTruish (readOnlyStr , false );
78+
79+ // Client name option
6980 props .put ("duckdb_api" , "jdbc" );
7081
7182 // Apache Spark passes this option when SELECT on a JDBC DataSource
@@ -74,6 +85,7 @@ public Connection connect(String url, Properties info) throws SQLException {
7485 // to be established.
7586 props .remove ("path" );
7687
88+ // DuckLake options
7789 String ducklake = removeOption (props , DUCKLAKE_OPTION );
7890 String ducklakeAlias = removeOption (props , DUCKLAKE_ALIAS_OPTION , DUCKLAKE_OPTION );
7991 final String shortUrl ;
@@ -90,9 +102,11 @@ public Connection connect(String url, Properties info) throws SQLException {
90102 shortUrl = pp .shortUrl ;
91103 }
92104
105+ // Pin DB option
93106 String pinDbOptStr = removeOption (props , JDBC_PIN_DB );
94107 boolean pinDBOpt = isStringTruish (pinDbOptStr , false );
95108
109+ // Create connection
96110 DuckDBConnection conn = DuckDBConnection .newConnection (shortUrl , readOnly , props );
97111
98112 pinDB (pinDBOpt , shortUrl , conn );
@@ -123,6 +137,8 @@ public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws
123137 list .add (createDriverPropInfo (JDBC_AUTO_COMMIT , "" , "Set default auto-commit mode" ));
124138 list .add (createDriverPropInfo (JDBC_PIN_DB , "" ,
125139 "Do not close the DB instance after all connections to it are closed" ));
140+ list .add (createDriverPropInfo (JDBC_IGNORE_UNSUPPORTED_OPTIONS , "" ,
141+ "Silently discard unsupported connection options" ));
126142 list .sort ((o1 , o2 ) -> o1 .name .compareToIgnoreCase (o2 .name ));
127143 return list .toArray (new DriverPropertyInfo [0 ]);
128144 }
@@ -258,6 +274,38 @@ private static DriverPropertyInfo createDriverPropInfo(String name, String value
258274 return dpi ;
259275 }
260276
277+ private static void removeUnsupportedOptions (Properties props ) throws SQLException {
278+ String ignoreStr = removeOption (props , JDBC_IGNORE_UNSUPPORTED_OPTIONS );
279+ boolean ignore = isStringTruish (ignoreStr , false );
280+ if (!ignore ) {
281+ return ;
282+ }
283+ supportedOptionsLock .lock ();
284+ try {
285+ if (supportedOptions .isEmpty ()) {
286+ Driver driver = DriverManager .getDriver (DUCKDB_URL_PREFIX );
287+ Properties dpiProps = new Properties ();
288+ dpiProps .put ("threads" , 1 );
289+ DriverPropertyInfo [] dpis = driver .getPropertyInfo (DUCKDB_URL_PREFIX , dpiProps );
290+ for (DriverPropertyInfo dpi : dpis ) {
291+ supportedOptions .add (dpi .name );
292+ }
293+ }
294+ List <String > unsupportedNames = new ArrayList <>();
295+ for (Object nameObj : props .keySet ()) {
296+ String name = String .valueOf (nameObj );
297+ if (!supportedOptions .contains (name )) {
298+ unsupportedNames .add (name );
299+ }
300+ }
301+ for (String name : unsupportedNames ) {
302+ props .remove (name );
303+ }
304+ } finally {
305+ supportedOptionsLock .unlock ();
306+ }
307+ }
308+
261309 private static class ParsedProps {
262310 final String shortUrl ;
263311 final LinkedHashMap <String , String > props ;
0 commit comments