mirror of
https://github.com/apache/sqoop.git
synced 2025-05-03 16:40:21 +08:00
SQOOP-1097: Export using procedures feature needs fixes for working with mysql
(Venkat Ranganathan via Jarek Jarcec Cecho)
This commit is contained in:
parent
00bc001fb9
commit
73cc549d9d
@ -368,8 +368,17 @@ public Map<String, String> getColumnTypeNamesForTable(String tableName) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return an unordered mapping from colname to sql type name for
|
* Return an unordered mapping from colname to sql type name for all columns
|
||||||
* all columns in a query.
|
* in a procedure.
|
||||||
|
*/
|
||||||
|
public Map<String, String> getColumnTypeNamesForProcedure(String callName) {
|
||||||
|
LOG.error("This database does not support procedure param type names.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return an unordered mapping from colname to sql type name for all columns
|
||||||
|
* in a query.
|
||||||
*/
|
*/
|
||||||
public Map<String, String> getColumnTypeNamesForQuery(String query) {
|
public Map<String, String> getColumnTypeNamesForQuery(String query) {
|
||||||
LOG.error("This database does not support free-form query"
|
LOG.error("This database does not support free-form query"
|
||||||
@ -385,11 +394,29 @@ public Map<String, String> getColumnTypeNamesForQuery(String query) {
|
|||||||
* @param sqlQuery the SQL query to use if tableName is null
|
* @param sqlQuery the SQL query to use if tableName is null
|
||||||
*/
|
*/
|
||||||
public Map<String, String> getColumnTypeNames(String tableName,
|
public Map<String, String> getColumnTypeNames(String tableName,
|
||||||
String sqlQuery) {
|
String sqlQuery) {
|
||||||
|
return getColumnTypeNames(tableName, null, sqlQuery);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return an unordered mapping from colname to sql type name for all columns
|
||||||
|
* in a table or query.
|
||||||
|
*
|
||||||
|
* @param tableName
|
||||||
|
* the name of the table
|
||||||
|
* @param callName
|
||||||
|
* the name of the procedure
|
||||||
|
* @param sqlQuery
|
||||||
|
* the SQL query to use if tableName is null
|
||||||
|
*/
|
||||||
|
public Map<String, String> getColumnTypeNames(String tableName,
|
||||||
|
String callName, String sqlQuery) {
|
||||||
Map<String, String> columnTypeNames;
|
Map<String, String> columnTypeNames;
|
||||||
if (null != tableName) {
|
if (null != tableName) {
|
||||||
// We're generating a class based on a table import.
|
// We're generating a class based on a table import.
|
||||||
columnTypeNames = getColumnTypeNamesForTable(tableName);
|
columnTypeNames = getColumnTypeNamesForTable(tableName);
|
||||||
|
} else if (null != callName) {
|
||||||
|
columnTypeNames = getColumnTypeNamesForProcedure(callName);
|
||||||
} else {
|
} else {
|
||||||
// This is based on an arbitrary query.
|
// This is based on an arbitrary query.
|
||||||
String query = sqlQuery;
|
String query = sqlQuery;
|
||||||
|
@ -22,12 +22,19 @@
|
|||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
|
import java.sql.DatabaseMetaData;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.sql.Types;
|
import java.sql.Types;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
import org.apache.avro.Schema.Type;
|
import org.apache.avro.Schema.Type;
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
@ -261,6 +268,126 @@ public boolean supportsStagingForExport() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getColumnNamesForProcedure(String procedureName) {
|
||||||
|
List<String> ret = new ArrayList<String>();
|
||||||
|
try {
|
||||||
|
DatabaseMetaData metaData = this.getConnection().getMetaData();
|
||||||
|
ResultSet results = metaData.getProcedureColumns(null, null,
|
||||||
|
procedureName, null);
|
||||||
|
if (null == results) {
|
||||||
|
LOG.debug("Get Procedure Columns returns null");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
while (results.next()) {
|
||||||
|
if (results.getInt("COLUMN_TYPE")
|
||||||
|
!= DatabaseMetaData.procedureColumnReturn) {
|
||||||
|
String name = results.getString("COLUMN_NAME");
|
||||||
|
ret.add(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String[] result = ret.toArray(new String[ret.size()]);
|
||||||
|
LOG.debug("getColumnsNamesForProcedure returns "
|
||||||
|
+ StringUtils.join(ret, ","));
|
||||||
|
return result;
|
||||||
|
} finally {
|
||||||
|
results.close();
|
||||||
|
getConnection().commit();
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
LoggingUtils.logAll(LOG, "Error reading procedure metadata: ", e);
|
||||||
|
throw new RuntimeException("Can't fetch column names for procedure.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, Integer> getColumnTypesForProcedure(String procedureName) {
|
||||||
|
Map<String, Integer> ret = new TreeMap<String, Integer>();
|
||||||
|
try {
|
||||||
|
DatabaseMetaData metaData = this.getConnection().getMetaData();
|
||||||
|
ResultSet results = metaData.getProcedureColumns(null, null,
|
||||||
|
procedureName, null);
|
||||||
|
if (null == results) {
|
||||||
|
LOG.debug("getColumnTypesForProcedure returns null");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
while (results.next()) {
|
||||||
|
if (results.getInt("COLUMN_TYPE")
|
||||||
|
!= DatabaseMetaData.procedureColumnReturn) {
|
||||||
|
// we don't care if we get several rows for the
|
||||||
|
// same ORDINAL_POSITION (e.g. like H2 gives us)
|
||||||
|
// as we'll just overwrite the entry in the map:
|
||||||
|
ret.put(
|
||||||
|
results.getString("COLUMN_NAME"),
|
||||||
|
results.getInt("DATA_TYPE"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG.debug("Columns returned = " + StringUtils.join(ret.keySet(), ","));
|
||||||
|
LOG.debug("Types returned = " + StringUtils.join(ret.values(), ","));
|
||||||
|
|
||||||
|
return ret.isEmpty() ? null : ret;
|
||||||
|
} finally {
|
||||||
|
if (results != null) {
|
||||||
|
results.close();
|
||||||
|
}
|
||||||
|
getConnection().commit();
|
||||||
|
}
|
||||||
|
} catch (SQLException sqlException) {
|
||||||
|
LoggingUtils.logAll(LOG, "Error reading primary key metadata: "
|
||||||
|
+ sqlException.toString(), sqlException);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String>
|
||||||
|
getColumnTypeNamesForProcedure(String procedureName) {
|
||||||
|
Map<String, String> ret = new TreeMap<String, String>();
|
||||||
|
try {
|
||||||
|
DatabaseMetaData metaData = this.getConnection().getMetaData();
|
||||||
|
ResultSet results = metaData.getProcedureColumns(null, null,
|
||||||
|
procedureName, null);
|
||||||
|
if (null == results) {
|
||||||
|
LOG.debug("getColumnTypesForProcedure returns null");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
while (results.next()) {
|
||||||
|
if (results.getInt("COLUMN_TYPE")
|
||||||
|
!= DatabaseMetaData.procedureColumnReturn) {
|
||||||
|
// we don't care if we get several rows for the
|
||||||
|
// same ORDINAL_POSITION (e.g. like H2 gives us)
|
||||||
|
// as we'll just overwrite the entry in the map:
|
||||||
|
ret.put(
|
||||||
|
results.getString("COLUMN_NAME"),
|
||||||
|
results.getString("TYPE_NAME"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG.debug("Columns returned = " + StringUtils.join(ret.keySet(), ","));
|
||||||
|
LOG.debug(
|
||||||
|
"Type names returned = " + StringUtils.join(ret.values(), ","));
|
||||||
|
|
||||||
|
return ret.isEmpty() ? null : ret;
|
||||||
|
} finally {
|
||||||
|
if (results != null) {
|
||||||
|
results.close();
|
||||||
|
}
|
||||||
|
getConnection().commit();
|
||||||
|
}
|
||||||
|
} catch (SQLException sqlException) {
|
||||||
|
LoggingUtils.logAll(LOG, "Error reading primary key metadata: "
|
||||||
|
+ sqlException.toString(), sqlException);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getListDatabasesQuery() {
|
protected String getListDatabasesQuery() {
|
||||||
return "SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA";
|
return "SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA";
|
||||||
@ -276,8 +403,10 @@ protected String getSchemaQuery() {
|
|||||||
|
|
||||||
private int overrideSqlType(String tableName, String columnName,
|
private int overrideSqlType(String tableName, String columnName,
|
||||||
int sqlType) {
|
int sqlType) {
|
||||||
|
|
||||||
if (colTypeNames == null) {
|
if (colTypeNames == null) {
|
||||||
colTypeNames = getColumnTypeNames(tableName, options.getSqlQuery());
|
colTypeNames = getColumnTypeNames(tableName, options.getCall(),
|
||||||
|
options.getSqlQuery());
|
||||||
}
|
}
|
||||||
|
|
||||||
if ("YEAR".equalsIgnoreCase(colTypeNames.get(columnName))) {
|
if ("YEAR".equalsIgnoreCase(colTypeNames.get(columnName))) {
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
@ -482,7 +483,8 @@ public ResultSet readTable(String tableName, String[] columns)
|
|||||||
*/
|
*/
|
||||||
private String toDbSpecificJavaType(String tableName, String colName) {
|
private String toDbSpecificJavaType(String tableName, String colName) {
|
||||||
if (columnTypeNames == null) {
|
if (columnTypeNames == null) {
|
||||||
columnTypeNames = getColumnTypeNames(tableName, options.getSqlQuery());
|
columnTypeNames = getColumnTypeNames(tableName, options.getCall(),
|
||||||
|
options.getSqlQuery());
|
||||||
}
|
}
|
||||||
|
|
||||||
String colTypeName = columnTypeNames.get(colName);
|
String colTypeName = columnTypeNames.get(colName);
|
||||||
@ -490,9 +492,15 @@ private String toDbSpecificJavaType(String tableName, String colName) {
|
|||||||
if (colTypeName.equalsIgnoreCase("BINARY_FLOAT")) {
|
if (colTypeName.equalsIgnoreCase("BINARY_FLOAT")) {
|
||||||
return "Float";
|
return "Float";
|
||||||
}
|
}
|
||||||
|
if (colTypeName.equalsIgnoreCase("FLOAT")) {
|
||||||
|
return "Float";
|
||||||
|
}
|
||||||
if (colTypeName.equalsIgnoreCase("BINARY_DOUBLE")) {
|
if (colTypeName.equalsIgnoreCase("BINARY_DOUBLE")) {
|
||||||
return "Double";
|
return "Double";
|
||||||
}
|
}
|
||||||
|
if (colTypeName.equalsIgnoreCase("DOUBLE")) {
|
||||||
|
return "Double";
|
||||||
|
}
|
||||||
if (colTypeName.toUpperCase().startsWith("TIMESTAMP")) {
|
if (colTypeName.toUpperCase().startsWith("TIMESTAMP")) {
|
||||||
return "java.sql.Timestamp";
|
return "java.sql.Timestamp";
|
||||||
}
|
}
|
||||||
@ -508,8 +516,14 @@ private String toDbSpecificJavaType(String tableName, String colName) {
|
|||||||
*/
|
*/
|
||||||
private String toDbSpecificHiveType(String tableName, String colName) {
|
private String toDbSpecificHiveType(String tableName, String colName) {
|
||||||
if (columnTypeNames == null) {
|
if (columnTypeNames == null) {
|
||||||
columnTypeNames = getColumnTypeNames(tableName, options.getSqlQuery());
|
columnTypeNames = getColumnTypeNames(tableName, options.getCall(),
|
||||||
|
options.getSqlQuery());
|
||||||
}
|
}
|
||||||
|
LOG.debug("Column Types and names returned = ("
|
||||||
|
+ StringUtils.join(columnTypeNames.keySet(), ",")
|
||||||
|
+ ")=>("
|
||||||
|
+ StringUtils.join(columnTypeNames.values(), ",")
|
||||||
|
+ ")");
|
||||||
|
|
||||||
String colTypeName = columnTypeNames.get(colName);
|
String colTypeName = columnTypeNames.get(colName);
|
||||||
if (colTypeName != null) {
|
if (colTypeName != null) {
|
||||||
@ -753,6 +767,91 @@ public String[] getColumnNamesForProcedure(String procedureName) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, Integer>
|
||||||
|
getColumnTypesForProcedure(String procedureName) {
|
||||||
|
Map<String, Integer> ret = new TreeMap<String, Integer>();
|
||||||
|
try {
|
||||||
|
DatabaseMetaData metaData = this.getConnection().getMetaData();
|
||||||
|
ResultSet results = metaData.getProcedureColumns(null, null,
|
||||||
|
procedureName, null);
|
||||||
|
if (null == results) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
while (results.next()) {
|
||||||
|
if (results.getInt("COLUMN_TYPE")
|
||||||
|
!= DatabaseMetaData.procedureColumnReturn) {
|
||||||
|
int index = results.getInt("ORDINAL_POSITION");
|
||||||
|
if (index < 0) {
|
||||||
|
continue; // actually the return type
|
||||||
|
}
|
||||||
|
// we don't care if we get several rows for the
|
||||||
|
// same ORDINAL_POSITION (e.g. like H2 gives us)
|
||||||
|
// as we'll just overwrite the entry in the map:
|
||||||
|
ret.put(
|
||||||
|
results.getString("COLUMN_NAME"),
|
||||||
|
results.getInt("DATA_TYPE"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LOG.debug("Columns returned = " + StringUtils.join(ret.keySet(), ","));
|
||||||
|
LOG.debug("Types returned = " + StringUtils.join(ret.values(), ","));
|
||||||
|
return ret.isEmpty() ? null : ret;
|
||||||
|
} finally {
|
||||||
|
results.close();
|
||||||
|
getConnection().commit();
|
||||||
|
}
|
||||||
|
} catch (SQLException sqlException) {
|
||||||
|
LoggingUtils.logAll(LOG, "Error reading primary key metadata: "
|
||||||
|
+ sqlException.toString(), sqlException);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String>
|
||||||
|
getColumnTypeNamesForProcedure(String procedureName) {
|
||||||
|
Map<String, String> ret = new TreeMap<String, String>();
|
||||||
|
try {
|
||||||
|
DatabaseMetaData metaData = this.getConnection().getMetaData();
|
||||||
|
ResultSet results = metaData.getProcedureColumns(null, null,
|
||||||
|
procedureName, null);
|
||||||
|
if (null == results) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
while (results.next()) {
|
||||||
|
if (results.getInt("COLUMN_TYPE")
|
||||||
|
!= DatabaseMetaData.procedureColumnReturn) {
|
||||||
|
int index = results.getInt("ORDINAL_POSITION");
|
||||||
|
if (index < 0) {
|
||||||
|
continue; // actually the return type
|
||||||
|
}
|
||||||
|
// we don't care if we get several rows for the
|
||||||
|
// same ORDINAL_POSITION (e.g. like H2 gives us)
|
||||||
|
// as we'll just overwrite the entry in the map:
|
||||||
|
ret.put(
|
||||||
|
results.getString("COLUMN_NAME"),
|
||||||
|
results.getString("TYPE_NAME"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LOG.debug("Columns returned = " + StringUtils.join(ret.keySet(), ","));
|
||||||
|
LOG.debug(
|
||||||
|
"Type names returned = " + StringUtils.join(ret.values(), ","));
|
||||||
|
return ret.isEmpty() ? null : ret;
|
||||||
|
} finally {
|
||||||
|
results.close();
|
||||||
|
getConnection().commit();
|
||||||
|
}
|
||||||
|
} catch (SQLException sqlException) {
|
||||||
|
LoggingUtils.logAll(LOG, "Error reading primary key metadata: "
|
||||||
|
+ sqlException.toString(), sqlException);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] getColumnNames(String tableName) {
|
public String[] getColumnNames(String tableName) {
|
||||||
Connection conn = null;
|
Connection conn = null;
|
||||||
|
@ -235,6 +235,7 @@ public Map<String, Integer> getColumnTypesForQuery(String query) {
|
|||||||
*/
|
*/
|
||||||
protected Map<String, Integer> getColumnTypesForRawQuery(String stmt) {
|
protected Map<String, Integer> getColumnTypesForRawQuery(String stmt) {
|
||||||
ResultSet results;
|
ResultSet results;
|
||||||
|
LOG.debug("Execute getColumnTypesRawQuery : " + stmt);
|
||||||
try {
|
try {
|
||||||
results = execute(stmt);
|
results = execute(stmt);
|
||||||
} catch (SQLException sqlE) {
|
} catch (SQLException sqlE) {
|
||||||
@ -399,6 +400,8 @@ public Map<String, Integer> getColumnTypesForProcedure(String procedureName) {
|
|||||||
results.getInt("DATA_TYPE"));
|
results.getInt("DATA_TYPE"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
LOG.debug("Columns returned = " + StringUtils.join(ret.keySet(), ","));
|
||||||
|
LOG.debug("Types returned = " + StringUtils.join(ret.values(), ","));
|
||||||
return ret.isEmpty() ? null : ret;
|
return ret.isEmpty() ? null : ret;
|
||||||
} finally {
|
} finally {
|
||||||
results.close();
|
results.close();
|
||||||
@ -411,6 +414,46 @@ public Map<String, Integer> getColumnTypesForProcedure(String procedureName) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String>
|
||||||
|
getColumnTypeNamesForProcedure(String procedureName) {
|
||||||
|
Map<String, String> ret = new TreeMap<String, String>();
|
||||||
|
try {
|
||||||
|
DatabaseMetaData metaData = this.getConnection().getMetaData();
|
||||||
|
ResultSet results = metaData.getProcedureColumns(null, null,
|
||||||
|
procedureName, null);
|
||||||
|
if (null == results) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
while (results.next()) {
|
||||||
|
if (results.getInt("COLUMN_TYPE")
|
||||||
|
!= DatabaseMetaData.procedureColumnReturn
|
||||||
|
&& results.getInt("ORDINAL_POSITION") > 0) {
|
||||||
|
// we don't care if we get several rows for the
|
||||||
|
// same ORDINAL_POSITION (e.g. like H2 gives us)
|
||||||
|
// as we'll just overwrite the entry in the map:
|
||||||
|
ret.put(
|
||||||
|
results.getString("COLUMN_NAME"),
|
||||||
|
results.getString("TYPE_NAME"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LOG.debug("Columns returned = " + StringUtils.join(ret.keySet(), ","));
|
||||||
|
LOG.debug(
|
||||||
|
"Type names returned = " + StringUtils.join(ret.values(), ","));
|
||||||
|
return ret.isEmpty() ? null : ret;
|
||||||
|
} finally {
|
||||||
|
results.close();
|
||||||
|
getConnection().commit();
|
||||||
|
}
|
||||||
|
} catch (SQLException sqlException) {
|
||||||
|
LoggingUtils.logAll(LOG, "Error reading primary key metadata: "
|
||||||
|
+ sqlException.toString(), sqlException);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] listTables() {
|
public String[] listTables() {
|
||||||
ResultSet results = null;
|
ResultSet results = null;
|
||||||
|
@ -41,6 +41,9 @@
|
|||||||
import com.cloudera.sqoop.manager.OracleCompatTest;
|
import com.cloudera.sqoop.manager.OracleCompatTest;
|
||||||
import com.cloudera.sqoop.manager.PostgresqlExportTest;
|
import com.cloudera.sqoop.manager.PostgresqlExportTest;
|
||||||
import com.cloudera.sqoop.manager.PostgresqlImportTest;
|
import com.cloudera.sqoop.manager.PostgresqlImportTest;
|
||||||
|
|
||||||
|
import org.apache.sqoop.manager.mysql.MySqlCallExportTest;
|
||||||
|
import org.apache.sqoop.manager.oracle.OracleCallExportTest;
|
||||||
import org.apache.sqoop.manager.sqlserver.SQLServerDatatypeExportDelimitedFileManualTest;
|
import org.apache.sqoop.manager.sqlserver.SQLServerDatatypeExportDelimitedFileManualTest;
|
||||||
import org.apache.sqoop.manager.sqlserver.SQLServerDatatypeExportSequenceFileManualTest;
|
import org.apache.sqoop.manager.sqlserver.SQLServerDatatypeExportSequenceFileManualTest;
|
||||||
import org.apache.sqoop.manager.sqlserver.SQLServerDatatypeImportDelimitedFileManualTest;
|
import org.apache.sqoop.manager.sqlserver.SQLServerDatatypeImportDelimitedFileManualTest;
|
||||||
@ -110,6 +113,10 @@ public static Test suite() {
|
|||||||
suite.addTestSuite(HCatalogImportTest.class);
|
suite.addTestSuite(HCatalogImportTest.class);
|
||||||
suite.addTestSuite(HCatalogExportTest.class);
|
suite.addTestSuite(HCatalogExportTest.class);
|
||||||
|
|
||||||
|
// Call Export tests
|
||||||
|
suite.addTestSuite(MySqlCallExportTest.class);
|
||||||
|
suite.addTestSuite(OracleCallExportTest.class);
|
||||||
|
|
||||||
return suite;
|
return suite;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ public void createTable(ColumnGenerator... extraColumns) throws SQLException {
|
|||||||
createProcedure(names, types);
|
createProcedure(names, types);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createProcedure(String[] extraNames, String[] extraTypes)
|
protected void createProcedure(String[] extraNames, String[] extraTypes)
|
||||||
throws SQLException {
|
throws SQLException {
|
||||||
StringBuilder drop = new StringBuilder("DROP ALIAS IF EXISTS ");
|
StringBuilder drop = new StringBuilder("DROP ALIAS IF EXISTS ");
|
||||||
drop.append(PROCEDURE_NAME);
|
drop.append(PROCEDURE_NAME);
|
||||||
|
199
src/test/org/apache/sqoop/manager/mysql/MySqlCallExportTest.java
Normal file
199
src/test/org/apache/sqoop/manager/mysql/MySqlCallExportTest.java
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* 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.apache.sqoop.manager.mysql;
|
||||||
|
|
||||||
|
import java.io.BufferedWriter;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.Writer;
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Statement;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.apache.hadoop.conf.Configuration;
|
||||||
|
|
||||||
|
import com.cloudera.sqoop.SqoopOptions;
|
||||||
|
import com.cloudera.sqoop.manager.MySQLTestUtils;
|
||||||
|
import com.cloudera.sqoop.testutil.CommonArgs;
|
||||||
|
import com.cloudera.sqoop.testutil.ExportJobTestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test free form query import with the MySQL db.
|
||||||
|
*/
|
||||||
|
public class MySqlCallExportTest extends ExportJobTestCase {
|
||||||
|
|
||||||
|
public static final Log LOG = LogFactory.getLog(
|
||||||
|
MySqlCallExportTest.class.getName());
|
||||||
|
|
||||||
|
private final String tableName = "MYSQL_CALL_EXPORT_BASE_TABLE";
|
||||||
|
private final String procName = "MYSQL_CALL_EXPORT_PROC";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setUp() {
|
||||||
|
super.setUp();
|
||||||
|
createObjects();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String[] getArgv(String... extraArgs) {
|
||||||
|
ArrayList<String> args = new ArrayList<String>();
|
||||||
|
|
||||||
|
CommonArgs.addHadoopFlags(args);
|
||||||
|
|
||||||
|
args.add("--call");
|
||||||
|
args.add(procName);
|
||||||
|
args.add("--export-dir");
|
||||||
|
args.add(getWarehouseDir());
|
||||||
|
args.add("--fields-terminated-by");
|
||||||
|
args.add(",");
|
||||||
|
args.add("--lines-terminated-by");
|
||||||
|
args.add("\\n");
|
||||||
|
args.add("--connect");
|
||||||
|
args.add(getConnectString());
|
||||||
|
args.add("-m");
|
||||||
|
args.add("1");
|
||||||
|
|
||||||
|
for (String arg : extraArgs) {
|
||||||
|
args.add(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return args.toArray(new String[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createObjects() {
|
||||||
|
|
||||||
|
String createTableSql = "CREATE TABLE " + tableName + " ( "
|
||||||
|
+ "id INT NOT NULL PRIMARY KEY, "
|
||||||
|
+ "msg VARCHAR(24) NOT NULL, "
|
||||||
|
+ "d DATE, "
|
||||||
|
+ "f FLOAT, "
|
||||||
|
+ "vc VARCHAR(32))";
|
||||||
|
|
||||||
|
String createProcSql = "CREATE PROCEDURE " + procName + " ( "
|
||||||
|
+ "IN id INT,"
|
||||||
|
+ "IN msg VARCHAR(24),"
|
||||||
|
+ "IN d DATE,"
|
||||||
|
+ "IN f FLOAT) BEGIN "
|
||||||
|
+ "INSERT INTO " + tableName + " "
|
||||||
|
+ "VALUES(id,"
|
||||||
|
+ "msg,"
|
||||||
|
+ "d,"
|
||||||
|
+ "f,"
|
||||||
|
+ "concat(msg, '_2')); END";
|
||||||
|
|
||||||
|
try {
|
||||||
|
dropTableIfExists(tableName);
|
||||||
|
dropProcedureIfExists(procName);
|
||||||
|
} catch (SQLException sqle) {
|
||||||
|
throw new AssertionError(sqle.getMessage());
|
||||||
|
}
|
||||||
|
Connection conn = getConnection();
|
||||||
|
|
||||||
|
try {
|
||||||
|
Statement st = conn.createStatement();
|
||||||
|
st.executeUpdate(createTableSql);
|
||||||
|
LOG.debug("Successfully created table " + tableName);
|
||||||
|
st.executeUpdate(createProcSql);
|
||||||
|
LOG.debug("Successfully created procedure " + procName);
|
||||||
|
st.close();
|
||||||
|
} catch (SQLException sqle) {
|
||||||
|
throw new AssertionError(sqle.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Connection getConnection() {
|
||||||
|
try {
|
||||||
|
return getManager().getConnection();
|
||||||
|
} catch (SQLException sqle) {
|
||||||
|
throw new AssertionError(sqle.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean useHsqldbTestServer() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getConnectString() {
|
||||||
|
return MySQLTestUtils.CONNECT_STRING;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected SqoopOptions getSqoopOptions(Configuration conf) {
|
||||||
|
SqoopOptions opts = new SqoopOptions(conf);
|
||||||
|
opts.setUsername(MySQLTestUtils.getCurrentUser());
|
||||||
|
return opts;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getTableName() {
|
||||||
|
return tableName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void dropTableIfExists(String table) throws SQLException {
|
||||||
|
Connection conn = getManager().getConnection();
|
||||||
|
PreparedStatement statement = conn.prepareStatement(
|
||||||
|
"DROP TABLE IF EXISTS " + table,
|
||||||
|
ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
|
||||||
|
try {
|
||||||
|
statement.executeUpdate();
|
||||||
|
conn.commit();
|
||||||
|
} finally {
|
||||||
|
statement.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void dropProcedureIfExists(String proc) throws SQLException {
|
||||||
|
Connection conn = getManager().getConnection();
|
||||||
|
PreparedStatement statement = conn.prepareStatement(
|
||||||
|
"DROP PROCEDURE IF EXISTS " + proc,
|
||||||
|
ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
|
||||||
|
try {
|
||||||
|
statement.executeUpdate();
|
||||||
|
conn.commit();
|
||||||
|
} finally {
|
||||||
|
statement.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testExportUsingProcedure() throws IOException, SQLException {
|
||||||
|
String[] lines = {
|
||||||
|
"0,textfield0,2002-12-29,3300",
|
||||||
|
"1,textfield1,2007-06-04,4400",
|
||||||
|
};
|
||||||
|
new File(getWarehouseDir()).mkdirs();
|
||||||
|
File file = new File(getWarehouseDir() + "/part-00000");
|
||||||
|
Writer output = new BufferedWriter(new FileWriter(file));
|
||||||
|
for (String line : lines) {
|
||||||
|
output.write(line);
|
||||||
|
output.write("\n");
|
||||||
|
}
|
||||||
|
output.close();
|
||||||
|
runExport(getArgv());
|
||||||
|
verifyExport(2, getConnection());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,213 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* 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.apache.sqoop.manager.oracle;
|
||||||
|
|
||||||
|
import java.io.BufferedWriter;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.Writer;
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Statement;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.apache.hadoop.conf.Configuration;
|
||||||
|
|
||||||
|
import com.cloudera.sqoop.SqoopOptions;
|
||||||
|
import com.cloudera.sqoop.manager.OracleUtils;
|
||||||
|
import com.cloudera.sqoop.testutil.CommonArgs;
|
||||||
|
import com.cloudera.sqoop.testutil.ExportJobTestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test free form query import with the MySQL db.
|
||||||
|
*/
|
||||||
|
public class OracleCallExportTest extends ExportJobTestCase {
|
||||||
|
|
||||||
|
public static final Log LOG = LogFactory.getLog(
|
||||||
|
OracleCallExportTest.class.getName());
|
||||||
|
|
||||||
|
private final String tableName = "ORACLE_CALL_EXPORT_BASE_TABLE";
|
||||||
|
private final String procName = "ORACLE_CALL_EXPORT_PROC";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setUp() {
|
||||||
|
super.setUp();
|
||||||
|
createObjects();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private String[] getArgv(String... extraArgs) {
|
||||||
|
ArrayList<String> args = new ArrayList<String>();
|
||||||
|
|
||||||
|
CommonArgs.addHadoopFlags(args);
|
||||||
|
|
||||||
|
args.add("--call");
|
||||||
|
args.add(procName);
|
||||||
|
args.add("--export-dir");
|
||||||
|
args.add(getWarehouseDir());
|
||||||
|
args.add("--fields-terminated-by");
|
||||||
|
args.add(",");
|
||||||
|
args.add("--lines-terminated-by");
|
||||||
|
args.add("\\n");
|
||||||
|
args.add("--connect");
|
||||||
|
args.add(getConnectString());
|
||||||
|
args.add("--username");
|
||||||
|
args.add(OracleUtils.ORACLE_USER_NAME);
|
||||||
|
args.add("--password");
|
||||||
|
args.add(OracleUtils.ORACLE_USER_PASS);
|
||||||
|
args.add("-m");
|
||||||
|
args.add("1");
|
||||||
|
|
||||||
|
for (String arg : extraArgs) {
|
||||||
|
args.add(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return args.toArray(new String[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void createObjects() {
|
||||||
|
|
||||||
|
String createTableSql = "CREATE TABLE " + tableName + " ( "
|
||||||
|
+ "id INT NOT NULL PRIMARY KEY, "
|
||||||
|
+ "msg VARCHAR(24) NOT NULL, "
|
||||||
|
+ "d DATE, "
|
||||||
|
+ "f FLOAT, "
|
||||||
|
+ "vc VARCHAR(32))";
|
||||||
|
|
||||||
|
String createProcSql = "CREATE PROCEDURE " + procName + " ( "
|
||||||
|
+ "id IN INT,"
|
||||||
|
+ "msg IN VARCHAR,"
|
||||||
|
+ "d IN DATE,"
|
||||||
|
+ "f IN FLOAT) IS BEGIN "
|
||||||
|
+ "INSERT INTO " + tableName + " "
|
||||||
|
+ "VALUES(id,"
|
||||||
|
+ "msg,"
|
||||||
|
+ "d,"
|
||||||
|
+ "f,"
|
||||||
|
+ "msg || '_2'); END;";
|
||||||
|
|
||||||
|
try {
|
||||||
|
dropTableIfExists(tableName);
|
||||||
|
dropProcedureIfExists(procName);
|
||||||
|
} catch (SQLException sqle) {
|
||||||
|
throw new AssertionError(sqle.getMessage());
|
||||||
|
}
|
||||||
|
Connection conn = getConnection();
|
||||||
|
|
||||||
|
try {
|
||||||
|
Statement st = conn.createStatement();
|
||||||
|
st.executeUpdate(createTableSql);
|
||||||
|
LOG.debug("Successfully created table " + tableName);
|
||||||
|
st.executeUpdate(createProcSql);
|
||||||
|
LOG.debug("Successfully created procedure " + procName);
|
||||||
|
st.close();
|
||||||
|
} catch (SQLException sqle) {
|
||||||
|
throw new AssertionError(sqle.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Connection getConnection() {
|
||||||
|
try {
|
||||||
|
return getManager().getConnection();
|
||||||
|
} catch (SQLException sqle) {
|
||||||
|
throw new AssertionError(sqle.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean useHsqldbTestServer() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getConnectString() {
|
||||||
|
return OracleUtils.CONNECT_STRING;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected SqoopOptions getSqoopOptions(Configuration conf) {
|
||||||
|
SqoopOptions opts = new SqoopOptions(conf);
|
||||||
|
opts.setUsername(OracleUtils.ORACLE_USER_NAME);
|
||||||
|
opts.setPassword(OracleUtils.ORACLE_USER_PASS);
|
||||||
|
return opts;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getTableName() {
|
||||||
|
return tableName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void dropTableIfExists(String table) throws SQLException {
|
||||||
|
Connection conn = getManager().getConnection();
|
||||||
|
PreparedStatement statement = conn.prepareStatement(
|
||||||
|
"DROP TABLE " + table,
|
||||||
|
ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
statement.executeUpdate();
|
||||||
|
} catch (SQLException sqle) {
|
||||||
|
// Ignore
|
||||||
|
}
|
||||||
|
conn.commit();
|
||||||
|
} finally {
|
||||||
|
statement.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void dropProcedureIfExists(String proc) throws SQLException {
|
||||||
|
Connection conn = getManager().getConnection();
|
||||||
|
PreparedStatement statement = conn.prepareStatement(
|
||||||
|
"DROP PROCEDURE " + proc,
|
||||||
|
ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
statement.executeUpdate();
|
||||||
|
} catch (SQLException sqle) {
|
||||||
|
// Ignore
|
||||||
|
}
|
||||||
|
conn.commit();
|
||||||
|
} finally {
|
||||||
|
statement.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void testExportUsingProcedure() throws IOException, SQLException {
|
||||||
|
String[] lines = {
|
||||||
|
"0,textfield0,2002-12-29 08:40:00,3300",
|
||||||
|
"1,textfield1,2007-06-04 13:15:10,4400",
|
||||||
|
};
|
||||||
|
new File(getWarehouseDir()).mkdirs();
|
||||||
|
File file = new File(getWarehouseDir() + "/part-00000");
|
||||||
|
Writer output = new BufferedWriter(new FileWriter(file));
|
||||||
|
for (String line : lines) {
|
||||||
|
output.write(line);
|
||||||
|
output.write("\n");
|
||||||
|
}
|
||||||
|
output.close();
|
||||||
|
runExport(getArgv());
|
||||||
|
verifyExport(2, getConnection());
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user