/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.sqoop.manager.oracle.util; import java.net.URL; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.Statement; import java.util.List; import org.apache.commons.io.IOUtils; import org.apache.sqoop.manager.oracle.OraOopTestCase; import org.apache.sqoop.manager.oracle.OracleUtils; /** * Class to load an Oracle table with data based on configuration file. */ public final class OracleData { private OracleData() { } enum KeyType { PRIMARY, UNIQUE } private static ClassLoader classLoader; static { classLoader = Thread.currentThread().getContextClassLoader(); if (classLoader == null) { classLoader = OraOopTestCase.class.getClassLoader(); } } private static String getColumnList(OracleTableDefinition tableDefinition) { StringBuilder result = new StringBuilder(); String delim = ""; for (OracleDataDefinition column : tableDefinition.getColumnList()) { result.append(delim).append(OracleUtils.escapeIdentifier(column.getColumnName())).append(" ") .append( column.getDataType()); delim = ",\n"; } return result.toString(); } private static String getDataExpression(List<OracleDataDefinition> columnList) { StringBuilder result = new StringBuilder(); for (OracleDataDefinition column : columnList) { result.append("l_ret_rec.").append(OracleUtils.escapeIdentifier(column.getColumnName())).append(" := ") .append(column.getDataExpression()).append(";\n"); } return result.toString(); } private static void createPackageSpec(Connection conn, OracleTableDefinition tableDefinition) throws Exception { String pkgSql = IOUtils.toString(classLoader.getResource( "oraoop/pkg_tst_product_gen.psk").openStream()); pkgSql = pkgSql.replaceAll("\\$COLUMN_LIST", getColumnList(tableDefinition)); pkgSql = pkgSql.replaceAll("\\$TABLE_NAME", tableDefinition.getTableName()); PreparedStatement stmt = conn.prepareStatement(pkgSql); stmt.execute(); } private static void createPackageBody(Connection conn, OracleTableDefinition tableDefinition) throws Exception { String pkgSql = IOUtils.toString(classLoader.getResource( "oraoop/pkg_tst_product_gen.pbk").openStream()); String columnList = getColumnList(tableDefinition); if (tableDefinition.isIndexOrganizedTable()) { columnList += "\n," + getKeyString(KeyType.PRIMARY, tableDefinition); } pkgSql = pkgSql.replaceAll("\\$COLUMN_LIST", columnList); pkgSql = pkgSql.replaceAll("\\$TABLE_NAME", tableDefinition.getTableName()); pkgSql = pkgSql.replaceAll("\\$DATA_EXPRESSION_LIST", getDataExpression(tableDefinition.getColumnList())); pkgSql = pkgSql.replaceAll("\\$TABLE_ORGANIZATION_CLAUSE", tableDefinition.isIndexOrganizedTable() ? "ORGANIZATION INDEX OVERFLOW NOLOGGING" : ""); pkgSql = pkgSql.replaceAll("\\$PARTITION_CLAUSE", tableDefinition .getPartitionClause()); PreparedStatement stmt = conn.prepareStatement(pkgSql); stmt.execute(); } private static String getKeyColumns(KeyType keyType, OracleTableDefinition tableDefinition) { String result = null; List<String> columns = null; switch (keyType) { case PRIMARY: columns = tableDefinition.getPrimaryKeyColumns(); break; case UNIQUE: columns = tableDefinition.getUniqueKeyColumns(); break; default: throw new RuntimeException("Missing key type."); } if (columns != null && columns.size() > 0) { StringBuilder keyColumnList = new StringBuilder(); String delim = ""; for (String column : columns) { keyColumnList.append(delim).append(OracleUtils.escapeIdentifier(column)); delim = ","; } result = keyColumnList.toString(); } return result; } private static String getKeyString(KeyType keyType, OracleTableDefinition tableDefinition) { String keySql = null; String keyColumnList = getKeyColumns(keyType, tableDefinition); if (keyColumnList!=null) { keySql = "constraint \"$TABLE_NAME_" + ((keyType == KeyType.PRIMARY) ? "PK\" primary key" : "UK\" unique") + "($PK_COLUMN_LIST) "; keySql = keySql.replaceAll("\\$PK_COLUMN_LIST", keyColumnList); keySql = keySql.replaceAll("\\$TABLE_NAME", tableDefinition.getTableName()); } return keySql; } private static void createKey(Connection conn, KeyType keyType, OracleTableDefinition tableDefinition) throws Exception { String keySql = getKeyString(keyType, tableDefinition); String keyColumnList = getKeyColumns(keyType, tableDefinition); if (keySql!=null) { keySql = "alter table \"$TABLE_NAME\" add " + keySql + " using index (create unique index \"$TABLE_NAME_" + ((keyType == KeyType.PRIMARY) ? "PK\"" : "UK\"") + " on \"$TABLE_NAME\"($PK_COLUMN_LIST) " + "parallel nologging)"; keySql = keySql.replaceAll("\\$PK_COLUMN_LIST", keyColumnList); keySql = keySql.replaceAll("\\$TABLE_NAME", tableDefinition.getTableName()); PreparedStatement stmt = conn.prepareStatement(keySql); stmt.execute(); } } public static int getParallelProcesses(Connection conn) throws Exception { PreparedStatement stmt = conn.prepareStatement("SELECT cc.value value" + "\n" + "FROM" + "\n" + " (SELECT to_number(value) value" + "\n" + " FROM v$parameter" + "\n" + " WHERE name='parallel_max_servers'" + "\n" + " ) pms," + "\n" + " (SELECT to_number(value) value" + "\n" + " FROM v$parameter" + "\n" + " WHERE name='parallel_threads_per_cpu'" + "\n" + " ) ptpc," + "\n" + " (SELECT to_number(value) value FROM v$parameter " + " WHERE name='cpu_count'" + "\n" + " ) cc"); ResultSet res = stmt.executeQuery(); res.next(); return res.getInt(1); } public static void createTable(Connection conn, OracleTableDefinition tableDefinition, int parallelDegree, int rowsPerSlave) throws Exception { createPackageSpec(conn, tableDefinition); createPackageBody(conn, tableDefinition); CallableStatement procStmt = conn.prepareCall("begin \"PKG_ODG_" + tableDefinition.getTableName() + "\".prc_load_table(?,?); end;"); procStmt.setInt(1, parallelDegree); procStmt.setInt(2, rowsPerSlave); procStmt.execute(); if (!tableDefinition.isIndexOrganizedTable()) { createKey(conn, KeyType.PRIMARY, tableDefinition); } createKey(conn, KeyType.UNIQUE, tableDefinition); } public static void createTable(Connection conn, String fileName, int parallelDegree, int rowsPerSlave) throws Exception { createTable(conn, fileName, parallelDegree, rowsPerSlave, false); } public static void createTable(Connection conn, String fileName, int parallelDegree, int rowsPerSlave, boolean dropTableIfExists) throws Exception { URL file = classLoader.getResource("oraoop/" + fileName); OracleTableDefinition tableDefinition = new OracleTableDefinition(file); if (dropTableIfExists) { dropTableIfExists(conn, tableDefinition.getTableName()); } createTable(conn, tableDefinition, parallelDegree, rowsPerSlave); } private static void dropTableIfExists(Connection conn, String tableName) throws Exception { try (Statement stmt = conn.createStatement()) { stmt.execute("BEGIN EXECUTE IMMEDIATE 'DROP TABLE " + tableName + "'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END;"); } } }