From 680afe77eac2e4e56117135252024df6ca81c8ab Mon Sep 17 00:00:00 2001 From: Olav Loite Date: Sun, 25 Aug 2019 07:47:35 +0200 Subject: [PATCH 1/3] nullsAreSortedAtStart should be false Cloud Spanner treats null values as the lowest possible value, and sorts these accordingly. That means that when sort order is descending, null values will be sorted at the end, while when sort order is ascending null values will be sorted at the start. This method should only return true if nulls are ALWAYS sorted at start. --- .../com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/google-cloud-clients/google-cloud-contrib/google-cloud-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java b/google-cloud-clients/google-cloud-contrib/google-cloud-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java index 828bb06bbbf2..c88781c0cc5e 100644 --- a/google-cloud-clients/google-cloud-contrib/google-cloud-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java +++ b/google-cloud-clients/google-cloud-contrib/google-cloud-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java @@ -115,7 +115,7 @@ public boolean nullsAreSortedLow() throws SQLException { @Override public boolean nullsAreSortedAtStart() throws SQLException { - return true; + return false; } @Override From b3d9d3c8b64031d60b0848024e9c164f3364e48d Mon Sep 17 00:00:00 2001 From: Olav Loite Date: Sun, 25 Aug 2019 08:05:04 +0200 Subject: [PATCH 2/3] document how Cloud Spanner supports UNION --- .../com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/google-cloud-clients/google-cloud-contrib/google-cloud-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java b/google-cloud-clients/google-cloud-contrib/google-cloud-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java index c88781c0cc5e..9ab38d9d2254 100644 --- a/google-cloud-clients/google-cloud-contrib/google-cloud-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java +++ b/google-cloud-clients/google-cloud-contrib/google-cloud-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java @@ -502,6 +502,8 @@ public boolean supportsCorrelatedSubqueries() throws SQLException { @Override public boolean supportsUnion() throws SQLException { + // Note that Cloud Spanner requires the user to specify 'UNION DISTINCT' or 'UNION ALL' in a + // query. 'UNION DISTINCT' is equal to the SQL operation 'UNION'. return true; } From 98a16ee95c89409c792fd80557f4d77f6410a713 Mon Sep 17 00:00:00 2001 From: Olav Loite Date: Sun, 25 Aug 2019 08:05:24 +0200 Subject: [PATCH 3/3] add missing trivial test cases --- .../jdbc/JdbcDatabaseMetaDataTest.java | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/google-cloud-clients/google-cloud-contrib/google-cloud-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java b/google-cloud-clients/google-cloud-contrib/google-cloud-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java index db7c7f812837..6c3363be3832 100644 --- a/google-cloud-clients/google-cloud-contrib/google-cloud-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java +++ b/google-cloud-clients/google-cloud-contrib/google-cloud-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java @@ -31,6 +31,7 @@ import java.sql.ResultSetMetaData; import java.sql.RowIdLifetime; import java.sql.SQLException; +import java.sql.Types; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -61,6 +62,13 @@ public void testTrivialMethods() throws SQLException { }) { assertThat(meta.deletesAreDetected(type), is(false)); assertThat(meta.insertsAreDetected(type), is(false)); + assertThat(meta.updatesAreDetected(type), is(false)); + assertThat(meta.ownDeletesAreVisible(type), is(false)); + assertThat(meta.ownInsertsAreVisible(type), is(false)); + assertThat(meta.ownUpdatesAreVisible(type), is(false)); + assertThat(meta.othersDeletesAreVisible(type), is(false)); + assertThat(meta.othersInsertsAreVisible(type), is(false)); + assertThat(meta.othersUpdatesAreVisible(type), is(false)); } assertThat(meta.doesMaxRowSizeIncludeBlobs(), is(true)); assertThat(meta.generatedKeyAlwaysReturned(), is(false)); @@ -72,6 +80,8 @@ public void testTrivialMethods() throws SQLException { assertThat( meta.getDatabaseProductVersion(), is(equalTo(DATABASE_MAJOR_VERSION + "." + DATABASE_MINOR_VERSION))); + assertThat( + meta.getDefaultTransactionIsolation(), is(equalTo(Connection.TRANSACTION_SERIALIZABLE))); assertThat(meta.getDriverName(), is(equalTo("com.google.cloud.spanner.jdbc.JdbcDriver"))); assertThat(meta.getExtraNameCharacters(), is(equalTo(""))); assertThat(meta.getIdentifierQuoteString(), is(equalTo("`"))); @@ -104,6 +114,12 @@ public void testTrivialMethods() throws SQLException { assertThat(meta.getSchemaTerm(), is(equalTo("SCHEMA"))); assertThat(meta.getSearchStringEscape(), is(equalTo("\\"))); assertThat(meta.getSQLStateType(), is(equalTo(DatabaseMetaData.sqlStateSQL))); + assertThat(meta.locatorsUpdateCopy(), is(true)); + assertThat(meta.nullsAreSortedHigh(), is(false)); + assertThat(meta.nullsAreSortedLow(), is(true)); + assertThat(meta.nullsAreSortedAtStart(), is(false)); + assertThat(meta.nullsAreSortedAtEnd(), is(false)); + assertThat(meta.nullPlusNonNullIsNull(), is(true)); assertThat(meta.isCatalogAtStart(), is(false)); assertThat(meta.isReadOnly(), is(equalTo(connection.isReadOnly()))); assertThat(meta.storesLowerCaseIdentifiers(), is(false)); @@ -124,7 +140,54 @@ public void testTrivialMethods() throws SQLException { assertThat(meta.supportsCatalogsInProcedureCalls(), is(false)); assertThat(meta.supportsCatalogsInTableDefinitions(), is(false)); assertThat(meta.supportsColumnAliasing(), is(true)); + // Note that the supportsConvert() method indicates whether the server side function CONVERT is + // supported, not what the JDBC driver might be able to convert on the client side. assertThat(meta.supportsConvert(), is(false)); + int[] types = + new int[] { + Types.ARRAY, + Types.BIGINT, + Types.BINARY, + Types.BIT, + Types.BLOB, + Types.BOOLEAN, + Types.CHAR, + Types.CLOB, + Types.DATALINK, + Types.DATE, + Types.DECIMAL, + Types.DISTINCT, + Types.DOUBLE, + Types.FLOAT, + Types.INTEGER, + Types.JAVA_OBJECT, + Types.LONGNVARCHAR, + Types.LONGVARCHAR, + Types.LONGVARBINARY, + Types.LONGVARCHAR, + Types.NCHAR, + Types.NCLOB, + Types.NULL, + Types.NUMERIC, + Types.NVARCHAR, + Types.OTHER, + Types.REAL, + Types.REF, + Types.ROWID, + Types.SMALLINT, + Types.SQLXML, + Types.STRUCT, + Types.TIME, + Types.TIMESTAMP, + Types.TINYINT, + Types.VARBINARY, + Types.VARCHAR + }; + for (int from : types) { + for (int to : types) { + assertThat(meta.supportsConvert(from, to), is(false)); + } + } assertThat(meta.supportsCoreSQLGrammar(), is(false)); assertThat(meta.supportsCorrelatedSubqueries(), is(true)); assertThat(meta.supportsDataDefinitionAndDataManipulationTransactions(), is(false)); @@ -186,6 +249,11 @@ public void testTrivialMethods() throws SQLException { assertThat(meta.supportsSubqueriesInIns(), is(true)); assertThat(meta.supportsSubqueriesInQuantifieds(), is(true)); assertThat(meta.supportsTableCorrelationNames(), is(true)); + assertThat(meta.supportsTransactions(), is(true)); + assertThat(meta.supportsUnion(), is(true)); + assertThat(meta.supportsUnionAll(), is(true)); + assertThat(meta.usesLocalFiles(), is(false)); + assertThat(meta.usesLocalFilePerTable(), is(false)); assertThat( meta.supportsTransactionIsolationLevel(Connection.TRANSACTION_SERIALIZABLE), is(true)); for (int level :