This is an automated email from the ASF dual-hosted git repository. agingade pushed a commit to branch feature/GEODE-4237 in repository https://gitbox.apache.org/repos/asf/geode.git
commit dbb285069f0f0c76ecbea3cf776bd7f466b3415f Author: Anil <[email protected]> AuthorDate: Mon Jan 8 16:59:46 2018 -0800 GEODE-4237: The JdbcLoader creates PdxInstance using region mapping (column to field). --- .../connectors/jdbc/internal/RegionMapping.java | 36 +++++++ .../geode/connectors/jdbc/internal/SqlHandler.java | 11 +- .../jdbc/internal/RegionMappingTest.java | 118 ++++++++++++++++++++- .../connectors/jdbc/internal/SqlHandlerTest.java | 35 +++++- 4 files changed, 189 insertions(+), 11 deletions(-) diff --git a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/RegionMapping.java b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/RegionMapping.java index 394fe48..d87c4d5 100644 --- a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/RegionMapping.java +++ b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/RegionMapping.java @@ -16,6 +16,7 @@ package org.apache.geode.connectors.jdbc.internal; import java.io.Serializable; import java.util.Collections; +import java.util.HashMap; import java.util.Map; import org.apache.geode.annotations.Experimental; @@ -28,6 +29,7 @@ public class RegionMapping implements Serializable { private final String connectionConfigName; private final Boolean primaryKeyInValue; private final Map<String, String> fieldToColumnMap; + private final Map<String, String> columnToFieldMap; public RegionMapping(String regionName, String pdxClassName, String tableName, String connectionConfigName, Boolean primaryKeyInValue, @@ -39,6 +41,24 @@ public class RegionMapping implements Serializable { this.primaryKeyInValue = primaryKeyInValue; this.fieldToColumnMap = fieldToColumnMap == null ? null : Collections.unmodifiableMap(fieldToColumnMap); + this.columnToFieldMap = createReverseMap(fieldToColumnMap); + } + + private static Map<String, String> createReverseMap(Map<String, String> fieldToColumnMap) { + if (fieldToColumnMap == null) { + return null; + } + Map<String, String> reverseMap = new HashMap<>(); + for (Map.Entry<String, String> entry : fieldToColumnMap.entrySet()) { + String reverseMapKey = entry.getValue().toLowerCase(); + String reverseMapValue = entry.getKey(); + if (reverseMap.containsKey(reverseMapKey)) { + throw new IllegalArgumentException( + "The field " + reverseMapValue + " can not be mapped to more than one column."); + } + reverseMap.put(reverseMapKey, reverseMapValue); + } + return Collections.unmodifiableMap(reverseMap); } public String getConnectionConfigName() { @@ -76,10 +96,26 @@ public class RegionMapping implements Serializable { return columnName != null ? columnName : fieldName; } + public String getFieldNameForColumn(String columnName) { + String canonicalColumnName = columnName.toLowerCase(); + String fieldName = null; + if (this.columnToFieldMap != null) { + fieldName = columnToFieldMap.get(canonicalColumnName); + } + return fieldName != null ? fieldName : canonicalColumnName; + } + public Map<String, String> getFieldToColumnMap() { return fieldToColumnMap; } + /** + * For unit tests + */ + Map<String, String> getColumnToFieldMap() { + return this.columnToFieldMap; + } + @Override public boolean equals(Object o) { if (this == o) { 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 65f9240..25a3694 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 @@ -121,9 +121,8 @@ public class SqlHandler { return factory; } - private PdxInstance executeReadStatement(PreparedStatement statement, - List<ColumnValue> columnList, PdxInstanceFactory factory, RegionMapping regionMapping, - String keyColumnName) { + PdxInstance executeReadStatement(PreparedStatement statement, List<ColumnValue> columnList, + PdxInstanceFactory factory, RegionMapping regionMapping, String keyColumnName) { PdxInstance pdxInstance = null; try { setValuesInStatement(statement, columnList); @@ -134,7 +133,7 @@ public class SqlHandler { for (int i = 1; i <= ColumnsNumber; i++) { Object columnValue = resultSet.getObject(i); String columnName = metaData.getColumnName(i); - String fieldName = mapColumnNameToFieldName(columnName); + String fieldName = mapColumnNameToFieldName(columnName, regionMapping); if (regionMapping.isPrimaryKeyInValue() || !keyColumnName.equalsIgnoreCase(columnName)) { factory.writeField(fieldName, columnValue, Object.class); @@ -162,8 +161,8 @@ public class SqlHandler { } } - private String mapColumnNameToFieldName(String columnName) { - return columnName.toLowerCase(); + private String mapColumnNameToFieldName(String columnName, RegionMapping regionMapping) { + return regionMapping.getFieldNameForColumn(columnName); } public <K, V> void write(Region<K, V> region, Operation operation, K key, PdxInstance value) { diff --git a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/RegionMappingTest.java b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/RegionMappingTest.java index 99433e9..992d0c4 100644 --- a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/RegionMappingTest.java +++ b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/RegionMappingTest.java @@ -20,14 +20,19 @@ import java.util.HashMap; import java.util.Map; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.experimental.categories.Category; +import org.junit.rules.ExpectedException; import org.apache.geode.test.junit.categories.UnitTest; @Category(UnitTest.class) public class RegionMappingTest { + @Rule + public ExpectedException expectedException = ExpectedException.none(); + private String name; private String fieldName1; private String columnName1; @@ -48,15 +53,20 @@ public class RegionMappingTest { fieldMap = new HashMap<>(); - mapping = new RegionMapping(null, null, null, null, false, null); } @Test public void initiatedWithNullValues() { + mapping = new RegionMapping(null, null, null, null, false, null); assertThat(mapping.getTableName()).isNull(); assertThat(mapping.getRegionName()).isNull(); assertThat(mapping.getConnectionConfigName()).isNull(); assertThat(mapping.getPdxClassName()).isNull(); + assertThat(mapping.getFieldToColumnMap()).isNull(); + assertThat(mapping.getColumnToFieldMap()).isNull(); + assertThat(mapping.getRegionToTableName()).isNull(); + assertThat(mapping.getColumnNameForField("fieldName")).isEqualTo("fieldName"); + assertThat(mapping.getFieldNameForColumn("columnName")).isEqualTo("columnname"); } @Test @@ -64,6 +74,16 @@ public class RegionMappingTest { mapping = new RegionMapping(null, null, name, null, false, null); assertThat(mapping.getTableName()).isEqualTo(name); + assertThat(mapping.getRegionToTableName()).isEqualTo(name); + } + + @Test + public void hasCorrectTableNameWhenRegionNameIsSet() { + mapping = new RegionMapping("regionName", null, "tableName", null, false, null); + + assertThat(mapping.getRegionName()).isEqualTo("regionName"); + assertThat(mapping.getTableName()).isEqualTo("tableName"); + assertThat(mapping.getRegionToTableName()).isEqualTo("tableName"); } @Test @@ -71,6 +91,7 @@ public class RegionMappingTest { mapping = new RegionMapping(name, null, null, null, false, null); assertThat(mapping.getRegionName()).isEqualTo(name); + assertThat(mapping.getRegionToTableName()).isEqualTo(name); } @Test @@ -104,6 +125,15 @@ public class RegionMappingTest { } @Test + public void returnsColumnNameIfFieldNotMapped() { + fieldMap.put("otherField", "column"); + + mapping = new RegionMapping(null, null, null, null, true, fieldMap); + + assertThat(mapping.getFieldNameForColumn("columnName")).isEqualTo("columnname"); + } + + @Test public void returnsMappedColumnNameForField() { fieldMap.put(fieldName1, columnName1); @@ -113,6 +143,15 @@ public class RegionMappingTest { } @Test + public void returnsMappedFieldNameForColumn() { + fieldMap.put(fieldName1, columnName1); + + mapping = new RegionMapping(null, null, null, null, true, fieldMap); + + assertThat(mapping.getFieldNameForColumn(columnName1)).isEqualTo(fieldName1); + } + + @Test public void returnsAllMappings() { fieldMap.put(fieldName1, columnName1); fieldMap.put(fieldName2, columnName2); @@ -123,5 +162,82 @@ public class RegionMappingTest { assertThat(mapping.getFieldToColumnMap()).containsOnlyKeys(fieldName1, fieldName2); assertThat(mapping.getFieldToColumnMap()).containsEntry(fieldName1, columnName1) .containsEntry(fieldName2, columnName2); + assertThat(mapping.getColumnToFieldMap().size()).isEqualTo(2); + assertThat(mapping.getColumnToFieldMap()).containsOnlyKeys(columnName1.toLowerCase(), + columnName2.toLowerCase()); + assertThat(mapping.getColumnToFieldMap()).containsEntry(columnName1.toLowerCase(), fieldName1) + .containsEntry(columnName2.toLowerCase(), fieldName2); + } + + @Test + public void regionMappingFailsForInvalidFieldToColumnMapping() { + fieldMap.put(fieldName1, columnName1); + fieldMap.put(fieldName2, columnName1); + expectedException.expect(IllegalArgumentException.class); + new RegionMapping(null, null, null, null, true, fieldMap); } + + @Test + public void verifyTwoNonDefaultInstancesAreEqual() { + fieldMap.put(fieldName1, columnName1); + fieldMap.put(fieldName2, columnName2); + RegionMapping rm1 = new RegionMapping("regionName", "pdxClassName", "tableName", + "connectionName", true, fieldMap); + RegionMapping rm2 = new RegionMapping("regionName", "pdxClassName", "tableName", + "connectionName", true, fieldMap); + assertThat(rm1).isEqualTo(rm2); + } + + @Test + public void verifyTwoDefaultInstancesAreEqual() { + RegionMapping rm1 = new RegionMapping("regionName", null, null, "connectionName", false, null); + RegionMapping rm2 = new RegionMapping("regionName", null, null, "connectionName", false, null); + assertThat(rm1).isEqualTo(rm2); + } + + @Test + public void verifyTwoSimiliarInstancesAreNotEqual() { + fieldMap.put(fieldName1, columnName1); + fieldMap.put(fieldName2, columnName2); + RegionMapping rm1 = new RegionMapping("regionName", "pdxClassName", "tableName", + "connectionName", true, fieldMap); + RegionMapping rm2 = + new RegionMapping("regionName", "pdxClassName", "tableName", "connectionName", true, null); + assertThat(rm1).isNotEqualTo(rm2); + } + + + @Test + public void verifyTwoInstancesThatAreEqualHaveSameHashCode() { + fieldMap.put(fieldName1, columnName1); + fieldMap.put(fieldName2, columnName2); + RegionMapping rm1 = new RegionMapping("regionName", "pdxClassName", "tableName", + "connectionName", true, fieldMap); + RegionMapping rm2 = new RegionMapping("regionName", "pdxClassName", "tableName", + "connectionName", true, fieldMap); + assertThat(rm1.hashCode()).isEqualTo(rm2.hashCode()); + } + + @Test + public void verifyThatMappingIsEqualToItself() { + mapping = new RegionMapping(null, null, null, null, false, null); + boolean result = mapping.equals(mapping); + assertThat(mapping.hashCode()).isEqualTo(mapping.hashCode()); + assertThat(result).isTrue(); + } + + @Test + public void verifyThatNullIsNotEqual() { + mapping = new RegionMapping(null, null, null, null, false, null); + boolean result = mapping.equals(null); + assertThat(result).isFalse(); + } + + @Test + public void verifyOtherClassIsNotEqual() { + mapping = new RegionMapping(null, null, null, null, false, null); + boolean result = mapping.equals("not equal"); + assertThat(result).isFalse(); + } + } 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 e915a4e..afe8988 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 @@ -33,6 +33,7 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -171,11 +172,13 @@ public class SqlHandlerTest { PdxInstanceFactory factory = mock(PdxInstanceFactory.class); when(cache.createPdxInstanceFactory(anyString(), anyBoolean())).thenReturn(factory); - String filedName1 = COLUMN_NAME_1.toLowerCase(); - String filedName2 = COLUMN_NAME_2.toLowerCase(); + String fieldName1 = COLUMN_NAME_1.toLowerCase(); + String fieldName2 = COLUMN_NAME_2.toLowerCase(); + when(regionMapping.getFieldNameForColumn(COLUMN_NAME_1)).thenReturn(fieldName1); + when(regionMapping.getFieldNameForColumn(COLUMN_NAME_2)).thenReturn(fieldName2); handler.read(region, new Object()); - verify(factory).writeField(filedName1, COLUMN_VALUE_1, Object.class); - verify(factory).writeField(filedName2, COLUMN_VALUE_2, Object.class); + verify(factory).writeField(fieldName1, COLUMN_VALUE_1, Object.class); + verify(factory).writeField(fieldName2, COLUMN_VALUE_2, Object.class); verify(factory).create(); } @@ -191,6 +194,7 @@ public class SqlHandlerTest { when(cache.createPdxInstanceFactory(anyString(), anyBoolean())).thenReturn(factory); String fieldName2 = COLUMN_NAME_2.toLowerCase(); + when(regionMapping.getFieldNameForColumn(COLUMN_NAME_2)).thenReturn(fieldName2); handler.read(region, new Object()); verify(factory).writeField(fieldName2, COLUMN_VALUE_2, Object.class); verify(factory, times(1)).writeField(any(), any(), any()); @@ -420,6 +424,28 @@ public class SqlHandlerTest { assertThat(columnValueList.get(0).getColumnName()).isEqualTo(KEY_COLUMN); } + @Test + public void usesMappedPdxFieldNameWhenReading() throws Exception { + ResultSet result = mock(ResultSet.class); + setupResultSet(result); + when(result.next()).thenReturn(true).thenReturn(false); + when(statement.executeQuery()).thenReturn(result); + + PdxInstanceFactory factory = mock(PdxInstanceFactory.class); + when(cache.createPdxInstanceFactory(anyString(), anyBoolean())).thenReturn(factory); + + List<ColumnValue> columnList = new ArrayList<>(); + + String fieldName1 = "pdxFieldName1"; + String fieldName2 = "pdxFieldName2"; + when(regionMapping.getFieldNameForColumn(COLUMN_NAME_1)).thenReturn(fieldName1); + when(regionMapping.getFieldNameForColumn(COLUMN_NAME_2)).thenReturn(fieldName2); + handler.executeReadStatement(statement, columnList, factory, regionMapping, "keyColumn"); + verify(factory).writeField(fieldName1, COLUMN_VALUE_1, Object.class); + verify(factory).writeField(fieldName2, COLUMN_VALUE_2, Object.class); + verify(factory).create(); + } + private ResultSet getPrimaryKeysMetaData() throws SQLException { DatabaseMetaData metadata = mock(DatabaseMetaData.class); ResultSet resultSet = mock(ResultSet.class); @@ -443,4 +469,5 @@ public class SqlHandlerTest { .isInstanceOf(IllegalStateException.class).hasMessage("Could not connect to fake:url"); } + } -- To stop receiving notification emails like this one, please contact "[email protected]" <[email protected]>.
