You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by ag...@apache.org on 2018/04/05 23:36:30 UTC

[geode] branch develop updated: GEODE-4947: JdbcConnector tests run against external database as AcceptanceTest category (#1747)

This is an automated email from the ASF dual-hosted git repository.

agingade pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/geode.git


The following commit(s) were added to refs/heads/develop by this push:
     new d00dbd7  GEODE-4947: JdbcConnector tests run against external database as AcceptanceTest category (#1747)
d00dbd7 is described below

commit d00dbd735e9d823a0639bcdbbec955d606536391
Author: agingade <ag...@pivotal.io>
AuthorDate: Thu Apr 5 16:36:26 2018 -0700

    GEODE-4947: JdbcConnector tests run against external database as AcceptanceTest category (#1747)
    
    Add test with Postgres and MySQL for JDBC connector
    Add rule for Postgres, MySQL and Derby standing up Docker instance to enable testing
    Update integration tests to use mysql and postgres
    Convert distributed tests to use mysql and postgres
    Fix issue with null character string in Postgres
    Add geode-connectors test to acceptance tests
---
 build.gradle                                       |   1 +
 ci/pipelines/develop.yml                           |   2 +-
 geode-connectors/build.gradle                      |  10 ++
 .../geode/connectors/jdbc/internal/SqlHandler.java |   4 +-
 .../jdbc/internal/SqlStatementFactory.java         |  14 +-
 .../jdbc/JdbcAsyncWriterIntegrationTest.java       |  18 ++-
 ...JdbcDUnitTest.java => JdbcDistributedTest.java} | 168 +++++++++------------
 .../connectors/jdbc/JdbcLoaderIntegrationTest.java |  35 +++--
 .../connectors/jdbc/JdbcWriterIntegrationTest.java |  18 ++-
 .../jdbc/MySqlJdbcAsyncWriterIntegrationTest.java  |  47 ++++++
 .../connectors/jdbc/MySqlJdbcDistributedTest.java  | 100 ++++++++++++
 .../jdbc/MySqlJdbcLoaderIntegrationTest.java       |  58 +++++++
 .../jdbc/MySqlJdbcWriterIntegrationTest.java       |  47 ++++++
 .../PostgresJdbcAsyncWriterIntegrationTest.java    |  47 ++++++
 .../jdbc/PostgresJdbcDistributedTest.java          |  88 +++++++++++
 .../jdbc/PostgresJdbcLoaderIntegrationTest.java    |  57 +++++++
 .../jdbc/PostgresJdbcWriterIntegrationTest.java    |  47 ++++++
 .../MySqlTableMetaDataManagerIntegrationTest.java  |  42 ++++++
 ...ostgresTableMetaDataManagerIntegrationTest.java |  43 ++++++
 .../jdbc/internal/SqlStatementFactoryTest.java     |  17 +--
 .../TableMetaDataManagerIntegrationTest.java       |  28 ++--
 .../jdbc/internal/TestConfigService.java           |  14 +-
 .../test/junit/rules/DatabaseConnectionRule.java   |  26 ++++
 .../junit/rules/InMemoryDerbyConnectionRule.java   |  42 ++++++
 .../test/junit/rules/MySqlConnectionRule.java      |  72 +++++++++
 .../test/junit/rules/PostgresConnectionRule.java   |  45 ++++++
 .../junit/rules/SqlDatabaseConnectionRule.java     | 123 +++++++++++++++
 .../geode/connectors/jdbc/internal/mysql.yml       |  28 ++++
 .../geode/connectors/jdbc/internal/postgres.yml    |  27 ++++
 .../org/apache/geode/connectors/jdbc/mysql.yml     |  28 ++++
 .../org/apache/geode/connectors/jdbc/postgres.yml  |  27 ++++
 31 files changed, 1159 insertions(+), 164 deletions(-)

diff --git a/build.gradle b/build.gradle
index cd76ede..c3f1604 100755
--- a/build.gradle
+++ b/build.gradle
@@ -18,6 +18,7 @@
 buildscript {
   repositories {
     maven { url "https://plugins.gradle.org/m2/" }
+    maven { url "https://dl.bintray.com/palantir/releases" }
     jcenter()
   }
 
diff --git a/ci/pipelines/develop.yml b/ci/pipelines/develop.yml
index a969f1e..564c870 100644
--- a/ci/pipelines/develop.yml
+++ b/ci/pipelines/develop.yml
@@ -246,7 +246,7 @@ jobs:
           CALL_STACK_TIMEOUT: 25200
         run:
           args:
-          - :geode-assembly:acceptanceTest
+          - :geode-assembly:acceptanceTest geode-connectors:acceptanceTest
           - acceptancetestfiles
           path: geode-ci/ci/scripts/test-run.sh
       on_failure:
diff --git a/geode-connectors/build.gradle b/geode-connectors/build.gradle
index c2b55ba..005f498 100644
--- a/geode-connectors/build.gradle
+++ b/geode-connectors/build.gradle
@@ -15,15 +15,25 @@
  * limitations under the License.
  */
 
+repositories {
+    maven {
+        url 'https://dl.bintray.com/palantir/releases' // docker-compose-rule is published on bintray
+    }
+}
+
 dependencies {
     compile project(':geode-core')
     compile project(':geode-common')
     compile group: 'com.zaxxer', name: 'HikariCP', version: project.'HikariCP.version'
 
+
     testCompile project(':geode-junit')
 
     //Connectors test framework.
     testRuntime 'org.apache.derby:derby:' + project.'derby.version'
+    testCompile group: 'mysql', name: 'mysql-connector-java', version: '5.1.46'
+    testCompile group: 'org.postgresql', name: 'postgresql', version: '42.2.2'
+    testCompile 'com.palantir.docker.compose:docker-compose-rule-junit4:0.31.1'
     testCompile 'com.pholser:junit-quickcheck-core:' + project.'junit-quickcheck.version'
     testCompile 'com.pholser:junit-quickcheck-generators:' + project.'junit-quickcheck.version'
     testCompile files(project(':geode-core').sourceSets.test.output)
diff --git a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/SqlHandler.java b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/SqlHandler.java
index 3e49cf2..8fc2c5e 100644
--- a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/SqlHandler.java
+++ b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/SqlHandler.java
@@ -113,7 +113,9 @@ public class SqlHandler {
       index++;
       Object value = columnValue.getValue();
       if (value instanceof Character) {
-        value = ((Character) value).toString();
+        Character character = ((Character) value);
+        // if null character, set to null string instead of a string with the null character
+        value = character == Character.valueOf((char) 0) ? null : character.toString();
       } else if (value instanceof Date) {
         Date jdkDate = (Date) value;
         switch (columnValue.getDataType()) {
diff --git a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/SqlStatementFactory.java b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/SqlStatementFactory.java
index ac787b8..d5367ef 100644
--- a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/SqlStatementFactory.java
+++ b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/SqlStatementFactory.java
@@ -22,18 +22,18 @@ class SqlStatementFactory {
     assert columnList.size() == 1;
     ColumnValue keyCV = columnList.get(0);
     assert keyCV.isKey();
-    return "SELECT * FROM \"" + tableName + "\" WHERE \"" + keyCV.getColumnName() + "\" = ?";
+    return "SELECT * FROM " + tableName + " WHERE " + keyCV.getColumnName() + " = ?";
   }
 
   String createDestroySqlString(String tableName, List<ColumnValue> columnList) {
     assert columnList.size() == 1;
     ColumnValue keyCV = columnList.get(0);
     assert keyCV.isKey();
-    return "DELETE FROM \"" + tableName + "\" WHERE \"" + keyCV.getColumnName() + "\" = ?";
+    return "DELETE FROM " + tableName + " WHERE " + keyCV.getColumnName() + " = ?";
   }
 
   String createUpdateSqlString(String tableName, List<ColumnValue> columnList) {
-    StringBuilder query = new StringBuilder("UPDATE \"" + tableName + "\" SET ");
+    StringBuilder query = new StringBuilder("UPDATE " + tableName + " SET ");
     int idx = 0;
     for (ColumnValue column : columnList) {
       if (!column.isKey()) {
@@ -41,14 +41,14 @@ class SqlStatementFactory {
         if (idx > 1) {
           query.append(", ");
         }
-        query.append('"').append(column.getColumnName()).append('"');
+        query.append(column.getColumnName());
         query.append(" = ?");
       }
     }
     for (ColumnValue column : columnList) {
       if (column.isKey()) {
         query.append(" WHERE ");
-        query.append('"').append(column.getColumnName()).append('"');
+        query.append(column.getColumnName());
         query.append(" = ?");
         // currently only support simple primary key with one column
         break;
@@ -58,13 +58,13 @@ class SqlStatementFactory {
   }
 
   String createInsertSqlString(String tableName, List<ColumnValue> columnList) {
-    StringBuilder columnNames = new StringBuilder("INSERT INTO \"" + tableName + "\" (");
+    StringBuilder columnNames = new StringBuilder("INSERT INTO " + tableName + " (");
     StringBuilder columnValues = new StringBuilder(" VALUES (");
     int columnCount = columnList.size();
     int idx = 0;
     for (ColumnValue column : columnList) {
       idx++;
-      columnNames.append('"').append(column.getColumnName()).append('"');
+      columnNames.append(column.getColumnName());
       columnValues.append('?');
       if (idx != columnCount) {
         columnNames.append(", ");
diff --git a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/JdbcAsyncWriterIntegrationTest.java b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/JdbcAsyncWriterIntegrationTest.java
index c1adcb9..819551b 100644
--- a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/JdbcAsyncWriterIntegrationTest.java
+++ b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/JdbcAsyncWriterIntegrationTest.java
@@ -18,7 +18,6 @@ import static org.apache.geode.cache.RegionShortcut.REPLICATE;
 import static org.assertj.core.api.Assertions.assertThat;
 
 import java.sql.Connection;
-import java.sql.DriverManager;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.Statement;
@@ -41,14 +40,13 @@ import org.apache.geode.connectors.jdbc.internal.TestConfigService;
 import org.apache.geode.connectors.jdbc.internal.TestableConnectionManager;
 import org.apache.geode.internal.cache.InternalCache;
 import org.apache.geode.pdx.PdxInstance;
-import org.apache.geode.test.junit.categories.IntegrationTest;
+import org.apache.geode.test.junit.categories.AcceptanceTest;
 
-@Category(IntegrationTest.class)
-public class JdbcAsyncWriterIntegrationTest {
+@Category(AcceptanceTest.class)
+public abstract class JdbcAsyncWriterIntegrationTest {
 
-  private static final String DB_NAME = "DerbyDB";
+  static final String DB_NAME = "test";
   private static final String REGION_TABLE_NAME = "employees";
-  private static final String CONNECTION_URL = "jdbc:derby:memory:" + DB_NAME + ";create=true";
 
   private InternalCache cache;
   private Region<String, PdxInstance> employees;
@@ -65,7 +63,7 @@ public class JdbcAsyncWriterIntegrationTest {
     cache = (InternalCache) new CacheFactory().set("locators", "").set("mcast-port", "0")
         .setPdxReadSerialized(false).create();
     employees = createRegionWithJDBCAsyncWriter(REGION_TABLE_NAME);
-    connection = DriverManager.getConnection(CONNECTION_URL);
+    connection = getConnection();
     statement = connection.createStatement();
     statement.execute("Create Table " + REGION_TABLE_NAME
         + " (id varchar(10) primary key not null, name varchar(10), age int)");
@@ -95,6 +93,10 @@ public class JdbcAsyncWriterIntegrationTest {
     }
   }
 
+  public abstract Connection getConnection() throws SQLException;
+
+  public abstract String getConnectionUrl();
+
   @Test
   public void validateJDBCAsyncWriterTotalEvents() {
     employees.put("1", pdxEmployee1);
@@ -241,7 +243,7 @@ public class JdbcAsyncWriterIntegrationTest {
   private SqlHandler createSqlHandler()
       throws ConnectionConfigExistsException, RegionMappingExistsException {
     return new SqlHandler(new TestableConnectionManager(), new TableMetaDataManager(),
-        TestConfigService.getTestConfigService());
+        TestConfigService.getTestConfigService(getConnectionUrl()));
   }
 
 }
diff --git a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/JdbcDUnitTest.java b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/JdbcDistributedTest.java
similarity index 85%
rename from geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/JdbcDUnitTest.java
rename to geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/JdbcDistributedTest.java
index e63d480..12fb6fb 100644
--- a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/JdbcDUnitTest.java
+++ b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/JdbcDistributedTest.java
@@ -17,6 +17,7 @@ package org.apache.geode.connectors.jdbc;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
+import java.io.IOException;
 import java.io.Serializable;
 import java.sql.Connection;
 import java.sql.DriverManager;
@@ -24,7 +25,6 @@ import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.Statement;
-import java.sql.Types;
 import java.util.Date;
 import java.util.Properties;
 import java.util.concurrent.TimeUnit;
@@ -48,23 +48,21 @@ import org.apache.geode.test.dunit.rules.ClientVM;
 import org.apache.geode.test.dunit.rules.ClusterStartupRule;
 import org.apache.geode.test.dunit.rules.DistributedRestoreSystemProperties;
 import org.apache.geode.test.dunit.rules.MemberVM;
-import org.apache.geode.test.junit.categories.DistributedTest;
+import org.apache.geode.test.junit.categories.AcceptanceTest;
 import org.apache.geode.test.junit.rules.GfshCommandRule;
 import org.apache.geode.test.junit.rules.serializable.SerializableTestName;
 
 /**
- * End-to-end dunits for jdbc connector
+ * End-to-end dunits for JDBC connector
  */
-@Category(DistributedTest.class)
-public class JdbcDUnitTest implements Serializable {
+@Category(AcceptanceTest.class)
+public abstract class JdbcDistributedTest implements Serializable {
 
-  private static final String DB_NAME = "DerbyDB";
+  static final String DB_NAME = "test";
   private static final String TABLE_NAME = "employees";
   private static final String REGION_NAME = "employees";
-  private static final String CONNECTION_URL = "jdbc:derby:memory:" + DB_NAME + ";create=true";
   private static final String CONNECTION_NAME = "TestConnection";
 
-
   @Rule
   public transient GfshCommandRule gfsh = new GfshCommandRule();
 
@@ -80,109 +78,88 @@ public class JdbcDUnitTest implements Serializable {
 
   private MemberVM server;
   private MemberVM locator;
+  private String connectionUrl;
 
   @Before
   public void setup() throws Exception {
     locator = startupRule.startLocatorVM(0);
     gfsh.connectAndVerify(locator);
+    connectionUrl = getConnectionUrl();
   }
 
+  public abstract Connection getConnection() throws SQLException;
+
+  public abstract String getConnectionUrl() throws IOException, InterruptedException;
+
   private void createTable() throws SQLException {
     server = startupRule.startServerVM(1, x -> x.withConnectionToLocator(locator.getPort()));
-    server.invoke(() -> {
-      Connection connection = DriverManager.getConnection(CONNECTION_URL);
-      Statement statement = connection.createStatement();
-      statement.execute("Create Table " + TABLE_NAME
-          + " (id varchar(10) primary key not null, name varchar(10), age int)");
-    });
+    Connection connection = getConnection();
+    Statement statement = connection.createStatement();
+    statement.execute("Create Table " + TABLE_NAME
+        + " (id varchar(10) primary key not null, name varchar(10), age int)");
   }
 
   private void createTableForAllSupportedFields() throws SQLException {
     server = startupRule.startServerVM(1,
         x -> x.withConnectionToLocator(locator.getPort()).withPDXReadSerialized());
-    server.invoke(() -> {
-      Connection connection = DriverManager.getConnection(CONNECTION_URL);
-      Statement statement = connection.createStatement();
-      statement
-          .execute("Create Table \"" + TABLE_NAME + "\" (\"id\" varchar(10) primary key not null, "
-              + "aboolean smallint, " + "abyte smallint, " + "ashort smallint, " + "anint int, "
-              + "\"along\" bigint, " + "\"aFloat\" float, " + "\"ADOUBLE\" double, "
-              + "astring varchar(10), " + "adate timestamp, " + "anobject varchar(20), "
-              + "abytearray blob(100), " + "achar char(1))");
-    });
+    Connection connection = getConnection();
+    Statement statement = connection.createStatement();
+    createSupportedFieldsTable(statement, TABLE_NAME);
   }
 
-  private void insertNullDataForAllSupportedFieldsTable(String key) {
-    server.invoke(() -> {
-      Connection connection = DriverManager.getConnection(CONNECTION_URL);
-
-      String insertQuery =
-          "Insert into \"" + TABLE_NAME + "\" values (" + "?,?,?,?,?,?,?,?,?,?,?,?,?)";
-      System.out.println("### Query is :" + insertQuery);
-      PreparedStatement statement = connection.prepareStatement(insertQuery);
-      statement.setObject(1, key);
-      statement.setNull(2, Types.SMALLINT);
-      statement.setNull(3, Types.SMALLINT);
-      statement.setNull(4, Types.SMALLINT);
-      statement.setNull(5, Types.INTEGER);
-      statement.setNull(6, Types.BIGINT);
-      statement.setNull(7, Types.FLOAT);
-      statement.setNull(8, Types.DOUBLE);
-      statement.setNull(9, Types.VARCHAR);
-      statement.setNull(10, Types.TIMESTAMP);
-      statement.setNull(11, Types.VARCHAR);
-      statement.setNull(12, Types.BLOB);
-      statement.setNull(13, Types.CHAR);
-
-      statement.execute();
-    });
+  protected abstract void createSupportedFieldsTable(Statement statement, String tableName)
+      throws SQLException;
+
+  private void insertNullDataForAllSupportedFieldsTable(String key) throws SQLException {
+    Connection connection = DriverManager.getConnection(connectionUrl);
+
+    String insertQuery = "Insert into " + TABLE_NAME + " values (" + "?,?,?,?,?,?,?,?,?,?,?,?,?)";
+    System.out.println("### Query is :" + insertQuery);
+    PreparedStatement statement = connection.prepareStatement(insertQuery);
+    createNullStatement(key, statement);
+
+    statement.execute();
   }
 
-  private void insertDataForAllSupportedFieldsTable(String key, ClassWithSupportedPdxFields data) {
-    server.invoke(() -> {
-      Connection connection = DriverManager.getConnection(CONNECTION_URL);
-
-      String insertQuery =
-          "Insert into \"" + TABLE_NAME + "\" values (" + "?,?,?,?,?,?,?,?,?,?,?,?,?)";
-      System.out.println("### Query is :" + insertQuery);
-      PreparedStatement statement = connection.prepareStatement(insertQuery);
-      statement.setObject(1, key);
-      statement.setObject(2, data.isAboolean());
-      statement.setObject(3, data.getAbyte());
-      statement.setObject(4, data.getAshort());
-      statement.setObject(5, data.getAnint());
-      statement.setObject(6, data.getAlong());
-      statement.setObject(7, data.getAfloat());
-      statement.setObject(8, data.getAdouble());
-      statement.setObject(9, data.getAstring());
-      statement.setObject(10, data.getAdate());
-      statement.setObject(11, data.getAnobject());
-      statement.setObject(12, data.getAbytearray());
-      statement.setObject(13, new Character(data.getAchar()).toString());
-
-      statement.execute();
-    });
+  protected abstract void createNullStatement(String key, PreparedStatement statement)
+      throws SQLException;
+
+  private void insertDataForAllSupportedFieldsTable(String key, ClassWithSupportedPdxFields data)
+      throws SQLException {
+    Connection connection = DriverManager.getConnection(connectionUrl);
+
+    String insertQuery = "Insert into " + TABLE_NAME + " values (" + "?,?,?,?,?,?,?,?,?,?,?,?,?)";
+    System.out.println("### Query is :" + insertQuery);
+    PreparedStatement statement = connection.prepareStatement(insertQuery);
+    statement.setObject(1, key);
+    statement.setObject(2, data.isAboolean());
+    statement.setObject(3, data.getAbyte());
+    statement.setObject(4, data.getAshort());
+    statement.setObject(5, data.getAnint());
+    statement.setObject(6, data.getAlong());
+    statement.setObject(7, data.getAfloat());
+    statement.setObject(8, data.getAdouble());
+    statement.setObject(9, data.getAstring());
+    statement.setObject(10, new java.sql.Timestamp(data.getAdate().getTime()));
+    statement.setObject(11, data.getAnobject());
+    statement.setObject(12, data.getAbytearray());
+    statement.setObject(13, new Character(data.getAchar()).toString());
+
+    statement.execute();
   }
 
   @After
   public void tearDown() throws Exception {
-    server.invoke(() -> {
-      closeDB();
-    });
+    closeDB();
   }
 
   private void closeDB() throws SQLException {
-    try (Connection connection = DriverManager.getConnection(CONNECTION_URL)) {
+    try (Connection connection = DriverManager.getConnection(connectionUrl)) {
       try (Statement statement = connection.createStatement()) {
         try {
           statement.execute("Drop table " + TABLE_NAME);
         } catch (SQLException ignore) {
         }
-
-        try {
-          statement.execute("Drop table \"" + TABLE_NAME + "\"");
-        } catch (SQLException ignore) {
-        }
       }
     }
   }
@@ -266,7 +243,7 @@ public class JdbcDUnitTest implements Serializable {
   public void verifyDateToDate() throws Exception {
     server = startupRule.startServerVM(1, x -> x.withConnectionToLocator(locator.getPort()));
     server.invoke(() -> {
-      Connection connection = DriverManager.getConnection(CONNECTION_URL);
+      Connection connection = DriverManager.getConnection(connectionUrl);
       Statement statement = connection.createStatement();
       statement.execute(
           "Create Table " + TABLE_NAME + " (id varchar(10) primary key not null, mydate date)");
@@ -301,7 +278,7 @@ public class JdbcDUnitTest implements Serializable {
   public void verifyDateToTime() throws Exception {
     server = startupRule.startServerVM(1, x -> x.withConnectionToLocator(locator.getPort()));
     server.invoke(() -> {
-      Connection connection = DriverManager.getConnection(CONNECTION_URL);
+      Connection connection = DriverManager.getConnection(connectionUrl);
       Statement statement = connection.createStatement();
       statement.execute(
           "Create Table " + TABLE_NAME + " (id varchar(10) primary key not null, mytime time)");
@@ -335,12 +312,8 @@ public class JdbcDUnitTest implements Serializable {
   @Test
   public void verifyDateToTimestamp() throws Exception {
     server = startupRule.startServerVM(1, x -> x.withConnectionToLocator(locator.getPort()));
-    server.invoke(() -> {
-      Connection connection = DriverManager.getConnection(CONNECTION_URL);
-      Statement statement = connection.createStatement();
-      statement.execute("Create Table " + TABLE_NAME
-          + " (id varchar(10) primary key not null, mytimestamp timestamp)");
-    });
+    createTableWithTimeStamp(server, connectionUrl, TABLE_NAME);
+
     createRegionUsingGfsh(true, false, true);
     createJdbcConnection();
     createMapping(REGION_NAME, CONNECTION_NAME);
@@ -367,6 +340,15 @@ public class JdbcDUnitTest implements Serializable {
     });
   }
 
+  protected void createTableWithTimeStamp(MemberVM vm, String connectionUrl, String tableName) {
+    vm.invoke(() -> {
+      Connection connection = DriverManager.getConnection(connectionUrl);
+      Statement statement = connection.createStatement();
+      statement.execute("Create Table " + tableName
+          + " (id varchar(10) primary key not null, mytimestamp timestamp)");
+    });
+  }
+
   @Test
   public void putWritesToDB() throws Exception {
     createTable();
@@ -507,7 +489,7 @@ public class JdbcDUnitTest implements Serializable {
     client.invoke(() -> {
       String key = "id1";
       ClassWithSupportedPdxFields value = new ClassWithSupportedPdxFields(true, (byte) 1, (short) 2,
-          3, 4, 5.5f, 6.0, "BigEmp", new Date(100000), "BigEmpObject", new byte[] {1, 2}, 'c');
+          3, 4, 5.5f, 6.0, "BigEmp", new Date(0), "BigEmpObject", new byte[] {1, 2}, 'c');
       Region<String, ClassWithSupportedPdxFields> region =
           ClusterStartupRule.getClientCache().getRegion(REGION_NAME);
       region.put(key, value);
@@ -550,7 +532,7 @@ public class JdbcDUnitTest implements Serializable {
     createMapping(REGION_NAME, CONNECTION_NAME, ClassWithSupportedPdxFields.class.getName(), false);
     String key = "id1";
     ClassWithSupportedPdxFields value = new ClassWithSupportedPdxFields(true, (byte) 1, (short) 2,
-        3, 4, 5.5f, 6.0, "BigEmp", new Date(100000), "BigEmpObject", new byte[] {1, 2}, 'c');
+        3, 4, 5.5f, 6.0, "BigEmp", new Date(0), "BigEmpObject", new byte[] {1, 2}, 'c');
 
     server.invoke(() -> {
       insertDataForAllSupportedFieldsTable(key, value);
@@ -613,7 +595,7 @@ public class JdbcDUnitTest implements Serializable {
 
   private void createJdbcConnection() {
     final String commandStr =
-        "create jdbc-connection --name=" + CONNECTION_NAME + " --url=" + CONNECTION_URL;
+        "create jdbc-connection --name=" + CONNECTION_NAME + " --url=" + connectionUrl;
     gfsh.executeAndAssertThat(commandStr).statusIsSuccess();
   }
 
@@ -660,7 +642,7 @@ public class JdbcDUnitTest implements Serializable {
 
   private void assertTableHasEmployeeData(int size, PdxInstance employee, String key)
       throws SQLException {
-    Connection connection = DriverManager.getConnection(CONNECTION_URL);
+    Connection connection = DriverManager.getConnection(connectionUrl);
     Statement statement = connection.createStatement();
     Awaitility.await().atMost(30, TimeUnit.SECONDS).until(() -> {
       assertThat(getRowCount(statement, TABLE_NAME)).isEqualTo(size);
diff --git a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/JdbcLoaderIntegrationTest.java b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/JdbcLoaderIntegrationTest.java
index a4ec5ab..805f8b4 100644
--- a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/JdbcLoaderIntegrationTest.java
+++ b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/JdbcLoaderIntegrationTest.java
@@ -19,8 +19,8 @@ import static org.assertj.core.api.Assertions.assertThat;
 
 import java.io.IOException;
 import java.sql.Connection;
-import java.sql.DriverManager;
 import java.sql.PreparedStatement;
+import java.sql.SQLException;
 import java.sql.Statement;
 import java.util.Date;
 
@@ -45,14 +45,14 @@ import org.apache.geode.internal.util.BlobHelper;
 import org.apache.geode.pdx.PdxInstance;
 import org.apache.geode.pdx.ReflectionBasedAutoSerializer;
 import org.apache.geode.pdx.internal.AutoSerializableManager;
-import org.apache.geode.test.junit.categories.IntegrationTest;
+import org.apache.geode.test.junit.categories.AcceptanceTest;
 
-@Category(IntegrationTest.class)
-public class JdbcLoaderIntegrationTest {
+@Category(AcceptanceTest.class)
+public abstract class JdbcLoaderIntegrationTest {
+
+  static final String DB_NAME = "test";
 
-  private static final String DB_NAME = "DerbyDB";
   private static final String REGION_TABLE_NAME = "employees";
-  private static final String CONNECTION_URL = "jdbc:derby:memory:" + DB_NAME + ";create=true";
 
   private InternalCache cache;
   private Connection connection;
@@ -69,7 +69,7 @@ public class JdbcLoaderIntegrationTest {
         .setPdxSerializer(
             new ReflectionBasedAutoSerializer(ClassWithSupportedPdxFields.class.getName()))
         .create();
-    connection = DriverManager.getConnection(CONNECTION_URL);
+    connection = getConnection();
     statement = connection.createStatement();
   }
 
@@ -79,19 +79,18 @@ public class JdbcLoaderIntegrationTest {
     closeDB();
   }
 
+  public abstract Connection getConnection() throws SQLException;
+
+  public abstract String getConnectionUrl();
+
+  protected abstract void createClassWithSupportedPdxFieldsTable(Statement statement,
+      String tableName) throws SQLException;
+
   private void createEmployeeTable() throws Exception {
     statement.execute("Create Table " + REGION_TABLE_NAME
         + " (id varchar(10) primary key not null, name varchar(10), age int)");
   }
 
-  private void createClassWithSupportedPdxFieldsTable() throws Exception {
-    statement.execute("Create Table " + REGION_TABLE_NAME
-        + " (id varchar(10) primary key not null, " + "aboolean smallint, " + "abyte smallint, "
-        + "ashort smallint, " + "anint int, " + "along bigint, " + "afloat float, "
-        + "adouble float, " + "astring varchar(10), " + "adate timestamp, "
-        + "anobject varchar(20), " + "abytearray blob(100), " + "achar char(1))");
-  }
-
   private void closeDB() throws Exception {
     if (statement == null) {
       statement = connection.createStatement();
@@ -148,7 +147,7 @@ public class JdbcLoaderIntegrationTest {
 
   @Test
   public void verifyGetWithSupportedFieldsWithPdxClassName() throws Exception {
-    createClassWithSupportedPdxFieldsTable();
+    createClassWithSupportedPdxFieldsTable(statement, REGION_TABLE_NAME);
     ClassWithSupportedPdxFields classWithSupportedPdxFields =
         createClassWithSupportedPdxFieldsForInsert();
     insertIntoClassWithSupportedPdxFieldsTable("1", classWithSupportedPdxFields);
@@ -182,7 +181,7 @@ public class JdbcLoaderIntegrationTest {
       throws ConnectionConfigExistsException, RegionMappingExistsException {
     return new SqlHandler(new TestableConnectionManager(), new TableMetaDataManager(),
         TestConfigService.getTestConfigService((InternalCache) cache, pdxClassName,
-            primaryKeyInValue));
+            primaryKeyInValue, getConnectionUrl()));
   }
 
   private <K, V> Region<K, V> createRegionWithJDBCLoader(String regionName, String pdxClassName,
@@ -198,7 +197,7 @@ public class JdbcLoaderIntegrationTest {
   private ClassWithSupportedPdxFields createClassWithSupportedPdxFieldsForInsert() {
     ClassWithSupportedPdxFields classWithSupportedPdxFields =
         new ClassWithSupportedPdxFields(true, (byte) 1, (short) 2, 3, 4, 5.5f, 6.0, "BigEmp",
-            new Date(100000), "BigEmpObject", new byte[] {1, 2}, 'c');
+            new Date(0), "BigEmpObject", new byte[] {1, 2}, 'c');
 
     return classWithSupportedPdxFields;
   }
diff --git a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/JdbcWriterIntegrationTest.java b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/JdbcWriterIntegrationTest.java
index 5e42631..dbdc18a 100644
--- a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/JdbcWriterIntegrationTest.java
+++ b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/JdbcWriterIntegrationTest.java
@@ -19,7 +19,6 @@ import static com.googlecode.catchexception.CatchException.caughtException;
 import static org.assertj.core.api.Assertions.assertThat;
 
 import java.sql.Connection;
-import java.sql.DriverManager;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.Statement;
@@ -43,14 +42,13 @@ import org.apache.geode.connectors.jdbc.internal.TestConfigService;
 import org.apache.geode.connectors.jdbc.internal.TestableConnectionManager;
 import org.apache.geode.internal.cache.InternalCache;
 import org.apache.geode.pdx.PdxInstance;
-import org.apache.geode.test.junit.categories.IntegrationTest;
+import org.apache.geode.test.junit.categories.AcceptanceTest;
 
-@Category(IntegrationTest.class)
-public class JdbcWriterIntegrationTest {
+@Category(AcceptanceTest.class)
+public abstract class JdbcWriterIntegrationTest {
 
-  private static final String DB_NAME = "DerbyDB";
+  static final String DB_NAME = "test";
   private static final String REGION_TABLE_NAME = "employees";
-  private static final String CONNECTION_URL = "jdbc:derby:memory:" + DB_NAME + ";create=true";
 
   private InternalCache cache;
   private Region<String, PdxInstance> employees;
@@ -68,7 +66,7 @@ public class JdbcWriterIntegrationTest {
         .setPdxReadSerialized(false).create();
     employees = createRegionWithJDBCSynchronousWriter(REGION_TABLE_NAME);
 
-    connection = DriverManager.getConnection(CONNECTION_URL);
+    connection = getConnection();
     statement = connection.createStatement();
     statement.execute("Create Table " + REGION_TABLE_NAME
         + " (id varchar(10) primary key not null, name varchar(10), age int)");
@@ -86,6 +84,10 @@ public class JdbcWriterIntegrationTest {
     closeDB();
   }
 
+  public abstract Connection getConnection() throws SQLException;
+
+  public abstract String getConnectionUrl();
+
   private void closeDB() throws Exception {
     if (statement == null) {
       statement = connection.createStatement();
@@ -227,7 +229,7 @@ public class JdbcWriterIntegrationTest {
   private SqlHandler createSqlHandler()
       throws ConnectionConfigExistsException, RegionMappingExistsException {
     return new SqlHandler(new TestableConnectionManager(), new TableMetaDataManager(),
-        TestConfigService.getTestConfigService());
+        TestConfigService.getTestConfigService(getConnectionUrl()));
   }
 
   private void assertRecordMatchesEmployee(ResultSet resultSet, String key, Employee employee)
diff --git a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/MySqlJdbcAsyncWriterIntegrationTest.java b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/MySqlJdbcAsyncWriterIntegrationTest.java
new file mode 100644
index 0000000..1391fb9
--- /dev/null
+++ b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/MySqlJdbcAsyncWriterIntegrationTest.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You 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 org.apache.geode.connectors.jdbc;
+
+import java.net.URL;
+import java.sql.Connection;
+import java.sql.SQLException;
+
+import org.junit.ClassRule;
+import org.junit.experimental.categories.Category;
+
+import org.apache.geode.test.junit.categories.AcceptanceTest;
+import org.apache.geode.test.junit.rules.DatabaseConnectionRule;
+import org.apache.geode.test.junit.rules.MySqlConnectionRule;
+
+@Category(AcceptanceTest.class)
+public class MySqlJdbcAsyncWriterIntegrationTest extends JdbcAsyncWriterIntegrationTest {
+
+  private static final URL COMPOSE_RESOURCE_PATH =
+      MySqlJdbcAsyncWriterIntegrationTest.class.getResource("mysql.yml");
+
+  @ClassRule
+  public static DatabaseConnectionRule dbRule = new MySqlConnectionRule.Builder()
+      .file(COMPOSE_RESOURCE_PATH.getPath()).serviceName("db").port(3306).database(DB_NAME).build();
+
+  @Override
+  public Connection getConnection() throws SQLException {
+    return dbRule.getConnection();
+  }
+
+  @Override
+  public String getConnectionUrl() {
+    return dbRule.getConnectionUrl();
+  }
+}
diff --git a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/MySqlJdbcDistributedTest.java b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/MySqlJdbcDistributedTest.java
new file mode 100644
index 0000000..48de63c
--- /dev/null
+++ b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/MySqlJdbcDistributedTest.java
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You 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 org.apache.geode.connectors.jdbc;
+
+import java.net.URL;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.Types;
+
+import org.junit.ClassRule;
+import org.junit.experimental.categories.Category;
+
+import org.apache.geode.test.dunit.rules.MemberVM;
+import org.apache.geode.test.junit.categories.AcceptanceTest;
+import org.apache.geode.test.junit.rules.MySqlConnectionRule;
+import org.apache.geode.test.junit.rules.SqlDatabaseConnectionRule;
+
+/**
+ * End-to-end dunits for jdbc connector
+ */
+@Category(AcceptanceTest.class)
+public class MySqlJdbcDistributedTest extends JdbcDistributedTest {
+
+  private static final URL COMPOSE_RESOURCE_PATH =
+      MySqlJdbcDistributedTest.class.getResource("mysql.yml");
+
+  @ClassRule
+  public static transient SqlDatabaseConnectionRule dbRule = createConnectionRule();
+
+  private static SqlDatabaseConnectionRule createConnectionRule() {
+    try {
+      return new MySqlConnectionRule.Builder().file(COMPOSE_RESOURCE_PATH.getPath())
+          .serviceName("db").port(3306).database(DB_NAME).build();
+    } catch (IllegalStateException e) {
+      return null;
+    }
+  }
+
+  @Override
+  public Connection getConnection() throws SQLException {
+    return dbRule.getConnection();
+  }
+
+  @Override
+  public String getConnectionUrl() {
+    return dbRule == null ? null : dbRule.getConnectionUrl();
+  }
+
+  @Override
+  protected void createSupportedFieldsTable(Statement statement, String tableName)
+      throws SQLException {
+    statement.execute("CREATE TABLE " + tableName + " (id varchar(10) primary key not null, "
+        + "aboolean smallint, " + "abyte smallint, " + "ashort smallint, " + "anint int, "
+        + "along bigint, " + "aFloat float, " + "ADOUBLE double, " + "astring varchar(10), "
+        + "adate datetime, " + "anobject varchar(20), " + "abytearray blob(100), "
+        + "achar char(1))");
+  }
+
+  @Override
+  protected void createNullStatement(String key, PreparedStatement statement) throws SQLException {
+    statement.setObject(1, key);
+    statement.setNull(2, Types.BOOLEAN);
+    statement.setNull(3, Types.SMALLINT);
+    statement.setNull(4, Types.SMALLINT);
+    statement.setNull(5, Types.INTEGER);
+    statement.setNull(6, Types.BIGINT);
+    statement.setNull(7, Types.FLOAT);
+    statement.setNull(8, Types.DOUBLE);
+    statement.setNull(9, Types.VARCHAR);
+    statement.setNull(10, Types.TIMESTAMP);
+    statement.setNull(11, Types.VARCHAR);
+    statement.setNull(12, Types.BLOB);
+    statement.setNull(13, Types.CHAR);
+  }
+
+  @Override
+  protected void createTableWithTimeStamp(MemberVM vm, String connectionUrl, String tableName) {
+    vm.invoke(() -> {
+      Connection connection = DriverManager.getConnection(connectionUrl);
+      Statement statement = connection.createStatement();
+      statement.execute("CREATE TABLE " + tableName
+          + " (id varchar(10) primary key not null, mytimestamp timestamp(3))");
+    });
+  }
+}
diff --git a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/MySqlJdbcLoaderIntegrationTest.java b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/MySqlJdbcLoaderIntegrationTest.java
new file mode 100644
index 0000000..f74fd0b
--- /dev/null
+++ b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/MySqlJdbcLoaderIntegrationTest.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You 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 org.apache.geode.connectors.jdbc;
+
+import java.net.URL;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import org.junit.ClassRule;
+import org.junit.experimental.categories.Category;
+
+import org.apache.geode.test.junit.categories.AcceptanceTest;
+import org.apache.geode.test.junit.rules.DatabaseConnectionRule;
+import org.apache.geode.test.junit.rules.MySqlConnectionRule;
+
+@Category(AcceptanceTest.class)
+public class MySqlJdbcLoaderIntegrationTest extends JdbcLoaderIntegrationTest {
+
+  private static final URL COMPOSE_RESOURCE_PATH =
+      MySqlJdbcLoaderIntegrationTest.class.getResource("mysql.yml");
+
+  @ClassRule
+  public static DatabaseConnectionRule dbRule = new MySqlConnectionRule.Builder()
+      .file(COMPOSE_RESOURCE_PATH.getPath()).serviceName("db").port(3306).database(DB_NAME).build();
+
+  @Override
+  public Connection getConnection() throws SQLException {
+    return dbRule.getConnection();
+  }
+
+  @Override
+  public String getConnectionUrl() {
+    return dbRule.getConnectionUrl();
+  }
+
+  @Override
+  protected void createClassWithSupportedPdxFieldsTable(Statement statement, String tableName)
+      throws SQLException {
+    statement.execute("CREATE TABLE " + tableName + " (id varchar(10) primary key not null, "
+        + "aboolean smallint, " + "abyte smallint, " + "ashort smallint, " + "anint int, "
+        + "along bigint, " + "afloat float, " + "adouble float, " + "astring varchar(10), "
+        + "adate datetime, " + "anobject varchar(20), " + "abytearray blob(100), "
+        + "achar char(1))");
+  }
+}
diff --git a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/MySqlJdbcWriterIntegrationTest.java b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/MySqlJdbcWriterIntegrationTest.java
new file mode 100644
index 0000000..329b8c1
--- /dev/null
+++ b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/MySqlJdbcWriterIntegrationTest.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You 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 org.apache.geode.connectors.jdbc;
+
+import java.net.URL;
+import java.sql.Connection;
+import java.sql.SQLException;
+
+import org.junit.ClassRule;
+import org.junit.experimental.categories.Category;
+
+import org.apache.geode.test.junit.categories.AcceptanceTest;
+import org.apache.geode.test.junit.rules.DatabaseConnectionRule;
+import org.apache.geode.test.junit.rules.MySqlConnectionRule;
+
+@Category(AcceptanceTest.class)
+public class MySqlJdbcWriterIntegrationTest extends JdbcWriterIntegrationTest {
+
+  private static final URL COMPOSE_RESOURCE_PATH =
+      MySqlJdbcWriterIntegrationTest.class.getResource("mysql.yml");
+
+  @ClassRule
+  public static DatabaseConnectionRule dbRule = new MySqlConnectionRule.Builder()
+      .file(COMPOSE_RESOURCE_PATH.getPath()).serviceName("db").port(3306).database(DB_NAME).build();
+
+  @Override
+  public Connection getConnection() throws SQLException {
+    return dbRule.getConnection();
+  }
+
+  @Override
+  public String getConnectionUrl() {
+    return dbRule.getConnectionUrl();
+  }
+}
diff --git a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/PostgresJdbcAsyncWriterIntegrationTest.java b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/PostgresJdbcAsyncWriterIntegrationTest.java
new file mode 100644
index 0000000..dcaaaf0
--- /dev/null
+++ b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/PostgresJdbcAsyncWriterIntegrationTest.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You 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 org.apache.geode.connectors.jdbc;
+
+import java.net.URL;
+import java.sql.Connection;
+import java.sql.SQLException;
+
+import org.junit.ClassRule;
+import org.junit.experimental.categories.Category;
+
+import org.apache.geode.test.junit.categories.AcceptanceTest;
+import org.apache.geode.test.junit.rules.DatabaseConnectionRule;
+import org.apache.geode.test.junit.rules.PostgresConnectionRule;
+
+@Category(AcceptanceTest.class)
+public class PostgresJdbcAsyncWriterIntegrationTest extends JdbcAsyncWriterIntegrationTest {
+
+  private static final URL COMPOSE_RESOURCE_PATH =
+      PostgresJdbcAsyncWriterIntegrationTest.class.getResource("postgres.yml");
+
+  @ClassRule
+  public static DatabaseConnectionRule dbRule = new PostgresConnectionRule.Builder()
+      .file(COMPOSE_RESOURCE_PATH.getPath()).serviceName("db").port(5432).database(DB_NAME).build();
+
+  @Override
+  public Connection getConnection() throws SQLException {
+    return dbRule.getConnection();
+  }
+
+  @Override
+  public String getConnectionUrl() {
+    return dbRule.getConnectionUrl();
+  }
+}
diff --git a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/PostgresJdbcDistributedTest.java b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/PostgresJdbcDistributedTest.java
new file mode 100644
index 0000000..224fd9e
--- /dev/null
+++ b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/PostgresJdbcDistributedTest.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You 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 org.apache.geode.connectors.jdbc;
+
+import java.net.URL;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.Types;
+
+import org.junit.ClassRule;
+import org.junit.experimental.categories.Category;
+
+import org.apache.geode.test.junit.categories.AcceptanceTest;
+import org.apache.geode.test.junit.rules.PostgresConnectionRule;
+import org.apache.geode.test.junit.rules.SqlDatabaseConnectionRule;
+
+/**
+ * End-to-end dunits for jdbc connector
+ */
+@Category(AcceptanceTest.class)
+public class PostgresJdbcDistributedTest extends JdbcDistributedTest {
+
+  private static final URL COMPOSE_RESOURCE_PATH =
+      PostgresJdbcDistributedTest.class.getResource("postgres.yml");
+
+  @ClassRule
+  public static transient SqlDatabaseConnectionRule dbRule = createConnectionRule();
+
+  private static SqlDatabaseConnectionRule createConnectionRule() {
+    try {
+      return new PostgresConnectionRule.Builder().file(COMPOSE_RESOURCE_PATH.getPath())
+          .serviceName("db").port(5432).database(DB_NAME).build();
+    } catch (IllegalStateException e) {
+      return null;
+    }
+  }
+
+  @Override
+  public Connection getConnection() throws SQLException {
+    return dbRule.getConnection();
+  }
+
+  @Override
+  public String getConnectionUrl() {
+    return dbRule == null ? null : dbRule.getConnectionUrl();
+  }
+
+  @Override
+  protected void createSupportedFieldsTable(Statement statement, String tableName)
+      throws SQLException {
+    statement.execute("CREATE TABLE " + tableName + " (id varchar(10) primary key not null, "
+        + "aboolean boolean, " + "abyte smallint, " + "ashort smallint, " + "anint int, "
+        + "along bigint, " + "aFloat float, " + "ADOUBLE double precision, "
+        + "astring varchar(10), " + "adate timestamp, " + "anobject varchar(20), "
+        + "abytearray bytea, " + "achar char(1))");
+  }
+
+  @Override
+  protected void createNullStatement(String key, PreparedStatement statement) throws SQLException {
+    statement.setObject(1, key);
+    statement.setNull(2, Types.BOOLEAN);
+    statement.setNull(3, Types.SMALLINT);
+    statement.setNull(4, Types.SMALLINT);
+    statement.setNull(5, Types.INTEGER);
+    statement.setNull(6, Types.BIGINT);
+    statement.setNull(7, Types.FLOAT);
+    statement.setNull(8, Types.DOUBLE);
+    statement.setNull(9, Types.VARCHAR);
+    statement.setNull(10, Types.TIMESTAMP);
+    statement.setNull(11, Types.VARCHAR);
+    statement.setNull(12, Types.ARRAY);
+    statement.setNull(13, Types.CHAR);
+  }
+}
diff --git a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/PostgresJdbcLoaderIntegrationTest.java b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/PostgresJdbcLoaderIntegrationTest.java
new file mode 100644
index 0000000..f90a37c
--- /dev/null
+++ b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/PostgresJdbcLoaderIntegrationTest.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You 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 org.apache.geode.connectors.jdbc;
+
+import java.net.URL;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import org.junit.ClassRule;
+import org.junit.experimental.categories.Category;
+
+import org.apache.geode.test.junit.categories.AcceptanceTest;
+import org.apache.geode.test.junit.rules.DatabaseConnectionRule;
+import org.apache.geode.test.junit.rules.PostgresConnectionRule;
+
+@Category(AcceptanceTest.class)
+public class PostgresJdbcLoaderIntegrationTest extends JdbcLoaderIntegrationTest {
+
+  private static final URL COMPOSE_RESOURCE_PATH =
+      PostgresJdbcLoaderIntegrationTest.class.getResource("postgres.yml");
+
+  @ClassRule
+  public static DatabaseConnectionRule dbRule = new PostgresConnectionRule.Builder()
+      .file(COMPOSE_RESOURCE_PATH.getPath()).serviceName("db").port(5432).database(DB_NAME).build();
+
+  @Override
+  public Connection getConnection() throws SQLException {
+    return dbRule.getConnection();
+  }
+
+  @Override
+  public String getConnectionUrl() {
+    return dbRule.getConnectionUrl();
+  }
+
+  @Override
+  protected void createClassWithSupportedPdxFieldsTable(Statement statement, String tableName)
+      throws SQLException {
+    statement.execute("CREATE TABLE " + tableName + " (id varchar(10) primary key not null, "
+        + "aboolean boolean, " + "abyte smallint, " + "ashort smallint, " + "anint int, "
+        + "along bigint, " + "afloat float, " + "adouble float, " + "astring varchar(10), "
+        + "adate timestamp, " + "anobject varchar(20), " + "abytearray bytea, " + "achar char(1))");
+  }
+}
diff --git a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/PostgresJdbcWriterIntegrationTest.java b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/PostgresJdbcWriterIntegrationTest.java
new file mode 100644
index 0000000..7b324c3
--- /dev/null
+++ b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/PostgresJdbcWriterIntegrationTest.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You 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 org.apache.geode.connectors.jdbc;
+
+import java.net.URL;
+import java.sql.Connection;
+import java.sql.SQLException;
+
+import org.junit.ClassRule;
+import org.junit.experimental.categories.Category;
+
+import org.apache.geode.test.junit.categories.AcceptanceTest;
+import org.apache.geode.test.junit.rules.DatabaseConnectionRule;
+import org.apache.geode.test.junit.rules.PostgresConnectionRule;
+
+@Category(AcceptanceTest.class)
+public class PostgresJdbcWriterIntegrationTest extends JdbcWriterIntegrationTest {
+
+  private static final URL COMPOSE_RESOURCE_PATH =
+      PostgresJdbcWriterIntegrationTest.class.getResource("postgres.yml");
+
+  @ClassRule
+  public static DatabaseConnectionRule dbRule = new PostgresConnectionRule.Builder()
+      .file(COMPOSE_RESOURCE_PATH.getPath()).serviceName("db").port(5432).database(DB_NAME).build();
+
+  @Override
+  public Connection getConnection() throws SQLException {
+    return dbRule.getConnection();
+  }
+
+  @Override
+  public String getConnectionUrl() {
+    return dbRule.getConnectionUrl();
+  }
+}
diff --git a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/MySqlTableMetaDataManagerIntegrationTest.java b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/MySqlTableMetaDataManagerIntegrationTest.java
new file mode 100644
index 0000000..e75472f
--- /dev/null
+++ b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/MySqlTableMetaDataManagerIntegrationTest.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You 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 org.apache.geode.connectors.jdbc.internal;
+
+import java.net.URL;
+import java.sql.Connection;
+import java.sql.SQLException;
+
+import org.junit.ClassRule;
+import org.junit.experimental.categories.Category;
+
+import org.apache.geode.test.junit.categories.AcceptanceTest;
+import org.apache.geode.test.junit.rules.DatabaseConnectionRule;
+import org.apache.geode.test.junit.rules.MySqlConnectionRule;
+
+@Category(AcceptanceTest.class)
+public class MySqlTableMetaDataManagerIntegrationTest extends TableMetaDataManagerIntegrationTest {
+
+  private static final URL COMPOSE_RESOURCE_PATH =
+      MySqlTableMetaDataManagerIntegrationTest.class.getResource("mysql.yml");
+
+  @ClassRule
+  public static DatabaseConnectionRule dbRule = new MySqlConnectionRule.Builder()
+      .file(COMPOSE_RESOURCE_PATH.getPath()).serviceName("db").port(3306).database(DB_NAME).build();
+
+  @Override
+  public Connection getConnection() throws SQLException {
+    return dbRule.getConnection();
+  }
+}
diff --git a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/PostgresTableMetaDataManagerIntegrationTest.java b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/PostgresTableMetaDataManagerIntegrationTest.java
new file mode 100644
index 0000000..0697abd
--- /dev/null
+++ b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/PostgresTableMetaDataManagerIntegrationTest.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You 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 org.apache.geode.connectors.jdbc.internal;
+
+import java.net.URL;
+import java.sql.Connection;
+import java.sql.SQLException;
+
+import org.junit.ClassRule;
+import org.junit.experimental.categories.Category;
+
+import org.apache.geode.test.junit.categories.AcceptanceTest;
+import org.apache.geode.test.junit.rules.DatabaseConnectionRule;
+import org.apache.geode.test.junit.rules.PostgresConnectionRule;
+
+@Category(AcceptanceTest.class)
+public class PostgresTableMetaDataManagerIntegrationTest
+    extends TableMetaDataManagerIntegrationTest {
+
+  private static final URL COMPOSE_RESOURCE_PATH =
+      PostgresTableMetaDataManagerIntegrationTest.class.getResource("postgres.yml");
+
+  @ClassRule
+  public static DatabaseConnectionRule dbRule = new PostgresConnectionRule.Builder()
+      .file(COMPOSE_RESOURCE_PATH.getPath()).serviceName("db").port(5432).database(DB_NAME).build();
+
+  @Override
+  public Connection getConnection() throws SQLException {
+    return dbRule.getConnection();
+  }
+}
diff --git a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/SqlStatementFactoryTest.java b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/SqlStatementFactoryTest.java
index 3bc3ae9..b8bdbc2 100644
--- a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/SqlStatementFactoryTest.java
+++ b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/SqlStatementFactoryTest.java
@@ -44,7 +44,7 @@ public class SqlStatementFactoryTest {
   @Test
   public void getSelectQueryString() throws Exception {
     String expectedStatement =
-        String.format("SELECT * FROM \"%s\" WHERE \"%s\" = ?", TABLE_NAME, KEY_COLUMN_NAME);
+        String.format("SELECT * FROM %s WHERE %s = ?", TABLE_NAME, KEY_COLUMN_NAME);
     List<ColumnValue> keyColumn = new ArrayList<>();
     keyColumn.add(new ColumnValue(true, KEY_COLUMN_NAME, null, 0));
 
@@ -56,7 +56,7 @@ public class SqlStatementFactoryTest {
   @Test
   public void getDestroySqlString() throws Exception {
     String expectedStatement =
-        String.format("DELETE FROM \"%s\" WHERE \"%s\" = ?", TABLE_NAME, KEY_COLUMN_NAME);
+        String.format("DELETE FROM %s WHERE %s = ?", TABLE_NAME, KEY_COLUMN_NAME);
     List<ColumnValue> keyColumn = new ArrayList<>();
     keyColumn.add(new ColumnValue(true, KEY_COLUMN_NAME, null, 0));
 
@@ -67,9 +67,9 @@ public class SqlStatementFactoryTest {
 
   @Test
   public void getUpdateSqlString() throws Exception {
-    String expectedStatement = String.format(
-        "UPDATE \"%s\" SET \"%s\" = ?, \"%s\" = ? WHERE \"%s\" = ?", TABLE_NAME,
-        columnValues.get(0).getColumnName(), columnValues.get(2).getColumnName(), KEY_COLUMN_NAME);
+    String expectedStatement = String.format("UPDATE %s SET %s = ?, %s = ? WHERE %s = ?",
+        TABLE_NAME, columnValues.get(0).getColumnName(), columnValues.get(2).getColumnName(),
+        KEY_COLUMN_NAME);
 
     String statement = factory.createUpdateSqlString(TABLE_NAME, columnValues);
 
@@ -78,10 +78,9 @@ public class SqlStatementFactoryTest {
 
   @Test
   public void getInsertSqlString() throws Exception {
-    String expectedStatement =
-        String.format("INSERT INTO \"%s\" (\"%s\", \"%s\", \"%s\") VALUES (?,?,?)", TABLE_NAME,
-            columnValues.get(0).getColumnName(), columnValues.get(1).getColumnName(),
-            columnValues.get(2).getColumnName());
+    String expectedStatement = String.format("INSERT INTO %s (%s, %s, %s) VALUES (?,?,?)",
+        TABLE_NAME, columnValues.get(0).getColumnName(), columnValues.get(1).getColumnName(),
+        columnValues.get(2).getColumnName());
 
     String statement = factory.createInsertSqlString(TABLE_NAME, columnValues);
 
diff --git a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/TableMetaDataManagerIntegrationTest.java b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/TableMetaDataManagerIntegrationTest.java
index cf91661..15c9e93 100644
--- a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/TableMetaDataManagerIntegrationTest.java
+++ b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/TableMetaDataManagerIntegrationTest.java
@@ -19,7 +19,7 @@ package org.apache.geode.connectors.jdbc.internal;
 import static org.assertj.core.api.Assertions.assertThat;
 
 import java.sql.Connection;
-import java.sql.DriverManager;
+import java.sql.SQLException;
 import java.sql.Statement;
 import java.sql.Types;
 
@@ -28,25 +28,23 @@ import org.junit.Before;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
 
-import org.apache.geode.test.junit.categories.IntegrationTest;
+import org.apache.geode.test.junit.categories.AcceptanceTest;
 
-@Category(IntegrationTest.class)
-public class TableMetaDataManagerIntegrationTest {
+@Category(AcceptanceTest.class)
+public abstract class TableMetaDataManagerIntegrationTest {
 
-  private static final String DB_NAME = "DerbyDB";
   private static final String REGION_TABLE_NAME = "employees";
-  private static final String CONNECTION_URL = "jdbc:derby:memory:" + DB_NAME + ";create=true";
+  protected static final String DB_NAME = "test";
 
   private TableMetaDataManager manager;
-  private Connection connection;
-  private Statement statement;
+  protected Connection connection;
+  protected Statement statement;
 
   @Before
   public void setup() throws Exception {
-    connection = DriverManager.getConnection(CONNECTION_URL);
+    connection = getConnection();
     statement = connection.createStatement();
-    statement.execute("Create Table " + REGION_TABLE_NAME
-        + " (\"id\" varchar(10) primary key not null, \"name\" varchar(10), \"age\" int)");
+    createTable();
     manager = new TableMetaDataManager();
   }
 
@@ -67,6 +65,14 @@ public class TableMetaDataManagerIntegrationTest {
     }
   }
 
+  protected abstract Connection getConnection() throws SQLException;
+
+  protected void createTable() throws SQLException {
+    statement.execute("CREATE TABLE " + REGION_TABLE_NAME
+        + " (id VARCHAR(10) primary key not null, name VARCHAR(10), age int)");
+
+  }
+
   @Test
   public void validateKeyColumnName() {
     TableMetaDataView metaData = manager.getTableMetaDataView(connection, REGION_TABLE_NAME);
diff --git a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/TestConfigService.java b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/TestConfigService.java
index 93c3f27..4e2aacf 100644
--- a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/TestConfigService.java
+++ b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/TestConfigService.java
@@ -26,24 +26,22 @@ import org.apache.geode.internal.cache.extension.ExtensionPoint;
  * Generates fake JdbcConnectorService with Connections and RegionMappings for tests.
  */
 public class TestConfigService {
-  private static final String DB_NAME = "DerbyDB";
   private static final String REGION_TABLE_NAME = "employees";
   private static final String REGION_NAME = "employees";
-  private static final String CONNECTION_URL = "jdbc:derby:memory:" + DB_NAME + ";create=true";
   private static final String CONNECTION_CONFIG_NAME = "testConnectionConfig";
 
-  public static JdbcConnectorServiceImpl getTestConfigService()
+  public static JdbcConnectorServiceImpl getTestConfigService(String connectionUrl)
       throws ConnectionConfigExistsException, RegionMappingExistsException {
-    return getTestConfigService(createMockCache(), null, false);
+    return getTestConfigService(createMockCache(), null, false, connectionUrl);
   }
 
   public static JdbcConnectorServiceImpl getTestConfigService(InternalCache cache,
-      String pdxClassName, boolean primaryKeyInValue)
+      String pdxClassName, boolean primaryKeyInValue, String connectionUrl)
       throws ConnectionConfigExistsException, RegionMappingExistsException {
 
     JdbcConnectorServiceImpl service = new JdbcConnectorServiceImpl();
     service.init(cache);
-    service.createConnectionConfig(createConnectionConfig());
+    service.createConnectionConfig(createConnectionConfig(connectionUrl));
     service.createRegionMapping(createRegionMapping(pdxClassName, primaryKeyInValue));
     return service;
   }
@@ -59,7 +57,7 @@ public class TestConfigService {
         primaryKeyInValue, Collections.emptyMap());
   }
 
-  private static ConnectionConfiguration createConnectionConfig() {
-    return new ConnectionConfiguration(CONNECTION_CONFIG_NAME, CONNECTION_URL, null, null, null);
+  private static ConnectionConfiguration createConnectionConfig(String connectionUrl) {
+    return new ConnectionConfiguration(CONNECTION_CONFIG_NAME, connectionUrl, null, null, null);
   }
 }
diff --git a/geode-connectors/src/test/java/org/apache/geode/test/junit/rules/DatabaseConnectionRule.java b/geode-connectors/src/test/java/org/apache/geode/test/junit/rules/DatabaseConnectionRule.java
new file mode 100644
index 0000000..a2d7d56
--- /dev/null
+++ b/geode-connectors/src/test/java/org/apache/geode/test/junit/rules/DatabaseConnectionRule.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You 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 org.apache.geode.test.junit.rules;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+
+import org.junit.rules.TestRule;
+
+public interface DatabaseConnectionRule extends TestRule {
+  Connection getConnection() throws SQLException;
+
+  String getConnectionUrl();
+}
diff --git a/geode-connectors/src/test/java/org/apache/geode/test/junit/rules/InMemoryDerbyConnectionRule.java b/geode-connectors/src/test/java/org/apache/geode/test/junit/rules/InMemoryDerbyConnectionRule.java
new file mode 100644
index 0000000..86b55e0
--- /dev/null
+++ b/geode-connectors/src/test/java/org/apache/geode/test/junit/rules/InMemoryDerbyConnectionRule.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You 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 org.apache.geode.test.junit.rules;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+
+import org.junit.rules.ExternalResource;
+
+public class InMemoryDerbyConnectionRule extends ExternalResource
+    implements DatabaseConnectionRule {
+  private static final String CONNECTION_URL = "jdbc:derby:memory:%s;create=true";
+
+  private final String dbName;
+
+  public InMemoryDerbyConnectionRule(String dbName) {
+    this.dbName = dbName;
+  }
+
+  @Override
+  public Connection getConnection() throws SQLException {
+    return DriverManager.getConnection(getConnectionUrl());
+  }
+
+  @Override
+  public String getConnectionUrl() {
+    return String.format(CONNECTION_URL, dbName);
+  }
+}
diff --git a/geode-connectors/src/test/java/org/apache/geode/test/junit/rules/MySqlConnectionRule.java b/geode-connectors/src/test/java/org/apache/geode/test/junit/rules/MySqlConnectionRule.java
new file mode 100644
index 0000000..ca10229
--- /dev/null
+++ b/geode-connectors/src/test/java/org/apache/geode/test/junit/rules/MySqlConnectionRule.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You 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 org.apache.geode.test.junit.rules;
+
+import static org.awaitility.Awaitility.matches;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.util.concurrent.TimeUnit;
+
+import com.palantir.docker.compose.DockerComposeRule;
+import org.awaitility.Awaitility;
+
+public class MySqlConnectionRule extends SqlDatabaseConnectionRule {
+  private static final String CREATE_DB_CONNECTION_STRING =
+      "jdbc:mysql://$HOST:$EXTERNAL_PORT?user=root&useSSL=false";
+
+  private static final String CONNECTION_STRING =
+      "jdbc:mysql://$HOST:$EXTERNAL_PORT/%s?user=root&useSSL=false";
+
+  protected MySqlConnectionRule(DockerComposeRule dockerRule, String serviceName, int port,
+      String dbName) {
+    super(dockerRule, serviceName, port, dbName);
+  }
+
+  @Override
+  public Connection getConnection() throws SQLException {
+    Awaitility.await().ignoreExceptions().atMost(10, TimeUnit.SECONDS)
+        .until(matches(() -> DriverManager.getConnection(getCreateDbConnectionUrl())));
+    String dbName = getDbName();
+    if (dbName != null) {
+      Connection connection = DriverManager.getConnection(getCreateDbConnectionUrl());
+      connection.createStatement().execute("CREATE DATABASE IF NOT EXISTS " + dbName);
+    }
+    return DriverManager.getConnection(getConnectionUrl());
+  }
+
+  @Override
+  public String getConnectionUrl() {
+    return getDockerPort().inFormat(String.format(CONNECTION_STRING, getDbName()));
+  }
+
+
+  public String getCreateDbConnectionUrl() {
+    return getDockerPort().inFormat(CREATE_DB_CONNECTION_STRING);
+  }
+
+  public static class Builder extends SqlDatabaseConnectionRule.Builder {
+
+    public Builder() {
+      super();
+    }
+
+    @Override
+    public MySqlConnectionRule build() {
+      return new MySqlConnectionRule(createDockerRule(), getServiceName(), getPort(), getDbName());
+    }
+  }
+}
diff --git a/geode-connectors/src/test/java/org/apache/geode/test/junit/rules/PostgresConnectionRule.java b/geode-connectors/src/test/java/org/apache/geode/test/junit/rules/PostgresConnectionRule.java
new file mode 100644
index 0000000..2f11c4b
--- /dev/null
+++ b/geode-connectors/src/test/java/org/apache/geode/test/junit/rules/PostgresConnectionRule.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You 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 org.apache.geode.test.junit.rules;
+
+import com.palantir.docker.compose.DockerComposeRule;
+
+public class PostgresConnectionRule extends SqlDatabaseConnectionRule {
+  private static final String CONNECTION_STRING =
+      "jdbc:postgresql://$HOST:$EXTERNAL_PORT/%s?user=postgres";
+
+  protected PostgresConnectionRule(DockerComposeRule dockerRule, String serviceName, int port,
+      String dbName) {
+    super(dockerRule, serviceName, port, dbName);
+  }
+
+  @Override
+  public String getConnectionUrl() {
+    return getDockerPort().inFormat(String.format(CONNECTION_STRING, getDbName()));
+  }
+
+  public static class Builder extends SqlDatabaseConnectionRule.Builder {
+
+    public Builder() {
+      super();
+    }
+
+    @Override
+    public PostgresConnectionRule build() {
+      return new PostgresConnectionRule(createDockerRule(), getServiceName(), getPort(),
+          getDbName());
+    }
+  }
+}
diff --git a/geode-connectors/src/test/java/org/apache/geode/test/junit/rules/SqlDatabaseConnectionRule.java b/geode-connectors/src/test/java/org/apache/geode/test/junit/rules/SqlDatabaseConnectionRule.java
new file mode 100644
index 0000000..628dfb3
--- /dev/null
+++ b/geode-connectors/src/test/java/org/apache/geode/test/junit/rules/SqlDatabaseConnectionRule.java
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You 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 org.apache.geode.test.junit.rules;
+
+import static org.awaitility.Awaitility.matches;
+
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.util.concurrent.TimeUnit;
+
+import com.palantir.docker.compose.DockerComposeRule;
+import com.palantir.docker.compose.connection.DockerPort;
+import com.palantir.docker.compose.connection.waiting.HealthChecks;
+import org.awaitility.Awaitility;
+import org.junit.rules.ExternalResource;
+
+public abstract class SqlDatabaseConnectionRule extends ExternalResource
+    implements DatabaseConnectionRule {
+
+  private final DockerComposeRule dockerRule;
+  private final String serviceName;
+  private final int port;
+  private final String dbName;
+
+  protected SqlDatabaseConnectionRule(DockerComposeRule dockerRule, String serviceName, int port,
+      String dbName) {
+    this.dockerRule = dockerRule;
+    this.serviceName = serviceName;
+    this.port = port;
+    this.dbName = dbName;
+  }
+
+  @Override
+  public void before() throws IOException, InterruptedException {
+    dockerRule.before();
+  }
+
+  @Override
+  public void after() {
+    dockerRule.after();
+  }
+
+  protected DockerPort getDockerPort() {
+    return dockerRule.containers().container(serviceName).port(port);
+  }
+
+  protected String getDbName() {
+    return dbName;
+  }
+
+  @Override
+  public Connection getConnection() throws SQLException {
+    String connectionUrl = getConnectionUrl();
+    Awaitility.await().ignoreExceptions().atMost(10, TimeUnit.SECONDS)
+        .until(matches(() -> DriverManager.getConnection(connectionUrl)));
+    Connection connection = DriverManager.getConnection(connectionUrl);
+    return connection;
+  }
+
+  public abstract String getConnectionUrl();
+
+  public abstract static class Builder {
+    private String filePath;
+    private String serviceName;
+    private int port;
+    private String dbName;
+
+    public abstract SqlDatabaseConnectionRule build();
+
+    public Builder file(String filePath) {
+      this.filePath = filePath;
+      return this;
+    }
+
+    public Builder serviceName(String serviceName) {
+      this.serviceName = serviceName;
+      return this;
+    }
+
+    public Builder port(int port) {
+      this.port = port;
+      return this;
+    }
+
+    public Builder database(String dbName) {
+      this.dbName = dbName;
+      return this;
+    }
+
+    protected String getDbName() {
+      return dbName;
+    }
+
+    protected String getServiceName() {
+      return serviceName;
+    }
+
+    protected int getPort() {
+      return port;
+    }
+
+    protected DockerComposeRule createDockerRule() {
+      return DockerComposeRule.builder().file(filePath)
+          .waitingForService(serviceName, HealthChecks.toHaveAllPortsOpen()).build();
+    }
+
+  }
+
+}
diff --git a/geode-connectors/src/test/resources/org/apache/geode/connectors/jdbc/internal/mysql.yml b/geode-connectors/src/test/resources/org/apache/geode/connectors/jdbc/internal/mysql.yml
new file mode 100644
index 0000000..6b127df
--- /dev/null
+++ b/geode-connectors/src/test/resources/org/apache/geode/connectors/jdbc/internal/mysql.yml
@@ -0,0 +1,28 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
+#
+version: '2.0'
+
+services:
+
+  db:
+    image: mysql:5.7
+    restart: always
+    ports:
+        - 3306
+    environment:
+      MYSQL_ALLOW_EMPTY_PASSWORD: "true"
+      #MYSQL_ROOT_PASSWORD: "secret"
\ No newline at end of file
diff --git a/geode-connectors/src/test/resources/org/apache/geode/connectors/jdbc/internal/postgres.yml b/geode-connectors/src/test/resources/org/apache/geode/connectors/jdbc/internal/postgres.yml
new file mode 100644
index 0000000..2320682
--- /dev/null
+++ b/geode-connectors/src/test/resources/org/apache/geode/connectors/jdbc/internal/postgres.yml
@@ -0,0 +1,27 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
+#
+version: '2.0'
+
+services:
+
+  db:
+    image: postgres
+    restart: always
+    ports:
+      - 5432
+    environment:
+      POSTGRES_DB: test
diff --git a/geode-connectors/src/test/resources/org/apache/geode/connectors/jdbc/mysql.yml b/geode-connectors/src/test/resources/org/apache/geode/connectors/jdbc/mysql.yml
new file mode 100644
index 0000000..6b127df
--- /dev/null
+++ b/geode-connectors/src/test/resources/org/apache/geode/connectors/jdbc/mysql.yml
@@ -0,0 +1,28 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
+#
+version: '2.0'
+
+services:
+
+  db:
+    image: mysql:5.7
+    restart: always
+    ports:
+        - 3306
+    environment:
+      MYSQL_ALLOW_EMPTY_PASSWORD: "true"
+      #MYSQL_ROOT_PASSWORD: "secret"
\ No newline at end of file
diff --git a/geode-connectors/src/test/resources/org/apache/geode/connectors/jdbc/postgres.yml b/geode-connectors/src/test/resources/org/apache/geode/connectors/jdbc/postgres.yml
new file mode 100644
index 0000000..2320682
--- /dev/null
+++ b/geode-connectors/src/test/resources/org/apache/geode/connectors/jdbc/postgres.yml
@@ -0,0 +1,27 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
+#
+version: '2.0'
+
+services:
+
+  db:
+    image: postgres
+    restart: always
+    ports:
+      - 5432
+    environment:
+      POSTGRES_DB: test

-- 
To stop receiving notification emails like this one, please contact
agingade@apache.org.