org.jumpmind.symmetric.io.data.writer.DatabaseWriterTest.java Source code

Java tutorial

Introduction

Here is the source code for org.jumpmind.symmetric.io.data.writer.DatabaseWriterTest.java

Source

/**
 * Licensed to JumpMind Inc under one or more contributor
 * license agreements.  See the NOTICE file distributed
 * with this work for additional information regarding
 * copyright ownership.  JumpMind Inc licenses this file
 * to you under the GNU General Public License, version 3.0 (GPLv3)
 * (the "License"); you may not use this file except in compliance
 * with the License.
 *
 * You should have received a copy of the GNU General Public License,
 * version 3.0 (GPLv3) along with this library; if not, see
 * <http://www.gnu.org/licenses/>.
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.jumpmind.symmetric.io.data.writer;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.apache.commons.lang.ArrayUtils;
import org.jumpmind.db.DbTestUtils;
import org.jumpmind.db.model.Table;
import org.jumpmind.db.platform.AbstractDatabasePlatform;
import org.jumpmind.db.platform.ase.AseDatabasePlatform;
import org.jumpmind.db.platform.informix.InformixDatabasePlatform;
import org.jumpmind.db.platform.mssql.MsSql2000DatabasePlatform;
import org.jumpmind.db.platform.mssql.MsSql2005DatabasePlatform;
import org.jumpmind.db.platform.mssql.MsSql2008DatabasePlatform;
import org.jumpmind.db.platform.mysql.MySqlDatabasePlatform;
import org.jumpmind.db.platform.oracle.OracleDatabasePlatform;
import org.jumpmind.db.platform.postgresql.PostgreSqlDatabasePlatform;
import org.jumpmind.db.platform.sqlanywhere.SqlAnywhereDatabasePlatform;
import org.jumpmind.symmetric.io.AbstractWriterTest;
import org.jumpmind.symmetric.io.data.CsvData;
import org.jumpmind.symmetric.io.data.DataEventType;
import org.jumpmind.symmetric.io.data.writer.Conflict.DetectConflict;
import org.jumpmind.symmetric.io.data.writer.Conflict.ResolveConflict;
import org.jumpmind.util.CollectionUtils;
import org.jumpmind.util.Statistics;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

public class DatabaseWriterTest extends AbstractWriterTest {

    @BeforeClass
    public static void setup() throws Exception {
        platform = DbTestUtils.createDatabasePlatform(DbTestUtils.ROOT);
        platform.createDatabase(platform.readDatabaseFromXml("/testDatabaseWriter.xml", true), true, false);
    }

    @Before
    public void notExpectingError() {
        setErrorExpected(false);
        writerSettings.setDefaultConflictSetting(new Conflict());
    }

    @Test
    public void testUpdateDetectTimestampNewerWins() {
        Conflict setting = new Conflict();
        setting.setConflictId("unit.test");
        setting.setDetectType(DetectConflict.USE_TIMESTAMP);
        setting.setDetectExpression("time_value");
        setting.setResolveRowOnly(true);
        setting.setResolveChangesOnly(true);
        setting.setResolveType(ResolveConflict.NEWER_WINS);
        writerSettings.setDefaultConflictSetting(setting);

        String id = getNextId();
        String[] originalValues = massageExpectectedResultsForDialect(
                new String[] { id, "string2", "string not null2", "char2", "char not null2",
                        "2007-01-02 03:20:10.000", "2012-03-12 07:00:00.000", "0", "47", "67.89", "-0.0747663" });

        CsvData data = new CsvData(DataEventType.INSERT, originalValues);
        writeData(data, originalValues);

        String[] updateShouldNotBeApplied = CollectionUtils.copyOfRange(originalValues, 0, originalValues.length);
        updateShouldNotBeApplied[2] = "updated string";
        updateShouldNotBeApplied[6] = "2012-03-12 06:00:00.0";
        data = new CsvData(DataEventType.UPDATE, massageExpectectedResultsForDialect(updateShouldNotBeApplied));
        writeData(data, originalValues);

        String[] updateShouldBeApplied = CollectionUtils.copyOfRange(originalValues, 0, originalValues.length);
        updateShouldBeApplied[2] = "string3";
        updateShouldBeApplied[6] = "2012-03-12 08:00:00.000";
        data = new CsvData(DataEventType.UPDATE, massageExpectectedResultsForDialect(updateShouldBeApplied));
        writeData(data, updateShouldBeApplied);

    }

    @Test
    public void testInsertDetectTimestampNewerWins() {
        Conflict setting = new Conflict();
        setting.setConflictId("unit.test");
        setting.setDetectType(DetectConflict.USE_TIMESTAMP);
        setting.setDetectExpression("time_value");
        setting.setResolveRowOnly(true);
        setting.setResolveChangesOnly(false);
        setting.setResolveType(ResolveConflict.NEWER_WINS);
        writerSettings.setDefaultConflictSetting(setting);

        String id = getNextId();
        String[] originalValues = massageExpectectedResultsForDialect(
                new String[] { id, "string2", "string not null2", "char2", "char not null2",
                        "2007-01-02 03:20:10.000", "2012-03-12 07:00:00.000", "0", "47", "67.89", "-0.0747663" });

        CsvData data = new CsvData(DataEventType.INSERT, originalValues);
        writeData(data, originalValues);

        String[] updateShouldNotBeApplied = CollectionUtils.copyOfRange(originalValues, 0, originalValues.length);
        updateShouldNotBeApplied[2] = "updated string";
        updateShouldNotBeApplied[6] = "2012-03-12 06:00:00.0";
        data = new CsvData(DataEventType.INSERT, massageExpectectedResultsForDialect(updateShouldNotBeApplied));
        writeData(data, originalValues);

        String[] updateShouldBeApplied = CollectionUtils.copyOfRange(originalValues, 0, originalValues.length);
        updateShouldBeApplied[2] = "string3";
        updateShouldBeApplied[6] = "2012-03-12 08:00:00.000";
        data = new CsvData(DataEventType.INSERT, massageExpectectedResultsForDialect(updateShouldBeApplied));
        writeData(data, updateShouldBeApplied);
    }

    @Test
    public void testUpdateDetectVersionNewWins() {
        Conflict setting = new Conflict();
        setting.setConflictId("unit.test");
        setting.setDetectType(DetectConflict.USE_VERSION);
        setting.setDetectExpression("integer_value");
        setting.setResolveRowOnly(true);
        setting.setResolveChangesOnly(false);
        setting.setResolveType(ResolveConflict.NEWER_WINS);
        writerSettings.setDefaultConflictSetting(setting);

        String id = getNextId();
        String[] originalValues = massageExpectectedResultsForDialect(
                new String[] { id, "string2", "string not null2", "char2", "char not null2",
                        "2007-01-02 03:20:10.000", "2012-03-12 07:00:00.000", "0", "47", "67.89", "-0.0747663" });

        CsvData data = new CsvData(DataEventType.INSERT, originalValues);
        writeData(data, originalValues);

        String[] updateShouldNotBeApplied = CollectionUtils.copyOfRange(originalValues, 0, originalValues.length);
        updateShouldNotBeApplied[2] = "updated string";
        updateShouldNotBeApplied[8] = "46";
        data = new CsvData(DataEventType.UPDATE, massageExpectectedResultsForDialect(updateShouldNotBeApplied));
        writeData(data, originalValues);

        String[] updateShouldBeApplied = CollectionUtils.copyOfRange(originalValues, 0, originalValues.length);
        updateShouldBeApplied[2] = "string3";
        updateShouldBeApplied[8] = "48";
        data = new CsvData(DataEventType.UPDATE, massageExpectectedResultsForDialect(updateShouldBeApplied));
        writeData(data, updateShouldBeApplied);
    }

    @Test
    public void testUpdateDetectVersionIgnoreBatch() {
        Conflict setting = new Conflict();
        setting.setConflictId("unit.test");
        setting.setDetectType(DetectConflict.USE_VERSION);
        setting.setDetectExpression("integer_value");
        setting.setResolveRowOnly(false);
        setting.setResolveChangesOnly(false);
        setting.setResolveType(ResolveConflict.NEWER_WINS);
        writerSettings.setDefaultConflictSetting(setting);

        String id = getNextId();
        String[] originalValues = massageExpectectedResultsForDialect(
                new String[] { id, "string2", "string not null2", "char2", "char not null2",
                        "2007-01-02 03:20:10.000", "2012-03-12 07:00:00.000", "0", "2", "67.89", "-0.0747663" });

        CsvData data = new CsvData(DataEventType.INSERT, originalValues);
        writeData(data, originalValues);

        long before = countRows(TEST_TABLE);

        String[] updateShouldNotBeApplied = CollectionUtils.copyOfRange(originalValues, 0, originalValues.length);
        updateShouldNotBeApplied[2] = "updated string";
        updateShouldNotBeApplied[8] = "1";
        CsvData update = new CsvData(DataEventType.UPDATE,
                massageExpectectedResultsForDialect(updateShouldNotBeApplied));
        String newId = getNextId();
        CsvData newInsert = new CsvData(DataEventType.INSERT,
                massageExpectectedResultsForDialect(new String[] { newId, "string2", "string not null2", "char2",
                        "char not null2", "2007-01-02 03:20:10.0", "2012-03-12 07:00:00.0", "0", "2", "67.89",
                        "-0.0747663" }));

        writeData(update, newInsert);

        Assert.assertEquals(before, countRows(TEST_TABLE));

    }

    @Test
    public void testUpdateDetectOldDataIgnoreRow() {

    }

    @Test
    public void testUpdateDetectOldDataIgnoreBatch() {

    }

    @Test
    public void testUpdateDetectOldDataManual() {
        Conflict setting = new Conflict();
        setting.setConflictId("unit.test");
        setting.setDetectType(DetectConflict.USE_OLD_DATA);
        setting.setResolveRowOnly(false);
        setting.setResolveChangesOnly(false);
        setting.setResolveType(ResolveConflict.MANUAL);
        writerSettings.setDefaultConflictSetting(setting);

        String origId = getNextId();
        String[] originalValues = massageExpectectedResultsForDialect(
                new String[] { origId, "string2", "changed value", "char2", "char not null2",
                        "2007-01-02 03:20:10.000", "2012-03-12 07:00:00.000", "0", "2", "67.89", "-0.0747663" });

        CsvData data = new CsvData(DataEventType.INSERT, originalValues);
        writeData(data, originalValues);

        String[] oldData = CollectionUtils.copyOfRange(originalValues, 0, originalValues.length);
        oldData[2] = "original value";
        oldData = massageExpectectedResultsForDialect(oldData);

        String[] newData = CollectionUtils.copyOfRange(originalValues, 0, originalValues.length);
        newData[2] = "new value";
        newData = massageExpectectedResultsForDialect(newData);

        CsvData update = new CsvData(DataEventType.UPDATE);
        update.putParsedData(CsvData.ROW_DATA, newData);
        update.putParsedData(CsvData.OLD_DATA, oldData);

        try {
            writeData(update);
            Assert.fail("Should have received a conflict exception");
        } catch (ConflictException ex) {
            Statistics stats = lastDataWriterUsed.getStatistics().values().iterator().next();
            long statementNumber = stats.get(DataWriterStatisticConstants.STATEMENTCOUNT);
            ResolvedData resolvedData = new ResolvedData(statementNumber, update.getCsvData(CsvData.ROW_DATA),
                    false);
            writerSettings.setResolvedData(resolvedData);
            writeData(update);
            Map<String, Object> row = queryForRow(origId);
            Assert.assertNotNull(row);
            Assert.assertEquals(newData[2], row.get("string_required_value"));
        }

    }

    @Test
    public void testUpdateDetectOldDataWithNullManual() {
        Conflict setting = new Conflict();
        setting.setConflictId("unit.test");
        setting.setDetectType(DetectConflict.USE_OLD_DATA);
        setting.setResolveRowOnly(false);
        setting.setResolveChangesOnly(false);
        setting.setResolveType(ResolveConflict.MANUAL);
        writerSettings.setDefaultConflictSetting(setting);

        String origId = getNextId();
        String[] originalValues = massageExpectectedResultsForDialect(
                new String[] { origId, null, "changed value", "char2", "char not null2", "2007-01-02 03:20:10.000",
                        "2012-03-12 07:00:00.000", "0", "2", "67.89", "-0.0747663" });

        CsvData data = new CsvData(DataEventType.INSERT, originalValues);
        writeData(data, originalValues);

        String[] oldData = CollectionUtils.copyOfRange(originalValues, 0, originalValues.length);
        oldData[2] = "original value";
        oldData = massageExpectectedResultsForDialect(oldData);

        String[] newData = CollectionUtils.copyOfRange(originalValues, 0, originalValues.length);
        newData[2] = "new value";
        newData = massageExpectectedResultsForDialect(newData);

        CsvData update = new CsvData(DataEventType.UPDATE);
        update.putParsedData(CsvData.ROW_DATA, newData);
        update.putParsedData(CsvData.OLD_DATA, oldData);

        try {
            writeData(update);
            Assert.fail("Should have received a conflict exception");
        } catch (ConflictException ex) {
            Statistics stats = lastDataWriterUsed.getStatistics().values().iterator().next();
            long statementNumber = stats.get(DataWriterStatisticConstants.STATEMENTCOUNT);
            ResolvedData resolvedData = new ResolvedData(statementNumber, update.getCsvData(CsvData.ROW_DATA),
                    false);
            writerSettings.setResolvedData(resolvedData);
            writeData(update);
            Map<String, Object> row = queryForRow(origId);
            Assert.assertNotNull(row);
            Assert.assertEquals(newData[2], row.get("string_required_value"));
        }

    }

    @Test
    public void testUpdateDetectChangedDataIgnoreRow() {

    }

    @Test
    public void testUpdateDetectChangedDataIgnoreBatch() {

    }

    @Test
    public void testUpdateDetectChangedDataFallbackAll() {

    }

    @Test
    public void testDeleteDetectTimestampIgnoreRow() {

    }

    @Test
    public void testDeleteDetectTimestampIgnoreBatch() {

    }

    @Test
    public void testDeleteDetectTimestampNewerWins() {

    }

    @Test
    public void testInsertDetectTimestampManual() {

    }

    @Test
    public void testUpdateDetectChangedDataManual() {

    }

    @Test
    public void testInsertExisting() throws Exception {
        String[] values = { getNextId(), "string2", "string not null2", "char2", "char not null2",
                "2007-01-02 03:20:10.000", "2007-02-03 04:05:06.000", "0", "47", "67.89", "-0.0747663" };
        massageExpectectedResultsForDialect(values);
        CsvData data = new CsvData(DataEventType.INSERT, values);
        writeData(data, values);

        values[1] = "insert fallback to update";
        massageExpectectedResultsForDialect(values);
        writeData(data, values);
    }

    @Test
    public void testLargeDouble() throws Exception {
        String[] values = new String[TEST_COLUMNS.length];
        values[0] = getNextId();
        values[10] = "-0.0747663551401869";
        String[] expectedValues = (String[]) ArrayUtils.clone(values);
        massageExpectectedResultsForDialect(expectedValues);

        if (platform.getDatabaseInfo().isRequiredCharColumnEmptyStringSameAsNull()) {
            expectedValues[4] = AbstractDatabasePlatform.REQUIRED_FIELD_NULL_SUBSTITUTE;
        }

        writeData(new CsvData(DataEventType.INSERT, values), expectedValues);
    }

    @Test
    public void testDecimalLocale() throws Exception {
        String[] values = new String[TEST_COLUMNS.length];
        values[0] = getNextId();
        values[10] = "123456,99";
        String[] expectedValues = (String[]) ArrayUtils.clone(values);
        massageExpectectedResultsForDialect(expectedValues);
        if (platform.getDatabaseInfo().isRequiredCharColumnEmptyStringSameAsNull()) {
            expectedValues[4] = AbstractDatabasePlatform.REQUIRED_FIELD_NULL_SUBSTITUTE;
        }
        writeData(new CsvData(DataEventType.INSERT, values), expectedValues);
    }

    @Test
    public void testUpdateNotExisting() throws Exception {
        String id = getNextId();
        String[] values = { id, "it's /a/  string", "it's  -not-  null", "You're a \"character\"", "Where are you?",
                "2007-12-31 02:33:45.000", "2007-12-31 23:59:59.000", "1", "13", "9.95", "-0.0747" };
        String[] expectedValues = (String[]) ArrayUtils.subarray(values, 0, values.length);
        massageExpectectedResultsForDialect(expectedValues);
        writeData(new CsvData(DataEventType.UPDATE, new String[] { id }, values), expectedValues);
    }

    @Test
    public void testStringQuotes() throws Exception {
        String[] values = new String[TEST_COLUMNS.length];
        values[0] = getNextId();
        values[1] = "It's \"quoted,\" with a comma";
        values[2] = "two 'ticks'";
        values[3] = "One quote\"";
        values[4] = "One comma,";
        writeData(new CsvData(DataEventType.INSERT, values), values);
    }

    @Test
    public void testStringSpaces() throws Exception {
        String[] values = new String[TEST_COLUMNS.length];
        values[0] = getNextId();
        values[1] = "  two spaces before";
        if (!(platform instanceof AseDatabasePlatform)) {
            values[2] = "two spaces after  ";
        }
        values[3] = " one space before";
        values[4] = "one space after ";
        writeData(new CsvData(DataEventType.INSERT, values), values);
    }

    @Test
    public void testStringOneSpace() throws Exception {
        String[] values = new String[TEST_COLUMNS.length];
        values[0] = getNextId();
        values[2] = values[4] = " ";
        writeData(new CsvData(DataEventType.INSERT, values), values);
    }

    @Test
    public void testStringEmpty() throws Exception {
        String[] values = new String[TEST_COLUMNS.length];
        values[0] = getNextId();
        if (!(platform instanceof AseDatabasePlatform)) {
            values[1] = values[2] = "";
        }
        values[3] = values[4] = "";
        String[] expectedValues = (String[]) ArrayUtils.clone(values);
        if (platform.getDatabaseInfo().isRequiredCharColumnEmptyStringSameAsNull()) {
            expectedValues[4] = null;
        }
        writeData(new CsvData(DataEventType.INSERT, values), expectedValues);
    }

    @Test
    public void testStringNull() throws Exception {
        String[] values = new String[TEST_COLUMNS.length];
        values[0] = getNextId();
        String[] expectedValues = (String[]) ArrayUtils.clone(values);
        if (platform.getDatabaseInfo().isRequiredCharColumnEmptyStringSameAsNull()) {
            expectedValues[4] = AbstractDatabasePlatform.REQUIRED_FIELD_NULL_SUBSTITUTE;
        }
        writeData(new CsvData(DataEventType.INSERT, values), expectedValues);
    }

    @Test
    public void testStringBackslash() throws Exception {
        String[] values = new String[TEST_COLUMNS.length];
        values[0] = getNextId();
        values[1] = "Here's a \\, a (backslash)";
        values[2] = "Fix TODO";
        // TODO: Fix backslashing alphanumeric
        // values[2] = "\\a\\b\\c\\ \\1\\2\\3";
        values[3] = "Tick quote \\'\\\"";
        values[4] = "Comma quote \\,\\\"";
        writeData(new CsvData(DataEventType.INSERT, values), values);
    }

    @Test
    public void testDeleteExisting() throws Exception {
        String[] values = { getNextId(), "a row to be deleted", "testDeleteExisting", "char2", "char not null2",
                "2007-01-02 03:20:10.000", "2007-02-03 04:05:06.000", "0", "47", "67.89", "-0.0747" };
        massageExpectectedResultsForDialect(values);
        writeData(new CsvData(DataEventType.INSERT, values), values);
        writeData(new CsvData(DataEventType.DELETE, new String[] { getId() }, null), null);
    }

    @Test
    public void testDeleteNotExisting() throws Exception {
        writeData(new CsvData(DataEventType.DELETE, new String[] { getNextId() }, null), null);
    }

    @Test
    public void testColumnNotExisting() throws Exception {
        List<String> testColumns = new ArrayList<String>(Arrays.asList(TEST_COLUMNS));
        testColumns.add(4, "Unknown_Column");
        String[] columns = testColumns.toArray(new String[testColumns.size()]);

        String[] values = { getNextId(), "testColumnNotExisting", "string not null", "char", "i do not exist!",
                "char not null", "2007-01-02 00:00:00.000", "2007-02-03 04:05:06.000", "0", "47", "67.89",
                "-0.0747" };
        List<String> valuesAsList = new ArrayList<String>(Arrays.asList(values));
        valuesAsList.remove(4);
        String[] expectedValues = valuesAsList.toArray(new String[valuesAsList.size()]);
        writeData(new CsvData(DataEventType.INSERT, values), expectedValues, columns);
    }

    @Test
    public void testTableNotExisting() throws Exception {
        String[] values = { getNextId(), "testTableNotExisting", "This row should load", "char", "char not null",
                "2007-01-02 00:00:00.000", "2007-02-03 04:05:06.000", "0", "0", "12.10", "-0.0747" };

        Table badTable = buildSourceTable("UnknownTable", TEST_KEYS, TEST_COLUMNS);
        writeData(new TableCsvData(badTable, new CsvData(DataEventType.INSERT, values)), new TableCsvData(
                buildSourceTable(TEST_TABLE, TEST_KEYS, TEST_COLUMNS), new CsvData(DataEventType.INSERT, values)));

        massageExpectectedResultsForDialect(values);
        assertTestTableEquals(values[0], values);
    }

    @Test
    public void testColumnLevelSync() throws Exception {
        String[] insertValues = new String[TEST_COLUMNS.length];
        insertValues[2] = insertValues[4] = "column sync";
        insertValues[0] = getNextId();
        String[] updateValues = new String[2];
        updateValues[0] = insertValues[0];
        updateValues[1] = "new value";

        writeData(new CsvData(DataEventType.INSERT, insertValues), insertValues);

        // update a single column
        String[] columns = { "id", "string_value" };
        insertValues[1] = updateValues[1];
        writeData(new CsvData(DataEventType.UPDATE, new String[] { getId() }, updateValues), insertValues, columns);

        // update a single column
        columns = new String[] { "id", "char_value" };
        insertValues[3] = updateValues[1];
        writeData(new CsvData(DataEventType.UPDATE, new String[] { getId() }, updateValues), insertValues, columns);
    }

    @Test
    public void testBinaryColumnTypesForPostgres() throws Exception {
        if (platform instanceof PostgreSqlDatabasePlatform) {
            platform.getSqlTemplate().update("drop table if exists test_postgres_binary_types");
            platform.getSqlTemplate().update("create table test_postgres_binary_types (binary_data oid)");

            String tableName = "test_postgres_binary_types";
            String[] keys = { "binary_data" };
            String[] columns = { "binary_data" };
            String[] values = { "dGVzdCAxIDIgMw==" };

            Table table = buildSourceTable(tableName, keys, columns);
            writeData(new TableCsvData(table, new CsvData(DataEventType.INSERT, values)));

            String result = (String) platform.getSqlTemplate().queryForObject(
                    "select encode(data,'escape') from pg_largeobject where loid in (select binary_data from test_postgres_binary_types)",
                    String.class);

            // clean up the object from pg_largeobject, otherwise it becomes
            // abandoned on subsequent runs
            platform.getSqlTemplate().query("select lo_unlink(binary_data) from test_postgres_binary_types");
            Assert.assertEquals("test 1 2 3", result);
        }
    }

    @Test
    public void testBenchmark() throws Exception {
        Table table = buildSourceTable(TEST_TABLE, TEST_KEYS, TEST_COLUMNS);
        int startId = Integer.parseInt(getId()) + 1;
        List<CsvData> datas = new ArrayList<CsvData>();
        for (int i = 0; i < 1600; i++) {
            String[] values = { getNextId(), UUID.randomUUID().toString(), UUID.randomUUID().toString(),
                    UUID.randomUUID().toString(), UUID.randomUUID().toString(), "2007-01-02 03:20:10.0",
                    "2007-02-03 04:05:06.0", "0", "47", "67.89", "-0.0747663" };
            datas.add(new CsvData(DataEventType.INSERT, values));

        }

        for (int i = startId; i < 1600 + startId; i++) {
            String[] values = { Integer.toString(i) };
            datas.add(new CsvData(DataEventType.DELETE, values, null));
        }

        long startTime = System.currentTimeMillis();
        long statementCount = writeData(new TableCsvData(table, datas));
        double totalSeconds = (System.currentTimeMillis() - startTime) / 1000.0;

        double targetTime = 15.0;
        if (platform instanceof InformixDatabasePlatform) {
            targetTime = 20.0;
        }

        Assert.assertEquals(3200, statementCount);

        // TODO: this used to run in 1 second; can we do some optimization?
        Assert.assertTrue("DataLoader running in " + totalSeconds + " is too slow", totalSeconds <= targetTime);
    }

    private String[] massageExpectectedResultsForDialect(String[] values) {
        RoundingMode mode = RoundingMode.DOWN;

        if (values[5] != null && (!(platform instanceof OracleDatabasePlatform
                || platform instanceof MsSql2000DatabasePlatform || platform instanceof MsSql2005DatabasePlatform
                || platform instanceof MsSql2008DatabasePlatform || platform instanceof AseDatabasePlatform
                || platform instanceof SqlAnywhereDatabasePlatform))) {
            values[5] = values[5].replaceFirst(" \\d\\d:\\d\\d:\\d\\d\\.?0?", " 00:00:00.0");
        }
        if (values[10] != null) {
            values[10] = values[10].replace(',', '.');
        }
        if (values[10] != null && !(platform instanceof OracleDatabasePlatform)) {
            int scale = 17;
            if (platform instanceof MySqlDatabasePlatform) {
                scale = 16;
            }

            DecimalFormat df = new DecimalFormat("0.00####################################");
            values[10] = df.format(new BigDecimal(values[10]).setScale(scale, mode));
        }

        // Adjust character fields that may have been adjusted from null to a default space with appropriate padding
        values[3] = translateExpectedCharString(values[3], 50, false);
        values[4] = translateExpectedCharString(values[4], 50, true);

        return values;
    }

}