Repository: googleapis/java-spanner-jdbc (java)

Issue:
Allow unknown properties in connection URL / properties
Some applications automatically add additional properties to the Connection URL or Connection properties. Properties that are unknown to the Spanner JDBC driver will cause the driver to throw an error. This prevents the driver to be used with some applications, such as for example the IntelliJ Database Navigator: https://stackoverflow.com/questions/64975569/connecting-to-a-gcloud-spanner-emulator-instance-from-intellijs-database-naviga

The driver should therefore also have a mode where unknown properties do not cause errors but only warnings.

Pull request description:
feat: allow unknown properties in connection url with lenient mode
Adds support for lenient mode in JDBC connections.

DO NOT MERGE: Requires `google-cloud-spanner` version 3.0.6.

Fixes #283 


Patch:
diff --git a/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java b/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java
index 65b944d..d2a2fea 100644
--- a/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java
+++ b/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java
@@ -28,6 +28,7 @@ import java.sql.DriverManager;
 import java.sql.DriverPropertyInfo;
 import java.sql.SQLException;
 import java.sql.SQLFeatureNotSupportedException;
+import java.sql.SQLWarning;
 import java.util.Map.Entry;
 import java.util.Properties;
 import java.util.logging.Logger;
@@ -172,7 +173,11 @@ public class JdbcDriver implements Driver {
           // Connection API
           String connectionUri = appendPropertiesToUrl(url.substring(5), info);
           ConnectionOptions options = ConnectionOptions.newBuilder().setUri(connectionUri).build();
-          return new JdbcConnection(url, options);
+          JdbcConnection connection = new JdbcConnection(url, options);
+          if (options.getWarnings() != null) {
+            connection.pushWarning(new SQLWarning(options.getWarnings()));
+          }
+          return connection;
         }
       } catch (SpannerException e) {
         throw JdbcSqlExceptionFactory.of(e);


Test patch:
diff --git a/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java b/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java
index 9eb1047..014d9bd 100644
--- a/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java
+++ b/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java
@@ -161,4 +161,32 @@ public class JdbcDriverTest {
             });
     assertThat(driverPropertyNames).containsExactlyElementsIn(validConnectionPropertyNames);
   }
+
+  @Test
+  public void testLenient() throws SQLException {
+    // With lenient=true the driver should accept unknown properties and only generate a warning.
+    try (Connection connection =
+        DriverManager.getConnection(
+            String.format(
+                "jdbc:cloudspanner://localhost:%d/projects/p/instances/i/databases/d?usePlainText=true;credentials=%s;lenient=true;foo=bar",
+                server.getPort(), TEST_KEY_PATH))) {
+      assertThat(connection.isClosed()).isFalse();
+      assertThat((Throwable) connection.getWarnings()).isNotNull();
+      assertThat(connection.getWarnings().getMessage()).contains("foo");
+    }
+
+    // Without lenient the driver should throw an exception for unknown properties.
+    try (Connection connection =
+        DriverManager.getConnection(
+            String.format(
+                "jdbc:cloudspanner://localhost:%d/projects/p/instances/i/databases/d?usePlainText=true;credentials=%s;foo=bar",
+                server.getPort(), TEST_KEY_PATH))) {
+      fail("missing expected exception");
+    } catch (SQLException e) {
+      assertThat((Throwable) e).isInstanceOf(JdbcSqlException.class);
+      JdbcSqlException jdbc = (JdbcSqlException) e;
+      assertThat(jdbc.getMessage()).contains("foo");
+      assertThat(jdbc.getCode()).isEqualTo(Code.INVALID_ARGUMENT);
+    }
+  }
 }