@@ -16,6 +16,7 @@ public class DuckDBDriver implements java.sql.Driver {
16
16
public static final String JDBC_STREAM_RESULTS = "jdbc_stream_results" ;
17
17
public static final String JDBC_AUTO_COMMIT = "jdbc_auto_commit" ;
18
18
public static final String JDBC_PIN_DB = "jdbc_pin_db" ;
19
+ public static final String JDBC_IGNORE_UNSUPPORTED_OPTIONS = "jdbc_ignore_unsupported_options" ;
19
20
20
21
static final String DUCKDB_URL_PREFIX = "jdbc:duckdb:" ;
21
22
static final String MEMORY_DB = ":memory:" ;
@@ -33,6 +34,9 @@ public class DuckDBDriver implements java.sql.Driver {
33
34
private static boolean pinnedDbRefsShutdownHookRegistered = false ;
34
35
private static boolean pinnedDbRefsShutdownHookRun = false ;
35
36
37
+ private static final Set <String > supportedOptions = new LinkedHashSet <>();
38
+ private static final ReentrantLock supportedOptionsLock = new ReentrantLock ();
39
+
36
40
static {
37
41
try {
38
42
DriverManager .registerDriver (new DuckDBDriver ());
@@ -52,13 +56,20 @@ public Connection connect(String url, Properties info) throws SQLException {
52
56
props = (Properties ) info .clone ();
53
57
}
54
58
59
+ // URL options
55
60
ParsedProps pp = parsePropsFromUrl (url );
56
61
for (Map .Entry <String , String > en : pp .props .entrySet ()) {
57
62
props .put (en .getKey (), en .getValue ());
58
63
}
59
64
65
+ // Ignore unsupported
66
+ removeUnsupportedOptions (props );
67
+
68
+ // Read-only option
60
69
String readOnlyStr = removeOption (props , DUCKDB_READONLY_PROPERTY );
61
70
boolean readOnly = isStringTruish (readOnlyStr , false );
71
+
72
+ // Client name option
62
73
props .put ("duckdb_api" , "jdbc" );
63
74
64
75
// Apache Spark passes this option when SELECT on a JDBC DataSource
@@ -67,6 +78,7 @@ public Connection connect(String url, Properties info) throws SQLException {
67
78
// to be established.
68
79
props .remove ("path" );
69
80
81
+ // DuckLake options
70
82
String ducklake = removeOption (props , DUCKLAKE_OPTION );
71
83
String ducklakeAlias = removeOption (props , DUCKLAKE_ALIAS_OPTION , DUCKLAKE_OPTION );
72
84
final String shortUrl ;
@@ -83,13 +95,13 @@ public Connection connect(String url, Properties info) throws SQLException {
83
95
shortUrl = pp .shortUrl ;
84
96
}
85
97
98
+ // Pin DB option
86
99
String pinDbOptStr = removeOption (props , JDBC_PIN_DB );
87
100
boolean pinDBOpt = isStringTruish (pinDbOptStr , false );
88
101
102
+ // Create connection
89
103
DuckDBConnection conn = DuckDBConnection .newConnection (shortUrl , readOnly , props );
90
-
91
104
pinDB (pinDBOpt , shortUrl , conn );
92
-
93
105
initDucklake (conn , shortUrl , ducklake , ducklakeAlias );
94
106
95
107
return conn ;
@@ -116,6 +128,8 @@ public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws
116
128
list .add (createDriverPropInfo (JDBC_AUTO_COMMIT , "" , "Set default auto-commit mode" ));
117
129
list .add (createDriverPropInfo (JDBC_PIN_DB , "" ,
118
130
"Do not close the DB instance after all connections to it are closed" ));
131
+ list .add (createDriverPropInfo (JDBC_IGNORE_UNSUPPORTED_OPTIONS , "" ,
132
+ "Silently discard unsupported connection options" ));
119
133
list .sort ((o1 , o2 ) -> o1 .name .compareToIgnoreCase (o2 .name ));
120
134
return list .toArray (new DriverPropertyInfo [0 ]);
121
135
}
@@ -251,6 +265,38 @@ private static DriverPropertyInfo createDriverPropInfo(String name, String value
251
265
return dpi ;
252
266
}
253
267
268
+ private static void removeUnsupportedOptions (Properties props ) throws SQLException {
269
+ String ignoreStr = removeOption (props , JDBC_IGNORE_UNSUPPORTED_OPTIONS );
270
+ boolean ignore = isStringTruish (ignoreStr , false );
271
+ if (!ignore ) {
272
+ return ;
273
+ }
274
+ supportedOptionsLock .lock ();
275
+ try {
276
+ if (supportedOptions .isEmpty ()) {
277
+ Driver driver = DriverManager .getDriver (DUCKDB_URL_PREFIX );
278
+ Properties dpiProps = new Properties ();
279
+ dpiProps .put ("threads" , 1 );
280
+ DriverPropertyInfo [] dpis = driver .getPropertyInfo (DUCKDB_URL_PREFIX , dpiProps );
281
+ for (DriverPropertyInfo dpi : dpis ) {
282
+ supportedOptions .add (dpi .name );
283
+ }
284
+ }
285
+ List <String > unsupportedNames = new ArrayList <>();
286
+ for (Object nameObj : props .keySet ()) {
287
+ String name = String .valueOf (nameObj );
288
+ if (!supportedOptions .contains (name )) {
289
+ unsupportedNames .add (name );
290
+ }
291
+ }
292
+ for (String name : unsupportedNames ) {
293
+ props .remove (name );
294
+ }
295
+ } finally {
296
+ supportedOptionsLock .unlock ();
297
+ }
298
+ }
299
+
254
300
private static class ParsedProps {
255
301
final String shortUrl ;
256
302
final LinkedHashMap <String , String > props ;
0 commit comments