diff --git a/google-cloud-spanner/clirr-ignored-differences.xml b/google-cloud-spanner/clirr-ignored-differences.xml
index c6a936c51c..75f83555c9 100644
--- a/google-cloud-spanner/clirr-ignored-differences.xml
+++ b/google-cloud-spanner/clirr-ignored-differences.xml
@@ -618,4 +618,23 @@
com/google/cloud/spanner/TransactionContext
com.google.api.core.ApiFuture bufferAsync(java.lang.Iterable)
+
+
+
+
+ 7012
+ com/google/cloud/spanner/SpannerOptions$SpannerEnvironment
+ java.lang.String getOptimizerStatisticsPackage()
+
+
+ 7012
+ com/google/cloud/spanner/connection/Connection
+ java.lang.String getOptimizerStatisticsPackage()
+
+
+ 7012
+ com/google/cloud/spanner/connection/Connection
+ void setOptimizerStatisticsPackage(java.lang.String)
+
+
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerOptions.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerOptions.java
index 88587c6428..3274048c61 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerOptions.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerOptions.java
@@ -585,6 +585,15 @@ public interface SpannerEnvironment {
*/
@Nonnull
String getOptimizerVersion();
+
+ /**
+ * The optimizer statistics package to use. Must return an empty string to indicate that no
+ * value has been set.
+ */
+ @Nonnull
+ default String getOptimizerStatisticsPackage() {
+ throw new UnsupportedOperationException("Unimplemented");
+ }
}
/**
@@ -594,6 +603,8 @@ public interface SpannerEnvironment {
private static class SpannerEnvironmentImpl implements SpannerEnvironment {
private static final SpannerEnvironmentImpl INSTANCE = new SpannerEnvironmentImpl();
private static final String SPANNER_OPTIMIZER_VERSION_ENV_VAR = "SPANNER_OPTIMIZER_VERSION";
+ private static final String SPANNER_OPTIMIZER_STATISTICS_PACKAGE_ENV_VAR =
+ "SPANNER_OPTIMIZER_STATISTICS_PACKAGE";
private SpannerEnvironmentImpl() {}
@@ -601,6 +612,12 @@ private SpannerEnvironmentImpl() {}
public String getOptimizerVersion() {
return MoreObjects.firstNonNull(System.getenv(SPANNER_OPTIMIZER_VERSION_ENV_VAR), "");
}
+
+ @Override
+ public String getOptimizerStatisticsPackage() {
+ return MoreObjects.firstNonNull(
+ System.getenv(SPANNER_OPTIMIZER_STATISTICS_PACKAGE_ENV_VAR), "");
+ }
}
/** Builder for {@link SpannerOptions} instances. */
@@ -957,6 +974,7 @@ public Builder setDefaultQueryOptions(DatabaseId database, QueryOptions defaultQ
QueryOptions getEnvironmentQueryOptions() {
return QueryOptions.newBuilder()
.setOptimizerVersion(environment.getOptimizerVersion())
+ .setOptimizerStatisticsPackage(environment.getOptimizerStatisticsPackage())
.build();
}
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/Connection.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/Connection.java
index 813dda25cc..fb7e7bca01 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/Connection.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/Connection.java
@@ -96,6 +96,11 @@
*
* SET OPTIMIZER_VERSION='<version>' | 'LATEST'
*
: Sets the value of OPTIMIZER_VERSION
for this connection.
+ * SHOW OPTIMIZER_STATISTICS_PACKAGE
: Returns the current value of
+ * OPTIMIZER_STATISTICS_PACKAGE
of this connection as a {@link ResultSet}
+ *
+ * SET OPTIMIZER_STATISTICS_PACKAGE='<package>' | ''
+ *
: Sets the value of OPTIMIZER_STATISTICS_PACKAGE
for this connection.
* BEGIN [TRANSACTION]
: Begins a new transaction. This statement is optional when
* the connection is not in autocommit mode, as a new transaction will automatically be
* started when a query or update statement is issued. In autocommit mode, this statement will
@@ -448,6 +453,29 @@ public interface Connection extends AutoCloseable {
*/
String getOptimizerVersion();
+ /**
+ * Sets the query optimizer statistics package
+ *
+ * @param optimizerStatisticsPackage The query optimizer statistics package to use. Must be a
+ * string composed of letters, numbers, dashes and underscores or an empty string. The empty
+ * string will instruct the connection to use the optimizer statistics package that is defined
+ * the environment variable SPANNER_OPTIMIZER_STATISTICS_PACKAGE
. If no value is
+ * specified in the environment variable, the client level query optimizer is used. If none is
+ * set, the default query optimizer of Cloud Spanner is used.
+ */
+ default void setOptimizerStatisticsPackage(String optimizerStatisticsPackage) {
+ throw new UnsupportedOperationException("Unimplemented");
+ }
+
+ /**
+ * Gets the current query optimizer statistics package of this connection.
+ *
+ * @return The query optimizer statistics package that is currently used by this connection.
+ */
+ default String getOptimizerStatisticsPackage() {
+ throw new UnsupportedOperationException("Unimplemented");
+ }
+
/**
* Sets whether this connection should request commit statistics from Cloud Spanner for read/write
* transactions and DML statements in autocommit mode.
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionImpl.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionImpl.java
index 345c881d29..ecf79a8086 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionImpl.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionImpl.java
@@ -433,6 +433,20 @@ public String getOptimizerVersion() {
return this.queryOptions.getOptimizerVersion();
}
+ @Override
+ public void setOptimizerStatisticsPackage(String optimizerStatisticsPackage) {
+ Preconditions.checkNotNull(optimizerStatisticsPackage);
+ ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG);
+ this.queryOptions =
+ queryOptions.toBuilder().setOptimizerStatisticsPackage(optimizerStatisticsPackage).build();
+ }
+
+ @Override
+ public String getOptimizerStatisticsPackage() {
+ ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG);
+ return this.queryOptions.getOptimizerStatisticsPackage();
+ }
+
@Override
public void setStatementTimeout(long timeout, TimeUnit unit) {
Preconditions.checkArgument(timeout > 0L, "Zero or negative timeout values are not allowed");
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionOptions.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionOptions.java
index f5ccaddf6b..3a1f321d09 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionOptions.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionOptions.java
@@ -157,6 +157,7 @@ public String[] getValidValues() {
private static final String DEFAULT_NUM_CHANNELS = null;
private static final String DEFAULT_USER_AGENT = null;
private static final String DEFAULT_OPTIMIZER_VERSION = "";
+ private static final String DEFAULT_OPTIMIZER_STATISTICS_PACKAGE = "";
private static final boolean DEFAULT_RETURN_COMMIT_STATS = false;
private static final boolean DEFAULT_LENIENT = false;
@@ -190,6 +191,9 @@ public String[] getValidValues() {
private static final String USER_AGENT_PROPERTY_NAME = "userAgent";
/** Query optimizer version to use for a connection. */
private static final String OPTIMIZER_VERSION_PROPERTY_NAME = "optimizerVersion";
+ /** Query optimizer statistics package to use for a connection. */
+ private static final String OPTIMIZER_STATISTICS_PACKAGE_PROPERTY_NAME =
+ "optimizerStatisticsPackage";
/** Name of the 'lenientMode' connection property. */
public static final String LENIENT_PROPERTY_NAME = "lenient";
@@ -238,6 +242,8 @@ public String[] getValidValues() {
ConnectionProperty.createStringProperty(
OPTIMIZER_VERSION_PROPERTY_NAME,
"Sets the default query optimizer version to use for this connection."),
+ ConnectionProperty.createStringProperty(
+ OPTIMIZER_STATISTICS_PACKAGE_PROPERTY_NAME, ""),
ConnectionProperty.createBooleanProperty("returnCommitStats", "", false),
ConnectionProperty.createBooleanProperty(
"autoConfigEmulator",
@@ -521,6 +527,7 @@ private ConnectionOptions(Builder builder) {
this.userAgent = parseUserAgent(this.uri);
QueryOptions.Builder queryOptionsBuilder = QueryOptions.newBuilder();
queryOptionsBuilder.setOptimizerVersion(parseOptimizerVersion(this.uri));
+ queryOptionsBuilder.setOptimizerStatisticsPackage(parseOptimizerStatisticsPackage(this.uri));
this.queryOptions = queryOptionsBuilder.build();
this.returnCommitStats = parseReturnCommitStats(this.uri);
this.autoConfigEmulator = parseAutoConfigEmulator(this.uri);
@@ -695,6 +702,12 @@ static String parseOptimizerVersion(String uri) {
return value != null ? value : DEFAULT_OPTIMIZER_VERSION;
}
+ @VisibleForTesting
+ static String parseOptimizerStatisticsPackage(String uri) {
+ String value = parseUriProperty(uri, OPTIMIZER_STATISTICS_PACKAGE_PROPERTY_NAME);
+ return value != null ? value : DEFAULT_OPTIMIZER_STATISTICS_PACKAGE;
+ }
+
@VisibleForTesting
static boolean parseReturnCommitStats(String uri) {
String value = parseUriProperty(uri, "returnCommitStats");
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionStatementExecutor.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionStatementExecutor.java
index 5cbbdfb7c4..3f6dba9a40 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionStatementExecutor.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionStatementExecutor.java
@@ -66,6 +66,10 @@ interface ConnectionStatementExecutor {
StatementResult statementShowOptimizerVersion();
+ StatementResult statementSetOptimizerStatisticsPackage(String optimizerStatisticsPackage);
+
+ StatementResult statementShowOptimizerStatisticsPackage();
+
StatementResult statementSetReturnCommitStats(Boolean returnCommitStats);
StatementResult statementShowReturnCommitStats();
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionStatementExecutorImpl.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionStatementExecutorImpl.java
index 1d7a202c5e..0f3f7470a6 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionStatementExecutorImpl.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionStatementExecutorImpl.java
@@ -23,6 +23,7 @@
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.RUN_BATCH;
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SET_AUTOCOMMIT;
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SET_AUTOCOMMIT_DML_MODE;
+import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SET_OPTIMIZER_STATISTICS_PACKAGE;
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SET_OPTIMIZER_VERSION;
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SET_READONLY;
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SET_READ_ONLY_STALENESS;
@@ -34,6 +35,7 @@
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SHOW_AUTOCOMMIT_DML_MODE;
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SHOW_COMMIT_RESPONSE;
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SHOW_COMMIT_TIMESTAMP;
+import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SHOW_OPTIMIZER_STATISTICS_PACKAGE;
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SHOW_OPTIMIZER_VERSION;
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SHOW_READONLY;
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SHOW_READ_ONLY_STALENESS;
@@ -230,6 +232,20 @@ public StatementResult statementShowOptimizerVersion() {
"OPTIMIZER_VERSION", getConnection().getOptimizerVersion(), SHOW_OPTIMIZER_VERSION);
}
+ @Override
+ public StatementResult statementSetOptimizerStatisticsPackage(String optimizerStatisticsPackage) {
+ getConnection().setOptimizerStatisticsPackage(optimizerStatisticsPackage);
+ return noResult(SET_OPTIMIZER_STATISTICS_PACKAGE);
+ }
+
+ @Override
+ public StatementResult statementShowOptimizerStatisticsPackage() {
+ return resultSet(
+ "OPTIMIZER_STATISTICS_PACKAGE",
+ getConnection().getOptimizerStatisticsPackage(),
+ SHOW_OPTIMIZER_STATISTICS_PACKAGE);
+ }
+
@Override
public StatementResult statementSetReturnCommitStats(Boolean returnCommitStats) {
getConnection().setReturnCommitStats(returnCommitStats);
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/StatementResult.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/StatementResult.java
index 94269d6ac7..5ece3a20e9 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/StatementResult.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/StatementResult.java
@@ -65,6 +65,8 @@ enum ClientSideStatementType {
SET_READ_ONLY_STALENESS,
SHOW_OPTIMIZER_VERSION,
SET_OPTIMIZER_VERSION,
+ SHOW_OPTIMIZER_STATISTICS_PACKAGE,
+ SET_OPTIMIZER_STATISTICS_PACKAGE,
SHOW_RETURN_COMMIT_STATS,
SET_RETURN_COMMIT_STATS,
BEGIN,
diff --git a/google-cloud-spanner/src/main/resources/com/google/cloud/spanner/connection/ClientSideStatements.json b/google-cloud-spanner/src/main/resources/com/google/cloud/spanner/connection/ClientSideStatements.json
index 6761374ea5..4dfe480395 100644
--- a/google-cloud-spanner/src/main/resources/com/google/cloud/spanner/connection/ClientSideStatements.json
+++ b/google-cloud-spanner/src/main/resources/com/google/cloud/spanner/connection/ClientSideStatements.json
@@ -76,6 +76,14 @@
"method": "statementShowOptimizerVersion",
"exampleStatements": ["show variable optimizer_version"]
},
+ {
+ "name": "SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE",
+ "executorName": "ClientSideStatementNoParamExecutor",
+ "resultType": "RESULT_SET",
+ "regex": "(?is)\\A\\s*show\\s+variable\\s+optimizer_statistics_package\\s*\\z",
+ "method": "statementShowOptimizerStatisticsPackage",
+ "exampleStatements": ["show variable optimizer_statistics_package"]
+ },
{
"name": "SHOW VARIABLE RETURN_COMMIT_STATS",
"executorName": "ClientSideStatementNoParamExecutor",
@@ -281,6 +289,20 @@
"converterName": "ClientSideStatementValueConverters$StringValueConverter"
}
},
+ {
+ "name": "SET OPTIMIZER_STATISTICS_PACKAGE = ''|''",
+ "executorName": "ClientSideStatementSetExecutor",
+ "resultType": "NO_RESULT",
+ "regex": "(?is)\\A\\s*set\\s+optimizer_statistics_package\\s*(?:=)\\s*(.*)\\z",
+ "method": "statementSetOptimizerStatisticsPackage",
+ "exampleStatements": ["set optimizer_statistics_package='auto_20191128_14_47_22UTC'", "set optimizer_statistics_package=''"],
+ "setStatement": {
+ "propertyName": "OPTIMIZER_STATISTICS_PACKAGE",
+ "separator": "=",
+ "allowedValues": "'((\\S+)|())'",
+ "converterName": "ClientSideStatementValueConverters$StringValueConverter"
+ }
+ },
{
"name": "SET RETURN_COMMIT_STATS = TRUE|FALSE",
"executorName": "ClientSideStatementSetExecutor",
@@ -296,4 +318,4 @@
}
}
]
-}
\ No newline at end of file
+}
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/AbstractReadContextTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/AbstractReadContextTest.java
index 16f5dc8a25..66c3609d6f 100644
--- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/AbstractReadContextTest.java
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/AbstractReadContextTest.java
@@ -52,7 +52,12 @@ public static Collection