Skip to content

Commit

Permalink
Fix time zone issue
Browse files Browse the repository at this point in the history
  • Loading branch information
zhicwu committed Dec 26, 2021
1 parent ffcec66 commit 7080f4e
Show file tree
Hide file tree
Showing 34 changed files with 1,190 additions and 339 deletions.
Expand Up @@ -437,10 +437,12 @@ static CompletableFuture<List<ClickHouseResponseSummary>> send(ClickHouseNode se
throw new IllegalArgumentException("Non-empty column list is required");
}

// FIXME better get the configuration from request/client
ClickHouseConfig config = new ClickHouseConfig();
ClickHouseValue[] templates = new ClickHouseValue[len];
int index = 0;
for (ClickHouseColumn column : columns) {
templates[index++] = ClickHouseValues.newValue(ClickHouseChecker.nonNull(column, "column"));
templates[index++] = ClickHouseValues.newValue(config, ClickHouseChecker.nonNull(column, "column"));
}

return send(server, sql, templates, params);
Expand All @@ -467,11 +469,6 @@ static CompletableFuture<List<ClickHouseResponseSummary>> send(ClickHouseNode se
throw new IllegalArgumentException("Non-empty templates and parameters are required");
}

final ClickHouseParameterizedQuery query = ClickHouseParameterizedQuery.of(sql);
if (!query.hasParameter()) {
throw new IllegalArgumentException("No named parameter found from the given query");
}

// in case the protocol is ANY
final ClickHouseNode theServer = ClickHouseCluster.probe(server);

Expand All @@ -483,8 +480,7 @@ static CompletableFuture<List<ClickHouseResponseSummary>> send(ClickHouseNode se
.nodeSelector(ClickHouseNodeSelector.of(theServer.getProtocol()))
.option(ClickHouseClientOption.ASYNC, false).build()) {
// format doesn't matter here as we only need a summary
ClickHouseRequest<?> request = client.connect(theServer).format(ClickHouseFormat.RowBinary)
.query(query);
ClickHouseRequest<?> request = client.connect(theServer).format(ClickHouseFormat.RowBinary).query(sql);
for (int i = 0; i < size; i++) {
Object[] o = params[i];
String[] arr = new String[len];
Expand Down Expand Up @@ -533,11 +529,6 @@ static CompletableFuture<List<ClickHouseResponseSummary>> send(ClickHouseNode se
return send(server, sql);
}

final ClickHouseParameterizedQuery query = ClickHouseParameterizedQuery.of(sql);
if (!query.hasParameter()) {
throw new IllegalArgumentException("No named parameter found from the given query");
}

// in case the protocol is ANY
final ClickHouseNode theServer = ClickHouseCluster.probe(server);

Expand All @@ -550,6 +541,7 @@ static CompletableFuture<List<ClickHouseResponseSummary>> send(ClickHouseNode se
.option(ClickHouseClientOption.ASYNC, false).build()) {
// format doesn't matter here as we only need a summary
ClickHouseRequest<?> request = client.connect(theServer).format(ClickHouseFormat.RowBinary);
ClickHouseParameterizedQuery query = ClickHouseParameterizedQuery.of(request.getConfig(), sql);
for (String[] p : params) {
try (ClickHouseResponse resp = request.query(query.apply(p)).execute().get()) {
list.add(resp.getSummary());
Expand Down
Expand Up @@ -132,8 +132,9 @@ protected static final Object mergeMetricRegistry(List<ClickHouseConfig> list) {
private final String sslKey;
private final boolean useObjectsInArray;
private final boolean useServerTimeZone;
private final String useTimeZone;
private final boolean useServerTimeZoneForDate;
private final TimeZone timeZoneForDate;
private final TimeZone useTimeZone;

// client specific options
private final Map<ClickHouseOption, Serializable> options;
Expand Down Expand Up @@ -212,8 +213,19 @@ public ClickHouseConfig(Map<ClickHouseOption, Serializable> options, ClickHouseC
this.sslKey = (String) getOption(ClickHouseClientOption.SSL_KEY);
this.useObjectsInArray = (boolean) getOption(ClickHouseClientOption.USE_OBJECTS_IN_ARRAYS);
this.useServerTimeZone = (boolean) getOption(ClickHouseClientOption.USE_SERVER_TIME_ZONE);
this.useServerTimeZoneForDate = (boolean) getOption(ClickHouseClientOption.USE_SERVER_TIME_ZONE_FOR_DATES);
this.useTimeZone = (String) getOption(ClickHouseClientOption.USE_TIME_ZONE);
this.useServerTimeZoneForDate = (boolean) getOption(ClickHouseClientOption.USE_SERVER_TIME_ZONE_FOR_DATE);

if (this.useServerTimeZone) {
this.useTimeZone = this.serverTimeZone;
} else {
String timeZone = (String) getOption(ClickHouseClientOption.USE_TIME_ZONE);
TimeZone tz = ClickHouseChecker.isNullOrBlank(timeZone) ? TimeZone.getDefault()
: TimeZone.getTimeZone(timeZone);
this.useTimeZone = this.serverTimeZone.equals(tz) ? this.serverTimeZone : tz;
}

this.timeZoneForDate = this.useServerTimeZoneForDate || this.serverTimeZone.equals(this.useTimeZone) ? null
: this.useTimeZone;

if (credentials == null) {
this.credentials = ClickHouseCredentials.fromUserAndPassword((String) getOption(ClickHouseDefaults.USER),
Expand Down Expand Up @@ -358,12 +370,24 @@ public boolean isUseServerTimeZone() {
return useServerTimeZone;
}

public String getUseTimeZone() {
return useTimeZone;
/**
* Gets time zone for date values.
*
* @return time zone, could be null when {@code time_zone_for_date} is set to
* {@code NONE}.
*/
public TimeZone getTimeZoneForDate() {
return timeZoneForDate;
}

public boolean isUseServerTimeZoneForDate() {
return useServerTimeZoneForDate;
/**
* Gets preferred time zone. When {@link #isUseServerTimeZone()} is
* {@code true}, this returns same time zone as {@link #getServerTimeZone()}.
*
* @return non-null preferred time zone
*/
public TimeZone getUseTimeZone() {
return useTimeZone;
}

public ClickHouseCredentials getDefaultCredentials() {
Expand Down
Expand Up @@ -35,14 +35,14 @@ protected static class QueryPart implements Serializable {
public final String paramName;
public final ClickHouseColumn paramType;

protected QueryPart(String part, int paramIndex, String paramName, String paramType,
protected QueryPart(ClickHouseConfig config, String part, int paramIndex, String paramName, String paramType,
Map<String, ClickHouseValue> map) {
this.part = part;
this.paramIndex = paramIndex;
this.paramName = paramName != null ? paramName : String.valueOf(paramIndex);
if (paramType != null) {
this.paramType = ClickHouseColumn.of("", paramType);
map.put(paramName, ClickHouseValues.newValue(this.paramType));
map.put(paramName, ClickHouseValues.newValue(config, this.paramType));
} else {
this.paramType = null;
map.putIfAbsent(paramName, null);
Expand Down Expand Up @@ -148,14 +148,16 @@ public static String apply(String sql, Map<String, String> params) {
/**
* Creates an instance by parsing the given query.
*
* @param query non-empty SQL query
* @param config non-null config
* @param query non-empty SQL query
* @return parameterized query
*/
public static ClickHouseParameterizedQuery of(String query) {
public static ClickHouseParameterizedQuery of(ClickHouseConfig config, String query) {
// cache if query.length() is greater than 1024?
return new ClickHouseParameterizedQuery(query);
return new ClickHouseParameterizedQuery(config, query);
}

protected final ClickHouseConfig config;
protected final String originalQuery;

private final List<QueryPart> parts;
Expand All @@ -165,9 +167,11 @@ public static ClickHouseParameterizedQuery of(String query) {
/**
* Default constructor.
*
* @param query non-blank query
* @param config non-null config
* @param query non-blank query
*/
protected ClickHouseParameterizedQuery(String query) {
protected ClickHouseParameterizedQuery(ClickHouseConfig config, String query) {
this.config = ClickHouseChecker.nonNull(config, "config");
originalQuery = ClickHouseChecker.nonBlank(query, "query");

parts = new LinkedList<>();
Expand Down Expand Up @@ -201,7 +205,7 @@ protected void addPart(String part, int paramIndex, String paramName, String par
paramName = String.valueOf(paramIndex);
}

parts.add(new QueryPart(part, paramIndex, paramName, paramType, names));
parts.add(new QueryPart(config, part, paramIndex, paramName, paramType, names));
}

/**
Expand Down Expand Up @@ -264,7 +268,7 @@ protected String parse() {
}
}

parts.add(new QueryPart(part, paramIndex, paramName, paramType, names));
parts.add(new QueryPart(config, part, paramIndex, paramName, paramType, names));
}
}
}
Expand Down
Expand Up @@ -367,7 +367,7 @@ public Optional<String> getQueryId() {
*/
public ClickHouseParameterizedQuery getPreparedQuery() {
if (preparedQuery == null) {
preparedQuery = ClickHouseParameterizedQuery.of(getQuery());
preparedQuery = ClickHouseParameterizedQuery.of(getConfig(), getQuery());
}

return preparedQuery;
Expand Down
Expand Up @@ -15,6 +15,7 @@
import java.net.Inet6Address;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
Expand Down Expand Up @@ -287,6 +288,16 @@ default LocalDateTime asDateTime() {
return asDateTime(0);
}

/**
* Gets value as {@link java.time.Instant}, using default scale(usually
* 0).
*
* @return date time, could be null
*/
default Instant asInstant() {
return asInstant(0);
}

/**
* Gets value as {@link java.time.OffsetDateTime}, using default scale(usually
* 0).
Expand Down Expand Up @@ -322,6 +333,21 @@ default LocalDateTime asDateTime(int scale) {
.convertToDateTime(asBigDecimal(ClickHouseChecker.between(scale, ClickHouseValues.PARAM_SCALE, 0, 9)));
}

/**
* Gets value as {@link java.time.Instant}.
*
* @param scale scale of the date time, between 0 (second) and 9 (nano second)
* @return instant, could be null
*/
default Instant asInstant(int scale) {
if (isNullOrEmpty()) {
return null;
}

return ClickHouseValues
.convertToInstant(asBigDecimal(ClickHouseChecker.between(scale, ClickHouseValues.PARAM_SCALE, 0, 9)));
}

/**
* Gets value as {@link java.time.OffsetDateTime}.
*
Expand Down Expand Up @@ -483,6 +509,8 @@ default <T, E extends Enum<E>> T asObject(Class<T> clazz) {
return clazz.cast(asDate());
} else if (clazz == LocalDateTime.class) {
return clazz.cast(asDateTime());
} else if (clazz == Instant.class) {
return clazz.cast(asInstant());
} else if (clazz == OffsetDateTime.class) {
return clazz.cast(asOffsetDateTime());
} else if (clazz == ZonedDateTime.class) {
Expand Down Expand Up @@ -927,6 +955,24 @@ default ClickHouseValue update(LocalDateTime value) {
: update(seconds);
}

/**
* Updates value.
*
* @param value value to update
* @return this object
*/
default ClickHouseValue update(Instant value) {
if (value == null) {
return resetToNullOrEmpty();
}

long seconds = value.getEpochSecond();
int nanos = value.getNano();
return nanos > 0
? update(BigDecimal.valueOf(seconds).add(BigDecimal.valueOf(nanos, 9).divide(ClickHouseValues.NANOS)))
: update(seconds);
}

/**
* Updates value.
*
Expand All @@ -937,6 +983,16 @@ default ClickHouseValue update(OffsetDateTime value) {
return update(value != null ? value.toLocalDateTime() : null);
}

/**
* Updates value.
*
* @param value value to update
* @return this object
*/
default ClickHouseValue update(ZonedDateTime value) {
return update(value != null ? value.toLocalDateTime() : null);
}

/**
* Updates value.
*
Expand Down Expand Up @@ -1126,8 +1182,12 @@ default ClickHouseValue update(Object value) {
return update((LocalTime) value);
} else if (value instanceof LocalDateTime) {
return update((LocalDateTime) value);
} else if (value instanceof Instant) {
return update((Instant) value);
} else if (value instanceof OffsetDateTime) {
return update((OffsetDateTime) value);
} else if (value instanceof ZonedDateTime) {
return update((ZonedDateTime) value);
} else if (value instanceof Collection) {
return update((Collection<?>) value);
} else if (value instanceof Enumeration) {
Expand Down

0 comments on commit 7080f4e

Please sign in to comment.