Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@

package com.google.cloud.spanner.connection;

import static com.google.cloud.spanner.connection.ReadOnlyStalenessUtil.parseTimeUnit;
import static com.google.cloud.spanner.connection.ReadOnlyStalenessUtil.toChronoUnit;

import com.google.cloud.spanner.ErrorCode;
import com.google.cloud.spanner.Options.RpcPriority;
import com.google.cloud.spanner.SpannerException;
Expand All @@ -27,15 +30,14 @@
import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.protobuf.Duration;
import com.google.protobuf.util.Durations;
import com.google.spanner.v1.DirectedReadOptions;
import java.time.Duration;
import java.time.temporal.ChronoUnit;
import java.util.Base64;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

Expand Down Expand Up @@ -165,9 +167,16 @@ public Integer convert(String value) {

/** Converter from string to {@link Duration}. */
static class DurationConverter implements ClientSideStatementValueConverter<Duration> {
private final String resetValue;

private final Pattern allowedValues;

public DurationConverter(String allowedValues) {
this("NULL", allowedValues);
}

DurationConverter(String resetValue, String allowedValues) {
this.resetValue = Preconditions.checkNotNull(resetValue);
// Remove the parentheses from the beginning and end.
this.allowedValues =
Pattern.compile(
Expand All @@ -183,62 +192,35 @@ public Class<Duration> getParameterClass() {
public Duration convert(String value) {
Matcher matcher = allowedValues.matcher(value);
if (matcher.find()) {
if (matcher.group(0).equalsIgnoreCase("null")) {
return Durations.fromNanos(0L);
if (value.trim().equalsIgnoreCase(resetValue)) {
return Duration.ZERO;
} else {
Duration duration =
ReadOnlyStalenessUtil.createDuration(
Long.parseLong(matcher.group(1)),
ReadOnlyStalenessUtil.parseTimeUnit(matcher.group(2)));
if (duration.getSeconds() == 0L && duration.getNanos() == 0) {
try {
Duration duration;
if (matcher.group(1) != null && matcher.group(2) != null) {
ChronoUnit unit = toChronoUnit(parseTimeUnit(matcher.group(2)));
duration = Duration.of(Long.parseLong(matcher.group(1)), unit);
} else {
duration = Duration.ofMillis(Long.parseLong(value.trim()));
}
if (duration.isZero()) {
return null;
}
return duration;
} catch (NumberFormatException exception) {
// Converters should return null for invalid values.
return null;
}
return duration;
}
}
return null;
}
}

/** Converter from string to {@link Duration}. */
static class PgDurationConverter implements ClientSideStatementValueConverter<Duration> {
private final Pattern allowedValues;

static class PgDurationConverter extends DurationConverter {
public PgDurationConverter(String allowedValues) {
// Remove the parentheses from the beginning and end.
this.allowedValues =
Pattern.compile(
"(?is)\\A" + allowedValues.substring(1, allowedValues.length() - 1) + "\\z");
}

@Override
public Class<Duration> getParameterClass() {
return Duration.class;
}

@Override
public Duration convert(String value) {
Matcher matcher = allowedValues.matcher(value);
if (matcher.find()) {
Duration duration;
if (matcher.group(0).equalsIgnoreCase("default")) {
return Durations.fromNanos(0L);
} else if (matcher.group(2) == null) {
duration =
ReadOnlyStalenessUtil.createDuration(
Long.parseLong(matcher.group(0)), TimeUnit.MILLISECONDS);
} else {
duration =
ReadOnlyStalenessUtil.createDuration(
Long.parseLong(matcher.group(1)),
ReadOnlyStalenessUtil.parseTimeUnit(matcher.group(2)));
}
if (duration.getSeconds() == 0L && duration.getNanos() == 0) {
return null;
}
return duration;
}
return null;
super("DEFAULT", allowedValues);
}
}

Expand Down Expand Up @@ -288,7 +270,7 @@ public TimestampBound convert(String value) {
try {
return TimestampBound.ofExactStaleness(
Long.parseLong(matcher.group(groupIndex + 2)),
ReadOnlyStalenessUtil.parseTimeUnit(matcher.group(groupIndex + 3)));
parseTimeUnit(matcher.group(groupIndex + 3)));
} catch (IllegalArgumentException e) {
throw SpannerExceptionFactory.newSpannerException(
ErrorCode.INVALID_ARGUMENT, e.getMessage());
Expand All @@ -297,7 +279,7 @@ public TimestampBound convert(String value) {
try {
return TimestampBound.ofMaxStaleness(
Long.parseLong(matcher.group(groupIndex + 2)),
ReadOnlyStalenessUtil.parseTimeUnit(matcher.group(groupIndex + 3)));
parseTimeUnit(matcher.group(groupIndex + 3)));
} catch (IllegalArgumentException e) {
throw SpannerExceptionFactory.newSpannerException(
ErrorCode.INVALID_ARGUMENT, e.getMessage());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
import com.google.cloud.spanner.Statement;
import com.google.cloud.spanner.TimestampBound;
import com.google.cloud.spanner.connection.PgTransactionMode.IsolationLevel;
import com.google.protobuf.Duration;
import com.google.spanner.v1.DirectedReadOptions;
import java.time.Duration;

/**
* The Cloud Spanner JDBC driver supports a number of client side statements that are interpreted by
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,11 @@
import com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType;
import com.google.common.base.MoreObjects;
import com.google.common.base.Preconditions;
import com.google.protobuf.Duration;
import com.google.spanner.v1.DirectedReadOptions;
import com.google.spanner.v1.PlanNode;
import com.google.spanner.v1.QueryPlan;
import com.google.spanner.v1.RequestOptions;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
Expand Down Expand Up @@ -205,14 +205,19 @@ public StatementResult statementShowAutocommitDmlMode() {

@Override
public StatementResult statementSetStatementTimeout(Duration duration) {
if (duration.getSeconds() == 0L && duration.getNanos() == 0) {
if (duration == null || duration.isZero()) {
getConnection().clearStatementTimeout();
} else {
com.google.protobuf.Duration protoDuration =
com.google.protobuf.Duration.newBuilder()
.setSeconds(duration.getSeconds())
.setNanos(duration.getNano())
.build();
TimeUnit unit =
ReadOnlyStalenessUtil.getAppropriateTimeUnit(
new ReadOnlyStalenessUtil.DurationGetter(duration));
new ReadOnlyStalenessUtil.DurationGetter(protoDuration));
getConnection()
.setStatementTimeout(ReadOnlyStalenessUtil.durationToUnits(duration, unit), unit);
.setStatementTimeout(ReadOnlyStalenessUtil.durationToUnits(protoDuration, unit), unit);
}
return noResult(SET_STATEMENT_TIMEOUT);
}
Expand Down Expand Up @@ -343,11 +348,7 @@ public StatementResult statementShowReturnCommitStats() {

@Override
public StatementResult statementSetMaxCommitDelay(Duration duration) {
getConnection()
.setMaxCommitDelay(
duration == null || duration.equals(Duration.getDefaultInstance())
? null
: java.time.Duration.ofSeconds(duration.getSeconds(), duration.getNanos()));
getConnection().setMaxCommitDelay(duration == null || duration.isZero() ? null : duration);
return noResult(SET_MAX_COMMIT_DELAY);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import com.google.cloud.spanner.TimestampBound.Mode;
import com.google.protobuf.Duration;
import com.google.protobuf.util.Durations;
import java.time.temporal.ChronoUnit;
import java.util.concurrent.TimeUnit;

/**
Expand Down Expand Up @@ -93,6 +94,31 @@ static TimeUnit parseTimeUnit(String unit) {
ErrorCode.INVALID_ARGUMENT, "Invalid option for time unit: " + unit);
}

/**
* Convert from {@link TimeUnit} to {@link ChronoUnit}. This code is copied from {@link
* TimeUnit#toChronoUnit()}, which is available in Java 9 and higher.
*/
static ChronoUnit toChronoUnit(TimeUnit timeUnit) {
switch (timeUnit) {
case NANOSECONDS:
return ChronoUnit.NANOS;
case MICROSECONDS:
return ChronoUnit.MICROS;
case MILLISECONDS:
return ChronoUnit.MILLIS;
case SECONDS:
return ChronoUnit.SECONDS;
case MINUTES:
return ChronoUnit.MINUTES;
case HOURS:
return ChronoUnit.HOURS;
case DAYS:
return ChronoUnit.DAYS;
default:
throw new IllegalArgumentException();
}
}

/**
* Internal interface that is used to generalize getting a time duration from Cloud Spanner
* read-only staleness settings.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -365,11 +365,21 @@
"statementType": "SET_STATEMENT_TIMEOUT",
"regex": "(?is)\\A\\s*set\\s+statement_timeout\\s*(?:=)\\s*(.*)\\z",
"method": "statementSetStatementTimeout",
"exampleStatements": ["set statement_timeout=null", "set statement_timeout='1s'", "set statement_timeout='100ms'", "set statement_timeout='10000us'", "set statement_timeout='9223372036854775807ns'"],
"exampleStatements": [
"set statement_timeout=null",
"set statement_timeout = null ",
"set statement_timeout='1s'",
"set statement_timeout = '1s' ",
"set statement_timeout=100",
"set statement_timeout = 100 ",
"set statement_timeout='100ms'",
"set statement_timeout='10000us'",
"set statement_timeout='9223372036854775807ns'"
],
"setStatement": {
"propertyName": "STATEMENT_TIMEOUT",
"separator": "=",
"allowedValues": "('(\\d{1,19})(s|ms|us|ns)'|NULL)",
"allowedValues": "('(\\d{1,19})(s|ms|us|ns)'|\\d{1,19}|NULL)",
"converterName": "ClientSideStatementValueConverters$DurationConverter"
}
},
Expand Down Expand Up @@ -485,11 +495,23 @@
"statementType": "SET_MAX_COMMIT_DELAY",
"regex": "(?is)\\A\\s*set\\s+max_commit_delay\\s*(?:=)\\s*(.*)\\z",
"method": "statementSetMaxCommitDelay",
"exampleStatements": ["set max_commit_delay=null", "set max_commit_delay='1s'", "set max_commit_delay='100ms'", "set max_commit_delay='10000us'", "set max_commit_delay='9223372036854775807ns'"],
"exampleStatements": [
"set max_commit_delay=null",
"set max_commit_delay = null",
"set max_commit_delay = null ",
"set max_commit_delay=1000",
"set max_commit_delay = 1000",
"set max_commit_delay = 1000 ",
"set max_commit_delay='1s'",
"set max_commit_delay = '1s'",
"set max_commit_delay = '1s' ",
"set max_commit_delay='100ms'",
"set max_commit_delay='10000us'",
"set max_commit_delay='9223372036854775807ns'"],
"setStatement": {
"propertyName": "MAX_COMMIT_DELAY",
"separator": "=",
"allowedValues": "('(\\d{1,19})(s|ms|us|ns)'|NULL)",
"allowedValues": "('(\\d{1,19})(s|ms|us|ns)'|\\d{1,19}|NULL)",
"converterName": "ClientSideStatementValueConverters$DurationConverter"
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -421,9 +421,13 @@
"method": "statementSetStatementTimeout",
"exampleStatements": [
"set statement_timeout=default",
"set statement_timeout = default ",
"set statement_timeout = DEFAULT ",
"set statement_timeout='1s'",
"set statement_timeout = '1s' ",
"set statement_timeout='100ms'",
"set statement_timeout=100",
"set statement_timeout = 100 ",
"set statement_timeout='10000us'",
"set statement_timeout='9223372036854775807ns'",
"set statement_timeout to default",
Expand All @@ -436,7 +440,7 @@
"setStatement": {
"propertyName": "STATEMENT_TIMEOUT",
"separator": "(?:=|\\s+TO\\s+)",
"allowedValues": "(\\d{1,19}|'(\\d{1,19})(s|ms|us|ns)'|DEFAULT)",
"allowedValues": "('(\\d{1,19})(s|ms|us|ns)'|\\d{1,19}|DEFAULT)",
"converterName": "ClientSideStatementValueConverters$PgDurationConverter"
}
},
Expand Down Expand Up @@ -651,11 +655,23 @@
"statementType": "SET_MAX_COMMIT_DELAY",
"regex": "(?is)\\A\\s*set\\s+spanner\\.max_commit_delay(?:\\s*=\\s*|\\s+to\\s+)(.*)\\z",
"method": "statementSetMaxCommitDelay",
"exampleStatements": ["set spanner.max_commit_delay=null", "set spanner.max_commit_delay='1s'", "set spanner.max_commit_delay='100ms'", "set spanner.max_commit_delay to '10000us'", "set spanner.max_commit_delay TO '9223372036854775807ns'"],
"exampleStatements": [
"set spanner.max_commit_delay=null",
"set spanner.max_commit_delay = NULL",
"set spanner.max_commit_delay = null ",
"set spanner.max_commit_delay='1s'",
"set spanner.max_commit_delay = '1s'",
"set spanner.max_commit_delay = '1s' ",
"set spanner.max_commit_delay=1000",
"set spanner.max_commit_delay = 1000",
"set spanner.max_commit_delay = 1000 ",
"set spanner.max_commit_delay='100ms'",
"set spanner.max_commit_delay to '10000us'",
"set spanner.max_commit_delay TO '9223372036854775807ns'"],
"setStatement": {
"propertyName": "SPANNER.MAX_COMMIT_DELAY",
"separator": "(?:=|\\s+TO\\s+)",
"allowedValues": "('(\\d{1,19})(s|ms|us|ns)'|NULL)",
"allowedValues": "('(\\d{1,19})(s|ms|us|ns)'|\\d{1,19}|NULL)",
"converterName": "ClientSideStatementValueConverters$DurationConverter"
}
},
Expand Down
Loading
Loading