mirror of
https://github.com/apache/sqoop.git
synced 2025-05-19 02:10:54 +08:00
SQOOP-605: Generic JDBC connector for import
(Bilung Lee via Jarek Jarcec Cecho)
This commit is contained in:
parent
f1893ab9bb
commit
d4b4df8825
@ -35,8 +35,41 @@ limitations under the License.
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.sqoop</groupId>
|
<groupId>org.apache.sqoop</groupId>
|
||||||
<artifactId>sqoop-spi</artifactId>
|
<artifactId>sqoop-spi</artifactId>
|
||||||
<version>2.0.0-SNAPSHOT</version>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-lang</groupId>
|
||||||
|
<artifactId>commons-lang</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.derby</groupId>
|
||||||
|
<artifactId>derby</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<finalName>sqoop</finalName>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>test-jar</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
@ -86,7 +86,13 @@ public class GenericJdbcConnector implements SqoopConnector {
|
|||||||
forms = new ArrayList<MForm>();
|
forms = new ArrayList<MForm>();
|
||||||
inputs = new ArrayList<MInput<?>>();
|
inputs = new ArrayList<MInput<?>>();
|
||||||
|
|
||||||
inputs.add(new MStringInput(INPUT_TBL_TABLE, false, (short) 50));
|
inputs.add(new MStringInput(INPUT_TBL_NAME, false, (short) 50));
|
||||||
|
inputs.add(new MStringInput(INPUT_TBL_SQL, false, (short) 50));
|
||||||
|
inputs.add(new MStringInput(INPUT_TBL_COLUMNS, false, (short) 50));
|
||||||
|
inputs.add(new MStringInput(INPUT_TBL_WAREHOUSE, false, (short) 50));
|
||||||
|
inputs.add(new MStringInput(INPUT_TBL_DATADIR, false, (short) 50));
|
||||||
|
inputs.add(new MStringInput(INPUT_TBL_PCOL, false, (short) 50));
|
||||||
|
inputs.add(new MStringInput(INPUT_TBL_BOUNDARY, false, (short) 50));
|
||||||
forms.add(new MForm(FORM_TABLE, inputs));
|
forms.add(new MForm(FORM_TABLE, inputs));
|
||||||
|
|
||||||
JOB_FORMS = new ArrayList<MJobForms>();
|
JOB_FORMS = new ArrayList<MJobForms>();
|
||||||
|
@ -43,7 +43,54 @@ public final class GenericJdbcConnectorConstants {
|
|||||||
public static final String FORM_TABLE = "form-table";
|
public static final String FORM_TABLE = "form-table";
|
||||||
|
|
||||||
// Table form inputs
|
// Table form inputs
|
||||||
public static final String INPUT_TBL_TABLE = "inp-tbl-table";
|
public static final String INPUT_TBL_NAME = "inp-tbl-name";
|
||||||
|
public static final String INPUT_TBL_SQL = "inp-tbl-sql";
|
||||||
|
public static final String INPUT_TBL_COLUMNS = "inp-tbl-columns";
|
||||||
|
public static final String INPUT_TBL_WAREHOUSE = "inp-tbl-warehouse";
|
||||||
|
public static final String INPUT_TBL_DATADIR = "inp-tbl-datadir";
|
||||||
|
public static final String INPUT_TBL_PCOL = "inp-tbl-pcol";
|
||||||
|
public static final String INPUT_TBL_BOUNDARY = "inp-tbl-boundary";
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* All jdbc connector related configuration is prefixed with this:
|
||||||
|
* <tt>org.apache.sqoop.jdbc.</tt>
|
||||||
|
*/
|
||||||
|
public static final String PREFIX_CONNECTOR_JDBC_CONFIG =
|
||||||
|
"org.apache.sqoop.connector.jdbc.";
|
||||||
|
|
||||||
|
public static final String CONNECTOR_JDBC_DRIVER =
|
||||||
|
PREFIX_CONNECTOR_JDBC_CONFIG + "driver";
|
||||||
|
public static final String CONNECTOR_JDBC_URL =
|
||||||
|
PREFIX_CONNECTOR_JDBC_CONFIG + "url";
|
||||||
|
public static final String CONNECTOR_JDBC_USERNAME =
|
||||||
|
PREFIX_CONNECTOR_JDBC_CONFIG + "username";
|
||||||
|
public static final String CONNECTOR_JDBC_PASSWORD =
|
||||||
|
PREFIX_CONNECTOR_JDBC_CONFIG + "password";
|
||||||
|
|
||||||
|
public static final String CONNECTOR_JDBC_PARTITION_COLUMNNAME =
|
||||||
|
PREFIX_CONNECTOR_JDBC_CONFIG + "partition.columnname";
|
||||||
|
public static final String CONNECTOR_JDBC_PARTITION_COLUMNTYPE =
|
||||||
|
PREFIX_CONNECTOR_JDBC_CONFIG + "partition.columntype";
|
||||||
|
public static final String CONNECTOR_JDBC_PARTITION_MINVALUE =
|
||||||
|
PREFIX_CONNECTOR_JDBC_CONFIG + "partition.minvalue";
|
||||||
|
public static final String CONNECTOR_JDBC_PARTITION_MAXVALUE =
|
||||||
|
PREFIX_CONNECTOR_JDBC_CONFIG + "partition.maxvalue";
|
||||||
|
|
||||||
|
public static final String CONNECTOR_JDBC_DATA_SQL =
|
||||||
|
PREFIX_CONNECTOR_JDBC_CONFIG + "data.sql";
|
||||||
|
|
||||||
|
public static final String FILE_SEPARATOR = System.getProperty("file.separator");
|
||||||
|
|
||||||
|
public static final String DEFAULT_WAREHOUSE = "/tmp/sqoop/warehouse/";
|
||||||
|
|
||||||
|
public static final String DEFAULT_DATADIR = "DataStore";
|
||||||
|
|
||||||
|
public static final String SQL_CONDITIONS_TOKEN = "${CONDITIONS}";
|
||||||
|
|
||||||
|
public static final String SQL_PARAMETER_MARKER = "?";
|
||||||
|
|
||||||
|
public static final String SUBQUERY_ALIAS = "SQOOP_SUBQUERY_ALIAS";
|
||||||
|
|
||||||
private GenericJdbcConnectorConstants() {
|
private GenericJdbcConnectorConstants() {
|
||||||
// Disable explicit object creation
|
// Disable explicit object creation
|
||||||
|
@ -0,0 +1,83 @@
|
|||||||
|
/**
|
||||||
|
* 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.connector.jdbc;
|
||||||
|
|
||||||
|
import org.apache.sqoop.common.ErrorCode;
|
||||||
|
|
||||||
|
public enum GenericJdbcConnectorError implements ErrorCode {
|
||||||
|
|
||||||
|
/** Unable to load the driver class. */
|
||||||
|
GENERIC_JDBC_CONNECTOR_0000("Unable to load the driver class"),
|
||||||
|
|
||||||
|
/** Unable to get a connection. */
|
||||||
|
GENERIC_JDBC_CONNECTOR_0001("Unable to get a connection"),
|
||||||
|
|
||||||
|
/** Unable to execute the SQL statement. */
|
||||||
|
GENERIC_JDBC_CONNECTOR_0002("Unable to execute the SQL statement"),
|
||||||
|
|
||||||
|
/** Unable to access meta data. */
|
||||||
|
GENERIC_JDBC_CONNECTOR_0003("Unable to access meta data"),
|
||||||
|
|
||||||
|
/** Error occurs while retrieving data from result. */
|
||||||
|
GENERIC_JDBC_CONNECTOR_0004("Error occurs while retrieving data from result"),
|
||||||
|
|
||||||
|
/** No column is found to partition data. */
|
||||||
|
GENERIC_JDBC_CONNECTOR_0005("No column is found to partition data"),
|
||||||
|
|
||||||
|
/** No boundaries are found for partition column. */
|
||||||
|
GENERIC_JDBC_CONNECTOR_0006("No boundaries are found for partition column"),
|
||||||
|
|
||||||
|
/** The table name and the table sql cannot be specify together. */
|
||||||
|
GENERIC_JDBC_CONNECTOR_0007("The table name and the table sql "
|
||||||
|
+ "cannot be specified together"),
|
||||||
|
|
||||||
|
/** Neither the table name nor the table sql are specified. */
|
||||||
|
GENERIC_JDBC_CONNECTOR_0008("Neither the table name nor the table sql "
|
||||||
|
+ "are specified"),
|
||||||
|
|
||||||
|
/** No substitute token in the specified sql. */
|
||||||
|
GENERIC_JDBC_CONNECTOR_0010("No substitute token in the specified sql"),
|
||||||
|
|
||||||
|
/** The type is not supported. */
|
||||||
|
GENERIC_JDBC_CONNECTOR_0011("The type is not supported"),
|
||||||
|
|
||||||
|
/** The required option has not been set yet. */
|
||||||
|
GENERIC_JDBC_CONNECTOR_0012("The required option has not been set yet"),
|
||||||
|
|
||||||
|
/** No parameter marker in the specified sql. */
|
||||||
|
GENERIC_JDBC_CONNECTOR_0013("No parameter marker in the specified sql"),
|
||||||
|
|
||||||
|
/** The table columns cannot be specified when
|
||||||
|
* the table sql is specified during export. */
|
||||||
|
GENERIC_JDBC_CONNECTOR_0014("The table columns cannot be specified "
|
||||||
|
+ "when the table sql is specified during export");
|
||||||
|
|
||||||
|
private final String message;
|
||||||
|
|
||||||
|
private GenericJdbcConnectorError(String message) {
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCode() {
|
||||||
|
return name();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,172 @@
|
|||||||
|
/**
|
||||||
|
* 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.connector.jdbc;
|
||||||
|
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.DatabaseMetaData;
|
||||||
|
import java.sql.DriverManager;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.ResultSetMetaData;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Statement;
|
||||||
|
|
||||||
|
import org.apache.sqoop.common.SqoopException;
|
||||||
|
|
||||||
|
public class GenericJdbcExecutor {
|
||||||
|
|
||||||
|
private Connection connection;
|
||||||
|
|
||||||
|
public GenericJdbcExecutor(String driver, String url,
|
||||||
|
String username, String password) {
|
||||||
|
try {
|
||||||
|
Class.forName(driver);
|
||||||
|
connection = DriverManager.getConnection(url, username, password);
|
||||||
|
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
throw new SqoopException(
|
||||||
|
GenericJdbcConnectorError.GENERIC_JDBC_CONNECTOR_0000, driver, e);
|
||||||
|
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new SqoopException(
|
||||||
|
GenericJdbcConnectorError.GENERIC_JDBC_CONNECTOR_0001, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResultSet executeQuery(String sql) {
|
||||||
|
try {
|
||||||
|
Statement statement = connection.createStatement(
|
||||||
|
ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
|
||||||
|
return statement.executeQuery(sql);
|
||||||
|
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new SqoopException(
|
||||||
|
GenericJdbcConnectorError.GENERIC_JDBC_CONNECTOR_0002, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void executeUpdate(String sql) {
|
||||||
|
try {
|
||||||
|
Statement statement = connection.createStatement(
|
||||||
|
ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
|
||||||
|
statement.executeUpdate(sql);
|
||||||
|
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new SqoopException(
|
||||||
|
GenericJdbcConnectorError.GENERIC_JDBC_CONNECTOR_0002, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPrimaryKey(String table) {
|
||||||
|
try {
|
||||||
|
String[] splitNames = dequalify(table);
|
||||||
|
DatabaseMetaData dbmd = connection.getMetaData();
|
||||||
|
ResultSet rs = dbmd.getPrimaryKeys(null, splitNames[0], splitNames[1]);
|
||||||
|
|
||||||
|
if (rs != null && rs.next()) {
|
||||||
|
return rs.getString("COLUMN_NAME");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new SqoopException(
|
||||||
|
GenericJdbcConnectorError.GENERIC_JDBC_CONNECTOR_0003, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] getQueryColumns(String query) {
|
||||||
|
try {
|
||||||
|
Statement statement = connection.createStatement(
|
||||||
|
ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
|
||||||
|
ResultSet rs = statement.executeQuery(query);
|
||||||
|
|
||||||
|
ResultSetMetaData rsmd = rs.getMetaData();
|
||||||
|
int count = rsmd.getColumnCount();
|
||||||
|
String[] columns = new String[count];
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
columns[i] = rsmd.getColumnName(i+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return columns;
|
||||||
|
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new SqoopException(
|
||||||
|
GenericJdbcConnectorError.GENERIC_JDBC_CONNECTOR_0003, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean existTable(String table) {
|
||||||
|
try {
|
||||||
|
String[] splitNames = dequalify(table);
|
||||||
|
|
||||||
|
DatabaseMetaData dbmd = connection.getMetaData();
|
||||||
|
ResultSet rs = dbmd.getTables(null, splitNames[0], splitNames[1], null);
|
||||||
|
|
||||||
|
if (rs.next()) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new SqoopException(
|
||||||
|
GenericJdbcConnectorError.GENERIC_JDBC_CONNECTOR_0003, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If not qualified already, the name will be added with the qualifier.
|
||||||
|
* If qualified already, old qualifier will be replaced.
|
||||||
|
*/
|
||||||
|
public String qualify(String name, String qualifier) {
|
||||||
|
String[] splits = dequalify(name);
|
||||||
|
return qualifier + "." + splits[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Split the name into a qualifier (element 0) and a base (element 1).
|
||||||
|
*/
|
||||||
|
public String[] dequalify(String name) {
|
||||||
|
String qualifier;
|
||||||
|
String base;
|
||||||
|
int dot = name.indexOf(".");
|
||||||
|
if (dot != -1) {
|
||||||
|
qualifier = name.substring(0, dot);
|
||||||
|
base = name.substring(dot + 1);
|
||||||
|
} else {
|
||||||
|
qualifier = null;
|
||||||
|
base = name;
|
||||||
|
}
|
||||||
|
return new String[] {qualifier, base};
|
||||||
|
}
|
||||||
|
|
||||||
|
public String delimitIdentifier(String name) {
|
||||||
|
return "\"" + name + "\"";
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() {
|
||||||
|
try {
|
||||||
|
connection.close();
|
||||||
|
|
||||||
|
} catch (SQLException e) {
|
||||||
|
// TODO: Log the exception
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -19,11 +19,12 @@
|
|||||||
|
|
||||||
import org.apache.sqoop.job.etl.MutableContext;
|
import org.apache.sqoop.job.etl.MutableContext;
|
||||||
import org.apache.sqoop.job.etl.Initializer;
|
import org.apache.sqoop.job.etl.Initializer;
|
||||||
|
import org.apache.sqoop.job.etl.Options;
|
||||||
|
|
||||||
public class GenericJdbcExportInitializer extends Initializer {
|
public class GenericJdbcExportInitializer extends Initializer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run(MutableContext context) {
|
public void run(MutableContext context, Options options) {
|
||||||
// TODO Auto-generated method stub
|
// TODO Auto-generated method stub
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,6 +17,11 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.sqoop.connector.jdbc;
|
package org.apache.sqoop.connector.jdbc;
|
||||||
|
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.ResultSetMetaData;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
import org.apache.sqoop.common.SqoopException;
|
||||||
import org.apache.sqoop.job.etl.Context;
|
import org.apache.sqoop.job.etl.Context;
|
||||||
import org.apache.sqoop.job.etl.Partition;
|
import org.apache.sqoop.job.etl.Partition;
|
||||||
import org.apache.sqoop.job.etl.Extractor;
|
import org.apache.sqoop.job.etl.Extractor;
|
||||||
@ -26,7 +31,43 @@ public class GenericJdbcImportExtractor extends Extractor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run(Context context, Partition partition, DataWriter writer) {
|
public void run(Context context, Partition partition, DataWriter writer) {
|
||||||
// TODO Auto-generated method stub
|
String driver = context.getString(
|
||||||
|
GenericJdbcConnectorConstants.CONNECTOR_JDBC_DRIVER);
|
||||||
|
String url = context.getString(
|
||||||
|
GenericJdbcConnectorConstants.CONNECTOR_JDBC_URL);
|
||||||
|
String username = context.getString(
|
||||||
|
GenericJdbcConnectorConstants.CONNECTOR_JDBC_USERNAME);
|
||||||
|
String password = context.getString(
|
||||||
|
GenericJdbcConnectorConstants.CONNECTOR_JDBC_PASSWORD);
|
||||||
|
GenericJdbcExecutor executor = new GenericJdbcExecutor(
|
||||||
|
driver, url, username, password);
|
||||||
|
|
||||||
|
String query = context.getString(
|
||||||
|
GenericJdbcConnectorConstants.CONNECTOR_JDBC_DATA_SQL);
|
||||||
|
String conditions =
|
||||||
|
((GenericJdbcImportPartition)partition).getConditions();
|
||||||
|
query = query.replace(
|
||||||
|
GenericJdbcConnectorConstants.SQL_CONDITIONS_TOKEN, conditions);
|
||||||
|
ResultSet resultSet = executor.executeQuery(query);
|
||||||
|
|
||||||
|
try {
|
||||||
|
ResultSetMetaData metaData = resultSet.getMetaData();
|
||||||
|
int column = metaData.getColumnCount();
|
||||||
|
Object[] array = new Object[column];
|
||||||
|
while (resultSet.next()) {
|
||||||
|
for (int i = 0; i< column; i++) {
|
||||||
|
array[i] = resultSet.getObject(i+1);
|
||||||
|
}
|
||||||
|
writer.writeArrayRecord(array);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new SqoopException(
|
||||||
|
GenericJdbcConnectorError.GENERIC_JDBC_CONNECTOR_0004, e);
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
executor.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -17,14 +17,301 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.sqoop.connector.jdbc;
|
package org.apache.sqoop.connector.jdbc;
|
||||||
|
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.ResultSetMetaData;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
import org.apache.sqoop.common.SqoopException;
|
||||||
|
import org.apache.sqoop.job.Constants;
|
||||||
import org.apache.sqoop.job.etl.MutableContext;
|
import org.apache.sqoop.job.etl.MutableContext;
|
||||||
import org.apache.sqoop.job.etl.Initializer;
|
import org.apache.sqoop.job.etl.Initializer;
|
||||||
|
import org.apache.sqoop.job.etl.Options;
|
||||||
|
|
||||||
public class GenericJdbcImportInitializer extends Initializer {
|
public class GenericJdbcImportInitializer extends Initializer {
|
||||||
|
|
||||||
|
private MutableContext context;
|
||||||
|
private Options options;
|
||||||
|
|
||||||
|
private GenericJdbcExecutor executor;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run(MutableContext context) {
|
public void run(MutableContext context, Options options) {
|
||||||
// TODO Auto-generated method stub
|
this.context = context;
|
||||||
|
this.options = options;
|
||||||
|
|
||||||
|
configureJdbcProperties();
|
||||||
|
try {
|
||||||
|
configurePartitionProperties();
|
||||||
|
configureTableProperties();
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
executor.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void configureJdbcProperties() {
|
||||||
|
String driver = options.getOption(
|
||||||
|
GenericJdbcConnectorConstants.INPUT_CONN_JDBCDRIVER);
|
||||||
|
String url = options.getOption(
|
||||||
|
GenericJdbcConnectorConstants.INPUT_CONN_CONNECTSTRING);
|
||||||
|
String username = options.getOption(
|
||||||
|
GenericJdbcConnectorConstants.INPUT_CONN_USERNAME);
|
||||||
|
String password = options.getOption(
|
||||||
|
GenericJdbcConnectorConstants.INPUT_CONN_PASSWORD);
|
||||||
|
|
||||||
|
if (driver == null) {
|
||||||
|
throw new SqoopException(
|
||||||
|
GenericJdbcConnectorError.GENERIC_JDBC_CONNECTOR_0012,
|
||||||
|
GenericJdbcConnectorConstants.INPUT_CONN_JDBCDRIVER);
|
||||||
|
}
|
||||||
|
context.setString(
|
||||||
|
GenericJdbcConnectorConstants.CONNECTOR_JDBC_DRIVER,
|
||||||
|
driver);
|
||||||
|
|
||||||
|
if (url == null) {
|
||||||
|
throw new SqoopException(
|
||||||
|
GenericJdbcConnectorError.GENERIC_JDBC_CONNECTOR_0012,
|
||||||
|
GenericJdbcConnectorConstants.INPUT_CONN_CONNECTSTRING);
|
||||||
|
}
|
||||||
|
context.setString(
|
||||||
|
GenericJdbcConnectorConstants.CONNECTOR_JDBC_URL,
|
||||||
|
url);
|
||||||
|
|
||||||
|
if (username != null) {
|
||||||
|
context.setString(
|
||||||
|
GenericJdbcConnectorConstants.CONNECTOR_JDBC_USERNAME,
|
||||||
|
username);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (password != null) {
|
||||||
|
context.setString(
|
||||||
|
GenericJdbcConnectorConstants.CONNECTOR_JDBC_PASSWORD,
|
||||||
|
password);
|
||||||
|
}
|
||||||
|
|
||||||
|
executor = new GenericJdbcExecutor(driver, url, username, password);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void configurePartitionProperties() {
|
||||||
|
// ----- configure column name -----
|
||||||
|
|
||||||
|
String partitionColumnName = options.getOption(
|
||||||
|
GenericJdbcConnectorConstants.INPUT_TBL_PCOL);
|
||||||
|
|
||||||
|
if (partitionColumnName == null) {
|
||||||
|
// if column is not specified by the user,
|
||||||
|
// find the primary key of the table (when there is a table).
|
||||||
|
String tableName = options.getOption(
|
||||||
|
GenericJdbcConnectorConstants.INPUT_TBL_NAME);
|
||||||
|
if (tableName != null) {
|
||||||
|
partitionColumnName = executor.getPrimaryKey(tableName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (partitionColumnName != null) {
|
||||||
|
context.setString(
|
||||||
|
GenericJdbcConnectorConstants.CONNECTOR_JDBC_PARTITION_COLUMNNAME,
|
||||||
|
partitionColumnName);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
throw new SqoopException(
|
||||||
|
GenericJdbcConnectorError.GENERIC_JDBC_CONNECTOR_0005);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----- configure column type, min value, and max value -----
|
||||||
|
|
||||||
|
String minMaxQuery = options.getOption(
|
||||||
|
GenericJdbcConnectorConstants.INPUT_TBL_BOUNDARY);
|
||||||
|
|
||||||
|
if (minMaxQuery == null) {
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
|
||||||
|
String tableName = options.getOption(
|
||||||
|
GenericJdbcConnectorConstants.INPUT_TBL_NAME);
|
||||||
|
String tableSql = options.getOption(
|
||||||
|
GenericJdbcConnectorConstants.INPUT_TBL_SQL);
|
||||||
|
|
||||||
|
if (tableName != null && tableSql != null) {
|
||||||
|
// when both table name and table sql are specified:
|
||||||
|
throw new SqoopException(
|
||||||
|
GenericJdbcConnectorError.GENERIC_JDBC_CONNECTOR_0007);
|
||||||
|
|
||||||
|
} else if (tableName != null) {
|
||||||
|
// when table name is specified:
|
||||||
|
String column = partitionColumnName;
|
||||||
|
builder.append("SELECT MIN(");
|
||||||
|
builder.append(column);
|
||||||
|
builder.append("), MAX(");
|
||||||
|
builder.append(column);
|
||||||
|
builder.append(") FROM ");
|
||||||
|
builder.append(executor.delimitIdentifier(tableName));
|
||||||
|
|
||||||
|
} else if (tableSql != null) {
|
||||||
|
String column = executor.qualify(
|
||||||
|
partitionColumnName, GenericJdbcConnectorConstants.SUBQUERY_ALIAS);
|
||||||
|
builder.append("SELECT MIN(");
|
||||||
|
builder.append(column);
|
||||||
|
builder.append("), MAX(");
|
||||||
|
builder.append(column);
|
||||||
|
builder.append(") FROM ");
|
||||||
|
builder.append("(");
|
||||||
|
builder.append(tableSql.replace(
|
||||||
|
GenericJdbcConnectorConstants.SQL_CONDITIONS_TOKEN, "1 = 1"));
|
||||||
|
builder.append(") ");
|
||||||
|
builder.append(GenericJdbcConnectorConstants.SUBQUERY_ALIAS);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// when neither are specified:
|
||||||
|
throw new SqoopException(
|
||||||
|
GenericJdbcConnectorError.GENERIC_JDBC_CONNECTOR_0008);
|
||||||
|
}
|
||||||
|
|
||||||
|
minMaxQuery = builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
ResultSet rs = executor.executeQuery(minMaxQuery);
|
||||||
|
try {
|
||||||
|
ResultSetMetaData rsmd = rs.getMetaData();
|
||||||
|
if (rsmd.getColumnCount() != 2) {
|
||||||
|
throw new SqoopException(
|
||||||
|
GenericJdbcConnectorError.GENERIC_JDBC_CONNECTOR_0006);
|
||||||
|
}
|
||||||
|
|
||||||
|
rs.next();
|
||||||
|
|
||||||
|
context.setString(
|
||||||
|
GenericJdbcConnectorConstants.CONNECTOR_JDBC_PARTITION_COLUMNTYPE,
|
||||||
|
String.valueOf(rsmd.getColumnType(1)));
|
||||||
|
context.setString(
|
||||||
|
GenericJdbcConnectorConstants.CONNECTOR_JDBC_PARTITION_MINVALUE,
|
||||||
|
rs.getString(1));
|
||||||
|
context.setString(
|
||||||
|
GenericJdbcConnectorConstants.CONNECTOR_JDBC_PARTITION_MAXVALUE,
|
||||||
|
rs.getString(2));
|
||||||
|
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new SqoopException(
|
||||||
|
GenericJdbcConnectorError.GENERIC_JDBC_CONNECTOR_0006, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void configureTableProperties() {
|
||||||
|
String dataSql;
|
||||||
|
String fieldNames;
|
||||||
|
String outputDirectory;
|
||||||
|
|
||||||
|
String tableName = options.getOption(
|
||||||
|
GenericJdbcConnectorConstants.INPUT_TBL_NAME);
|
||||||
|
String tableSql = options.getOption(
|
||||||
|
GenericJdbcConnectorConstants.INPUT_TBL_SQL);
|
||||||
|
String tableColumns = options.getOption(
|
||||||
|
GenericJdbcConnectorConstants.INPUT_TBL_COLUMNS);
|
||||||
|
|
||||||
|
String datadir = options.getOption(
|
||||||
|
GenericJdbcConnectorConstants.INPUT_TBL_DATADIR);
|
||||||
|
String warehouse = options.getOption(
|
||||||
|
GenericJdbcConnectorConstants.INPUT_TBL_WAREHOUSE);
|
||||||
|
if (warehouse == null) {
|
||||||
|
warehouse = GenericJdbcConnectorConstants.DEFAULT_WAREHOUSE;
|
||||||
|
} else if (!warehouse.endsWith(GenericJdbcConnectorConstants.FILE_SEPARATOR)) {
|
||||||
|
warehouse += GenericJdbcConnectorConstants.FILE_SEPARATOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tableName != null && tableSql != null) {
|
||||||
|
// when both table name and table sql are specified:
|
||||||
|
throw new SqoopException(
|
||||||
|
GenericJdbcConnectorError.GENERIC_JDBC_CONNECTOR_0007);
|
||||||
|
|
||||||
|
} else if (tableName != null) {
|
||||||
|
// when table name is specified:
|
||||||
|
|
||||||
|
if (tableColumns == null) {
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
builder.append("SELECT * FROM ");
|
||||||
|
builder.append(executor.delimitIdentifier(tableName));
|
||||||
|
builder.append(" WHERE ");
|
||||||
|
builder.append(GenericJdbcConnectorConstants.SQL_CONDITIONS_TOKEN);
|
||||||
|
dataSql = builder.toString();
|
||||||
|
|
||||||
|
String[] queryColumns = executor.getQueryColumns(dataSql.replace(
|
||||||
|
GenericJdbcConnectorConstants.SQL_CONDITIONS_TOKEN, "1 = 0"));
|
||||||
|
fieldNames = StringUtils.join(queryColumns, ',');
|
||||||
|
|
||||||
|
} else {
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
builder.append("SELECT ");
|
||||||
|
builder.append(tableColumns);
|
||||||
|
builder.append(" FROM ");
|
||||||
|
builder.append(executor.delimitIdentifier(tableName));
|
||||||
|
builder.append(" WHERE ");
|
||||||
|
builder.append(GenericJdbcConnectorConstants.SQL_CONDITIONS_TOKEN);
|
||||||
|
dataSql = builder.toString();
|
||||||
|
|
||||||
|
fieldNames = tableColumns;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (datadir == null) {
|
||||||
|
outputDirectory = warehouse + tableName;
|
||||||
|
} else {
|
||||||
|
outputDirectory = warehouse + datadir;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (tableSql != null) {
|
||||||
|
// when table sql is specified:
|
||||||
|
|
||||||
|
if (tableSql.indexOf(
|
||||||
|
GenericJdbcConnectorConstants.SQL_CONDITIONS_TOKEN) == -1) {
|
||||||
|
// make sure substitute token for conditions is in the specified sql
|
||||||
|
throw new SqoopException(
|
||||||
|
GenericJdbcConnectorError.GENERIC_JDBC_CONNECTOR_0010);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tableColumns == null) {
|
||||||
|
dataSql = tableSql;
|
||||||
|
|
||||||
|
String[] queryColumns = executor.getQueryColumns(dataSql.replace(
|
||||||
|
GenericJdbcConnectorConstants.SQL_CONDITIONS_TOKEN, "1 = 0"));
|
||||||
|
fieldNames = StringUtils.join(queryColumns, ',');
|
||||||
|
|
||||||
|
} else {
|
||||||
|
String[] columns = StringUtils.split(tableColumns, ',');
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
builder.append("SELECT ");
|
||||||
|
builder.append(executor.qualify(
|
||||||
|
columns[0], GenericJdbcConnectorConstants.SUBQUERY_ALIAS));
|
||||||
|
for (int i = 1; i < columns.length; i++) {
|
||||||
|
builder.append(",");
|
||||||
|
builder.append(executor.qualify(
|
||||||
|
columns[i], GenericJdbcConnectorConstants.SUBQUERY_ALIAS));
|
||||||
|
}
|
||||||
|
builder.append(" FROM ");
|
||||||
|
builder.append("(");
|
||||||
|
builder.append(tableSql);
|
||||||
|
builder.append(") ");
|
||||||
|
builder.append(GenericJdbcConnectorConstants.SUBQUERY_ALIAS);
|
||||||
|
dataSql = builder.toString();
|
||||||
|
|
||||||
|
fieldNames = tableColumns;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (datadir == null) {
|
||||||
|
outputDirectory =
|
||||||
|
warehouse + GenericJdbcConnectorConstants.DEFAULT_DATADIR;
|
||||||
|
} else {
|
||||||
|
outputDirectory = warehouse + datadir;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// when neither are specified:
|
||||||
|
throw new SqoopException(
|
||||||
|
GenericJdbcConnectorError.GENERIC_JDBC_CONNECTOR_0008);
|
||||||
|
}
|
||||||
|
|
||||||
|
context.setString(GenericJdbcConnectorConstants.CONNECTOR_JDBC_DATA_SQL,
|
||||||
|
dataSql.toString());
|
||||||
|
context.setString(Constants.JOB_ETL_FIELD_NAMES, fieldNames);
|
||||||
|
context.setString(Constants.JOB_ETL_OUTPUT_DIRECTORY, outputDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -25,14 +25,24 @@
|
|||||||
|
|
||||||
public class GenericJdbcImportPartition extends Partition {
|
public class GenericJdbcImportPartition extends Partition {
|
||||||
|
|
||||||
|
private String conditions;
|
||||||
|
|
||||||
|
public void setConditions(String conditions) {
|
||||||
|
this.conditions = conditions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getConditions() {
|
||||||
|
return conditions;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void readFields(DataInput in) throws IOException {
|
public void readFields(DataInput in) throws IOException {
|
||||||
// TODO Auto-generated method stub
|
conditions = in.readUTF();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(DataOutput out) throws IOException {
|
public void write(DataOutput out) throws IOException {
|
||||||
// TODO Auto-generated method stub
|
out.writeUTF(conditions);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -17,19 +17,166 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.sqoop.connector.jdbc;
|
package org.apache.sqoop.connector.jdbc;
|
||||||
|
|
||||||
|
import java.sql.Types;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.sqoop.common.SqoopException;
|
||||||
|
import org.apache.sqoop.job.Constants;
|
||||||
import org.apache.sqoop.job.etl.Context;
|
import org.apache.sqoop.job.etl.Context;
|
||||||
import org.apache.sqoop.job.etl.Partition;
|
import org.apache.sqoop.job.etl.Partition;
|
||||||
import org.apache.sqoop.job.etl.Partitioner;
|
import org.apache.sqoop.job.etl.Partitioner;
|
||||||
|
|
||||||
public class GenericJdbcImportPartitioner extends Partitioner {
|
public class GenericJdbcImportPartitioner extends Partitioner {
|
||||||
|
|
||||||
|
private int numberPartitions;
|
||||||
|
private String partitionColumnName;
|
||||||
|
private int partitionColumnType;
|
||||||
|
private String partitionMinValue;
|
||||||
|
private String partitionMaxValue;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Partition> run(Context context) {
|
public List<Partition> run(Context context) {
|
||||||
// TODO Auto-generated method stub
|
numberPartitions = Integer.parseInt(context.getString(
|
||||||
return new LinkedList<Partition>();
|
Constants.JOB_ETL_NUMBER_PARTITIONS));
|
||||||
|
partitionColumnName = context.getString(
|
||||||
|
GenericJdbcConnectorConstants.CONNECTOR_JDBC_PARTITION_COLUMNNAME);
|
||||||
|
partitionColumnType = Integer.parseInt(context.getString(
|
||||||
|
GenericJdbcConnectorConstants.CONNECTOR_JDBC_PARTITION_COLUMNTYPE));
|
||||||
|
partitionMinValue = context.getString(
|
||||||
|
GenericJdbcConnectorConstants.CONNECTOR_JDBC_PARTITION_MINVALUE);
|
||||||
|
partitionMaxValue = context.getString(
|
||||||
|
GenericJdbcConnectorConstants.CONNECTOR_JDBC_PARTITION_MAXVALUE);
|
||||||
|
|
||||||
|
switch (partitionColumnType) {
|
||||||
|
case Types.TINYINT:
|
||||||
|
case Types.SMALLINT:
|
||||||
|
case Types.INTEGER:
|
||||||
|
case Types.BIGINT:
|
||||||
|
// Integer column
|
||||||
|
return partitionIntegerColumn();
|
||||||
|
|
||||||
|
case Types.REAL:
|
||||||
|
case Types.FLOAT:
|
||||||
|
case Types.DOUBLE:
|
||||||
|
// Floating point column
|
||||||
|
return partitionFloatingPointColumn();
|
||||||
|
|
||||||
|
case Types.NUMERIC:
|
||||||
|
case Types.DECIMAL:
|
||||||
|
// Decimal column
|
||||||
|
// TODO: Add partition function
|
||||||
|
|
||||||
|
case Types.BIT:
|
||||||
|
case Types.BOOLEAN:
|
||||||
|
// Boolean column
|
||||||
|
// TODO: Add partition function
|
||||||
|
|
||||||
|
case Types.DATE:
|
||||||
|
case Types.TIME:
|
||||||
|
case Types.TIMESTAMP:
|
||||||
|
// Date time column
|
||||||
|
// TODO: Add partition function
|
||||||
|
|
||||||
|
case Types.CHAR:
|
||||||
|
case Types.VARCHAR:
|
||||||
|
case Types.LONGVARCHAR:
|
||||||
|
// Text column
|
||||||
|
// TODO: Add partition function
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new SqoopException(
|
||||||
|
GenericJdbcConnectorError.GENERIC_JDBC_CONNECTOR_0011,
|
||||||
|
String.valueOf(partitionColumnType));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected List<Partition> partitionIntegerColumn() {
|
||||||
|
List<Partition> partitions = new LinkedList<Partition>();
|
||||||
|
|
||||||
|
if (partitionMinValue == null && partitionMaxValue == null) {
|
||||||
|
GenericJdbcImportPartition partition = new GenericJdbcImportPartition();
|
||||||
|
partition.setConditions(partitionColumnName + "IS NULL");
|
||||||
|
partitions.add(partition);
|
||||||
|
return partitions;
|
||||||
|
}
|
||||||
|
|
||||||
|
long minValue = Long.parseLong(partitionMinValue);
|
||||||
|
long maxValue = Long.parseLong(partitionMaxValue);
|
||||||
|
|
||||||
|
long interval = (maxValue - minValue) / numberPartitions;
|
||||||
|
long remainder = (maxValue - minValue) % numberPartitions;
|
||||||
|
|
||||||
|
if (interval == 0) {
|
||||||
|
numberPartitions = (int)remainder;
|
||||||
|
}
|
||||||
|
|
||||||
|
long lowerBound;
|
||||||
|
long upperBound = minValue;
|
||||||
|
for (int i = 1; i < numberPartitions; i++) {
|
||||||
|
lowerBound = upperBound;
|
||||||
|
upperBound = lowerBound + interval;
|
||||||
|
upperBound += (i <= remainder) ? 1 : 0;
|
||||||
|
|
||||||
|
GenericJdbcImportPartition partition = new GenericJdbcImportPartition();
|
||||||
|
partition.setConditions(
|
||||||
|
constructConditions(lowerBound, upperBound, false));
|
||||||
|
partitions.add(partition);
|
||||||
|
}
|
||||||
|
|
||||||
|
GenericJdbcImportPartition partition = new GenericJdbcImportPartition();
|
||||||
|
partition.setConditions(
|
||||||
|
constructConditions(upperBound, maxValue, true));
|
||||||
|
partitions.add(partition);
|
||||||
|
|
||||||
|
return partitions;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<Partition> partitionFloatingPointColumn() {
|
||||||
|
List<Partition> partitions = new LinkedList<Partition>();
|
||||||
|
|
||||||
|
if (partitionMinValue == null && partitionMaxValue == null) {
|
||||||
|
GenericJdbcImportPartition partition = new GenericJdbcImportPartition();
|
||||||
|
partition.setConditions(partitionColumnName + "IS NULL");
|
||||||
|
partitions.add(partition);
|
||||||
|
return partitions;
|
||||||
|
}
|
||||||
|
|
||||||
|
double minValue = Double.parseDouble(partitionMinValue);
|
||||||
|
double maxValue = Double.parseDouble(partitionMaxValue);
|
||||||
|
|
||||||
|
double interval = (maxValue - minValue) / numberPartitions;
|
||||||
|
|
||||||
|
double lowerBound;
|
||||||
|
double upperBound = minValue;
|
||||||
|
for (int i = 1; i < numberPartitions; i++) {
|
||||||
|
lowerBound = upperBound;
|
||||||
|
upperBound = lowerBound + interval;
|
||||||
|
|
||||||
|
GenericJdbcImportPartition partition = new GenericJdbcImportPartition();
|
||||||
|
partition.setConditions(
|
||||||
|
constructConditions(lowerBound, upperBound, false));
|
||||||
|
partitions.add(partition);
|
||||||
|
}
|
||||||
|
|
||||||
|
GenericJdbcImportPartition partition = new GenericJdbcImportPartition();
|
||||||
|
partition.setConditions(
|
||||||
|
constructConditions(upperBound, maxValue, true));
|
||||||
|
partitions.add(partition);
|
||||||
|
|
||||||
|
return partitions;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String constructConditions(
|
||||||
|
Object lowerBound, Object upperBound, boolean lastOne) {
|
||||||
|
StringBuilder conditions = new StringBuilder();
|
||||||
|
conditions.append(lowerBound);
|
||||||
|
conditions.append(" <= ");
|
||||||
|
conditions.append(partitionColumnName);
|
||||||
|
conditions.append(" AND ");
|
||||||
|
conditions.append(partitionColumnName);
|
||||||
|
conditions.append(lastOne ? " <= " : " < ");
|
||||||
|
conditions.append(upperBound);
|
||||||
|
return conditions.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,5 +54,29 @@ form-table-help = You must supply the information requested in order to create \
|
|||||||
a connection object.
|
a connection object.
|
||||||
|
|
||||||
# Table name
|
# Table name
|
||||||
inp-tbl-table-label = Table name
|
inp-tbl-name-label = Table name
|
||||||
inp-tbl-table-help = Name of the table in remote database
|
inp-tbl-name-help = Table name to process data in the remote database
|
||||||
|
|
||||||
|
# Table SQL
|
||||||
|
inp-tbl-sql-label = Table SQL statement
|
||||||
|
inp-tbl-sql-help = SQL statement to process data in the remote database
|
||||||
|
|
||||||
|
# Table columns
|
||||||
|
inp-tbl-columns-label = Table column names
|
||||||
|
inp-tbl-columns-help = Specific columns of a table name or a table SQL
|
||||||
|
|
||||||
|
# Table warehouse
|
||||||
|
inp-tbl-warehouse-label = Data warehouse
|
||||||
|
inp-tbl-warehouse-help = The root directory for data
|
||||||
|
|
||||||
|
# Table datadir
|
||||||
|
inp-tbl-datadir-label = Data directory
|
||||||
|
inp-tbl-datadir-help = The sub-directory under warehouse for data
|
||||||
|
|
||||||
|
# Table pcol
|
||||||
|
inp-tbl-pcol-label = Partition column name
|
||||||
|
inp-tbl-pcol-help = A specific column for data partition
|
||||||
|
|
||||||
|
# Table boundary
|
||||||
|
inp-tbl-boundary-label = Boundary query
|
||||||
|
inp-tbl-boundary-help = The boundary query for data partition
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
/**
|
||||||
|
* 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.connector.jdbc;
|
||||||
|
|
||||||
|
public class GenericJdbcTestConstants {
|
||||||
|
|
||||||
|
public static final String DRIVER = "org.apache.derby.jdbc.EmbeddedDriver";
|
||||||
|
public static final String URL = "jdbc:derby:memory:TESTDB;create=true";
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,171 @@
|
|||||||
|
/**
|
||||||
|
* 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.connector.jdbc;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import org.apache.sqoop.job.etl.Extractor;
|
||||||
|
import org.apache.sqoop.job.etl.MutableContext;
|
||||||
|
import org.apache.sqoop.job.io.DataWriter;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class TestImportExtractor extends TestCase {
|
||||||
|
|
||||||
|
private final String tableName;
|
||||||
|
|
||||||
|
private GenericJdbcExecutor executor;
|
||||||
|
|
||||||
|
private static final int START = -50;
|
||||||
|
private static final int NUMBER_OF_ROWS = 101;
|
||||||
|
|
||||||
|
public TestImportExtractor() {
|
||||||
|
tableName = getClass().getSimpleName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setUp() {
|
||||||
|
executor = new GenericJdbcExecutor(GenericJdbcTestConstants.DRIVER,
|
||||||
|
GenericJdbcTestConstants.URL, null, null);
|
||||||
|
|
||||||
|
if (!executor.existTable(tableName)) {
|
||||||
|
executor.executeUpdate("CREATE TABLE "
|
||||||
|
+ executor.delimitIdentifier(tableName)
|
||||||
|
+ "(ICOL INTEGER PRIMARY KEY, DCOL DOUBLE, VCOL VARCHAR(20))");
|
||||||
|
|
||||||
|
for (int i = 0; i < NUMBER_OF_ROWS; i++) {
|
||||||
|
int value = START + i;
|
||||||
|
String sql = "INSERT INTO " + executor.delimitIdentifier(tableName)
|
||||||
|
+ " VALUES(" + value + ", " + value + ", '" + value + "')";
|
||||||
|
executor.executeUpdate(sql);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tearDown() {
|
||||||
|
executor.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testQuery() throws Exception {
|
||||||
|
DummyContext context = new DummyContext();
|
||||||
|
context.setString(
|
||||||
|
GenericJdbcConnectorConstants.CONNECTOR_JDBC_DRIVER,
|
||||||
|
GenericJdbcTestConstants.DRIVER);
|
||||||
|
context.setString(
|
||||||
|
GenericJdbcConnectorConstants.CONNECTOR_JDBC_URL,
|
||||||
|
GenericJdbcTestConstants.URL);
|
||||||
|
context.setString(GenericJdbcConnectorConstants.CONNECTOR_JDBC_DATA_SQL,
|
||||||
|
"SELECT * FROM " + executor.delimitIdentifier(tableName)
|
||||||
|
+ " WHERE ${CONDITIONS}");
|
||||||
|
|
||||||
|
GenericJdbcImportPartition partition;
|
||||||
|
|
||||||
|
Extractor extractor = new GenericJdbcImportExtractor();
|
||||||
|
DummyWriter writer = new DummyWriter();
|
||||||
|
|
||||||
|
partition = new GenericJdbcImportPartition();
|
||||||
|
partition.setConditions("-50.0 <= DCOL AND DCOL < -16.6666666666666665");
|
||||||
|
extractor.run(context, partition, writer);
|
||||||
|
|
||||||
|
partition = new GenericJdbcImportPartition();
|
||||||
|
partition.setConditions("-16.6666666666666665 <= DCOL AND DCOL < 16.666666666666667");
|
||||||
|
extractor.run(context, partition, writer);
|
||||||
|
|
||||||
|
partition = new GenericJdbcImportPartition();
|
||||||
|
partition.setConditions("16.666666666666667 <= DCOL AND DCOL <= 50.0");
|
||||||
|
extractor.run(context, partition, writer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSubquery() throws Exception {
|
||||||
|
DummyContext context = new DummyContext();
|
||||||
|
context.setString(
|
||||||
|
GenericJdbcConnectorConstants.CONNECTOR_JDBC_DRIVER,
|
||||||
|
GenericJdbcTestConstants.DRIVER);
|
||||||
|
context.setString(
|
||||||
|
GenericJdbcConnectorConstants.CONNECTOR_JDBC_URL,
|
||||||
|
GenericJdbcTestConstants.URL);
|
||||||
|
context.setString(GenericJdbcConnectorConstants.CONNECTOR_JDBC_DATA_SQL,
|
||||||
|
"SELECT SQOOP_SUBQUERY_ALIAS.ICOL,SQOOP_SUBQUERY_ALIAS.VCOL FROM "
|
||||||
|
+ "(SELECT * FROM " + executor.delimitIdentifier(tableName)
|
||||||
|
+ " WHERE ${CONDITIONS}) SQOOP_SUBQUERY_ALIAS");
|
||||||
|
|
||||||
|
GenericJdbcImportPartition partition;
|
||||||
|
|
||||||
|
Extractor extractor = new GenericJdbcImportExtractor();
|
||||||
|
DummyWriter writer = new DummyWriter();
|
||||||
|
|
||||||
|
partition = new GenericJdbcImportPartition();
|
||||||
|
partition.setConditions("-50 <= ICOL AND ICOL < -16");
|
||||||
|
extractor.run(context, partition, writer);
|
||||||
|
|
||||||
|
partition = new GenericJdbcImportPartition();
|
||||||
|
partition.setConditions("-16 <= ICOL AND ICOL < 17");
|
||||||
|
extractor.run(context, partition, writer);
|
||||||
|
|
||||||
|
partition = new GenericJdbcImportPartition();
|
||||||
|
partition.setConditions("17 <= ICOL AND ICOL < 50");
|
||||||
|
extractor.run(context, partition, writer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DummyContext implements MutableContext {
|
||||||
|
HashMap<String, String> store = new HashMap<String, String>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getString(String key) {
|
||||||
|
return store.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setString(String key, String value) {
|
||||||
|
store.put(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DummyWriter extends DataWriter {
|
||||||
|
int indx = START;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeArrayRecord(Object[] array) {
|
||||||
|
for (int i = 0; i < array.length; i++) {
|
||||||
|
if (array[i] instanceof Integer) {
|
||||||
|
assertEquals(indx, ((Integer)array[i]).intValue());
|
||||||
|
} else if (array[i] instanceof Double) {
|
||||||
|
assertEquals((double)indx, ((Double)array[i]).doubleValue());
|
||||||
|
} else {
|
||||||
|
assertEquals(String.valueOf(indx), array[i].toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
indx++;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeCsvRecord(String csv) {
|
||||||
|
fail("This method should not be invoked.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeRecord(Object record) {
|
||||||
|
fail("This method should not be invoked.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,235 @@
|
|||||||
|
/**
|
||||||
|
* 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.connector.jdbc;
|
||||||
|
|
||||||
|
import java.sql.Types;
|
||||||
|
import java.util.Hashtable;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import org.apache.sqoop.job.Constants;
|
||||||
|
import org.apache.sqoop.job.etl.Initializer;
|
||||||
|
import org.apache.sqoop.job.etl.MutableContext;
|
||||||
|
import org.apache.sqoop.job.etl.Options;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class TestImportInitializer extends TestCase {
|
||||||
|
|
||||||
|
private final String tableName;
|
||||||
|
private final String tableSql;
|
||||||
|
private final String tableColumns;
|
||||||
|
|
||||||
|
private GenericJdbcExecutor executor;
|
||||||
|
|
||||||
|
private static final int START = -50;
|
||||||
|
private static final int NUMBER_OF_ROWS = 101;
|
||||||
|
|
||||||
|
public TestImportInitializer() {
|
||||||
|
tableName = getClass().getSimpleName();
|
||||||
|
tableSql = "SELECT * FROM \"" + tableName + "\" WHERE ${CONDITIONS}";
|
||||||
|
tableColumns = "ICOL,VCOL";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setUp() {
|
||||||
|
executor = new GenericJdbcExecutor(GenericJdbcTestConstants.DRIVER,
|
||||||
|
GenericJdbcTestConstants.URL, null, null);
|
||||||
|
|
||||||
|
if (!executor.existTable(tableName)) {
|
||||||
|
executor.executeUpdate("CREATE TABLE "
|
||||||
|
+ executor.delimitIdentifier(tableName)
|
||||||
|
+ "(ICOL INTEGER PRIMARY KEY, DCOL DOUBLE, VCOL VARCHAR(20))");
|
||||||
|
|
||||||
|
for (int i = 0; i < NUMBER_OF_ROWS; i++) {
|
||||||
|
int value = START + i;
|
||||||
|
String sql = "INSERT INTO " + executor.delimitIdentifier(tableName)
|
||||||
|
+ " VALUES(" + value + ", " + value + ", '" + value + "')";
|
||||||
|
executor.executeUpdate(sql);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tearDown() {
|
||||||
|
executor.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTableName() throws Exception {
|
||||||
|
DummyOptions options = new DummyOptions();
|
||||||
|
options.setOption(GenericJdbcConnectorConstants.INPUT_CONN_JDBCDRIVER,
|
||||||
|
GenericJdbcTestConstants.DRIVER);
|
||||||
|
options.setOption(GenericJdbcConnectorConstants.INPUT_CONN_CONNECTSTRING,
|
||||||
|
GenericJdbcTestConstants.URL);
|
||||||
|
options.setOption(GenericJdbcConnectorConstants.INPUT_TBL_NAME,
|
||||||
|
tableName);
|
||||||
|
|
||||||
|
DummyContext context = new DummyContext();
|
||||||
|
|
||||||
|
Initializer initializer = new GenericJdbcImportInitializer();
|
||||||
|
initializer.run(context, options);
|
||||||
|
|
||||||
|
verifyResult(context,
|
||||||
|
"SELECT * FROM " + executor.delimitIdentifier(tableName)
|
||||||
|
+ " WHERE ${CONDITIONS}",
|
||||||
|
"ICOL,DCOL,VCOL",
|
||||||
|
GenericJdbcConnectorConstants.DEFAULT_WAREHOUSE + tableName,
|
||||||
|
"ICOL",
|
||||||
|
String.valueOf(Types.INTEGER),
|
||||||
|
String.valueOf(START),
|
||||||
|
String.valueOf(START+NUMBER_OF_ROWS-1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTableNameWithTableColumns() throws Exception {
|
||||||
|
DummyOptions options = new DummyOptions();
|
||||||
|
options.setOption(GenericJdbcConnectorConstants.INPUT_CONN_JDBCDRIVER,
|
||||||
|
GenericJdbcTestConstants.DRIVER);
|
||||||
|
options.setOption(GenericJdbcConnectorConstants.INPUT_CONN_CONNECTSTRING,
|
||||||
|
GenericJdbcTestConstants.URL);
|
||||||
|
options.setOption(GenericJdbcConnectorConstants.INPUT_TBL_NAME,
|
||||||
|
tableName);
|
||||||
|
options.setOption(GenericJdbcConnectorConstants.INPUT_TBL_COLUMNS,
|
||||||
|
tableColumns);
|
||||||
|
|
||||||
|
DummyContext context = new DummyContext();
|
||||||
|
|
||||||
|
Initializer initializer = new GenericJdbcImportInitializer();
|
||||||
|
initializer.run(context, options);
|
||||||
|
|
||||||
|
verifyResult(context,
|
||||||
|
"SELECT ICOL,VCOL FROM " + executor.delimitIdentifier(tableName)
|
||||||
|
+ " WHERE ${CONDITIONS}",
|
||||||
|
tableColumns,
|
||||||
|
GenericJdbcConnectorConstants.DEFAULT_WAREHOUSE + tableName,
|
||||||
|
"ICOL",
|
||||||
|
String.valueOf(Types.INTEGER),
|
||||||
|
String.valueOf(START),
|
||||||
|
String.valueOf(START+NUMBER_OF_ROWS-1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTableSql() throws Exception {
|
||||||
|
DummyOptions options = new DummyOptions();
|
||||||
|
options.setOption(GenericJdbcConnectorConstants.INPUT_CONN_JDBCDRIVER,
|
||||||
|
GenericJdbcTestConstants.DRIVER);
|
||||||
|
options.setOption(GenericJdbcConnectorConstants.INPUT_CONN_CONNECTSTRING,
|
||||||
|
GenericJdbcTestConstants.URL);
|
||||||
|
options.setOption(GenericJdbcConnectorConstants.INPUT_TBL_SQL,
|
||||||
|
tableSql);
|
||||||
|
options.setOption(GenericJdbcConnectorConstants.INPUT_TBL_PCOL,
|
||||||
|
"DCOL");
|
||||||
|
|
||||||
|
DummyContext context = new DummyContext();
|
||||||
|
|
||||||
|
Initializer initializer = new GenericJdbcImportInitializer();
|
||||||
|
initializer.run(context, options);
|
||||||
|
|
||||||
|
verifyResult(context,
|
||||||
|
"SELECT * FROM " + executor.delimitIdentifier(tableName)
|
||||||
|
+ " WHERE ${CONDITIONS}",
|
||||||
|
"ICOL,DCOL,VCOL",
|
||||||
|
GenericJdbcConnectorConstants.DEFAULT_WAREHOUSE
|
||||||
|
+ GenericJdbcConnectorConstants.DEFAULT_DATADIR,
|
||||||
|
"DCOL",
|
||||||
|
String.valueOf(Types.DOUBLE),
|
||||||
|
String.valueOf((double)START),
|
||||||
|
String.valueOf((double)(START+NUMBER_OF_ROWS-1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTableSqlWithTableColumns() throws Exception {
|
||||||
|
DummyOptions options = new DummyOptions();
|
||||||
|
options.setOption(GenericJdbcConnectorConstants.INPUT_CONN_JDBCDRIVER,
|
||||||
|
GenericJdbcTestConstants.DRIVER);
|
||||||
|
options.setOption(GenericJdbcConnectorConstants.INPUT_CONN_CONNECTSTRING,
|
||||||
|
GenericJdbcTestConstants.URL);
|
||||||
|
options.setOption(GenericJdbcConnectorConstants.INPUT_TBL_SQL,
|
||||||
|
tableSql);
|
||||||
|
options.setOption(GenericJdbcConnectorConstants.INPUT_TBL_COLUMNS,
|
||||||
|
tableColumns);
|
||||||
|
options.setOption(GenericJdbcConnectorConstants.INPUT_TBL_PCOL,
|
||||||
|
"DCOL");
|
||||||
|
|
||||||
|
DummyContext context = new DummyContext();
|
||||||
|
|
||||||
|
Initializer initializer = new GenericJdbcImportInitializer();
|
||||||
|
initializer.run(context, options);
|
||||||
|
|
||||||
|
verifyResult(context,
|
||||||
|
"SELECT SQOOP_SUBQUERY_ALIAS.ICOL,SQOOP_SUBQUERY_ALIAS.VCOL FROM "
|
||||||
|
+ "(SELECT * FROM " + executor.delimitIdentifier(tableName)
|
||||||
|
+ " WHERE ${CONDITIONS}) SQOOP_SUBQUERY_ALIAS",
|
||||||
|
tableColumns,
|
||||||
|
GenericJdbcConnectorConstants.DEFAULT_WAREHOUSE
|
||||||
|
+ GenericJdbcConnectorConstants.DEFAULT_DATADIR,
|
||||||
|
"DCOL",
|
||||||
|
String.valueOf(Types.DOUBLE),
|
||||||
|
String.valueOf((double)START),
|
||||||
|
String.valueOf((double)(START+NUMBER_OF_ROWS-1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void verifyResult(DummyContext context,
|
||||||
|
String dataSql, String fieldNames, String outputDirectory,
|
||||||
|
String partitionColumnName, String partitionColumnType,
|
||||||
|
String partitionMinValue, String partitionMaxValue) {
|
||||||
|
assertEquals(dataSql, context.getString(
|
||||||
|
GenericJdbcConnectorConstants.CONNECTOR_JDBC_DATA_SQL));
|
||||||
|
assertEquals(fieldNames, context.getString(
|
||||||
|
Constants.JOB_ETL_FIELD_NAMES));
|
||||||
|
assertEquals(outputDirectory, context.getString(
|
||||||
|
Constants.JOB_ETL_OUTPUT_DIRECTORY));
|
||||||
|
|
||||||
|
assertEquals(partitionColumnName, context.getString(
|
||||||
|
GenericJdbcConnectorConstants.CONNECTOR_JDBC_PARTITION_COLUMNNAME));
|
||||||
|
assertEquals(partitionColumnType, context.getString(
|
||||||
|
GenericJdbcConnectorConstants.CONNECTOR_JDBC_PARTITION_COLUMNTYPE));
|
||||||
|
assertEquals(partitionMinValue, context.getString(
|
||||||
|
GenericJdbcConnectorConstants.CONNECTOR_JDBC_PARTITION_MINVALUE));
|
||||||
|
assertEquals(partitionMaxValue, context.getString(
|
||||||
|
GenericJdbcConnectorConstants.CONNECTOR_JDBC_PARTITION_MAXVALUE));
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DummyOptions implements Options {
|
||||||
|
Hashtable<String, String> store = new Hashtable<String, String>();
|
||||||
|
|
||||||
|
public void setOption(String key, String value) {
|
||||||
|
store.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getOption(String key) {
|
||||||
|
return store.get(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DummyContext implements MutableContext {
|
||||||
|
Hashtable<String, String> store = new Hashtable<String, String>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getString(String key) {
|
||||||
|
return store.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setString(String key, String value) {
|
||||||
|
store.put(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,209 @@
|
|||||||
|
/**
|
||||||
|
* 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.connector.jdbc;
|
||||||
|
|
||||||
|
import java.sql.Types;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import org.apache.sqoop.job.Constants;
|
||||||
|
import org.apache.sqoop.job.etl.MutableContext;
|
||||||
|
import org.apache.sqoop.job.etl.Partition;
|
||||||
|
import org.apache.sqoop.job.etl.Partitioner;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class TestImportPartitioner extends TestCase {
|
||||||
|
|
||||||
|
private static final int START = -5;
|
||||||
|
private static final int NUMBER_OF_ROWS = 11;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIntegerEvenPartition() throws Exception {
|
||||||
|
DummyContext context = new DummyContext();
|
||||||
|
context.setString(
|
||||||
|
GenericJdbcConnectorConstants.CONNECTOR_JDBC_PARTITION_COLUMNNAME,
|
||||||
|
"ICOL");
|
||||||
|
context.setString(
|
||||||
|
GenericJdbcConnectorConstants.CONNECTOR_JDBC_PARTITION_COLUMNTYPE,
|
||||||
|
String.valueOf(Types.INTEGER));
|
||||||
|
context.setString(
|
||||||
|
GenericJdbcConnectorConstants.CONNECTOR_JDBC_PARTITION_MINVALUE,
|
||||||
|
String.valueOf(START));
|
||||||
|
context.setString(
|
||||||
|
GenericJdbcConnectorConstants.CONNECTOR_JDBC_PARTITION_MAXVALUE,
|
||||||
|
String.valueOf(START + NUMBER_OF_ROWS - 1));
|
||||||
|
context.setString(Constants.JOB_ETL_NUMBER_PARTITIONS, "5");
|
||||||
|
|
||||||
|
Partitioner partitioner = new GenericJdbcImportPartitioner();
|
||||||
|
List<Partition> partitions = partitioner.run(context);
|
||||||
|
|
||||||
|
verifyResult(partitions, new String[] {
|
||||||
|
"-5 <= ICOL AND ICOL < -3",
|
||||||
|
"-3 <= ICOL AND ICOL < -1",
|
||||||
|
"-1 <= ICOL AND ICOL < 1",
|
||||||
|
"1 <= ICOL AND ICOL < 3",
|
||||||
|
"3 <= ICOL AND ICOL <= 5"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIntegerUnevenPartition() throws Exception {
|
||||||
|
DummyContext context = new DummyContext();
|
||||||
|
context.setString(
|
||||||
|
GenericJdbcConnectorConstants.CONNECTOR_JDBC_PARTITION_COLUMNNAME,
|
||||||
|
"ICOL");
|
||||||
|
context.setString(
|
||||||
|
GenericJdbcConnectorConstants.CONNECTOR_JDBC_PARTITION_COLUMNTYPE,
|
||||||
|
String.valueOf(Types.INTEGER));
|
||||||
|
context.setString(
|
||||||
|
GenericJdbcConnectorConstants.CONNECTOR_JDBC_PARTITION_MINVALUE,
|
||||||
|
String.valueOf(START));
|
||||||
|
context.setString(
|
||||||
|
GenericJdbcConnectorConstants.CONNECTOR_JDBC_PARTITION_MAXVALUE,
|
||||||
|
String.valueOf(START + NUMBER_OF_ROWS - 1));
|
||||||
|
context.setString(Constants.JOB_ETL_NUMBER_PARTITIONS, "3");
|
||||||
|
|
||||||
|
Partitioner partitioner = new GenericJdbcImportPartitioner();
|
||||||
|
List<Partition> partitions = partitioner.run(context);
|
||||||
|
|
||||||
|
verifyResult(partitions, new String[] {
|
||||||
|
"-5 <= ICOL AND ICOL < -1",
|
||||||
|
"-1 <= ICOL AND ICOL < 2",
|
||||||
|
"2 <= ICOL AND ICOL <= 5"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIntegerOverPartition() throws Exception {
|
||||||
|
DummyContext context = new DummyContext();
|
||||||
|
context.setString(
|
||||||
|
GenericJdbcConnectorConstants.CONNECTOR_JDBC_PARTITION_COLUMNNAME,
|
||||||
|
"ICOL");
|
||||||
|
context.setString(
|
||||||
|
GenericJdbcConnectorConstants.CONNECTOR_JDBC_PARTITION_COLUMNTYPE,
|
||||||
|
String.valueOf(Types.INTEGER));
|
||||||
|
context.setString(
|
||||||
|
GenericJdbcConnectorConstants.CONNECTOR_JDBC_PARTITION_MINVALUE,
|
||||||
|
String.valueOf(START));
|
||||||
|
context.setString(
|
||||||
|
GenericJdbcConnectorConstants.CONNECTOR_JDBC_PARTITION_MAXVALUE,
|
||||||
|
String.valueOf(START + NUMBER_OF_ROWS - 1));
|
||||||
|
context.setString(Constants.JOB_ETL_NUMBER_PARTITIONS, "13");
|
||||||
|
|
||||||
|
Partitioner partitioner = new GenericJdbcImportPartitioner();
|
||||||
|
List<Partition> partitions = partitioner.run(context);
|
||||||
|
|
||||||
|
verifyResult(partitions, new String[] {
|
||||||
|
"-5 <= ICOL AND ICOL < -4",
|
||||||
|
"-4 <= ICOL AND ICOL < -3",
|
||||||
|
"-3 <= ICOL AND ICOL < -2",
|
||||||
|
"-2 <= ICOL AND ICOL < -1",
|
||||||
|
"-1 <= ICOL AND ICOL < 0",
|
||||||
|
"0 <= ICOL AND ICOL < 1",
|
||||||
|
"1 <= ICOL AND ICOL < 2",
|
||||||
|
"2 <= ICOL AND ICOL < 3",
|
||||||
|
"3 <= ICOL AND ICOL < 4",
|
||||||
|
"4 <= ICOL AND ICOL <= 5"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFloatingPointEvenPartition() throws Exception {
|
||||||
|
DummyContext context = new DummyContext();
|
||||||
|
context.setString(
|
||||||
|
GenericJdbcConnectorConstants.CONNECTOR_JDBC_PARTITION_COLUMNNAME,
|
||||||
|
"DCOL");
|
||||||
|
context.setString(
|
||||||
|
GenericJdbcConnectorConstants.CONNECTOR_JDBC_PARTITION_COLUMNTYPE,
|
||||||
|
String.valueOf(Types.DOUBLE));
|
||||||
|
context.setString(
|
||||||
|
GenericJdbcConnectorConstants.CONNECTOR_JDBC_PARTITION_MINVALUE,
|
||||||
|
String.valueOf((double)START));
|
||||||
|
context.setString(
|
||||||
|
GenericJdbcConnectorConstants.CONNECTOR_JDBC_PARTITION_MAXVALUE,
|
||||||
|
String.valueOf((double)(START + NUMBER_OF_ROWS - 1)));
|
||||||
|
context.setString(Constants.JOB_ETL_NUMBER_PARTITIONS, "5");
|
||||||
|
|
||||||
|
Partitioner partitioner = new GenericJdbcImportPartitioner();
|
||||||
|
List<Partition> partitions = partitioner.run(context);
|
||||||
|
|
||||||
|
verifyResult(partitions, new String[] {
|
||||||
|
"-5.0 <= DCOL AND DCOL < -3.0",
|
||||||
|
"-3.0 <= DCOL AND DCOL < -1.0",
|
||||||
|
"-1.0 <= DCOL AND DCOL < 1.0",
|
||||||
|
"1.0 <= DCOL AND DCOL < 3.0",
|
||||||
|
"3.0 <= DCOL AND DCOL <= 5.0"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFloatingPointUnevenPartition() throws Exception {
|
||||||
|
DummyContext context = new DummyContext();
|
||||||
|
context.setString(
|
||||||
|
GenericJdbcConnectorConstants.CONNECTOR_JDBC_PARTITION_COLUMNNAME,
|
||||||
|
"DCOL");
|
||||||
|
context.setString(
|
||||||
|
GenericJdbcConnectorConstants.CONNECTOR_JDBC_PARTITION_COLUMNTYPE,
|
||||||
|
String.valueOf(Types.DOUBLE));
|
||||||
|
context.setString(
|
||||||
|
GenericJdbcConnectorConstants.CONNECTOR_JDBC_PARTITION_MINVALUE,
|
||||||
|
String.valueOf((double)START));
|
||||||
|
context.setString(
|
||||||
|
GenericJdbcConnectorConstants.CONNECTOR_JDBC_PARTITION_MAXVALUE,
|
||||||
|
String.valueOf((double)(START + NUMBER_OF_ROWS - 1)));
|
||||||
|
context.setString(Constants.JOB_ETL_NUMBER_PARTITIONS, "3");
|
||||||
|
|
||||||
|
Partitioner partitioner = new GenericJdbcImportPartitioner();
|
||||||
|
List<Partition> partitions = partitioner.run(context);
|
||||||
|
|
||||||
|
verifyResult(partitions, new String[] {
|
||||||
|
"-5.0 <= DCOL AND DCOL < -1.6666666666666665",
|
||||||
|
"-1.6666666666666665 <= DCOL AND DCOL < 1.666666666666667",
|
||||||
|
"1.666666666666667 <= DCOL AND DCOL <= 5.0"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void verifyResult(List<Partition> partitions,
|
||||||
|
String[] expected) {
|
||||||
|
assertEquals(expected.length, partitions.size());
|
||||||
|
|
||||||
|
Iterator<Partition> iterator = partitions.iterator();
|
||||||
|
for (int i = 0; i < expected.length; i++) {
|
||||||
|
assertEquals(expected[i],
|
||||||
|
((GenericJdbcImportPartition)iterator.next()).getConditions());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DummyContext implements MutableContext {
|
||||||
|
HashMap<String, String> store = new HashMap<String, String>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getString(String key) {
|
||||||
|
return store.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setString(String key, String value) {
|
||||||
|
store.put(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
22
core/pom.xml
22
core/pom.xml
@ -35,27 +35,25 @@ limitations under the License.
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.sqoop</groupId>
|
<groupId>org.apache.sqoop</groupId>
|
||||||
<artifactId>sqoop-spi</artifactId>
|
<artifactId>sqoop-spi</artifactId>
|
||||||
<version>2.0.0-SNAPSHOT</version>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.sqoop</groupId>
|
<groupId>org.apache.sqoop</groupId>
|
||||||
<artifactId>sqoop-common</artifactId>
|
<artifactId>sqoop-common</artifactId>
|
||||||
<version>2.0.0-SNAPSHOT</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.hadoop</groupId>
|
|
||||||
<artifactId>hadoop-common</artifactId>
|
|
||||||
<version>2.0.0-SNAPSHOT</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.hadoop</groupId>
|
|
||||||
<artifactId>hadoop-mapreduce-client-jobclient</artifactId>
|
|
||||||
<version>2.0.0-SNAPSHOT</version>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>commons-dbcp</groupId>
|
<groupId>commons-dbcp</groupId>
|
||||||
<artifactId>commons-dbcp</artifactId>
|
<artifactId>commons-dbcp</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.hadoop</groupId>
|
||||||
|
<artifactId>hadoop-common</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.hadoop</groupId>
|
||||||
|
<artifactId>hadoop-mapreduce-client-jobclient</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>junit</groupId>
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>junit</artifactId>
|
||||||
|
@ -84,8 +84,16 @@ public enum CoreError implements ErrorCode {
|
|||||||
/** Error occurs during loader run */
|
/** Error occurs during loader run */
|
||||||
CORE_0018("Error occurs during loader run"),
|
CORE_0018("Error occurs during loader run"),
|
||||||
|
|
||||||
/** Data have not been completely consumed yet */
|
CORE_0019("Data have not been completely consumed yet"),
|
||||||
CORE_0019("Data have not been completely consumed yet");
|
|
||||||
|
/** The required option has not been set yet */
|
||||||
|
CORE_0020("The required option has not been set yet"),
|
||||||
|
|
||||||
|
/** Error occurs during partitioner run */
|
||||||
|
CORE_0021("Error occurs during partitioner run"),
|
||||||
|
|
||||||
|
/** Unable to parse because it is not properly delimited */
|
||||||
|
CORE_0022("Unable to parse because it is not properly delimited");
|
||||||
|
|
||||||
private final String message;
|
private final String message;
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
import org.apache.sqoop.core.ConfigurationConstants;
|
import org.apache.sqoop.core.ConfigurationConstants;
|
||||||
|
|
||||||
public final class JobConstants {
|
public final class JobConstants extends Constants {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All job related configuration is prefixed with this:
|
* All job related configuration is prefixed with this:
|
||||||
|
95
pom.xml
95
pom.xml
@ -91,11 +91,14 @@ limitations under the License.
|
|||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<maven.compile.source>1.6</maven.compile.source>
|
<maven.compile.source>1.6</maven.compile.source>
|
||||||
<maven.compile.target>1.6</maven.compile.target>
|
<maven.compile.target>1.6</maven.compile.target>
|
||||||
<log4j.version>1.2.16</log4j.version>
|
|
||||||
<json-simple.version>1.1</json-simple.version>
|
|
||||||
<commons-dbcp.version>1.4</commons-dbcp.version>
|
<commons-dbcp.version>1.4</commons-dbcp.version>
|
||||||
|
<commons-lang.version>2.5</commons-lang.version>
|
||||||
<derby.version>10.8.2.2</derby.version>
|
<derby.version>10.8.2.2</derby.version>
|
||||||
|
<hadoop.version>2.0.0-SNAPSHOT</hadoop.version>
|
||||||
|
<json-simple.version>1.1</json-simple.version>
|
||||||
<junit.version>4.9</junit.version>
|
<junit.version>4.9</junit.version>
|
||||||
|
<log4j.version>1.2.16</log4j.version>
|
||||||
|
<servlet.version>2.5</servlet.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
@ -108,14 +111,57 @@ limitations under the License.
|
|||||||
<dependencyManagement>
|
<dependencyManagement>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>log4j</groupId>
|
<groupId>org.apache.sqoop</groupId>
|
||||||
<artifactId>log4j</artifactId>
|
<artifactId>sqoop-client</artifactId>
|
||||||
<version>${log4j.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.servlet</groupId>
|
<groupId>org.apache.sqoop</groupId>
|
||||||
<artifactId>servlet-api</artifactId>
|
<artifactId>sqoop-common</artifactId>
|
||||||
<version>2.5</version>
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.sqoop</groupId>
|
||||||
|
<artifactId>sqoop-core</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.sqoop</groupId>
|
||||||
|
<artifactId>sqoop-core</artifactId>
|
||||||
|
<type>test-jar</type>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.sqoop</groupId>
|
||||||
|
<artifactId>sqoop-server</artifactId>
|
||||||
|
<type>war</type>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.sqoop</groupId>
|
||||||
|
<artifactId>sqoop-spi</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.sqoop.repository</groupId>
|
||||||
|
<artifactId>sqoop-repository-derby</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.sqoop.connector</groupId>
|
||||||
|
<artifactId>sqoop-connector-generic-jdbc</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.sqoop.connector</groupId>
|
||||||
|
<artifactId>sqoop-connector-generic-jdbc</artifactId>
|
||||||
|
<type>test-jar</type>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.sqoop.connector</groupId>
|
||||||
|
<artifactId>sqoop-connector-mysql-jdbc</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.googlecode.json-simple</groupId>
|
<groupId>com.googlecode.json-simple</groupId>
|
||||||
@ -128,16 +174,41 @@ limitations under the License.
|
|||||||
<version>${commons-dbcp.version}</version>
|
<version>${commons-dbcp.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.derby</groupId>
|
<groupId>commons-lang</groupId>
|
||||||
<artifactId>derby</artifactId>
|
<artifactId>commons-lang</artifactId>
|
||||||
<version>${derby.version}</version>
|
<version>${commons-lang.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>javax.servlet</groupId>
|
||||||
|
<artifactId>servlet-api</artifactId>
|
||||||
|
<version>${servlet.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>junit</groupId>
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>junit</artifactId>
|
||||||
<version>${junit.version}</version>
|
<version>${junit.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
<dependency>
|
||||||
|
<groupId>log4j</groupId>
|
||||||
|
<artifactId>log4j</artifactId>
|
||||||
|
<version>${log4j.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.derby</groupId>
|
||||||
|
<artifactId>derby</artifactId>
|
||||||
|
<version>${derby.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.hadoop</groupId>
|
||||||
|
<artifactId>hadoop-common</artifactId>
|
||||||
|
<version>${hadoop.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.hadoop</groupId>
|
||||||
|
<artifactId>hadoop-mapreduce-client-jobclient</artifactId>
|
||||||
|
<version>${hadoop.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
|
41
spi/src/main/java/org/apache/sqoop/job/Constants.java
Normal file
41
spi/src/main/java/org/apache/sqoop/job/Constants.java
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/**
|
||||||
|
* 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.job;
|
||||||
|
|
||||||
|
public class Constants {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All job related configuration is prefixed with this:
|
||||||
|
* <tt>org.apache.sqoop.job.</tt>
|
||||||
|
*/
|
||||||
|
public static final String PREFIX_CONFIG = "org.apache.sqoop.job.";
|
||||||
|
|
||||||
|
public static final String JOB_ETL_NUMBER_PARTITIONS = PREFIX_CONFIG
|
||||||
|
+ "etl.number.partitions";
|
||||||
|
|
||||||
|
public static final String JOB_ETL_FIELD_NAMES = PREFIX_CONFIG
|
||||||
|
+ "etl.field.names";
|
||||||
|
|
||||||
|
public static final String JOB_ETL_OUTPUT_DIRECTORY = PREFIX_CONFIG
|
||||||
|
+ "etl.output.directory";
|
||||||
|
|
||||||
|
protected Constants() {
|
||||||
|
// Disable explicit object creation
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -23,6 +23,6 @@
|
|||||||
*/
|
*/
|
||||||
public abstract class Initializer {
|
public abstract class Initializer {
|
||||||
|
|
||||||
public abstract void run(MutableContext context);
|
public abstract void run(MutableContext context, Options options);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
27
spi/src/main/java/org/apache/sqoop/job/etl/Options.java
Normal file
27
spi/src/main/java/org/apache/sqoop/job/etl/Options.java
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/**
|
||||||
|
* 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.job.etl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The options provided from user input.
|
||||||
|
*/
|
||||||
|
public interface Options {
|
||||||
|
|
||||||
|
public String getOption(String key);
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user