Skip to content

Commit 7a52db9

Browse files
authored
Merge pull request #1920 from ClickHouse/allow-v1-and-v2
Co-mingle Drivers
2 parents 1baf186 + 7a72ba7 commit 7a52db9

File tree

24 files changed

+514
-131
lines changed

24 files changed

+514
-131
lines changed

clickhouse-client/src/test/java/com/clickhouse/client/ClickHouseServerForTest.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -324,10 +324,12 @@ public static boolean isCloud() {
324324

325325
@BeforeSuite(groups = {"integration"})
326326
public static void beforeSuite() {
327-
if (isCloud()) {
327+
if (isCloud) {
328328
if (!runQuery("CREATE DATABASE IF NOT EXISTS " + database)) {
329329
throw new IllegalStateException("Failed to create database for testing.");
330330
}
331+
332+
return;
331333
}
332334

333335
if (clickhouseContainer != null) {
@@ -337,6 +339,10 @@ public static void beforeSuite() {
337339

338340
try {
339341
clickhouseContainer.start();
342+
343+
if (clickhouseContainer.isRunning()) {
344+
runQuery("CREATE DATABASE IF NOT EXISTS " + database);
345+
}
340346
} catch (RuntimeException e) {
341347
throw new IllegalStateException(new StringBuilder()
342348
.append("Failed to start docker container for integration test.\r\n")
@@ -353,7 +359,7 @@ public static void afterSuite() {
353359
clickhouseContainer.stop();
354360
}
355361

356-
if (isCloud()) {
362+
if (isCloud) {
357363
if (!runQuery("DROP DATABASE IF EXISTS " + database)) {
358364
LOGGER.warn("Failed to drop database for testing.");
359365
}

clickhouse-jdbc/pom.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@
5858
<artifactId>gson</artifactId>
5959
<optional>true</optional>
6060
</dependency>
61+
<dependency>
62+
<groupId>com.clickhouse</groupId>
63+
<artifactId>jdbc-v2</artifactId>
64+
<version>${revision}</version>
65+
</dependency>
6166
<dependency>
6267
<groupId>io.opencensus</groupId>
6368
<artifactId>opencensus-impl</artifactId>
@@ -303,6 +308,7 @@
303308
<include>org.apache.httpcomponents.client5:httpclient5</include>
304309
<include>org.apache.httpcomponents.core5:httpcore5</include>
305310
<include>org.apache.httpcomponents.core5:httpcore5-h2</include>
311+
<include>com.clickhouse:jdbc-v2</include>
306312
<include>org.lz4:lz4-pure-java</include>
307313
</includes>
308314
</artifactSet>
@@ -374,6 +380,7 @@
374380
<include>org.apache.httpcomponents.core5:httpcore5</include>
375381
<include>org.apache.httpcomponents.core5:httpcore5-h2</include>
376382
<include>org.lz4:lz4-pure-java</include>
383+
<include>com.clickhouse:jdbc-v2</include>
377384
</includes>
378385
</artifactSet>
379386
<relocations>

clickhouse-jdbc/src/main/java/com/clickhouse/jdbc/ClickHouseDataSource.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
import com.clickhouse.jdbc.internal.ClickHouseJdbcUrlParser.ConnectionInfo;
99

1010
import java.io.PrintWriter;
11+
import java.sql.Connection;
12+
import java.sql.DriverManager;
1113
import java.sql.SQLException;
1214
import java.sql.SQLFeatureNotSupportedException;
1315
import java.util.Properties;
@@ -38,6 +40,7 @@ public ClickHouseDataSource(String url, Properties properties) throws SQLExcepti
3840
}
3941

4042
this.driver = new ClickHouseDriver();
43+
new VersionSelectingDriver();//This is a workaround to make sure the driver is loaded
4144
this.connInfo = ClickHouseJdbcUrlParser.parse(url, properties);
4245
}
4346

clickhouse-jdbc/src/main/java/com/clickhouse/jdbc/ClickHouseDriver.java

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,13 @@
99
import java.util.*;
1010
import java.util.Map.Entry;
1111

12+
import org.slf4j.Logger;
13+
import org.slf4j.LoggerFactory;
14+
1215
import com.clickhouse.client.ClickHouseClient;
1316
import com.clickhouse.client.config.ClickHouseClientOption;
1417
import com.clickhouse.config.ClickHouseOption;
1518
import com.clickhouse.data.ClickHouseVersion;
16-
import com.clickhouse.logging.Logger;
17-
import com.clickhouse.logging.LoggerFactory;
1819
import com.clickhouse.jdbc.internal.ClickHouseConnectionImpl;
1920
import com.clickhouse.jdbc.internal.ClickHouseJdbcUrlParser;
2021

@@ -65,10 +66,10 @@ public static String getFrameworksDetected() {
6566
}
6667
return frameworksDetected;
6768
}
68-
6969
}
7070

7171
static {
72+
log.debug("Initializing ClickHouse JDBC driver V1");
7273
String str = ClickHouseDriver.class.getPackage().getImplementationVersion();
7374
if (str != null && !str.isEmpty()) {
7475
char[] chars = str.toCharArray();
@@ -85,14 +86,6 @@ public static String getFrameworksDetected() {
8586
driverVersion = ClickHouseVersion.of(driverVersionString);
8687
specVersion = ClickHouseVersion.of(ClickHouseDriver.class.getPackage().getSpecificationVersion());
8788

88-
try {
89-
DriverManager.registerDriver(new ClickHouseDriver());
90-
} catch (SQLException e) {
91-
throw new IllegalStateException(e);
92-
}
93-
94-
log.debug("ClickHouse Driver %s(JDBC: %s) registered", driverVersion, specVersion);
95-
9689
// client-specific options
9790
Map<Object, ClickHouseOption> m = new LinkedHashMap<>();
9891
try {
@@ -113,6 +106,26 @@ public static String getFrameworksDetected() {
113106
clientSpecificOptions = Collections.unmodifiableMap(m);
114107
}
115108

109+
public static void load() {
110+
try {
111+
log.info("Registering ClickHouse JDBC driver v1 ({})", driverVersion);
112+
DriverManager.registerDriver(new ClickHouseDriver());
113+
} catch (SQLException e) {
114+
throw new IllegalStateException(e);
115+
}
116+
117+
log.debug("ClickHouse Driver {}(JDBC: {}) registered", driverVersion, specVersion);
118+
}
119+
120+
public static void unload() {
121+
try {
122+
log.info("Unregistering ClickHouse JDBC driver v1 ({})", driverVersion);
123+
DriverManager.deregisterDriver(new ClickHouseDriver());
124+
} catch (SQLException e) {
125+
throw new IllegalStateException(e);
126+
}
127+
}
128+
116129
public static Map<ClickHouseOption, Serializable> toClientOptions(Properties props) {
117130
if (props == null || props.isEmpty()) {
118131
return Collections.emptyMap();
@@ -180,7 +193,7 @@ public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws
180193
try {
181194
info = ClickHouseJdbcUrlParser.parse(url, info).getProperties();
182195
} catch (Exception e) {
183-
log.error("Could not parse url %s", url, e);
196+
log.error("Could not parse url {}", url, e);
184197
}
185198

186199
List<DriverPropertyInfo> result = new ArrayList<>(ClickHouseClientOption.values().length * 2);
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package com.clickhouse.jdbc;
2+
3+
import javax.sql.DataSource;
4+
import java.io.PrintWriter;
5+
import java.sql.Connection;
6+
import java.sql.SQLException;
7+
import java.sql.SQLFeatureNotSupportedException;
8+
import java.util.Properties;
9+
10+
public class VersionSelectingDataSource implements javax.sql.DataSource, com.clickhouse.jdbc.JdbcV2Wrapper {
11+
private final DataSource dataSource;
12+
13+
public VersionSelectingDataSource(String url) throws SQLException {
14+
this(url, new Properties());
15+
}
16+
17+
public VersionSelectingDataSource(String url, Properties properties) throws SQLException {
18+
if (VersionSelectingDriver.isV2(url)) {
19+
//v2
20+
this.dataSource = new com.clickhouse.jdbc.DataSourceImpl(url, properties);
21+
} else {
22+
//v1
23+
this.dataSource = new ClickHouseDataSource(url, properties);
24+
}
25+
}
26+
27+
@Override
28+
public Connection getConnection() throws SQLException {
29+
return dataSource.getConnection();
30+
}
31+
32+
@Override
33+
public Connection getConnection(String username, String password) throws SQLException {
34+
return dataSource.getConnection(username, password);
35+
}
36+
37+
@Override
38+
public PrintWriter getLogWriter() throws SQLException {
39+
return dataSource.getLogWriter();
40+
}
41+
42+
@Override
43+
public void setLogWriter(PrintWriter out) throws SQLException {
44+
dataSource.setLogWriter(out);
45+
}
46+
47+
@Override
48+
public void setLoginTimeout(int seconds) throws SQLException {
49+
dataSource.setLoginTimeout(seconds);
50+
}
51+
52+
@Override
53+
public int getLoginTimeout() throws SQLException {
54+
return dataSource.getLoginTimeout();
55+
}
56+
57+
@Override
58+
public java.util.logging.Logger getParentLogger() throws SQLFeatureNotSupportedException {
59+
return dataSource.getParentLogger();
60+
}
61+
}
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
package com.clickhouse.jdbc;
2+
3+
import org.slf4j.Logger;
4+
import org.slf4j.LoggerFactory;
5+
6+
import java.sql.Connection;
7+
import java.sql.DriverPropertyInfo;
8+
import java.sql.SQLException;
9+
import java.sql.SQLFeatureNotSupportedException;
10+
import java.util.Properties;
11+
12+
public class VersionSelectingDriver implements java.sql.Driver {
13+
private static final Logger log = LoggerFactory.getLogger(VersionSelectingDriver.class);
14+
private java.sql.Driver driver;
15+
16+
static {
17+
load();
18+
}
19+
20+
public static void load() {
21+
try {
22+
log.debug("Loading the 'proxy' JDBC driver.");
23+
java.sql.DriverManager.registerDriver(new VersionSelectingDriver());
24+
} catch (SQLException e) {
25+
throw new RuntimeException("Failed to register ClickHouse JDBC driver", e);
26+
}
27+
}
28+
29+
public static void unload() {
30+
try {
31+
log.debug("Unloading the 'proxy' JDBC driver.");
32+
java.sql.DriverManager.deregisterDriver(new VersionSelectingDriver());
33+
} catch (SQLException e) {
34+
throw new RuntimeException("Failed to deregister ClickHouse JDBC driver", e);
35+
}
36+
}
37+
38+
public static boolean isV2() {
39+
return isV2(null);
40+
}
41+
42+
public static boolean isV2(String url) {
43+
log.debug("Checking if V2 driver is requested");
44+
boolean v2Flag = Boolean.parseBoolean(System.getProperty("clickhouse.jdbc.v2", "false"));
45+
46+
if (v2Flag || (url != null && url.contains("clickhouse.jdbc.v2=true"))) {
47+
log.debug("V2 driver is requested");
48+
return true;
49+
}
50+
51+
return false;
52+
}
53+
54+
55+
private java.sql.Driver getDriver(String url) {
56+
if (driver != null) {
57+
return driver;
58+
}
59+
60+
if (isV2(url)) {
61+
driver = new com.clickhouse.jdbc.Driver();
62+
} else {
63+
driver = new ClickHouseDriver();
64+
}
65+
66+
return driver;
67+
}
68+
69+
@Override
70+
public Connection connect(String url, Properties info) throws SQLException {
71+
java.sql.Driver driver = getDriver(url);
72+
return driver.connect(url, info);
73+
}
74+
75+
@Override
76+
public boolean acceptsURL(String url) throws SQLException {
77+
java.sql.Driver driver = getDriver(url);
78+
return driver.acceptsURL(url);
79+
}
80+
81+
@Override
82+
public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException {
83+
java.sql.Driver driver = getDriver(url);
84+
return driver.getPropertyInfo(url, info);
85+
}
86+
87+
@Override
88+
public int getMajorVersion() {
89+
return driver.getMajorVersion();
90+
}
91+
92+
@Override
93+
public int getMinorVersion() {
94+
return driver.getMinorVersion();
95+
}
96+
97+
@Override
98+
public boolean jdbcCompliant() {
99+
return driver.jdbcCompliant();
100+
}
101+
102+
@Override
103+
public java.util.logging.Logger getParentLogger() throws SQLFeatureNotSupportedException {
104+
return driver.getParentLogger();
105+
}
106+
}

clickhouse-jdbc/src/test/java/com/clickhouse/jdbc/ClickHouseConnectionTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
public class ClickHouseConnectionTest extends JdbcIntegrationTest {
2424
@Override
2525
public ClickHouseConnection newConnection(Properties properties) throws SQLException {
26-
return newDataSource(properties).getConnection();
26+
return (ClickHouseConnection) newDataSource(properties).getConnection();
2727
}
2828

2929
@Test(groups = "integration")

clickhouse-jdbc/src/test/java/com/clickhouse/jdbc/ClickHouseDataSourceTest.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
import java.util.Properties;
88

99
import com.clickhouse.client.ClickHouseServerForTest;
10+
import junit.runner.Version;
1011
import org.testng.Assert;
12+
import org.testng.annotations.Ignore;
1113
import org.testng.annotations.Test;
1214

1315
import com.clickhouse.client.ClickHouseLoadBalancingPolicy;
@@ -19,7 +21,7 @@
1921
public class ClickHouseDataSourceTest extends JdbcIntegrationTest {
2022
@Test(groups = "integration")
2123
public void testHighAvailabilityConfig() throws SQLException {
22-
if (isCloud()) return; //TODO: testHighAvailabilityConfig - Revisit, see: https://github.com/ClickHouse/clickhouse-java/issues/1747
24+
if (isCloud() || VersionSelectingDriver.isV2()) return; //TODO: testHighAvailabilityConfig - Revisit, see: https://github.com/ClickHouse/clickhouse-java/issues/1747
2325
String httpEndpoint = getEndpointString();
2426
String grpcEndpoint = "grpc://" + getServerAddress(ClickHouseProtocol.GRPC) + "/";
2527
String tcpEndpoint = "tcp://" + getServerAddress(ClickHouseProtocol.TCP) + "/";
@@ -36,8 +38,9 @@ public void testHighAvailabilityConfig() throws SQLException {
3638
}
3739

3840
@Test // (groups = "integration")
41+
@Ignore
3942
public void testMultiEndpoints() throws SQLException {
40-
if (isCloud()) return; //TODO: testMultiEndpoints - Revisit, see: https://github.com/ClickHouse/clickhouse-java/issues/1747
43+
if (isCloud() || VersionSelectingDriver.isV2()) return; //TODO: testMultiEndpoints - Revisit, see: https://github.com/ClickHouse/clickhouse-java/issues/1747
4144
String httpEndpoint = getEndpointString();
4245
String grpcEndpoint = "grpc://" + getServerAddress(ClickHouseProtocol.GRPC) + "/";
4346
String tcpEndpoint = "tcp://" + getServerAddress(ClickHouseProtocol.TCP) + "/";

clickhouse-jdbc/src/test/java/com/clickhouse/jdbc/ClickHouseResultSetTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,7 @@ public void testFetchSize() throws SQLException {
433433

434434
@Test(groups = "integration")
435435
public void testDateTimeWithoutTimezone() throws SQLException {
436-
final String sql = "select now(), toDateTime(now(), 'America/Los_Angeles') as tzTime SETTINGS session_timezone = 'America/Los_Angeles'";
436+
final String sql = "select now(), toDateTime(now(), 'America/New_York') as tzTime SETTINGS session_timezone = 'America/New_York'";
437437
// Default behavior
438438
try (ClickHouseConnection conn = newConnection(new Properties());
439439
Statement stmt = conn.createStatement()) {
@@ -445,8 +445,8 @@ public void testDateTimeWithoutTimezone() throws SQLException {
445445
ZonedDateTime serverNowZoned = rs.getObject(1, ZonedDateTime.class);
446446
Assert.assertTrue(serverNow.isEqual(tzTime.toLocalDateTime()));
447447
Assert.assertTrue(serverNow.isEqual(serverNowOffseted.toLocalDateTime()));
448-
Assert.assertEquals(tzTime.getOffset(), TimeZone.getTimeZone("America/Los_Angeles").toZoneId().getRules().getOffset(tzTime.toInstant()));
449-
Assert.assertEquals(serverNowZoned.getZone(), TimeZone.getTimeZone("America/Los_Angeles").toZoneId());
448+
Assert.assertEquals(tzTime.getOffset(), TimeZone.getTimeZone("America/New_York").toZoneId().getRules().getOffset(tzTime.toInstant()));
449+
Assert.assertEquals(serverNowZoned.getZone(), TimeZone.getTimeZone("America/New_York").toZoneId());
450450
Assert.assertEquals(serverNowZoned.toLocalDateTime(), serverNow);
451451

452452
Time serverNowTime = rs.getTime(1);

0 commit comments

Comments
 (0)