diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/AbstractStatementParser.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/AbstractStatementParser.java index 629ab9cca6a..8fc3043791e 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/AbstractStatementParser.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/AbstractStatementParser.java @@ -470,7 +470,7 @@ ParsedStatement parse(Statement statement, QueryOptions defaultQueryOptions) { ParsedStatement parsedStatement = statementCache.getIfPresent(statement.getSql()); if (parsedStatement == null) { - parsedStatement = internalParse(statement, null); + parsedStatement = internalParse(statement, defaultQueryOptions); statementCache.put(statement.getSql(), parsedStatement.forCache()); return parsedStatement; } diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/AbstractMockServerTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/AbstractMockServerTest.java index 43c57c8e21c..af67859b4a8 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/AbstractMockServerTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/AbstractMockServerTest.java @@ -36,6 +36,7 @@ import com.google.protobuf.ListValue; import com.google.protobuf.Value; import com.google.spanner.v1.ExecuteSqlRequest; +import com.google.spanner.v1.ResultSet; import com.google.spanner.v1.ResultSetMetadata; import com.google.spanner.v1.ResultSetStats; import com.google.spanner.v1.StructType; @@ -66,7 +67,10 @@ public abstract class AbstractMockServerTest { public static final long COUNT_AFTER_INSERT = 1L; public static final Statement SELECT_COUNT_STATEMENT = Statement.of("SELECT COUNT(*) AS C FROM TEST WHERE ID=1"); - private static final ResultSetMetadata SELECT_COUNT_METADATA = + + protected static final Statement SELECT1_STATEMENT = Statement.of("SELECT 1"); + + private static final ResultSetMetadata SINGLE_COL_INT64_RESULTSET_METADATA = ResultSetMetadata.newBuilder() .setRowType( StructType.newBuilder() @@ -86,7 +90,7 @@ public abstract class AbstractMockServerTest { .setStringValue(String.valueOf(COUNT_BEFORE_INSERT)) .build()) .build()) - .setMetadata(SELECT_COUNT_METADATA) + .setMetadata(SINGLE_COL_INT64_RESULTSET_METADATA) .build(); public static final com.google.spanner.v1.ResultSet SELECT_COUNT_RESULTSET_AFTER_INSERT = com.google.spanner.v1.ResultSet.newBuilder() @@ -95,7 +99,7 @@ public abstract class AbstractMockServerTest { .addValues( Value.newBuilder().setStringValue(String.valueOf(COUNT_AFTER_INSERT)).build()) .build()) - .setMetadata(SELECT_COUNT_METADATA) + .setMetadata(SINGLE_COL_INT64_RESULTSET_METADATA) .build(); public static final com.google.spanner.v1.ResultSet UPDATE_RETURNING_RESULTSET = com.google.spanner.v1.ResultSet.newBuilder() @@ -110,6 +114,16 @@ public abstract class AbstractMockServerTest { .setType(Type.newBuilder().setCodeValue(TypeCode.INT64_VALUE)) .build()))) .build(); + + protected static final ResultSet SELECT1_RESULTSET = + ResultSet.newBuilder() + .setMetadata(SINGLE_COL_INT64_RESULTSET_METADATA) + .addRows( + ListValue.newBuilder() + .addValues(Value.newBuilder().setStringValue("1").build()) + .build()) + .build(); + public static final Statement INSERT_STATEMENT = Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test aborted')"); public static final Statement INSERT_RETURNING_STATEMENT = @@ -173,6 +187,7 @@ public void getOperation( StatementResult.updateReturning(PG_INSERT_RETURNING_STATEMENT, UPDATE_RETURNING_RESULTSET)); mockSpanner.putStatementResult( StatementResult.query(SELECT_RANDOM_STATEMENT, RANDOM_RESULT_SET)); + mockSpanner.putStatementResult(StatementResult.query(SELECT1_STATEMENT, SELECT1_RESULTSET)); futureParentHandlers = Logger.getLogger(AbstractFuture.class.getName()).getUseParentHandlers(); exceptionRunnableParentHandlers = diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/QueryOptionsTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/QueryOptionsTest.java new file mode 100644 index 00000000000..627e8c7acc9 --- /dev/null +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/QueryOptionsTest.java @@ -0,0 +1,75 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spanner.connection; + +import static org.junit.Assert.assertEquals; + +import com.google.cloud.spanner.ResultSet; +import com.google.cloud.spanner.Statement; +import com.google.spanner.v1.ExecuteSqlRequest; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class QueryOptionsTest extends AbstractMockServerTest { + + @Test + public void testUseOptimizerVersionFromConnectionUrl() { + try (Connection connection = createConnection("?optimizerVersion=10")) { + Repeat.twice( + () -> { + executeSelect1AndConsumeResults(connection); + + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + ExecuteSqlRequest request = + mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0); + assertEquals("10", request.getQueryOptions().getOptimizerVersion()); + + mockSpanner.clearRequests(); + }); + } + } + + @Test + public void testUseOptimizerVersionFromStatement() { + try (Connection connection = createConnection()) { + connection.execute(Statement.of("set optimizer_version='7'")); + + Repeat.twice( + () -> { + executeSelect1AndConsumeResults(connection); + + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + ExecuteSqlRequest request = + mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0); + assertEquals("7", request.getQueryOptions().getOptimizerVersion()); + + mockSpanner.clearRequests(); + }); + } + } + + private void executeSelect1AndConsumeResults(Connection connection) { + try (ResultSet resultSet = connection.executeQuery(SELECT1_STATEMENT)) { + //noinspection StatementWithEmptyBody + while (resultSet.next()) { + // ignore + } + } + } +}