package hiro.yoshioka.sql;

import hiro.yoshioka.ast.sql.util.BindInfo;
import hiro.yoshioka.sdh.ResultSetMetaCopy;
import hiro.yoshioka.sdh.diff.DiffCatalog;
import hiro.yoshioka.sdh.diff.DiffToResultSetDataHolder;
import hiro.yoshioka.sdh2.ReflectionPreparedStatement;
import hiro.yoshioka.sdh2.ResultSetDataHolder2;
import hiro.yoshioka.sql.engine.CallRequest;
import hiro.yoshioka.sql.engine.DifferenceInStructureRequest;
import hiro.yoshioka.sql.engine.MirroringRequest;
import hiro.yoshioka.sql.engine.Request;
import hiro.yoshioka.sql.engine.SQLOperationType;
import hiro.yoshioka.sql.engine.TransactionRequest;
import hiro.yoshioka.sql.params.ConnectionProperties;
import hiro.yoshioka.sql.params.OutPutParameter;
import hiro.yoshioka.sql.params.Parameter;
import hiro.yoshioka.sql.resource.DBCrossRefference;
import hiro.yoshioka.sql.resource.DBResourceType;
import hiro.yoshioka.sql.resource.DBRoot;
import hiro.yoshioka.sql.resource.IDBResource;
import hiro.yoshioka.sql.resource.IDBSequence;
import hiro.yoshioka.sql.resource.IDBTable;
import hiro.yoshioka.sql.resource.INameFamily;
import hiro.yoshioka.sql.util.SQLUtil2;
import hiro.yoshioka.util.SQLDataType;
import hiro.yoshioka.util.SQLUtil;
import hiro.yoshioka.util.StringUtil;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.util.Collection;
import java.util.Date;
import java.util.Properties;
import java.util.Set;

import jp.sf.orangesignal.csv.CsvWriter;
import jp.sf.orangesignal.csv.handlers.ResultSetHandler;

public abstract class AbsTransactionSQL extends AbsBasicSQL implements
		ITransactionSQL {
	static final String savepointName = "mySavePoint";
	static final String savepointNameExtra = "myExtraSavePoint";

	private boolean fTrunsactionTime;

	protected static final int DEFAULT_ROW_NUM = 1000;

	protected Statement fActiveStatement;

	private int queryTimeOut;

	protected long maxRow;
	private Date latestOperationTime;

	protected AbsTransactionSQL(Driver ds) {
		super(ds);
	}

	@Override
	public void updateLatestRequestTime() {
		this.latestOperationTime = new java.util.Date();
	}

	@Override
	public Date getLatestRequestTime() {
		return this.latestOperationTime;
	}

	@Override
	public Boolean isAlive(ConnectionProperties properties) throws SQLException {
		if (properties == null
				|| !properties.getDatabaseType().enableKeepAlive()) {
			return null;
		}

		Connection con = null;
		try {
			_url = properties.getProperty("url"); //$NON-NLS-1$
			fLogger.info("Driver=" + _driver + " THIS[" + this + "]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			if (this._driver == null) {
				File f = new File(properties.getDriverFilePath());
				String s = null;
				if (f.isFile() && f.exists()) {
					s = String.format(
							Messages.getString("AbsBasicSQL.MissingClass"), //$NON-NLS-1$
							properties.getDriverName(),
							properties.getDriverFilePath());
				} else {
					s = String.format(Messages
							.getString("AbsBasicSQL.MissingJDBCDriverFile"), //$NON-NLS-1$
							properties.getDriverFilePath());
				}
				throw new IllegalStateException(s);
			}
			fLogger.info("URL ACCEPT=" + (_driver.acceptsURL(_url)) //$NON-NLS-1$
					+ "ConnectionInfo:" + properties); //$NON-NLS-1$

			con = _driver.connect(_url,
					properties.getRelationalDBConnectionProperties());
			con.setAutoCommit(true);
			execute(con, properties.getDatabaseType().getKeepAliveStatement(),
					StringUtil.EMPTY_STRING_ARRAY);
			this.latestOperationTime = new java.util.Date();
			return true;
		} finally {
			if (con != null) {
				try {
					con.close();
				} catch (Exception e) {
				}
			}
		}
	}

	public abstract ResultSetDataHolder2 getSessionInfo() throws SQLException;

	public abstract ResultSetDataHolder2 getLockInfo() throws SQLException;

	public boolean doOperation(SQLOperationType Operation, Request request)
			throws SQLException {
		boolean retCode = false;
		fLogger.info("doOperation:" + Operation);
		rsUtil.setMakeBlobData(request.makeBlob);
		TransactionRequest treq = null;
		if (request instanceof TransactionRequest) {
			treq = (TransactionRequest) request;
			queryTimeOut = treq.getTimeOut();
			setMaxRowNum(treq.getMaxRownum());
		}
		try {
			switch (Operation) {
			case DIFFERENCE_IN_STRUCTURE:
				DifferenceInStructureRequest diff_request = (DifferenceInStructureRequest) request;
				retCode = diff(diff_request);
				break;
			case RESOURCE_MIRRORING:
				MirroringRequest mirroring_request = (MirroringRequest) request;
				retCode = createMirroredTableTo(mirroring_request);
				break;
			case EXECUTE_BAT:
				treq.setRDH(executeBatUpdate(treq.getSQLStatements()));
				break;
			case PREPARED_EXECUTE_QUERY:
				treq.setRDH(executePrepareQuery(treq.getSQLStatement(),
						treq.getBindStrings()));
				break;
			case EXECUTE:
				treq.setResult(execute(treq.getSQLStatement()));
				break;
			case PREPARED_CALL:
				executePrepareCall((CallRequest) request);
				break;
			case CREATE_TRIG_FNC_PROC:
			case PREPARED_EXECUTE:
				treq.setRDH(executePrepare(treq.getSQLStatement(),
						treq.getBindObjects()));
				break;

			case COUNT:
				String sql = null;
				if (StringUtil.isEmpty(treq.getSQLStatement())) {
					IDBTable table = treq.getIDBTable();
					IDBResource schema = table.getParent();

					if (schema.getName().length() > 0) {
						sql = String.format("SELECT COUNT(*) CNT FROM %s.%s",
								schema.getName(), table.getName());
					} else {
						sql = String.format("SELECT COUNT(*) CNT FROM %s",
								table.getName());
					}
				}
				treq.setResultCount(count(sql));
				break;

			case COUNTS:
				IDBTable[] tables = treq.getIDBTables();
				String[] sqls = new String[tables.length];
				if (StringUtil.isEmpty(treq.getSQLStatement())) {
					for (int i = 0; i < tables.length; i++) {
						IDBTable table = tables[i];
						IDBResource schema = table.getParent();

						if (schema.getName().length() > 0) {
							sqls[i] = String.format(
									"SELECT COUNT(*) CNT FROM %s.%s",
									schema.getName(), table.getName());
						} else {
							sqls[i] = String.format(
									"SELECT COUNT(*) CNT FROM %s",
									table.getName());
						}
					}
				}
				treq.setRDH(counts(sqls));
				break;

			case CANSEL:
				retCode = cansel();
				break;
			case COMMIT:
				retCode = commit();
				break;
			case ROLLBACK:
				retCode = rollback();
				break;
			case SELECT_ALL:
				treq.setRDH(getAllData2(treq.getIDBTable(), treq));
				break;
			case CREATE_DATABASE:
				retCode = createDatabase(treq.getTitle(),
						treq.getExtra_properties());
				break;
			case CREATE_SCHEMA:
				retCode = createSchema(treq.getTitle(),
						treq.getExtra_properties());
				break;
			default:
				retCode = super.doOperation(Operation, request);
				break;
			}
		} catch (SQLException e) {
			notifyExecute(_con, SQLExecutionStatus.EXCEPTION, e.getMessage());
			throw e;
		} finally {
			queryTimeOut = 0;
			maxRow = 0;
		}

		return retCode;
	}

	@Override
	public ResultSet getAllData(IDBTable table) throws SQLException {
		IDBResource schema = table.getParent();

		getStatement(_con, ResultSet.TYPE_FORWARD_ONLY,
				ResultSet.CONCUR_READ_ONLY);

		if (schema.getName().length() > 0) {
			return fActiveStatement.executeQuery("SELECT * FROM "
					+ schema.getName() + "." + table.getName());
		} else {
			return fActiveStatement.executeQuery("SELECT * FROM "
					+ table.getName());
		}
	}

	@Override
	public ResultSetDataHolder2 getAllData2(String schema, String table,
			Request request) throws SQLException {
		String sql_statement = null;
		getStatement(_con, ResultSet.TYPE_FORWARD_ONLY,
				ResultSet.CONCUR_READ_ONLY);
		if (request != null && request instanceof MirroringRequest) {
			MirroringRequest mreq = (MirroringRequest) request;
			fActiveStatement.setMaxRows(mreq.maxRowNum);
		}

		if (StringUtil.isEmpty(schema)) {
			sql_statement = String.format("SELECT * FROM %s", table);
		} else {
			sql_statement = String.format("SELECT * FROM %s.%s", schema, table);
		}
		fLogger.info(sql_statement);
		ResultSetDataHolder2 rdh2 = RS2RDH(
				fActiveStatement.executeQuery(sql_statement), true,
				sql_statement, null);
		if (rdh2 != null) {
			rdh2.setTableNameE(table);
		}
		return rdh2;
	}

	@Override
	public ResultSetDataHolder2 getAllData2(IDBTable table, Request request)
			throws SQLException {
		INameFamily schema = table.getParent();
		ResultSetDataHolder2 ret = this.getAllData2(schema.getName(),
				table.getName(), request);
		if (ret != null) {
			ret.setTableName(table.getComment());
		}
		return ret;
	}

	public boolean executePrepareCall(CallRequest request) throws SQLException {
		CallableStatement statement = null;
		boolean ret = false;
		if (_con == null) {
			return ret;
		}
		try {
			if (fLogger.isTraceEnabled()) {
				fLogger.trace("sql=" + request.getSQLStatement());
			}
			statement = _con.prepareCall(request.getSQLStatement());
			Parameter[] inputs = request.getInputParameters();
			for (int i = 0; i < inputs.length; i++) {
				if (fLogger.isWarnEnabled()) {
					fLogger.warn("in[" + inputs[i].index + "]="
							+ inputs[i].value);
				}
				SQLUtil.setBinds(statement, inputs[i].index, inputs[i].value);
			}
			OutPutParameter[] outputs = request.getOutPutParameters();
			for (int i = 0; i < outputs.length; i++) {
				if (fLogger.isTraceEnabled()) {
					fLogger.trace("registerOutParameter[" + outputs[i].index
							+ "]=" + outputs[i].datatype);
				}
				statement.registerOutParameter(outputs[i].index,
						outputs[i].datatype.getType());
			}

			ret = statement.execute();

			for (int i = 0; i < outputs.length; i++) {
				outputs[i].setResult(SQLUtil.getStringUsingType(statement,
						outputs[i].index,
						SQLDataType.parse(outputs[i].datatype.getType())));
			}
		} finally {
			if (statement != null) {
				statement.close();
			}
			setTransactionTime(true);
		}
		return ret;
	}

	/**
	 * @param operationCode
	 * @return
	 */
	public boolean canDoOperation(SQLOperationType operation) {
		switch (operation) {
		case TRUNCATE:
			return false;
		case CANSEL:
			return _con != null;
		case COMMIT:
			if (_info.isConnected() && !_info.isAutoCommit()) {
				return fTrunsactionTime;
			}
			return false;
		case ROLLBACK:
			if (_info.isConnected()) {
				return !_info.isAutoCommit();
			}
			return false;
		case CREATE_DATABASE:
		case CREATE_SCHEMA:
			return _con != null;
		default:
			return super.canDoOperation(operation);
		}
	}

	protected PreparedStatement getPrepareStatement(String sql_statement)
			throws SQLException {
		return getPrepareStatement(_extra_con, sql_statement);
	}

	protected PreparedStatement getPrepareStatement(Connection connection,
			String sql_statement) throws SQLException {
		PreparedStatement statement = connection
				.prepareStatement(sql_statement);

		fActiveStatement = statement;
		statement.setQueryTimeout(getQueryTimeout());
		statement.setMaxRows((int) maxRow);

		return statement;
	}

	protected PreparedStatement getPrepareStatement(Connection connection,
			String sql_statement, int scroll, int read) throws SQLException {
		PreparedStatement statement = connection.prepareStatement(
				sql_statement, scroll, read);
		fActiveStatement = statement;
		statement.setQueryTimeout(getQueryTimeout());
		statement.setMaxRows((int) maxRow);

		return statement;
	}

	protected Statement getStatement(Connection connection, int scroll, int read)
			throws SQLException {
		Statement statement = connection.createStatement(scroll, read);
		fActiveStatement = statement;
		statement.setQueryTimeout(getQueryTimeout());
		statement.setMaxRows((int) maxRow);

		return statement;
	}

	public ResultSetDataHolder2 executeBatUpdate(String[] statements)
			throws SQLException {
		Statement statement = null;
		ResultSetDataHolder2 sdh = null;
		if (_con == null) {
			return sdh;
		}
		try {
			statement = getStatement(_con, ResultSet.TYPE_FORWARD_ONLY,
					ResultSet.CONCUR_READ_ONLY);

			for (int i = 0; i < statements.length; i++) {
				fLogger.trace(statements[i]);
				statement.addBatch(statements[i]);
			}

			long time = System.currentTimeMillis();
			notifyExecute(_con, SQLExecutionStatus.BEFORE_EXECUTE);
			int[] ret = statement.executeBatch();
			time = System.currentTimeMillis() - time;
			notifyExecute(_con, SQLExecutionStatus.AFTER_EXECUTE,
					String.valueOf(time));

			sdh = createRdh2(new String[] { "Returns", "Statement" }, null);
			for (int i = 0; i < ret.length; i++) {
				sdh.addRow(new String[] { String.valueOf(ret[i]), statements[i] });
			}

			sdh.setWrapTime(time);
			return sdh;
		} finally {
			setTransactionTime(true);

			if (statement != null) {
				statement.close();
			}
		}
	}

	public boolean execute(Connection connection, String sql_statement,
			String[] args) throws SQLException {
		PreparedStatement statement = null;
		boolean ret = false;
		if (connection == null) {
			return false;
		}
		try {
			statement = getPrepareStatement(connection, sql_statement);

			fLogger.trace(sql_statement);
			if (args != null) {
				for (int i = 0; i < args.length; i++) {
					statement.setString(i + 1, args[i]);
				}
			}
			notifyExecute(connection, SQLExecutionStatus.BEFORE_EXECUTE);
			long time = System.currentTimeMillis();

			statement.execute();
			time = System.currentTimeMillis() - time;
			notifyExecute(connection, SQLExecutionStatus.AFTER_EXECUTE,
					Boolean.toString(ret), String.valueOf(time));
			return true;
		} finally {
			if (statement != null) {
				statement.close();
			}
		}
	}

	/**
	 * @return
	 */
	private int getQueryTimeout() {
		return queryTimeOut;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see hiro.yoshioka.sql.ITransactionSQL#count(java.lang.String)
	 */
	public int count(String sql_statement) throws SQLException {
		PreparedStatement statement = null;
		ResultSet rs = null;
		try {
			int ret = -1;
			statement = getPrepareStatement(_con, sql_statement);
			fLogger.trace(sql_statement);
			notifyExecute(_con, SQLExecutionStatus.BEFORE_EXECUTE);
			try {
				rs = statement.executeQuery();
				rs.next();
				ret = rs.getInt(1);
			} catch (SQLException e) {
				fLogger.warn(e);
			}
			notifyExecute(_con, SQLExecutionStatus.AFTER_EXECUTE,
					StringUtil.EMPTY_STRING + ret, "0");
			return ret;
		} finally {
			if (rs != null) {
				rs.close();
			}
			if (statement != null) {
				statement.close();
			}
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see hiro.yoshioka.sql.ITransactionSQL#counts(java.lang.String[])
	 */
	public ResultSetDataHolder2 counts(String[] sql_statements)
			throws SQLException {
		ResultSetDataHolder2 ret = createRdh2(new String[] { "CNT" }, null);
		for (int i = 0; i < sql_statements.length; i++) {
			PreparedStatement statement = null;
			ResultSet rs = null;
			try {
				statement = getPrepareStatement(_con, sql_statements[i]);
				fLogger.trace(sql_statements[i]);
				notifyExecute(_con, SQLExecutionStatus.BEFORE_EXECUTE);
				try {
					rs = statement.executeQuery();
					rs.next();
					ret.addRow(new String[] { String.valueOf(rs.getInt(1)) });
				} catch (SQLException e) {
					fLogger.warn(e);
					ret.addRow(new String[] { "-1" });
				}
				notifyExecute(_con, SQLExecutionStatus.AFTER_EXECUTE,
						StringUtil.EMPTY_STRING + ret, "0");
			} finally {
				if (rs != null) {
					rs.close();
				}
				if (statement != null) {
					statement.close();
				}
			}
		}
		return ret;
	}

	public int count(Connection con, String sql_statement, String[] args)
			throws SQLException {
		PreparedStatement statement = null;
		ResultSet rs = null;
		try {
			sql_statement = "SELECT COUNT(*) CNT FROM (" + sql_statement + ")";
			statement = getPrepareStatement(con, sql_statement);
			fLogger.trace(sql_statement);
			for (int i = 0; i < args.length; i++) {
				statement.setString(i + 1, args[i]);
			}
			notifyExecute(con, SQLExecutionStatus.BEFORE_EXECUTE);
			rs = statement.executeQuery();
			rs.next();
			int ret = rs.getInt(1);
			notifyExecute(con, SQLExecutionStatus.AFTER_EXECUTE,
					StringUtil.EMPTY_STRING + ret, "0");
			return ret;
		} finally {
			if (rs != null) {
				rs.close();
			}
			if (statement != null) {
				statement.close();
			}
		}
	}

	public boolean execute(ReflectionPreparedStatement ref) throws SQLException {
		PreparedStatement statement = null;
		boolean ret = false;

		try {
			String st = ref.getStatement();
			statement = getPrepareStatement(_con, st);

			fLogger.trace("STATEMENT[" + st + "]");
			ref.setBinds(statement);

			notifyExecute(_con, SQLExecutionStatus.BEFORE_EXECUTE);
			long time = System.currentTimeMillis();
			ret = statement.execute();
			time = System.currentTimeMillis() - time;
			notifyExecute(_con, SQLExecutionStatus.AFTER_EXECUTE,
					Boolean.toString(ret), String.valueOf(time));
			setTransactionTime(true);
			return ret;
		} finally {
			if (statement != null) {
				statement.close();
			}
		}
	}

	public ResultSetDataHolder2 executeQueryForBlob(
			ReflectionPreparedStatement ref) throws SQLException {
		PreparedStatement statement = null;
		ResultSetDataHolder2 rdh = null;

		try {
			String st = ref.getStatement();
			statement = getPrepareStatement(_con, st);

			fLogger.trace("STATEMENT[" + st + "]");
			ref.setBinds(statement);

			notifyExecute(_con, SQLExecutionStatus.BEFORE_EXECUTE);
			long time = System.currentTimeMillis();
			ResultSet rs = statement.executeQuery();
			time = System.currentTimeMillis() - time;
			rdh = RS2RDH(rs, true, st, null);
			notifyExecute(_con, SQLExecutionStatus.AFTER_EXECUTE,
					String.valueOf(rdh.getRowCount()), String.valueOf(time));

		} finally {
			if (statement != null) {
				statement.close();
			}
		}
		return rdh;
	}

	public boolean execute(String sql_statement) throws SQLException {
		Statement statement = null;
		boolean ret = false;
		try {
			statement = _con.createStatement();

			fLogger.trace(sql_statement);
			notifyExecute(_con, SQLExecutionStatus.BEFORE_EXECUTE);
			long time = System.currentTimeMillis();
			// com.microsoft.sqlserver.jdbc.SQLServerException:
			// sp_cursoropen/sp_cursorprepare: ステートメントのパラメータは、バッチまたはストアド
			// プロシージャだけで、単一の選択を含み、FOR BROWSE、COMPUTE BY、または変数代入は含みません。
			// PreparetdStatementを使うなってことみたい。

			ret = statement.execute(sql_statement);
			time = System.currentTimeMillis() - time;
			notifyExecute(_con, SQLExecutionStatus.AFTER_EXECUTE,
					Boolean.toString(ret), String.valueOf(time));
			return ret;
		} finally {
			if (statement != null) {
				statement.close();
			}
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see hiro.yoshioka.sql.ITransactionSQL#execute(java.lang.String,
	 * java.lang.String[])
	 */
	public boolean execute(String sql_statement, String[] args)
			throws SQLException {
		return execute(_con, sql_statement, args);
	}

	// --------------------------------------------------------------------------
	// --
	/**
	 * 引数のSQL文を実行して結果を返す。 <BR>
	 * 
	 * @param connection
	 *            コネクション
	 * @param sql_statement
	 *            SQL文
	 * @param arg1
	 *            ?にセットする文字
	 * @return ResultSetDataHolder 結果セット connectionがNullの場合はNULLを返す。
	 * @throws SQLException
	 *             例外情報
	 */
	// --------------------------------------------------------------------------
	// --
	public ResultSetDataHolder2 executePrepareQuery(Connection connection,
			String sql_statement, String arg1) throws SQLException {
		return executePrepareQuery(connection, sql_statement,
				new String[] { arg1 });
	}

	public boolean diff(DifferenceInStructureRequest diff_request) {
		boolean ret = true;
		try {
			DiffCatalog catalog = diff_request.getDiffCatalog();
			ITransactionSQL targetSql = diff_request.getMirroringToSql();
			ResultSetDataHolder2 me = null, target = null;
			for (String fromSchemaName : diff_request
					.getMappingFromSchemaNames()) {
				String toSchemaName = diff_request
						.getMappingToSchemaName(fromSchemaName);
				for (DBResourceType type : DBResourceType.values()) {
					if (diff_request.containResourceType(type)) {
						fLogger.info(fromSchemaName + "/" + type);
						int[] matchKeys = { 1, 2 };
						switch (type) {
						case TABLE:
							matchKeys = new int[] { 1, 3 };
							break;
						case FUNCTION:
						case SEQUENCE:
							matchKeys = new int[] { 1 };
							break;
						}
						me = this.getDiffInfoOf(type, fromSchemaName,
								diff_request.withValue());
						target = targetSql.getDiffInfoOf(type, toSchemaName,
								diff_request.withValue());
						DiffToResultSetDataHolder drh = new DiffToResultSetDataHolder();
						drh.diffConfigure(me, target, matchKeys);
						drh.setCase_insensitive(true);
						drh.diff();
						drh.setRemarks(DiffToResultSetDataHolder.REMARK_STAMP.STRUCT);
						catalog.put(type.name(), drh);
					}
				}
			}
		} catch (UnsupportedOperationException ue) {
			ret = false;
		} catch (Throwable e) {
			fLogger.info(StringUtil.EMPTY_STRING, e);
			ret = false;
		}
		fLogger.debug("ret:[" + ret + "]");
		return ret;
	}

	@Override
	public ResultSetDataHolder2 getDiffInfoOf(DBResourceType resourceType,
			String schemaName, boolean withValue) {
		fLogger.error("throw new UnsupportedOperationException");
		throw new UnsupportedOperationException();
	}

	public ResultSetDataHolder2 executePrepareQuery(String sql_statement,
			String[] arg1) throws SQLException {
		return executePrepareQuery(_con, sql_statement, arg1);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see hiro.yoshioka.sql.ITransactionSQL#executePrepare(java.lang.String,
	 * java.lang.Object[])
	 */
	public ResultSetDataHolder2 executePrepare(String sql_statement,
			Object[] arg1) throws SQLException {
		return executePrepare(_con, sql_statement, arg1);
	}

	public ResultSetDataHolder2 executePrepare(Connection connection,
			String sql_statement, Object[] args) throws SQLException {
		PreparedStatement statement = null;
		int rs = 0;
		if (connection == null) {
			fLogger.info("connection is null...");
			return null;
		}
		try {
			statement = getPrepareStatement(connection, sql_statement);
			fLogger.trace(sql_statement);
			for (int i = 0; i < args.length; i++) {
				if (args[i] instanceof BindInfo) {
					BindInfo bind = (BindInfo) args[i];
					try {
						if (bind.isBlob()) {
							if (bind.getValue() == null
									|| bind.getStringValue().length() == 0) {
								statement.setNull(i + 1, Types.BLOB);
							} else {
								File file = (File) bind.getValue();
								FileInputStream in = new FileInputStream(file);
								byte[] bytes = new byte[(int) file.length()];
								in.read(bytes, 0, (int) file.length());
								in.close();
								statement.setBytes(i + 1, bytes);
								statement.setBinaryStream(i + 1, in,
										file.length());

							}
						} else if (bind.isBinary()) {
							if (bind.getValue() == null
									|| bind.getStringValue().length() == 0) {
								statement.setNull(i + 1, Types.BINARY);
							} else {
								File file = (File) bind.getValue();
								FileInputStream in = new FileInputStream(file);
								byte[] bytes = new byte[(int) file.length()];
								in.read(bytes, 0, (int) file.length());
								in.close();
								statement.setBytes(i + 1, bytes);
							}
						} else if (bind.isTimeStamp()) {
							if (bind.getValue() == null
									|| bind.getStringValue().length() == 0) {
								statement.setNull(i + 1, Types.TIMESTAMP);
							} else {
								statement.setTimestamp(i + 1, SQLUtil
										.getTimeStamp(bind.getStringValue()));
							}
						} else if (bind.isDate()) {
							if (bind.getValue() == null
									|| bind.getStringValue().length() == 0) {
								statement.setNull(i + 1, Types.DATE);
							} else {
								statement.setDate(i + 1,
										SQLUtil.getDate(bind.getStringValue()));
							}
						} else if (bind.isTime()) {
							if (bind.getValue() == null
									|| bind.getStringValue().length() == 0) {
								statement.setNull(i + 1, Types.TIME);
							} else {
								statement.setTime(i + 1,
										SQLUtil.getTime(bind.getStringValue()));
							}
						} else if (bind.isNumeric()) {
							if (bind.getValue() == null
									|| bind.getStringValue().length() == 0) {
								statement.setNull(i + 1, Types.NUMERIC);
							} else {
								statement.setBigDecimal(i + 1, new BigDecimal(
										bind.getStringValue()));
							}
						} else {
							statement.setString(i + 1, bind.getStringValue());
						}

					} catch (Throwable e) {
						fLogger.warn(e);
					}

				} else {
					statement.setString(i + 1, (String) args[i]);
				}
			}
			notifyExecute(connection, SQLExecutionStatus.BEFORE_EXECUTE);
			long time = System.currentTimeMillis();
			rs = statement.executeUpdate();
			time = System.currentTimeMillis() - time;
			notifyExecute(connection, SQLExecutionStatus.AFTER_EXECUTE,
					String.valueOf(rs), String.valueOf(time));

			ResultSetDataHolder2 rdh = createRdh2(
					new String[] { "UpdateCount" }, null);
			rdh.addRow(new String[] { String.valueOf(rs) });
			rdh.setWrapTime(time);
			setTransactionTime(true);
			return rdh;
		} finally {
			if (statement != null) {
				statement.close();
			}
		}
	}

	public ResultSetDataHolder2 createRdh2(String[] argNames,
			ResultSetMetaData meta) throws NullPointerException {
		ResultSetDataHolder2 rdh = new ResultSetDataHolder2(argNames, meta,
				getDatabaseType());
		rdh.setConnectionDisplayString(_info.getDisplayString());
		return rdh;
	}

	public void setMaxRowNum(int max) {
		maxRow = max;
	}

	// --------------------------------------------------------------------------
	// --
	/**
	 * 引数のSQL文を実行して結果を返す。 <BR>
	 * 
	 * @param connection
	 *            コネクション
	 * @param sql_statement
	 *            SQL文
	 * @param args
	 *            ?にセットする文字
	 * @return ResultSetDataHolder 結果セット connectionがNullの場合はNULLを返す。
	 * @throws SQLException
	 *             例外情報
	 */
	// --------------------------------------------------------------------------
	// --
	public ResultSetDataHolder2 executePrepareQuery(Connection connection,
			String sql_statement, String[] args) throws SQLException {
		PreparedStatement statement = null;
		ResultSet rs = null;
		if (connection == null) {
			return null;
		}
		try {

			statement = getPrepareStatement(connection, sql_statement);
			fLogger.trace(sql_statement);
			if (args != null) {
				for (int i = 0; i < args.length; i++) {
					statement.setString(i + 1, args[i]);
					fLogger.trace("bind[" + i + "]=" + args[i]);
				}
			}
			notifyExecute(connection, SQLExecutionStatus.BEFORE_EXECUTE);
			long time = System.currentTimeMillis();
			rs = statement.executeQuery();
			time = System.currentTimeMillis() - time;

			ResultSetDataHolder2 rdh = RS2RDH(rs, true, sql_statement, args);
			notifyExecute(connection, SQLExecutionStatus.AFTER_EXECUTE,
					String.valueOf(rdh.getRowCount()), String.valueOf(time));

			rdh.setWrapTime(time);
			return rdh;
		} finally {
			if (statement != null) {
				statement.close();
			}
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see hiro.yoshioka.sql.ITransactionSQL#saveCsv(java.lang.String,
	 * jp.sf.orangesignal.csv.handlers.ResultSetHandler,
	 * jp.sf.orangesignal.csv.CsvWriter)
	 */
	public boolean saveCsv(String sql_statement, ResultSetHandler handler,
			CsvWriter writer) throws SQLException {
		PreparedStatement statement = null;
		ResultSet rs = null;
		if (_con == null) {
			return false;
		}
		try {
			notifyExecute(_con, SQLExecutionStatus.BEFORE_EXECUTE);
			statement = _con
					.prepareStatement(sql_statement,
							ResultSet.TYPE_SCROLL_SENSITIVE,
							ResultSet.CONCUR_READ_ONLY);
			fLogger.trace(sql_statement);
			long time = System.currentTimeMillis();
			rs = statement.executeQuery();
			time = System.currentTimeMillis() - time;

			notifyExecute(_con, SQLExecutionStatus.AFTER_EXECUTE, "0",
					String.valueOf(time));
			try {
				handler.save(rs, writer);
				writer.flush();
				writer.close();
				return true;
			} catch (IOException e) {
				fLogger.error(e);
			}
			return false;
		} finally {
			if (rs != null) {
				rs.close();
			}
			if (statement != null) {
				statement.close();
			}
		}
	}

	public void executePrepareQueryByLine(String sql_statement,
			LineListener listner) throws SQLException {
		PreparedStatement statement = null;
		ResultSet rs = null;
		if (_con == null) {
			return;
		}
		try {
			notifyExecute(_con, SQLExecutionStatus.BEFORE_EXECUTE);

			statement = _con
					.prepareStatement(sql_statement,
							ResultSet.TYPE_SCROLL_SENSITIVE,
							ResultSet.CONCUR_READ_ONLY);
			fLogger.trace(sql_statement);

			long time = System.currentTimeMillis();

			rs = statement.executeQuery();

			listner.first(rs);
			rs.close();

			rs = statement.executeQuery();

			time = System.currentTimeMillis() - time;

			for (int i = 0; rs.next(); i++) {
				listner.next(rs);
			}
			notifyExecute(_con, SQLExecutionStatus.AFTER_EXECUTE, "0",
					String.valueOf(time));
		} finally {
			if (rs != null) {
				rs.close();
			}
			if (statement != null) {
				statement.close();
			}
		}
	}

	// --------------------------------------------------------------------------
	// --
	/*
	 * (non-Javadoc)
	 * 
	 * @see hiro.yoshioka.sql.ITransactionSQL#cansel()
	 */
	// --------------------------------------------------------------------------
	// --
	public boolean cansel() throws SQLException {
		boolean status = true;
		if (fActiveStatement != null) {
			fActiveStatement.cancel();
			fActiveStatement = null;
		}

		return true;
	}

	public boolean closeActiveStatement() throws SQLException {
		if (fActiveStatement != null) {
			fActiveStatement.close();
			fActiveStatement = null;
		}

		return true;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see hiro.yoshioka.sql.ITransactionSQL#commit()
	 */
	public boolean commit() {
		try {
			_con.commit();
			setTransactionTime(false);
			for (int i = 0; i < fTransactionListenerList.size(); i++) {
				try {
					fTransactionListenerList.get(i).commited();
				} catch (RuntimeException e) {
					fLogger.error(e);
				}
			}
		} catch (SQLException e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see hiro.yoshioka.sql.ITransactionSQL#rollback()
	 */
	public boolean rollback() {
		try {
			_con.rollback();
			for (int i = 0; i < fTransactionListenerList.size(); i++) {
				try {
					fTransactionListenerList.get(i).rollbacked();
				} catch (RuntimeException e) {
					fLogger.error(e);
				}
			}
			setTransactionTime(false);
		} catch (SQLException e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	protected void setTransactionTime(boolean f) {
		boolean bf = fTrunsactionTime;
		fTrunsactionTime = f;
		if (bf != fTrunsactionTime) {
			for (int i = 0; i < fTransactionListenerList.size(); i++) {
				try {
					if (fTrunsactionTime) {
						fTransactionListenerList.get(i).transactionStarted();
					} else {
						fTransactionListenerList.get(i).transactionEnded();
					}
				} catch (RuntimeException e) {
					fLogger.error(e);
				}
			}
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see hiro.yoshioka.sql.ITransactionSQL#trunsactionTime()
	 */
	public boolean trunsactionTime() {
		return fTrunsactionTime;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see hiro.yoshioka.sql.ITransactionSQL#getTableMetaCopy(java.lang.String)
	 */
	public ResultSetMetaCopy getTableMetaCopy(String name) {
		return getTableMetaCopy(name, StringUtil.EMPTY_STRING_ARRAY);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see hiro.yoshioka.sql.ITransactionSQL#getTableMetaCopy(java.lang.String,
	 * java.lang.String[])
	 */
	public ResultSetMetaCopy getTableMetaCopy(String name, String[] strings) {

		Statement st = null;
		try {
			st = _con.createStatement();

			StringBuffer selection = new StringBuffer("SELECT ");
			if (strings.length <= 0) {
				selection.append("*");
			} else {
				for (int i = 0; i < strings.length; i++) {
					selection.append(strings[i]).append(",");
				}
				selection.setLength(selection.length() - 1);
			}

			selection.append(" FROM ").append(name).append(" WHERE 1 = 2");

			ResultSet rs = st.executeQuery(selection.toString());

			ResultSetMetaData meta = rs.getMetaData();

			ResultSetMetaCopy copy = new ResultSetMetaCopy(meta);

			rs.close();

			return copy;
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			if (st != null) {
				try {
					st.close();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}

		return null;
	}

	public int[] getSQLTypes(String select_statement) {

		Statement st = null;
		try {
			st = _con.createStatement();
			st.setMaxRows(1);
			ResultSet rs = st.executeQuery(select_statement);

			ResultSetMetaData meta = rs.getMetaData();

			int[] ret = new int[meta.getColumnCount()];

			for (int i = 1; i <= meta.getColumnCount(); i++) {
				ret[i - 1] = meta.getColumnType(i);
			}
			rs.close();

			return ret;
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			if (st != null) {
				try {
					st.close();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}

		return null;
	}

	public boolean setDDLOfTable(String schemaName, IDBTable tableOrView)
			throws SQLException {
		MirroringRequest request = new MirroringRequest(this._info, this._info);
		if (tableOrView.getColumns().length == 0) {
			setTableColumns(schemaName, tableOrView);
		}
		String str = SQLUtil2.createTableAtMirroring(schemaName, tableOrView,
				request);
		tableOrView.setText(str);
		return true;
	}

	public boolean createMirroredTableTo(MirroringRequest mirroring_request)
			throws SQLException {
		fLogger.info("start.");

		mirroring_request.setMirroringFromSql(this);
		ITransactionSQL mirroring_to_sql = mirroring_request
				.getMirroringToSql();
		boolean retCode = true;
		try {
			ConnectionProperties targetConnectionProperties = mirroring_request
					.getTargetConnectionProperties();
			String text = String.format("DB Migraion Connecting[%s]",
					targetConnectionProperties.getDisplayString());
			mirroring_request.beginTask(text, 2);

			mirroring_request.worked(1);

			mirroring_to_sql.connect(targetConnectionProperties);
			mirroring_request.worked(1);
			text = String.format("DB Migraion Connect Success[%s]",
					targetConnectionProperties.getDisplayString());
			mirroring_request.subTask(text);

			DBRoot targetRoot = targetConnectionProperties.getDBRootResource();
			if (targetRoot == null) {
				fLogger.fatal("☆☆☆");
				String message = String.format(
						"☆☆☆ Missing DBRoot Resourceon [%s]",
						targetConnectionProperties.getDisplayString());
				fLogger.fatal(message);
				mirroring_request.setThrowable(new IllegalStateException(
						message));
				mirroring_request.addResultRecord(new String[] { "CHECK", "-",
						targetConnectionProperties.getDisplayString(),
						StringUtil.EMPTY_STRING, "×", "-",
						"Missing DBRoot Resourceon" });
				return false;
			}
			if (!mirroring_to_sql
					.createMirroredTableTo_FaseOnSchema(mirroring_request)) {
				retCode = false;
			}
			if (!mirroring_to_sql
					.createMirroredTableTo_FaseOnTable(mirroring_request)) {
				retCode = false;
			}

			// IDBSequence[] sequences =
			// fDBResourceTreeSelection.getSequencese();
			// mirroring_request.beginTask("Sequence Migration Start",
			// sequences.length);
			// doMig(mirroring_request, sql, target_sql, sequences);

			retCode = !mirroring_request.hasException();
		} catch (Throwable e) {
			mirroring_request.setThrowable(e);
			fLogger.error(StringUtil.EMPTY_STRING, e);
			retCode = false;
		} finally {
		}
		fLogger.info("end. retCode=" + retCode);
		return retCode;
	}

	// ----------------------------------------------------------------
	// [5] MIRRORING
	// ----------------------------------------------------------------
	@Override
	public boolean createMirroredTableTo_FaseOnSchema(
			MirroringRequest mirroring_request) throws SQLException {
		fLogger.info("start.");

		Collection<String> schemaCollection = mirroring_request
				.getMappingToSchemaNames();
		mirroring_request.beginTask("Schema Migraion Start",
				schemaCollection.size());
		int cnt = 0;

		for (String schemaName : schemaCollection) {
			try {
				int dropCnt = 0;
				int createCnt = 0;
				cnt++;
				String text = String.format("DB Migtaion NOW %s.%s [%d/%d]",
						mirroring_request.getConnectionProperties()
								.getDisplayString(), schemaName, cnt,
						schemaCollection.size());
				mirroring_request.subTask(text);
				if (mirroring_request.isCanceled()) {
					return false;
				}
				mirroring_request.worked(1);
				boolean existsSchema = existsSchema(schemaName);
				mirroring_request.subTask(String.format(
						"Exists Schema Check... exists[%b]", existsSchema));
				if (existsSchema && mirroring_request.dropSchema) {
					mirroring_request.subTask(String.format("Drop Schema [%s]",
							schemaName));
					dropSchema(schemaName, mirroring_request.cascade);
					dropCnt++;
					fLogger.info(String.format("Schema droped"));
				}

				existsSchema = existsSchema(schemaName);
				if (!existsSchema || mirroring_request.dropSchema) {
					mirroring_request.subTask(String.format(
							"CREATE Schema [%s]", schemaName));
					createSchema(schemaName, null);
					createCnt++;
					fLogger.info(String.format("schema created"));
				}
				if (!_con.getAutoCommit()) {
					boolean rlt = commit();
					fLogger.info(String.format("commited result[%b]", rlt));
				}
				mirroring_request.addResultRecord(new String[] { "SCHEMA", "-",
						schemaName, StringUtil.EMPTY_STRING, "○",
						String.format("C:%d D:%d", createCnt, dropCnt), "-" });
			} catch (SQLException e) {
				mirroring_request.addResultRecord(new String[] { "SCHEMA", "-",
						schemaName, StringUtil.EMPTY_STRING, "×", "-",
						StringUtil.getStackTraceString(e, 8) });
				if (!mirroring_request.continuing) {
					throw e;
				}
				if (!_con.getAutoCommit()) {
					boolean rlt = rollback();
					fLogger.info(String.format("rollbacked result[%b]", rlt));
				}
			} finally {
				mirroring_request.worked(1);
			}
		}

		fLogger.info("end.");
		return true;
	}

	@Override
	public boolean createMirroredTableTo_FaseOnTable(
			MirroringRequest mirroring_request) throws SQLException {
		boolean retCode = true;

		// IDBTable[] tables = mirroring_request.getTargetTables();
		// mirroring_request.beginTask("Column Info Check Start",
		// tables.length);
		// for (IDBTable table : tables) {
		// if (table.getColumns().length == 0) {
		// setTableColumns(table.getParent().getName(), table);
		// }
		// mirroring_request.worked(1);
		// }
		Set<String> mappingFromSchemaNameSet = mirroring_request
				.getTableMapping().keySet();
		fLogger.info("start mirroing table mappingFromSchemaNameSet size="
				+ mappingFromSchemaNameSet.size());
		out: for (String mappingFromSchemaName : mappingFromSchemaNameSet) {
			Set<MirroringRequest.MirroringTableInfo> tableInfoSet = mirroring_request
					.getTableMapping().get(mappingFromSchemaName);
			String mappingToSchemaName = mirroring_request
					.getMappingToSchemaName(mappingFromSchemaName);
			mirroring_request.beginTask(mappingFromSchemaName
					+ " Table Migraion Start", tableInfoSet.size());
			int i = 0;
			for (MirroringRequest.MirroringTableInfo tableInfo : tableInfoSet) {
				i++;
				int retCnt = 0;
				try {
					IDBTable mappingFromTable = tableInfo
							.getMappingFromDBTable(mappingFromSchemaName);
					boolean existsTable = existsTable(mappingToSchemaName,
							tableInfo.name);

					mirroring_request.subTask(String.format(
							"Exists Table Checker... [%s.%s] exists[%b]",
							mappingToSchemaName, tableInfo.name, existsTable));
					if (existsTable && mirroring_request.dropTable) {
						dropTable(mappingToSchemaName, mappingFromTable,
								mirroring_request.cascade);
					}

					ITransactionSQL mirroringFromSql = mirroring_request
							.getMirroringFromSql();
					fLogger.info(String.format("supportReusltSet[%b]",
							mirroringFromSql.supportResultSet()));
					fLogger.info(String.format("Table Info[%s] ", tableInfo));
					// for table
					if (mirroringFromSql.supportResultSet()) {
						ResultSet rs = null;
						try {
							rs = mirroringFromSql.getAllData(mappingFromTable);
							if (mappingFromTable.getColumns().length == 0) {
								mirroring_request.getMirroringToSql()
										.setTableColumns(mappingToSchemaName,
												mappingFromTable);
							}
							if (!existsTable || mirroring_request.dropTable) {
								fLogger.info(String.format(
										"create table [%s.%s]",
										mappingToSchemaName,
										mappingFromTable.getName()));
								String create_sql_statement = SQLUtil2
										.createTableAtMirroring(
												mappingToSchemaName,
												mappingFromTable,
												mirroring_request);

								boolean ret = execute(create_sql_statement);
								fLogger.info("create table result=" + ret);
							}

							retCnt = doInsertFromRs(rs, mappingToSchemaName,
									mirroring_request, tableInfo);
						} catch (SQLException e) {
							retCode = false;
							fLogger.warn(StringUtil.EMPTY_STRING, e);
							mirroring_request.addResultRecord(new String[] {
									"TABLE", "-", tableInfo.name,
									StringUtil.EMPTY_STRING, "×",
									String.valueOf(retCnt),
									StringUtil.getStackTraceString(e, 8) });
							mirroring_request.setThrowable(e);
							if (!mirroring_request.continuing) {
								break out;
							}
						} finally {
							try {
								if (rs != null) {
									rs.close();
								}
							} catch (SQLException e) {
								fLogger.warn(e);
								return false;
							}
						}
					} else {
						try {
							ResultSetDataHolder2 copy_rdh = mirroringFromSql
									.getAllData2(mappingFromTable,
											mirroring_request);
							if (mappingFromTable.getColumns().length == 0) {
								// fromのテーブル情報でToにテーブルを作成する。Fromの列がなければ取得する
								mirroring_request.getMirroringFromSql()
										.setTableColumns(mappingFromSchemaName,
												mappingFromTable);
							}
							if (!existsTable || mirroring_request.dropTable) {
								String sql_statement = SQLUtil2
										.createTableAtMirroring(
												mappingToSchemaName,
												mappingFromTable,
												mirroring_request);
								execute(sql_statement);
							}

							retCnt = doInsertFromRdh(copy_rdh,
									mappingToSchemaName, mirroring_request,
									tableInfo);
						} catch (Exception e) {
							retCode = false;
							fLogger.warn(StringUtil.EMPTY_STRING, e);
							mirroring_request.addResultRecord(new String[] {
									"TABLE", "-", tableInfo.name,
									StringUtil.EMPTY_STRING, "×",
									String.valueOf(retCnt),
									StringUtil.getStackTraceString(e, 8) });
							if (!mirroring_request.continuing) {
								break out;
							}

						} finally {
						}
					}

					if (!_con.getAutoCommit()) {
						boolean commit_result = commit();
						mirroring_request
								.subTask(String.format(
										"Insert commited... result[%b]",
										commit_result));
					}
					mirroring_request.addResultRecord(new String[] { "TABLE",
							"-", tableInfo.name, StringUtil.EMPTY_STRING, "○",
							String.valueOf(retCnt), "-" });
				} catch (SQLException e) {
					retCode = false;
					mirroring_request.addResultRecord(new String[] { "TABLE",
							"-", tableInfo.name, StringUtil.EMPTY_STRING, "×",
							String.valueOf(retCnt),
							StringUtil.getStackTraceString(e, 8) });
					mirroring_request.setThrowable(e);
					if (!_con.getAutoCommit()) {
						rollback();
					}
					if (!mirroring_request.continuing) {
						break out;
					}
				} finally {
					mirroring_request.worked(1);
				}
			}
		}

		return retCode;
	}

	@Override
	public boolean createDatabase(String name, Properties properties)
			throws SQLException {
		fLogger.fatal("========================================="); //$NON-NLS-1$
		fLogger.fatal("Not support yet"); //$NON-NLS-1$
		fLogger.fatal("========================================="); //$NON-NLS-1$
		return false;
	}

	@Override
	public boolean dropDatabase(String name) throws SQLException {
		fLogger.fatal("========================================="); //$NON-NLS-1$
		fLogger.fatal("Not support yet"); //$NON-NLS-1$
		fLogger.fatal("========================================="); //$NON-NLS-1$
		return false;
	}

	@Override
	public boolean createUser(String name, Properties properties)
			throws SQLException {
		fLogger.fatal("========================================="); //$NON-NLS-1$
		fLogger.fatal("Not support yet"); //$NON-NLS-1$
		fLogger.fatal("========================================="); //$NON-NLS-1$
		return false;
	}

	@Override
	public boolean dropUser(String name) throws SQLException {
		fLogger.fatal("========================================="); //$NON-NLS-1$
		fLogger.fatal("Not support yet"); //$NON-NLS-1$
		fLogger.fatal("========================================="); //$NON-NLS-1$
		return false;
	}

	protected boolean createSchema(String schemaName, Properties properties)
			throws SQLException {
		String st = String.format("CREATE SCHEMA  %s ", schemaName);
		executePrepare(st, EMPTY);
		return true;
	}

	protected boolean dropSchema(String schemaName, boolean cascade)
			throws SQLException {
		String st = String.format("DROP SCHEMA %s", schemaName);
		if (cascade) {
			st += " CASCADE";
		}
		executePrepare(st, EMPTY);
		return true;
	}

	protected boolean dropTable(String schemaName, IDBTable table,
			boolean cascade) throws SQLException {
		StringBuilder st = new StringBuilder();
		if (StringUtil.isEmpty(schemaName)) {
			st.append(String.format("DROP TABLE %s", table.getName()));
		} else {
			st.append(String.format("DROP TABLE %s.%s", schemaName,
					table.getName()));
		}
		if (cascade) {
			st.append(" CASCADE ");
		}
		executePrepare(st.toString(), EMPTY);
		return true;
	}

	public boolean migration(ITransactionSQL osql, DBCrossRefference original,
			boolean drop, boolean cascade) throws SQLException {
		return false;
	}

	public boolean existsTable(String schemaName, String tableName)
			throws SQLException {
		System.err.println("do override!!!!!!!!!!!");
		return false;
	}

	public boolean migration(ITransactionSQL osql, IDBSequence original,
			boolean drop, boolean cascade, boolean noSchema)
			throws SQLException {
		return false;
	}

	public int doInsertFromRs(ResultSet all_rs, String mappingToSchemaName,
			MirroringRequest request,
			MirroringRequest.MirroringTableInfo tableInfo) throws SQLException {
		int retCnt = 0;
		ResultSetMetaData rs_meta = all_rs.getMetaData();

		if (rs_meta == null || rs_meta.getColumnCount() == 0) {
			return retCnt;
		}
		PreparedStatement st = null;
		StringBuilder buf = new StringBuilder();
		StringBuilder value_buf = new StringBuilder();
		buf.append("INSERT INTO ");

		if (!StringUtil.isEmpty(mappingToSchemaName)) {
			buf.append(mappingToSchemaName).append(".");
		}
		buf.append(tableInfo.name).append(" ");
		buf.append("(");
		for (int i = 1; i <= rs_meta.getColumnCount(); i++) {
			if (i > 1) {
				buf.append(",");
				value_buf.append(",");
			}
			String columnName = request.getSubsutituteColumnName(rs_meta
					.getColumnName(i));
			if (StringUtil.isEmpty(columnName)) {
				buf.append(rs_meta.getColumnName(i));
			} else {
				buf.append(columnName);
			}
			value_buf.append("?");
		}
		buf.append(")").append(StringUtil.LINE_SEPARATOR);
		buf.append("VALUES (");
		buf.append(value_buf);
		buf.append(")");
		int sum = 0;

		fLogger.debug(buf.toString());
		while (all_rs.next() && sum < request.maxRowNum) {
			try {
				st = getPrepareStatement(_con, buf.toString());
				for (int i = 1; i <= rs_meta.getColumnCount(); i++) {
					SQLDataType dataType = SQLDataType.parse(rs_meta
							.getColumnType(i));
					if ((dataType.isBinary() || dataType.isBlob())
							&& !request.makeBlob) {
						st.setNull(i, dataType.getType());
					} else {
						SQLUtil.setBindString(
								request.getMirroringFromDatabaseType(),
								request.getMirroringToDatabaseType(), st, i,
								all_rs, dataType);
					}
				}
				st.execute();
				retCnt++;
			} finally {
				sum++;
				if (st != null) {
					st.close();
				}
			}
		}
		return retCnt;
	}

	public int doInsertFromRdh(ResultSetDataHolder2 rdh,
			String mappingToSchemaName, MirroringRequest request,
			MirroringRequest.MirroringTableInfo tableInfo) throws SQLException {

		int retCnt = 0;
		String[] keyNames = rdh.getNoRowKeys();
		if (keyNames.length == 0) {
			return retCnt;
		}
		PreparedStatement st = null;

		for (int i = 0; i < rdh.getRowCount() && i < request.maxRowNum; i++) {
			try {

				ReflectionPreparedStatement reflect = rdh
						.generateInsertPreparedStatement(i,
								request.getcolumnNameSubstitutionMap(),
								StringUtil.isEmpty(mappingToSchemaName));
				if (fLogger.isTraceEnabled()) {
					fLogger.trace("reflectsql=" + reflect.getStatement());
				}
				st = getPrepareStatement(_con, reflect.getStatement());
				reflect.setBinds(st);
				st.execute();
				retCnt++;
			} finally {
				if (st != null) {
					st.close();
				}
			}
		}
		return retCnt;
	}

}