mirror of
https://github.com/apache/sqoop.git
synced 2025-05-07 10:51:42 +08:00
SQOOP-2971: OraOop does not close connections properly
(Szabolcs Vasas via Kate Ting)
This commit is contained in:
parent
c339b23b6c
commit
7808c6bc3e
@ -136,8 +136,16 @@ public List<InputSplit> getSplits(JobContext jobContext) throws IOException {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
connection.commit();
|
||||||
} catch (SQLException ex) {
|
} catch (SQLException ex) {
|
||||||
|
try {
|
||||||
|
connection.rollback();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
LOG.error("Cannot rollback transaction.", e);
|
||||||
|
}
|
||||||
throw new IOException(ex);
|
throw new IOException(ex);
|
||||||
|
} finally {
|
||||||
|
closeConnection();
|
||||||
}
|
}
|
||||||
|
|
||||||
return splits;
|
return splits;
|
||||||
@ -199,13 +207,11 @@ protected RecordReader<LongWritable, T> createDBRecordReader(
|
|||||||
// the current
|
// the current
|
||||||
// value of the URL_PROPERTY...
|
// value of the URL_PROPERTY...
|
||||||
|
|
||||||
return new OraOopDBRecordReader<T>(split, inputClass, conf, dbConf
|
return new OraOopDBRecordReader<T>(split, inputClass, conf,
|
||||||
.getConnection(), dbConf, dbConf.getInputConditions(), dbConf
|
getConnection(), dbConf, dbConf.getInputConditions(), dbConf
|
||||||
.getInputFieldNames(), dbConf.getInputTableName());
|
.getInputFieldNames(), dbConf.getInputTableName());
|
||||||
} catch (SQLException ex) {
|
} catch (SQLException ex) {
|
||||||
throw new IOException(ex);
|
throw new IOException(ex);
|
||||||
} catch (ClassNotFoundException ex) {
|
|
||||||
throw new IOException(ex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,8 +158,11 @@ public void write(DataOutput output) throws IOException {
|
|||||||
@Override
|
@Override
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
public void setConf(Configuration conf) {
|
public void setConf(Configuration conf) {
|
||||||
|
setDbConf(new DBConfiguration(conf));
|
||||||
|
}
|
||||||
|
|
||||||
dbConf = new DBConfiguration(conf);
|
public void setDbConf(DBConfiguration dbConf) {
|
||||||
|
this.dbConf = dbConf;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
getConnection();
|
getConnection();
|
||||||
@ -389,7 +392,9 @@ protected void closeConnection() {
|
|||||||
this.connection.close();
|
this.connection.close();
|
||||||
this.connection = null;
|
this.connection = null;
|
||||||
}
|
}
|
||||||
} catch (SQLException sqlE) { /* ignore exception on close. */ }
|
} catch (SQLException sqlE) {
|
||||||
|
LOG.error("Cannot close JDBC connection.", sqlE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -55,6 +55,7 @@
|
|||||||
import org.apache.sqoop.manager.netezza.DirectNetezzaHCatImportManualTest;
|
import org.apache.sqoop.manager.netezza.DirectNetezzaHCatImportManualTest;
|
||||||
import org.apache.sqoop.manager.netezza.NetezzaExportManualTest;
|
import org.apache.sqoop.manager.netezza.NetezzaExportManualTest;
|
||||||
import org.apache.sqoop.manager.netezza.NetezzaImportManualTest;
|
import org.apache.sqoop.manager.netezza.NetezzaImportManualTest;
|
||||||
|
import org.apache.sqoop.manager.oracle.OraOopDataDrivenDBInputFormatConnectionCloseTest;
|
||||||
import org.apache.sqoop.manager.oracle.OracleCallExportTest;
|
import org.apache.sqoop.manager.oracle.OracleCallExportTest;
|
||||||
import org.apache.sqoop.manager.oracle.OracleIncrementalImportTest;
|
import org.apache.sqoop.manager.oracle.OracleIncrementalImportTest;
|
||||||
import org.apache.sqoop.manager.oracle.OracleSplitterTest;
|
import org.apache.sqoop.manager.oracle.OracleSplitterTest;
|
||||||
@ -98,6 +99,7 @@ public static Test suite() {
|
|||||||
suite.addTestSuite(OracleCompatTest.class);
|
suite.addTestSuite(OracleCompatTest.class);
|
||||||
suite.addTestSuite(OracleIncrementalImportTest.class);
|
suite.addTestSuite(OracleIncrementalImportTest.class);
|
||||||
suite.addTestSuite(OracleSplitterTest.class);
|
suite.addTestSuite(OracleSplitterTest.class);
|
||||||
|
suite.addTestSuite(OraOopDataDrivenDBInputFormatConnectionCloseTest.class);
|
||||||
|
|
||||||
// SQL Server
|
// SQL Server
|
||||||
suite.addTestSuite(SQLServerDatatypeExportDelimitedFileManualTest.class);
|
suite.addTestSuite(SQLServerDatatypeExportDelimitedFileManualTest.class);
|
||||||
|
@ -0,0 +1,91 @@
|
|||||||
|
package org.apache.sqoop.manager.oracle;
|
||||||
|
|
||||||
|
import com.cloudera.sqoop.mapreduce.db.DBConfiguration;
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
import org.apache.hadoop.conf.Configuration;
|
||||||
|
import org.apache.hadoop.mapreduce.JobContext;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.DatabaseMetaData;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
import static org.mockito.Matchers.anyString;
|
||||||
|
import static org.mockito.Mockito.doThrow;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
public class OraOopDataDrivenDBInputFormatConnectionCloseTest extends TestCase {
|
||||||
|
|
||||||
|
private static final OraOopLog LOG = OraOopLogFactory.getLog(
|
||||||
|
TestOraOopDataDrivenDBInputFormat.class.getName());
|
||||||
|
|
||||||
|
private static final String ORACLE_PREPARED_STATEMENT_CLASS = "oracle.jdbc.OraclePreparedStatement";
|
||||||
|
|
||||||
|
private OraOopDataDrivenDBInputFormat inputFormat;
|
||||||
|
|
||||||
|
private Connection mockConnection;
|
||||||
|
|
||||||
|
private JobContext mockJobContext;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
Configuration configuration = new Configuration();
|
||||||
|
configuration.set(DBConfiguration.USERNAME_PROPERTY, "Oracle user");
|
||||||
|
configuration.setInt(OraOopConstants.ORAOOP_DESIRED_NUMBER_OF_MAPPERS, 1);
|
||||||
|
|
||||||
|
Class<? extends PreparedStatement> preparedStatementClass =
|
||||||
|
(Class<? extends PreparedStatement>) Class.forName(ORACLE_PREPARED_STATEMENT_CLASS);
|
||||||
|
PreparedStatement mockPreparedStatement = mock(preparedStatementClass);
|
||||||
|
ResultSet mockResultSet = mock(ResultSet.class);
|
||||||
|
when(mockResultSet.next()).thenReturn(true).thenReturn(false);
|
||||||
|
when(mockPreparedStatement.executeQuery()).thenReturn(mockResultSet);
|
||||||
|
|
||||||
|
mockConnection = mock(Connection.class);
|
||||||
|
DatabaseMetaData dbMetaData = mock(DatabaseMetaData.class);
|
||||||
|
when(dbMetaData.getDatabaseProductName()).thenReturn("Oracle");
|
||||||
|
when(mockConnection.getMetaData()).thenReturn(dbMetaData);
|
||||||
|
when(mockConnection.prepareStatement(anyString())).thenReturn(mockPreparedStatement);
|
||||||
|
|
||||||
|
DBConfiguration dbConf = mock(DBConfiguration.class);
|
||||||
|
when(dbConf.getConnection()).thenReturn(mockConnection);
|
||||||
|
when(dbConf.getConf()).thenReturn(configuration);
|
||||||
|
when(dbConf.getInputTableName()).thenReturn("InputTable");
|
||||||
|
|
||||||
|
mockJobContext = mock(JobContext.class);
|
||||||
|
when(mockJobContext.getConfiguration()).thenReturn(configuration);
|
||||||
|
|
||||||
|
inputFormat = new OraOopDataDrivenDBInputFormat();
|
||||||
|
inputFormat.setDbConf(dbConf);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetSplitsClosesConnectionProperly() throws Exception {
|
||||||
|
inputFormat.getSplits(mockJobContext);
|
||||||
|
verify(mockConnection).commit();
|
||||||
|
verify(mockConnection).close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetSplitsClosesConnectionProperlyWhenExceptionIsThrown() throws Exception {
|
||||||
|
|
||||||
|
doThrow(new SQLException("For the sake of testing the commit fails.")).when(mockConnection).commit();
|
||||||
|
|
||||||
|
try {
|
||||||
|
inputFormat.getSplits(mockJobContext);
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOG.debug("An expected exception is thrown in testSplitsClosesConnectionProperlyWhenExceptionIsThrown, ignoring.");
|
||||||
|
}
|
||||||
|
|
||||||
|
verify(mockConnection).rollback();
|
||||||
|
verify(mockConnection).close();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user