5
0
mirror of https://github.com/apache/sqoop.git synced 2025-05-03 10:29:05 +08:00

SQOOP-1358: Add wallet support for Oracle High performance connector

(Venkat Ranganathan via Jarek Jarcec Cecho)
This commit is contained in:
Jarek Jarcec Cecho 2014-07-19 13:18:49 -07:00
parent 9aac957b9c
commit 1e2bc6e72b
7 changed files with 111 additions and 50 deletions

View File

@ -692,13 +692,16 @@ The Sqoop +--connect+ parameter defines the Oracle instance or Oracle RAC to
connect to. It is required with all Sqoop import and export commands.
Data Connector for Oracle and Hadoop expects the associated connection string
to be of a specific format dependent on whether the Oracle SID or Service
is defined.
to be of a specific format dependent on whether the Oracle SID, Service
or TNS name is defined. The TNS name based URL scheme can be used to enable
authentication using Oracle wallets.
+--connect jdbc:oracle:thin:@OracleServer:OraclePort:OracleSID+
+--connect jdbc:oracle:thin:@//OracleServer:OraclePort/OracleService+
+--connect jdbc:oracle:thin:@TNSName+
Connect to An Oracle Database Instance
++++++++++++++++++++++++++++++++++++++
@ -720,6 +723,8 @@ with other drivers such as OCI.
|The Oracle instance.
|+OracleService+
|The Oracle Service.
|+TNSName+
|The TNS name for the entry describing the connection to the Oracle server.
|===============================================================================
[NOTE]

View File

@ -345,7 +345,7 @@ protected Connection makeConnection() throws SQLException {
return connection;
}
public String getSessionUser(Connection conn) {
public static String getSessionUser(Connection conn) {
Statement stmt = null;
ResultSet rset = null;
String user = null;
@ -380,6 +380,9 @@ public String getSessionUser(Connection conn) {
}
}
}
if (user == null) {
throw new RuntimeException("Unable to get current session user");
}
return user;
}

View File

@ -31,6 +31,7 @@
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.mapreduce.OutputFormat;
import org.apache.sqoop.manager.OracleManager;
import com.cloudera.sqoop.SqoopOptions;
import com.cloudera.sqoop.manager.ExportJobContext;
@ -96,7 +97,10 @@ protected Connection makeConnection() throws SQLException {
Connection connection =
OracleConnectionFactory.createOracleJdbcConnection(this
.getDriverClass(), connectStr, username, password, additionalProps);
if (username == null) {
username = OracleManager.getSessionUser(connection);
}
OraOopUtilities.setCurrentSessionUser(username);
return connection;
}
@ -627,4 +631,5 @@ private void explainWhyExportClassCannotBeLoaded(NoClassDefFoundError ex,
.getJavaClassPath());
LOG.fatal(msg, ex);
}
}

View File

@ -399,6 +399,9 @@ public enum AppendValuesHintUsage {
+ " OR DATA_TYPE LIKE 'TIMESTAMP(%) WITH TIME ZONE'"
+ " OR DATA_TYPE LIKE 'TIMESTAMP(%) WITH LOCAL TIME ZONE'" + ")";
// Query to get current logged on user
public static final String QUERY_GET_SESSION_USER = "SELECT USER FROM DUAL";
// public static final int[] SUPPORTED_ORACLE_DATA_TYPES = {
// oracle.jdbc.OracleTypes.BIT // -7;
// ,oracle.jdbc.OracleTypes.TINYINT // -6;

View File

@ -89,6 +89,7 @@ public JdbcOracleThinConnection parseJdbcOracleThinConnectionString()
/*
* The format of an Oracle jdbc URL is one of:
* jdbc:oracle:<driver-type>:@tnsname - for tnsname based login
* jdbc:oracle:<driver-type>:@<host>:<port>:<sid>
* jdbc:oracle:<driver-type>:@<host>:<port>/<service>
* jdbc:oracle:<driver-type>:@<host>:<port>/<service>?<parameters>
@ -105,11 +106,12 @@ public JdbcOracleThinConnection parseJdbcOracleThinConnectionString()
}
// Check we can proceed...
if (jdbcFragments.length < 5 || jdbcFragments.length > 6) {
if (jdbcFragments.length < 4 || jdbcFragments.length > 6) {
throw new JdbcOracleThinConnectionParsingError(
String.format(
"There should be 5 or 6 colon-separated pieces of data in the JDBC "
+ "URL, such as:\n\tjdbc:oracle:<driver-type>:@<host>:<port>:<sid>\n"
"There should be 4, 5 or 6 colon-separated pieces of data in the "
+ "JDBC URL, such as:\n\tjdbc:oracle:<driver-type>:@tnsname\n"
+ "\tjdbc:oracle:<driver-type>:@<host>:<port>:<sid>\n"
+ "\tjdbc:oracle:<driver-type>:@<host>:<port>/<service>\n"
+ "\tjdbc:oracle:<driver-type>:@<host>:<port>/<service>?<parameters>\n"
+ "The JDBC URL specified was:\n"
@ -156,6 +158,8 @@ public JdbcOracleThinConnection parseJdbcOracleThinConnectionString()
}
String portStr = "";
String tnsName = "";
switch (jdbcFragments.length) {
case 6:
// jdbc:oracle:<driver-type>:@<host>:<port>:<sid>
@ -176,41 +180,49 @@ public JdbcOracleThinConnection parseJdbcOracleThinConnectionString()
service = portAndService[1].trim();
break;
case 4:
// jdbc:oracle:<driver-type>:@tnsname
tnsName = jdbcFragments[3].trim();
break;
default:
throw new JdbcOracleThinConnectionParsingError("Internal error parsing "
+ "JDBC connection string.");
}
if (portStr.isEmpty()) {
throw new JdbcOracleThinConnectionParsingError(
"The fifth item in the colon-separated JDBC URL (the port) must not "
+ "be empty.");
if (jdbcFragments.length > 4) {
if (portStr.isEmpty()) {
throw new JdbcOracleThinConnectionParsingError(
"The fifth item in the colon-separated JDBC URL (the port) must not"
+ " be empty.");
}
try {
port = Integer.parseInt(portStr);
} catch (NumberFormatException ex) {
throw new JdbcOracleThinConnectionParsingError(
String
.format(
"The fifth item in the colon-separated JDBC URL (the port) "
+ "must be a valid number.\n"
+ "\"%s\" could not be parsed as an integer.", portStr));
}
if (port <= 0) {
throw new JdbcOracleThinConnectionParsingError(
String
.format(
"The fifth item in the colon-separated JDBC URL (the port) "
+ "must be greater than zero.\n"
+ "\"%s\" was specified.", portStr));
}
}
try {
port = Integer.parseInt(portStr);
} catch (NumberFormatException ex) {
throw new JdbcOracleThinConnectionParsingError(
String
.format(
"The fifth item in the colon-separated JDBC URL (the port) "
+ "must be a valid number.\n"
+ "\"%s\" could not be parsed as an integer.", portStr));
}
if (port <= 0) {
throw new JdbcOracleThinConnectionParsingError(
String
.format(
"The fifth item in the colon-separated JDBC URL (the port) "
+ "must be greater than zero.\n"
+ "\"%s\" was specified.", portStr));
}
if (sid == null && service == null) {
if (sid == null && service == null && tnsName == null) {
throw new JdbcOracleThinConnectionParsingError(
"The JDBC URL does not contain a SID or SERVICE. The URL should look "
+ "like one of these:\n\tjdbc:oracle:<driver-type>:@<host>:<port>:<sid>\n"
+ "like one of these:\n\tjdbc:oracle:<driver-type>:@tnsname\n"
+ "\tjdbc:oracle:<driver-type>:@<host>:<port>:<sid>\n"
+ "\tjdbc:oracle:<driver-type>:@<host>:<port>/<service>\n"
+ "\tjdbc:oracle:<driver-type>:@<host>:<port>/<service>?<parameters>\n"
+ "\tjdbc:oracle:<driver-type>:@//<host>:<port>/<service>\n"
@ -220,7 +232,7 @@ public JdbcOracleThinConnection parseJdbcOracleThinConnectionString()
// Remove the "@" prefix of the hostname
JdbcOracleThinConnection result =
new JdbcOracleThinConnection(hostName.replaceFirst("^[@][/]{0,2}", "")
, port, sid, service);
, port, sid, service, tnsName.replaceFirst("^[@][/]{0,2}", ""));
return result;
}

View File

@ -34,6 +34,8 @@
import com.cloudera.sqoop.manager.ConnManager;
import com.cloudera.sqoop.manager.ManagerFactory;
import com.cloudera.sqoop.metastore.JobData;
import org.apache.sqoop.manager.OracleManager;
import org.apache.sqoop.manager.oracle.OraOopOutputFormatUpdate.UpdateMode;
import org.apache.sqoop.manager.oracle.OraOopUtilities.
JdbcOracleThinConnectionParsingError;
@ -319,6 +321,7 @@ private void setMapperConnectionDetails(OraOopConnManager oraOopConnManager,
int jdbcPort = 0;
String jdbcSid = "";
String jdbcService = "";
String jdbcTnsName = "";
try {
OraOopJdbcUrl oraOopJdbcUrl = new OraOopJdbcUrl(jdbcConnectStr);
@ -328,6 +331,7 @@ private void setMapperConnectionDetails(OraOopConnManager oraOopConnManager,
jdbcPort = jdbcConnection.getPort();
jdbcSid = jdbcConnection.getSid();
jdbcService = jdbcConnection.getService();
jdbcTnsName = jdbcConnection.getTnsName();
} catch (JdbcOracleThinConnectionParsingError ex) {
LOG.info(String.format(
"Unable to parse the JDBC connection URL \"%s\" as a connection "
@ -362,18 +366,19 @@ private void setMapperConnectionDetails(OraOopConnManager oraOopConnManager,
jobData);
}
} else {
generateJdbcConnectionUrlsBySidOrService(jdbcHost, jdbcPort, jdbcSid,
jdbcService, jobData);
generateJdbcConnectionUrlsByTnsnameSidOrService(jdbcHost, jdbcPort,
jdbcSid, jdbcService, jdbcTnsName, jobData);
}
}
private void generateJdbcConnectionUrlsBySidOrService(String hostName,
int port, String sid, String serviceName, JobData jobData) {
private void generateJdbcConnectionUrlsByTnsnameSidOrService(String hostName,
int port, String sid, String serviceName, String tnsName, JobData jobData) {
String jdbcUrl = null;
if (sid != null && !sid.isEmpty()) {
if (tnsName != null && !tnsName.isEmpty()) {
jdbcUrl = OraOopUtilities.generateOracleTnsNameJdbcUrl(tnsName);
} else if (sid != null && !sid.isEmpty()) {
jdbcUrl = OraOopUtilities.generateOracleSidJdbcUrl(hostName, port, sid);
} else {
jdbcUrl =
@ -437,7 +442,7 @@ private boolean generateRacJdbcConnectionUrlsByServiceName(String hostName,
jdbcActiveInstanceThinConnection =
new OraOopUtilities.JdbcOracleThinConnection(
activeInstance.getHostName(),
jdbcPort, activeInstance.getInstanceName(), "");
jdbcPort, activeInstance.getInstanceName(), "", "");
if (testDynamicallyGeneratedOracleRacInstanceConnection(
jdbcActiveInstanceThinConnection.toString(), jobData
@ -533,6 +538,8 @@ private void storeJdbcUrlForMapper(int mapperIdx, String jdbcUrl,
Configuration conf = jobData.getSqoopOptions().getConf();
String mapperJdbcUrlPropertyName =
OraOopUtilities.getMapperJdbcUrlPropertyName(mapperIdx, conf);
LOG.debug("Setting mapper url " + mapperJdbcUrlPropertyName + " = "
+ jdbcUrl);
conf.set(mapperJdbcUrlPropertyName, jdbcUrl);
}
@ -821,9 +828,14 @@ private void createAnyRequiredOracleObjects(SqoopOptions sqoopOptions,
String exportTableTemplate =
conf.get(OraOopConstants.ORAOOP_EXPORT_CREATE_TABLE_TEMPLATE, "");
String user = sqoopOptions.getUsername();
if (user == null) {
user = OracleManager.getSessionUser(connection);
}
OracleTable templateTableContext =
OraOopUtilities.decodeOracleTableName(sqoopOptions.getUsername(),
exportTableTemplate);
OraOopUtilities.decodeOracleTableName(user, exportTableTemplate);
boolean noLoggingOnNewTable =
conf.getBoolean(OraOopConstants.ORAOOP_EXPORT_CREATE_TABLE_NO_LOGGING,

View File

@ -38,14 +38,13 @@
import org.apache.log4j.Category;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.sqoop.manager.oracle.OraOopOutputFormatInsert.InsertMode;
import org.apache.sqoop.manager.oracle.OraOopOutputFormatUpdate.UpdateMode;
import com.cloudera.sqoop.Sqoop;
import com.cloudera.sqoop.SqoopOptions;
import com.cloudera.sqoop.mapreduce.ExportJobBase;
import org.apache.sqoop.manager.oracle.OraOopOutputFormatInsert.InsertMode;
import org.apache.sqoop.manager.oracle.OraOopOutputFormatUpdate.UpdateMode;
/**
* Utilities used by OraOop.
*/
@ -54,6 +53,8 @@ public final class OraOopUtilities {
private OraOopUtilities() {
}
private static String currentSessionUser = null;
/**
* Used for testing purposes - can get OraOop to call a class to run a report
* on various performance metrics.
@ -104,6 +105,10 @@ public static OracleTable decodeOracleTableName(
// "schema"."table"
String[] tableStrings = tableStr.split("\"");
if (oracleConnectionUserName == null) {
oracleConnectionUserName = currentSessionUser;
}
switch (tableStrings.length) {
case 1: // <- table or schema.table
@ -748,17 +753,23 @@ public static class JdbcOracleThinConnection {
private int port;
private String sid;
private String service;
private String tnsName;
public JdbcOracleThinConnection(String host, int port, String sid,
String service) {
String service, String tnsName) {
this.host = host;
this.port = port;
this.sid = sid;
this.service = service;
this.tnsName = tnsName;
}
@Override
public String toString() {
// Use tnsName if it is available
if (this.tnsName != null && !this.tnsName.isEmpty()) {
return String.format("jdbc:oracle:thin:@%s", tnsName);
}
// Use the SID if it's available...
if (this.sid != null && !this.sid.isEmpty()) {
@ -774,8 +785,8 @@ public String toString() {
}
throw new RuntimeException(
"Unable to generate a JDBC URL, as no SID or SERVICE has been "
+ "provided.");
"Unable to generate a JDBC URL, as no TNS name, SID or SERVICE "
+ "has been provided.");
}
@ -794,6 +805,10 @@ public String getSid() {
public String getService() {
return service;
}
public String getTnsName() {
return tnsName;
}
}
/**
@ -844,6 +859,10 @@ public static String generateOracleServiceNameJdbcUrl(String hostName,
port, serviceName);
}
public static String generateOracleTnsNameJdbcUrl(String tnsName) {
return String.format("jdbc:oracle:thin:@%s", tnsName);
}
public static String getMapperJdbcUrlPropertyName(int mapperId,
org.apache.hadoop.conf.Configuration conf) {
@ -1457,5 +1476,7 @@ public static void checkJavaSecurityEgd() {
+ "file:///dev/urandom - Oracle connections may time out.");
}
}
public static void setCurrentSessionUser(String user) {
currentSessionUser = user;
}
}