/**
* DataCleaner (community edition)
* Copyright (C) 2014 Neopost - Customer Information Management
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.datacleaner.beans.writers;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import java.io.File;
import java.util.Arrays;
import java.util.Set;
import org.apache.metamodel.UpdateableDataContext;
import org.apache.metamodel.data.DataSet;
import org.apache.metamodel.schema.ColumnType;
import org.apache.metamodel.schema.Table;
import org.apache.metamodel.util.FileHelper;
import org.datacleaner.api.ComponentContext;
import org.datacleaner.api.InputColumn;
import org.datacleaner.connection.DatastoreConnection;
import org.datacleaner.connection.FileDatastore;
import org.datacleaner.connection.PojoDatastore;
import org.datacleaner.connection.UpdateableDatastore;
import org.datacleaner.connection.UpdateableDatastoreConnection;
import org.datacleaner.data.MockInputColumn;
import org.datacleaner.data.MockInputRow;
import org.datacleaner.descriptors.AnalyzerDescriptor;
import org.datacleaner.descriptors.Descriptors;
import org.datacleaner.descriptors.MetricDescriptor;
import org.easymock.EasyMock;
import org.junit.Before;
import org.junit.Test;
import org.junit.rules.ExpectedException;
public class DeleteFromTableAnalyzerTest {
private static final String TEST_TABLE_NAME = "test_table";
private static final String VARCHAR_COLUMN_NAME = "foo";
private static final String INTEGER_COLUMN_NAME = "bar";
private static final String VARCHAR_COLUMN_VALUE = "StringValue";
private static final int INTEGER_COLUMN_VALUE = 1;
public ExpectedException expectedException = ExpectedException.none();
private UpdateableDatastore updateableDatastore;
@Before
public void setUp() throws Exception {
updateableDatastore = new PojoDatastore("my datastore");
final UpdateableDatastoreConnection con = updateableDatastore.openConnection();
final UpdateableDataContext dc = con.getUpdateableDataContext();
if (dc.getDefaultSchema().getTableByName(TEST_TABLE_NAME) == null) {
dc.executeUpdate(cb -> {
cb.createTable(dc.getDefaultSchema(), TEST_TABLE_NAME).withColumn(VARCHAR_COLUMN_NAME)
.ofType(ColumnType.VARCHAR).withColumn(INTEGER_COLUMN_NAME).ofType(ColumnType.INTEGER)
.execute();
cb.insertInto(TEST_TABLE_NAME).value(VARCHAR_COLUMN_NAME, VARCHAR_COLUMN_VALUE)
.value(INTEGER_COLUMN_NAME, INTEGER_COLUMN_VALUE).execute();
});
}
con.close();
}
@Test
public void shouldReturnTheCorrectMetricsFromDescriptor() throws Exception {
final AnalyzerDescriptor<?> descriptor = Descriptors.ofAnalyzer(DeleteFromTableAnalyzer.class);
final Set<MetricDescriptor> metrics = descriptor.getResultMetrics();
assertThat(metrics.size(), is(3));
final WriteDataResult result = new WriteDataResultImpl(10, 5, null, null, null);
assertThat(descriptor.getResultMetric("Inserts").getValue(result, null).intValue(), is(10));
assertThat(descriptor.getResultMetric("Updates").getValue(result, null).intValue(), is(5));
assertThat(descriptor.getResultMetric("Errornous rows").getValue(result, null).intValue(), is(0));
}
@Test
public void shouldThrowExceptionForIncorrectErrorHandlingFile() throws Exception {
expectedException.expect(IllegalStateException.class);
expectedException.expectMessage("Error log file does not have required column header: foo");
final DeleteFromTableAnalyzer deleteFromTable = new DeleteFromTableAnalyzer();
deleteFromTable.datastore = updateableDatastore;
deleteFromTable.tableName = "test_table";
deleteFromTable.errorHandlingOption = ErrorHandlingOption.SAVE_TO_FILE;
deleteFromTable.errorLogFile = new File("src/test/resources/invalid-error-handling-file.csv");
deleteFromTable.conditionColumnNames = new String[] { "col1", "col2" };
final InputColumn<Object> col1 = new MockInputColumn<>("in1", Object.class);
final InputColumn<Object> col2 = new MockInputColumn<>("in2", Object.class);
deleteFromTable.conditionValues = new InputColumn[] { col1, col2 };
deleteFromTable.validate();
}
@Test
public void shouldCorrectlyAppendErrorHandlingInfo() throws Exception {
final File file = new File("target/valid-error-handling-file-for-update.csv.csv");
FileHelper.copy(new File("src/test/resources/valid-error-handling-file-for-update.csv"), file);
final DeleteFromTableAnalyzer deleteFromTable = new DeleteFromTableAnalyzer();
deleteFromTable.datastore = updateableDatastore;
deleteFromTable.tableName = TEST_TABLE_NAME;
deleteFromTable.errorHandlingOption = ErrorHandlingOption.SAVE_TO_FILE;
deleteFromTable.errorLogFile = file;
deleteFromTable.conditionColumnNames = new String[] { INTEGER_COLUMN_NAME };
final InputColumn<Object> inputColumn = new MockInputColumn<>(INTEGER_COLUMN_NAME, Object.class);
deleteFromTable.conditionValues = new InputColumn[] { inputColumn };
deleteFromTable.validate();
deleteFromTable.init();
deleteFromTable.run(new MockInputRow().put(inputColumn, "blabla"), 1);
final WriteDataResult result = deleteFromTable.getResult();
assertThat(result.getUpdatesCount(), is(0));
assertThat(result.getErrorRowCount(), is(1));
assertThat(FileHelper.readFileAsString(file).replaceAll("\n", "\\[newline\\]"),
is(equalTo("foo,bar,extra1,update_table_error_message,extra2[newline]" + //
"f,b,e1,m,e2[newline]" + //
"\"\",\"\",\"\",\"Could not convert blabla to number\",\"\"")));//
}
@Test
public void shouldSuccessFullyDeleteRowFromTable() throws Exception {
final DeleteFromTableAnalyzer deleteFromTable = new DeleteFromTableAnalyzer();
deleteFromTable.datastore = updateableDatastore;
deleteFromTable.tableName = TEST_TABLE_NAME;
deleteFromTable.conditionColumnNames = new String[] { VARCHAR_COLUMN_NAME, INTEGER_COLUMN_NAME };
deleteFromTable.errorHandlingOption = ErrorHandlingOption.SAVE_TO_FILE;
deleteFromTable.errorLogFile = null;
deleteFromTable._componentContext = EasyMock.createMock(ComponentContext.class);
final InputColumn<Object> col1 = new MockInputColumn<>(VARCHAR_COLUMN_NAME, Object.class);
final InputColumn<Object> col2 = new MockInputColumn<>("in2", Object.class);
deleteFromTable.conditionValues = new InputColumn[] { col1, col2 };
deleteFromTable.validate();
deleteFromTable.init();
deleteFromTable.run(new MockInputRow().put(col1, VARCHAR_COLUMN_VALUE), 1);
final WriteDataResult result = deleteFromTable.getResult();
assertThat(result.getUpdatesCount(), is(1));
assertThat(result.getErrorRowCount(), is(0));
final FileDatastore errorDatastore = result.getErrorDatastore();
final DatastoreConnection con = errorDatastore.openConnection();
final Table table = con.getDataContext().getDefaultSchema().getTables()[0];
assertThat(Arrays.toString(table.getColumnNames()), is(equalTo("[foo, bar, update_table_error_message]")));
final DataSet ds = con.getDataContext().query().from(table).select(table.getColumns()).execute();
assertThat(ds.next(), is(false));
ds.close();
con.close();
}
}