TableMetadataChecker { public void ensureCopyingPossible(String sourceTable, String destinationTable) { Map<String, ColumnMetadata> sourceMetadataMap = getMetadata(sourceTable); Map<String, ColumnMetadata> destMetadataMap = getMetadata(destinationTable); if (destMetadataMap.size() < sourceMetadataMap.size()) { throw new IllegalArgumentException(format("Source table %s has more columns than destination table %s", sourceTable, destinationTable)); } Set<String> sourceKeySet = sourceMetadataMap.keySet(); Set<String> destKeySet = destMetadataMap.keySet(); if (!destKeySet.containsAll(sourceKeySet)) { Set<String> missingColumns = new LinkedHashSet<>(sourceKeySet); missingColumns.removeAll(destKeySet); throw new IllegalArgumentException(format("Destination table %s is missing columns %s that are present in source table %s", destinationTable, missingColumns, sourceTable)); } for (Entry<String, ColumnMetadata> entry : sourceMetadataMap.entrySet()) { ColumnMetadata sourceMetadata = entry.getValue(); ColumnMetadata destMetadata = destMetadataMap.get(entry.getKey()); if (!sourceMetadata.typeName.equals(destMetadata.typeName)) { throw new IllegalArgumentException(format( "Source column %s.%s has type %s and destination column %s.%s has mismatching type %s", sourceTable, sourceMetadata.columnName, sourceMetadata.typeName, destinationTable, destMetadata.columnName, destMetadata.typeName)); } if (sourceMetadata.size > destMetadata.size) { throw new IllegalArgumentException(format("Source column %s.%s has size %s and destination column %s.%s smaller size %s", sourceTable, sourceMetadata.columnName, sourceMetadata.size, destinationTable, destMetadata.columnName, destMetadata.size)); } } } @Inject  TableMetadataChecker(@NFlow JdbcTemplate jdbcTemplate); void ensureCopyingPossible(String sourceTable, String destinationTable);  }
@Test public void identicalTableIsValid() { tableMetadataChecker.ensureCopyingPossible("base", "identical"); }
@Test public void tableIsValidWithItself() { tableMetadataChecker.ensureCopyingPossible("base", "base"); }
@Test public void destinationWithExtraColumnsIsValid() { tableMetadataChecker.ensureCopyingPossible("base", "more_columns"); }
@Test public void destinationWithLargerColumnIsValid() { tableMetadataChecker.ensureCopyingPossible("base", "larger_size"); }
@Test public void destinationWithFewerColumnsIsInvalid() { IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () -> tableMetadataChecker.ensureCopyingPossible("base", "fewer_columns")); assertThat(thrown.getMessage(), containsString("Source table base has more columns than destination table fewer_columns")); }
@Test public void destinationWithMissingColumnsIsInvalid() { IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () -> tableMetadataChecker.ensureCopyingPossible("base", "wrong_columns")); assertThat(thrown.getMessage(), containsString("Destination table wrong_columns is missing columns [TEXT2] that are present in source table base")); }
@Test public void destinationWithWrongTypeIsInvalid() { IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () -> tableMetadataChecker.ensureCopyingPossible("base", "wrong_type")); assertThat(thrown.getMessage(), containsString("Source column base.TIME1 has type TIME and destination column wrong_type.TIME1 has mismatching type INTEGER")); }
@Test public void destinationWithSmallerColumnIsInvalid() { IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () -> tableMetadataChecker.ensureCopyingPossible("base", "smaller_size")); assertThat(thrown.getMessage(), containsString("Source column base.TEXT2 has size 30 and destination column smaller_size.TEXT2 smaller size 25")); }