@@ -18,6 +18,7 @@ public class DuckDBDriver implements java.sql.Driver {
18
18
public static final String JDBC_STREAM_RESULTS = "jdbc_stream_results" ;
19
19
public static final String JDBC_AUTO_COMMIT = "jdbc_auto_commit" ;
20
20
public static final String JDBC_PIN_DB = "jdbc_pin_db" ;
21
+ public static final String JDBC_IGNORE_UNSUPPORTED_OPTIONS = "jdbc_ignore_unsupported_options" ;
21
22
22
23
static final String DUCKDB_URL_PREFIX = "jdbc:duckdb:" ;
23
24
static final String MEMORY_DB = ":memory:" ;
@@ -37,6 +38,9 @@ public class DuckDBDriver implements java.sql.Driver {
37
38
private static boolean pinnedDbRefsShutdownHookRegistered = false ;
38
39
private static boolean pinnedDbRefsShutdownHookRun = false ;
39
40
41
+ private static final Set <String > supportedOptions = new LinkedHashSet <>();
42
+ private static final ReentrantLock supportedOptionsLock = new ReentrantLock ();
43
+
40
44
static {
41
45
try {
42
46
DriverManager .registerDriver (new DuckDBDriver ());
@@ -59,13 +63,20 @@ public Connection connect(String url, Properties info) throws SQLException {
59
63
props = (Properties ) info .clone ();
60
64
}
61
65
66
+ // URL options
62
67
ParsedProps pp = parsePropsFromUrl (url );
63
68
for (Map .Entry <String , String > en : pp .props .entrySet ()) {
64
69
props .put (en .getKey (), en .getValue ());
65
70
}
66
71
72
+ // Ignore unsupported
73
+ removeUnsupportedOptions (props );
74
+
75
+ // Read-only option
67
76
String readOnlyStr = removeOption (props , DUCKDB_READONLY_PROPERTY );
68
77
boolean readOnly = isStringTruish (readOnlyStr , false );
78
+
79
+ // Client name option
69
80
props .put ("duckdb_api" , "jdbc" );
70
81
71
82
// Apache Spark passes this option when SELECT on a JDBC DataSource
@@ -74,6 +85,7 @@ public Connection connect(String url, Properties info) throws SQLException {
74
85
// to be established.
75
86
props .remove ("path" );
76
87
88
+ // DuckLake options
77
89
String ducklake = removeOption (props , DUCKLAKE_OPTION );
78
90
String ducklakeAlias = removeOption (props , DUCKLAKE_ALIAS_OPTION , DUCKLAKE_OPTION );
79
91
final String shortUrl ;
@@ -90,9 +102,11 @@ public Connection connect(String url, Properties info) throws SQLException {
90
102
shortUrl = pp .shortUrl ;
91
103
}
92
104
105
+ // Pin DB option
93
106
String pinDbOptStr = removeOption (props , JDBC_PIN_DB );
94
107
boolean pinDBOpt = isStringTruish (pinDbOptStr , false );
95
108
109
+ // Create connection
96
110
DuckDBConnection conn = DuckDBConnection .newConnection (shortUrl , readOnly , props );
97
111
98
112
pinDB (pinDBOpt , shortUrl , conn );
@@ -123,6 +137,8 @@ public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws
123
137
list .add (createDriverPropInfo (JDBC_AUTO_COMMIT , "" , "Set default auto-commit mode" ));
124
138
list .add (createDriverPropInfo (JDBC_PIN_DB , "" ,
125
139
"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" ));
126
142
list .sort ((o1 , o2 ) -> o1 .name .compareToIgnoreCase (o2 .name ));
127
143
return list .toArray (new DriverPropertyInfo [0 ]);
128
144
}
@@ -258,6 +274,38 @@ private static DriverPropertyInfo createDriverPropInfo(String name, String value
258
274
return dpi ;
259
275
}
260
276
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
+
261
309
private static class ParsedProps {
262
310
final String shortUrl ;
263
311
final LinkedHashMap <String , String > props ;
0 commit comments