You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by ds...@apache.org on 2018/03/27 19:27:23 UTC

[geode] branch develop updated: GEODE-4922: handle Date conversion (#1686)

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

dschneider 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 1307696  GEODE-4922: handle Date conversion (#1686)
1307696 is described below

commit 1307696270a571b94a24bc4dace9bc2ab1bc104a
Author: Darrel Schneider <ds...@pivotal.io>
AuthorDate: Tue Mar 27 12:27:18 2018 -0700

    GEODE-4922: handle Date conversion (#1686)
    
    When writing a java.util.Date the column type will be used
    to convert it to a java.sql.Date, java.sql.Time, or java.sql.Timestamp.
    When reading a pdx DATE field, the column type will be used to
    decide if getDate, getTime, or getTimestamp is called.
    When reading a pdx OBJECT field, if getObject returns an instance of
    java.sql.Date, java.sql.Time, or java.sql.Timestamp then it will be
    converted to java.util.Date and that will be stored in the pdx field.
---
 .../geode/connectors/jdbc/internal/SqlHandler.java |  23 ++-
 .../jdbc/internal/SqlToPdxInstanceCreator.java     |  47 ++++--
 .../geode/connectors/jdbc/JdbcDUnitTest.java       | 124 ++++++++++++++--
 .../connectors/jdbc/JdbcLoaderIntegrationTest.java |   7 +-
 .../connectors/jdbc/internal/SqlHandlerTest.java   | 132 ++++++++++++++++-
 .../jdbc/internal/SqlToPdxInstanceCreatorTest.java | 162 ++++++++++++++++++++-
 6 files changed, 458 insertions(+), 37 deletions(-)

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 94a792b..8e9ab6c 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
@@ -18,8 +18,10 @@ import java.sql.Connection;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
+import java.sql.Types;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Date;
 import java.util.List;
 
 import org.apache.geode.InternalGemFireException;
@@ -69,10 +71,9 @@ public class SqlHandler {
       try (PreparedStatement statement =
           getPreparedStatement(connection, columnList, realTableName, Operation.GET)) {
         try (ResultSet resultSet = executeReadQuery(statement, columnList)) {
-          String keyColumnName = tableMetaData.getKeyColumnName();
           InternalCache cache = (InternalCache) region.getRegionService();
           SqlToPdxInstanceCreator sqlToPdxInstanceCreator =
-              new SqlToPdxInstanceCreator(cache, regionMapping, resultSet, keyColumnName);
+              new SqlToPdxInstanceCreator(cache, regionMapping, resultSet, tableMetaData);
           result = sqlToPdxInstanceCreator.create();
         }
       }
@@ -113,6 +114,24 @@ public class SqlHandler {
       Object value = columnValue.getValue();
       if (value instanceof Character) {
         value = ((Character) value).toString();
+      } else if (value instanceof Date) {
+        Date jdkDate = (Date) value;
+        switch (columnValue.getDataType()) {
+          case Types.DATE:
+            value = new java.sql.Date(jdkDate.getTime());
+            break;
+          case Types.TIME:
+          case Types.TIME_WITH_TIMEZONE:
+            value = new java.sql.Time(jdkDate.getTime());
+            break;
+          case Types.TIMESTAMP:
+          case Types.TIMESTAMP_WITH_TIMEZONE:
+            value = new java.sql.Timestamp(jdkDate.getTime());
+            break;
+          default:
+            // no conversion needed
+            break;
+        }
       }
       if (value == null) {
         statement.setNull(index, columnValue.getDataType());
diff --git a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/SqlToPdxInstanceCreator.java b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/SqlToPdxInstanceCreator.java
index 1d6a816..6d08e0b 100644
--- a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/SqlToPdxInstanceCreator.java
+++ b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/SqlToPdxInstanceCreator.java
@@ -17,6 +17,7 @@ package org.apache.geode.connectors.jdbc.internal;
 import java.sql.ResultSet;
 import java.sql.ResultSetMetaData;
 import java.sql.SQLException;
+import java.sql.Types;
 
 import org.apache.geode.connectors.jdbc.JdbcConnectorException;
 import org.apache.geode.internal.cache.InternalCache;
@@ -31,14 +32,14 @@ class SqlToPdxInstanceCreator {
   private final InternalCache cache;
   private final RegionMapping regionMapping;
   private final ResultSet resultSet;
-  private final String keyColumnName;
+  private final TableMetaDataView tableMetaData;
 
   public SqlToPdxInstanceCreator(InternalCache cache, RegionMapping regionMapping,
-      ResultSet resultSet, String keyColumnName) {
+      ResultSet resultSet, TableMetaDataView tableMetaData) {
     this.cache = cache;
     this.regionMapping = regionMapping;
     this.resultSet = resultSet;
-    this.keyColumnName = keyColumnName;
+    this.tableMetaData = tableMetaData;
   }
 
   public PdxInstance create() throws SQLException {
@@ -50,11 +51,12 @@ class SqlToPdxInstanceCreator {
       TypeRegistry typeRegistry = cache.getPdxRegistry();
       for (int i = 1; i <= ColumnsNumber; i++) {
         String columnName = metaData.getColumnName(i);
-        if (regionMapping.isPrimaryKeyInValue() || !keyColumnName.equalsIgnoreCase(columnName)) {
+        if (regionMapping.isPrimaryKeyInValue()
+            || !tableMetaData.getKeyColumnName().equalsIgnoreCase(columnName)) {
           String fieldName = regionMapping.getFieldNameForColumn(columnName, typeRegistry);
           FieldType fieldType =
               getFieldType(typeRegistry, regionMapping.getPdxClassName(), fieldName);
-          writeField(factory, resultSet, i, fieldName, fieldType);
+          writeField(factory, resultSet, i, fieldName, fieldType, columnName);
         }
       }
       if (resultSet.next()) {
@@ -82,7 +84,7 @@ class SqlToPdxInstanceCreator {
    * @throws SQLException if the column value get fails
    */
   private void writeField(PdxInstanceFactory factory, ResultSet resultSet, int columnIndex,
-      String fieldName, FieldType fieldType) throws SQLException {
+      String fieldName, FieldType fieldType, String columnName) throws SQLException {
     switch (fieldType) {
       case STRING:
         factory.writeString(fieldName, resultSet.getString(columnIndex));
@@ -116,14 +118,28 @@ class SqlToPdxInstanceCreator {
       case BOOLEAN:
         factory.writeBoolean(fieldName, resultSet.getBoolean(columnIndex));
         break;
-      case DATE:
-        java.sql.Timestamp sqlDate = resultSet.getTimestamp(columnIndex);
+      case DATE: {
+        int columnType = this.tableMetaData.getColumnDataType(columnName);
+        java.util.Date sqlDate;
+        switch (columnType) {
+          case Types.DATE:
+            sqlDate = resultSet.getDate(columnIndex);
+            break;
+          case Types.TIME:
+          case Types.TIME_WITH_TIMEZONE:
+            sqlDate = resultSet.getTime(columnIndex);
+            break;
+          default:
+            sqlDate = resultSet.getTimestamp(columnIndex);
+            break;
+        }
         java.util.Date pdxDate = null;
         if (sqlDate != null) {
           pdxDate = new java.util.Date(sqlDate.getTime());
         }
         factory.writeDate(fieldName, pdxDate);
         break;
+      }
       case BYTE_ARRAY:
         factory.writeByteArray(fieldName, resultSet.getBytes(columnIndex));
         break;
@@ -168,7 +184,20 @@ class SqlToPdxInstanceCreator {
             convertJdbcObjectToJavaType(byte[][].class, resultSet.getObject(columnIndex)));
         break;
       case OBJECT:
-        factory.writeObject(fieldName, resultSet.getObject(columnIndex));
+        Object v = resultSet.getObject(columnIndex);
+        if (v instanceof java.util.Date) {
+          if (v instanceof java.sql.Date) {
+            java.sql.Date sqlDate = (java.sql.Date) v;
+            v = new java.util.Date(sqlDate.getTime());
+          } else if (v instanceof java.sql.Time) {
+            java.sql.Time sqlTime = (java.sql.Time) v;
+            v = new java.util.Date(sqlTime.getTime());
+          } else if (v instanceof java.sql.Timestamp) {
+            java.sql.Timestamp sqlTimestamp = (java.sql.Timestamp) v;
+            v = new java.util.Date(sqlTimestamp.getTime());
+          }
+        }
+        factory.writeObject(fieldName, v);
         break;
     }
   }
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/JdbcDUnitTest.java
index 7cdd055..e63d480 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/JdbcDUnitTest.java
@@ -197,7 +197,7 @@ public class JdbcDUnitTest implements Serializable {
       PdxInstance pdxEmployee1 =
           ClusterStartupRule.getCache().createPdxInstanceFactory(Employee.class.getName())
               .writeString("name", "Emp1").writeInt("age", 55).create();
-      Region region = ClusterStartupRule.getCache().getRegion(REGION_NAME);
+      Region<Object, Object> region = ClusterStartupRule.getCache().getRegion(REGION_NAME);
       assertThatThrownBy(() -> region.put("key1", pdxEmployee1))
           .isExactlyInstanceOf(JdbcConnectorException.class).hasMessage(
               "JDBC mapping for region employees not found. Create the mapping with the gfsh command 'create jdbc-mapping'.");
@@ -215,7 +215,7 @@ public class JdbcDUnitTest implements Serializable {
       PdxInstance pdxEmployee1 =
           ClusterStartupRule.getCache().createPdxInstanceFactory(Employee.class.getName())
               .writeString("name", "Emp1").writeInt("age", 55).create();
-      Region region = ClusterStartupRule.getCache().getRegion(REGION_NAME);
+      Region<Object, Object> region = ClusterStartupRule.getCache().getRegion(REGION_NAME);
       region.put("key1", pdxEmployee1);
 
       JdbcAsyncWriter asyncWriter = (JdbcAsyncWriter) ClusterStartupRule.getCache()
@@ -238,7 +238,7 @@ public class JdbcDUnitTest implements Serializable {
       PdxInstance pdxEmployee1 =
           ClusterStartupRule.getCache().createPdxInstanceFactory(Employee.class.getName())
               .writeString("name", "Emp1").writeInt("age", 55).create();
-      Region region = ClusterStartupRule.getCache().getRegion(REGION_NAME);
+      Region<Object, Object> region = ClusterStartupRule.getCache().getRegion(REGION_NAME);
       assertThatThrownBy(() -> region.put("key1", pdxEmployee1))
           .isExactlyInstanceOf(JdbcConnectorException.class).hasMessage(
               "JDBC mapping for region employees not found. Create the mapping with the gfsh command 'create jdbc-mapping'.");
@@ -255,7 +255,7 @@ public class JdbcDUnitTest implements Serializable {
       PdxInstance pdxEmployee1 =
           ClusterStartupRule.getCache().createPdxInstanceFactory(Employee.class.getName())
               .writeString("name", "Emp1").writeInt("age", 55).create();
-      Region region = ClusterStartupRule.getCache().getRegion(REGION_NAME);
+      Region<Object, Object> region = ClusterStartupRule.getCache().getRegion(REGION_NAME);
       assertThatThrownBy(() -> region.put("key1", pdxEmployee1))
           .isExactlyInstanceOf(JdbcConnectorException.class).hasMessage(
               "JDBC connection with name TestConnection not found. Create the connection with the gfsh command 'create jdbc-connection'");
@@ -263,6 +263,111 @@ public class JdbcDUnitTest implements Serializable {
   }
 
   @Test
+  public void verifyDateToDate() 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, mydate date)");
+    });
+    createRegionUsingGfsh(true, false, true);
+    createJdbcConnection();
+    createMapping(REGION_NAME, CONNECTION_NAME);
+    final String key = "emp1";
+    final java.sql.Date sqlDate = java.sql.Date.valueOf("1982-09-11");
+    final Date jdkDate = new Date(sqlDate.getTime());
+    server.invoke(() -> {
+      PdxInstance pdxEmployee1 =
+          ClusterStartupRule.getCache().createPdxInstanceFactory(Employee.class.getName())
+              .writeString("id", "key1").writeDate("mydate", jdkDate).create();
+
+      Region<Object, Object> region = ClusterStartupRule.getCache().getRegion(REGION_NAME);
+      region.put(key, pdxEmployee1);
+      region.invalidate(key);
+    });
+    ClientVM client = getClientVM();
+    createClientRegion(client);
+    client.invoke(() -> {
+      Region<String, ClassWithSupportedPdxFields> region =
+          ClusterStartupRule.getClientCache().getRegion(REGION_NAME);
+      PdxInstance getResult = (PdxInstance) region.get(key);
+      assertThat(getResult.getField("mydate")).isInstanceOf(java.util.Date.class)
+          .isEqualTo(jdkDate);
+    });
+  }
+
+  @Test
+  public void verifyDateToTime() 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, mytime time)");
+    });
+    createRegionUsingGfsh(true, false, true);
+    createJdbcConnection();
+    createMapping(REGION_NAME, CONNECTION_NAME);
+    final String key = "emp1";
+    final java.sql.Time sqlTime = java.sql.Time.valueOf("23:59:59");
+    final Date jdkDate = new Date(sqlTime.getTime());
+    server.invoke(() -> {
+      PdxInstance pdxEmployee1 =
+          ClusterStartupRule.getCache().createPdxInstanceFactory(Employee.class.getName())
+              .writeString("id", "key1").writeDate("mytime", jdkDate).create();
+
+      Region<Object, Object> region = ClusterStartupRule.getCache().getRegion(REGION_NAME);
+      region.put(key, pdxEmployee1);
+      region.invalidate(key);
+    });
+    ClientVM client = getClientVM();
+    createClientRegion(client);
+    client.invoke(() -> {
+      Region<String, ClassWithSupportedPdxFields> region =
+          ClusterStartupRule.getClientCache().getRegion(REGION_NAME);
+      PdxInstance getResult = (PdxInstance) region.get(key);
+      assertThat(getResult.getField("mytime")).isInstanceOf(java.util.Date.class)
+          .isEqualTo(jdkDate);
+    });
+  }
+
+  @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)");
+    });
+    createRegionUsingGfsh(true, false, true);
+    createJdbcConnection();
+    createMapping(REGION_NAME, CONNECTION_NAME);
+    final String key = "emp1";
+    final java.sql.Timestamp sqlTimestamp = java.sql.Timestamp.valueOf("1982-09-11 23:59:59.123");
+    final Date jdkDate = new Date(sqlTimestamp.getTime());
+    server.invoke(() -> {
+      PdxInstance pdxEmployee1 =
+          ClusterStartupRule.getCache().createPdxInstanceFactory(Employee.class.getName())
+              .writeString("id", "key1").writeDate("mytimestamp", jdkDate).create();
+
+      Region<Object, Object> region = ClusterStartupRule.getCache().getRegion(REGION_NAME);
+      region.put(key, pdxEmployee1);
+      region.invalidate(key);
+    });
+    ClientVM client = getClientVM();
+    createClientRegion(client);
+    client.invoke(() -> {
+      Region<String, ClassWithSupportedPdxFields> region =
+          ClusterStartupRule.getClientCache().getRegion(REGION_NAME);
+      PdxInstance getResult = (PdxInstance) region.get(key);
+      assertThat(getResult.getField("mytimestamp")).isInstanceOf(java.util.Date.class)
+          .isEqualTo(jdkDate);
+    });
+  }
+
+  @Test
   public void putWritesToDB() throws Exception {
     createTable();
     createRegionUsingGfsh(true, false, false);
@@ -304,7 +409,7 @@ public class JdbcDUnitTest implements Serializable {
     createMapping(REGION_NAME, CONNECTION_NAME);
     server.invoke(() -> {
       String key = "emp1";
-      Region region = ClusterStartupRule.getCache().getRegion(REGION_NAME);
+      Region<Object, Object> region = ClusterStartupRule.getCache().getRegion(REGION_NAME);
       Object value = region.get(key);
       assertThat(value).isNull();
       assertThat(region.size()).isEqualTo(0);
@@ -323,11 +428,12 @@ public class JdbcDUnitTest implements Serializable {
               .writeString("id", "id1").writeString("name", "Emp1").writeInt("age", 55).create();
 
       String key = "id1";
-      Region region = ClusterStartupRule.getCache().getRegion(REGION_NAME);
+      Region<Object, Object> region = ClusterStartupRule.getCache().getRegion(REGION_NAME);
       region.put(key, pdxEmployee1);
       region.invalidate(key);
 
-      JdbcWriter writer = (JdbcWriter) region.getAttributes().getCacheWriter();
+      JdbcWriter<Object, Object> writer =
+          (JdbcWriter<Object, Object>) region.getAttributes().getCacheWriter();
       long writeCallsCompletedBeforeGet = writer.getTotalEvents();
 
       PdxInstance result = (PdxInstance) region.get(key);
@@ -350,7 +456,7 @@ public class JdbcDUnitTest implements Serializable {
           ClusterStartupRule.getCache().createPdxInstanceFactory(Employee.class.getName())
               .writeString("id", "id1").writeString("name", "Emp1").writeInt("age", 55).create();
       String key = "id1";
-      Region region = ClusterStartupRule.getCache().getRegion(REGION_NAME);
+      Region<Object, Object> region = ClusterStartupRule.getCache().getRegion(REGION_NAME);
       JdbcAsyncWriter asyncWriter = (JdbcAsyncWriter) ClusterStartupRule.getCache()
           .getAsyncEventQueue("JAW").getAsyncEventListener();
 
@@ -379,7 +485,7 @@ public class JdbcDUnitTest implements Serializable {
     server.invoke(() -> {
       String key = "id1";
       Employee value = new Employee("Emp1", 55);
-      Region region = ClusterStartupRule.getCache().getRegion(REGION_NAME);
+      Region<Object, Object> region = ClusterStartupRule.getCache().getRegion(REGION_NAME);
       region.put(key, value);
       region.invalidate(key);
 
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 eb44dee..a4ec5ab 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
@@ -84,11 +84,6 @@ public class JdbcLoaderIntegrationTest {
         + " (id varchar(10) primary key not null, name varchar(10), age int)");
   }
 
-  private void createEmployeeTableWithQuotes() throws Exception {
-    statement.execute("Create Table \"" + REGION_TABLE_NAME
-        + "\" (\"id\" varchar(10) primary key not null, \"name\" varchar(10), \"age\" int, \"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, "
@@ -223,7 +218,7 @@ public class JdbcLoaderIntegrationTest {
     ps.setObject(i++, classWithSupportedPdxFields.getAfloat());
     ps.setObject(i++, classWithSupportedPdxFields.getAdouble());
     ps.setObject(i++, classWithSupportedPdxFields.getAstring());
-    ps.setObject(i++, classWithSupportedPdxFields.getAdate());
+    ps.setObject(i++, new java.sql.Timestamp(classWithSupportedPdxFields.getAdate().getTime()));
     ps.setObject(i++, classWithSupportedPdxFields.getAnobject());
     ps.setObject(i++, classWithSupportedPdxFields.getAbytearray());
     ps.setObject(i++, new Character(classWithSupportedPdxFields.getAchar()).toString());
diff --git a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/SqlHandlerTest.java b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/SqlHandlerTest.java
index 100fa13..196bfa1 100644
--- a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/SqlHandlerTest.java
+++ b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/SqlHandlerTest.java
@@ -31,7 +31,9 @@ import java.sql.DatabaseMetaData;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
+import java.sql.Types;
 import java.util.Arrays;
+import java.util.Date;
 import java.util.List;
 
 import junitparams.JUnitParamsRunner;
@@ -57,13 +59,7 @@ public class SqlHandlerTest {
   private static final String CONNECTION_CONFIG_NAME = "testConnectionConfig";
   private static final String REGION_NAME = "testRegion";
   private static final String TABLE_NAME = "testTable";
-  private static final String COLUMN_NAME_1 = "columnName1";
-  private static final Object COLUMN_VALUE_1 = "columnValue1";
-  private static final Object COLUMN_VALUE_2 = "columnValue2";
-  private static final String COLUMN_NAME_2 = "columnName2";
   private static final String KEY_COLUMN = "keyColumn";
-  private static final String PDX_FIELD_NAME_1 = COLUMN_NAME_1.toLowerCase();
-  private static final String PDX_FIELD_NAME_2 = COLUMN_NAME_2.toLowerCase();
 
   @Rule
   public ExpectedException thrown = ExpectedException.none();
@@ -75,7 +71,7 @@ public class SqlHandlerTest {
   private TableMetaDataManager tableMetaDataManager;
   private TableMetaDataView tableMetaDataView;
   private Connection connection;
-  private Region region;
+  private Region<Object, Object> region;
   private InternalCache cache;
   private SqlHandler handler;
   private PreparedStatement statement;
@@ -83,6 +79,7 @@ public class SqlHandlerTest {
   private PdxInstanceImpl value;
   private Object key;
 
+  @SuppressWarnings("unchecked")
   @Before
   public void setup() throws Exception {
     manager = mock(DataSourceManager.class);
@@ -137,6 +134,7 @@ public class SqlHandlerTest {
     handler.read(region, null);
   }
 
+  @SuppressWarnings("unchecked")
   @Test
   public void readThrowsIfNoMapping() throws Exception {
     thrown.expect(JdbcConnectorException.class);
@@ -145,7 +143,8 @@ public class SqlHandlerTest {
 
   @Test
   public void readThrowsIfNoConnectionConfig() throws Exception {
-    Region region2 = mock(Region.class);
+    @SuppressWarnings("unchecked")
+    Region<Object, Object> region2 = mock(Region.class);
     when(region2.getName()).thenReturn("region2");
     RegionMapping regionMapping2 = mock(RegionMapping.class);
     when(regionMapping2.getConnectionConfigName()).thenReturn("bogus connection name");
@@ -198,6 +197,123 @@ public class SqlHandlerTest {
   }
 
   @Test
+  public void writeWithDateField() throws Exception {
+    String fieldName = "fieldName";
+    Object fieldValue = new Date();
+    when(regionMapping.getColumnNameForField(eq(fieldName), any())).thenReturn(fieldName);
+    when(value.getFieldNames()).thenReturn(Arrays.asList(fieldName));
+    when(value.getField(fieldName)).thenReturn(fieldValue);
+
+    when(statement.executeUpdate()).thenReturn(1);
+    Object createKey = "createKey";
+    handler.write(region, Operation.CREATE, createKey, value);
+
+    verify(statement).setObject(1, fieldValue);
+    verify(statement).setObject(2, createKey);
+    verify(statement).close();
+  }
+
+  @Test
+  public void writeWithDateFieldWithDateTypeFromMetaData() throws Exception {
+    String fieldName = "fieldName";
+    Date fieldValue = new Date();
+    Object expectedValueWritten = new java.sql.Date(fieldValue.getTime());
+    int dataType = Types.DATE;
+    when(tableMetaDataView.getColumnDataType(fieldName)).thenReturn(dataType);
+    when(regionMapping.getColumnNameForField(eq(fieldName), any())).thenReturn(fieldName);
+    when(value.getFieldNames()).thenReturn(Arrays.asList(fieldName));
+    when(value.getField(fieldName)).thenReturn(fieldValue);
+
+    when(statement.executeUpdate()).thenReturn(1);
+    Object createKey = "createKey";
+    handler.write(region, Operation.CREATE, createKey, value);
+
+    verify(statement).setObject(1, expectedValueWritten);
+    verify(statement).setObject(2, createKey);
+    verify(statement).close();
+  }
+
+  @Test
+  public void writeWithDateFieldWithTimeTypeFromMetaData() throws Exception {
+    String fieldName = "fieldName";
+    Date fieldValue = new Date();
+    Object expectedValueWritten = new java.sql.Time(fieldValue.getTime());
+    int dataType = Types.TIME;
+    when(tableMetaDataView.getColumnDataType(fieldName)).thenReturn(dataType);
+    when(regionMapping.getColumnNameForField(eq(fieldName), any())).thenReturn(fieldName);
+    when(value.getFieldNames()).thenReturn(Arrays.asList(fieldName));
+    when(value.getField(fieldName)).thenReturn(fieldValue);
+
+    when(statement.executeUpdate()).thenReturn(1);
+    Object createKey = "createKey";
+    handler.write(region, Operation.CREATE, createKey, value);
+
+    verify(statement).setObject(1, expectedValueWritten);
+    verify(statement).setObject(2, createKey);
+    verify(statement).close();
+  }
+
+  @Test
+  public void writeWithDateFieldWithTimeWithTimezoneTypeFromMetaData() throws Exception {
+    String fieldName = "fieldName";
+    Date fieldValue = new Date();
+    Object expectedValueWritten = new java.sql.Time(fieldValue.getTime());
+    int dataType = Types.TIME_WITH_TIMEZONE;
+    when(tableMetaDataView.getColumnDataType(fieldName)).thenReturn(dataType);
+    when(regionMapping.getColumnNameForField(eq(fieldName), any())).thenReturn(fieldName);
+    when(value.getFieldNames()).thenReturn(Arrays.asList(fieldName));
+    when(value.getField(fieldName)).thenReturn(fieldValue);
+
+    when(statement.executeUpdate()).thenReturn(1);
+    Object createKey = "createKey";
+    handler.write(region, Operation.CREATE, createKey, value);
+
+    verify(statement).setObject(1, expectedValueWritten);
+    verify(statement).setObject(2, createKey);
+    verify(statement).close();
+  }
+
+  @Test
+  public void writeWithDateFieldWithTimestampTypeFromMetaData() throws Exception {
+    String fieldName = "fieldName";
+    Date fieldValue = new Date();
+    Object expectedValueWritten = new java.sql.Timestamp(fieldValue.getTime());
+    int dataType = Types.TIMESTAMP;
+    when(tableMetaDataView.getColumnDataType(fieldName)).thenReturn(dataType);
+    when(regionMapping.getColumnNameForField(eq(fieldName), any())).thenReturn(fieldName);
+    when(value.getFieldNames()).thenReturn(Arrays.asList(fieldName));
+    when(value.getField(fieldName)).thenReturn(fieldValue);
+
+    when(statement.executeUpdate()).thenReturn(1);
+    Object createKey = "createKey";
+    handler.write(region, Operation.CREATE, createKey, value);
+
+    verify(statement).setObject(1, expectedValueWritten);
+    verify(statement).setObject(2, createKey);
+    verify(statement).close();
+  }
+
+  @Test
+  public void writeWithDateFieldWithTimestampWithTimezoneTypeFromMetaData() throws Exception {
+    String fieldName = "fieldName";
+    Date fieldValue = new Date();
+    Object expectedValueWritten = new java.sql.Timestamp(fieldValue.getTime());
+    int dataType = Types.TIMESTAMP_WITH_TIMEZONE;
+    when(tableMetaDataView.getColumnDataType(fieldName)).thenReturn(dataType);
+    when(regionMapping.getColumnNameForField(eq(fieldName), any())).thenReturn(fieldName);
+    when(value.getFieldNames()).thenReturn(Arrays.asList(fieldName));
+    when(value.getField(fieldName)).thenReturn(fieldValue);
+
+    when(statement.executeUpdate()).thenReturn(1);
+    Object createKey = "createKey";
+    handler.write(region, Operation.CREATE, createKey, value);
+
+    verify(statement).setObject(1, expectedValueWritten);
+    verify(statement).setObject(2, createKey);
+    verify(statement).close();
+  }
+
+  @Test
   public void writeWithNonCharField() throws Exception {
     String fieldName = "fieldName";
     int fieldValue = 100;
diff --git a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/SqlToPdxInstanceCreatorTest.java b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/SqlToPdxInstanceCreatorTest.java
index 41cef01..9f84f72 100644
--- a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/SqlToPdxInstanceCreatorTest.java
+++ b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/SqlToPdxInstanceCreatorTest.java
@@ -29,6 +29,7 @@ import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.ResultSetMetaData;
 import java.sql.SQLException;
+import java.sql.Types;
 import java.util.Date;
 
 import junitparams.JUnitParamsRunner;
@@ -66,6 +67,7 @@ public class SqlToPdxInstanceCreatorTest {
   private SqlToPdxInstanceCreator sqlToPdxInstanceCreator;
   private RegionMapping regionMapping;
   private ResultSet resultSet;
+  private TableMetaDataView tableMetaDataView;
 
   @Rule
   public ExpectedException thrown = ExpectedException.none();
@@ -75,8 +77,10 @@ public class SqlToPdxInstanceCreatorTest {
     cache = mock(InternalCache.class);
     regionMapping = mock(RegionMapping.class);
     resultSet = mock(ResultSet.class);
+    tableMetaDataView = mock(TableMetaDataView.class);
+    when(tableMetaDataView.getKeyColumnName()).thenReturn(KEY_COLUMN);
     sqlToPdxInstanceCreator =
-        new SqlToPdxInstanceCreator(cache, regionMapping, resultSet, KEY_COLUMN);
+        new SqlToPdxInstanceCreator(cache, regionMapping, resultSet, tableMetaDataView);
   }
 
   @Test
@@ -116,8 +120,10 @@ public class SqlToPdxInstanceCreatorTest {
     when(cache.createPdxInstanceFactory(anyString(), anyBoolean())).thenReturn(factory);
     when(regionMapping.getFieldNameForColumn(eq(COLUMN_NAME_2), any()))
         .thenReturn(PDX_FIELD_NAME_2);
+    tableMetaDataView = mock(TableMetaDataView.class);
+    when(tableMetaDataView.getKeyColumnName()).thenReturn(COLUMN_NAME_1);
     sqlToPdxInstanceCreator =
-        new SqlToPdxInstanceCreator(cache, regionMapping, resultSet, COLUMN_NAME_1);
+        new SqlToPdxInstanceCreator(cache, regionMapping, resultSet, tableMetaDataView);
 
     sqlToPdxInstanceCreator.create();
 
@@ -191,6 +197,7 @@ public class SqlToPdxInstanceCreatorTest {
 
   @Test
   public void readOfCharFieldWithEmptyStringWritesCharZero() throws Exception {
+    char expectedValue = 0;
     FieldType fieldType = FieldType.CHAR;
     ResultSetMetaData metaData = mock(ResultSetMetaData.class);
     when(resultSet.getMetaData()).thenReturn(metaData);
@@ -204,7 +211,155 @@ public class SqlToPdxInstanceCreatorTest {
 
     sqlToPdxInstanceCreator.create();
 
-    char expectedValue = 0;
+    verifyPdxFactoryWrite(factory, fieldType, expectedValue);
+    verify(factory).create();
+  }
+
+  @Test
+  public void readOfDateFieldWithDateColumnWritesDate() throws Exception {
+    FieldType fieldType = FieldType.DATE;
+    ResultSetMetaData metaData = mock(ResultSetMetaData.class);
+    when(resultSet.getMetaData()).thenReturn(metaData);
+    when(metaData.getColumnCount()).thenReturn(1);
+    when(metaData.getColumnName(1)).thenReturn(COLUMN_NAME_1);
+    when(tableMetaDataView.getColumnDataType(COLUMN_NAME_1)).thenReturn(Types.DATE);
+    java.sql.Date sqlDate = java.sql.Date.valueOf("1979-09-11");
+    Date expectedValue = new Date(sqlDate.getTime());
+    when(resultSet.getDate(1)).thenReturn(sqlDate);
+    when(resultSet.next()).thenReturn(true).thenReturn(false);
+    PdxInstanceFactory factory = setupPdxInstanceFactory(fieldType);
+    when(regionMapping.getFieldNameForColumn(eq(COLUMN_NAME_1), any()))
+        .thenReturn(PDX_FIELD_NAME_1);
+
+    sqlToPdxInstanceCreator.create();
+
+    verifyPdxFactoryWrite(factory, fieldType, expectedValue);
+    verify(factory).create();
+  }
+
+  @Test
+  public void readOfDateFieldWithTimeColumnWritesDate() throws Exception {
+    FieldType fieldType = FieldType.DATE;
+    ResultSetMetaData metaData = mock(ResultSetMetaData.class);
+    when(resultSet.getMetaData()).thenReturn(metaData);
+    when(metaData.getColumnCount()).thenReturn(1);
+    when(metaData.getColumnName(1)).thenReturn(COLUMN_NAME_1);
+    when(tableMetaDataView.getColumnDataType(COLUMN_NAME_1)).thenReturn(Types.TIME);
+    java.sql.Time sqlTime = java.sql.Time.valueOf("22:33:44");
+    Date expectedValue = new Date(sqlTime.getTime());
+    when(resultSet.getTime(1)).thenReturn(sqlTime);
+    when(resultSet.next()).thenReturn(true).thenReturn(false);
+    PdxInstanceFactory factory = setupPdxInstanceFactory(fieldType);
+    when(regionMapping.getFieldNameForColumn(eq(COLUMN_NAME_1), any()))
+        .thenReturn(PDX_FIELD_NAME_1);
+
+    sqlToPdxInstanceCreator.create();
+
+    verifyPdxFactoryWrite(factory, fieldType, expectedValue);
+    verify(factory).create();
+  }
+
+  @Test
+  public void readOfDateFieldWithTimestampColumnWritesDate() throws Exception {
+    FieldType fieldType = FieldType.DATE;
+    ResultSetMetaData metaData = mock(ResultSetMetaData.class);
+    when(resultSet.getMetaData()).thenReturn(metaData);
+    when(metaData.getColumnCount()).thenReturn(1);
+    when(metaData.getColumnName(1)).thenReturn(COLUMN_NAME_1);
+    when(tableMetaDataView.getColumnDataType(COLUMN_NAME_1)).thenReturn(Types.TIMESTAMP);
+    java.sql.Timestamp sqlTimestamp = java.sql.Timestamp.valueOf("1979-09-11 22:33:44.567");
+    Date expectedValue = new Date(sqlTimestamp.getTime());
+    when(resultSet.getTimestamp(1)).thenReturn(sqlTimestamp);
+    when(resultSet.next()).thenReturn(true).thenReturn(false);
+    PdxInstanceFactory factory = setupPdxInstanceFactory(fieldType);
+    when(regionMapping.getFieldNameForColumn(eq(COLUMN_NAME_1), any()))
+        .thenReturn(PDX_FIELD_NAME_1);
+
+    sqlToPdxInstanceCreator.create();
+
+    verifyPdxFactoryWrite(factory, fieldType, expectedValue);
+    verify(factory).create();
+  }
+
+  @Test
+  public void readOfObjectFieldWithDateColumnWritesDate() throws Exception {
+    FieldType fieldType = FieldType.OBJECT;
+    ResultSetMetaData metaData = mock(ResultSetMetaData.class);
+    when(resultSet.getMetaData()).thenReturn(metaData);
+    when(metaData.getColumnCount()).thenReturn(1);
+    when(metaData.getColumnName(1)).thenReturn(COLUMN_NAME_1);
+    java.sql.Date sqlDate = java.sql.Date.valueOf("1979-09-11");
+    Date expectedValue = new Date(sqlDate.getTime());
+    when(resultSet.getObject(1)).thenReturn(sqlDate);
+    when(resultSet.next()).thenReturn(true).thenReturn(false);
+    PdxInstanceFactory factory = setupPdxInstanceFactory(fieldType);
+    when(regionMapping.getFieldNameForColumn(eq(COLUMN_NAME_1), any()))
+        .thenReturn(PDX_FIELD_NAME_1);
+
+    sqlToPdxInstanceCreator.create();
+
+    verifyPdxFactoryWrite(factory, fieldType, expectedValue);
+    verify(factory).create();
+  }
+
+  @Test
+  public void readOfObjectFieldWithJavaUtilDateWritesDate() throws Exception {
+    FieldType fieldType = FieldType.OBJECT;
+    ResultSetMetaData metaData = mock(ResultSetMetaData.class);
+    when(resultSet.getMetaData()).thenReturn(metaData);
+    when(metaData.getColumnCount()).thenReturn(1);
+    when(metaData.getColumnName(1)).thenReturn(COLUMN_NAME_1);
+    Date expectedValue = new Date();
+    when(resultSet.getObject(1)).thenReturn(expectedValue);
+    when(resultSet.next()).thenReturn(true).thenReturn(false);
+    PdxInstanceFactory factory = setupPdxInstanceFactory(fieldType);
+    when(regionMapping.getFieldNameForColumn(eq(COLUMN_NAME_1), any()))
+        .thenReturn(PDX_FIELD_NAME_1);
+
+    sqlToPdxInstanceCreator.create();
+
+    verifyPdxFactoryWrite(factory, fieldType, expectedValue);
+    verify(factory).create();
+  }
+
+  @Test
+  public void readOfObjectFieldWithTimeColumnWritesDate() throws Exception {
+    FieldType fieldType = FieldType.OBJECT;
+    ResultSetMetaData metaData = mock(ResultSetMetaData.class);
+    when(resultSet.getMetaData()).thenReturn(metaData);
+    when(metaData.getColumnCount()).thenReturn(1);
+    when(metaData.getColumnName(1)).thenReturn(COLUMN_NAME_1);
+    java.sql.Time sqlTime = java.sql.Time.valueOf("22:33:44");
+    Date expectedValue = new Date(sqlTime.getTime());
+    when(resultSet.getObject(1)).thenReturn(sqlTime);
+    when(resultSet.next()).thenReturn(true).thenReturn(false);
+    PdxInstanceFactory factory = setupPdxInstanceFactory(fieldType);
+    when(regionMapping.getFieldNameForColumn(eq(COLUMN_NAME_1), any()))
+        .thenReturn(PDX_FIELD_NAME_1);
+
+    sqlToPdxInstanceCreator.create();
+
+    verifyPdxFactoryWrite(factory, fieldType, expectedValue);
+    verify(factory).create();
+  }
+
+  @Test
+  public void readOfObjectFieldWithTimestampColumnWritesDate() throws Exception {
+    FieldType fieldType = FieldType.OBJECT;
+    ResultSetMetaData metaData = mock(ResultSetMetaData.class);
+    when(resultSet.getMetaData()).thenReturn(metaData);
+    when(metaData.getColumnCount()).thenReturn(1);
+    when(metaData.getColumnName(1)).thenReturn(COLUMN_NAME_1);
+    java.sql.Timestamp sqlTimestamp = java.sql.Timestamp.valueOf("1979-09-11 22:33:44.567");
+    Date expectedValue = new Date(sqlTimestamp.getTime());
+    when(resultSet.getObject(1)).thenReturn(sqlTimestamp);
+    when(resultSet.next()).thenReturn(true).thenReturn(false);
+    PdxInstanceFactory factory = setupPdxInstanceFactory(fieldType);
+    when(regionMapping.getFieldNameForColumn(eq(COLUMN_NAME_1), any()))
+        .thenReturn(PDX_FIELD_NAME_1);
+
+    sqlToPdxInstanceCreator.create();
+
     verifyPdxFactoryWrite(factory, fieldType, expectedValue);
     verify(factory).create();
   }
@@ -363,6 +518,7 @@ public class SqlToPdxInstanceCreatorTest {
 
   private static byte[][] arrayOfByteArray = new byte[][] {{1, 2}, {3, 4}};
 
+  @SuppressWarnings("unchecked")
   private <T> T getValueByFieldType(FieldType fieldType) {
     switch (fieldType) {
       case STRING:

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