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 <dschnei...@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 dschnei...@apache.org.