Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
centralized configuration for JDBC driver
  • Loading branch information
zhicwu committed Mar 18, 2023
commit 6fe47697fd055a3b4f1ce36a2550d8dff62d09e9
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
## 0.4.2

### New Features
* centralized configuration for JDBC driver using custom server setting `custom_jdbc_config`.
* support `BEGIN TRANSACTION`, `COMMIT`, and `ROLLBACK` in JDBC driver. [#975](https://github.com/ClickHouse/clickhouse-java/issues/975)
* new options for JDBC driver
* databaseTerm(catalog or schema, defaults to schema) [#1273](https://github.com/ClickHouse/clickhouse-java/issues/1273)
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ Java libraries for connecting to ClickHouse and processing data in various forma
| Transaction | Transaction | :white_check_mark: | supported since 0.3.2-patch11, use ClickHouse 22.7+ for native implicit transaction support |
| | Savepoint | :x: | |
| | XAConnection | :x: | |
| Misc. | Implicit Type Conversion | :white_check_mark: | String/number to Date/Time/Timestamp and more |
| | Centralized Configuration | :white_check_mark: | supported since 0.4.2, custom server setting `custom_jdbc_config` for all connected JDBC clients |

## Usage

Expand All @@ -60,11 +62,13 @@ The library can be downloaded from both [Github Releases](../../releases) and [M
```

### Java Client

See the [client docs on the ClickHouse website](https://clickhouse.com/docs/en/integrations/language-clients/java/client).

### JDBC Driver

See the [jdbc driver docs on the ClickHouse website](https://clickhouse.com/docs/en/integrations/language-clients/java/jdbc).

## Contributing

Check out our [contributing guide](./CONTRIBUTING.md).
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,18 @@ public ClickHouseClientBuilder removeOption(ClickHouseOption option) {
return this;
}

/**
* Removes all options.
*
* @return this builder
*/
public ClickHouseClientBuilder clearOptions() {
options.clear();
resetConfig();

return this;
}

/**
* Sets options.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -571,48 +571,6 @@ static void parseDatabase(String path, Map<String, String> params) {
}
}

static void parseOptions(String query, Map<String, String> params) {
if (ClickHouseChecker.isNullOrEmpty(query)) {
return;
}
int len = query.length();
for (int i = 0; i < len; i++) {
int index = query.indexOf('&', i);
if (index == i) {
continue;
}

String param;
if (index < 0) {
param = query.substring(i);
i = len;
} else {
param = query.substring(i, index);
i = index;
}
index = param.indexOf('=');
String key;
String value;
if (index < 0) {
key = ClickHouseUtils.decode(param);
if (key.charAt(0) == '!') {
key = key.substring(1);
value = Boolean.FALSE.toString();
} else {
value = Boolean.TRUE.toString();
}
} else {
key = ClickHouseUtils.decode(param.substring(0, index));
value = ClickHouseUtils.decode(param.substring(index + 1));
}

// any multi-value option? cluster?
if (!ClickHouseChecker.isNullOrEmpty(value)) {
params.put(key, value);
}
}
}

static void parseTags(String fragment, Set<String> tags) {
if (ClickHouseChecker.isNullOrEmpty(fragment)) {
return;
Expand Down Expand Up @@ -809,7 +767,7 @@ public static ClickHouseNode of(String uri, Map<?, ?> options) {
Map<String, String> params = new LinkedHashMap<>();
parseDatabase(normalizedUri.getPath(), params);

parseOptions(normalizedUri.getRawQuery(), params);
ClickHouseUtils.extractParameters(normalizedUri.getRawQuery(), params);

Set<String> tags = new LinkedHashSet<>();
parseTags(normalizedUri.getRawFragment(), tags);
Expand Down Expand Up @@ -867,7 +825,7 @@ public static ClickHouseNode of(URI uri, ClickHouseNode template) {
Map<String, String> params = new LinkedHashMap<>(template.options);
parseDatabase(uri.getPath(), params);

parseOptions(uri.getRawQuery(), params);
ClickHouseUtils.extractParameters(uri.getRawQuery(), params);

ClickHouseProtocol protocol = ClickHouseProtocol.fromUriScheme(scheme);
int port = extract(scheme, uri.getPort(), protocol, params);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,9 @@ public interface ClickHouseNodeManager extends Function<ClickHouseNodeSelector,
* @param status non-null status of the node
*/
void update(ClickHouseNode node, Status status);

/**
* Shuts down scheduled tasks if any.
*/
void shutdown();
}
Original file line number Diff line number Diff line change
Expand Up @@ -752,6 +752,17 @@ public Optional<ScheduledFuture<?>> scheduleHealthCheck() {
}));
}

@Override
public void shutdown() {
for (ScheduledFuture<?> future : new ScheduledFuture<?>[] {
discoveryFuture.get(), healthCheckFuture.get()
}) {
if (future != null && !future.isDone() && !future.isCancelled()) {
future.cancel(true);
}
}
}

@Override
public int hashCode() {
final int prime = 31;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import com.clickhouse.data.ClickHouseExternalTable;
import com.clickhouse.data.ClickHouseFile;
import com.clickhouse.data.ClickHouseFormat;
import com.clickhouse.data.ClickHouseFreezableMap;
import com.clickhouse.data.ClickHouseInputStream;
import com.clickhouse.data.ClickHouseOutputStream;
import com.clickhouse.data.ClickHousePassThruStream;
Expand Down Expand Up @@ -84,12 +85,18 @@ public static class Mutation extends ClickHouseRequest<Mutation> {
protected Mutation(ClickHouseRequest<?> request, boolean sealed) {
super(request.getClient(), request.server, request.serverRef, request.options, sealed);

if (request.options.isFreezed()) {
this.options.freeze();
}
// use headless format if possible
if (!sealed) {
format(request.getFormat().defaultInputFormat());
}

this.settings.putAll(request.settings);
if (request.settings.isFreezed()) {
this.settings.freeze();
}
this.txRef.set(request.txRef.get());

this.changeListener = request.changeListener;
Expand Down Expand Up @@ -317,7 +324,13 @@ public Mutation seal() {
req = new Mutation(this, true);
req.externalTables.addAll(externalTables);
req.options.putAll(options);
if (options.isFreezed()) {
req.options.freeze();
}
req.settings.putAll(settings);
if (settings.isFreezed()) {
req.settings.freeze();
}

req.namedParameters.putAll(namedParameters);

Expand Down Expand Up @@ -356,8 +369,8 @@ public Mutation seal() {
protected final AtomicReference<ClickHouseTransaction> txRef;

protected final List<ClickHouseExternalTable> externalTables;
protected final Map<ClickHouseOption, Serializable> options;
protected final Map<String, Serializable> settings;
protected final ClickHouseFreezableMap<ClickHouseOption, Serializable> options;
protected final ClickHouseFreezableMap<String, Serializable> settings;

protected final Map<String, String> namedParameters;

Expand Down Expand Up @@ -390,8 +403,8 @@ protected ClickHouseRequest(ClickHouseClient client, Function<ClickHouseNodeSele
this.txRef = new AtomicReference<>(null);

this.externalTables = new LinkedList<>();
this.options = new HashMap<>();
this.settings = new LinkedHashMap<>(client.getConfig().getCustomSettings());
this.options = ClickHouseFreezableMap.of(new HashMap<>());
this.settings = ClickHouseFreezableMap.of(new LinkedHashMap<>(client.getConfig().getCustomSettings()));
options(options);

this.namedParameters = new HashMap<>();
Expand Down Expand Up @@ -464,8 +477,14 @@ protected void resetCache() {
*/
public ClickHouseRequest<SelfT> copy() {
ClickHouseRequest<SelfT> req = new ClickHouseRequest<>(getClient(), server, serverRef, options, false);
if (options.isFreezed()) {
req.options.freeze();
}
req.externalTables.addAll(externalTables);
req.settings.putAll(settings);
if (settings.isFreezed()) {
req.settings.freeze();
}
req.namedParameters.putAll(namedParameters);
req.input = input;
req.writer = writer;
Expand Down Expand Up @@ -658,6 +677,28 @@ public ClickHouseParameterizedQuery getPreparedQuery() {
return preparedQuery;
}

/**
* Freezes settings to discard future changes.
*
* @return the request itself
*/
@SuppressWarnings("unchecked")
public SelfT freezeSettings() {
settings.freeze();
return (SelfT) this;
}

/**
* Unfreezes settings to accept future changes.
*
* @return the request itself
*/
@SuppressWarnings("unchecked")
public SelfT unfreezeSettings() {
settings.unfreeze();
return (SelfT) this;
}

/**
* Gets typed setting value.
*
Expand Down Expand Up @@ -994,6 +1035,28 @@ public SelfT manager(ClickHouseRequestManager manager) {
return (SelfT) this;
}

/**
* Freezes options to discard future changes.
*
* @return the request itself
*/
@SuppressWarnings("unchecked")
public SelfT freezeOptions() {
options.freeze();
return (SelfT) this;
}

/**
* Unfreezes options to accept future changes.
*
* @return the request itself
*/
@SuppressWarnings("unchecked")
public SelfT unfreezeOptions() {
options.unfreeze();
return (SelfT) this;
}

/**
* Sets an option. {@code option} is for configuring client's behaviour, while
* {@code setting} is for server.
Expand All @@ -1012,17 +1075,19 @@ public SelfT option(ClickHouseOption option, Serializable value) {
value = ClickHouseOption.fromString(value.toString(), option.getValueType());
}

Serializable oldValue = options.put(ClickHouseChecker.nonNull(option, ClickHouseConfig.PARAM_OPTION), value); // NOSONAR
if (oldValue == null || !oldValue.equals(value)) {
if (changeListener != null) {
changeListener.optionChanged(this, option, oldValue, value);
if (option == ClickHouseClientOption.CUSTOM_SETTINGS) {
for (Entry<String, String> entry : ClickHouseOption.toKeyValuePairs(value.toString()).entrySet()) {
set(entry.getKey(), entry.getValue());
}
if (option == ClickHouseClientOption.CUSTOM_SETTINGS) {
for (Entry<String, String> entry : ClickHouseOption.toKeyValuePairs(value.toString()).entrySet()) {
set(entry.getKey(), entry.getValue());
} else {
Serializable oldValue = options.put(ClickHouseChecker.nonNull(option, ClickHouseConfig.PARAM_OPTION),
value); // NOSONAR
if (oldValue == null || !oldValue.equals(value)) {
if (changeListener != null) {
changeListener.optionChanged(this, option, oldValue, value);
}
resetCache();
}
resetCache();
}

return (SelfT) this;
Expand Down Expand Up @@ -2032,8 +2097,14 @@ public ClickHouseRequest<SelfT> seal() {
if (!isSealed()) {
// no idea which node we'll connect to until now
req = new ClickHouseRequest<>(client, getServer(), serverRef, options, true);
if (options.isFreezed()) {
req.options.freeze();
}
req.externalTables.addAll(externalTables);
req.settings.putAll(settings);
if (settings.isFreezed()) {
req.settings.freeze();
}

req.namedParameters.putAll(namedParameters);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,14 @@ public void testOptions() {
Assert.assertEquals(request.options.get(ClickHouseClientOption.DATABASE), "mydb");
Assert.assertEquals(request.options.get(ClickHouseClientOption.CLIENT_NAME), "new");
Assert.assertEquals(request.options.get(ClickHouseClientOption.FORMAT), ClickHouseFormat.CapnProto);

request.freezeOptions().option(ClickHouseClientOption.ASYNC, true).removeOption(ClickHouseClientOption.FORMAT);
Assert.assertEquals(request.options.get(ClickHouseClientOption.ASYNC), false);
Assert.assertEquals(request.options.get(ClickHouseClientOption.FORMAT), ClickHouseFormat.CapnProto);
request.unfreezeOptions().option(ClickHouseClientOption.ASYNC, true)
.removeOption(ClickHouseClientOption.FORMAT);
Assert.assertEquals(request.options.get(ClickHouseClientOption.ASYNC), true);
Assert.assertEquals(request.options.get(ClickHouseClientOption.FORMAT), null);
}

@Test(groups = { "unit" })
Expand Down Expand Up @@ -596,6 +604,13 @@ public void testSettings() {
Assert.assertEquals(request.getStatements().size(), 2);
Assert.assertEquals(request.getStatements().get(1),
"SET log_queries_min_type='EXCEPTION_WHILE_PROCESSING'");

request.freezeSettings().set("enable_optimize_predicate_expression", 2).removeSetting("log_queries_min_type");
Assert.assertEquals(request.settings.get("enable_optimize_predicate_expression"), 1);
Assert.assertEquals(request.settings.get("log_queries_min_type"), "EXCEPTION_WHILE_PROCESSING");
request.unfreezeSettings().set("enable_optimize_predicate_expression", 2).removeSetting("log_queries_min_type");
Assert.assertEquals(request.settings.get("enable_optimize_predicate_expression"), 2);
Assert.assertEquals(request.settings.get("log_queries_min_type"), null);
}

@Test(groups = { "unit" })
Expand Down
Loading