Repository: googleapis/java-spanner-jdbc
Pull request #1381 (2023-10-03 23:23:39)

chore: bump urllib3 from 1.26.16 to 1.26.17 in /synthtool/gcp/templates/java_library/.kokoro (#1875)
chore: bump urllib3 in /synthtool/gcp/templates/java_library/.kokoro

Bumps [urllib3](https://github.com/urllib3/urllib3) from 1.26.16 to 1.26.17.
- [Release notes](https://github.com/urllib3/urllib3/releases)
- [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst)
- [Commits](https://github.com/urllib3/urllib3/compare/1.26.16...1.26.17)

---
updated-dependencies:
- dependency-name: urllib3
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Source-Link: https://github.com/googleapis/synthtool/commit/dbb940f3b99eca99265fda43dd4526a548b63a54
Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:6e2fc7eba84c3100cde964ebcfd0e553d4664ec4a74989c978a143812785ff23


Patch:
diff --git a/.github/.OwlBot.lock.yaml b/.github/.OwlBot.lock.yaml
index 52eaa54..11fe204 100644
--- a/.github/.OwlBot.lock.yaml
+++ b/.github/.OwlBot.lock.yaml
@@ -13,5 +13,5 @@
 # limitations under the License.
 docker:
   image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest
-  digest: sha256:88ba8dcc5c2c7792e1c3511381f4ab329002a1c42c512f66ca87ced572dfbf9f
-# created: 2023-09-05T18:54:42.225408832Z
+  digest: sha256:6e2fc7eba84c3100cde964ebcfd0e553d4664ec4a74989c978a143812785ff23
+# created: 2023-10-03T23:18:35.620358763Z
diff --git a/.kokoro/requirements.txt b/.kokoro/requirements.txt
index a73256a..59de492 100644
--- a/.kokoro/requirements.txt
+++ b/.kokoro/requirements.txt
@@ -418,6 +418,7 @@ protobuf==3.20.3 \
     #   gcp-docuploader
     #   gcp-releasetool
     #   google-api-core
+    #   googleapis-common-protos
 pyasn1==0.5.0 \
     --hash=sha256:87a2121042a1ac9358cabcaf1d07680ff97ee6404333bacca15f76aa8ad01a57 \
     --hash=sha256:97b7290ca68e62a832558ec3976f15cbf911bf5d7c7039d8b861c2a0ece69fde
@@ -469,9 +470,9 @@ typing-extensions==4.7.1 \
     --hash=sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36 \
     --hash=sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2
     # via -r requirements.in
-urllib3==1.26.16 \
-    --hash=sha256:8d36afa7616d8ab714608411b4a3b13e58f463aee519024578e062e141dce20f \
-    --hash=sha256:8f135f6502756bde6b2a9b28989df5fbe87c9970cecaa69041edcce7f0589b14
+urllib3==1.26.17 \
+    --hash=sha256:24d6a242c28d29af46c3fae832c36db3bbebcc533dd1bb549172cd739c82df21 \
+    --hash=sha256:94a757d178c9be92ef5539b8840d48dc9cf1b2709c9d6b588232a055c524458b
     # via
     #   google-auth
     #   requests
@@ -485,5 +486,6 @@ zipp==3.16.1 \
     # via importlib-metadata
 
 # WARNING: The following packages were not pinned, but pip requires them to be
-# pinned when the requirements file includes hashes. Consider using the --allow-unsafe flag.
+# pinned when the requirements file includes hashes and the requirement is not
+# satisfied by a package already installed. Consider using the --allow-unsafe flag.
 # setuptools
diff --git a/pom.xml b/pom.xml
index ee537da..07e029e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -14,7 +14,7 @@
   <parent>
     <groupId>com.google.cloud</groupId>
     <artifactId>google-cloud-shared-config</artifactId>
-    <version>1.5.7</version>
+    <version>1.5.8</version>
   </parent>
   <developers>
     <developer>
@@ -420,7 +420,6 @@
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-javadoc-plugin</artifactId>
-        <version>3.6.0</version>
         <reportSets>
           <reportSet>
             <id>html</id>
diff --git a/samples/install-without-bom/pom.xml b/samples/install-without-bom/pom.xml
index 015e8b3..1bc1db9 100644
--- a/samples/install-without-bom/pom.xml
+++ b/samples/install-without-bom/pom.xml
@@ -29,7 +29,7 @@
     <dependency>
       <groupId>com.google.cloud</groupId>
       <artifactId>google-cloud-spanner-jdbc</artifactId>
-      <version>2.13.2</version>
+      <version>2.13.4</version>
     </dependency>
     <!-- [END spanner-jdbc_install_without_bom] -->
 
diff --git a/samples/snippets/pom.xml b/samples/snippets/pom.xml
index a00b7a5..3144149 100644
--- a/samples/snippets/pom.xml
+++ b/samples/snippets/pom.xml
@@ -30,7 +30,7 @@
       <dependency>
         <groupId>com.google.cloud</groupId>
         <artifactId>libraries-bom</artifactId>
-        <version>26.23.0</version>
+        <version>26.24.0</version>
         <type>pom</type>
         <scope>import</scope>
       </dependency>
diff --git a/samples/spring-data-jdbc/pom.xml b/samples/spring-data-jdbc/pom.xml
index 20f858d..5ed1d02 100644
--- a/samples/spring-data-jdbc/pom.xml
+++ b/samples/spring-data-jdbc/pom.xml
@@ -30,7 +30,7 @@
       <dependency>
         <groupId>com.google.cloud</groupId>
         <artifactId>libraries-bom</artifactId>
-        <version>26.23.0</version>
+        <version>26.24.0</version>
         <scope>import</scope>
         <type>pom</type>
       </dependency>
diff --git a/samples/spring-data-mybatis/pom.xml b/samples/spring-data-mybatis/pom.xml
index 07563c6..8dbf025 100644
--- a/samples/spring-data-mybatis/pom.xml
+++ b/samples/spring-data-mybatis/pom.xml
@@ -35,7 +35,7 @@
       <dependency>
         <groupId>com.google.cloud</groupId>
         <artifactId>libraries-bom</artifactId>
-        <version>26.23.0</version>
+        <version>26.24.0</version>
         <scope>import</scope>
         <type>pom</type>
       </dependency>
diff --git a/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java b/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java
index 6031afe..9248dac 100644
--- a/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java
+++ b/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java
@@ -47,6 +47,7 @@ import java.util.Iterator;
 import java.util.Map;
 import java.util.function.BiConsumer;
 import java.util.function.Function;
+import javax.annotation.Nonnull;
 
 /** Jdbc Connection class for Google Cloud Spanner */
 class JdbcConnection extends AbstractJdbcConnection {
@@ -394,31 +395,66 @@ class JdbcConnection extends AbstractJdbcConnection {
   @Override
   public void setCatalog(String catalog) throws SQLException {
     // This method could be changed to allow the user to change to another database.
-    // For now we only support setting an empty string in order to support frameworks
+    // For now, we only support setting the default catalog in order to support frameworks
     // and applications that set this when no catalog has been specified in the connection
     // URL.
     checkClosed();
-    JdbcPreconditions.checkArgument("".equals(catalog), "Only catalog \"\" is supported");
+    checkValidCatalog(catalog);
+  }
+
+  void checkValidCatalog(String catalog) throws SQLException {
+    String defaultCatalog = getDefaultCatalog();
+    JdbcPreconditions.checkArgument(
+        defaultCatalog.equals(catalog),
+        String.format("Only catalog %s is supported", defaultCatalog));
   }
 
   @Override
   public String getCatalog() throws SQLException {
     checkClosed();
-    return "";
+    return getDefaultCatalog();
+  }
+
+  @Nonnull
+  String getDefaultCatalog() {
+    switch (getDialect()) {
+      case POSTGRESQL:
+        String database = getConnectionOptions().getDatabaseName();
+        // It should not be possible that database is null, but it's better to be safe than sorry.
+        return database == null ? "" : database;
+      case GOOGLE_STANDARD_SQL:
+      default:
+        return "";
+    }
   }
 
   @Override
   public void setSchema(String schema) throws SQLException {
     checkClosed();
-    // Cloud Spanner does not support schemas, but does contain a pseudo 'empty string' schema that
-    // might be set by frameworks and applications that read the database metadata.
-    JdbcPreconditions.checkArgument("".equals(schema), "Only schema \"\" is supported");
+    checkValidSchema(schema);
+  }
+
+  void checkValidSchema(String schema) throws SQLException {
+    String defaultSchema = getDefaultSchema();
+    JdbcPreconditions.checkArgument(
+        defaultSchema.equals(schema), String.format("Only schema %s is supported", defaultSchema));
   }
 
   @Override
   public String getSchema() throws SQLException {
     checkClosed();
-    return "";
+    return getDefaultSchema();
+  }
+
+  @Nonnull
+  String getDefaultSchema() {
+    switch (getDialect()) {
+      case POSTGRESQL:
+        return "public";
+      case GOOGLE_STANDARD_SQL:
+      default:
+        return "";
+    }
   }
 
   @Override
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 b9c7cb8..4463395 100644
--- a/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java
+++ b/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java
@@ -777,11 +777,12 @@ class JdbcDatabaseMetaData extends AbstractJdbcWrapper implements DatabaseMetaDa
   }
 
   @Override
-  public ResultSet getCatalogs() {
+  public ResultSet getCatalogs() throws SQLException {
     return JdbcResultSet.of(
         ResultSets.forRows(
             Type.struct(StructField.of("TABLE_CAT", Type.string())),
-            Collections.singletonList(Struct.newBuilder().set("TABLE_CAT").to("").build())));
+            Collections.singletonList(
+                Struct.newBuilder().set("TABLE_CAT").to(getConnection().getCatalog()).build())));
   }
 
   @Override
@@ -1524,9 +1525,10 @@ class JdbcDatabaseMetaData extends AbstractJdbcWrapper implements DatabaseMetaDa
   @Override
   public ResultSet getSchemas(String catalog, String schemaPattern) throws SQLException {
     String sql = readSqlFromFile("DatabaseMetaData_GetSchemas.sql", connection.getDialect());
-    JdbcPreparedStatement statement =
-        prepareStatementReplaceNullWithAnyString(sql, catalog, schemaPattern);
-    return statement.executeQueryWithOptions(InternalMetadataQuery.INSTANCE);
+    try (JdbcPreparedStatement statement =
+        prepareStatementReplaceNullWithAnyString(sql, catalog, schemaPattern)) {
+      return statement.executeQueryWithOptions(InternalMetadataQuery.INSTANCE);
+    }
   }
 
   @Override


Test patch:
diff --git a/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java b/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java
index 592d404..ff811f3 100644
--- a/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java
+++ b/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java
@@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.mockito.Mockito.any;
@@ -700,34 +701,33 @@ public class JdbcConnectionTest {
     ConnectionOptions options = mockOptions();
     when(options.getDatabaseName()).thenReturn("test");
     try (JdbcConnection connection = createConnection(options)) {
-      // The connection should always return the empty string as the current catalog, as no other
+      // The connection should always return the default catalog as the current catalog, as no other
       // catalogs exist in the INFORMATION_SCHEMA.
-      assertThat(connection.getCatalog()).isEqualTo("");
+      // The default catalog is the empty string for GoogleSQL databases.
+      // The default catalog is the database name for PostgreSQL databases.
+      assertEquals(connection.getDefaultCatalog(), connection.getCatalog());
       // This should be allowed.
-      connection.setCatalog("");
-      try {
-        // This should cause an exception.
-        connection.setCatalog("other");
-        fail("missing expected exception");
-      } catch (JdbcSqlExceptionImpl e) {
-        assertThat(e.getCode()).isEqualTo(Code.INVALID_ARGUMENT);
-      }
+      connection.setCatalog(connection.getDefaultCatalog());
+      // This should cause an exception.
+      JdbcSqlExceptionImpl exception =
+          assertThrows(JdbcSqlExceptionImpl.class, () -> connection.setCatalog("other"));
+      assertEquals(Code.INVALID_ARGUMENT, exception.getCode());
     }
   }
 
   @Test
   public void testSchema() throws SQLException {
     try (JdbcConnection connection = createConnection(mockOptions())) {
-      assertThat(connection.getSchema()).isEqualTo("");
+      // The connection should always return the default schema as the current schema, as we
+      // currently do not support setting the connection to a different schema.
+      // The default schema is the empty string for GoogleSQL databases.
+      // The default schema is 'public' for PostgreSQL databases.
+      assertEquals(connection.getDefaultSchema(), connection.getSchema());
       // This should be allowed.
-      connection.setSchema("");
-      try {
-        // This should cause an exception.
-        connection.setSchema("other");
-        fail("missing expected exception");
-      } catch (JdbcSqlExceptionImpl e) {
-        assertThat(e.getCode()).isEqualTo(Code.INVALID_ARGUMENT);
-      }
+      connection.setSchema(connection.getDefaultSchema());
+      JdbcSqlExceptionImpl exception =
+          assertThrows(JdbcSqlExceptionImpl.class, () -> connection.setSchema("other"));
+      assertEquals(Code.INVALID_ARGUMENT, exception.getCode());
     }
   }
 
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 6a2b0ca..9782e96 100644
--- a/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java
+++ b/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java
@@ -41,10 +41,19 @@ import java.sql.Types;
 import java.util.Objects;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
 
-@RunWith(JUnit4.class)
+@RunWith(Parameterized.class)
 public class JdbcDatabaseMetaDataTest {
+  @Parameter public Dialect dialect;
+
+  @Parameters(name = "dialect = {0}")
+  public static Object[] data() {
+    return Dialect.values();
+  }
+
   private static final String DEFAULT_CATALOG = "";
   private static final String DEFAULT_SCHEMA = "";
   private static final String TEST_TABLE = "FOO";
@@ -314,10 +323,12 @@ public class JdbcDatabaseMetaDataTest {
   @Test
   public void testGetCatalogs() throws SQLException {
     JdbcConnection connection = mock(JdbcConnection.class);
+    when(connection.getDialect()).thenReturn(dialect);
+    when(connection.getCatalog()).thenCallRealMethod();
     DatabaseMetaData meta = new JdbcDatabaseMetaData(connection);
     try (ResultSet rs = meta.getCatalogs()) {
       assertThat(rs.next(), is(true));
-      assertThat(rs.getString("TABLE_CAT"), is(equalTo("")));
+      assertThat(rs.getString("TABLE_CAT"), is(equalTo(connection.getDefaultCatalog())));
       assertThat(rs.next(), is(false));
       ResultSetMetaData rsmd = rs.getMetaData();
       assertThat(rsmd.getColumnCount(), is(equalTo(1)));
diff --git a/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java b/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java
index 7e2481a..820bdfa 100644
--- a/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java
+++ b/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java
@@ -822,6 +822,7 @@ public class ITJdbcDatabaseMetaDataTest extends ITAbstractJdbcTest {
   @Test
   public void testGetSchemas() throws SQLException {
     try (Connection connection = createConnection(env, database)) {
+      assertEquals("", connection.getSchema());
       try (ResultSet rs = connection.getMetaData().getSchemas()) {
         assertThat(rs.next(), is(true));
         assertThat(rs.getString("TABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA)));
@@ -829,11 +830,22 @@ public class ITJdbcDatabaseMetaDataTest extends ITAbstractJdbcTest {
         assertThat(rs.next(), is(true));
         assertThat(rs.getString("TABLE_SCHEM"), is(equalTo("INFORMATION_SCHEMA")));
         assertThat(rs.getString("TABLE_CATALOG"), is(equalTo(DEFAULT_CATALOG)));
-        if (!EmulatorSpannerHelper.isUsingEmulator()) {
-          assertThat(rs.next(), is(true));
-          assertThat(rs.getString("TABLE_SCHEM"), is(equalTo("SPANNER_SYS")));
-          assertThat(rs.getString("TABLE_CATALOG"), is(equalTo(DEFAULT_CATALOG)));
-        }
+        assertThat(rs.next(), is(true));
+        assertThat(rs.getString("TABLE_SCHEM"), is(equalTo("SPANNER_SYS")));
+        assertThat(rs.getString("TABLE_CATALOG"), is(equalTo(DEFAULT_CATALOG)));
+        assertFalse(rs.next());
+      }
+    }
+  }
+
+  @Test
+  public void testGetCatalogs() throws SQLException {
+    try (Connection connection = createConnection(env, database)) {
+      assertEquals("", connection.getCatalog());
+      try (ResultSet rs = connection.getMetaData().getCatalogs()) {
+        assertTrue(rs.next());
+        assertEquals("", rs.getString("TABLE_CAT"));
+
         assertFalse(rs.next());
       }
     }
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 ff0bff7..56d75db 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
@@ -752,6 +752,7 @@ public class ITJdbcPgDatabaseMetaDataTest extends ITAbstractJdbcTest {
   @Test
   public void testGetSchemas() throws SQLException {
     try (Connection connection = createConnection(env, database)) {
+      assertEquals("public", connection.getSchema());
       try (ResultSet rs = connection.getMetaData().getSchemas()) {
         assertTrue(rs.next());
         assertEquals(getDefaultCatalog(database), rs.getString("TABLE_CATALOG"));
@@ -774,6 +775,19 @@ public class ITJdbcPgDatabaseMetaDataTest extends ITAbstractJdbcTest {
     }
   }
 
+  @Test
+  public void testGetCatalogs() throws SQLException {
+    try (Connection connection = createConnection(env, database)) {
+      assertEquals(database.getId().getDatabase(), connection.getCatalog());
+      try (ResultSet rs = connection.getMetaData().getCatalogs()) {
+        assertTrue(rs.next());
+        assertEquals(database.getId().getDatabase(), rs.getString("TABLE_CAT"));
+
+        assertFalse(rs.next());
+      }
+    }
+  }
+
   private static final class Table {
     private final String name;
     private final String type;