Skip to content

Commit fbd16ec

Browse files
authored
feat: support 'select version()' and similar (#495)
Add support for `select version()` and similar commands.
1 parent e1f02fe commit fbd16ec

File tree

4 files changed

+160
-0
lines changed

4 files changed

+160
-0
lines changed
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
// Copyright 2022 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package com.google.cloud.spanner.pgadapter.statements.local;
16+
17+
import com.google.api.core.InternalApi;
18+
import com.google.cloud.spanner.ResultSet;
19+
import com.google.cloud.spanner.ResultSets;
20+
import com.google.cloud.spanner.Struct;
21+
import com.google.cloud.spanner.Type;
22+
import com.google.cloud.spanner.Type.StructField;
23+
import com.google.cloud.spanner.connection.StatementResult;
24+
import com.google.cloud.spanner.pgadapter.statements.BackendConnection;
25+
import com.google.cloud.spanner.pgadapter.statements.BackendConnection.QueryResult;
26+
import com.google.common.collect.ImmutableList;
27+
28+
@InternalApi
29+
public class SelectVersionStatement implements LocalStatement {
30+
public static final SelectVersionStatement INSTANCE = new SelectVersionStatement();
31+
32+
private SelectVersionStatement() {}
33+
34+
@Override
35+
public String[] getSql() {
36+
return new String[] {
37+
"select version()",
38+
"SELECT version()",
39+
"Select version()",
40+
"select VERSION()",
41+
"SELECT VERSION()",
42+
"Select VERSION()",
43+
"select * from version()",
44+
"SELECT * FROM version()",
45+
"Select * from version()",
46+
"select * from VERSION()",
47+
"SELECT * FROM VERSION()",
48+
"Select * from VERSION()",
49+
"select pg_catalog.version()",
50+
"SELECT pg_catalog.version()",
51+
"Select pg_catalog.version()",
52+
"select PG_CATALOG.VERSION()",
53+
"SELECT PG_CATALOG.VERSION()",
54+
"Select PG_CATALOG.VERSION()",
55+
"select * from pg_catalog.version()",
56+
"SELECT * FROM pg_catalog.version()",
57+
"Select * from pg_catalog.version()",
58+
"select * from PG_CATALOG.VERSION()",
59+
"SELECT * FROM PG_CATALOG.VERSION()",
60+
"Select * from PG_CATALOG.VERSION()"
61+
};
62+
}
63+
64+
@Override
65+
public StatementResult execute(BackendConnection backendConnection) {
66+
ResultSet resultSet =
67+
ResultSets.forRows(
68+
Type.struct(StructField.of("version", Type.string())),
69+
ImmutableList.of(
70+
Struct.newBuilder()
71+
.set("version")
72+
.to(
73+
"PostgreSQL "
74+
+ backendConnection
75+
.getSessionState()
76+
.get(null, "server_version")
77+
.getSetting())
78+
.build()));
79+
return new QueryResult(resultSet);
80+
}
81+
}

src/main/java/com/google/cloud/spanner/pgadapter/utils/ClientAutoDetector.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import com.google.cloud.spanner.pgadapter.statements.local.SelectCurrentCatalogStatement;
2323
import com.google.cloud.spanner.pgadapter.statements.local.SelectCurrentDatabaseStatement;
2424
import com.google.cloud.spanner.pgadapter.statements.local.SelectCurrentSchemaStatement;
25+
import com.google.cloud.spanner.pgadapter.statements.local.SelectVersionStatement;
2526
import com.google.common.collect.ImmutableList;
2627
import com.google.common.collect.ImmutableMap;
2728
import java.util.List;
@@ -41,6 +42,7 @@ public class ClientAutoDetector {
4142
SelectCurrentSchemaStatement.INSTANCE,
4243
SelectCurrentDatabaseStatement.INSTANCE,
4344
SelectCurrentCatalogStatement.INSTANCE,
45+
SelectVersionStatement.INSTANCE,
4446
DjangoGetTableNamesStatement.INSTANCE);
4547

4648
public enum WellKnownClient {

src/test/java/com/google/cloud/spanner/pgadapter/JdbcMockServerTest.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,31 @@ public void testSelectCurrentCatalog() throws SQLException {
227227
assertEquals(0, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class));
228228
}
229229

230+
@Test
231+
public void testSelectVersion() throws SQLException {
232+
for (String sql :
233+
new String[] {"SELECT version()", "select version()", "select * from version()"}) {
234+
235+
try (Connection connection = DriverManager.getConnection(createUrl())) {
236+
String version = null;
237+
try (ResultSet resultSet =
238+
connection.createStatement().executeQuery("show server_version")) {
239+
assertTrue(resultSet.next());
240+
version = resultSet.getString(1);
241+
assertFalse(resultSet.next());
242+
}
243+
try (ResultSet resultSet = connection.createStatement().executeQuery(sql)) {
244+
assertTrue(resultSet.next());
245+
assertEquals("PostgreSQL " + version, resultSet.getString("version"));
246+
assertFalse(resultSet.next());
247+
}
248+
}
249+
}
250+
251+
// The statement is handled locally and not sent to Cloud Spanner.
252+
assertEquals(0, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class));
253+
}
254+
230255
@Test
231256
public void testShowSearchPath() throws SQLException {
232257
String sql = "show search_path";
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Copyright 2022 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package com.google.cloud.spanner.pgadapter.statements.local;
16+
17+
import static org.junit.Assert.assertEquals;
18+
import static org.junit.Assert.assertFalse;
19+
import static org.junit.Assert.assertTrue;
20+
import static org.mockito.Mockito.mock;
21+
import static org.mockito.Mockito.when;
22+
23+
import com.google.cloud.spanner.ResultSet;
24+
import com.google.cloud.spanner.pgadapter.session.PGSetting;
25+
import com.google.cloud.spanner.pgadapter.session.SessionState;
26+
import com.google.cloud.spanner.pgadapter.statements.BackendConnection;
27+
import org.junit.Test;
28+
import org.junit.runner.RunWith;
29+
import org.junit.runners.JUnit4;
30+
31+
@RunWith(JUnit4.class)
32+
public class SelectVersionStatementTest {
33+
@Test
34+
public void testExecute() {
35+
for (String version : new String[] {"14.1", "10.0"}) {
36+
BackendConnection backendConnection = mock(BackendConnection.class);
37+
SessionState sessionState = mock(SessionState.class);
38+
PGSetting pgSetting = mock(PGSetting.class);
39+
when(backendConnection.getSessionState()).thenReturn(sessionState);
40+
when(sessionState.get(null, "server_version")).thenReturn(pgSetting);
41+
when(pgSetting.getSetting()).thenReturn(version);
42+
43+
try (ResultSet resultSet =
44+
SelectVersionStatement.INSTANCE.execute(backendConnection).getResultSet()) {
45+
assertTrue(resultSet.next());
46+
assertEquals(1, resultSet.getColumnCount());
47+
assertEquals("PostgreSQL " + version, resultSet.getString("version"));
48+
assertFalse(resultSet.next());
49+
}
50+
}
51+
}
52+
}

0 commit comments

Comments
 (0)