From 6bc086bfea58eea898bab84c7be307cbb2f8bcab Mon Sep 17 00:00:00 2001
From: "release-please[bot]"
<55107282+release-please[bot]@users.noreply.github.com>
Date: Wed, 21 Feb 2024 19:16:15 +0000
Subject: [PATCH 01/18] chore(main): release 2.15.6-SNAPSHOT (#1509)
:robot: I have created a release *beep* *boop*
---
### Updating meta-information for bleeding-edge SNAPSHOT release.
---
This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please).
---
pom.xml | 2 +-
samples/snapshot/pom.xml | 2 +-
versions.txt | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/pom.xml b/pom.xml
index 5a43ed346..1353d760b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
google-cloud-spanner-jdbc
- 2.15.5
+ 2.15.6-SNAPSHOT
jar
Google Cloud Spanner JDBC
https://github.com/googleapis/java-spanner-jdbc
diff --git a/samples/snapshot/pom.xml b/samples/snapshot/pom.xml
index 9a07ca1f5..fe95f8152 100644
--- a/samples/snapshot/pom.xml
+++ b/samples/snapshot/pom.xml
@@ -28,7 +28,7 @@
com.google.cloud
google-cloud-spanner-jdbc
- 2.15.5
+ 2.15.6-SNAPSHOT
diff --git a/versions.txt b/versions.txt
index 2c09e8c87..a6e48e1b8 100644
--- a/versions.txt
+++ b/versions.txt
@@ -1,4 +1,4 @@
# Format:
# module:released-version:current-version
-google-cloud-spanner-jdbc:2.15.5:2.15.5
+google-cloud-spanner-jdbc:2.15.5:2.15.6-SNAPSHOT
From 3ce948919fc0474076ea8903ed451778898349f5 Mon Sep 17 00:00:00 2001
From: Mend Renovate
Date: Thu, 22 Feb 2024 08:40:59 +0100
Subject: [PATCH 02/18] chore(deps): update dependency
com.google.cloud:libraries-bom to v26.33.0 (#1511)
---
samples/snippets/pom.xml | 2 +-
samples/spring-data-jdbc/pom.xml | 2 +-
samples/spring-data-mybatis/pom.xml | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/samples/snippets/pom.xml b/samples/snippets/pom.xml
index 70a8532c6..57231a4c7 100644
--- a/samples/snippets/pom.xml
+++ b/samples/snippets/pom.xml
@@ -30,7 +30,7 @@
com.google.cloud
libraries-bom
- 26.32.0
+ 26.33.0
pom
import
diff --git a/samples/spring-data-jdbc/pom.xml b/samples/spring-data-jdbc/pom.xml
index 383514617..900b0b235 100644
--- a/samples/spring-data-jdbc/pom.xml
+++ b/samples/spring-data-jdbc/pom.xml
@@ -30,7 +30,7 @@
com.google.cloud
libraries-bom
- 26.32.0
+ 26.33.0
import
pom
diff --git a/samples/spring-data-mybatis/pom.xml b/samples/spring-data-mybatis/pom.xml
index 120b79fa7..ba23fdb74 100644
--- a/samples/spring-data-mybatis/pom.xml
+++ b/samples/spring-data-mybatis/pom.xml
@@ -35,7 +35,7 @@
com.google.cloud
libraries-bom
- 26.32.0
+ 26.33.0
import
pom
From ca4082cbb4a7050147ee9d090e6f9efee3e8709e Mon Sep 17 00:00:00 2001
From: Mend Renovate
Date: Thu, 22 Feb 2024 08:42:37 +0100
Subject: [PATCH 03/18] chore(deps): update dependency
com.google.cloud:google-cloud-spanner-jdbc to v2.15.5 (#1510)
---
samples/install-without-bom/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/samples/install-without-bom/pom.xml b/samples/install-without-bom/pom.xml
index 5024bca92..93270ee3b 100644
--- a/samples/install-without-bom/pom.xml
+++ b/samples/install-without-bom/pom.xml
@@ -29,7 +29,7 @@
com.google.cloud
google-cloud-spanner-jdbc
- 2.15.4
+ 2.15.5
From cf8fe9eea2423f64867c9ecd790916b81165e575 Mon Sep 17 00:00:00 2001
From: Mend Renovate
Date: Fri, 23 Feb 2024 12:09:47 +0100
Subject: [PATCH 04/18] deps: update dependency
com.google.cloud:google-cloud-spanner-bom to v6.60.1 (#1514)
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index 1353d760b..c3941278e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -62,7 +62,7 @@
com.google.cloud
google-cloud-spanner-bom
- 6.60.0
+ 6.60.1
pom
import
From e5825c9a4aa9df68b1ca911430ef37cb6d3549c4 Mon Sep 17 00:00:00 2001
From: Mend Renovate
Date: Fri, 23 Feb 2024 12:10:06 +0100
Subject: [PATCH 05/18] deps: update dependency
org.springframework.boot:spring-boot-starter-data-jdbc to v3.2.3 (#1512)
---
samples/spring-data-jdbc/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/samples/spring-data-jdbc/pom.xml b/samples/spring-data-jdbc/pom.xml
index 900b0b235..6bcfd491d 100644
--- a/samples/spring-data-jdbc/pom.xml
+++ b/samples/spring-data-jdbc/pom.xml
@@ -41,7 +41,7 @@
org.springframework.boot
spring-boot-starter-data-jdbc
- 3.2.2
+ 3.2.3
From 8cfaa1a523c32ebed307f747fd939bd900c28b34 Mon Sep 17 00:00:00 2001
From: Mend Renovate
Date: Fri, 23 Feb 2024 12:10:38 +0100
Subject: [PATCH 06/18] deps: update dependency
org.springframework.boot:spring-boot-starter-parent to v3.2.3 (#1513)
---
samples/spring-data-mybatis/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/samples/spring-data-mybatis/pom.xml b/samples/spring-data-mybatis/pom.xml
index ba23fdb74..a32e7a800 100644
--- a/samples/spring-data-mybatis/pom.xml
+++ b/samples/spring-data-mybatis/pom.xml
@@ -13,7 +13,7 @@
org.springframework.boot
spring-boot-starter-parent
- 3.2.2
+ 3.2.3
From dd6e0ecf41a2e25535528e65f0a3c55cba77b4cf Mon Sep 17 00:00:00 2001
From: Mend Renovate
Date: Tue, 27 Feb 2024 20:25:29 +0100
Subject: [PATCH 07/18] build(deps): update dependency
com.google.cloud:google-cloud-shared-config to v1.7.2 (#1516)
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index c3941278e..5ff725fc1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -14,7 +14,7 @@
com.google.cloud
google-cloud-shared-config
- 1.7.1
+ 1.7.2
From 32e4c8794a43e3e89b1d312c73ed3d045425c355 Mon Sep 17 00:00:00 2001
From: Mend Renovate
Date: Thu, 29 Feb 2024 14:42:38 +0100
Subject: [PATCH 08/18] build(deps): update dependency
com.google.cloud:google-cloud-shared-config to v1.7.4 (#1517)
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index 5ff725fc1..6d4cef261 100644
--- a/pom.xml
+++ b/pom.xml
@@ -14,7 +14,7 @@
com.google.cloud
google-cloud-shared-config
- 1.7.2
+ 1.7.4
From 28986f9dddabfe2d89b2e3155885434413c3941e Mon Sep 17 00:00:00 2001
From: Mend Renovate
Date: Fri, 1 Mar 2024 07:37:39 +0100
Subject: [PATCH 09/18] deps: update dependency
com.google.cloud:sdk-platform-java-config to v3.27.0 (#1522)
---
.kokoro/presubmit/graalvm-native-17.cfg | 2 +-
.kokoro/presubmit/graalvm-native.cfg | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/.kokoro/presubmit/graalvm-native-17.cfg b/.kokoro/presubmit/graalvm-native-17.cfg
index 5e86d37f0..56db68092 100644
--- a/.kokoro/presubmit/graalvm-native-17.cfg
+++ b/.kokoro/presubmit/graalvm-native-17.cfg
@@ -3,7 +3,7 @@
# Configure the docker image for kokoro-trampoline.
env_vars: {
key: "TRAMPOLINE_IMAGE"
- value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.25.0"
+ value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.27.0"
}
env_vars: {
diff --git a/.kokoro/presubmit/graalvm-native.cfg b/.kokoro/presubmit/graalvm-native.cfg
index 8e8cded78..628318477 100644
--- a/.kokoro/presubmit/graalvm-native.cfg
+++ b/.kokoro/presubmit/graalvm-native.cfg
@@ -3,7 +3,7 @@
# Configure the docker image for kokoro-trampoline.
env_vars: {
key: "TRAMPOLINE_IMAGE"
- value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.25.0"
+ value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.27.0"
}
env_vars: {
From a8eecfb3a731505ba309b4a359dea7b88990c88a Mon Sep 17 00:00:00 2001
From: Mend Renovate
Date: Fri, 1 Mar 2024 07:37:57 +0100
Subject: [PATCH 10/18] deps: update dependency
com.google.cloud:google-cloud-shared-dependencies to v3.27.0 (#1521)
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index 6d4cef261..8085d0fd7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -69,7 +69,7 @@
com.google.cloud
google-cloud-shared-dependencies
- 3.25.0
+ 3.27.0
pom
import
From a457e3a4dc8cb378ab72d93e26168876a603da21 Mon Sep 17 00:00:00 2001
From: Mend Renovate
Date: Fri, 1 Mar 2024 19:47:35 +0100
Subject: [PATCH 11/18] test(deps): update dependency com.google.truth:truth to
v1.4.2 (#1519)
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index 8085d0fd7..f2e14a689 100644
--- a/pom.xml
+++ b/pom.xml
@@ -51,7 +51,7 @@
google-cloud-spanner-jdbc
4.13.2
3.0.2
- 1.4.1
+ 1.4.2
4.11.0
2.2
0.31.1
From fd428db155921d7300a8da478c5d5b370beeaa30 Mon Sep 17 00:00:00 2001
From: Mend Renovate
Date: Fri, 1 Mar 2024 19:47:54 +0100
Subject: [PATCH 12/18] test(deps): update dependency com.google.truth:truth to
v1.4.2 (#1520)
---
samples/install-without-bom/pom.xml | 2 +-
samples/snapshot/pom.xml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/samples/install-without-bom/pom.xml b/samples/install-without-bom/pom.xml
index 93270ee3b..0fabc41fb 100644
--- a/samples/install-without-bom/pom.xml
+++ b/samples/install-without-bom/pom.xml
@@ -42,7 +42,7 @@
com.google.truth
truth
- 1.4.1
+ 1.4.2
test
diff --git a/samples/snapshot/pom.xml b/samples/snapshot/pom.xml
index fe95f8152..832a1bf1f 100644
--- a/samples/snapshot/pom.xml
+++ b/samples/snapshot/pom.xml
@@ -41,7 +41,7 @@
com.google.truth
truth
- 1.4.1
+ 1.4.2
test
From 0c1e28177131f30405b09cf38fa7a78645a3508a Mon Sep 17 00:00:00 2001
From: Mend Renovate
Date: Tue, 5 Mar 2024 11:38:17 +0100
Subject: [PATCH 13/18] deps: update dependency
com.google.cloud:google-cloud-spanner-bom to v6.61.0 (#1523)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
[](https://renovatebot.com)
This PR contains the following updates:
| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [com.google.cloud:google-cloud-spanner-bom](https://togithub.com/googleapis/java-spanner) | `6.60.1` -> `6.61.0` | [](https://docs.renovatebot.com/merge-confidence/) | [](https://docs.renovatebot.com/merge-confidence/) | [](https://docs.renovatebot.com/merge-confidence/) | [](https://docs.renovatebot.com/merge-confidence/) |
---
### Release Notes
googleapis/java-spanner (com.google.cloud:google-cloud-spanner-bom)
### [`v6.61.0`](https://togithub.com/googleapis/java-spanner/blob/HEAD/CHANGELOG.md#6610-2024-03-04)
[Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.60.1...v6.61.0)
##### Features
- Support float32 type ([#2894](https://togithub.com/googleapis/java-spanner/issues/2894)) ([19b7976](https://togithub.com/googleapis/java-spanner/commit/19b79764294e938ad85d02b7c0662db6ec3afeda))
##### Bug Fixes
- Flaky test issue due to AbortedException. ([#2925](https://togithub.com/googleapis/java-spanner/issues/2925)) ([cd34c1d](https://togithub.com/googleapis/java-spanner/commit/cd34c1d3ae9a5a36f4d5516dcf7c3667a9cf015a))
##### Dependencies
- Update dependency com.google.cloud:sdk-platform-java-config to v3.27.0 ([#2935](https://togithub.com/googleapis/java-spanner/issues/2935)) ([f8f835a](https://togithub.com/googleapis/java-spanner/commit/f8f835a9da705605c492e232a58276c39d1d7e6c))
- Update dependency org.json:json to v20240303 ([#2936](https://togithub.com/googleapis/java-spanner/issues/2936)) ([1d7044e](https://togithub.com/googleapis/java-spanner/commit/1d7044e97d16f5296b7de020cd24b11cbe2a7df0))
##### Documentation
- Samples and tests for backup Admin APIs and overall spanner Admin APIs. ([#2882](https://togithub.com/googleapis/java-spanner/issues/2882)) ([de13636](https://togithub.com/googleapis/java-spanner/commit/de1363645e03f46deed5be41f90ddfed72766751))
- Update all public documents to use auto-generated admin clients. ([#2928](https://togithub.com/googleapis/java-spanner/issues/2928)) ([ccb110a](https://togithub.com/googleapis/java-spanner/commit/ccb110ad6835557870933c95cfd76580fd317a16))
---
### Configuration
📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).
🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.
â™» **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update again.
---
- [ ] If you want to rebase/retry this PR, check this box
---
This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/googleapis/java-spanner-jdbc).
---
pom.xml | 2 +-
.../cloud/spanner/jdbc/PartitionedQueryMockServerTest.java | 6 +++---
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/pom.xml b/pom.xml
index f2e14a689..9b9a6fb8a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -62,7 +62,7 @@
com.google.cloud
google-cloud-spanner-bom
- 6.60.1
+ 6.61.0
pom
import
diff --git a/src/test/java/com/google/cloud/spanner/jdbc/PartitionedQueryMockServerTest.java b/src/test/java/com/google/cloud/spanner/jdbc/PartitionedQueryMockServerTest.java
index 7144bfa2a..be5087fe4 100644
--- a/src/test/java/com/google/cloud/spanner/jdbc/PartitionedQueryMockServerTest.java
+++ b/src/test/java/com/google/cloud/spanner/jdbc/PartitionedQueryMockServerTest.java
@@ -158,7 +158,7 @@ public void testPartitionedQueryUsingSql() throws SQLException {
partitionStatement.setBoolean(1, true);
try (ResultSet results = partitionStatement.executeQuery()) {
assertNotNull(results.getMetaData());
- assertEquals(22, results.getMetaData().getColumnCount());
+ assertEquals(24, results.getMetaData().getColumnCount());
int rowCount = 0;
while (results.next()) {
rowCount++;
@@ -376,7 +376,7 @@ public void testAutoPartitionMode() throws SQLException {
try (ResultSet results =
connection.createStatement().executeQuery("select * from my_table where active=true")) {
assertNotNull(results.getMetaData());
- assertEquals(22, results.getMetaData().getColumnCount());
+ assertEquals(24, results.getMetaData().getColumnCount());
int rowCount = 0;
while (results.next()) {
rowCount++;
@@ -482,7 +482,7 @@ public void testAutoPartitionModeEmptyResult() throws SQLException {
try (ResultSet results =
connection.createStatement().executeQuery("select * from my_table where active=true")) {
assertNotNull(results.getMetaData());
- assertEquals(22, results.getMetaData().getColumnCount());
+ assertEquals(24, results.getMetaData().getColumnCount());
int rowCount = 0;
while (results.next()) {
rowCount++;
From a3c26da2d64ad066b57ee80ce2f661c8ff2b7843 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?=
Date: Wed, 6 Mar 2024 12:09:16 +0100
Subject: [PATCH 14/18] chore: remove custom type name implementation (#1525)
Remove the custom type name implementation in the JDBC driver and rely
on the implementation in the Java client library.
---
.../spanner/jdbc/AbstractJdbcWrapper.java | 60 +------------------
1 file changed, 1 insertion(+), 59 deletions(-)
diff --git a/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java b/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java
index b56aed037..86281af0d 100644
--- a/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java
+++ b/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java
@@ -71,65 +71,7 @@ static int extractColumnType(Type type) {
}
static String getSpannerTypeName(Type type, Dialect dialect) {
- // TODO: Use com.google.cloud.spanner.Type#getSpannerTypeName() when available.
- Preconditions.checkNotNull(type);
- switch (type.getCode()) {
- case BOOL:
- return dialect == Dialect.POSTGRESQL ? "boolean" : "BOOL";
- case BYTES:
- return dialect == Dialect.POSTGRESQL ? "bytea" : "BYTES";
- case DATE:
- return dialect == Dialect.POSTGRESQL ? "date" : "DATE";
- case FLOAT64:
- return dialect == Dialect.POSTGRESQL ? "double precision" : "FLOAT64";
- case INT64:
- return dialect == Dialect.POSTGRESQL ? "bigint" : "INT64";
- case NUMERIC:
- return "NUMERIC";
- case PG_NUMERIC:
- return "numeric";
- case STRING:
- return dialect == Dialect.POSTGRESQL ? "character varying" : "STRING";
- case JSON:
- return "JSON";
- case PG_JSONB:
- return "jsonb";
- case TIMESTAMP:
- return dialect == Dialect.POSTGRESQL ? "timestamp with time zone" : "TIMESTAMP";
- case STRUCT:
- return "STRUCT";
- case ARRAY:
- switch (type.getArrayElementType().getCode()) {
- case BOOL:
- return dialect == Dialect.POSTGRESQL ? "boolean[]" : "ARRAY";
- case BYTES:
- return dialect == Dialect.POSTGRESQL ? "bytea[]" : "ARRAY";
- case DATE:
- return dialect == Dialect.POSTGRESQL ? "date[]" : "ARRAY";
- case FLOAT64:
- return dialect == Dialect.POSTGRESQL ? "double precision[]" : "ARRAY";
- case INT64:
- return dialect == Dialect.POSTGRESQL ? "bigint[]" : "ARRAY";
- case NUMERIC:
- return "ARRAY";
- case PG_NUMERIC:
- return "numeric[]";
- case STRING:
- return dialect == Dialect.POSTGRESQL ? "character varying[]" : "ARRAY";
- case JSON:
- return "ARRAY";
- case PG_JSONB:
- return "jsonb[]";
- case TIMESTAMP:
- return dialect == Dialect.POSTGRESQL
- ? "timestamp with time zone[]"
- : "ARRAY";
- case STRUCT:
- return "ARRAY";
- }
- default:
- return null;
- }
+ return Preconditions.checkNotNull(type).getSpannerTypeName(dialect);
}
/**
From 90f35b36ead96e4439e275bf6d56f3e02c3fdb3d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?=
Date: Wed, 6 Mar 2024 18:10:16 +0100
Subject: [PATCH 15/18] test: enable integration tests for PG on emulator
(#1526)
The emulator now supports PostgreSQL, so we can enable the integration tests for PostgreSQL when running on the emulator.
This change also changes some of the tests that had workarounds for features that were initially missing in PostgreSQL, such as support for DATE and TIMESTAMPTZ.
---
.../spanner/jdbc/it/ITAbstractJdbcTest.java | 7 +-
.../spanner/jdbc/it/ITJdbcConnectTest.java | 3 +-
.../cloud/spanner/jdbc/it/ITJdbcDdlTest.java | 6 -
.../jdbc/it/ITJdbcPgDatabaseMetaDataTest.java | 11 +-
.../spanner/jdbc/it/ITJdbcPgNumericTest.java | 16 +-
.../jdbc/it/ITJdbcPreparedStatementTest.java | 233 ++++++------------
.../jdbc/it/ITJdbcQueryOptionsTest.java | 3 -
.../spanner/jdbc/it/ITJdbcReadOnlyTest.java | 5 -
.../it/ITJdbcReadWriteAutocommitTest.java | 5 -
.../spanner/jdbc/it/ITJdbcScriptTest.java | 18 +-
.../jdbc/it/ITJdbcSimpleStatementsTest.java | 4 -
.../jdbc/it/ITJdbcSqlMusicScriptTest.java | 6 -
.../ITReadWriteAutocommitSpannerTest.sql | 2 +-
.../ITScriptTest_TestGetReadTimestamp.sql | 8 +-
...ITSqlScriptTest_TestGetCommitTimestamp.sql | 138 +++++++++++
.../spanner/jdbc/it/CreateMusicTables_PG.sql | 9 +-
16 files changed, 241 insertions(+), 233 deletions(-)
create mode 100644 src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITSqlScriptTest_TestGetCommitTimestamp.sql
diff --git a/src/test/java/com/google/cloud/spanner/jdbc/it/ITAbstractJdbcTest.java b/src/test/java/com/google/cloud/spanner/jdbc/it/ITAbstractJdbcTest.java
index b6fb245c7..b2f949e2d 100644
--- a/src/test/java/com/google/cloud/spanner/jdbc/it/ITAbstractJdbcTest.java
+++ b/src/test/java/com/google/cloud/spanner/jdbc/it/ITAbstractJdbcTest.java
@@ -16,6 +16,8 @@
package com.google.cloud.spanner.jdbc.it;
+import static com.google.cloud.spanner.testing.EmulatorSpannerHelper.isUsingEmulator;
+
import com.google.cloud.spanner.Database;
import com.google.cloud.spanner.Dialect;
import com.google.cloud.spanner.GceTestEnvConfig;
@@ -23,7 +25,6 @@
import com.google.cloud.spanner.connection.ITAbstractSpannerTest;
import com.google.cloud.spanner.jdbc.CloudSpannerJdbcConnection;
import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier.JdbcGenericConnection;
-import com.google.cloud.spanner.testing.EmulatorSpannerHelper;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import java.nio.file.Files;
@@ -116,7 +117,7 @@ static Collection getMusicTablesDdl(Dialect dialect) {
default:
scriptFile = "CreateMusicTables.sql";
}
- if (EmulatorSpannerHelper.isUsingEmulator()) {
+ if (dialect != Dialect.POSTGRESQL && isUsingEmulator()) {
scriptFile = "CreateMusicTables_Emulator.sql";
}
return AbstractSqlScriptVerifier.readStatementsFromFile(scriptFile, ITAbstractJdbcTest.class)
@@ -130,7 +131,7 @@ public Dialect getDialect() {
}
public String getDefaultCatalog(Database database) {
- if (getDialect() == Dialect.POSTGRESQL) {
+ if (getDialect() == Dialect.POSTGRESQL && !isUsingEmulator()) {
return database.getId().getDatabase();
}
return "";
diff --git a/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java b/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java
index bf6d2892c..17bd65785 100644
--- a/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java
+++ b/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java
@@ -73,8 +73,7 @@ private String createBaseUrl() {
if (EmulatorSpannerHelper.isUsingEmulator()) {
url.append("//").append(System.getenv("SPANNER_EMULATOR_HOST"));
}
- // Extract "//x.y.googleapis.com" from "https://x.y.googleapis.com" and append it to
- // url.
+ // Extract "//x.y.googleapis.com" from "https://x.y.googleapis.com" and append it to url.
if (options.getHost() != null) {
url.append(options.getHost().substring(options.getHost().indexOf(':') + 1));
}
diff --git a/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDdlTest.java b/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDdlTest.java
index 5273cb4d3..88cffc0be 100644
--- a/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDdlTest.java
+++ b/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDdlTest.java
@@ -16,13 +16,10 @@
package com.google.cloud.spanner.jdbc.it;
-import static org.junit.Assume.assumeFalse;
-
import com.google.cloud.spanner.Database;
import com.google.cloud.spanner.Dialect;
import com.google.cloud.spanner.ParallelIntegrationTest;
import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier;
-import com.google.cloud.spanner.testing.EmulatorSpannerHelper;
import com.google.common.collect.ImmutableMap;
import java.util.ArrayList;
import java.util.Collections;
@@ -64,9 +61,6 @@ public static List data() {
@Before
public void setup() {
- assumeFalse(
- "Emulator does not support PostgreSQL",
- dialect.dialect == Dialect.POSTGRESQL && EmulatorSpannerHelper.isUsingEmulator());
database = env.getOrCreateDatabase(getDialect(), Collections.emptyList());
}
diff --git a/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgDatabaseMetaDataTest.java b/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgDatabaseMetaDataTest.java
index 56d75db1a..1b96e9569 100644
--- a/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgDatabaseMetaDataTest.java
+++ b/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgDatabaseMetaDataTest.java
@@ -21,12 +21,10 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
-import static org.junit.Assume.assumeFalse;
import com.google.cloud.spanner.Database;
import com.google.cloud.spanner.Dialect;
import com.google.cloud.spanner.ParallelIntegrationTest;
-import com.google.cloud.spanner.testing.EmulatorSpannerHelper;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
@@ -35,7 +33,6 @@
import java.util.Arrays;
import java.util.List;
import org.junit.Before;
-import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Ignore;
import org.junit.Test;
@@ -57,13 +54,6 @@ public class ITJdbcPgDatabaseMetaDataTest extends ITAbstractJdbcTest {
private static final String TABLE_WITH_ALL_COLS = "TableWithAllColumnTypes";
private static final String TABLE_WITH_REF = "TableWithRef";
- @BeforeClass
- public static void skipOnEmulator() {
- assumeFalse(
- "PostgreSQL dialect is not yet supported on the emulator",
- EmulatorSpannerHelper.isUsingEmulator());
- }
-
private Database database;
@Before
@@ -71,6 +61,7 @@ public void setup() {
database = env.getOrCreateDatabase(getDialect(), getMusicTablesDdl(getDialect()));
}
+ @Override
public Dialect getDialect() {
return Dialect.POSTGRESQL;
}
diff --git a/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgNumericTest.java b/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgNumericTest.java
index 57b3e8982..5527c8b95 100644
--- a/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgNumericTest.java
+++ b/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgNumericTest.java
@@ -16,10 +16,10 @@
package com.google.cloud.spanner.jdbc.it;
+import static com.google.cloud.spanner.testing.EmulatorSpannerHelper.isUsingEmulator;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThrows;
-import static org.junit.Assume.assumeFalse;
import com.google.cloud.spanner.Database;
import com.google.cloud.spanner.DatabaseAdminClient;
@@ -30,7 +30,6 @@
import com.google.cloud.spanner.Value;
import com.google.cloud.spanner.connection.ConnectionOptions;
import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcSqlExceptionImpl;
-import com.google.cloud.spanner.testing.EmulatorSpannerHelper;
import com.google.cloud.spanner.testing.RemoteSpannerHelper;
import java.math.BigDecimal;
import java.sql.Connection;
@@ -64,8 +63,6 @@ public class ITJdbcPgNumericTest {
@BeforeClass
public static void setup() throws Exception {
- assumeFalse(
- "PgNumeric is not supported in the emulator", EmulatorSpannerHelper.isUsingEmulator());
testHelper = env.getTestHelper();
final String projectId = testHelper.getInstanceId().getProject();
final String instanceId = testHelper.getInstanceId().getInstance();
@@ -83,6 +80,9 @@ public static void setup() throws Exception {
.createDatabase(databaseToCreate, Collections.emptyList())
.get(OPERATION_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS);
url = "jdbc:cloudspanner://" + host + "/" + database.getId() + "?dialect=postgresql";
+ if (isUsingEmulator()) {
+ url += ";usePlainText=true";
+ }
}
@AfterClass
@@ -95,8 +95,6 @@ public static void teardown() {
@Test
public void testResultSet() throws SQLException {
- assumeFalse(
- "PgNumeric is not supported in the emulator", EmulatorSpannerHelper.isUsingEmulator());
final String table = testHelper.getUniqueDatabaseId();
final String positiveBigNumeric =
String.join("", Collections.nCopies(131072, "1"))
@@ -124,7 +122,7 @@ public void testResultSet() throws SQLException {
try (Connection connection = DriverManager.getConnection(url);
Statement statement = connection.createStatement();
- ResultSet resultSet = statement.executeQuery("SELECT * FROM " + table)) {
+ ResultSet resultSet = statement.executeQuery("SELECT * FROM " + table + " ORDER BY id")) {
resultSet.next();
assertEquals("1.23", resultSet.getString("col1"));
@@ -190,8 +188,6 @@ public void testResultSet() throws SQLException {
@Test
public void testPreparedStatement() throws Exception {
- assumeFalse(
- "PgNumeric is not supported in the emulator", EmulatorSpannerHelper.isUsingEmulator());
final String table = testHelper.getUniqueDatabaseId();
try (Connection connection = DriverManager.getConnection(url);
Statement statement = connection.createStatement(); ) {
@@ -253,7 +249,7 @@ public void testPreparedStatement() throws Exception {
try (Connection connection = DriverManager.getConnection(url);
Statement statement = connection.createStatement();
- ResultSet resultSet = statement.executeQuery("SELECT * FROM " + table)) {
+ ResultSet resultSet = statement.executeQuery("SELECT * FROM " + table + " ORDER BY id")) {
resultSet.next();
assertNull(resultSet.getObject("col1"));
diff --git a/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java b/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java
index 8f014937a..2fb170a98 100644
--- a/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java
+++ b/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java
@@ -16,7 +16,6 @@
package com.google.cloud.spanner.jdbc.it;
-import static com.google.cloud.spanner.testing.EmulatorSpannerHelper.isUsingEmulator;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -32,7 +31,6 @@
import com.google.cloud.spanner.ParallelIntegrationTest;
import com.google.cloud.spanner.Value;
import com.google.cloud.spanner.jdbc.JsonType;
-import com.google.cloud.spanner.testing.EmulatorSpannerHelper;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.io.BaseEncoding;
@@ -91,9 +89,6 @@ public static List data() {
@Before
public void setup() {
- assumeFalse(
- "Emulator does not support PostgreSQL",
- dialect.dialect == Dialect.POSTGRESQL && EmulatorSpannerHelper.isUsingEmulator());
database = env.getOrCreateDatabase(getDialect(), getMusicTablesDdl(getDialect()));
}
@@ -137,11 +132,7 @@ private void setPreparedStatement(PreparedStatement ps, Dialect dialect) throws
ps.setString(2, this.firstName);
ps.setString(3, this.lastName);
ps.setBytes(4, this.singerInfo);
- if (dialect == Dialect.POSTGRESQL) {
- ps.setString(5, this.birthDate.toString());
- } else {
- ps.setDate(5, this.birthDate);
- }
+ ps.setDate(5, this.birthDate);
}
}
@@ -253,34 +244,22 @@ private void setPreparedStatement(Connection connection, PreparedStatement ps, D
throws SQLException {
ps.setLong(1, this.venueId);
ps.setLong(2, this.singerId);
- if (dialect == Dialect.POSTGRESQL) {
- ps.setString(3, this.concertDate.toString());
- ps.setString(4, this.beginTime.toString());
- ps.setString(5, this.endTime.toString());
- } else {
- ps.setDate(3, this.concertDate);
- ps.setTimestamp(4, this.beginTime);
- ps.setTimestamp(5, this.endTime);
- ps.setArray(6, connection.createArrayOf("INT64", this.ticketPrices));
- }
+ ps.setDate(3, this.concertDate);
+ ps.setTimestamp(4, this.beginTime);
+ ps.setTimestamp(5, this.endTime);
+ ps.setArray(6, connection.createArrayOf("INT64", this.ticketPrices));
}
private void assertEqualsFields(Connection connection, ResultSet rs, Dialect dialect)
throws SQLException {
assertEquals(rs.getLong(1), this.venueId);
assertEquals(rs.getLong(2), this.singerId);
- if (dialect == Dialect.POSTGRESQL) {
- assertEquals(rs.getString(3), this.concertDate.toString());
- assertEquals(rs.getString(4), this.beginTime.toString());
- assertEquals(rs.getString(5), this.endTime.toString());
- } else {
- assertEquals(rs.getDate(3), this.concertDate);
- assertEquals(rs.getTimestamp(4), this.beginTime);
- assertEquals(rs.getTimestamp(5), this.endTime);
- assertArrayEquals(
- (Object[]) rs.getArray(6).getArray(),
- (Object[]) connection.createArrayOf("INT64", this.ticketPrices).getArray());
- }
+ assertEquals(rs.getDate(3), this.concertDate);
+ assertEquals(rs.getTimestamp(4), this.beginTime);
+ assertEquals(rs.getTimestamp(5), this.endTime);
+ assertArrayEquals(
+ (Object[]) rs.getArray(6).getArray(),
+ (Object[]) connection.createArrayOf("INT64", this.ticketPrices).getArray());
}
}
@@ -346,15 +325,12 @@ private List createConcerts() {
}
private String getConcertsInsertQuery(Dialect dialect) {
- if (dialect == Dialect.POSTGRESQL) {
- return "INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime) VALUES (?,?,?,?,?);";
- }
return "INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (?,?,?,?,?,?);";
}
private String getConcertsInsertReturningQuery(Dialect dialect) {
if (dialect == Dialect.POSTGRESQL) {
- return "INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime) VALUES (?,?,?,?,?) RETURNING *;";
+ return "INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (?,?,?,?,?,?) RETURNING *;";
}
return "INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (?,?,?,?,?,?) THEN RETURN *;";
}
@@ -380,13 +356,6 @@ private String getSongsInsertReturningQuery(Dialect dialect) {
return "INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (?,?,?,?,?,?) THEN RETURN *;";
}
- private int getConcertExpectedParamCount(Dialect dialect) {
- if (dialect == Dialect.POSTGRESQL) {
- return 5;
- }
- return 6;
- }
-
@Test
public void test01_InsertTestData() throws SQLException {
try (Connection connection = createConnection(env, database)) {
@@ -396,24 +365,13 @@ public void test01_InsertTestData() throws SQLException {
"INSERT INTO Singers (SingerId, FirstName, LastName, SingerInfo, BirthDate) values (?,?,?,?,?)")) {
assertParameterMetaData(
ps.getParameterMetaData(),
+ ImmutableList.of(
+ Types.BIGINT, Types.NVARCHAR, Types.NVARCHAR, Types.BINARY, Types.DATE),
dialect.dialect == Dialect.POSTGRESQL
? ImmutableList.of(
- Types.BIGINT, Types.NVARCHAR, Types.NVARCHAR, Types.BINARY, Types.NVARCHAR)
- : ImmutableList.of(
- Types.BIGINT, Types.NVARCHAR, Types.NVARCHAR, Types.BINARY, Types.DATE),
- dialect.dialect == Dialect.POSTGRESQL
- ? ImmutableList.of(
- "bigint",
- "character varying",
- "character varying",
- "bytea",
- "character varying")
+ "bigint", "character varying", "character varying", "bytea", "date")
: ImmutableList.of("INT64", "STRING", "STRING", "BYTES", "DATE"),
- dialect.dialect == Dialect.POSTGRESQL
- ? ImmutableList.of(
- Long.class, String.class, String.class, byte[].class, String.class)
- : ImmutableList.of(
- Long.class, String.class, String.class, byte[].class, Date.class));
+ ImmutableList.of(Long.class, String.class, String.class, byte[].class, Date.class));
for (Singer singer : createSingers()) {
singer.setPreparedStatement(ps, getDialect());
assertInsertSingerParameterMetadata(ps.getParameterMetaData());
@@ -487,39 +445,35 @@ public void test01_InsertTestData() throws SQLException {
connection.prepareStatement(getConcertsInsertQuery(dialect.dialect))) {
assertParameterMetaData(
ps.getParameterMetaData(),
- dialect.dialect == Dialect.POSTGRESQL
- ? ImmutableList.of(
- Types.BIGINT, Types.BIGINT, Types.NVARCHAR, Types.NVARCHAR, Types.NVARCHAR)
- : ImmutableList.of(
- Types.BIGINT,
- Types.BIGINT,
- Types.DATE,
- Types.TIMESTAMP,
- Types.TIMESTAMP,
- Types.ARRAY),
+ ImmutableList.of(
+ Types.BIGINT,
+ Types.BIGINT,
+ Types.DATE,
+ Types.TIMESTAMP,
+ Types.TIMESTAMP,
+ Types.ARRAY),
dialect.dialect == Dialect.POSTGRESQL
? ImmutableList.of(
"bigint",
"bigint",
- "character varying",
- "character varying",
- "character varying")
+ "date",
+ "timestamp with time zone",
+ "timestamp with time zone",
+ "bigint[]")
: ImmutableList.of(
"INT64", "INT64", "DATE", "TIMESTAMP", "TIMESTAMP", "ARRAY"),
- dialect.dialect == Dialect.POSTGRESQL
- ? ImmutableList.of(Long.class, Long.class, String.class, String.class, String.class)
- : ImmutableList.of(
- Long.class,
- Long.class,
- Date.class,
- Timestamp.class,
- Timestamp.class,
- Long[].class));
+ ImmutableList.of(
+ Long.class,
+ Long.class,
+ Date.class,
+ Timestamp.class,
+ Timestamp.class,
+ Long[].class));
for (Concert concert : createConcerts()) {
concert.setPreparedStatement(connection, ps, getDialect());
assertInsertConcertParameterMetadata(ps.getParameterMetaData());
assertEquals(1, ps.executeUpdate());
- // check that calling executeUpdate will not reset the meta data
+ // check that calling executeUpdate will not reset the metadata.
assertInsertConcertParameterMetadata(ps.getParameterMetaData());
}
}
@@ -564,17 +518,10 @@ public void test02_VerifyTestData() throws SQLException {
assertTrue(rs.next());
assertEquals(1L, rs.getLong(1));
assertEquals(1L, rs.getLong(2));
- if (dialect.dialect == Dialect.POSTGRESQL) {
- assertEquals("2003-06-19", rs.getString(3));
- assertEquals("2003-06-19 12:30:05.0", rs.getString(4));
- assertEquals("2003-06-19 18:57:15.0", rs.getString(5));
- } else {
- assertEquals(Date.valueOf("2003-06-19"), rs.getDate(3));
- assertEquals(Timestamp.valueOf("2003-06-19 12:30:05"), rs.getTimestamp(4));
- assertEquals(Timestamp.valueOf("2003-06-19 18:57:15"), rs.getTimestamp(5));
- assertArrayEquals(
- new Long[] {11L, 93L, 140L, 923L}, (Long[]) rs.getArray(6).getArray());
- }
+ assertEquals(Date.valueOf("2003-06-19"), rs.getDate(3));
+ assertEquals(Timestamp.valueOf("2003-06-19 12:30:05"), rs.getTimestamp(4));
+ assertEquals(Timestamp.valueOf("2003-06-19 18:57:15"), rs.getTimestamp(5));
+ assertArrayEquals(new Long[] {11L, 93L, 140L, 923L}, (Long[]) rs.getArray(6).getArray());
}
}
}
@@ -583,8 +530,6 @@ public void test02_VerifyTestData() throws SQLException {
@SuppressWarnings("deprecation")
@Test
public void test03_Dates() throws SQLException {
- assumeFalse(
- "Date type is not supported on POSTGRESQL dialect", dialect.dialect == Dialect.POSTGRESQL);
List expectedValues = new ArrayList<>();
expectedValues.add("2008-01-01");
expectedValues.add("2000-01-01");
@@ -645,8 +590,16 @@ public void test03_Dates() throws SQLException {
Types.TIMESTAMP,
Types.TIMESTAMP,
Types.ARRAY),
- ImmutableList.of(
- "INT64", "INT64", "DATE", "TIMESTAMP", "TIMESTAMP", "ARRAY"),
+ dialect.dialect == Dialect.POSTGRESQL
+ ? ImmutableList.of(
+ "bigint",
+ "bigint",
+ "date",
+ "timestamp with time zone",
+ "timestamp with time zone",
+ "bigint[]")
+ : ImmutableList.of(
+ "INT64", "INT64", "DATE", "TIMESTAMP", "TIMESTAMP", "ARRAY"),
ImmutableList.of(
Long.class,
Long.class,
@@ -1140,7 +1093,6 @@ public void test09_MetaData_FromQuery() throws SQLException {
assumeFalse(
"TableWithAllColumnTypes type is not supported on POSTGRESQL dialect",
dialect.dialect == Dialect.POSTGRESQL);
- assumeFalse("The emulator does not support PLAN mode", isUsingEmulator());
try (Connection con = createConnection(env, database)) {
try (PreparedStatement ps =
con.prepareStatement("SELECT * FROM TableWithAllColumnTypes WHERE ColInt64=?")) {
@@ -1341,9 +1293,6 @@ private void assertParameterMetaData(
@Test
public void test12_InsertReturningTestData() throws SQLException {
- assumeFalse(
- "Emulator does not support DML with returning clause",
- EmulatorSpannerHelper.isUsingEmulator());
try (Connection connection = createConnection(env, database)) {
connection.setAutoCommit(false);
// Delete existing rows from tables populated by other tests,
@@ -1358,24 +1307,13 @@ public void test12_InsertReturningTestData() throws SQLException {
connection.prepareStatement(getSingersInsertReturningQuery(dialect.dialect))) {
assertParameterMetaData(
ps.getParameterMetaData(),
+ ImmutableList.of(
+ Types.BIGINT, Types.NVARCHAR, Types.NVARCHAR, Types.BINARY, Types.DATE),
dialect.dialect == Dialect.POSTGRESQL
? ImmutableList.of(
- Types.BIGINT, Types.NVARCHAR, Types.NVARCHAR, Types.BINARY, Types.NVARCHAR)
- : ImmutableList.of(
- Types.BIGINT, Types.NVARCHAR, Types.NVARCHAR, Types.BINARY, Types.DATE),
- dialect.dialect == Dialect.POSTGRESQL
- ? ImmutableList.of(
- "bigint",
- "character varying",
- "character varying",
- "bytea",
- "character varying")
+ "bigint", "character varying", "character varying", "bytea", "date")
: ImmutableList.of("INT64", "STRING", "STRING", "BYTES", "DATE"),
- dialect.dialect == Dialect.POSTGRESQL
- ? ImmutableList.of(
- Long.class, String.class, String.class, byte[].class, String.class)
- : ImmutableList.of(
- Long.class, String.class, String.class, byte[].class, Date.class));
+ ImmutableList.of(Long.class, String.class, String.class, byte[].class, Date.class));
for (Singer singer : createSingers()) {
singer.setPreparedStatement(ps, getDialect());
assertInsertSingerParameterMetadata(ps.getParameterMetaData());
@@ -1465,34 +1403,30 @@ public void test12_InsertReturningTestData() throws SQLException {
connection.prepareStatement(getConcertsInsertReturningQuery(dialect.dialect))) {
assertParameterMetaData(
ps.getParameterMetaData(),
- dialect.dialect == Dialect.POSTGRESQL
- ? ImmutableList.of(
- Types.BIGINT, Types.BIGINT, Types.NVARCHAR, Types.NVARCHAR, Types.NVARCHAR)
- : ImmutableList.of(
- Types.BIGINT,
- Types.BIGINT,
- Types.DATE,
- Types.TIMESTAMP,
- Types.TIMESTAMP,
- Types.ARRAY),
+ ImmutableList.of(
+ Types.BIGINT,
+ Types.BIGINT,
+ Types.DATE,
+ Types.TIMESTAMP,
+ Types.TIMESTAMP,
+ Types.ARRAY),
dialect.dialect == Dialect.POSTGRESQL
? ImmutableList.of(
"bigint",
"bigint",
- "character varying",
- "character varying",
- "character varying")
+ "date",
+ "timestamp with time zone",
+ "timestamp with time zone",
+ "bigint[]")
: ImmutableList.of(
"INT64", "INT64", "DATE", "TIMESTAMP", "TIMESTAMP", "ARRAY"),
- dialect.dialect == Dialect.POSTGRESQL
- ? ImmutableList.of(Long.class, Long.class, String.class, String.class, String.class)
- : ImmutableList.of(
- Long.class,
- Long.class,
- Date.class,
- Timestamp.class,
- Timestamp.class,
- Long[].class));
+ ImmutableList.of(
+ Long.class,
+ Long.class,
+ Date.class,
+ Timestamp.class,
+ Timestamp.class,
+ Long[].class));
for (Concert concert : createConcerts()) {
concert.setPreparedStatement(connection, ps, getDialect());
assertInsertConcertParameterMetadata(ps.getParameterMetaData());
@@ -1500,7 +1434,7 @@ public void test12_InsertReturningTestData() throws SQLException {
rs.next();
concert.assertEqualsFields(connection, rs, dialect.dialect);
}
- // check that calling executeQuery will not reset the meta data
+ // check that calling executeQuery will not reset the metadata.
assertInsertConcertParameterMetadata(ps.getParameterMetaData());
}
}
@@ -1569,11 +1503,7 @@ private void assertInsertSingerParameterMetadata(ParameterMetaData pmd) throws S
assertStringParam(pmd, 2);
assertStringParam(pmd, 3);
assertBytesParam(pmd, 4);
- if (dialect.dialect == Dialect.POSTGRESQL) {
- assertStringParam(pmd, 5);
- } else {
- assertDateParam(pmd, 5);
- }
+ assertDateParam(pmd, 5);
}
private void assertInsertAlbumParameterMetadata(ParameterMetaData pmd) throws SQLException {
@@ -1595,20 +1525,13 @@ private void assertInsertSongParameterMetadata(ParameterMetaData pmd) throws SQL
}
private void assertInsertConcertParameterMetadata(ParameterMetaData pmd) throws SQLException {
- int expectedParamCount = getConcertExpectedParamCount(getDialect());
- assertEquals(expectedParamCount, pmd.getParameterCount());
+ assertEquals(6, pmd.getParameterCount());
assertLongParam(pmd, 1);
assertLongParam(pmd, 2);
- if (dialect.dialect == Dialect.POSTGRESQL) {
- assertStringParam(pmd, 3);
- assertStringParam(pmd, 4);
- assertStringParam(pmd, 5);
- } else {
- assertDateParam(pmd, 3);
- assertTimestampParam(pmd, 4);
- assertTimestampParam(pmd, 5);
- assertLongArrayParam(pmd, 6);
- }
+ assertDateParam(pmd, 3);
+ assertTimestampParam(pmd, 4);
+ assertTimestampParam(pmd, 5);
+ assertLongArrayParam(pmd, 6);
}
private void assertLongParam(ParameterMetaData pmd, int param) throws SQLException {
diff --git a/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcQueryOptionsTest.java b/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcQueryOptionsTest.java
index 46251ac9e..737a76880 100644
--- a/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcQueryOptionsTest.java
+++ b/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcQueryOptionsTest.java
@@ -99,9 +99,6 @@ public static List data() {
@Before
public void setup() {
- assumeFalse(
- "Emulator does not support PostgreSQL",
- dialect.dialect == Dialect.POSTGRESQL && EmulatorSpannerHelper.isUsingEmulator());
database = env.getOrCreateDatabase(getDialect(), Collections.emptyList());
}
diff --git a/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadOnlyTest.java b/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadOnlyTest.java
index 7e13532c9..f70e025bc 100644
--- a/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadOnlyTest.java
+++ b/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadOnlyTest.java
@@ -17,7 +17,6 @@
package com.google.cloud.spanner.jdbc.it;
import static org.junit.Assert.assertTrue;
-import static org.junit.Assume.assumeFalse;
import com.google.cloud.spanner.Database;
import com.google.cloud.spanner.Dialect;
@@ -26,7 +25,6 @@
import com.google.cloud.spanner.connection.ConnectionOptions;
import com.google.cloud.spanner.jdbc.CloudSpannerJdbcConnection;
import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier;
-import com.google.cloud.spanner.testing.EmulatorSpannerHelper;
import com.google.common.collect.ImmutableMap;
import java.math.BigInteger;
import java.sql.Connection;
@@ -85,9 +83,6 @@ public static List data() {
@Before
public void setup() {
- assumeFalse(
- "Emulator does not support PostgreSQL",
- dialect.dialect == Dialect.POSTGRESQL && EmulatorSpannerHelper.isUsingEmulator());
database = env.getOrCreateDatabase(getDialect(), Collections.emptyList());
}
diff --git a/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java b/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java
index 7076563b3..525ccbbe1 100644
--- a/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java
+++ b/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java
@@ -19,7 +19,6 @@
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assume.assumeFalse;
import com.google.cloud.spanner.Database;
import com.google.cloud.spanner.Dialect;
@@ -27,7 +26,6 @@
import com.google.cloud.spanner.ParallelIntegrationTest;
import com.google.cloud.spanner.jdbc.CloudSpannerJdbcConnection;
import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier;
-import com.google.cloud.spanner.testing.EmulatorSpannerHelper;
import com.google.common.collect.ImmutableMap;
import java.util.ArrayList;
import java.util.List;
@@ -69,9 +67,6 @@ public static List data() {
@Before
public void setup() {
- assumeFalse(
- "Emulator does not support PostgreSQL",
- dialect.dialect == Dialect.POSTGRESQL && EmulatorSpannerHelper.isUsingEmulator());
database = env.getOrCreateDatabase(getDialect(), getTestTableDdl(getDialect()));
}
diff --git a/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcScriptTest.java b/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcScriptTest.java
index a6e44358e..8d8c0ffa0 100644
--- a/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcScriptTest.java
+++ b/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcScriptTest.java
@@ -90,6 +90,8 @@ public class ITJdbcScriptTest extends ITAbstractJdbcTest {
"PostgreSQL/ITScriptTest_InsertTestData.sql";
private static final String TEST_GET_READ_TIMESTAMP_PG =
"PostgreSQL/ITScriptTest_TestGetReadTimestamp.sql";
+ private static final String TEST_GET_COMMIT_TIMESTAMP_PG =
+ "PostgreSQL/ITSqlScriptTest_TestGetCommitTimestamp.sql";
private static final String TEST_TEMPORARY_TRANSACTIONS_PG =
"PostgreSQL/ITScriptTest_TestTemporaryTransactions.sql";
private static final String TEST_TRANSACTION_MODE_PG =
@@ -138,6 +140,7 @@ public static List data() {
postgresScripts.put("CREATE_TABLES_FILE", CREATE_TABLES_FILE_PG);
postgresScripts.put("INSERT_AND_VERIFY_TEST_DATA", INSERT_AND_VERIFY_TEST_DATA_PG);
postgresScripts.put("TEST_GET_READ_TIMESTAMP", TEST_GET_READ_TIMESTAMP_PG);
+ postgresScripts.put("TEST_GET_COMMIT_TIMESTAMP", TEST_GET_COMMIT_TIMESTAMP_PG);
postgresScripts.put("TEST_TEMPORARY_TRANSACTIONS", TEST_TEMPORARY_TRANSACTIONS_PG);
postgresScripts.put("TEST_TRANSACTION_MODE", TEST_TRANSACTION_MODE_PG);
postgresScripts.put("TEST_TRANSACTION_MODE_READ_ONLY", TEST_TRANSACTION_MODE_READ_ONLY_PG);
@@ -163,9 +166,6 @@ public static List data() {
@Before
public void setup() {
- assumeFalse(
- "Emulator does not support PostgreSQL",
- dialect.dialect == Dialect.POSTGRESQL && EmulatorSpannerHelper.isUsingEmulator());
database = env.getOrCreateDatabase(getDialect(), Collections.emptyList());
}
@@ -217,24 +217,12 @@ public void test03_TestGetReadTimestamp() throws Exception {
@Test
public void test04_TestGetCommitTimestamp() throws Exception {
- // Skipping test as Commit Timestamp not supported in POSTGRES
- assumeFalse(dialect.dialect == Dialect.POSTGRESQL);
try (CloudSpannerJdbcConnection connection = createConnection(env, database)) {
verifier.verifyStatementsInFile(
JdbcGenericConnection.of(connection),
dialect.executeQueriesFiles.get("TEST_GET_COMMIT_TIMESTAMP"),
JdbcSqlScriptVerifier.class,
false);
- } catch (SQLException e) {
- if (env.getTestHelper().isEmulator()
- && e.getErrorCode() == ErrorCode.INVALID_ARGUMENT.getGrpcStatusCode().value()) {
- // Ignore as errors during read/write transactions are sticky on the emulator.
- }
- } catch (SpannerException e) {
- if (env.getTestHelper().isEmulator() && e.getErrorCode() == ErrorCode.ALREADY_EXISTS) {
- // Ignore, this is expected as errors during a read/write transaction are sticky on the
- // emulator.
- }
}
}
diff --git a/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSimpleStatementsTest.java b/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSimpleStatementsTest.java
index b7fbc6956..f6948a9c2 100644
--- a/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSimpleStatementsTest.java
+++ b/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSimpleStatementsTest.java
@@ -29,7 +29,6 @@
import com.google.cloud.spanner.ParallelIntegrationTest;
import com.google.cloud.spanner.Struct;
import com.google.cloud.spanner.Value;
-import com.google.cloud.spanner.testing.EmulatorSpannerHelper;
import java.sql.Array;
import java.sql.Connection;
import java.sql.PreparedStatement;
@@ -69,9 +68,6 @@ public static List data() {
@Before
public void setup() {
- assumeFalse(
- "Emulator does not support PostgreSQL",
- dialect.dialect == Dialect.POSTGRESQL && EmulatorSpannerHelper.isUsingEmulator());
database = env.getOrCreateDatabase(getDialect(), Collections.emptyList());
}
diff --git a/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlMusicScriptTest.java b/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlMusicScriptTest.java
index 7c8c7aeb5..5a2240182 100644
--- a/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlMusicScriptTest.java
+++ b/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlMusicScriptTest.java
@@ -16,15 +16,12 @@
package com.google.cloud.spanner.jdbc.it;
-import static org.junit.Assume.assumeFalse;
-
import com.google.cloud.spanner.Database;
import com.google.cloud.spanner.Dialect;
import com.google.cloud.spanner.ParallelIntegrationTest;
import com.google.cloud.spanner.jdbc.CloudSpannerJdbcConnection;
import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier;
import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier.JdbcGenericConnection;
-import com.google.cloud.spanner.testing.EmulatorSpannerHelper;
import com.google.common.collect.ImmutableMap;
import java.util.ArrayList;
import java.util.Collections;
@@ -63,9 +60,6 @@ public static List data() {
@Before
public void setup() {
- assumeFalse(
- "Emulator does not support PostgreSQL",
- dialect.dialect == Dialect.POSTGRESQL && EmulatorSpannerHelper.isUsingEmulator());
database = env.getOrCreateDatabase(getDialect(), Collections.emptyList());
}
diff --git a/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITReadWriteAutocommitSpannerTest.sql b/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITReadWriteAutocommitSpannerTest.sql
index ae7ee898c..b1df42f1a 100644
--- a/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITReadWriteAutocommitSpannerTest.sql
+++ b/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITReadWriteAutocommitSpannerTest.sql
@@ -206,7 +206,7 @@ START BATCH DML;
@EXPECT UPDATE_COUNT -1
DELETE FROM TEST WHERE ID IN (10,11,12);
@EXPECT UPDATE_COUNT -1
-DELETE FROM TEST_NOT_FOUND WHERE ID IN (10,11,12);
+DELETE FROM TEST WERE ID IN (10,11,12);
-- Returns an error because of the second statement.
@EXPECT EXCEPTION INVALID_ARGUMENT
RUN BATCH;
diff --git a/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestGetReadTimestamp.sql b/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestGetReadTimestamp.sql
index 00fa78c3f..adff02e05 100644
--- a/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestGetReadTimestamp.sql
+++ b/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestGetReadTimestamp.sql
@@ -94,8 +94,8 @@ SET SPANNER.READONLY = TRUE;
@EXPECT EXCEPTION INVALID_ARGUMENT
SELECT LastName AS "ACTUAL", 'Last 1' AS "EXPECTED"
-FROM NonExistentTable
-WHERE SingerId=1;
+FROM Singers
+WERE SingerId=1;
@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null
SHOW VARIABLE SPANNER.READ_TIMESTAMP;
@@ -105,8 +105,8 @@ SET SPANNER.READONLY = FALSE;
@EXPECT EXCEPTION INVALID_ARGUMENT
SELECT LastName AS "ACTUAL", 'Last 1' AS "EXPECTED"
-FROM NonExistentTable
-WHERE SingerId=1;
+FROM Singers
+WERE SingerId=1;
@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null
SHOW VARIABLE SPANNER.READ_TIMESTAMP;
diff --git a/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITSqlScriptTest_TestGetCommitTimestamp.sql b/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITSqlScriptTest_TestGetCommitTimestamp.sql
new file mode 100644
index 000000000..a727461c7
--- /dev/null
+++ b/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITSqlScriptTest_TestGetCommitTimestamp.sql
@@ -0,0 +1,138 @@
+/*
+ * 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.
+ */
+
+/*
+ * Test SHOW VARIABLE COMMIT_TIMESTAMP in different modes
+ */
+
+-- Select query in autocommit and read-only mode should not yield a commit timestamp
+@EXPECT NO_RESULT
+SET AUTOCOMMIT = TRUE;
+@EXPECT NO_RESULT
+SET SPANNER.READONLY = TRUE;
+
+@EXPECT RESULT_SET
+SELECT LastName AS "ACTUAL", 'Last 1' AS "EXPECTED"
+FROM Singers
+WHERE SingerId=1;
+
+@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null
+SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP;
+
+-- Select query in autocommit and read-write mode should not yield a commit timestamp
+@EXPECT NO_RESULT
+SET SPANNER.READONLY = FALSE;
+
+@EXPECT RESULT_SET
+SELECT LastName AS "ACTUAL", 'Last 1' AS "EXPECTED"
+FROM Singers
+WHERE SingerId=1;
+
+@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null
+SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP;
+
+-- Select query in transactional and read-only mode should not yield a commit timestamp
+@EXPECT NO_RESULT
+SET AUTOCOMMIT = FALSE;
+@EXPECT NO_RESULT
+SET SPANNER.READONLY = TRUE;
+
+@EXPECT RESULT_SET
+SELECT LastName AS "ACTUAL", 'Last 1' AS "EXPECTED"
+FROM Singers
+WHERE SingerId=1;
+
+@EXPECT NO_RESULT
+COMMIT;
+
+@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null
+SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP;
+
+-- Select query in transactional and read-write mode should yield a commit timestamp
+@EXPECT NO_RESULT
+SET SPANNER.READONLY = FALSE;
+
+@EXPECT RESULT_SET
+SELECT LastName AS "ACTUAL", 'Last 1' AS "EXPECTED"
+FROM Singers
+WHERE SingerId=1;
+
+@EXPECT NO_RESULT
+COMMIT;
+
+@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP'
+SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP;
+
+-- Update statement in transactional and read-write mode should yield a commit timestamp
+@EXPECT NO_RESULT
+SET AUTOCOMMIT = FALSE;
+
+@EXPECT UPDATE_COUNT 1
+UPDATE Singers SET LastName='New Last 1'
+WHERE SingerId=1;
+
+@EXPECT NO_RESULT
+COMMIT;
+
+@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP'
+SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP;
+
+-- Reset the value to its original value
+@EXPECT UPDATE_COUNT 1
+UPDATE Singers SET LastName='Last 1'
+WHERE SingerId=1;
+
+@EXPECT NO_RESULT
+COMMIT;
+
+-- Select query in transactional and read-write mode that rollbacks should not yield a commit timestamp
+@EXPECT RESULT_SET
+SELECT LastName AS "ACTUAL", 'Last 1' AS "EXPECTED"
+FROM Singers
+WHERE SingerId=1;
+
+@EXPECT NO_RESULT
+ROLLBACK;
+
+@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null
+SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP;
+
+-- Update statement in transactional and read-write mode that rollbacks should not yield a commit timestamp
+@EXPECT UPDATE_COUNT 1
+UPDATE Singers SET LastName='New Last 1'
+WHERE SingerId=1;
+
+@EXPECT NO_RESULT
+ROLLBACK;
+
+@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null
+SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP;
+
+-- Invalid select query in transactional and read-write mode should yield a commit timestamp
+-- The (invalid) query is sent to the server, initiating a transaction, that is committed afterwards
+SET AUTOCOMMIT = FALSE;
+SET SPANNER.READONLY = FALSE;
+
+@EXPECT EXCEPTION INVALID_ARGUMENT
+SELECT LastName AS "ACTUAL", 'Last 1' AS "EXPECTED"
+FROM Singers
+WERE SingerId=1;
+
+@EXPECT NO_RESULT
+COMMIT;
+
+@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP'
+SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP;
diff --git a/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_PG.sql b/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_PG.sql
index c77968b45..abecd9fad 100644
--- a/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_PG.sql
+++ b/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_PG.sql
@@ -21,7 +21,7 @@ CREATE TABLE Singers (
FirstName VARCHAR(1024),
LastName VARCHAR(1024),
SingerInfo BYTEA,
- BirthDate VARCHAR
+ BirthDate DATE
);
CREATE INDEX SingersByFirstLastName ON Singers(FirstName, LastName);
@@ -55,9 +55,10 @@ CREATE INDEX SongsBySongName ON Songs(SongName);
CREATE TABLE Concerts (
VenueId BIGINT NOT NULL,
SingerId BIGINT NOT NULL,
- ConcertDate VARCHAR NOT NULL,
- BeginTime VARCHAR,
- EndTime VARCHAR,
+ ConcertDate DATE NOT NULL,
+ BeginTime TIMESTAMPTZ,
+ EndTime TIMESTAMPTZ,
+ TicketPrices BIGINT[],
PRIMARY KEY(VenueId, SingerId, ConcertDate),
FOREIGN KEY(SingerId) REFERENCES Singers(SingerId)
);
From 1e7a4f73339479134868206730c275fe752e8d0d Mon Sep 17 00:00:00 2001
From: Mend Renovate
Date: Thu, 7 Mar 2024 14:41:18 +0100
Subject: [PATCH 16/18] deps: update dependency
com.spotify.fmt:fmt-maven-plugin to v2.23 (#1527)
---
samples/spring-data-jdbc/pom.xml | 2 +-
samples/spring-data-mybatis/pom.xml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/samples/spring-data-jdbc/pom.xml b/samples/spring-data-jdbc/pom.xml
index 6bcfd491d..79af94427 100644
--- a/samples/spring-data-jdbc/pom.xml
+++ b/samples/spring-data-jdbc/pom.xml
@@ -87,7 +87,7 @@
com.spotify.fmt
fmt-maven-plugin
- 2.22.1
+ 2.23
diff --git a/samples/spring-data-mybatis/pom.xml b/samples/spring-data-mybatis/pom.xml
index a32e7a800..ef02f014a 100644
--- a/samples/spring-data-mybatis/pom.xml
+++ b/samples/spring-data-mybatis/pom.xml
@@ -97,7 +97,7 @@
com.spotify.fmt
fmt-maven-plugin
- 2.22.1
+ 2.23
From 635ac41e054814cf3b58d37cbc42b01ac183b2a1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?=
Date: Thu, 7 Mar 2024 16:24:47 +0100
Subject: [PATCH 17/18] feat: support float32 (#1518)
* feat: support float32
Adds support for the FLOAT32 / real data type.
* test: update tests to use new RandomResultSetGenerator
* test: add more tests
* deps: bump to Spanner 6.61.0
* test: enable pg_numeric test on emulator
* test: skip setFloat(..) until float32 is supported
* chore: address review comments
---
.../jdbc/AbstractJdbcPreparedStatement.java | 2 +-
.../spanner/jdbc/AbstractJdbcWrapper.java | 13 +
.../google/cloud/spanner/jdbc/JdbcArray.java | 3 +
.../cloud/spanner/jdbc/JdbcDataType.java | 56 +++
.../spanner/jdbc/JdbcDatabaseMetaData.java | 38 ++
.../spanner/jdbc/JdbcParameterMetaData.java | 3 +-
.../spanner/jdbc/JdbcParameterStore.java | 30 +-
.../cloud/spanner/jdbc/JdbcResultSet.java | 34 ++
.../spanner/jdbc/JdbcResultSetMetaData.java | 9 +
.../cloud/spanner/jdbc/JdbcTypeConverter.java | 17 +-
.../spanner/jdbc/AllTypesMockServerTest.java | 372 ++++++++++++++++++
.../cloud/spanner/jdbc/JdbcArrayTest.java | 18 +
.../jdbc/JdbcDatabaseMetaDataTest.java | 2 +
.../spanner/jdbc/JdbcParameterStoreTest.java | 40 +-
.../jdbc/JdbcResultSetMetaDataTest.java | 42 +-
.../jdbc/PartitionedQueryMockServerTest.java | 30 +-
...reparedStatementParameterMetadataTest.java | 63 ++-
.../spanner/jdbc/RandomResultSetTest.java | 164 ++++++++
.../spanner/jdbc/it/ITJdbcPgNumericTest.java | 8 +-
19 files changed, 883 insertions(+), 61 deletions(-)
create mode 100644 src/test/java/com/google/cloud/spanner/jdbc/AllTypesMockServerTest.java
create mode 100644 src/test/java/com/google/cloud/spanner/jdbc/RandomResultSetTest.java
diff --git a/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java b/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java
index cd1c50a73..2a9ba067d 100644
--- a/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java
+++ b/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java
@@ -118,7 +118,7 @@ public void setLong(int parameterIndex, long value) throws SQLException {
@Override
public void setFloat(int parameterIndex, float value) throws SQLException {
checkClosed();
- parameters.setParameter(parameterIndex, value, Types.FLOAT);
+ parameters.setParameter(parameterIndex, value, Types.REAL);
}
@Override
diff --git a/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java b/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java
index 86281af0d..b06e5999e 100644
--- a/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java
+++ b/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java
@@ -49,6 +49,8 @@ static int extractColumnType(Type type) {
return Types.BINARY;
case DATE:
return Types.DATE;
+ case FLOAT32:
+ return Types.REAL;
case FLOAT64:
return Types.DOUBLE;
case INT64:
@@ -81,9 +83,13 @@ static String getSpannerTypeName(Type type, Dialect dialect) {
*/
@Deprecated
static String getSpannerTypeName(int sqlType) {
+ // TODO: Re-write to be dialect-aware (or remove all-together).
if (sqlType == Types.BOOLEAN) return Type.bool().getCode().name();
if (sqlType == Types.BINARY) return Type.bytes().getCode().name();
if (sqlType == Types.DATE) return Type.date().getCode().name();
+ if (sqlType == Types.REAL) {
+ return Type.float32().getCode().name();
+ }
if (sqlType == Types.DOUBLE || sqlType == Types.FLOAT) return Type.float64().getCode().name();
if (sqlType == Types.BIGINT
|| sqlType == Types.INTEGER
@@ -109,6 +115,9 @@ static String getClassName(int sqlType) {
if (sqlType == Types.BOOLEAN) return Boolean.class.getName();
if (sqlType == Types.BINARY) return Byte[].class.getName();
if (sqlType == Types.DATE) return Date.class.getName();
+ if (sqlType == Types.REAL) {
+ return Float.class.getName();
+ }
if (sqlType == Types.DOUBLE || sqlType == Types.FLOAT) return Double.class.getName();
if (sqlType == Types.BIGINT
|| sqlType == Types.INTEGER
@@ -137,6 +146,8 @@ static String getClassName(Type type) {
return byte[].class.getName();
case DATE:
return Date.class.getName();
+ case FLOAT32:
+ return Float.class.getName();
case FLOAT64:
return Double.class.getName();
case INT64:
@@ -158,6 +169,8 @@ static String getClassName(Type type) {
return byte[][].class.getName();
case DATE:
return Date[].class.getName();
+ case FLOAT32:
+ return Float[].class.getName();
case FLOAT64:
return Double[].class.getName();
case INT64:
diff --git a/src/main/java/com/google/cloud/spanner/jdbc/JdbcArray.java b/src/main/java/com/google/cloud/spanner/jdbc/JdbcArray.java
index 650c1eb78..4ef2ac215 100644
--- a/src/main/java/com/google/cloud/spanner/jdbc/JdbcArray.java
+++ b/src/main/java/com/google/cloud/spanner/jdbc/JdbcArray.java
@@ -188,6 +188,9 @@ public ResultSet getResultSet(long startIndex, int count) throws SQLException {
case DATE:
builder = binder.to(JdbcTypeConverter.toGoogleDate((Date) value));
break;
+ case FLOAT32:
+ builder = binder.to((Float) value);
+ break;
case FLOAT64:
builder = binder.to((Double) value);
break;
diff --git a/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java b/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java
index 5dd082ef8..b920d3d55 100644
--- a/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java
+++ b/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java
@@ -110,6 +110,47 @@ public Type getSpannerType() {
return Type.date();
}
},
+ FLOAT32 {
+ @Override
+ public int getSqlType() {
+ return Types.REAL;
+ }
+
+ @Override
+ public int getScale() {
+ return 7;
+ }
+
+ @Override
+ public int getPrecision() {
+ return 7;
+ }
+
+ @Override
+ public int getDefaultColumnDisplaySize() {
+ return 7;
+ }
+
+ @Override
+ public Class getJavaClass() {
+ return Float.class;
+ }
+
+ @Override
+ public Code getCode() {
+ return Code.FLOAT32;
+ }
+
+ @Override
+ public List getArrayElements(ResultSet rs, int columnIndex) {
+ return rs.getFloatList(columnIndex);
+ }
+
+ @Override
+ public Type getSpannerType() {
+ return Type.float32();
+ }
+ },
FLOAT64 {
private final Set> classes = new HashSet<>(Arrays.asList(Float.class, Double.class));
@@ -371,6 +412,21 @@ public Type getSpannerType() {
public abstract Type getSpannerType();
+ // TODO: Implement and use this method for all types.
+ public int getPrecision() {
+ throw new UnsupportedOperationException();
+ }
+
+ // TODO: Implement and use this method for all types.
+ public int getScale() {
+ throw new UnsupportedOperationException();
+ }
+
+ // TODO: Implement and use this method for all types.
+ public int getDefaultColumnDisplaySize() {
+ throw new UnsupportedOperationException();
+ }
+
/**
* @param rs the result set to look up the elements
* @param columnIndex zero based column index
diff --git a/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java b/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java
index 446339587..025b26570 100644
--- a/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java
+++ b/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java
@@ -1056,6 +1056,44 @@ public ResultSet getTypeInfo() {
.set("NUM_PREC_RADIX")
.to((Long) null)
.build(),
+ Struct.newBuilder()
+ .set("TYPE_NAME")
+ .to("FLOAT32")
+ .set("DATA_TYPE")
+ .to(Types.REAL) // 8
+ .set("PRECISION")
+ .to(7L)
+ .set("LITERAL_PREFIX")
+ .to((String) null)
+ .set("LITERAL_SUFFIX")
+ .to((String) null)
+ .set("CREATE_PARAMS")
+ .to((String) null)
+ .set("NULLABLE")
+ .to(DatabaseMetaData.typeNullable)
+ .set("CASE_SENSITIVE")
+ .to(false)
+ .set("SEARCHABLE")
+ .to(DatabaseMetaData.typePredBasic)
+ .set("UNSIGNED_ATTRIBUTE")
+ .to(false)
+ .set("FIXED_PREC_SCALE")
+ .to(false)
+ .set("AUTO_INCREMENT")
+ .to(false)
+ .set("LOCAL_TYPE_NAME")
+ .to("FLOAT32")
+ .set("MINIMUM_SCALE")
+ .to(0)
+ .set("MAXIMUM_SCALE")
+ .to(0)
+ .set("SQL_DATA_TYPE")
+ .to((Long) null)
+ .set("SQL_DATETIME_SUB")
+ .to((Long) null)
+ .set("NUM_PREC_RADIX")
+ .to(2)
+ .build(),
Struct.newBuilder()
.set("TYPE_NAME")
.to("FLOAT64")
diff --git a/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterMetaData.java b/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterMetaData.java
index 82a4b9133..784a2678f 100644
--- a/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterMetaData.java
+++ b/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterMetaData.java
@@ -76,6 +76,7 @@ public boolean isSigned(int param) throws SQLException {
int type = getParameterType(param);
return type == Types.DOUBLE
|| type == Types.FLOAT
+ || type == Types.REAL
|| type == Types.BIGINT
|| type == Types.INTEGER
|| type == Types.SMALLINT
@@ -139,7 +140,7 @@ private int getParameterTypeFromValue(int param) {
} else if (Long.class.isAssignableFrom(value.getClass())) {
return Types.BIGINT;
} else if (Float.class.isAssignableFrom(value.getClass())) {
- return Types.FLOAT;
+ return Types.REAL;
} else if (Double.class.isAssignableFrom(value.getClass())) {
return Types.DOUBLE;
} else if (BigDecimal.class.isAssignableFrom(value.getClass())) {
diff --git a/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java b/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java
index 5fb4177fc..dabc9bfa0 100644
--- a/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java
+++ b/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java
@@ -452,8 +452,12 @@ private Builder setParamWithKnownType(ValueBinder binder, Object value,
return binder.to(((Number) value).longValue());
}
throw JdbcSqlExceptionFactory.of(value + " is not a valid long", Code.INVALID_ARGUMENT);
- case Types.FLOAT:
case Types.REAL:
+ if (value instanceof Number) {
+ return binder.to(((Number) value).floatValue());
+ }
+ throw JdbcSqlExceptionFactory.of(value + " is not a valid float", Code.INVALID_ARGUMENT);
+ case Types.FLOAT:
case Types.DOUBLE:
if (value instanceof Number) {
return binder.to(((Number) value).doubleValue());
@@ -744,8 +748,9 @@ private Builder setArrayValue(ValueBinder binder, int type, Object valu
case Types.INTEGER:
case Types.BIGINT:
return binder.toInt64Array((long[]) null);
- case Types.FLOAT:
case Types.REAL:
+ return binder.toFloat32Array((float[]) null);
+ case Types.FLOAT:
case Types.DOUBLE:
return binder.toFloat64Array((double[]) null);
case Types.NUMERIC:
@@ -814,13 +819,9 @@ private Builder setArrayValue(ValueBinder binder, int type, Object valu
} else if (Long[].class.isAssignableFrom(value.getClass())) {
return binder.toInt64Array(toLongList((Long[]) value));
} else if (float[].class.isAssignableFrom(value.getClass())) {
- double[] l = new double[((float[]) value).length];
- for (int i = 0; i < l.length; i++) {
- l[i] = ((float[]) value)[i];
- }
- return binder.toFloat64Array(l);
+ return binder.toFloat32Array((float[]) value);
} else if (Float[].class.isAssignableFrom(value.getClass())) {
- return binder.toFloat64Array(toDoubleList((Float[]) value));
+ return binder.toFloat32Array(toFloatList((Float[]) value));
} else if (double[].class.isAssignableFrom(value.getClass())) {
return binder.toFloat64Array((double[]) value);
} else if (Double[].class.isAssignableFrom(value.getClass())) {
@@ -860,6 +861,14 @@ private List toLongList(Number[] input) {
return res;
}
+ private List toFloatList(Number[] input) {
+ List res = new ArrayList<>(input.length);
+ for (Number number : input) {
+ res.add(number == null ? null : number.floatValue());
+ }
+ return res;
+ }
+
private List toDoubleList(Number[] input) {
List res = new ArrayList<>(input.length);
for (Number number : input) {
@@ -901,9 +910,8 @@ private Builder setNullValue(ValueBinder binder, Integer sqlType) {
} else {
return binder.to((BigDecimal) null);
}
- case Types.DOUBLE:
- return binder.to((Double) null);
case Types.FLOAT:
+ case Types.DOUBLE:
return binder.to((Double) null);
case Types.INTEGER:
return binder.to((Long) null);
@@ -920,7 +928,7 @@ private Builder setNullValue(ValueBinder binder, Integer sqlType) {
case Types.NVARCHAR:
return binder.to((String) null);
case Types.REAL:
- return binder.to((Double) null);
+ return binder.to((Float) null);
case Types.SMALLINT:
return binder.to((Long) null);
case Types.SQLXML:
diff --git a/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java b/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java
index 4152fa58b..91ec976b8 100644
--- a/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java
+++ b/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java
@@ -203,6 +203,8 @@ public String getString(int columnIndex) throws SQLException {
return isNull ? null : spanner.getBytes(spannerIndex).toBase64();
case DATE:
return isNull ? null : spanner.getDate(spannerIndex).toString();
+ case FLOAT32:
+ return isNull ? null : Float.toString(spanner.getFloat(spannerIndex));
case FLOAT64:
return isNull ? null : Double.toString(spanner.getDouble(spannerIndex));
case INT64:
@@ -235,6 +237,8 @@ public boolean getBoolean(int columnIndex) throws SQLException {
switch (type) {
case BOOL:
return !isNull && spanner.getBoolean(spannerIndex);
+ case FLOAT32:
+ return !isNull && spanner.getFloat(spannerIndex) != 0f;
case FLOAT64:
return !isNull && spanner.getDouble(spannerIndex) != 0D;
case INT64:
@@ -266,6 +270,10 @@ public byte getByte(int columnIndex) throws SQLException {
switch (type) {
case BOOL:
return isNull ? (byte) 0 : (spanner.getBoolean(spannerIndex) ? (byte) 1 : 0);
+ case FLOAT32:
+ return isNull
+ ? (byte) 0
+ : checkedCastToByte(Float.valueOf(spanner.getFloat(spannerIndex)).longValue());
case FLOAT64:
return isNull
? (byte) 0
@@ -301,6 +309,10 @@ public short getShort(int columnIndex) throws SQLException {
switch (type) {
case BOOL:
return isNull ? 0 : (spanner.getBoolean(spannerIndex) ? (short) 1 : 0);
+ case FLOAT32:
+ return isNull
+ ? 0
+ : checkedCastToShort(Float.valueOf(spanner.getFloat(spannerIndex)).longValue());
case FLOAT64:
return isNull
? 0
@@ -336,6 +348,10 @@ public int getInt(int columnIndex) throws SQLException {
switch (type) {
case BOOL:
return isNull ? 0 : (spanner.getBoolean(spannerIndex) ? 1 : 0);
+ case FLOAT32:
+ return isNull
+ ? 0
+ : checkedCastToInt(Float.valueOf(spanner.getFloat(spannerIndex)).longValue());
case FLOAT64:
return isNull
? 0
@@ -371,6 +387,8 @@ public long getLong(int columnIndex) throws SQLException {
switch (type) {
case BOOL:
return isNull ? 0L : (spanner.getBoolean(spannerIndex) ? 1L : 0L);
+ case FLOAT32:
+ return isNull ? 0L : Float.valueOf(spanner.getFloat(spannerIndex)).longValue();
case FLOAT64:
return isNull ? 0L : Double.valueOf(spanner.getDouble(spannerIndex)).longValue();
case INT64:
@@ -404,6 +422,8 @@ public float getFloat(int columnIndex) throws SQLException {
switch (type) {
case BOOL:
return isNull ? 0 : (spanner.getBoolean(spannerIndex) ? (float) 1 : 0);
+ case FLOAT32:
+ return isNull ? 0 : spanner.getFloat(spannerIndex);
case FLOAT64:
return isNull ? 0 : checkedCastToFloat(spanner.getDouble(spannerIndex));
case INT64:
@@ -435,6 +455,8 @@ public double getDouble(int columnIndex) throws SQLException {
switch (type) {
case BOOL:
return isNull ? 0 : (spanner.getBoolean(spannerIndex) ? (double) 1 : 0);
+ case FLOAT32:
+ return isNull ? 0 : spanner.getFloat(spannerIndex);
case FLOAT64:
return isNull ? 0 : spanner.getDouble(spannerIndex);
case INT64:
@@ -481,6 +503,7 @@ public Date getDate(int columnIndex) throws SQLException {
? null
: new Date(spanner.getTimestamp(spannerIndex).toSqlTimestamp().getTime());
case BOOL:
+ case FLOAT32:
case FLOAT64:
case INT64:
case NUMERIC:
@@ -508,6 +531,7 @@ public Time getTime(int columnIndex) throws SQLException {
return isNull ? null : JdbcTypeConverter.toSqlTime(spanner.getTimestamp(spannerIndex));
case BOOL:
case DATE:
+ case FLOAT32:
case FLOAT64:
case INT64:
case NUMERIC:
@@ -536,6 +560,7 @@ public Timestamp getTimestamp(int columnIndex) throws SQLException {
case TIMESTAMP:
return isNull ? null : JdbcTypeConverter.toSqlTimestamp(spanner.getTimestamp(spannerIndex));
case BOOL:
+ case FLOAT32:
case FLOAT64:
case INT64:
case NUMERIC:
@@ -694,6 +719,9 @@ private Object getObject(Type type, int columnIndex) throws SQLException {
if (type == Type.bool()) return getBoolean(columnIndex);
if (type == Type.bytes()) return getBytes(columnIndex);
if (type == Type.date()) return getDate(columnIndex);
+ if (type == Type.float32()) {
+ return getFloat(columnIndex);
+ }
if (type == Type.float64()) return getDouble(columnIndex);
if (type == Type.int64()) return getLong(columnIndex);
if (type == Type.numeric()) return getBigDecimal(columnIndex);
@@ -774,6 +802,9 @@ private BigDecimal getBigDecimal(int columnIndex, boolean fixedScale, int scale)
? null
: (spanner.getBoolean(columnIndex - 1) ? BigDecimal.ONE : BigDecimal.ZERO);
break;
+ case FLOAT32:
+ res = isNull ? null : BigDecimal.valueOf(spanner.getFloat(spannerIndex));
+ break;
case FLOAT64:
res = isNull ? null : BigDecimal.valueOf(spanner.getDouble(spannerIndex));
break;
@@ -886,6 +917,7 @@ public Date getDate(int columnIndex, Calendar cal) throws SQLException {
return new Date(
JdbcTypeConverter.getAsSqlTimestamp(spanner.getTimestamp(spannerIndex), cal).getTime());
case BOOL:
+ case FLOAT32:
case FLOAT64:
case INT64:
case NUMERIC:
@@ -917,6 +949,7 @@ public Time getTime(int columnIndex, Calendar cal) throws SQLException {
return isNull ? null : JdbcTypeConverter.toSqlTime(spanner.getTimestamp(spannerIndex), cal);
case BOOL:
case DATE:
+ case FLOAT32:
case FLOAT64:
case INT64:
case NUMERIC:
@@ -951,6 +984,7 @@ public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException
case TIMESTAMP:
return JdbcTypeConverter.getAsSqlTimestamp(spanner.getTimestamp(spannerIndex), cal);
case BOOL:
+ case FLOAT32:
case FLOAT64:
case INT64:
case NUMERIC:
diff --git a/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaData.java b/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaData.java
index 26226bc66..ff1ec2e2e 100644
--- a/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaData.java
+++ b/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaData.java
@@ -95,6 +95,9 @@ public int getColumnDisplaySize(int column) {
return binaryLength == 0 ? DEFAULT_COL_DISPLAY_SIZE_FOR_VARIABLE_LENGTH_COLS : binaryLength;
case Types.DATE:
return 10;
+ case Types.REAL:
+ return JdbcDataType.FLOAT32.getDefaultColumnDisplaySize();
+ case Types.FLOAT:
case Types.DOUBLE:
return 14;
case Types.BIGINT:
@@ -134,6 +137,9 @@ public int getPrecision(int column) {
return 1;
case Types.DATE:
return 10;
+ case Types.REAL:
+ return JdbcDataType.FLOAT32.getPrecision();
+ case Types.FLOAT:
case Types.DOUBLE:
return 14;
case Types.BIGINT:
@@ -155,6 +161,9 @@ public int getPrecision(int column) {
@Override
public int getScale(int column) {
int colType = getColumnType(column);
+ if (colType == Types.REAL) {
+ return JdbcDataType.FLOAT32.getScale();
+ }
if (colType == Types.DOUBLE || colType == Types.NUMERIC) {
return 15;
}
diff --git a/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java b/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java
index a506998ea..c6be0a824 100644
--- a/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java
+++ b/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java
@@ -91,6 +91,9 @@ static Object convert(Object value, Type type, Class> targetType) throws SQLEx
if (targetType.equals(Boolean.class)) {
if (type.getCode() == Code.BOOL) return value;
if (type.getCode() == Code.INT64) return (Long) value != 0;
+ if (type.getCode() == Code.FLOAT32) {
+ return (Float) value != 0f;
+ }
if (type.getCode() == Code.FLOAT64) return (Double) value != 0d;
if (type.getCode() == Code.NUMERIC) return !value.equals(BigDecimal.ZERO);
}
@@ -134,6 +137,9 @@ static Object convert(Object value, Type type, Class> targetType) throws SQLEx
if (targetType.equals(Float.class)) {
if (type.getCode() == Code.BOOL)
return (Boolean) value ? Float.valueOf(1f) : Float.valueOf(0f);
+ if (type.getCode() == Code.FLOAT32) {
+ return value;
+ }
if (type.getCode() == Code.FLOAT64)
return AbstractJdbcWrapper.checkedCastToFloat((Double) value);
if (type.getCode() == Code.NUMERIC) return ((BigDecimal) value).floatValue();
@@ -141,7 +147,9 @@ static Object convert(Object value, Type type, Class> targetType) throws SQLEx
if (targetType.equals(Double.class)) {
if (type.getCode() == Code.BOOL)
return (Boolean) value ? Double.valueOf(1d) : Double.valueOf(0d);
- if (type.getCode() == Code.FLOAT64) return value;
+ if (type.getCode() == Code.FLOAT64 || type.getCode() == Code.FLOAT32) {
+ return value;
+ }
if (type.getCode() == Code.NUMERIC) return ((BigDecimal) value).doubleValue();
}
if (targetType.equals(java.sql.Date.class)) {
@@ -190,6 +198,8 @@ private static Value convertToSpannerValue(Object value, Type type) throws SQLEx
case DATE:
return Value.dateArray(
toGoogleDates((java.sql.Date[]) ((java.sql.Array) value).getArray()));
+ case FLOAT32:
+ return Value.float32Array(Arrays.asList((Float[]) ((java.sql.Array) value).getArray()));
case FLOAT64:
return Value.float64Array(
Arrays.asList((Double[]) ((java.sql.Array) value).getArray()));
@@ -222,6 +232,8 @@ private static Value convertToSpannerValue(Object value, Type type) throws SQLEx
return Value.bytes(ByteArray.copyFrom((byte[]) value));
case DATE:
return Value.date(toGoogleDate((java.sql.Date) value));
+ case FLOAT32:
+ return Value.float32((Float) value);
case FLOAT64:
return Value.float64((Double) value);
case INT64:
@@ -260,6 +272,9 @@ private static void checkValidTypeAndValueForConvert(Type type, Object value)
JdbcPreconditions.checkArgument(
type.getCode() != Code.DATE || value.getClass().equals(java.sql.Date.class),
"input type is date, but input value is not an instance of java.sql.Date");
+ JdbcPreconditions.checkArgument(
+ type.getCode() != Code.FLOAT32 || value.getClass().equals(Float.class),
+ "input type is float32, but input value is not an instance of Float");
JdbcPreconditions.checkArgument(
type.getCode() != Code.FLOAT64 || value.getClass().equals(Double.class),
"input type is float64, but input value is not an instance of Double");
diff --git a/src/test/java/com/google/cloud/spanner/jdbc/AllTypesMockServerTest.java b/src/test/java/com/google/cloud/spanner/jdbc/AllTypesMockServerTest.java
new file mode 100644
index 000000000..4a1eb6a6f
--- /dev/null
+++ b/src/test/java/com/google/cloud/spanner/jdbc/AllTypesMockServerTest.java
@@ -0,0 +1,372 @@
+/*
+ * 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.jdbc;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import com.google.cloud.ByteArray;
+import com.google.cloud.spanner.Dialect;
+import com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult;
+import com.google.cloud.spanner.Statement;
+import com.google.common.collect.ImmutableList;
+import com.google.protobuf.Value;
+import com.google.spanner.v1.ExecuteSqlRequest;
+import com.google.spanner.v1.Type;
+import com.google.spanner.v1.TypeCode;
+import java.math.BigDecimal;
+import java.sql.Connection;
+import java.sql.Date;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Timestamp;
+import java.util.Arrays;
+import java.util.Base64;
+import java.util.Map;
+import java.util.stream.Collectors;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class AllTypesMockServerTest
+ extends com.google.cloud.spanner.connection.AllTypesMockServerTest {
+
+ @Override
+ @Test
+ public void testSelectAllTypes() {
+ try (Connection connection = createJdbcConnection()) {
+ try (ResultSet resultSet =
+ connection.createStatement().executeQuery(SELECT_STATEMENT.getSql())) {
+ assertTrue(resultSet.next());
+
+ int col = 0;
+ assertEquals(BOOL_VALUE, resultSet.getBoolean(++col));
+ assertEquals(INT64_VALUE, resultSet.getLong(++col));
+ assertEquals(FLOAT32_VALUE, resultSet.getFloat(++col), 0.0f);
+ assertEquals(FLOAT64_VALUE, resultSet.getDouble(++col), 0.0d);
+ if (dialect == Dialect.POSTGRESQL) {
+ assertEquals(PG_NUMERIC_VALUE, resultSet.getString(++col));
+ } else {
+ assertEquals(NUMERIC_VALUE, resultSet.getBigDecimal(++col));
+ }
+ assertEquals(STRING_VALUE, resultSet.getString(++col));
+ assertEquals(JSON_VALUE, resultSet.getString(++col));
+ assertArrayEquals(BYTES_VALUE, resultSet.getBytes(++col));
+ assertEquals(
+ new java.sql.Date(
+ DATE_VALUE.getYear() - 1900, DATE_VALUE.getMonth() - 1, DATE_VALUE.getDayOfMonth()),
+ resultSet.getDate(++col));
+ assertEquals(TIMESTAMP_VALUE.toSqlTimestamp(), resultSet.getTimestamp(++col));
+
+ assertEquals(
+ BOOL_ARRAY_VALUE, Arrays.asList((Boolean[]) resultSet.getArray(++col).getArray()));
+ assertEquals(
+ INT64_ARRAY_VALUE, Arrays.asList((Long[]) resultSet.getArray(++col).getArray()));
+ assertEquals(
+ FLOAT32_ARRAY_VALUE, Arrays.asList((Float[]) resultSet.getArray(++col).getArray()));
+ assertEquals(
+ FLOAT64_ARRAY_VALUE, Arrays.asList((Double[]) resultSet.getArray(++col).getArray()));
+ if (dialect == Dialect.POSTGRESQL) {
+ // TODO: Fix getting an ARRAY. This currently tries to cast it to a
+ // BigDecimal[], which is not supported for NaN values.
+ // assertEquals(PG_NUMERIC_ARRAY_VALUE, Arrays.asList((String[])
+ // resultSet.getArray(++col).getArray()));
+ ++col;
+ } else {
+ assertEquals(
+ NUMERIC_ARRAY_VALUE,
+ Arrays.asList((BigDecimal[]) resultSet.getArray(++col).getArray()));
+ }
+ assertEquals(
+ STRING_ARRAY_VALUE, Arrays.asList((String[]) resultSet.getArray(++col).getArray()));
+ assertEquals(
+ JSON_ARRAY_VALUE, Arrays.asList((String[]) resultSet.getArray(++col).getArray()));
+ // Convert bytes to base64 strings, as the equals(..) method for byte[] uses ==.
+ assertEquals(
+ BYTES_ARRAY_VALUE.stream()
+ .map(bytes -> bytes == null ? null : bytes.toBase64())
+ .collect(Collectors.toList()),
+ Arrays.stream((byte[][]) resultSet.getArray(++col).getArray())
+ .map(bytes -> bytes == null ? null : Base64.getEncoder().encodeToString(bytes))
+ .collect(Collectors.toList()));
+ assertEquals(
+ DATE_ARRAY_VALUE.stream()
+ .map(
+ date ->
+ date == null
+ ? null
+ : new Date(
+ date.getYear() - 1900, date.getMonth() - 1, date.getDayOfMonth()))
+ .collect(Collectors.toList()),
+ Arrays.asList((Date[]) resultSet.getArray(++col).getArray()));
+ assertEquals(
+ TIMESTAMP_ARRAY_VALUE.stream()
+ .map(timestamp -> timestamp == null ? null : timestamp.toSqlTimestamp())
+ .collect(Collectors.toList()),
+ Arrays.asList((Timestamp[]) resultSet.getArray(++col).getArray()));
+
+ assertFalse(resultSet.next());
+ }
+ } catch (SQLException sqlException) {
+ throw new RuntimeException(sqlException);
+ }
+ }
+
+ @Override
+ @Test
+ public void testInsertAllTypes() {
+ // TODO: Remove when PG_NUMERIC NaN is supported.
+ if (dialect == Dialect.POSTGRESQL) {
+ Statement insertStatement = createInsertStatement(dialect);
+ insertStatement =
+ insertStatement
+ .toBuilder()
+ .replace(insertStatement.getSql().replaceAll("@p", "\\$"))
+ .bind("p15")
+ .to(
+ com.google.cloud.spanner.Value.pgNumericArray(
+ NUMERIC_ARRAY_VALUE.stream()
+ .map(
+ bigDecimal ->
+ bigDecimal == null ? null : bigDecimal.toEngineeringString())
+ .collect(Collectors.toList())))
+ .build();
+ mockSpanner.putStatementResult(StatementResult.update(insertStatement, 1L));
+ }
+ try (Connection connection = createJdbcConnection()) {
+ try (PreparedStatement statement =
+ connection.prepareStatement(
+ createInsertStatement(dialect).getSql().replaceAll("@p\\d+", "?"))) {
+ int param = 0;
+ statement.setBoolean(++param, BOOL_VALUE);
+ statement.setLong(++param, INT64_VALUE);
+ statement.setFloat(++param, FLOAT32_VALUE);
+ statement.setDouble(++param, FLOAT64_VALUE);
+ if (dialect == Dialect.POSTGRESQL) {
+ statement.setBigDecimal(++param, new BigDecimal(PG_NUMERIC_VALUE));
+ } else {
+ statement.setBigDecimal(++param, NUMERIC_VALUE);
+ }
+ statement.setString(++param, STRING_VALUE);
+ if (dialect == Dialect.POSTGRESQL) {
+ statement.setObject(++param, JSON_VALUE, JdbcDataType.PG_JSONB.getSqlType());
+ } else {
+ statement.setObject(++param, JSON_VALUE, JdbcDataType.JSON.getSqlType());
+ }
+ statement.setBytes(++param, BYTES_VALUE);
+ statement.setDate(
+ ++param,
+ new Date(
+ DATE_VALUE.getYear() - 1900,
+ DATE_VALUE.getMonth() - 1,
+ DATE_VALUE.getDayOfMonth()));
+ statement.setTimestamp(++param, TIMESTAMP_VALUE.toSqlTimestamp());
+
+ // TODO: Support PostgreSQL type names for creating arrays.
+ statement.setArray(
+ ++param, connection.createArrayOf("BOOL", BOOL_ARRAY_VALUE.toArray(new Boolean[0])));
+ statement.setArray(
+ ++param, connection.createArrayOf("INT64", INT64_ARRAY_VALUE.toArray(new Long[0])));
+ statement.setArray(
+ ++param,
+ connection.createArrayOf("FLOAT32", FLOAT32_ARRAY_VALUE.toArray(new Float[0])));
+ statement.setArray(
+ ++param,
+ connection.createArrayOf("FLOAT64", FLOAT64_ARRAY_VALUE.toArray(new Double[0])));
+
+ // TODO: Make dialect-specific when NaN in arrays for PG_NUMERIC is supported.
+ // statement.setArray(
+ // ++param,
+ // connection.createArrayOf(
+ // "NUMERIC",
+ // dialect == Dialect.POSTGRESQL
+ // ? PG_NUMERIC_ARRAY_VALUE.toArray(new String[0])
+ // : NUMERIC_ARRAY_VALUE.toArray(new BigDecimal[0])));
+ statement.setArray(
+ ++param,
+ connection.createArrayOf(
+ dialect == Dialect.POSTGRESQL ? "PG_NUMERIC" : "NUMERIC",
+ NUMERIC_ARRAY_VALUE.toArray(new BigDecimal[0])));
+
+ statement.setArray(
+ ++param, connection.createArrayOf("STRING", STRING_ARRAY_VALUE.toArray(new String[0])));
+ statement.setArray(
+ ++param,
+ connection.createArrayOf(
+ dialect == Dialect.POSTGRESQL ? "JSONB" : "JSON",
+ JSON_ARRAY_VALUE.toArray(new String[0])));
+ statement.setArray(
+ ++param,
+ connection.createArrayOf(
+ "BYTES",
+ BYTES_ARRAY_VALUE.stream()
+ .map(bytes -> bytes == null ? null : bytes.toByteArray())
+ .toArray(byte[][]::new)));
+ statement.setArray(
+ ++param,
+ connection.createArrayOf(
+ "DATE",
+ DATE_ARRAY_VALUE.stream()
+ .map(
+ date ->
+ date == null
+ ? null
+ : new Date(
+ date.getYear() - 1900,
+ date.getMonth() - 1,
+ date.getDayOfMonth()))
+ .toArray(Date[]::new)));
+ statement.setArray(
+ ++param,
+ connection.createArrayOf(
+ "TIMESTAMP",
+ TIMESTAMP_ARRAY_VALUE.stream()
+ .map(timestamp -> timestamp == null ? null : timestamp.toSqlTimestamp())
+ .toArray(Timestamp[]::new)));
+
+ assertEquals(1, statement.executeUpdate());
+ }
+
+ assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class));
+ ExecuteSqlRequest request = mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0);
+ Map paramTypes = request.getParamTypesMap();
+ Map params = request.getParams().getFieldsMap();
+ assertEquals(20, paramTypes.size());
+ assertEquals(20, params.size());
+
+ // Verify param types.
+ ImmutableList expectedTypes =
+ ImmutableList.of(
+ TypeCode.BOOL,
+ TypeCode.INT64,
+ TypeCode.FLOAT32,
+ TypeCode.FLOAT64,
+ TypeCode.NUMERIC,
+ TypeCode.STRING,
+ TypeCode.JSON,
+ TypeCode.BYTES,
+ TypeCode.DATE,
+ TypeCode.TIMESTAMP);
+ for (int col = 0; col < expectedTypes.size(); col++) {
+ assertEquals(expectedTypes.get(col), paramTypes.get("p" + (col + 1)).getCode());
+ int arrayCol = col + expectedTypes.size();
+ assertEquals(TypeCode.ARRAY, paramTypes.get("p" + (arrayCol + 1)).getCode());
+ assertEquals(
+ expectedTypes.get(col),
+ paramTypes.get("p" + (arrayCol + 1)).getArrayElementType().getCode());
+ }
+
+ // Verify param values.
+ int col = 0;
+ assertEquals(BOOL_VALUE, params.get("p" + ++col).getBoolValue());
+ assertEquals(String.valueOf(INT64_VALUE), params.get("p" + ++col).getStringValue());
+ assertEquals(FLOAT32_VALUE, params.get("p" + ++col).getNumberValue(), 0.0d);
+ assertEquals(FLOAT64_VALUE, params.get("p" + ++col).getNumberValue(), 0.0d);
+ assertEquals(
+ dialect == Dialect.POSTGRESQL ? PG_NUMERIC_VALUE : NUMERIC_VALUE.toEngineeringString(),
+ params.get("p" + ++col).getStringValue());
+ assertEquals(STRING_VALUE, params.get("p" + ++col).getStringValue());
+ assertEquals(JSON_VALUE, params.get("p" + ++col).getStringValue());
+ assertEquals(
+ Base64.getEncoder().encodeToString(BYTES_VALUE),
+ params.get("p" + ++col).getStringValue());
+ assertEquals(DATE_VALUE.toString(), params.get("p" + ++col).getStringValue());
+ assertEquals(TIMESTAMP_VALUE.toString(), params.get("p" + ++col).getStringValue());
+
+ assertEquals(
+ BOOL_ARRAY_VALUE,
+ params.get("p" + ++col).getListValue().getValuesList().stream()
+ .map(value -> value.hasNullValue() ? null : value.getBoolValue())
+ .collect(Collectors.toList()));
+ assertEquals(
+ INT64_ARRAY_VALUE,
+ params.get("p" + ++col).getListValue().getValuesList().stream()
+ .map(value -> value.hasNullValue() ? null : Long.valueOf(value.getStringValue()))
+ .collect(Collectors.toList()));
+ assertEquals(
+ FLOAT32_ARRAY_VALUE,
+ params.get("p" + ++col).getListValue().getValuesList().stream()
+ .map(value -> value.hasNullValue() ? null : (float) value.getNumberValue())
+ .collect(Collectors.toList()));
+ assertEquals(
+ FLOAT64_ARRAY_VALUE,
+ params.get("p" + ++col).getListValue().getValuesList().stream()
+ .map(value -> value.hasNullValue() ? null : value.getNumberValue())
+ .collect(Collectors.toList()));
+ if (dialect == Dialect.POSTGRESQL) {
+ // TODO: Replace with PG specific value when NaN is supported.
+ // assertEquals(
+ // PG_NUMERIC_ARRAY_VALUE,
+ // params.get("p" + ++col).getListValue().getValuesList().stream()
+ // .map(value -> value.hasNullValue() ? null : value.getStringValue())
+ // .collect(Collectors.toList()));
+ assertEquals(
+ NUMERIC_ARRAY_VALUE,
+ params.get("p" + ++col).getListValue().getValuesList().stream()
+ .map(value -> value.hasNullValue() ? null : new BigDecimal(value.getStringValue()))
+ .collect(Collectors.toList()));
+ } else {
+ assertEquals(
+ NUMERIC_ARRAY_VALUE,
+ params.get("p" + ++col).getListValue().getValuesList().stream()
+ .map(value -> value.hasNullValue() ? null : new BigDecimal(value.getStringValue()))
+ .collect(Collectors.toList()));
+ }
+ assertEquals(
+ STRING_ARRAY_VALUE,
+ params.get("p" + ++col).getListValue().getValuesList().stream()
+ .map(value -> value.hasNullValue() ? null : value.getStringValue())
+ .collect(Collectors.toList()));
+ assertEquals(
+ JSON_ARRAY_VALUE,
+ params.get("p" + ++col).getListValue().getValuesList().stream()
+ .map(value -> value.hasNullValue() ? null : value.getStringValue())
+ .collect(Collectors.toList()));
+ assertEquals(
+ BYTES_ARRAY_VALUE,
+ params.get("p" + ++col).getListValue().getValuesList().stream()
+ .map(
+ value ->
+ value.hasNullValue() ? null : ByteArray.fromBase64(value.getStringValue()))
+ .collect(Collectors.toList()));
+ assertEquals(
+ DATE_ARRAY_VALUE,
+ params.get("p" + ++col).getListValue().getValuesList().stream()
+ .map(
+ value ->
+ value.hasNullValue()
+ ? null
+ : com.google.cloud.Date.parseDate(value.getStringValue()))
+ .collect(Collectors.toList()));
+ assertEquals(
+ TIMESTAMP_ARRAY_VALUE,
+ params.get("p" + ++col).getListValue().getValuesList().stream()
+ .map(
+ value ->
+ value.hasNullValue()
+ ? null
+ : com.google.cloud.Timestamp.parseTimestamp(value.getStringValue()))
+ .collect(Collectors.toList()));
+ } catch (SQLException sqlException) {
+ throw new RuntimeException(sqlException);
+ }
+ }
+}
diff --git a/src/test/java/com/google/cloud/spanner/jdbc/JdbcArrayTest.java b/src/test/java/com/google/cloud/spanner/jdbc/JdbcArrayTest.java
index 16e16ad06..e39e28a74 100644
--- a/src/test/java/com/google/cloud/spanner/jdbc/JdbcArrayTest.java
+++ b/src/test/java/com/google/cloud/spanner/jdbc/JdbcArrayTest.java
@@ -95,6 +95,24 @@ public void testCreateArrayTypeName() throws SQLException {
assertThat(rs.next()).isFalse();
}
+ array =
+ JdbcArray.createArray(
+ "FLOAT32", new Float[] {1.1f, 2.2f, Double.valueOf(Math.PI).floatValue()});
+ assertEquals(Types.REAL, array.getBaseType());
+ assertThat(((Float[]) array.getArray(1, 3))[2]).isEqualTo(Double.valueOf(Math.PI).floatValue());
+ assertEquals(Double.valueOf(Math.PI).floatValue(), ((Float[]) array.getArray(1, 3))[2], 0.0f);
+ try (ResultSet resultSet = array.getResultSet()) {
+ assertTrue(resultSet.next());
+ // Column index 2 of a JDBC array is the value.
+ // Column index 1 of a JDBC array is the index.
+ assertEquals(1.1f, resultSet.getFloat(2), 0.0f);
+ assertTrue(resultSet.next());
+ assertEquals(2.2f, resultSet.getFloat(2), 0.0f);
+ assertTrue(resultSet.next());
+ assertEquals(Double.valueOf(Math.PI).floatValue(), resultSet.getFloat(2), 0.0f);
+ assertFalse(resultSet.next());
+ }
+
array = JdbcArray.createArray("FLOAT64", new Double[] {1.1D, 2.2D, Math.PI});
assertThat(array.getBaseType()).isEqualTo(Types.DOUBLE);
assertThat(((Double[]) array.getArray(1, 3))[2]).isEqualTo(Math.PI);
diff --git a/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java b/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java
index 9782e964a..1dc95655f 100644
--- a/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java
+++ b/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java
@@ -487,6 +487,8 @@ public void testGetTypeInfo() throws SQLException {
assertTrue(rs.next());
assertEquals("BYTES", rs.getString("TYPE_NAME"));
assertTrue(rs.next());
+ assertEquals("FLOAT32", rs.getString("TYPE_NAME"));
+ assertTrue(rs.next());
assertEquals("FLOAT64", rs.getString("TYPE_NAME"));
assertTrue(rs.next());
assertEquals("BOOL", rs.getString("TYPE_NAME"));
diff --git a/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java b/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java
index 869655bb3..ba674b255 100644
--- a/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java
+++ b/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java
@@ -147,9 +147,9 @@ public void testSetParameterWithType() throws SQLException, IOException {
params.setParameter(1, 1L, Types.BIGINT);
assertEquals(1, ((Long) params.getParameter(1)).longValue());
verifyParameter(params, Value.int64(1));
- params.setParameter(1, (float) 1, Types.FLOAT);
+ params.setParameter(1, (float) 1, Types.REAL);
assertEquals(1.0f, (Float) params.getParameter(1), 0.0f);
- verifyParameter(params, Value.float64(1));
+ verifyParameter(params, Value.float32(1));
params.setParameter(1, (double) 1, Types.DOUBLE);
assertEquals(1.0d, (Double) params.getParameter(1), 0.0d);
verifyParameter(params, Value.float64(1));
@@ -266,8 +266,33 @@ public void testSetParameterWithType() throws SQLException, IOException {
verifyParameter(params, Value.int64(1));
}
+ // types that should lead to float32
+ for (int type : new int[] {Types.REAL}) {
+ params.setParameter(1, (byte) 1, type);
+ assertEquals(1, ((Byte) params.getParameter(1)).byteValue());
+ verifyParameter(params, Value.float32(1));
+ params.setParameter(1, (short) 1, type);
+ assertEquals(1, ((Short) params.getParameter(1)).shortValue());
+ verifyParameter(params, Value.float32(1));
+ params.setParameter(1, 1, type);
+ assertEquals(1, ((Integer) params.getParameter(1)).intValue());
+ verifyParameter(params, Value.float32(1));
+ params.setParameter(1, 1L, type);
+ assertEquals(1, ((Long) params.getParameter(1)).longValue());
+ verifyParameter(params, Value.float32(1));
+ params.setParameter(1, (float) 1, type);
+ assertEquals(1.0f, (Float) params.getParameter(1), 0.0f);
+ verifyParameter(params, Value.float32(1));
+ params.setParameter(1, (double) 1, type);
+ assertEquals(1.0d, (Double) params.getParameter(1), 0.0d);
+ verifyParameter(params, Value.float32(1));
+ params.setParameter(1, BigDecimal.ONE, type);
+ assertEquals(BigDecimal.ONE, params.getParameter(1));
+ verifyParameter(params, Value.float32(1));
+ }
+
// types that should lead to float64
- for (int type : new int[] {Types.FLOAT, Types.REAL, Types.DOUBLE}) {
+ for (int type : new int[] {Types.FLOAT, Types.DOUBLE}) {
params.setParameter(1, (byte) 1, type);
assertEquals(1, ((Byte) params.getParameter(1)).byteValue());
verifyParameter(params, Value.float64(1));
@@ -438,8 +463,15 @@ public void testSetInvalidParameterWithType() throws SQLException, IOException {
assertInvalidParameter(params, Boolean.TRUE, type);
}
+ // types that should not be valid float32 parameters.
+ for (int type : new int[] {Types.REAL}) {
+ assertInvalidParameter(params, "1", type);
+ assertInvalidParameter(params, new Object(), type);
+ assertInvalidParameter(params, Boolean.TRUE, type);
+ }
+
// types that should lead to float64
- for (int type : new int[] {Types.FLOAT, Types.REAL, Types.DOUBLE}) {
+ for (int type : new int[] {Types.FLOAT, Types.DOUBLE}) {
assertInvalidParameter(params, "1", type);
assertInvalidParameter(params, new Object(), type);
assertInvalidParameter(params, Boolean.TRUE, type);
diff --git a/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaDataTest.java b/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaDataTest.java
index a46a1c324..53b58dcc1 100644
--- a/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaDataTest.java
+++ b/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaDataTest.java
@@ -73,6 +73,8 @@ private static int getDefaultSize(Type type) {
return 1;
case DATE:
return 10;
+ case FLOAT32:
+ return 7;
case FLOAT64:
return 14;
case INT64:
@@ -189,6 +191,7 @@ private static List getAllTypes() {
types.add(Type.bool());
types.add(Type.bytes());
types.add(Type.date());
+ types.add(Type.float32());
types.add(Type.float64());
types.add(Type.int64());
types.add(Type.string());
@@ -237,6 +240,8 @@ private Value getDefaultValue(Type type, int row) {
return Value.numeric(new BigDecimal("3.14"));
case PG_NUMERIC:
return Value.pgNumeric("3.14");
+ case FLOAT32:
+ return Value.float32(6.626f);
case FLOAT64:
return Value.float64(123.45D);
case STRING:
@@ -261,6 +266,8 @@ private Value getDefaultValue(Type type, int row) {
return Value.numericArray(Arrays.asList(BigDecimal.ONE, BigDecimal.TEN));
case PG_NUMERIC:
return Value.pgNumericArray(Arrays.asList("3.14", null, "NaN", "6.626"));
+ case FLOAT32:
+ return Value.float32Array(Arrays.asList(-3498.31490f, 82.353f));
case FLOAT64:
return Value.float64Array(Arrays.asList(123.45D, 543.21D));
case STRING:
@@ -371,6 +378,8 @@ private int getDefaultDisplaySize(Type type, int column) {
return 5;
case INT64:
return 10;
+ case FLOAT32:
+ return 7;
case NUMERIC:
case PG_NUMERIC:
return 14;
@@ -432,6 +441,8 @@ private int getPrecision(TestColumn col) {
return 1;
case DATE:
return 10;
+ case FLOAT32:
+ return 7;
case FLOAT64:
return 14;
case INT64:
@@ -460,6 +471,9 @@ public void testGetScale() {
}
private int getScale(TestColumn col) {
+ if (col.type == Type.float32()) {
+ return 7;
+ }
if (col.type == Type.float64() || col.type == Type.numeric() || col.type == Type.pgNumeric()) {
return 15;
}
@@ -495,6 +509,8 @@ private int getSqlType(Type type) {
case NUMERIC:
case PG_NUMERIC:
return Types.NUMERIC;
+ case FLOAT32:
+ return Types.REAL;
case FLOAT64:
return Types.DOUBLE;
case STRING:
@@ -562,6 +578,8 @@ private String getTypeClassName(Type type) {
case NUMERIC:
case PG_NUMERIC:
return BigDecimal.class.getName();
+ case FLOAT32:
+ return Float.class.getName();
case FLOAT64:
return Double.class.getName();
case STRING:
@@ -583,6 +601,8 @@ private String getTypeClassName(Type type) {
case NUMERIC:
case PG_NUMERIC:
return BigDecimal[].class.getName();
+ case FLOAT32:
+ return Float[].class.getName();
case FLOAT64:
return Double[].class.getName();
case STRING:
@@ -610,15 +630,15 @@ private String getTypeClassName(Type type) {
"Col 1: COL1 BOOL\n"
+ "Col 2: COL2 BYTES\n"
+ "Col 3: COL3 DATE\n"
- + "Col 4: COL4 FLOAT64\n"
- + "Col 5: COL5 INT64\n"
- + "Col 6: COL6 STRING\n"
- + "Col 7: COL7 JSON\n"
- + "Col 8: COL8 PG_JSONB\n"
- + "Col 9: COL9 TIMESTAMP\n"
- + "Col 10: COL10 NUMERIC\n"
- + "Col 11: COL11 PG_NUMERIC\n"
- + "Col 12: COL12 ARRAY\n"
+ + "Col 4: COL4 FLOAT32\n"
+ + "Col 5: COL5 FLOAT64\n"
+ + "Col 6: COL6 INT64\n"
+ + "Col 7: COL7 STRING\n"
+ + "Col 8: COL8 JSON\n"
+ + "Col 9: COL9 PG_JSONB\n"
+ + "Col 10: COL10 TIMESTAMP\n"
+ + "Col 11: COL11 NUMERIC\n"
+ + "Col 12: COL12 PG_NUMERIC\n"
+ "Col 13: COL13 ARRAY\n"
+ "Col 14: COL14 ARRAY\n"
+ "Col 15: COL15 ARRAY\n"
@@ -629,7 +649,9 @@ private String getTypeClassName(Type type) {
+ "Col 20: COL20 ARRAY\n"
+ "Col 21: COL21 ARRAY\n"
+ "Col 22: COL22 ARRAY\n"
- + "Col 23: CALCULATED INT64\n";
+ + "Col 23: COL23 ARRAY\n"
+ + "Col 24: COL24 ARRAY\n"
+ + "Col 25: CALCULATED INT64\n";
@Test
public void testToString() {
diff --git a/src/test/java/com/google/cloud/spanner/jdbc/PartitionedQueryMockServerTest.java b/src/test/java/com/google/cloud/spanner/jdbc/PartitionedQueryMockServerTest.java
index be5087fe4..31842409b 100644
--- a/src/test/java/com/google/cloud/spanner/jdbc/PartitionedQueryMockServerTest.java
+++ b/src/test/java/com/google/cloud/spanner/jdbc/PartitionedQueryMockServerTest.java
@@ -50,6 +50,8 @@
public class PartitionedQueryMockServerTest extends AbstractMockServerTest {
@Parameter public Dialect dialect;
+ private Dialect currentDialect;
+
@Parameters(name = "dialect = {0}")
public static Object[] data() {
return Dialect.values();
@@ -57,13 +59,21 @@ public static Object[] data() {
@Before
public void setupDialect() {
- mockSpanner.putStatementResult(StatementResult.detectDialectResult(this.dialect));
+ if (currentDialect != dialect) {
+ mockSpanner.putStatementResult(StatementResult.detectDialectResult(this.dialect));
+ currentDialect = dialect;
+ SpannerPool.closeSpannerPool();
+ }
}
@After
public void clearRequests() {
mockSpanner.clearRequests();
- SpannerPool.closeSpannerPool();
+ }
+
+ private int getExpectedColumnCount(Dialect dialect) {
+ // GoogleSQL also adds 4 PROTO columns.
+ return dialect == Dialect.GOOGLE_STANDARD_SQL ? 24 : 20;
}
private String createUrl() {
@@ -80,7 +90,7 @@ private Connection createConnection() throws SQLException {
public void testPartitionedQueryUsingSql() throws SQLException {
int numRows = 5;
int maxPartitions = 4;
- RandomResultSetGenerator generator = new RandomResultSetGenerator(numRows);
+ RandomResultSetGenerator generator = new RandomResultSetGenerator(numRows, dialect);
Statement statement =
Statement.newBuilder(
String.format(
@@ -158,7 +168,7 @@ public void testPartitionedQueryUsingSql() throws SQLException {
partitionStatement.setBoolean(1, true);
try (ResultSet results = partitionStatement.executeQuery()) {
assertNotNull(results.getMetaData());
- assertEquals(24, results.getMetaData().getColumnCount());
+ assertEquals(getExpectedColumnCount(dialect), results.getMetaData().getColumnCount());
int rowCount = 0;
while (results.next()) {
rowCount++;
@@ -184,7 +194,7 @@ public void testPartitionedQueryUsingSql() throws SQLException {
public void testPartitionedQueryStatement() throws SQLException {
int numRows = 5;
int maxPartitions = 4;
- RandomResultSetGenerator generator = new RandomResultSetGenerator(numRows);
+ RandomResultSetGenerator generator = new RandomResultSetGenerator(numRows, dialect);
Statement statement = Statement.of("select * from my_table where active=true");
mockSpanner.putStatementResult(StatementResult.query(statement, generator.generate()));
@@ -266,7 +276,7 @@ public void testPartitionedQueryStatement() throws SQLException {
public void testPartitionedQueryPreparedStatement() throws SQLException {
int numRows = 5;
int maxPartitions = 4;
- RandomResultSetGenerator generator = new RandomResultSetGenerator(numRows);
+ RandomResultSetGenerator generator = new RandomResultSetGenerator(numRows, dialect);
Statement statement =
Statement.newBuilder(
String.format(
@@ -357,7 +367,7 @@ public void testPartitionedQueryPreparedStatement() throws SQLException {
public void testAutoPartitionMode() throws SQLException {
int numRows = 5;
int maxPartitions = 4;
- RandomResultSetGenerator generator = new RandomResultSetGenerator(numRows);
+ RandomResultSetGenerator generator = new RandomResultSetGenerator(numRows, dialect);
Statement statement = Statement.of("select * from my_table where active=true");
mockSpanner.putStatementResult(StatementResult.query(statement, generator.generate()));
@@ -376,7 +386,7 @@ public void testAutoPartitionMode() throws SQLException {
try (ResultSet results =
connection.createStatement().executeQuery("select * from my_table where active=true")) {
assertNotNull(results.getMetaData());
- assertEquals(24, results.getMetaData().getColumnCount());
+ assertEquals(getExpectedColumnCount(dialect), results.getMetaData().getColumnCount());
int rowCount = 0;
while (results.next()) {
rowCount++;
@@ -463,7 +473,7 @@ public void testAutoPartitionMode() throws SQLException {
public void testAutoPartitionModeEmptyResult() throws SQLException {
int numRows = 0;
int maxPartitions = 1;
- RandomResultSetGenerator generator = new RandomResultSetGenerator(numRows);
+ RandomResultSetGenerator generator = new RandomResultSetGenerator(numRows, dialect);
Statement statement = Statement.of("select * from my_table where active=true");
mockSpanner.putStatementResult(StatementResult.query(statement, generator.generate()));
@@ -482,7 +492,7 @@ public void testAutoPartitionModeEmptyResult() throws SQLException {
try (ResultSet results =
connection.createStatement().executeQuery("select * from my_table where active=true")) {
assertNotNull(results.getMetaData());
- assertEquals(24, results.getMetaData().getColumnCount());
+ assertEquals(getExpectedColumnCount(dialect), results.getMetaData().getColumnCount());
int rowCount = 0;
while (results.next()) {
rowCount++;
diff --git a/src/test/java/com/google/cloud/spanner/jdbc/PreparedStatementParameterMetadataTest.java b/src/test/java/com/google/cloud/spanner/jdbc/PreparedStatementParameterMetadataTest.java
index 8b7130ed6..a6d7c3542 100644
--- a/src/test/java/com/google/cloud/spanner/jdbc/PreparedStatementParameterMetadataTest.java
+++ b/src/test/java/com/google/cloud/spanner/jdbc/PreparedStatementParameterMetadataTest.java
@@ -60,18 +60,18 @@ public void testAllTypesParameterMetadata_GoogleSql() throws SQLException {
MockSpannerServiceImpl.StatementResult.detectDialectResult(Dialect.GOOGLE_STANDARD_SQL));
String baseSql =
- "insert into all_types (col_bool, col_bytes, col_date, col_float64, col_int64, "
+ "insert into all_types (col_bool, col_bytes, col_date, col_float32, col_float64, col_int64, "
+ "col_json, col_numeric, col_string, col_timestamp, col_bool_array, col_bytes_array, "
- + "col_date_array, col_float64_array, col_int64_array, col_json_array, col_numeric_array, "
- + "col_string_array, col_timestamp_array) values (%s)";
+ + "col_date_array, col_float32_array, col_float64_array, col_int64_array, col_json_array,"
+ + "col_numeric_array, col_string_array, col_timestamp_array) values (%s)";
String jdbcSql =
String.format(
baseSql,
- IntStream.range(0, 18).mapToObj(ignored -> "?").collect(Collectors.joining(", ")));
+ IntStream.range(0, 20).mapToObj(ignored -> "?").collect(Collectors.joining(", ")));
String googleSql =
String.format(
baseSql,
- IntStream.range(1, 19)
+ IntStream.range(1, 21)
.mapToObj(index -> "@p" + index)
.collect(Collectors.joining(", ")));
mockSpanner.putStatementResult(
@@ -89,7 +89,7 @@ public void testAllTypesParameterMetadata_GoogleSql() throws SQLException {
try (Connection connection = createJdbcConnection()) {
try (PreparedStatement statement = connection.prepareStatement(jdbcSql)) {
ParameterMetaData metadata = statement.getParameterMetaData();
- assertEquals(18, metadata.getParameterCount());
+ assertEquals(20, metadata.getParameterCount());
int index = 0;
assertEquals(Types.BOOLEAN, metadata.getParameterType(++index));
assertEquals("BOOL", metadata.getParameterTypeName(index));
@@ -97,6 +97,8 @@ public void testAllTypesParameterMetadata_GoogleSql() throws SQLException {
assertEquals("BYTES", metadata.getParameterTypeName(index));
assertEquals(Types.DATE, metadata.getParameterType(++index));
assertEquals("DATE", metadata.getParameterTypeName(index));
+ assertEquals(Types.REAL, metadata.getParameterType(++index));
+ assertEquals("FLOAT32", metadata.getParameterTypeName(index));
assertEquals(Types.DOUBLE, metadata.getParameterType(++index));
assertEquals("FLOAT64", metadata.getParameterTypeName(index));
assertEquals(Types.BIGINT, metadata.getParameterType(++index));
@@ -117,6 +119,8 @@ public void testAllTypesParameterMetadata_GoogleSql() throws SQLException {
assertEquals(Types.ARRAY, metadata.getParameterType(++index));
assertEquals("ARRAY", metadata.getParameterTypeName(index));
assertEquals(Types.ARRAY, metadata.getParameterType(++index));
+ assertEquals("ARRAY", metadata.getParameterTypeName(index));
+ assertEquals(Types.ARRAY, metadata.getParameterType(++index));
assertEquals("ARRAY", metadata.getParameterTypeName(index));
assertEquals(Types.ARRAY, metadata.getParameterType(++index));
assertEquals("ARRAY", metadata.getParameterTypeName(index));
@@ -166,7 +170,7 @@ public void testAllTypesParameterMetadata_PostgreSQL() throws SQLException {
try (Connection connection = createJdbcConnection()) {
try (PreparedStatement statement = connection.prepareStatement(jdbcSql)) {
ParameterMetaData metadata = statement.getParameterMetaData();
- assertEquals(18, metadata.getParameterCount());
+ assertEquals(20, metadata.getParameterCount());
int index = 0;
assertEquals(Types.BOOLEAN, metadata.getParameterType(++index));
assertEquals("boolean", metadata.getParameterTypeName(index));
@@ -174,6 +178,8 @@ public void testAllTypesParameterMetadata_PostgreSQL() throws SQLException {
assertEquals("bytea", metadata.getParameterTypeName(index));
assertEquals(Types.DATE, metadata.getParameterType(++index));
assertEquals("date", metadata.getParameterTypeName(index));
+ assertEquals(Types.REAL, metadata.getParameterType(++index));
+ assertEquals("real", metadata.getParameterTypeName(index));
assertEquals(Types.DOUBLE, metadata.getParameterType(++index));
assertEquals("double precision", metadata.getParameterTypeName(index));
assertEquals(Types.BIGINT, metadata.getParameterType(++index));
@@ -194,6 +200,8 @@ public void testAllTypesParameterMetadata_PostgreSQL() throws SQLException {
assertEquals(Types.ARRAY, metadata.getParameterType(++index));
assertEquals("date[]", metadata.getParameterTypeName(index));
assertEquals(Types.ARRAY, metadata.getParameterType(++index));
+ assertEquals("real[]", metadata.getParameterTypeName(index));
+ assertEquals(Types.ARRAY, metadata.getParameterType(++index));
assertEquals("double precision[]", metadata.getParameterTypeName(index));
assertEquals(Types.ARRAY, metadata.getParameterType(++index));
assertEquals("bigint[]", metadata.getParameterTypeName(index));
@@ -229,16 +237,21 @@ static StructType createAllTypesParameters(Dialect dialect) {
.addFields(
Field.newBuilder()
.setName("p4")
- .setType(Type.newBuilder().setCode(TypeCode.FLOAT64).build())
+ .setType(Type.newBuilder().setCode(TypeCode.FLOAT32).build())
.build())
.addFields(
Field.newBuilder()
.setName("p5")
- .setType(Type.newBuilder().setCode(TypeCode.INT64).build())
+ .setType(Type.newBuilder().setCode(TypeCode.FLOAT64).build())
.build())
.addFields(
Field.newBuilder()
.setName("p6")
+ .setType(Type.newBuilder().setCode(TypeCode.INT64).build())
+ .build())
+ .addFields(
+ Field.newBuilder()
+ .setName("p7")
.setType(
Type.newBuilder()
.setCode(TypeCode.JSON)
@@ -250,7 +263,7 @@ static StructType createAllTypesParameters(Dialect dialect) {
.build())
.addFields(
Field.newBuilder()
- .setName("p7")
+ .setName("p8")
.setType(
Type.newBuilder()
.setCode(TypeCode.NUMERIC)
@@ -262,17 +275,17 @@ static StructType createAllTypesParameters(Dialect dialect) {
.build())
.addFields(
Field.newBuilder()
- .setName("p8")
+ .setName("p9")
.setType(Type.newBuilder().setCode(TypeCode.STRING).build())
.build())
.addFields(
Field.newBuilder()
- .setName("p9")
+ .setName("p10")
.setType(Type.newBuilder().setCode(TypeCode.TIMESTAMP).build())
.build())
.addFields(
Field.newBuilder()
- .setName("p10")
+ .setName("p11")
.setType(
Type.newBuilder()
.setCode(TypeCode.ARRAY)
@@ -280,7 +293,7 @@ static StructType createAllTypesParameters(Dialect dialect) {
.build())
.addFields(
Field.newBuilder()
- .setName("p11")
+ .setName("p12")
.setType(
Type.newBuilder()
.setCode(TypeCode.ARRAY)
@@ -288,7 +301,7 @@ static StructType createAllTypesParameters(Dialect dialect) {
.build())
.addFields(
Field.newBuilder()
- .setName("p12")
+ .setName("p13")
.setType(
Type.newBuilder()
.setCode(TypeCode.ARRAY)
@@ -296,7 +309,15 @@ static StructType createAllTypesParameters(Dialect dialect) {
.build())
.addFields(
Field.newBuilder()
- .setName("p13")
+ .setName("p14")
+ .setType(
+ Type.newBuilder()
+ .setCode(TypeCode.ARRAY)
+ .setArrayElementType(Type.newBuilder().setCode(TypeCode.FLOAT32).build()))
+ .build())
+ .addFields(
+ Field.newBuilder()
+ .setName("p15")
.setType(
Type.newBuilder()
.setCode(TypeCode.ARRAY)
@@ -304,7 +325,7 @@ static StructType createAllTypesParameters(Dialect dialect) {
.build())
.addFields(
Field.newBuilder()
- .setName("p14")
+ .setName("p16")
.setType(
Type.newBuilder()
.setCode(TypeCode.ARRAY)
@@ -312,7 +333,7 @@ static StructType createAllTypesParameters(Dialect dialect) {
.build())
.addFields(
Field.newBuilder()
- .setName("p15")
+ .setName("p17")
.setType(
Type.newBuilder()
.setCode(TypeCode.ARRAY)
@@ -327,7 +348,7 @@ static StructType createAllTypesParameters(Dialect dialect) {
.build())
.addFields(
Field.newBuilder()
- .setName("p16")
+ .setName("p18")
.setType(
Type.newBuilder()
.setCode(TypeCode.ARRAY)
@@ -342,7 +363,7 @@ static StructType createAllTypesParameters(Dialect dialect) {
.build())
.addFields(
Field.newBuilder()
- .setName("p17")
+ .setName("p19")
.setType(
Type.newBuilder()
.setCode(TypeCode.ARRAY)
@@ -350,7 +371,7 @@ static StructType createAllTypesParameters(Dialect dialect) {
.build())
.addFields(
Field.newBuilder()
- .setName("p18")
+ .setName("p20")
.setType(
Type.newBuilder()
.setCode(TypeCode.ARRAY)
diff --git a/src/test/java/com/google/cloud/spanner/jdbc/RandomResultSetTest.java b/src/test/java/com/google/cloud/spanner/jdbc/RandomResultSetTest.java
new file mode 100644
index 000000000..4d24068dc
--- /dev/null
+++ b/src/test/java/com/google/cloud/spanner/jdbc/RandomResultSetTest.java
@@ -0,0 +1,164 @@
+/*
+ * 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.jdbc;
+
+import static org.junit.Assert.assertEquals;
+
+import com.google.cloud.spanner.Dialect;
+import com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult;
+import com.google.cloud.spanner.connection.AbstractMockServerTest;
+import com.google.cloud.spanner.connection.RandomResultSetGenerator;
+import com.google.cloud.spanner.connection.SpannerPool;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Types;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class RandomResultSetTest extends AbstractMockServerTest {
+ @Parameter public Dialect dialect;
+
+ @Parameters(name = "dialect = {0}")
+ public static Object[] data() {
+ return Dialect.values();
+ }
+
+ @Before
+ public void setupDialect() {
+ mockSpanner.putStatementResult(StatementResult.detectDialectResult(dialect));
+ RandomResultSetGenerator generator =
+ new RandomResultSetGenerator(RANDOM_RESULT_SET_ROW_COUNT, dialect);
+ mockSpanner.putStatementResult(
+ StatementResult.query(SELECT_RANDOM_STATEMENT, generator.generate()));
+ }
+
+ @After
+ public void reset() {
+ // This ensures that each test gets a fresh Spanner instance. This is necessary to get a new
+ // dialect result for each connection.
+ SpannerPool.closeSpannerPool();
+ }
+
+ @Test
+ public void testSelectRandomResults() throws SQLException {
+ try (Connection connection = createJdbcConnection()) {
+ try (ResultSet resultSet =
+ connection.createStatement().executeQuery(SELECT_RANDOM_STATEMENT.getSql())) {
+ ResultSetMetaData metadata = resultSet.getMetaData();
+ int col = 0;
+ assertEquals(Types.BOOLEAN, metadata.getColumnType(++col));
+ assertEquals(Types.BIGINT, metadata.getColumnType(++col));
+ assertEquals(Types.REAL, metadata.getColumnType(++col));
+ assertEquals(Types.DOUBLE, metadata.getColumnType(++col));
+ assertEquals(Types.NUMERIC, metadata.getColumnType(++col));
+ assertEquals(Types.NVARCHAR, metadata.getColumnType(++col));
+ assertEquals(Types.NVARCHAR, metadata.getColumnType(++col));
+ assertEquals(Types.BINARY, metadata.getColumnType(++col));
+ assertEquals(Types.DATE, metadata.getColumnType(++col));
+ assertEquals(Types.TIMESTAMP, metadata.getColumnType(++col));
+
+ assertEquals(Types.ARRAY, metadata.getColumnType(++col)); // boolean
+ assertEquals(Types.ARRAY, metadata.getColumnType(++col)); // bigint
+ assertEquals(Types.ARRAY, metadata.getColumnType(++col)); // real
+ assertEquals(Types.ARRAY, metadata.getColumnType(++col)); // double
+ assertEquals(Types.ARRAY, metadata.getColumnType(++col)); // numeric
+ assertEquals(Types.ARRAY, metadata.getColumnType(++col)); // nvarchar
+ assertEquals(Types.ARRAY, metadata.getColumnType(++col)); // nvarchar
+ assertEquals(Types.ARRAY, metadata.getColumnType(++col)); // binary
+ assertEquals(Types.ARRAY, metadata.getColumnType(++col)); // date
+ assertEquals(Types.ARRAY, metadata.getColumnType(++col)); // timestamp
+
+ // GoogleSQL also includes proto columns.
+ if (dialect == Dialect.GOOGLE_STANDARD_SQL) {
+ // Skip for now, as support for this has not yet been added.
+ // assertEquals(Types.OTHER, metadata.getColumnType(++col));
+ // assertEquals(Types.OTHER, metadata.getColumnType(++col));
+ // assertEquals(Types.ARRAY, metadata.getColumnType(++col));
+ // assertEquals(Types.ARRAY, metadata.getColumnType(++col));
+ col += 4;
+ }
+
+ assertEquals(col, metadata.getColumnCount());
+
+ int rowCount = 0;
+ while (resultSet.next()) {
+ // Verify that we can get all columns as an object.
+ for (col = 1; col <= resultSet.getMetaData().getColumnCount(); col++) {
+ if (dialect == Dialect.GOOGLE_STANDARD_SQL && col > 20) {
+ // Proto columns are not yet supported, so skipping.
+ } else if (dialect == Dialect.POSTGRESQL && col == 7) {
+ // PG_JSONB is not yet recognized by the JDBC driver, so skipping.
+ } else if (dialect == Dialect.POSTGRESQL && col == 15) {
+ // getObject for ARRAY tries to get the array as a List.
+ // That fails if the array contains a NaN, so skipping.
+ } else {
+ resultSet.getObject(col);
+ }
+ }
+
+ // Verify that we can get the results as the actual type.
+ col = 0;
+ resultSet.getBoolean(++col);
+ resultSet.getLong(++col);
+ resultSet.getFloat(++col);
+ resultSet.getDouble(++col);
+ resultSet.getFloat(++col);
+ resultSet.getString(++col);
+ resultSet.getString(++col); // JSON
+ resultSet.getBytes(++col);
+ resultSet.getDate(++col);
+ resultSet.getTimestamp(++col);
+
+ resultSet.getArray(++col);
+ resultSet.getArray(++col);
+ resultSet.getArray(++col);
+ resultSet.getArray(++col);
+ if (dialect == Dialect.POSTGRESQL) {
+ // Skipping, as getArray(..) returns an array of BigDecimal for PG_NUMERIC, and that is
+ // not supported if the array contains a NaN.
+ ++col;
+ } else {
+ resultSet.getArray(++col);
+ }
+ resultSet.getArray(++col);
+ resultSet.getArray(++col);
+ resultSet.getArray(++col);
+ resultSet.getArray(++col);
+ resultSet.getArray(++col);
+
+ // GoogleSQL also includes proto columns.
+ if (dialect == Dialect.GOOGLE_STANDARD_SQL) {
+ // Skip for now, as support for this has not yet been added.
+ col += 4;
+ }
+ assertEquals(col, resultSet.getMetaData().getColumnCount());
+
+ rowCount++;
+ }
+ assertEquals(RANDOM_RESULT_SET_ROW_COUNT, rowCount);
+ }
+ }
+ }
+}
diff --git a/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgNumericTest.java b/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgNumericTest.java
index 5527c8b95..2198c9464 100644
--- a/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgNumericTest.java
+++ b/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgNumericTest.java
@@ -227,7 +227,9 @@ public void testPreparedStatement() throws Exception {
preparedStatement.setShort(3, (short) 1);
preparedStatement.setInt(4, 1);
preparedStatement.setLong(5, 1L);
- preparedStatement.setFloat(6, 1F);
+ // TODO: Change to setFloat(..) when float32 is supported.
+ // preparedStatement.setFloat(6, 1f);
+ preparedStatement.setDouble(6, 1d);
preparedStatement.setDouble(7, 1D);
preparedStatement.setBigDecimal(8, new BigDecimal("1"));
preparedStatement.setObject(9, (byte) 1);
@@ -239,7 +241,9 @@ public void testPreparedStatement() throws Exception {
preparedStatement.setObject(15, new BigDecimal("1"));
preparedStatement.setObject(16, Value.pgNumeric("1"));
- preparedStatement.setFloat(17, Float.NaN);
+ // TODO: Change to setFloat(..) when float32 is supported.
+ // preparedStatement.setFloat(17, Float.NaN);
+ preparedStatement.setDouble(17, Double.NaN);
preparedStatement.setDouble(18, Double.NaN);
preparedStatement.setObject(19, Value.pgNumeric("NaN"));
From 138d637f1f66831cb86554ee566feb2a153c3f12 Mon Sep 17 00:00:00 2001
From: "release-please[bot]"
<55107282+release-please[bot]@users.noreply.github.com>
Date: Thu, 7 Mar 2024 18:08:16 +0100
Subject: [PATCH 18/18] chore(main): release 2.16.0 (#1515)
Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com>
---
CHANGELOG.md | 18 ++++++++++++++++++
pom.xml | 2 +-
samples/snapshot/pom.xml | 2 +-
versions.txt | 2 +-
4 files changed, 21 insertions(+), 3 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d4d5f2581..db9160047 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,23 @@
# Changelog
+## [2.16.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.15.5...v2.16.0) (2024-03-07)
+
+
+### Features
+
+* Support float32 ([#1518](https://github.com/googleapis/java-spanner-jdbc/issues/1518)) ([635ac41](https://github.com/googleapis/java-spanner-jdbc/commit/635ac41e054814cf3b58d37cbc42b01ac183b2a1))
+
+
+### Dependencies
+
+* Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.27.0 ([#1521](https://github.com/googleapis/java-spanner-jdbc/issues/1521)) ([a8eecfb](https://github.com/googleapis/java-spanner-jdbc/commit/a8eecfb3a731505ba309b4a359dea7b88990c88a))
+* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.60.1 ([#1514](https://github.com/googleapis/java-spanner-jdbc/issues/1514)) ([cf8fe9e](https://github.com/googleapis/java-spanner-jdbc/commit/cf8fe9eea2423f64867c9ecd790916b81165e575))
+* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.61.0 ([#1523](https://github.com/googleapis/java-spanner-jdbc/issues/1523)) ([0c1e281](https://github.com/googleapis/java-spanner-jdbc/commit/0c1e28177131f30405b09cf38fa7a78645a3508a))
+* Update dependency com.google.cloud:sdk-platform-java-config to v3.27.0 ([#1522](https://github.com/googleapis/java-spanner-jdbc/issues/1522)) ([28986f9](https://github.com/googleapis/java-spanner-jdbc/commit/28986f9dddabfe2d89b2e3155885434413c3941e))
+* Update dependency com.spotify.fmt:fmt-maven-plugin to v2.23 ([#1527](https://github.com/googleapis/java-spanner-jdbc/issues/1527)) ([1e7a4f7](https://github.com/googleapis/java-spanner-jdbc/commit/1e7a4f73339479134868206730c275fe752e8d0d))
+* Update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.2.3 ([#1512](https://github.com/googleapis/java-spanner-jdbc/issues/1512)) ([e5825c9](https://github.com/googleapis/java-spanner-jdbc/commit/e5825c9a4aa9df68b1ca911430ef37cb6d3549c4))
+* Update dependency org.springframework.boot:spring-boot-starter-parent to v3.2.3 ([#1513](https://github.com/googleapis/java-spanner-jdbc/issues/1513)) ([8cfaa1a](https://github.com/googleapis/java-spanner-jdbc/commit/8cfaa1a523c32ebed307f747fd939bd900c28b34))
+
## [2.15.5](https://github.com/googleapis/java-spanner-jdbc/compare/v2.15.4...v2.15.5) (2024-02-21)
diff --git a/pom.xml b/pom.xml
index 9b9a6fb8a..5ee420fc8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
google-cloud-spanner-jdbc
- 2.15.6-SNAPSHOT
+ 2.16.0
jar
Google Cloud Spanner JDBC
https://github.com/googleapis/java-spanner-jdbc
diff --git a/samples/snapshot/pom.xml b/samples/snapshot/pom.xml
index 832a1bf1f..319b7d2f8 100644
--- a/samples/snapshot/pom.xml
+++ b/samples/snapshot/pom.xml
@@ -28,7 +28,7 @@
com.google.cloud
google-cloud-spanner-jdbc
- 2.15.6-SNAPSHOT
+ 2.16.0
diff --git a/versions.txt b/versions.txt
index a6e48e1b8..b03866d33 100644
--- a/versions.txt
+++ b/versions.txt
@@ -1,4 +1,4 @@
# Format:
# module:released-version:current-version
-google-cloud-spanner-jdbc:2.15.5:2.15.6-SNAPSHOT
+google-cloud-spanner-jdbc:2.16.0:2.16.0