/* ==================================================================
* PreparedStatementCsvReaderTests.java - 6/10/2016 1:13:32 PM
*
* Copyright 2007-2016 SolarNetwork.net Dev Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* 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
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
* ==================================================================
*/
package net.solarnetwork.node.dao.jdbc.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Savepoint;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TimeZone;
import javax.annotation.Resource;
import javax.sql.DataSource;
import org.apache.commons.lang3.mutable.MutableInt;
import org.junit.Before;
import org.junit.Test;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.jdbc.core.ConnectionCallback;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.core.RowCallbackHandler;
import org.supercsv.cellprocessor.ift.CellProcessor;
import org.supercsv.prefs.CsvPreference;
import net.solarnetwork.node.dao.jdbc.ColumnCsvMetaData;
import net.solarnetwork.node.dao.jdbc.DatabaseSetup;
import net.solarnetwork.node.dao.jdbc.JdbcUtils;
import net.solarnetwork.node.dao.jdbc.PreparedStatementCsvReader;
import net.solarnetwork.node.test.AbstractNodeTransactionalTest;
/**
* Test cases for the {@link PreparedStatementCsvReader} class.
*
* @author matt
* @version 1.0
*/
public class PreparedStatementCsvReaderTests extends AbstractNodeTransactionalTest {
@Resource(name = "dataSource")
private DataSource dataSource;
private JdbcTemplate jdbcTemplate;
@Before
public void setup() {
DatabaseSetup setup = new DatabaseSetup();
setup.setDataSource(dataSource);
setup.init();
jdbcTemplate = new JdbcTemplate(dataSource);
}
private void importData(final String tableName) {
final Map<String, ColumnCsvMetaData> columnMetaData = new LinkedHashMap<String, ColumnCsvMetaData>(
8);
jdbcTemplate.execute(new ConnectionCallback<Object>() {
@Override
public Object doInConnection(Connection con) throws SQLException, DataAccessException {
columnMetaData.putAll(
JdbcUtils.columnCsvMetaDataForDatabaseMetaData(con.getMetaData(), tableName));
String sql = JdbcUtils.insertSqlForColumnCsvMetaData(tableName, columnMetaData);
PreparedStatement ps = con.prepareStatement(sql);
Reader in;
PreparedStatementCsvReader reader = null;
try {
in = new InputStreamReader(getClass().getResourceAsStream("csv-data-01.csv"),
"UTF-8");
reader = new PreparedStatementCsvReader(in, CsvPreference.STANDARD_PREFERENCE);
String[] header = reader.getHeader(true);
Map<String, Integer> csvColumns = JdbcUtils.csvColumnIndexMapping(header);
CellProcessor[] cellProcessors = JdbcUtils.parsingCellProcessorsForCsvColumns(header,
columnMetaData);
while ( reader.read(ps, csvColumns, cellProcessors, columnMetaData) ) {
Savepoint sp = con.setSavepoint();
try {
ps.executeUpdate();
} catch ( SQLException e ) {
DataAccessException dae = jdbcTemplate.getExceptionTranslator()
.translate("Load CSV", sql, e);
if ( dae instanceof DataIntegrityViolationException ) {
con.rollback(sp);
} else {
throw e;
}
}
}
} catch ( IOException e ) {
throw new DataAccessResourceFailureException("CSV encoding error", e);
} finally {
if ( reader != null ) {
try {
reader.close();
} catch ( IOException e ) {
// ignore
}
}
}
return null;
}
});
}
@Test
public void importTable() throws Exception {
final String tableName = "SOLARNODE.TEST_CSV_IO";
executeSqlScript("net/solarnetwork/node/dao/jdbc/test/csv-data-01.sql", false);
importData(tableName);
final MutableInt row = new MutableInt(0);
final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
final Calendar utcCalendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
jdbcTemplate.query(new PreparedStatementCreator() {
@Override
public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
// TODO Auto-generated method stub
return con.prepareStatement(
"select PK,STR,INUM,DNUM,TS from solarnode.test_csv_io order by pk");
}
}, new RowCallbackHandler() {
@Override
public void processRow(ResultSet rs) throws SQLException {
row.increment();
final int i = row.intValue();
assertEquals("PK " + i, i, rs.getLong(1));
if ( i == 2 ) {
assertNull("STR " + i, rs.getString(2));
} else {
assertEquals("STR " + i, "s0" + i, rs.getString(2));
}
if ( i == 3 ) {
assertNull("INUM " + i, rs.getObject(3));
} else {
assertEquals("INUM " + i, i, rs.getInt(3));
}
if ( i == 4 ) {
assertNull("DNUM " + i, rs.getObject(4));
} else {
assertEquals("DNUM " + i, i, rs.getDouble(4), 0.01);
}
if ( i == 5 ) {
assertNull("TS " + i, rs.getObject(5));
} else {
Timestamp ts = rs.getTimestamp(5, utcCalendar);
try {
assertEquals("TS " + i, sdf.parse("2016-10-0" + i + "T12:01:02.345Z"), ts);
} catch ( ParseException e ) {
// should not get here
}
}
}
});
assertEquals("Imported count", 5, row.intValue());
}
@Test
public void updateTable() throws Exception {
final String tableName = "SOLARNODE.TEST_CSV_IO";
executeSqlScript("net/solarnetwork/node/dao/jdbc/test/csv-data-01.sql", false);
importData(tableName);
// verify the savepoint logic works to ignore inserts on data that already exists
importData(tableName);
}
}