/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.sqoop.manager.oracle;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.security.InvalidParameterException;
import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;

import org.apache.hadoop.conf.Configuration;

/**
 * Contains the queries to get data dictionary information from Oracle database.
 */
public final class OraOopOracleQueries {

  private static final OraOopLog LOG = OraOopLogFactory
      .getLog(OraOopOracleQueries.class);

  private static Class<?> oracleConnectionClass;
  private static Class<?> oracleStatementClass;
  private static Class<?> oracleResultSetClass;
  private static Class<?> oracleTypesClass;
  private static Class<?> oracleDateClass;
  private static Method methSetLongAtName;
  private static Method methSetBigDecimalAtName;
  private static Method methSetStringAtName;
  private static Method methSetTimestampAtName;
  private static Method methSetBinaryDoubleAtName;
  private static Method methSetObjectAtName;
  private static Method methSetBinaryFloatAtName;
  private static Method methSetIntAtName;

  private static final Map<String, Integer> ORACLE_TYPES =
      new HashMap<String, Integer>();

  static {
    try {
      oracleStatementClass =
          Class.forName("oracle.jdbc.OraclePreparedStatement");
      methSetLongAtName =
          oracleStatementClass.getMethod("setLongAtName", String.class,
              long.class);
      methSetBigDecimalAtName =
          oracleStatementClass.getMethod("setBigDecimalAtName", String.class,
              BigDecimal.class);
      methSetStringAtName =
          oracleStatementClass.getMethod("setStringAtName", String.class,
              String.class);
      methSetTimestampAtName =
          oracleStatementClass.getMethod("setTimestampAtName", String.class,
              Timestamp.class);
      methSetBinaryDoubleAtName =
          oracleStatementClass.getMethod("setBinaryDoubleAtName", String.class,
              double.class);
      methSetObjectAtName =
          oracleStatementClass.getMethod("setObjectAtName", String.class,
              Object.class);
      methSetBinaryFloatAtName =
          oracleStatementClass.getMethod("setBinaryFloatAtName", String.class,
              float.class);
      methSetIntAtName =
          oracleStatementClass.getMethod("setIntAtName", String.class,
              int.class);

      oracleResultSetClass = Class.forName("oracle.jdbc.OracleResultSet");
      oracleDateClass = Class.forName("oracle.sql.DATE");
      oracleConnectionClass = Class.forName("oracle.jdbc.OracleConnection");
      oracleTypesClass = Class.forName("oracle.jdbc.OracleTypes");
    } catch (Exception e) {
      throw new RuntimeException(
          "Problem getting Oracle JDBC methods via reflection.", e);
    }
  }

  private OraOopOracleQueries() {
  }

  protected static void setJdbcFetchSize(Connection connection,
      org.apache.hadoop.conf.Configuration conf) {

    int fetchSize =
        conf.getInt(OraOopConstants.ORACLE_ROW_FETCH_SIZE,
            OraOopConstants.ORACLE_ROW_FETCH_SIZE_DEFAULT);
    try {
      Method methSetPrefetch =
          oracleConnectionClass.getMethod("setDefaultRowPrefetch", int.class);
      methSetPrefetch.invoke(connection, fetchSize);

      String msg =
          "The Oracle connection has had its default row fetch size set to : "
              + fetchSize;
      if (fetchSize == OraOopConstants.ORACLE_ROW_FETCH_SIZE_DEFAULT) {
        LOG.debug(msg);
      } else {
        LOG.info(msg);
      }
    } catch (Exception ex) {
      LOG.warn(
          String
              .format(
                  "Unable to configure the DefaultRowPrefetch of the "
                + "Oracle connection in %s.",
                  OraOopUtilities.getCurrentMethodName()), ex);
    }

  }

  public static void setConnectionTimeZone(Connection connection,
      Configuration conf) {
    String timeZoneString = conf.get("oracle.sessionTimeZone", "GMT");
    setConnectionTimeZone(connection, timeZoneString);
  }

  public static void setConnectionTimeZone(Connection connection,
      String timeZone) {
    TimeZone timeZoneObj = TimeZone.getTimeZone(timeZone);
    try {
      Method methSession =
          oracleConnectionClass.getMethod("setSessionTimeZone", String.class);
      Method methDefault =
          oracleConnectionClass.getMethod("setDefaultTimeZone", TimeZone.class);
      methSession.invoke(connection, timeZoneObj.getID());
      methDefault.invoke(connection, timeZoneObj);
      TimeZone.setDefault(timeZoneObj);
      LOG.info("Session Time Zone set to " + timeZoneObj.getID());
    } catch (Exception e) {
      LOG.error("Error setting time zone: " + e.getMessage());
    }
  }

  public static OracleTablePartitions getPartitions(Connection connection,
      OracleTable table) throws SQLException {

    OracleTablePartitions result = new OracleTablePartitions();

    PreparedStatement statement =
      connection
        .prepareStatement("with"
        + " partitions as"
        + "   (select table_owner, table_name, partition_name"
        +  "   from dba_tab_partitions"
        + "   where"
        + "   table_owner = ? and"
        + "   table_name = ?),"
        + " subpartitions as"
        + "  (select table_owner, table_name, partition_name, subpartition_name"
        + "  from dba_tab_subpartitions"
        + "  where"
        + "  table_owner = ? and"
        + "  table_name = ?)"
        + " select"
        + "   partitions.partition_name,"
        + "   subpartitions.subpartition_name"
        + " from partitions left outer join subpartitions on"
        + " (partitions.table_owner = subpartitions.table_owner"
        + " and partitions.table_name = subpartitions.table_name"
        + " and partitions.partition_name = subpartitions.partition_name)"
        + " order by partition_name, subpartition_name");

    statement.setString(1, table.getSchema());
    statement.setString(2, table.getName());
    statement.setString(3, table.getSchema());
    statement.setString(4, table.getName());

    ResultSet resultSet = statement.executeQuery();

    OracleTablePartition partition = null;
    while (resultSet.next()) {
      String partitionName = resultSet.getString("partition_name");
      String subPartitionName = resultSet.getString("subpartition_name");

      if (subPartitionName != null &&  !("".equals(subPartitionName))) {
        partition = new OracleTablePartition(subPartitionName, true);
        result.add(partition);
      } else {
        if (partition == null || partition.isSubPartition()
            || partition.getName() != partitionName) {
          partition = new OracleTablePartition(partitionName, false);
          result.add(partition);
        }
      }
    }

    resultSet.close();
    statement.close();

    return result;
  }

  public static int getOracleDataObjectNumber(Connection connection,
      OracleTable table) throws SQLException {

    PreparedStatement statement =
        connection.prepareStatement("SELECT data_object_id "
            + " FROM dba_objects" + " WHERE owner = ?" + " and object_name = ?"
            + " and object_type = ?");
    statement.setString(1, table.getSchema());
    statement.setString(2, table.getName());
    statement.setString(3, "TABLE");

    ResultSet resultSet = statement.executeQuery();

    resultSet.next();
    int result = resultSet.getInt("data_object_id");

    resultSet.close();
    statement.close();

    return result;
  }

  private static String getPartitionBindVars(List<String> partitionList) {
    String result = "";
    for (int i = 1; i <= partitionList.size(); i++) {
      result += (i > 1) ? "," : "";
      result += ":part" + i;
    }
    return result;
  }

  private static void bindPartitionBindVars(PreparedStatement statement,
      List<String> partitionList) throws SQLException {
    int i = 0;
    for (String partition : partitionList) {
      i++;
      OraOopOracleQueries.setStringAtName(statement, "part" + i, partition);
    }
  }

  public static List<OraOopOracleDataChunkPartition>
      getOracleDataChunksPartition(Connection connection, OracleTable table,
          List<String> partitionList) throws SQLException {
    List<OraOopOracleDataChunkPartition> result =
        new ArrayList<OraOopOracleDataChunkPartition>();
    String sql =
        "SELECT "
          + "  pl.partition_name, "
          + "  pl.is_subpartition, "
          + "  s.blocks "
          + "FROM "
          + "  (SELECT tp.table_owner, "
          + "    tp.table_name, "
          + "    NVL(tsp.subpartition_name,tp.partition_name) partition_name, "
          + "    nvl2(tsp.subpartition_name,1,0) is_subpartition "
          + "  FROM dba_tab_partitions tp, "
          + "    dba_tab_subpartitions tsp "
          + "  WHERE tp.table_owner     = :table_owner"
          + "  AND tp.table_name        = :table_name"
          + "  AND tsp.table_owner(+)   =tp.table_owner "
          + "  AND tsp.table_name(+)    =tp.table_name "
          + "  AND tsp.partition_name(+)=tp.partition_name ";

    if (partitionList != null && partitionList.size() > 0) {
      sql +=
          " AND tp.partition_name IN (" + getPartitionBindVars(partitionList)
              + ") ";
    }

    sql += "  ) pl, dba_tables t, dba_segments s "
        + "WHERE t.owner=pl.table_owner "
        + "AND t.table_name=pl.table_name "
        + "AND ( "
        + "     (t.iot_type='IOT' AND (s.owner,s.segment_name)= "
        + "                          (SELECT c.index_owner,c.index_name "
        + "                             FROM dba_constraints c "
        + "                            WHERE c.owner=pl.table_owner "
        + "                              AND c.table_name=pl.table_name "
        + "                              AND c.constraint_type='P')) "
        + "     OR (t.iot_type IS NULL "
        + "         AND s.owner=t.owner "
        + "         AND s.segment_name=t.table_name) "
        + "    ) "
        + "AND s.partition_name=pl.partition_name";

    PreparedStatement statement = connection.prepareStatement(sql);
    OraOopOracleQueries.setStringAtName(statement, "table_owner", table
        .getSchema());
    OraOopOracleQueries.setStringAtName(statement, "table_name", table
        .getName());

    if (partitionList != null && partitionList.size() > 0) {
      bindPartitionBindVars(statement, partitionList);
    }

    trace(String.format("%s SQL Query =\n%s", OraOopUtilities
        .getCurrentMethodName(), sql.replace(":table_owner", table.getSchema())
        .replace(":table_name", table.getName())));

    ResultSet resultSet = statement.executeQuery();

    while (resultSet.next()) {
      OraOopOracleDataChunkPartition dataChunk =
          new OraOopOracleDataChunkPartition(resultSet
              .getString("partition_name"), resultSet
              .getBoolean("is_subpartition"), resultSet.getLong("blocks"));
      result.add(dataChunk);
    }
    resultSet.close();
    statement.close();
    return result;
  }

  public static List<OraOopOracleDataChunkExtent> getOracleDataChunksExtent(
      Configuration conf, Connection connection, OracleTable table,
      List<String> partitionList, int numberOfChunksPerOracleDataFile)
      throws SQLException {

    List<OraOopOracleDataChunkExtent> result =
        new ArrayList<OraOopOracleDataChunkExtent>();

    String sql =
        "SELECT data_object_id, "
          + "file_id, "
          + "relative_fno, "
          + "file_batch, "
          + "MIN (start_block_id) start_block_id, "
          + "MAX (end_block_id) end_block_id, "
          + "SUM (blocks) blocks "
          + "FROM (SELECT o.data_object_id, "
          + "e.file_id, "
          + "e.relative_fno, "
          + "e.block_id start_block_id, "
          + "e.block_id + e.blocks - 1 end_block_id, "
          + "e.blocks, "
          + "CEIL ( "
          + "   SUM ( "
          + "      e.blocks) "
          + "   OVER (PARTITION BY o.data_object_id, e.file_id "
          + "         ORDER BY e.block_id ASC) "
          + "   / (SUM (e.blocks) "
          + "         OVER (PARTITION BY o.data_object_id, e.file_id) "
          + "      / :numchunks)) "
          + "   file_batch "
          + "FROM dba_extents e, dba_objects o, dba_tab_subpartitions tsp "
          + "WHERE     o.owner = :owner "
          + "AND o.object_name = :object_name "
          + "AND e.owner = :owner "
          + "AND e.segment_name = :object_name "
          + "AND o.owner = e.owner "
          + "AND o.object_name = e.segment_name "
          + "AND (o.subobject_name = e.partition_name "
          + "     OR (o.subobject_name IS NULL AND e.partition_name IS NULL)) "
          + "AND o.owner = tsp.table_owner(+) "
          + "AND o.object_name = tsp.table_name(+) "
          + "AND o.subobject_name = tsp.subpartition_name(+) ";

    if (partitionList != null && partitionList.size() > 0) {
      sql +=
          " AND case when o.object_type='TABLE SUBPARTITION' then "
          + "tsp.partition_name else o.subobject_name end IN ("
              + getPartitionBindVars(partitionList) + ") ";
    }

    sql +=
        ") " + "GROUP BY data_object_id, " + "         file_id, "
            + "         relative_fno, " + "         file_batch "
            + "ORDER BY data_object_id, " + "         file_id, "
            + "         relative_fno, " + "         file_batch";

    sql = conf.get(OraOopConstants.ORAOOP_ORACLE_DATA_CHUNKS_QUERY, sql);

    PreparedStatement statement = connection.prepareStatement(sql);
    OraOopOracleQueries.setIntAtName(statement, "numchunks",
        numberOfChunksPerOracleDataFile);
    OraOopOracleQueries.setStringAtName(statement, "owner", table.getSchema());
    OraOopOracleQueries.setStringAtName(statement, "object_name", table
        .getName());

    if (partitionList != null && partitionList.size() > 0) {
      bindPartitionBindVars(statement, partitionList);
    }

    trace(String.format("%s SQL Query =\n%s", OraOopUtilities
        .getCurrentMethodName(), sql.replace(":numchunks",
        Integer.toString(numberOfChunksPerOracleDataFile)).replace(":owner",
        table.getSchema()).replace(":object_name", table.getName())));

    ResultSet resultSet = statement.executeQuery();

    while (resultSet.next()) {
      int fileId = resultSet.getInt("relative_fno");
      int fileBatch = resultSet.getInt("file_batch");
      String dataChunkId =
          OraOopUtilities.generateDataChunkId(fileId, fileBatch);
      OraOopOracleDataChunkExtent dataChunk =
          new OraOopOracleDataChunkExtent(dataChunkId, resultSet
              .getInt("data_object_id"), resultSet.getInt("relative_fno"),
              resultSet.getLong("start_block_id"), resultSet
                  .getLong("end_block_id"));
      result.add(dataChunk);
    }

    resultSet.close();
    statement.close();

    return result;
  }

  private static void trace(String message) {

    LOG.debug(message);
  }

  public static String getOracleObjectType(Connection connection,
      OracleTable table) throws SQLException {

    PreparedStatement statement =
        connection.prepareStatement("SELECT object_type " + " FROM dba_objects"
            + " WHERE owner = ?" + " and object_name = ?");
    statement.setString(1, table.getSchema());
    statement.setString(2, table.getName());

    ResultSet resultSet = statement.executeQuery();

    String result = null;
    if (resultSet.next()) {
      result = resultSet.getString("object_type");
    }

    resultSet.close();
    statement.close();

    return result;
  }

  public static OracleVersion getOracleVersion(Connection connection)
      throws SQLException {

    String sql =
        "SELECT \n"
      + "  v.banner, \n"
      + "  rtrim(v.version)      full_version, \n"
      + "  rtrim(v.version_bit) version_bit, \n"
      + "  SUBSTR(v.version, 1, INSTR(v.version, '.', 1, 1)-1) major, \n"
      + "  SUBSTR(v.version, INSTR(v.version, '.', 1, 1) + 1, "
      + "  INSTR(v.version, '.', 1, 2) - INSTR(v.version, '.', 1, 1) - 1) "
      + "    minor, \n"
      + "  SUBSTR(v.version, INSTR(v.version, '.', 1, 2) + 1, "
      + "  INSTR(v.version, '.', 1, 3) - INSTR(v.version, '.', 1, 2) - 1) "
      + "    version, \n"
      + "  SUBSTR(v.version, INSTR(v.version, '.', 1, 3) + 1, "
      + "  INSTR(v.version, '.', 1, 4) - INSTR(v.version, '.', 1, 3) - 1) "
      + "    patch, \n"
      + "  DECODE(instr(v.banner, '64bit'), 0, 'False', 'True') isDb64bit, \n"
      + "  DECODE(instr(b.banner, 'HPUX'), 0, 'False', 'True') isHPUX \n"
      + "FROM (SELECT rownum row_num, \n"
      + "   banner,\n"
      + "   SUBSTR(SUBSTR(banner,INSTR(banner,'Release ')+8), 1) version_bit,\n"
      + "   SUBSTR(SUBSTR(banner,INSTR(banner,'Release ')+8), 1,\n"
      + "    INSTR(SUBSTR(banner,INSTR(banner,'Release ')+8),' ')) version\n"
      + "FROM v$version\n" + "  WHERE banner LIKE 'Oracle%'\n"
      + "     OR banner LIKE 'Personal Oracle%') v,\n" + "v$version b\n"
      + "  WHERE v.row_num = 1\n" + "  and b.banner like 'TNS%'\n";

    Statement statement = connection.createStatement();
    ResultSet resultSet = statement.executeQuery(sql);
    resultSet.next();
    OracleVersion result =
        new OracleVersion(resultSet.getInt("major"), resultSet.getInt("minor"),
            resultSet.getInt("version"), resultSet.getInt("patch"), resultSet
                .getString("banner"));

    resultSet.close();
    statement.close();

    return result;
  }

  public static List<OracleTable> getTables(Connection connection)
      throws SQLException {

    return getTables(connection, null, null, TableNameQueryType.Equals);
  }

  private enum GetTablesOptions {
    Owner, Table
  }

  private enum TableNameQueryType {
    Equals, Like
  }

  public static List<OracleTable>
      getTables(Connection connection, String owner) throws SQLException {

    return getTables(connection, owner, null, TableNameQueryType.Equals);
  }

  public static OracleTable getTable(Connection connection, String owner,
      String tableName) throws SQLException {

    List<OracleTable> tables =
        getTables(connection, owner, tableName, TableNameQueryType.Equals);
    if (tables.size() > 0) {
      return tables.get(0);
    }

    return null;
  }

  public static List<OracleTable> getTablesWithTableNameLike(
      Connection connection, String owner, String tableNameLike)
      throws SQLException {

    return getTables(connection, owner, tableNameLike, TableNameQueryType.Like);
  }

  private static List<OracleTable> getTables(Connection connection,
      String owner, String tableName, TableNameQueryType tableNameQueryType)
      throws SQLException {

    EnumSet<GetTablesOptions> options = EnumSet.noneOf(GetTablesOptions.class);

    if (owner != null && !owner.isEmpty()) {
      options.add(GetTablesOptions.Owner);
    }

    if (tableName != null && !tableName.isEmpty()) {
      options.add(GetTablesOptions.Table);
    }

    String sql =
        "SELECT owner, table_name " + " FROM dba_tables" + " %s %s %s %s "
            + " ORDER BY owner, table_name";

    String tableComparitor = null;
    switch (tableNameQueryType) {
      case Equals:
        tableComparitor = "=";
        break;
      case Like:
        tableComparitor = "LIKE";
        break;
      default:
        throw new RuntimeException("Operator not implemented.");
    }

    sql =
        String.format(sql, options.isEmpty() ? "" : "WHERE", options
            .contains(GetTablesOptions.Owner) ? "owner = ?" : "", options
            .containsAll(EnumSet.of(GetTablesOptions.Owner,
                GetTablesOptions.Table)) ? "AND" : "", options
            .contains(GetTablesOptions.Table) ? String.format(
            "table_name %s ?", tableComparitor) : "");

    PreparedStatement statement = connection.prepareStatement(sql);

    if (options.containsAll(EnumSet.of(GetTablesOptions.Owner,
        GetTablesOptions.Table))) {
      statement.setString(1, owner);
      statement.setString(2, tableName);
    } else {
      if (options.contains(GetTablesOptions.Owner)) {
        statement.setString(1, owner);
      } else if (options.contains(GetTablesOptions.Table)) {
        statement.setString(1, tableName);
      }
    }

    ResultSet resultSet = statement.executeQuery();

    ArrayList<OracleTable> result = new ArrayList<OracleTable>();
    while (resultSet.next()) {
      result.add(new OracleTable(resultSet.getString("owner"), resultSet
          .getString("table_name")));
    }

    resultSet.close();
    statement.close();

    return result;
  }

  public static List<String> getTableColumnNames(Connection connection,
      OracleTable table) throws SQLException {

    OracleTableColumns oracleTableColumns = getTableColumns(connection, table);
    List<String> result = new ArrayList<String>(oracleTableColumns.size());

    for (int idx = 0; idx < oracleTableColumns.size(); idx++) {
      result.add(oracleTableColumns.get(idx).getName());
    }

    return result;
  }

  public static List<String> getTableColumnNames(Connection connection,
      OracleTable table, boolean omitLobAndLongColumnsDuringImport,
      OraOopConstants.Sqoop.Tool sqoopTool, boolean onlyOraOopSupportedTypes,
      boolean omitOraOopPseudoColumns) throws SQLException {

    OracleTableColumns oracleTableColumns =
        getTableColumns(connection, table, omitLobAndLongColumnsDuringImport,
            sqoopTool, onlyOraOopSupportedTypes, omitOraOopPseudoColumns);

    List<String> result = new ArrayList<String>(oracleTableColumns.size());

    for (int idx = 0; idx < oracleTableColumns.size(); idx++) {
      result.add(oracleTableColumns.get(idx).getName());
    }

    return result;
  }

  private static OracleTableColumns getTableColumns(Connection connection,
      OracleTable table, boolean omitLobColumns, String dataTypesClause,
      HashSet<String> columnNamesToOmit) throws SQLException {

    String sql =
        "SELECT column_name, data_type " + " FROM dba_tab_columns"
            + " WHERE owner = ?" + " and table_name = ?" + " %s"
            + " ORDER BY column_id";

    sql =
        String.format(sql, dataTypesClause == null ? "" : " and "
            + dataTypesClause);

    LOG.debug(String.format("%s : sql = \n%s", OraOopUtilities
        .getCurrentMethodName(), sql));

    OracleTableColumns result = new OracleTableColumns();
    PreparedStatement statement = connection.prepareStatement(sql);
    statement.setString(1, getTableSchema(connection, table));
    statement.setString(2, table.getName());

    ResultSet resultSet = statement.executeQuery();

    while (resultSet.next()) {

      String columnName = resultSet.getString("column_name");

      if (columnNamesToOmit != null) {
        if (columnNamesToOmit.contains(columnName)) {
          continue;
        }
      }

      result.add(new OracleTableColumn(columnName, resultSet
          .getString("data_type")));
    }

    resultSet.close();
    statement.close();

    // Now get the actual JDBC data-types for these columns...
    StringBuilder columnList = new StringBuilder();
    for (int idx = 0; idx < result.size(); idx++) {
      if (idx > 0) {
        columnList.append(",");
      }
      columnList.append(OracleUtils.escapeIdentifier(result.get(idx).getName()));
    }
    sql =
        String.format("SELECT %s FROM %s WHERE 0=1", columnList.toString(),
            table.toString());
    Statement statementDesc = connection.createStatement();
    ResultSet resultSetDesc = statementDesc.executeQuery(sql);
    ResultSetMetaData metaData = resultSetDesc.getMetaData();
    for (int idx = 0; idx < metaData.getColumnCount(); idx++) {
      result.get(idx).setOracleType(metaData.getColumnType(idx + 1)); // <- JDBC
                                                                    // is
                                                                    // 1-based
    }
    resultSetDesc.close();
    statementDesc.close();

    return result;
  }

  public static OracleTableColumns getTableColumns(Connection connection,
      OracleTable table) throws SQLException {

    return getTableColumns(connection, table, false, null // <- dataTypesClause
        , null); // <-columnNamesToOmit
  }

  public static OracleTableColumns getTableColumns(Connection connection,
      OracleTable table, boolean omitLobAndLongColumnsDuringImport,
      OraOopConstants.Sqoop.Tool sqoopTool, boolean onlyOraOopSupportedTypes,
      boolean omitOraOopPseudoColumns) throws SQLException {

    String dataTypesClause = "";
    HashSet<String> columnNamesToOmit = null;

    if (onlyOraOopSupportedTypes) {

      switch (sqoopTool) {

        case UNKNOWN:
          throw new InvalidParameterException(
              "The sqoopTool parameter must not be \"UNKNOWN\".");

        case IMPORT:
          dataTypesClause =
              OraOopConstants.SUPPORTED_IMPORT_ORACLE_DATA_TYPES_CLAUSE;

          if (omitLobAndLongColumnsDuringImport) {
            LOG.info("LOB and LONG columns are being omitted from the Import.");
            dataTypesClause =
                " DATA_TYPE not in ('BLOB', 'CLOB', 'NCLOB', 'LONG') and "
                    + dataTypesClause;
          }
          break;

        case EXPORT:
          dataTypesClause =
              OraOopConstants.SUPPORTED_EXPORT_ORACLE_DATA_TYPES_CLAUSE;
          break;

        default:
          throw new InvalidParameterException("Sqoop Tool not implemented.");

      }
    }

    if (omitOraOopPseudoColumns) {

      switch (sqoopTool) {

        case EXPORT:
          if (columnNamesToOmit == null) {
            columnNamesToOmit = new HashSet<String>();
          }
          columnNamesToOmit.add(OraOopConstants.COLUMN_NAME_EXPORT_PARTITION);
          columnNamesToOmit
              .add(OraOopConstants.COLUMN_NAME_EXPORT_SUBPARTITION);
          columnNamesToOmit.add(OraOopConstants.COLUMN_NAME_EXPORT_MAPPER_ROW);
          break;
        default:
          // Only applicable for export.
          break;
      }
    }

    return getTableColumns(connection, table,
        omitLobAndLongColumnsDuringImport, dataTypesClause, columnNamesToOmit);
  }

  public static List<OracleActiveInstance> getOracleActiveInstances(
      Connection connection) throws SQLException {

    // Returns null if there are no rows in v$active_instances - which indicates
    // this Oracle database is not a RAC.
    ArrayList<OracleActiveInstance> result = null;

    Statement statement = connection.createStatement();
    ResultSet resultSet =
        statement.executeQuery("select inst_name from v$active_instances ");

    while (resultSet.next()) {
      String instName = resultSet.getString("inst_name");
      String[] nameFragments = instName.split(":");

      if (nameFragments.length != 2) {
        throw new SQLException(
            "Parsing Error: The inst_name column of v$active_instances does "
            + "not contain two values separated by a colon.");
      }

      String hostName = nameFragments[0].trim();
      String instanceName = nameFragments[1].trim();

      if (hostName.isEmpty()) {
        throw new SQLException(
            "Parsing Error: The inst_name column of v$active_instances does "
            + "not include a host name.");
      }

      if (instanceName.isEmpty()) {
        throw new SQLException(
            "Parsing Error: The inst_name column of v$active_instances does "
            + "not include an instance name.");
      }

      OracleActiveInstance instance = new OracleActiveInstance();
      instance.setHostName(hostName);
      instance.setInstanceName(instanceName);

      if (result == null) {
        result = new ArrayList<OracleActiveInstance>();
      }

      result.add(instance);
    }

    resultSet.close();
    statement.close();
    return result;
  }

  public static String getCurrentOracleInstanceName(Connection connection)
      throws SQLException {

    String result = "";

    Statement statement = connection.createStatement();
    ResultSet resultSet =
        statement.executeQuery("select instance_name from v$instance");

    if (resultSet.next()) {
      result = resultSet.getString("instance_name");
    }

    resultSet.close();
    statement.close();
    return result;
  }

  public static Object getSysDate(Connection connection) throws SQLException {
    Statement statement = connection.createStatement();
    ResultSet resultSet = statement.executeQuery("select sysdate from dual");

    resultSet.next();
    try {
      Method method = oracleResultSetClass.getMethod("getDATE", int.class);
      return method.invoke(resultSet, 1);
    } catch (Exception e) {
      if (e.getCause() instanceof SQLException) {
        throw (SQLException) e.getCause();
      } else {
        throw new RuntimeException("Could not get sysdate", e);
      }
    } finally {
      resultSet.close();
      statement.close();
    }
  }

  public static String oraDATEToString(Object date, String format) {
    try {
      Method dateMethod =
          oracleDateClass.getMethod("toText", String.class, String.class);
      return (String) dateMethod.invoke(date, format, null);
    } catch (Exception e) {
      throw new RuntimeException(String.format(
          "Unable to convert the oracle.sql.DATE value \"%s\" to text.", date
              .toString()), e);
    }
  }

  public static Object oraDATEFromString(String date, String format) {
    try {
      Method dateMethod =
          oracleDateClass.getMethod("fromText", String.class, String.class,
              String.class);
      return dateMethod.invoke(null, date, format, null);
    } catch (Exception e) {
      throw new RuntimeException(String
          .format(
              "Unable to convert the String value \"%s\" to oracle.sql.DATE.",
              date), e);
    }
  }

  public static Date oraDATEToDate(Object date) {
    try {
      Method dateMethod = oracleDateClass.getMethod("dateValue");
      return (Date) dateMethod.invoke(date);
    } catch (Exception e) {
      throw new RuntimeException("Could not get sysdate", e);
    }
  }

  public static String getSysTimeStamp(Connection connection)
      throws SQLException {

    Statement statement = connection.createStatement();
    ResultSet resultSet =
        statement.executeQuery("select systimestamp from dual");

    resultSet.next();

    try {
      Method method = oracleResultSetClass.getMethod("getTIMESTAMP", int.class);
      Object timestamp = method.invoke(resultSet, 1);
      return timestamp.toString();
    } catch (Exception e) {
      if (e.getCause() instanceof SQLException) {
        throw (SQLException) e.getCause();
      } else {
        throw new RuntimeException("Could not get sysdate", e);
      }
    } finally {
      resultSet.close();
      statement.close();
    }
  }

  public static boolean isTableAnIndexOrganizedTable(Connection connection,
      OracleTable table) throws SQLException {

    /*
     * http://ss64.com/orad/DBA_TABLES.html IOT_TYPE: If index-only table,then
     * IOT_TYPE is IOT or IOT_OVERFLOW or IOT_MAPPING else NULL
     */

    boolean result = false;

    PreparedStatement statement =
        connection.prepareStatement("select iot_type " + "from dba_tables "
            + "where owner = ? " + "and table_name = ?");
    statement.setString(1, table.getSchema());
    statement.setString(2, table.getName());
    ResultSet resultSet = statement.executeQuery();

    if (resultSet.next()) {
      String iotType = resultSet.getString("iot_type");
      result = iotType != null && !iotType.isEmpty();
    }

    resultSet.close();
    statement.close();

    return result;
  }

  public static void dropTable(Connection connection, OracleTable table)
      throws SQLException {

    String sql = String.format("DROP TABLE %s", table.toString());

    Statement statement = connection.createStatement();
    try {
      statement.execute(sql);
    } catch (SQLException ex) {
      if (ex.getErrorCode() != 942) { // ORA-00942: table or view does not exist
        throw ex;
      }
    }
    statement.close();
  }

  public static void
      exchangeSubpartition(Connection connection, OracleTable table,
          String subPartitionName, OracleTable subPartitionTable)
          throws SQLException {

    Statement statement = connection.createStatement();
    String sql =
        String.format("ALTER TABLE %s EXCHANGE SUBPARTITION %s WITH TABLE %s WITHOUT VALIDATION",
            table.toString(), subPartitionName, subPartitionTable.toString());
    statement.execute(sql);
    statement.close();
  }

  public static void createExportTableFromTemplate(Connection connection,
      OracleTable newTable, String tableStorageClause,
      OracleTable templateTable, boolean noLogging) throws SQLException {

    String sql =
        String.format("CREATE TABLE %s \n" + "%s %s \n" + "AS \n"
            + "(SELECT * FROM %s WHERE 0=1)", newTable.toString(),
            noLogging ? "NOLOGGING" : "", tableStorageClause, templateTable
                .toString());

    Statement statement = connection.createStatement();
    statement.execute(sql);
    statement.close();
  }

  private static Object oraDATEAddJulianDays(Object date, int julianDay,
      int julianSec) {
    try {
      Constructor<?> dateCon = oracleDateClass.getConstructor(byte[].class);
      Method dateBytes = oracleDateClass.getMethod("toBytes");
      Object result = dateCon.newInstance(dateBytes.invoke(date));
      Method dateAdd =
          oracleDateClass.getMethod("addJulianDays", int.class, int.class);
      result = dateAdd.invoke(result, julianDay, julianSec);
      return result;
    } catch (Exception e) {
      throw new RuntimeException("Could not add days to date.", e);
    }
  }

  public static void createExportTableFromTemplateWithPartitioning(
      Connection connection, OracleTable newTable, String tableStorageClause,
      OracleTable templateTable, boolean noLogging, String partitionName,
      Object jobDateTime, int numberOfMappers, String[] subPartitionNames)
      throws SQLException {

    String dateFormat = "yyyy-mm-dd hh24:mi:ss";

    Object partitionBound =
        OraOopOracleQueries.oraDATEAddJulianDays(jobDateTime, 0, 1);

    String partitionBoundStr =
        OraOopOracleQueries.oraDATEToString(partitionBound, dateFormat);

    StringBuilder subPartitions = new StringBuilder();
    for (int idx = 0; idx < numberOfMappers; idx++) {
      if (idx > 0) {
        subPartitions.append(",");
      }

      subPartitions.append(String.format(" SUBPARTITION %s VALUES (%d)",
          subPartitionNames[idx], idx));
    }

    String sql =
        String.format(
            "CREATE TABLE %s \n" + "%s %s \n" + "PARTITION BY RANGE (%s) \n"
                + "SUBPARTITION BY LIST (%s) \n" + "(PARTITION %s \n"
                + "VALUES LESS THAN (to_date('%s', '%s')) \n" + "( %s ) \n"
                + ") \n" + "AS \n"
                + "(SELECT t.*, sysdate %s, 0 %s, 0 %s FROM %s t \n"
                + "WHERE 0=1)", newTable.toString(), noLogging ? "NOLOGGING"
                : "", tableStorageClause,
            OraOopConstants.COLUMN_NAME_EXPORT_PARTITION,
            OraOopConstants.COLUMN_NAME_EXPORT_SUBPARTITION, partitionName,
            partitionBoundStr, dateFormat, subPartitions.toString(),
            OraOopConstants.COLUMN_NAME_EXPORT_PARTITION,
            OraOopConstants.COLUMN_NAME_EXPORT_SUBPARTITION,
            OraOopConstants.COLUMN_NAME_EXPORT_MAPPER_ROW, templateTable
                .toString());

    LOG.debug(String.format("SQL generated by %s:\n%s", OraOopUtilities
        .getCurrentMethodName(), sql));

    try {

      // Create the main export table...
      PreparedStatement preparedStatement = connection.prepareStatement(sql);
      preparedStatement.execute(sql);
      preparedStatement.close();
    } catch (SQLException ex) {
      LOG.error(String
          .format(
              "The error \"%s\" was encountered when executing the following "
              + "SQL statement:\n%s",
              ex.getMessage(), sql));
      throw ex;
    }
  }

  public static void createExportTableForMapper(Connection connection,
      OracleTable table, String tableStorageClause, OracleTable templateTable,
      boolean addOraOopPartitionColumns) throws SQLException {

    String sql = "";
    try {

      // Create the N tables to be used by the mappers...
      Statement statement = connection.createStatement();
      if (addOraOopPartitionColumns) {
        sql =
            String.format("CREATE TABLE %s \n" + "NOLOGGING %s \n" + "AS \n"
                + "(SELECT t.*, SYSDATE %s, 0 %s, 0 %s FROM %s t WHERE 0=1)",
                table.toString(), tableStorageClause,
                OraOopConstants.COLUMN_NAME_EXPORT_PARTITION,
                OraOopConstants.COLUMN_NAME_EXPORT_SUBPARTITION,
                OraOopConstants.COLUMN_NAME_EXPORT_MAPPER_ROW, templateTable
                    .toString());
      } else {
        sql =
            String.format("CREATE TABLE %s \n" + "NOLOGGING %s \n" + "AS \n"
                + "(SELECT * FROM %s WHERE 0=1)", table.toString(),
                tableStorageClause, templateTable.toString());
      }

      LOG.info(String.format("SQL generated by %s:\n%s", OraOopUtilities
          .getCurrentMethodName(), sql));

      statement.execute(sql);
      statement.close();
    } catch (SQLException ex) {
      LOG.error(String
          .format(
              "The error \"%s\" was encountered when executing the following "
              + "SQL statement:\n%s",
              ex.getMessage(), sql));
      throw ex;
    }
  }

  // public static void createExportTablesForMappers(Connection connection
  // ,String[] mapperTableNames
  // ,OracleTable templateTable
  // ,boolean addOraOopPartitionColumns)
  // throws SQLException {
  //
  // for(String tableName : mapperTableNames)
  // createExportTableForMapper(connection, tableName, templateTable,
  // addOraOopPartitionColumns);
  // }

  public static void createMoreExportTablePartitions(Connection connection,
      OracleTable table, String partitionName, Object jobDateTime,
      String[] subPartitionNames) throws SQLException {

    String dateFormat = "yyyy-mm-dd hh24:mi:ss";

    Object partitionBound =
        OraOopOracleQueries.oraDATEAddJulianDays(jobDateTime, 0, 1);
    String partitionBoundStr =
        OraOopOracleQueries.oraDATEToString(partitionBound, dateFormat);

    StringBuilder subPartitions = new StringBuilder();
    for (int idx = 0; idx < subPartitionNames.length; idx++) {
      if (idx > 0) {
        subPartitions.append(",");
      }

      subPartitions.append(String.format(" SUBPARTITION %s VALUES (%d)",
          subPartitionNames[idx], idx));
    }

    String sql =
        String.format("ALTER TABLE %s " + "ADD PARTITION %s "
            + "VALUES LESS THAN (to_date('%s', '%s'))" + "( %s ) ", table
            .toString(), partitionName, partitionBoundStr, dateFormat,
            subPartitions.toString());

    LOG.debug(String.format("SQL generated by %s:\n%s", OraOopUtilities
        .getCurrentMethodName(), sql));

    try {
      PreparedStatement preparedStatement = connection.prepareStatement(sql);
      preparedStatement.execute(sql);
      preparedStatement.close();

    } catch (SQLException ex) {
      LOG.error(String
          .format(
              "The error \"%s\" was encountered when executing the following "
              + "SQL statement:\n%s",
              ex.getMessage(), sql));
      throw ex;
    }
  }

  public static void mergeTable(Connection connection, OracleTable targetTable,
      OracleTable sourceTable, String[] mergeColumnNames,
      OracleTableColumns oracleTableColumns, Object oraOopSysDate,
      int oraOopMapperId, boolean parallelizationEnabled) throws SQLException {

    StringBuilder updateClause = new StringBuilder();
    StringBuilder insertClause = new StringBuilder();
    StringBuilder valuesClause = new StringBuilder();
    for (int idx = 0; idx < oracleTableColumns.size(); idx++) {
      OracleTableColumn oracleTableColumn = oracleTableColumns.get(idx);
      String columnName = oracleTableColumn.getName();

      if (insertClause.length() > 0) {
        insertClause.append(",");
      }
      insertClause.append(String.format("target.\"%s\"", columnName));

      if (valuesClause.length() > 0) {
        valuesClause.append(",");
      }
      valuesClause.append(String.format("source.\"%s\"", columnName));

      if (!OraOopUtilities.stringArrayContains(mergeColumnNames, columnName,
          true)) {

        // If we're performing a merge, then the table is not partitioned. (If
        // the table
        // was partitioned, we'd be deleting and then inserting rows.)
        if (!columnName
            .equalsIgnoreCase(OraOopConstants.COLUMN_NAME_EXPORT_PARTITION)
            && !columnName
            .equalsIgnoreCase(OraOopConstants.COLUMN_NAME_EXPORT_SUBPARTITION)
            && !columnName
            .equalsIgnoreCase(OraOopConstants.COLUMN_NAME_EXPORT_MAPPER_ROW)) {

          if (updateClause.length() > 0) {
            updateClause.append(",");
          }
          updateClause.append(String.format("target.\"%1$s\" = source.\"%1$s\"",
              columnName));

        }
      }
    }

    String sourceClause = valuesClause.toString();

    String sql =
        String.format("MERGE %7$s INTO %1$s target \n"
            + "USING (SELECT %8$s * FROM %2$s) source \n" + "  ON (%3$s) \n"
            + "WHEN MATCHED THEN \n" + "  UPDATE SET %4$s \n"
            + "WHEN NOT MATCHED THEN \n" + "  INSERT (%5$s) \n"
            + "  VALUES (%6$s)", targetTable.toString(),
            sourceTable.toString(),
            generateUpdateKeyColumnsWhereClauseFragment(mergeColumnNames,
                "target", "source"), updateClause.toString(), insertClause
                .toString(), sourceClause,
            parallelizationEnabled ? "/*+ append parallel(target) */" : "",
            parallelizationEnabled ? "/*+parallel*/" : "");

    LOG.info(String.format("Merge SQL statement:\n" + sql));

    Statement statement = connection.createStatement();
    ResultSet resultSet = statement.executeQuery(sql);
    resultSet.close();
    statement.close();
  }

  public static void updateTable(Connection connection,
      OracleTable targetTable, OracleTable sourceTable,
      String[] mergeColumnNames, OracleTableColumns oracleTableColumns,
      Object oraOopSysDate, int oraOopMapperId, boolean parallelizationEnabled)
      throws SQLException {

    StringBuilder targetColumnsClause = new StringBuilder();
    StringBuilder sourceColumnsClause = new StringBuilder();
    for (int idx = 0; idx < oracleTableColumns.size(); idx++) {
      OracleTableColumn oracleTableColumn = oracleTableColumns.get(idx);
      String columnName = oracleTableColumn.getName();

      if (targetColumnsClause.length() > 0) {
        targetColumnsClause.append(",");
      }
      targetColumnsClause.append(String.format("a.%s", OracleUtils.escapeIdentifier(columnName)));

      if (sourceColumnsClause.length() > 0) {
        sourceColumnsClause.append(",");
      }
      sourceColumnsClause.append(String.format("b.%s", OracleUtils.escapeIdentifier(columnName)));
    }

    String sourceClause = sourceColumnsClause.toString();

    sourceClause =
        sourceClause.replaceAll(OraOopConstants.COLUMN_NAME_EXPORT_PARTITION,
            String.format("to_date('%s', 'yyyy/mm/dd hh24:mi:ss')",
                OraOopOracleQueries.oraDATEToString(oraOopSysDate,
                    "yyyy/mm/dd hh24:mi:ss")));

    sourceClause =
        sourceClause.replaceAll(
            OraOopConstants.COLUMN_NAME_EXPORT_SUBPARTITION, Integer
                .toString(oraOopMapperId));

    String sql =
        String.format("UPDATE %5$s %1$s a \n" + "SET \n" + "(%2$s) \n"
            + "= (SELECT \n" + "%3$s \n" + "FROM %4$s b \n" + "WHERE %6$s) \n"
            + "WHERE EXISTS (SELECT null FROM %4$s c " + "WHERE %7$s)",
            targetTable.toString(), targetColumnsClause.toString(),
            sourceClause, sourceTable.toString(),
            parallelizationEnabled ? "/*+ parallel */" : "",
            generateUpdateKeyColumnsWhereClauseFragment(mergeColumnNames, "b",
                "a"), generateUpdateKeyColumnsWhereClauseFragment(
                mergeColumnNames, "c", "a"));

    LOG.info(String.format("Update SQL statement:\n" + sql));

    Statement statement = connection.createStatement();
    int rowsAffected = statement.executeUpdate(sql);

    LOG.info(String.format(
        "The number of rows affected by the update SQL was: %d", rowsAffected));

    statement.close();
  }

  /**
   * Whether new rows should be included in changes table or not.
   */
  public enum CreateExportChangesTableOptions {
    OnlyRowsThatDiffer, RowsThatDifferPlusNewRows
  }

  public static int createExportChangesTable(Connection connection,
      OracleTable tableToCreate, String tableToCreateStorageClause,
      OracleTable tableContainingUpdates, OracleTable tableToBeUpdated,
      String[] joinColumnNames, CreateExportChangesTableOptions options,
      boolean parallelizationEnabled) throws SQLException {

    List<String> columnNames =
        getTableColumnNames(connection, tableToBeUpdated
            , false // <- omitLobAndLongColumnsDuringImport
            , OraOopConstants.Sqoop.Tool.EXPORT
            , true // <- onlyOraOopSupportedTypes
            , false // <- omitOraOopPseudoColumns
        );

    StringBuilder columnClause = new StringBuilder(2 * columnNames.size());
    for (int idx = 0; idx < columnNames.size(); idx++) {
      if (idx > 0) {
        columnClause.append(",");
      }
      columnClause.append(String.format("a.%s", OracleUtils.escapeIdentifier(columnNames.get(idx))));
    }

    StringBuilder rowEqualityClause = new StringBuilder();
    for (int idx = 0; idx < columnNames.size(); idx++) {
      String columnName = columnNames.get(idx);

      // We need to omit the OraOop pseudo columns from the SQL statement that
      // compares the data in
      // the two tables we're interested in. Otherwise, EVERY row will be
      // considered to be changed,
      // since the values in the pseudo columns will differ. (i.e.
      // ORAOOP_EXPORT_SYSDATE will differ.)
      if (columnName
          .equalsIgnoreCase(OraOopConstants.COLUMN_NAME_EXPORT_PARTITION)
          || columnName
             .equalsIgnoreCase(OraOopConstants.COLUMN_NAME_EXPORT_SUBPARTITION)
          || columnName
             .equalsIgnoreCase(OraOopConstants.COLUMN_NAME_EXPORT_MAPPER_ROW)) {
        continue;
      }

      if (idx > 0) {
        rowEqualityClause.append("OR");
      }

      rowEqualityClause.append(String.format("(a.\"%1$s\" <> b.\"%1$s\" "
          + "OR (a.\"%1$s\" IS NULL AND b.\"%1$s\" IS NOT NULL) "
          + "OR (a.\"%1$s\" IS NOT NULL AND b.\"%1$s\" IS NULL))", columnName));
    }

    String sqlJoin = null;
    switch (options) {

      case OnlyRowsThatDiffer:
        sqlJoin = "";
        break;

      case RowsThatDifferPlusNewRows:
        sqlJoin = "(+)"; // <- An outer-join will cause the "new" rows to be
                         // included
        break;

      default:
        throw new RuntimeException(String.format(
            "Update %s to cater for the option \"%s\".", OraOopUtilities
                .getCurrentMethodName(), options.toString()));
    }

    String sql =
        String.format("CREATE TABLE %1$s \n" + "NOLOGGING %8$s \n" + "%7$s \n"
            + "AS \n " + "SELECT \n" + "%5$s \n" + "FROM %2$s a, %3$s b \n"
            + "WHERE (%4$s) \n" + "AND ( \n" + "%6$s \n" + ")", tableToCreate
            .toString(), tableContainingUpdates.toString(), tableToBeUpdated
            .toString(), generateUpdateKeyColumnsWhereClauseFragment(
            joinColumnNames, "a", "b", sqlJoin), columnClause.toString(),
            rowEqualityClause.toString(), parallelizationEnabled ? "PARALLEL"
                : "", tableToCreateStorageClause);

    LOG.info(String.format("The SQL to create the changes-table is:\n%s", sql));

    Statement statement = connection.createStatement();

    long start = System.nanoTime();
    statement.executeUpdate(sql);
    double timeInSec = (System.nanoTime() - start) / Math.pow(10, 9);
    LOG.info(String.format("Time spent creating change-table: %f sec.",
        timeInSec));

    String indexName = tableToCreate.toString().replaceAll("CHG", "IDX");
    start = System.nanoTime();
    statement.execute(String.format("CREATE INDEX %s ON %s (%s)", indexName,
        tableToCreate.toString(), OraOopUtilities
            .stringArrayToCSV(joinColumnNames)));
    timeInSec = (System.nanoTime() - start) / Math.pow(10, 9);
    LOG.info(String.format("Time spent creating change-table index: %f sec.",
        timeInSec));

    int changeTableRowCount = 0;

    ResultSet resultSet =
        statement.executeQuery(String.format("select count(*) from %s",
            tableToCreate.toString()));
    resultSet.next();
    changeTableRowCount = resultSet.getInt(1);
    LOG.info(String.format("The number of rows in the change-table is: %d",
        changeTableRowCount));

    statement.close();
    return changeTableRowCount;
  }

  public static void deleteRowsFromTable(Connection connection,
      OracleTable tableToDeleteRowsFrom,
      OracleTable tableContainingRowsToDelete, String[] joinColumnNames,
      boolean parallelizationEnabled) throws SQLException {

    String sql =
        String.format("DELETE %4$s FROM %1$s a \n" + "WHERE EXISTS ( \n"
            + "SELECT null FROM %3$s b WHERE \n" + "%2$s)",
            tableToDeleteRowsFrom.toString(),
            generateUpdateKeyColumnsWhereClauseFragment(joinColumnNames, "a",
                "b"), tableContainingRowsToDelete.toString(),
            parallelizationEnabled ? "/*+ parallel */" : "");

    LOG.info(String.format("The SQL to delete rows from a table:\n%s", sql));

    Statement statement = connection.createStatement();
    int rowsAffected = statement.executeUpdate(sql);

    LOG.info(String.format(
        "The number of rows affected by the delete SQL was: %d", rowsAffected));

    statement.close();
  }

  public static void insertRowsIntoExportTable(Connection connection,
      OracleTable tableToInsertRowsInto,
      OracleTable tableContainingRowsToInsert, Object oraOopSysDate,
      int oraOopMapperId, boolean parallelizationEnabled) throws SQLException {

    List<String> columnNames =
        getTableColumnNames(connection, tableToInsertRowsInto);

    StringBuilder columnClause =
        new StringBuilder(2 + (2 * columnNames.size()));
    for (int idx = 0; idx < columnNames.size(); idx++) {
      if (idx > 0) {
        columnClause.append(",");
      }
        columnClause.append(columnNames.get(idx));
    }

    String columnsClause = columnClause.toString();

    String sql =
        String.format("insert %4$s \n" + "into %1$s \n" + "select \n"
            + "%2$s \n" + "from %3$s", tableToInsertRowsInto.toString(),
            columnsClause, tableContainingRowsToInsert.toString(),
            parallelizationEnabled ? "/*+ append parallel */" : "");

    LOG.info(String.format(
        "The SQL to insert rows from one table into another:\n%s", sql));

    Statement statement = connection.createStatement();
    ResultSet resultSet = statement.executeQuery(sql);
    resultSet.close();
    statement.close();
  }

  public static boolean doesIndexOnColumnsExist(Connection connection,
      OracleTable oracleTable, String[] columnNames) throws SQLException {

    // Attempts to find an index on the table that *starts* with the N column
    // names passed.
    // These columns can be in any order.

    String columnNamesInClause =
        OraOopUtilities.stringArrayToCSV(columnNames, "'");

    String sql =
        String.format("SELECT b.index_name, \n"
            + "  sum(case when b.column_name in (%1$s) then 1 end) num_cols \n"
            + "FROM dba_indexes a, dba_ind_columns b \n" + "WHERE \n"
            + "a.owner = b.index_owner \n"
            + "AND a.index_name = b.index_name \n" + "AND b.table_owner = ? \n"
            + "AND b.table_name = ? \n" + "AND a.status = 'VALID' \n"
            + "AND b.column_position <= ? \n" + "GROUP BY b.index_name \n"
            + "HAVING sum(case when b.column_name in (%1$s) then 1 end) = ?",
            columnNamesInClause);

    PreparedStatement statement = connection.prepareStatement(sql);
    statement.setString(1, oracleTable.getSchema());
    statement.setString(2, oracleTable.getName());
    statement.setInt(3, columnNames.length);
    statement.setInt(4, columnNames.length);

    LOG.debug(String.format("SQL to find an index on the columns %s:\n%s",
        columnNamesInClause, sql));

    ResultSet resultSet = statement.executeQuery();

    boolean result = false;
    if (resultSet.next()) {
      LOG.debug(String
          .format(
              "The table %s has an index named %s starting with the column(s) "
              + "%s (in any order).",
              oracleTable.toString(), resultSet.getString("index_name"),
              columnNamesInClause));
      result = true;
    }

    resultSet.close();
    statement.close();

    return result;
  }

  private static String generateUpdateKeyColumnsWhereClauseFragment(
      String[] joinColumnNames, String prefix1, String prefix2) {

    return generateUpdateKeyColumnsWhereClauseFragment(joinColumnNames,
        prefix1, prefix2, "");
  }

  private static String generateUpdateKeyColumnsWhereClauseFragment(
      String[] joinColumnNames, String prefix1, String prefix2,
      String sqlJoinOperator) {

    StringBuilder result = new StringBuilder();
    for (int idx = 0; idx < joinColumnNames.length; idx++) {
      String joinColumnName = joinColumnNames[idx];
      if (idx > 0) {
        result.append(" AND ");
      }
      result.append(String.format("%1$s.%3$s = %2$s.%3$s %4$s", prefix1,
          prefix2, joinColumnName, sqlJoinOperator));
    }
    return result.toString();
  }

  public static String getCurrentSchema(Connection connection)
      throws SQLException {
    String sql = "SELECT SYS_CONTEXT('USERENV','CURRENT_SCHEMA') FROM DUAL";

    PreparedStatement statement = connection.prepareStatement(sql);

    ResultSet resultSet = statement.executeQuery();

    resultSet.next();
    String result = resultSet.getString(1);

    resultSet.close();
    statement.close();

    LOG.info("Current schema is: " + result);

    return result;
  }

  public static String getTableSchema(Connection connection, OracleTable table)
      throws SQLException {
    if (table.getSchema() == null || table.getSchema().isEmpty()) {
      return getCurrentSchema(connection);
    } else {
      return table.getSchema();
    }
  }

  public static long getCurrentScn(Connection connection) throws SQLException {
    String sql = "SELECT current_scn FROM v$database";
    PreparedStatement statement = connection.prepareStatement(sql);
    ResultSet resultSet = statement.executeQuery();

    resultSet.next();
    long result = resultSet.getLong(1);
    resultSet.close();
    statement.close();

    return result;
  }

  public static void setLongAtName(PreparedStatement statement,
      String bindName, long bindValue) throws SQLException {
    try {
      methSetLongAtName.invoke(statement, bindName, bindValue);
    } catch (Exception e) {
      if (e.getCause() instanceof SQLException) {
        throw (SQLException) e.getCause();
      } else {
        throw new RuntimeException("Could not set bind variable", e);
      }
    }
  }

  public static void setBigDecimalAtName(PreparedStatement statement,
      String bindName, BigDecimal bindValue) throws SQLException {
    try {
      methSetBigDecimalAtName.invoke(statement, bindName, bindValue);
    } catch (Exception e) {
      if (e.getCause() instanceof SQLException) {
        throw (SQLException) e.getCause();
      } else {
        throw new RuntimeException("Could not set bind variable", e);
      }
    }
  }

  public static void setStringAtName(PreparedStatement statement,
      String bindName, String bindValue) throws SQLException {
    try {
      methSetStringAtName.invoke(statement, bindName, bindValue);
    } catch (Exception e) {
      if (e.getCause() instanceof SQLException) {
        throw (SQLException) e.getCause();
      } else {
        throw new RuntimeException("Could not set bind variable", e);
      }
    }
  }

  public static void setTimestampAtName(PreparedStatement statement,
      String bindName, Timestamp bindValue) throws SQLException {
    try {
      methSetTimestampAtName.invoke(statement, bindName, bindValue);
    } catch (Exception e) {
      if (e.getCause() instanceof SQLException) {
        throw (SQLException) e.getCause();
      } else {
        throw new RuntimeException("Could not set bind variable", e);
      }
    }
  }

  public static void setBinaryDoubleAtName(PreparedStatement statement,
      String bindName, double bindValue) throws SQLException {
    try {
      methSetBinaryDoubleAtName.invoke(statement, bindName, bindValue);
    } catch (Exception e) {
      if (e.getCause() instanceof SQLException) {
        throw (SQLException) e.getCause();
      } else {
        throw new RuntimeException("Could not set bind variable", e);
      }
    }
  }

  public static void setObjectAtName(PreparedStatement statement,
      String bindName, Object bindValue) throws SQLException {
    try {
      methSetObjectAtName.invoke(statement, bindName, bindValue);
    } catch (Exception e) {
      if (e.getCause() instanceof SQLException) {
        throw (SQLException) e.getCause();
      } else {
        throw new RuntimeException("Could not set bind variable", e);
      }
    }
  }

  public static void setBinaryFloatAtName(PreparedStatement statement,
      String bindName, float bindValue) throws SQLException {
    try {
      methSetBinaryFloatAtName.invoke(statement, bindName, bindValue);
    } catch (Exception e) {
      if (e.getCause() instanceof SQLException) {
        throw (SQLException) e.getCause();
      } else {
        throw new RuntimeException("Could not set bind variable", e);
      }
    }
  }

  public static void setIntAtName(PreparedStatement statement, String bindName,
      int bindValue) throws SQLException {
    try {
      methSetIntAtName.invoke(statement, bindName, bindValue);
    } catch (Exception e) {
      if (e.getCause() instanceof SQLException) {
        throw (SQLException) e.getCause();
      } else {
        throw new RuntimeException("Could not set bind variable", e);
      }
    }
  }

  public static int getOracleType(String name) {
    Integer result = ORACLE_TYPES.get(name);
    if (result == null) {
      synchronized (ORACLE_TYPES) {
        try {
          result = oracleTypesClass.getField(name).getInt(null);
          ORACLE_TYPES.put(name, result);
        } catch (Exception e) {
          throw new RuntimeException("Invalid oracle type specified", e);
        }
      }
    }
    return result;
  }
}
