Skip to content

Commit b1027ba

Browse files
authored
Merge pull request #1960 from ClickHouse/updated-testing-and-url-parsing
Testing and parsing and enhancements
2 parents ce65071 + a30f19d commit b1027ba

File tree

10 files changed

+988
-103
lines changed

10 files changed

+988
-103
lines changed

client-v2/src/main/java/com/clickhouse/client/api/Client.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,24 @@ public Builder() {
229229
.compressClientRequest(false);
230230
}
231231

232+
/**
233+
* Builds a client object with the provided configuration through URL parameters.
234+
*
235+
* @param url - URL formatted string with protocol, host, port, and client configuration settings.
236+
* @return Client - a client object
237+
*/
238+
public Builder fromUrl(String url) {
239+
try {
240+
Map<String, String> urlProperties = HttpAPIClientHelper.parseUrlParameters(new java.net.URL(url));
241+
this.addEndpoint(url);
242+
this.configuration.putAll(urlProperties);//TODO: Mostly just a placeholder for now
243+
} catch (java.net.MalformedURLException e) {
244+
throw new IllegalArgumentException("Configuration via URL should be done with a valid URL string", e);
245+
}
246+
247+
return this;
248+
}
249+
232250
/**
233251
* Server address to which client may connect. If there are multiple endpoints then client will
234252
* connect to one of them.

client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/BinaryStreamReader.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ public <T> T readValue(ClickHouseColumn column, Class<?> typeHint) throws IOExce
221221
} catch (EOFException e) {
222222
throw e;
223223
} catch (Exception e) {
224+
log.debug("Failed to read value for column {}, {}", column.getColumnName(), e.getLocalizedMessage());
224225
throw new ClientException("Failed to read value for column " + column.getColumnName(), e);
225226
}
226227
}

client-v2/src/main/java/com/clickhouse/client/api/internal/HttpAPIClientHelper.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,14 @@
6060
import java.net.NoRouteToHostException;
6161
import java.net.URI;
6262
import java.net.URISyntaxException;
63+
import java.net.URL;
6364
import java.net.UnknownHostException;
6465
import java.nio.charset.StandardCharsets;
6566
import java.security.NoSuchAlgorithmException;
6667
import java.util.Base64;
6768
import java.util.Collection;
6869
import java.util.Collections;
70+
import java.util.HashMap;
6971
import java.util.Map;
7072
import java.util.Set;
7173
import java.util.concurrent.TimeUnit;
@@ -580,4 +582,30 @@ public ClientException wrapException(String message, Exception cause) {
580582

581583
return new ClientException(message, cause);
582584
}
585+
586+
587+
/**
588+
* Parses URL parameters.
589+
* @param url
590+
* @return Map of parameters
591+
*/
592+
public static Map<String, String> parseUrlParameters(URL url) {
593+
Map<String, String> params = new HashMap<>();
594+
595+
try {
596+
String query = url.getQuery();
597+
if (query != null) {
598+
for (String pair : query.split("&")) {
599+
int idx = pair.indexOf("=");
600+
if (idx > 0) {
601+
params.put(pair.substring(0, idx), pair.substring(idx + 1));
602+
}
603+
}
604+
}
605+
} catch (Exception e) {
606+
LOG.error("Failed to parse URL parameters", e);
607+
}
608+
609+
return params;
610+
}
583611
}

jdbc-v2/src/main/java/com/clickhouse/jdbc/ConnectionImpl.java

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,12 @@ public class ConnectionImpl implements Connection, JdbcV2Wrapper {
2727
public ConnectionImpl(String url, Properties info) {
2828
log.debug("Creating connection to {}", url);
2929

30-
this.url = url;
30+
this.url = url;//Raw URL
3131
this.config = new JdbcConfiguration(url, info);
32-
this.client = new Client.Builder()
33-
.addEndpoint(config.getProtocol() + "://" + config.getHost() + ":" + config.getPort())
32+
this.client = new Client.Builder()
33+
.fromUrl(this.config.getUrl())//URL without prefix
3434
.setUsername(config.getUser())
35-
.setPassword(config.getPassword())
36-
.compressServerResponse(true)
37-
.setDefaultDatabase(config.getDatabase())
38-
.build();
35+
.setPassword(config.getPassword()).build();
3936
}
4037

4138
public String getUser() {

jdbc-v2/src/main/java/com/clickhouse/jdbc/Driver.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,10 @@ public boolean acceptsURL(String url) throws SQLException {
6060

6161
@Override
6262
public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException {
63-
if (!JdbcConfiguration.acceptsURL(url)) {
64-
return new DriverPropertyInfo[0];
65-
}
66-
return new JdbcConfiguration(url, info).getPropertyInfo();
63+
// if (!JdbcConfiguration.acceptsURL(url)) {
64+
// return new DriverPropertyInfo[0];
65+
// }
66+
return new DriverPropertyInfo[0];
6767
}
6868

6969
public static int getDriverMajorVersion() {

jdbc-v2/src/main/java/com/clickhouse/jdbc/ResultSetImpl.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import com.clickhouse.client.api.data_formats.ClickHouseBinaryFormatReader;
1818
import com.clickhouse.client.api.metadata.TableSchema;
1919
import com.clickhouse.client.api.query.QueryResponse;
20+
import com.clickhouse.jdbc.internal.SimpleArray;
2021
import org.slf4j.Logger;
2122
import org.slf4j.LoggerFactory;
2223

@@ -913,7 +914,11 @@ public Clob getClob(int columnIndex) throws SQLException {
913914
@Override
914915
public Array getArray(int columnIndex) throws SQLException {
915916
checkClosed();
916-
throw new SQLFeatureNotSupportedException("Array is not supported.");
917+
try {
918+
return new SimpleArray(reader.getList(columnIndex));
919+
} catch (Exception e) {
920+
throw new SQLException(e);
921+
}
917922
}
918923

919924
@Override
@@ -943,7 +948,11 @@ public Clob getClob(String columnLabel) throws SQLException {
943948
@Override
944949
public Array getArray(String columnLabel) throws SQLException {
945950
checkClosed();
946-
throw new SQLFeatureNotSupportedException("Array is not supported.");
951+
try {
952+
return new SimpleArray(reader.getList(columnLabel));
953+
} catch (Exception e) {
954+
throw new SQLException(e);
955+
}
947956
}
948957

949958
@Override

jdbc-v2/src/main/java/com/clickhouse/jdbc/internal/JdbcConfiguration.java

Lines changed: 7 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -17,51 +17,24 @@ public class JdbcConfiguration {
1717
public static final String PREFIX_CLICKHOUSE = "jdbc:clickhouse:";
1818
public static final String PREFIX_CLICKHOUSE_SHORT = "jdbc:ch:";
1919

20-
final String host;
21-
final int port;
22-
final String protocol;
23-
final String database;
2420
final String user;
2521
final String password;
26-
final Map<String, String> queryParams;
27-
28-
public String getDatabase() {
29-
return database;
30-
}
31-
32-
public String getHost() {
33-
return host;
34-
}
22+
final String url;
3523

3624
public String getPassword() {
3725
return password;
3826
}
3927

40-
public int getPort() {
41-
return port;
42-
}
43-
44-
public String getProtocol() {
45-
return protocol;
46-
}
47-
48-
public Map<String, String> getQueryParams() {
49-
return queryParams;
50-
}
51-
5228
public String getUser() {
5329
return user;
5430
}
5531

56-
public JdbcConfiguration(String url, Properties info) {
57-
Map<String, String> urlProperties = parseUrl(url);
58-
this.host = urlProperties.get("host");
59-
this.port = Integer.parseInt(urlProperties.get("port"));
60-
this.protocol = urlProperties.get("protocol");
61-
this.database = urlProperties.get("database") == null ? "default" : urlProperties.get("database");
62-
this.queryParams = urlProperties.get("queryParams") == null ? new HashMap<>() : parseQueryParams(urlProperties.get("queryParams"));
63-
32+
public String getUrl() {
33+
return url;
34+
}
6435

36+
public JdbcConfiguration(String url, Properties info) {
37+
this.url = stripUrlPrefix(url);
6538
this.user = info.getProperty("user", "default");
6639
this.password = info.getProperty("password", "");
6740
}
@@ -70,51 +43,7 @@ public static boolean acceptsURL(String url) {
7043
return url.startsWith(PREFIX_CLICKHOUSE) || url.startsWith(PREFIX_CLICKHOUSE_SHORT);
7144
}
7245

73-
public DriverPropertyInfo[] getPropertyInfo() {
74-
List<DriverPropertyInfo> properties = new ArrayList<>();
75-
properties.add(new DriverPropertyInfo("host", host));
76-
properties.add(new DriverPropertyInfo("port", String.valueOf(port)));
77-
properties.add(new DriverPropertyInfo("protocol", protocol));
78-
properties.add(new DriverPropertyInfo("database", database));
79-
properties.add(new DriverPropertyInfo("user", user));
80-
properties.add(new DriverPropertyInfo("password", "*REDACTED*"));
81-
properties.add(new DriverPropertyInfo("queryParams", queryParams.toString()));
82-
return properties.toArray(new DriverPropertyInfo[0]);
83-
}
84-
85-
private Map<String, String> parseUrl(String urlString) {
86-
log.debug("Parsing URL: {}", urlString);
87-
URL url;
88-
try {
89-
String urlStripped = stripUrlPrefix(urlString);
90-
int index = urlStripped.indexOf("//");
91-
if (index == 0) {//Add in the HTTP protocol if it is missing
92-
urlStripped = "http:" + urlStripped;
93-
}
94-
95-
url = new URL(urlStripped);
96-
} catch (MalformedURLException e) {
97-
throw new IllegalArgumentException("URL is malformed.");
98-
}
99-
100-
Map<String, String> urlProperties = new HashMap<>();
101-
urlProperties.put("host", url.getHost());
102-
urlProperties.put("protocol", url.getProtocol());
103-
urlProperties.put("port", String.valueOf(url.getPort() == -1 ?
104-
url.getProtocol().equalsIgnoreCase("HTTP") ? 8123 : 8443
105-
: url.getPort()));
106-
107-
try {
108-
urlProperties.put("database", url.getPath().substring(1));
109-
} catch (StringIndexOutOfBoundsException e) {
110-
urlProperties.put("database", "default");
111-
}
112-
113-
urlProperties.put("queryParams", url.getQuery());
114-
115-
return urlProperties;
116-
}
117-
private String stripUrlPrefix(String url) {
46+
public String stripUrlPrefix(String url) {
11847
if (url.startsWith(PREFIX_CLICKHOUSE)) {
11948
return url.substring(PREFIX_CLICKHOUSE.length());
12049
} else if (url.startsWith(PREFIX_CLICKHOUSE_SHORT)) {
@@ -123,15 +52,4 @@ private String stripUrlPrefix(String url) {
12352
throw new IllegalArgumentException("URL is not supported.");
12453
}
12554
}
126-
private Map<String, String> parseQueryParams(String queryParams) {
127-
if (queryParams == null || queryParams.isEmpty()) {
128-
return new HashMap<>(0);
129-
}
130-
131-
return Arrays.stream(queryParams.split("&"))
132-
.map(s -> {
133-
String[] parts = s.split("=");
134-
return new AbstractMap.SimpleImmutableEntry<>(parts[0], parts[1]);
135-
}).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
136-
}
13755
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package com.clickhouse.jdbc.internal;
2+
3+
import org.slf4j.Logger;
4+
import org.slf4j.LoggerFactory;
5+
6+
import java.sql.ResultSet;
7+
import java.sql.SQLException;
8+
import java.sql.SQLFeatureNotSupportedException;
9+
import java.sql.Types;
10+
import java.util.List;
11+
import java.util.Map;
12+
13+
public class SimpleArray implements java.sql.Array {
14+
private static final Logger log = LoggerFactory.getLogger(SimpleArray.class);
15+
Object[] array;
16+
int type; //java.sql.Types
17+
18+
public SimpleArray(List<Object> list) {
19+
if (list == null) {
20+
throw new IllegalArgumentException("List cannot be null");
21+
}
22+
23+
this.array = list.toArray();
24+
this.type = Types.OTHER;
25+
}
26+
27+
@Override
28+
public String getBaseTypeName() throws SQLException {
29+
return Object.class.getName();
30+
}
31+
32+
@Override
33+
public int getBaseType() throws SQLException {
34+
return type;
35+
}
36+
37+
@Override
38+
public Object getArray() throws SQLException {
39+
return array;
40+
}
41+
42+
@Override
43+
public Object getArray(Map<String, Class<?>> map) throws SQLException {
44+
throw new SQLFeatureNotSupportedException("getArray(Map<String, Class<?>>) is not supported");
45+
}
46+
47+
@Override
48+
public Object getArray(long index, int count) throws SQLException {
49+
try {
50+
Object[] smallerArray = new Object[count];
51+
System.arraycopy(array, (int) index, smallerArray, 0, count);
52+
return smallerArray;
53+
} catch (Exception e) {
54+
log.error("Failed to get array", e);
55+
throw new SQLException(e);
56+
}
57+
}
58+
59+
@Override
60+
public Object getArray(long index, int count, Map<String, Class<?>> map) throws SQLException {
61+
throw new SQLFeatureNotSupportedException("getArray(long, int, Map<String, Class<?>>) is not supported");
62+
}
63+
64+
@Override
65+
public ResultSet getResultSet() throws SQLException {
66+
throw new SQLFeatureNotSupportedException("getResultSet() is not supported");
67+
}
68+
69+
@Override
70+
public ResultSet getResultSet(Map<String, Class<?>> map) throws SQLException {
71+
throw new SQLFeatureNotSupportedException("getResultSet(Map<String, Class<?>>) is not supported");
72+
}
73+
74+
@Override
75+
public ResultSet getResultSet(long index, int count) throws SQLException {
76+
throw new SQLFeatureNotSupportedException("getResultSet(long, int) is not supported");
77+
}
78+
79+
@Override
80+
public ResultSet getResultSet(long index, int count, Map<String, Class<?>> map) throws SQLException {
81+
throw new SQLFeatureNotSupportedException("getResultSet(long, int, Map<String, Class<?>>) is not supported");
82+
}
83+
84+
@Override
85+
public void free() throws SQLException {
86+
array = null;
87+
}
88+
}

0 commit comments

Comments
 (0)