From 1d299254da1858aef34688a80b2ce218ede21f96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Wed, 10 May 2023 13:47:21 +0200 Subject: [PATCH] feat: make JDBC connection URL delimiter configurable Make the JDBC connection URL delimiter configurable. The current delimiter is semicolon ';', which breaks JDBC drivers that use semicolons in the actual connection URL. The default delimiter remains semicolon for all databases, except a list of databases that are known to use semicolons in the connection URL. Users can always specifiy a custom delimiter to work around any issues with the default delimiter. Fixes #1458 --- jdbc/README.md | 12 ++++++++++++ jdbc/src/main/java/site/ycsb/db/JdbcDBClient.java | 14 +++++++++++++- .../test/java/site/ycsb/db/JdbcDBClientTest.java | 5 ++++- 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/jdbc/README.md b/jdbc/README.md index 97b0543030..55db5d02c0 100644 --- a/jdbc/README.md +++ b/jdbc/README.md @@ -91,6 +91,18 @@ db.user=admin db.passwd=admin ``` +You can specify a custom delimiter for multiple connection URLs by setting `db.urldelimiter` if your connection URL might contain a `;`. +The default delimiter is `,` for Google Cloud Spanner, SQLServer, H2, and Apache Phoenix. It is `;` for all +other databases. + +```sh +db.driver=com.google.cloud.spanner.jdbc.JdbcDriver +db.url=jdbc:cloudspanner:/projects/my-project/instances/my-instance/databass/my-database;minSessions=1000;maxSessions=1000;numChannels=20 +db.urldelimiter=, +db.user= +db.passwd= +``` + You can add these to your workload configuration or a separate properties file and specify it with ```-P``` or you can add the properties individually to your ycsb command with ```-p```. ### 5. Add your JDBC Driver to the classpath diff --git a/jdbc/src/main/java/site/ycsb/db/JdbcDBClient.java b/jdbc/src/main/java/site/ycsb/db/JdbcDBClient.java index 4916b9ae5d..b3d8d0c364 100644 --- a/jdbc/src/main/java/site/ycsb/db/JdbcDBClient.java +++ b/jdbc/src/main/java/site/ycsb/db/JdbcDBClient.java @@ -50,6 +50,9 @@ public class JdbcDBClient extends DB { /** The URL to connect to the database. */ public static final String CONNECTION_URL = "db.url"; + /** The delimiter that is used to split multiple JDBC connection URLs. */ + public static final String CONNECTION_URL_DELIMITER = "db.urldelimiter"; + /** The user name to use to connect to the database. */ public static final String CONNECTION_USER = "db.user"; @@ -188,6 +191,15 @@ public void init() throws DBException { String passwd = props.getProperty(CONNECTION_PASSWD, DEFAULT_PROP); String driver = props.getProperty(DRIVER_CLASS); + String defaultDelimiter = ";"; + if (driver != null) { + if (driver.contains("spanner") || driver.contains("sqlserver") + || driver.contains("org.h2.") || driver.contains("phoenix")) { + defaultDelimiter = ","; + } + } + String urlDelimiter = props.getProperty(CONNECTION_URL_DELIMITER, defaultDelimiter); + this.jdbcFetchSize = getIntProperty(props, JDBC_FETCH_SIZE); this.batchSize = getIntProperty(props, DB_BATCH_SIZE); @@ -220,7 +232,7 @@ public void init() throws DBException { // for a longer explanation see the README.md // semicolons aren't present in JDBC urls, so we use them to delimit // multiple JDBC connections to shard across. - final String[] urlArr = urls.split(";"); + final String[] urlArr = urls.split(urlDelimiter); for (String url : urlArr) { System.out.println("Adding shard node URL: " + url); Connection conn = DriverManager.getConnection(url, user, passwd); diff --git a/jdbc/src/test/java/site/ycsb/db/JdbcDBClientTest.java b/jdbc/src/test/java/site/ycsb/db/JdbcDBClientTest.java index a7d1e98e5b..10830ea85a 100644 --- a/jdbc/src/test/java/site/ycsb/db/JdbcDBClientTest.java +++ b/jdbc/src/test/java/site/ycsb/db/JdbcDBClientTest.java @@ -34,7 +34,9 @@ public class JdbcDBClientTest { private static final String TEST_DB_DRIVER = "org.hsqldb.jdbc.JDBCDriver"; - private static final String TEST_DB_URL = "jdbc:hsqldb:mem:ycsb"; + // The 'key=value' part in the connection URL is ignored by hsql. It is added to the URL to + // verify that URLs containing a semicolon work if a custom URL delimiter is set. + private static final String TEST_DB_URL = "jdbc:hsqldb:mem:ycsb;key=value"; private static final String TEST_DB_USER = "sa"; private static final String TABLE_NAME = "USERTABLE"; private static final int FIELD_LENGTH = 32; @@ -63,6 +65,7 @@ public static void setupWithBatch(int batchSize, boolean autoCommit) { p.setProperty(JdbcDBClient.DB_BATCH_SIZE, Integer.toString(batchSize)); p.setProperty(JdbcDBClient.JDBC_BATCH_UPDATES, "true"); p.setProperty(JdbcDBClient.JDBC_AUTO_COMMIT, Boolean.toString(autoCommit)); + p.setProperty(JdbcDBClient.CONNECTION_URL_DELIMITER, ","); jdbcDBClient.setProperties(p); jdbcDBClient.init();