forked from duckdb/duckdb-java
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDuckDBDriver.java
More file actions
128 lines (108 loc) · 4.22 KB
/
DuckDBDriver.java
File metadata and controls
128 lines (108 loc) · 4.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package org.duckdb;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.DriverPropertyInfo;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.logging.Logger;
public class DuckDBDriver implements java.sql.Driver {
public static final String DUCKDB_READONLY_PROPERTY = "duckdb.read_only";
public static final String DUCKDB_USER_AGENT_PROPERTY = "custom_user_agent";
public static final String JDBC_STREAM_RESULTS = "jdbc_stream_results";
static final ScheduledThreadPoolExecutor scheduler;
static {
try {
DriverManager.registerDriver(new DuckDBDriver());
ThreadFactory tf = r -> new Thread(r, "duckdb-query-cancel-scheduler-thread");
scheduler = new ScheduledThreadPoolExecutor(1, tf);
scheduler.setRemoveOnCancelPolicy(true);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public Connection connect(String url, Properties info) throws SQLException {
if (!acceptsURL(url)) {
return null;
}
boolean read_only = false;
if (info == null) {
info = new Properties();
} else { // make a copy because we're removing the read only property below
info = (Properties) info.clone();
}
String prop_val = (String) info.remove(DUCKDB_READONLY_PROPERTY);
if (prop_val != null) {
String prop_clean = prop_val.trim().toLowerCase();
read_only = prop_clean.equals("1") || prop_clean.equals("true") || prop_clean.equals("yes");
}
ParsedProps pp = parsePropsFromUrl(url);
for (Map.Entry<String, String> en : pp.props.entrySet()) {
info.put(en.getKey(), en.getValue());
}
url = pp.shortUrl;
info.put("duckdb_api", "jdbc");
// Apache Spark passes this option when SELECT on a JDBC DataSource
// table is performed. It is the internal Spark option and is likely
// passed by mistake, so we need to ignore it to allow the connection
// to be established.
info.remove("path");
return DuckDBConnection.newConnection(url, read_only, info);
}
public boolean acceptsURL(String url) throws SQLException {
return null != url && url.startsWith("jdbc:duckdb:");
}
public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException {
DriverPropertyInfo[] ret = {};
return ret; // no properties
}
public int getMajorVersion() {
return 1;
}
public int getMinorVersion() {
return 0;
}
public boolean jdbcCompliant() {
return true; // of course!
}
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
throw new SQLFeatureNotSupportedException("no logger");
}
private static ParsedProps parsePropsFromUrl(String url) throws SQLException {
if (!url.contains(";")) {
return new ParsedProps(url);
}
String[] parts = url.split(";");
LinkedHashMap<String, String> props = new LinkedHashMap<>();
for (int i = 1; i < parts.length; i++) {
String entry = parts[i].trim();
if (entry.isEmpty()) {
continue;
}
String[] kv = entry.split("=");
if (2 != kv.length) {
throw new SQLException("Invalid URL entry: " + entry);
}
String key = kv[0].trim();
String value = kv[1].trim();
props.put(key, value);
}
String shortUrl = parts[0].trim();
return new ParsedProps(shortUrl, props);
}
private static class ParsedProps {
final String shortUrl;
final LinkedHashMap<String, String> props;
private ParsedProps(String url) {
this(url, new LinkedHashMap<>());
}
private ParsedProps(String shortUrl, LinkedHashMap<String, String> props) {
this.shortUrl = shortUrl;
this.props = props;
}
}
}