This is an automated email from the ASF dual-hosted git repository. dschneider pushed a commit to branch feature/GEODE-6194 in repository https://gitbox.apache.org/repos/asf/geode.git
commit 0aba1e0478408bde4d3704ec66e1dde94d1036ca Author: bross <[email protected]> AuthorDate: Wed Dec 12 16:48:58 2018 -0800 WIP --- .../TableMetaDataManagerIntegrationTest.java | 6 +- .../geode/connectors/jdbc/internal/SqlHandler.java | 4 +- .../connectors/jdbc/internal/TableMetaData.java | 11 ++-- .../jdbc/internal/TableMetaDataManager.java | 50 ++++++++------- .../jdbc/internal/TableMetaDataView.java | 4 +- .../connectors/jdbc/internal/SqlHandlerTest.java | 2 +- .../jdbc/internal/SqlToPdxInstanceCreatorTest.java | 5 +- .../jdbc/internal/TableMetaDataManagerTest.java | 73 +++++++++++++++------- 8 files changed, 95 insertions(+), 60 deletions(-) diff --git a/geode-connectors/src/acceptanceTest/java/org/apache/geode/connectors/jdbc/internal/TableMetaDataManagerIntegrationTest.java b/geode-connectors/src/acceptanceTest/java/org/apache/geode/connectors/jdbc/internal/TableMetaDataManagerIntegrationTest.java index 399229c..b86eb9f 100644 --- a/geode-connectors/src/acceptanceTest/java/org/apache/geode/connectors/jdbc/internal/TableMetaDataManagerIntegrationTest.java +++ b/geode-connectors/src/acceptanceTest/java/org/apache/geode/connectors/jdbc/internal/TableMetaDataManagerIntegrationTest.java @@ -85,7 +85,7 @@ public abstract class TableMetaDataManagerIntegrationTest { createTable(); TableMetaDataView metaData = manager.getTableMetaDataView(connection, REGION_TABLE_NAME, null); - String keyColumnName = metaData.getKeyColumnName(); + String keyColumnName = metaData.getKeyColumnNames(); assertThat(keyColumnName).isEqualTo("id"); } @@ -96,7 +96,7 @@ public abstract class TableMetaDataManagerIntegrationTest { TableMetaDataView metaData = manager.getTableMetaDataView(connection, REGION_TABLE_NAME, "nonprimaryid"); - String keyColumnName = metaData.getKeyColumnName(); + String keyColumnName = metaData.getKeyColumnNames(); assertThat(keyColumnName).isEqualTo("nonprimaryid"); } @@ -107,7 +107,7 @@ public abstract class TableMetaDataManagerIntegrationTest { TableMetaDataView metaData = manager.getTableMetaDataView(connection, REGION_TABLE_NAME, "NonPrimaryId"); - String keyColumnName = metaData.getKeyColumnName(); + String keyColumnName = metaData.getKeyColumnNames(); assertThat(keyColumnName).isEqualTo("NonPrimaryId"); } 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 9335d03..06baf64 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 @@ -230,7 +230,7 @@ public class SqlHandler { <K> EntryColumnData getEntryColumnData(TableMetaDataView tableMetaData, RegionMapping regionMapping, K key, PdxInstance value, Operation operation) { - String keyColumnName = tableMetaData.getKeyColumnName(); + String keyColumnName = "ERROR";//tableMetaData.getKeyColumnNames(); ColumnData keyColumnData = new ColumnData(keyColumnName, key, tableMetaData.getColumnDataType(keyColumnName)); List<ColumnData> valueColumnData = null; @@ -247,7 +247,7 @@ public class SqlHandler { List<ColumnData> result = new ArrayList<>(); for (String fieldName : value.getFieldNames()) { String columnName = regionMapping.getColumnNameForField(fieldName, tableMetaData); - if (tableMetaData.getKeyColumnName().equals(columnName)) { + if (tableMetaData.getKeyColumnNames().equals(columnName)) { continue; } ColumnData columnData = new ColumnData(columnName, value.getField(fieldName), diff --git a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/TableMetaData.java b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/TableMetaData.java index 301e8b1..904acba 100644 --- a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/TableMetaData.java +++ b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/TableMetaData.java @@ -17,18 +17,19 @@ package org.apache.geode.connectors.jdbc.internal; import java.util.HashMap; +import java.util.List; import java.util.Set; public class TableMetaData implements TableMetaDataView { private final String tableName; - private final String keyColumnName; + private final List<String> keyColumnNames; private final HashMap<String, Integer> columnNameToTypeMap; private final String identifierQuoteString; - public TableMetaData(String tableName, String keyColumnName, String quoteString) { + public TableMetaData(String tableName, List<String> keyColumnNames, String quoteString) { this.tableName = tableName; - this.keyColumnName = keyColumnName; + this.keyColumnNames = keyColumnNames; this.columnNameToTypeMap = new HashMap<>(); this.identifierQuoteString = quoteString; } @@ -39,8 +40,8 @@ public class TableMetaData implements TableMetaDataView { } @Override - public String getKeyColumnName() { - return this.keyColumnName; + public List<String> getKeyColumnNames() { + return this.keyColumnNames; } @Override diff --git a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/TableMetaDataManager.java b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/TableMetaDataManager.java index a454d3e..bd6f779 100644 --- a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/TableMetaDataManager.java +++ b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/TableMetaDataManager.java @@ -14,6 +14,9 @@ */ package org.apache.geode.connectors.jdbc.internal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.ResultSet; @@ -47,12 +50,12 @@ public class TableMetaDataManager { DatabaseMetaData metaData = connection.getMetaData(); try (ResultSet tables = metaData.getTables(null, null, "%", null)) { String realTableName = getTableNameFromMetaData(tableName, tables); - String key = getPrimaryKeyColumnNameFromMetaData(realTableName, metaData, ids); + List<String> keys = getPrimaryKeyColumnNamesFromMetaData(realTableName, metaData, ids); String quoteString = metaData.getIdentifierQuoteString(); if (quoteString == null) { quoteString = ""; } - result = new TableMetaData(realTableName, key, quoteString); + result = new TableMetaData(realTableName, keys, quoteString); getDataTypesFromMetaData(realTableName, metaData, result); } } catch (SQLException e) { @@ -85,28 +88,29 @@ public class TableMetaDataManager { return result; } - private String getPrimaryKeyColumnNameFromMetaData(String tableName, DatabaseMetaData metaData, - String ids) + private List<String> getPrimaryKeyColumnNamesFromMetaData(String tableName, DatabaseMetaData metaData, + String ids) throws SQLException { + List<String> keys = new ArrayList<>(); + if (ids != null && !ids.isEmpty()) { - if (!doesColumnExistInTable(tableName, metaData, ids)) { - throw new JdbcConnectorException( - "The table " + tableName + " does not have a column named " + ids); - } - return ids; - } - try (ResultSet primaryKeys = metaData.getPrimaryKeys(null, null, tableName)) { - if (!primaryKeys.next()) { - throw new JdbcConnectorException( - "The table " + tableName + " does not have a primary key column."); + keys.addAll(Arrays.asList(ids.split(","))); + for( String key : keys) { + checkColumnExistsInTable(tableName, metaData, key); } - String key = primaryKeys.getString("COLUMN_NAME"); - if (primaryKeys.next()) { - throw new JdbcConnectorException( - "The table " + tableName + " has more than one primary key column."); + } else { + try (ResultSet primaryKeys = metaData.getPrimaryKeys(null, null, tableName)) { + while(primaryKeys.next()) { + String key = primaryKeys.getString("COLUMN_NAME"); + keys.add(key); + } + if (keys.isEmpty()) { + throw new JdbcConnectorException( + "The table " + tableName + " does not have a primary key column."); + } } - return key; } + return keys; } private void getDataTypesFromMetaData(String tableName, DatabaseMetaData metaData, @@ -120,14 +124,14 @@ public class TableMetaDataManager { } } - private boolean doesColumnExistInTable(String tableName, DatabaseMetaData metaData, + private void checkColumnExistsInTable(String tableName, DatabaseMetaData metaData, String columnName) throws SQLException { int caseInsensitiveMatches = 0; try (ResultSet columnData = metaData.getColumns(null, null, tableName, "%")) { while (columnData.next()) { String realColumnName = columnData.getString("COLUMN_NAME"); if (columnName.equals(realColumnName)) { - return true; + return; } else if (columnName.equalsIgnoreCase(realColumnName)) { caseInsensitiveMatches++; } @@ -136,7 +140,9 @@ public class TableMetaDataManager { if (caseInsensitiveMatches > 1) { throw new JdbcConnectorException( "The table " + tableName + " has more than one column that matches " + columnName); + } else if(caseInsensitiveMatches == 0) { + throw new JdbcConnectorException( + "The table " + tableName + " does not have a column named " + columnName); } - return caseInsensitiveMatches != 0; } } diff --git a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/TableMetaDataView.java b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/TableMetaDataView.java index 189d794..3c18dd4 100644 --- a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/TableMetaDataView.java +++ b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/TableMetaDataView.java @@ -16,12 +16,14 @@ */ package org.apache.geode.connectors.jdbc.internal; + +import java.util.List; import java.util.Set; public interface TableMetaDataView { String getTableName(); - String getKeyColumnName(); + List<String> getKeyColumnNames(); int getColumnDataType(String columnName); 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 d93743f..edb2604 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 @@ -90,7 +90,7 @@ public class SqlHandlerTest { tableMetaDataManager = mock(TableMetaDataManager.class); tableMetaDataView = mock(TableMetaDataView.class); when(tableMetaDataView.getTableName()).thenReturn(TABLE_NAME); - when(tableMetaDataView.getKeyColumnName()).thenReturn(KEY_COLUMN); + when(tableMetaDataView.getKeyColumnNames()).thenReturn(Arrays.asList(KEY_COLUMN)); final String IDS = "ids"; when(tableMetaDataManager.getTableMetaDataView(connection, TABLE_NAME, IDS)) .thenReturn(tableMetaDataView); 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 22fe169..df042df 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 @@ -30,6 +30,7 @@ import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Types; +import java.util.Arrays; import java.util.Date; import junitparams.JUnitParamsRunner; @@ -75,7 +76,7 @@ public class SqlToPdxInstanceCreatorTest { regionMapping = mock(RegionMapping.class); resultSet = mock(ResultSet.class); tableMetaDataView = mock(TableMetaDataView.class); - when(tableMetaDataView.getKeyColumnName()).thenReturn(KEY_COLUMN); + when(tableMetaDataView.getKeyColumnNames()).thenReturn(Arrays.asList(KEY_COLUMN)); } @Test @@ -109,7 +110,7 @@ public class SqlToPdxInstanceCreatorTest { when(regionMapping.getFieldNameForColumn(eq(COLUMN_NAME_2), any())) .thenReturn(PDX_FIELD_NAME_2); tableMetaDataView = mock(TableMetaDataView.class); - when(tableMetaDataView.getKeyColumnName()).thenReturn(COLUMN_NAME_1); + when(tableMetaDataView.getKeyColumnNames()).thenReturn(Arrays.asList(COLUMN_NAME_1)); TypeRegistry pdxTypeRegistry = mock(TypeRegistry.class); when(cache.getPdxRegistry()).thenReturn(pdxTypeRegistry); String pdxClassName = "myPdxClassName"; diff --git a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/TableMetaDataManagerTest.java b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/TableMetaDataManagerTest.java index 91e8a73..b159b0f 100644 --- a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/TableMetaDataManagerTest.java +++ b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/TableMetaDataManagerTest.java @@ -39,6 +39,7 @@ import org.apache.geode.connectors.jdbc.JdbcConnectorException; public class TableMetaDataManagerTest { private static final String TABLE_NAME = "testTable"; private static final String KEY_COLUMN = "keyColumn"; + private static final String KEY_COLUMN2 = "keyColumn2"; private TableMetaDataManager tableMetaDataManager; private Connection connection; @@ -69,14 +70,26 @@ public class TableMetaDataManagerTest { when(primaryKeysResultSet.next()).thenReturn(true).thenReturn(false); TableMetaDataView data = tableMetaDataManager.getTableMetaDataView(connection, TABLE_NAME, ""); - assertThat(data.getKeyColumnName()).isEqualTo(KEY_COLUMN); + + assertThat(data.getKeyColumnNames()).isEqualTo(Arrays.asList(KEY_COLUMN)); verify(connection).getMetaData(); } @Test + public void returnsCompositePrimaryKeyColumnNames() throws Exception { + setupCompositePrimaryKeysMetaData(); + + TableMetaDataView data = tableMetaDataManager.getTableMetaDataView(connection, TABLE_NAME, ""); + + assertThat(data.getKeyColumnNames()).isEqualTo(Arrays.asList(KEY_COLUMN, KEY_COLUMN2)); + verify(connection).getMetaData(); + } + + + + @Test public void givenNoColumnsAndNonNullIdsThenExpectException() throws Exception { - when(tablesResultSet.next()).thenReturn(true).thenReturn(false); - when(tablesResultSet.getString("TABLE_NAME")).thenReturn(TABLE_NAME); + setupTableMetaData(); when(columnResultSet.next()).thenReturn(false); assertThatThrownBy( @@ -87,8 +100,7 @@ public class TableMetaDataManagerTest { @Test public void givenOneColumnAndNonNullIdsThatDoesNotMatchThenExpectException() throws Exception { - when(tablesResultSet.next()).thenReturn(true).thenReturn(false); - when(tablesResultSet.getString("TABLE_NAME")).thenReturn(TABLE_NAME); + setupTableMetaData(); when(columnResultSet.next()).thenReturn(true).thenReturn(false); when(columnResultSet.getString("COLUMN_NAME")).thenReturn("existingColumn"); @@ -101,8 +113,7 @@ public class TableMetaDataManagerTest { @Test public void givenTwoColumnsAndNonNullIdsThatDoesNotExactlyMatchThenExpectException() throws Exception { - when(tablesResultSet.next()).thenReturn(true).thenReturn(false); - when(tablesResultSet.getString("TABLE_NAME")).thenReturn(TABLE_NAME); + setupTableMetaData(); when(columnResultSet.next()).thenReturn(true).thenReturn(true).thenReturn(false); when(columnResultSet.getString("COLUMN_NAME")).thenReturn("nonexistentid") .thenReturn("NONEXISTENTID"); @@ -116,8 +127,7 @@ public class TableMetaDataManagerTest { @Test public void givenThreeColumnsAndNonNullIdsThatDoesExactlyMatchThenKeyColumnNameIsReturned() throws Exception { - when(tablesResultSet.next()).thenReturn(true).thenReturn(false); - when(tablesResultSet.getString("TABLE_NAME")).thenReturn(TABLE_NAME); + setupTableMetaData(); when(columnResultSet.next()).thenReturn(true).thenReturn(true).thenReturn(true) .thenReturn(false); when(columnResultSet.getString("COLUMN_NAME")).thenReturn("existentid").thenReturn("EXISTENTID") @@ -126,21 +136,35 @@ public class TableMetaDataManagerTest { TableMetaDataView data = tableMetaDataManager.getTableMetaDataView(connection, TABLE_NAME, "ExistentId"); - assertThat(data.getKeyColumnName()).isEqualTo("ExistentId"); + assertThat(data.getKeyColumnNames()).isEqualTo(Arrays.asList("ExistentId")); + } + + @Test + public void givenFourColumnsAndCompositeIdsThenOnlyKeyColumnNamesAreReturned() + throws Exception { + setupTableMetaData(); + when(columnResultSet.next()).thenReturn(true).thenReturn(true).thenReturn(true) + .thenReturn(true).thenReturn(false); + when(columnResultSet.getString("COLUMN_NAME")).thenReturn("LeadingNonKeyColumn").thenReturn(KEY_COLUMN).thenReturn(KEY_COLUMN2) + .thenReturn("NonKeyColumn"); + + TableMetaDataView data = + tableMetaDataManager.getTableMetaDataView(connection, TABLE_NAME, KEY_COLUMN + "," + KEY_COLUMN2); + + assertThat(data.getKeyColumnNames()).isEqualTo(Arrays.asList(KEY_COLUMN, KEY_COLUMN2)); } @Test public void givenColumnAndNonNullIdsThatDoesInexactlyMatchThenKeyColumnNameIsReturned() throws Exception { - when(tablesResultSet.next()).thenReturn(true).thenReturn(false); - when(tablesResultSet.getString("TABLE_NAME")).thenReturn(TABLE_NAME); + setupTableMetaData(); when(columnResultSet.next()).thenReturn(true).thenReturn(false); when(columnResultSet.getString("COLUMN_NAME")).thenReturn("existentid"); TableMetaDataView data = tableMetaDataManager.getTableMetaDataView(connection, TABLE_NAME, "ExistentId"); - assertThat(data.getKeyColumnName()).isEqualTo("ExistentId"); + assertThat(data.getKeyColumnNames()).isEqualTo(Arrays.asList("ExistentId")); } @Test @@ -201,17 +225,6 @@ public class TableMetaDataManagerTest { } @Test - public void throwsExceptionIfTableHasCompositePrimaryKey() throws Exception { - setupPrimaryKeysMetaData(); - when(primaryKeysResultSet.next()).thenReturn(true); - - assertThatThrownBy( - () -> tableMetaDataManager.getTableMetaDataView(connection, TABLE_NAME, null)) - .isInstanceOf(JdbcConnectorException.class) - .hasMessage("The table " + TABLE_NAME + " has more than one primary key column."); - } - - @Test public void returnsExactMatchTableNameWhenTwoTablesHasCaseInsensitiveSameName() throws Exception { setupPrimaryKeysMetaData(); when(primaryKeysResultSet.next()).thenReturn(true).thenReturn(false); @@ -360,7 +373,19 @@ public class TableMetaDataManagerTest { private void setupPrimaryKeysMetaData() throws SQLException { when(primaryKeysResultSet.getString("COLUMN_NAME")).thenReturn(KEY_COLUMN); + setupTableMetaData(); + } + + private void setupCompositePrimaryKeysMetaData() throws SQLException { + when(primaryKeysResultSet.getString("COLUMN_NAME")).thenReturn(KEY_COLUMN).thenReturn(KEY_COLUMN2); + when(primaryKeysResultSet.next()).thenReturn(true).thenReturn(true).thenReturn(false); + setupTableMetaData(); + } + + private void setupTableMetaData() throws SQLException { when(tablesResultSet.next()).thenReturn(true).thenReturn(false); when(tablesResultSet.getString("TABLE_NAME")).thenReturn(TABLE_NAME); } + + }
