package hiro.yoshioka.sql;

import hiro.yoshioka.ast.sql.oracle.WolfSQLParserConstants;
import hiro.yoshioka.ast.sql.util.BindInfo;
import hiro.yoshioka.classmanager.ClassManager;
import hiro.yoshioka.sdh.ResultSetDataHolder;
import hiro.yoshioka.sdh2.ResultSetDataHolder2;
import hiro.yoshioka.sql.engine.GettingResourceRequest;
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.resource.DBColumn;
import hiro.yoshioka.sql.resource.DBCrossRefference;
import hiro.yoshioka.sql.resource.DBRoot;
import hiro.yoshioka.sql.resource.DBSchema;
import hiro.yoshioka.sql.resource.DBSequence;
import hiro.yoshioka.sql.resource.DBTable;
import hiro.yoshioka.sql.resource.DBTrigger;
import hiro.yoshioka.sql.resource.IDBColumn;
import hiro.yoshioka.sql.resource.IDBResource;
import hiro.yoshioka.sql.resource.IDBSchema;
import hiro.yoshioka.sql.resource.IDBSequence;
import hiro.yoshioka.sql.resource.IDBTable;
import hiro.yoshioka.sql.resource.IDBTrigger;
import hiro.yoshioka.sql.resource.ProcedureType;
import hiro.yoshioka.sql.resource.TableType;
import hiro.yoshioka.sql.util.OracleBlobInfo;
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.OutputStream;
import java.lang.reflect.Method;
import java.sql.CallableStatement;
import java.sql.DatabaseMetaData;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class OracleSQL extends AbsTransactionSQL implements IOracleConst,
		IDoExplainPlan {
	static final String CLIENTINFOBEGIN = "begin dbms_application_info.set_client_info('%s'); end;";
	public static final String[] RESULT_MESSAGE = { "RESULT" };

	public static final int EXPLAIN_PLAN = -3000;

	public static final int WORST_SQL = -3950;

	private boolean sessionChecked;

	private boolean canDoGetSession;

	private File classes12File;

	private DBMSOutput dbms;

	private ClassManager class_manager;

	class TableComment {
		String _owner;

		String _name;

		String _type;

		String _comment;

		public TableComment(String owner, String name, String type,
				String comment) {
			_owner = owner;
			_name = name;
			_type = type;
			_comment = comment;
		}

		public String toString() {
			return "N/C [" + _name + "/" + _comment + "]";
		}
	}

	// --
	protected OracleSQL(Driver driver) {
		super(driver);
		// driver.
	}

	protected OracleSQL(Driver driver, File classes12File) {
		super(driver);
		this.classes12File = classes12File;
	}

	protected String getSupportToken() {
		StringBuffer buf = new StringBuffer();
		Pattern p = Pattern.compile("\"(\\w+)\"");
		String[] str = WolfSQLParserConstants.tokenImage;
		for (int i = 0; i < str.length; i++) {
			Matcher m = p.matcher(str[i]);
			if (m.matches()) {
				buf.append(m.group(1)).append(",");
			}
		}
		if (buf.length() > 0) {
			buf.setLength(buf.length() - 1);
		}
		return buf.toString();
	}

	@Override
	public void setTableColumns(String schemaName, IDBTable table)
			throws SQLException {
		if (!table.isTable()) {
			super.setTableColumns(schemaName, table);
			return;
		}
		setColumnsToDBTable(null, table, schemaName);
	}

	@Override
	protected DBRoot getMetaData(GettingResourceRequest request) {
		pkMap = new HashMap<String, ResultSetDataHolder>();
		DBRoot oldRoot = getRoot();
		IDBSchema schema = null;
		fLogger.info("info=" + _info);
		if (_info.isOnlyConnectedUserInfo()) {
			try {
				DatabaseMetaData meta = _extra_con.getMetaData();
				capturing = true;

				if (request.canceld()) {
					return null;
				}
				if (!request.targetType.isOnlyTable()) {
					DBRoot rt = new DBRoot(meta.getUserName());
					setRoot(rt);
					rt.setProperties(getDBMetaProperties(meta));

					fLogger.info("new DBRoot");
					schema = new DBSchema(rt);
					schema.setName(meta.getUserName().toUpperCase());
					rt.putResource(schema.getName(), schema);

					rt.setDefaultSchema(schema);
					rt.setCurrentSchema(schema);

					fLogger.info("start TABLE");
					notifyExecute(_extra_con, SQLExecutionStatus.GET_META_TABLE);
					ResultSetDataHolder rdh = null;
					request.beginTask("SELECT USER OBJECTS", 1);
					rdh = executePrepareQuery(_extra_con, _SELECT_USER_OBJECTS,
							EMPTY);
					request.beginTask("SELECT USER OBJECTS DETAIL",
							rdh.getRowCount());
					boolean notifyProc = true;
					for (int j = 0; j < rdh.getRowCount(); j++) {
						String name = rdh.getStringData(j, "OBJECT_NAME");
						String type = rdh.getStringData(j, "OBJECT_TYPE");
						String status = rdh.getStringData(j, "STATUS");
						String comments = rdh.getStringData(j, "COMMENTS");
						if (name.indexOf("\\") >= 0 || name.indexOf("/") >= 0
								|| name.indexOf("BIN$") >= 0) {
							continue;
						}
						if (!_info.isCapturingTarget(null, null, name)) {
							continue;
						}
						if ("TABLE".equals(type)) {
							DBTable table = new DBTable(schema);
							table.setName(name);
							table.setTableType(type);
							table.setComment(comments);
							schema.putTable(table);
						} else if ("VIEW".equals(type)
								&& _info.isCaptureWithViewInfo()) {
							DBTable table = new DBTable(schema);
							table.setName(name);
							table.setTableType(type);
							table.setComment(comments);
							schema.putTable(table);
						} else if ("SYNONYM".equals(type)
								&& _info.isCaptureWithSynonymInfo()) {
							DBTable table = new DBTable(schema);
							table.setName(name);
							table.setTableType(type);
							table.setComment(comments);
							schema.putTable(table);
							setTableColumns(schema.getName(), table);
						} else if (_info.isCaptureWithProcedureInfo()
								&& ("PROCEDURE".equals(type) || "FUNCTION"
										.equals(type))) {
							if (notifyProc) {
								notifyProc = false;
								request.subTask("SELECT FUNCTIONS");
							}
							DBTable dbProcudure = new DBTable(schema);
							dbProcudure.setName(name);
							dbProcudure.setProcedureType(ProcedureType
									.parse(type));
							if (dbProcudure.getProcedureType()
									.isProcedureOrUnknown()) {
								dbProcudure.setTableType(TableType.PROCEDURE);
							} else {
								dbProcudure.setTableType(TableType.FUNCTION);
							}

							dbProcudure.setResources(getProcedureColumns(
									schema.getName(), dbProcudure));
							schema.putProcedure(dbProcudure);
						}
						request.subTask(name + "/" + type + "/" + comments);

						request.worked(1);
						if (request.canceld()) {
							return null;
						}
					}
					int maxLen = SQLUtil.getMaxColumnNameBytes(_extra_con);
					fLogger.info("start COLUMN");
					if (request.getConnectionProperties()
							.isCaptureWithColumnInfo()) {
						request.beginTask("SELECT ALL TAB COLS", 1);
						rdh = executePrepareQuery(_extra_con,
								_SELECT_COL_INFO_ALL, EMPTY);
						request.beginTask("SELECT ALL TAB COLS DETAIL",
								rdh.getRowCount());
						for (int j = 0; j < rdh.getRowCount(); j++) {
							String name = rdh.getStringData(j, "TABLE_NAME");
							String cname = rdh.getStringData(j, "COLUMN_NAME");
							String type = rdh.getStringData(j, "DATA_TYPE");
							String nullable = rdh.getStringData(j, "NULLABLE");
							String pk = rdh.getStringData(j, "PK");
							String comments = rdh.getStringData(j, "COMMENTS");
							int length = rdh.getIntDataDefaultZero(j,
									"DATA_LENGTH");
							int precision = rdh.getIntDataDefaultZero(j,
									"DATA_PRECISION");
							int scale = rdh.getIntDataDefaultZero(j,
									"DATA_SCALE");
							IDBTable table = schema.getTableResource(name);
							if (table == null) {
								continue;
							}
							DBColumn column = new DBColumn(table);
							column.setName(cname);
							column.setComment(comments);
							column.setPKey(pk.length() > 0);

							column.setDataType(SQLDataType.parse(type));
							if (precision == 0) {
								column.setSize(length);
							} else {
								column.setSize(precision);
							}
							column.setDecimalDigits(scale);
							column.setNotNull("N".equalsIgnoreCase(nullable));

							column.setDataTypeString(type);
							column.setMaxColumnNameLength(maxLen);

							fLogger.fatal(String.format(
									" %s %s[%d](%d.%d) PK[%b] ", cname, type,
									column.getDataType(), column.getSize(),
									column.getDecimalDigits(), pk));
							table.putResource(column.getUName(), column);

							request.subTask(name + "/" + type + "/" + comments);
							request.worked(1);
							if (request.canceld()) {
								return null;
							}
						}
					}
					if (request.canceld()) {
						return null;
					}

					if (request.fCaptionForignKey) {
						createCrossReferenceDef(request);
					}
					getTrigger(request);
					if (request.getConnectionProperties().isCaptureWithDDL()) {
						setTableText(request);
					}
					if (request.canceld()) {
						return null;
					}
					if (_info.isCaptureWithSequenceInfo()) {
						getSequence(request);
					}

					if (oldRoot != null) {
						rt.getRecentryUsedResource().addAll(
								oldRoot.getRecentryUsedResource());
					}
				} else {

					fLogger.info("start COLUMN");
					request.beginTask("SELECT ALL TAB COLS", 1);
					this.setColumnsToDBTable(request,
							(IDBTable) request.selectionResource, null);

				}

			} catch (Exception e) {
				fLogger.error(e);
				return null;
			} finally {
				capturing = false;
			}
		} else {
			super.getMetaData(request);
		}
		try {
			if (_info.isValidateDBResource()) {
				setValidation(request);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		pkMap.clear();
		pkMap = null;
		return getRoot();
	}

	private boolean setColumnsToDBTable(GettingResourceRequest request,
			IDBTable table, String schemaName) throws SQLException {
		int maxLen = SQLUtil.getMaxColumnNameBytes(_extra_con);
		boolean retCode = true;

		table.removeAllColumns();

		if (StringUtil.isEmpty(schemaName)) {
			schemaName = table.getParent().getName();
		}
		ResultSetDataHolder rdh = null;
		if (StringUtil.isEmpty(schemaName)) {
			rdh = executePrepareQuery(_extra_con,
					_SELECT_COL_INFO_A_TABLE_ONLY_ME,
					new String[] { table.getName() });
		} else {
			rdh = executePrepareQuery(_extra_con,
					_SELECT_COL_INFO_A_TABLE_FROMALL, new String[] {
							schemaName, table.getName() });
		}
		if (request != null) {
			request.beginTask("SELECT ALL TAB COLS DETAIL", rdh.getRowCount());
		}
		for (int j = 0; j < rdh.getRowCount(); j++) {
			String name = rdh.getStringData(j, "TABLE_NAME");
			String cname = rdh.getStringData(j, "COLUMN_NAME");
			String type = rdh.getStringData(j, "DATA_TYPE");
			String nullable = rdh.getStringData(j, "NULLABLE");
			String pk = rdh.getStringData(j, "PK");
			String comments = rdh.getStringData(j, "COMMENTS");
			int length = rdh.getIntDataDefaultZero(j, "DATA_LENGTH");
			int precision = rdh.getIntDataDefaultZero(j, "DATA_PRECISION");
			int scale = rdh.getIntDataDefaultZero(j, "DATA_SCALE");

			fLogger.info(" name/cname/pk [" + name + "/" + cname + "/" + pk);
			DBColumn column = new DBColumn(table);
			column.setName(cname);
			column.setComment(comments);
			column.setPKey(pk.length() > 0);

			column.setDataType(SQLDataType.parse(type));
			if (precision == 0) {
				column.setSize(length);
			} else {
				column.setSize(precision);
			}
			column.setDecimalDigits(scale);
			column.setNotNull("N".equalsIgnoreCase(nullable));

			column.setDataTypeString(type);
			column.setMaxColumnNameLength(maxLen);

			table.putResource(column.getUName(), column);

			if (request != null) {
				request.subTask(name + "/" + type + "/" + comments);
				request.worked(1);
			}
		}
		return retCode;
	}

	public boolean connect(ConnectionProperties p) throws SQLException {
		boolean ret = false;
		try {
			ret = super.connect(p);
		} catch (ArrayIndexOutOfBoundsException e) {
			try {
				if (_con == null) {
					connectiong = true;
					fLogger.error(
							"Do you use 'ojdbc14.jar' ? try re-connect using DraverManager#getConnection",
							e);
					String url = _info.getProperty("url");
					String user = _info.getProperty("user");
					String password = _info.getProperty("password");
					class_manager = new ClassManager();
					try {
						class_manager.add_lib(classes12File);
						Class cls = class_manager.getClassForName(_driver
								.getClass().getName());
					} catch (Exception e1) {
						fLogger.trace(e);
					}

					_con = DriverManager.getConnection(url, user, password);
					_con.setAutoCommit(p.isAutoCommit());

					_extra_con = DriverManager.getConnection(url, user,
							password);

					for (int i = 0; i < fConnectionListenerList.size(); i++) {
						fConnectionListenerList.get(i).connected();
					}
				}
				return true;
			} finally {
				connectiong = false;
			}
		}
		try {
			String sqlst = null;
			if (StringUtil.isEmpty(clientInfo)) {
				sqlst = String.format(CLIENTINFOBEGIN, "Wolf Connetion");
			} else {
				sqlst = String.format(CLIENTINFOBEGIN, clientInfo
						+ " Connetion");
			}
			Statement stmt = _con.createStatement();
			stmt.execute(sqlst);
			stmt = _extra_con.createStatement();
			if (StringUtil.isEmpty(clientInfo)) {
				sqlst = String.format(CLIENTINFOBEGIN, "Wolf System Connetion");
			} else {
				sqlst = String.format(CLIENTINFOBEGIN, clientInfo
						+ " Sys Connetion");
			}
			stmt.execute(sqlst);
			if (p.isWritableDBMS_PutLine()) {
				dbms = new DBMSOutput(_con);
			}
		} catch (Exception e) {
			fLogger.trace(e);
		}
		return ret;
	}

	@Override
	public boolean close() throws SQLException {
		dbms = null;
		return super.close();
	}

	@Override
	protected boolean setTableText(GettingResourceRequest request)
			throws SQLException {
		boolean retCode = true;
		ResultSetDataHolder rdh = null;

		if (request.targetType.isOnlySelectedResouce()) {
			request.beginTask(String.format("SCHEMA[%s] GET_DDL ",
					request.selectionResource.getName()), 3);
			if (request.selectionResource instanceof IDBTable) {
				IDBTable tbl = (IDBTable) request.selectionResource;

				System.out.println("table??? =" + tbl.getTableType().name());
				if (!StringUtil.isEmpty(tbl.getCatalog())
						&& tbl.getTableType().isFunctionOrProcedure()) {
					// for package
					rdh = executePrepareQuery(_extra_con, SELECT_GET_DDL,
							new String[] { "PACKAGE", tbl.getUCatalog(),
									tbl.getParent().getUName() });
					if (rdh.getRowCount() > 0) {
						StringBuilder buf = new StringBuilder();
						buf.append(rdh.getStringData(0, "TEXT"));
						// todo: body...
						tbl.setText(buf.toString());
					} else {
						retCode = false;
					}
				} else {
					rdh = executePrepareQuery(
							_extra_con,
							SELECT_GET_DDL,
							new String[] { tbl.getTableType().name(),
									tbl.getUName(), tbl.getParent().getUName() });
					if (rdh.getRowCount() > 0) {
						tbl.setText(rdh.getStringData(0, "TEXT"));
					} else {
						retCode = false;
					}
				}
			}
			return retCode;
		}
		IDBSchema[] schemas = getRoot().getSchemas();

		for (int i = 0; i < schemas.length; i++) {
			IDBTable[] prs = schemas[i].getTableOrSystemTables();
			request.beginTask(
					String.format("SCHEMA[%s] GET_DDL TABLES ",
							schemas[i].getName()), prs.length);
			for (int j = 0; j < prs.length; j++) {
				request.subTask(String.format("TABLE[%s]", prs[j].getName()));
				rdh = executePrepareQuery(
						_extra_con,
						SELECT_GET_DDL,
						new String[] { "TABLE", prs[j].getUName(),
								schemas[i].getUName() });
				if (rdh.getRowCount() > 0) {
					prs[j].setText(rdh.getStringData(0, "TEXT"));
				}
				request.worked(1);
			}
			prs = schemas[i].getProcedures();
			request.beginTask(
					String.format("SCHEMA[%s] GET_DDL PROCEDURES ",
							schemas[i].getName()), prs.length);
			for (int j = 0; j < prs.length; j++) {
				request.subTask(String.format("PROCEDURE[%s]", prs[j].getName()));
				rdh = executePrepareQuery(_extra_con, SELECT_GET_DDL,
						new String[] { "PROCEDURE", prs[j].getUName(),
								schemas[i].getUName() });
				if (rdh.getRowCount() > 0) {
					prs[j].setText(rdh.getStringData(0, "TEXT"));
				}
				request.worked(1);
			}
			prs = schemas[i].getFunctions();
			request.beginTask(
					String.format("SCHEMA[%s] GET_DDL FUNCTIONS ",
							schemas[i].getName()), prs.length);
			for (int j = 0; j < prs.length; j++) {
				request.subTask(String.format("FUNCTION[%s]", prs[j].getName()));
				rdh = executePrepareQuery(_extra_con, SELECT_GET_DDL,
						new String[] { "FUNCTION", prs[j].getUName(),
								schemas[i].getUName() });
				if (rdh.getRowCount() > 0) {
					prs[j].setText(rdh.getStringData(0, "TEXT"));
				}
				request.worked(1);
			}
			IDBTable[] tbl = schemas[i].getTableOrViews();
			request.beginTask(
					String.format("SCHEMA[%s] GET_DDL VIEWS ",
							schemas[i].getName()), tbl.length);
			for (int j = 0; j < tbl.length; j++) {
				if (tbl[j].isView()) {
					request.subTask(String.format("VIEW[%s]", tbl[j].getName()));
					rdh = executePrepareQuery(_extra_con, SELECT_GET_DDL,
							new String[] { "VIEW", tbl[j].getUName(),
									schemas[i].getUName() });
					if (rdh.getRowCount() > 0) {
						tbl[j].setText(rdh.getStringData(0, "TEXT"));
					}
				}
				request.worked(1);
			}
			IDBTrigger[] trg = schemas[i].getTriggers();
			request.beginTask(
					String.format("SCHEMA[%s] GET_DDL TRIGGERS ",
							schemas[i].getName()), trg.length);
			for (int j = 0; j < trg.length; j++) {
				request.subTask(String.format("TRIGGER[%s]", trg[j].getName()));
				rdh = executePrepareQuery(
						_extra_con,
						SELECT_GET_DDL,
						new String[] { "TRIGGER", trg[j].getUName(),
								schemas[i].getUName() });
				if (rdh.getRowCount() > 0) {
					trg[j].setText(rdh.getStringData(0, "TEXT"));
				}
				request.worked(1);
			}
		}
		return retCode;
	}

	// --
	private void setTableComments(IDBSchema schema) throws SQLException {
		PreparedStatement pre = null;
		ResultSet rsC = null;

		try {
			pre = _extra_con.prepareStatement(_SELECT_TAB_COMMENTS,
					ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
			pre.setString(1, schema.getName());
			rsC = pre.executeQuery();

			for (int i = 0; rsC.next(); i++) {
				String name = rsC.getString("TABLE_NAME");

				IDBResource res = schema.getTableResource(name);
				if (res != null) {
					res.setComment(rsC.getString("COMMENTS"));
				}
			}
		} finally {
			if (rsC != null) {
				rsC.close();
			}
			if (pre != null) {
				pre.close();
			}
		}
	}

	@Override
	protected void getTrigger(GettingResourceRequest request)
			throws SQLException {
		ResultSetDataHolder rdh = null;

		boolean withTrigger = request.getConnectionProperties()
				.isCaptureWithTriggerInfo();
		if (!withTrigger) {
			return;
		}
		IDBSchema[] schemas = getRoot().getSchemas();
		for (int i = 0; i < schemas.length; i++) {
			if (schemas[i].getName().length() == 0) {
				continue;
			}
			if (request.targetType.isOnlySchema()
					&& !schemas[i].equals(request.selectionResource)) {
				continue;
			}
			rdh = executePrepareQuery(_extra_con, _SELECT_TRIGGER,
					new String[] { schemas[i].getName() });
			DBTrigger trigger = null;
			for (int j = 0; j < rdh.getRowCount(); j++) {
				trigger = new DBTrigger(schemas[i]);
				trigger.setName(rdh.getStringData(j, "TRIGGER_NAME"));
				setResourceProperties(trigger, j, rdh);
				schemas[i].putTrigger(trigger);
				// setViewText(trigger);
			}
			if (request.canceld()) {
				return;
			}
		}
	}

	@Override
	protected void getSequence(GettingResourceRequest request)
			throws SQLException {
		ResultSetDataHolder rdh = null;

		IDBSchema[] schemas = getRoot().getSchemas();

		for (int i = 0; i < schemas.length; i++) {
			if (schemas[i].getName().length() == 0) {
				continue;
			}
			if (request.targetType.isOnlySchema()
					&& !schemas[i].equals(request.selectionResource)) {
				continue;
			}

			rdh = executePrepareQuery(_extra_con, _SELECT_SEQUENCES,
					new String[] { schemas[i].getName() });
			DBSequence sequence = null;
			for (int j = 0; j < rdh.getRowCount(); j++) {
				sequence = new DBSequence(schemas[i]);
				sequence.setName(rdh.getStringData(j, "NAME"));
				setResourceProperties(sequence, j, rdh);
				schemas[i].putSequence(sequence);
				// setViewText(trigger);
			}
			if (request.canceld()) {
				return;
			}
		}
	}

	// protected void setIndexes(ResourceCaptionRequest request)
	// throws SQLException {
	// ResultSet rsC = null;
	// int row = DEFAULT_ROW_NUM;
	// try {
	// PreparedStatement pre = _con
	// .prepareStatement(SELECT_INDEX_INFO,
	// ResultSet.TYPE_SCROLL_SENSITIVE,
	// ResultSet.CONCUR_READ_ONLY);
	// rsC = pre.executeQuery();
	// try {
	// rsC.afterLast();
	// row = rsC.getRow();
	// rsC.beforeFirst();
	// } catch (SQLException e) {
	// }
	//
	// IDBSchema ischema = null;
	// IDBTable itable = null;
	// DBIndex index = null;
	// for (int i = 0; rsC.next(); i++) {
	// String str_schema = rsC.getString("TABLE_OWNER");
	// String str_table = rsC.getString("TABLE_NAME");
	// String str_column = rsC.getString("COLUMN_NAME");
	// String str_index_name = rsC.getString("INDEX_NAME");
	// if (ischema == null
	// || !ischema.getName().equalsIgnoreCase(str_schema)) {
	// ischema = (IDBSchema) _root.getResource(str_schema);
	// }
	// if (itable == null
	// || !itable.getName().equalsIgnoreCase(str_table)) {
	// itable = ischema.getTable(str_table.toUpperCase());
	// index = new DBIndex(_root.getDBIndexRoot());
	// index.setTable(itable);
	// index.setName(str_index_name);
	// if (itable == null) {
	// fLogger.info("Bad Elements... table" + str_table);
	// continue;
	// }
	// }
	// if (!index.getName().equals(str_index_name)) {
	// index = new DBIndex(_root.getDBIndexRoot());
	// index.setTable(itable);
	// index.setName(str_index_name);
	// }
	// index.addColumn((IDBColumn) itable.getResource(str_column));
	// request.subTask(index.toString());
	// request.worked(1);
	// itable.addIndex(index);
	// _root.getDBIndexRoot().putIndex(index);
	// }
	// } finally {
	// if (rsC != null) {
	// rsC.close();
	// }
	// }
	// }

	// --------------------------------------------------------------------------
	// --
	protected void createDictionary() throws SQLException {
		ResultSetDataHolder rdh = null;

		rdh = executePrepareQuery(SELECT_DICTIONARY, null);
		DBTable table = null;
		DBRoot root = getRoot();
		for (int i = 0; i < rdh.getRowCount(); i++) {
			String tn = rdh.getStringData(i, "TN").toUpperCase();
			if (table == null || !table.getName().equals(tn)) {
				table = new DBTable(root.getDBDictionaryRoot());
				table.setName(tn);
				table.setComment(rdh.getStringData(i, "TC").toUpperCase());
				root.getDBDictionaryRoot().putDictionary(table);
			}
			;
			IDBColumn column = new DBColumn(table);
			column.setName(rdh.getStringData(i, "CN").toUpperCase());
			column.setComment(rdh.getStringData(i, "CC").toUpperCase());
			table.putResource(column.getName(), column);
		}

	}

	private HashMap<String, ResultSetDataHolder> pkMap;

	protected List<String> getTablePrimaryKeys(String schema, String table)
			throws SQLException {
		ResultSetDataHolder rdh = pkMap.get(schema);
		if (rdh == null) {
			rdh = executePrepareQuery(SELECT_PK, new String[] { schema });
			pkMap.put(schema, rdh);
		}
		ArrayList<String> items = new ArrayList<String>();

		for (int i = 0; i < rdh.getRowCount(); i++) {
			if (rdh.getStringData(i, "TABLE_NAME").equalsIgnoreCase(table)) {
				items.add(rdh.getStringData(i, "COLUMN_NAME"));
			}
		}

		return items;
	}

	protected void setValidation(GettingResourceRequest request)
			throws SQLException {
		fLogger.info("start");
		int row = DEFAULT_ROW_NUM;
		try {
			row = count(_extra_con, _SELECT_VALIDATION, new String[0]);
		} catch (SQLException e) {
			fLogger.warn("COUNT ERROR", e);
		}
		DBRoot root = getRoot();
		request.beginTask("VALIDATION CHECK (ORACLE NATIVE) ", row);

		ResultSetDataHolder rdh = executePrepareQuery(_extra_con,
				_SELECT_VALIDATION, new String[0]);

		for (int i = 0; i < rdh.getRowCount(); i++) {
			String name = rdh.getStringData(i, "OBJECT_NAME");
			String type = rdh.getStringData(i, "OBJECT_TYPE");
			String status = rdh.getStringData(i, "STATUS");
			IDBResource irs = null;
			if ("PROCEDURE".equals(type)) {
				irs = root.getCurrentSchema().getProcedure(name);
			} else if ("SYNONYM".equals(type)) {
				irs = root.getCurrentSchema().getTableResource(name);
			} else if ("FUNCTION".equals(type)) {
				irs = root.getCurrentSchema().getProcedure(name);
			} else if ("TABLE".equals(type)) {
				irs = root.getCurrentSchema().getTableResource(name);
			} else if ("TRIGGER".equals(type)) {
				irs = root.getCurrentSchema().getTrigger(name);
			} else if ("INDEX".equals(type)) {
			}
			if (irs != null) {
				irs.setValid("VALID".equals(status));
			}
			request.subTask(type + ":" + name + "[" + status + "]");
			request.worked(1);

		}
		fLogger.info("end");
	}

	protected void setComments(GettingResourceRequest request)
			throws SQLException {
		DBRoot root = getRoot();
		request.beginTask("ALL_COL_COMMENTS ORACLE NATIVE ",
				3 * root.getSchemas().length);
		boolean withColumn = request.getConnectionProperties()
				.isCaptureWithColumnInfo() || request.targetType.isOnlyTable();

		IDBSchema[] schemas = null;
		if (request.targetType.isOnlySchema()) {
			schemas = new IDBSchema[] { (IDBSchema) request.selectionResource };
		} else {
			schemas = root.getSchemas();
		}
		for (IDBSchema mschema : schemas) {
			setTableComments(mschema);
			request.worked(1);

			if (request.canceld()) {
				return;
			}
			if (!withColumn) {
				continue;
			}
			String[] params = new String[] { mschema.getName() };
			ResultSetDataHolder rdh = executePrepareQuery(_extra_con,
					_SELECT_TAB_COL_COMMENTS_SCHEMA, params);

			IDBColumn icolumn = null;
			for (int i = 0; i < rdh.getRowCount(); i++) {
				String str_table = rdh.getStringData(i, "TABLE_NAME");
				String str_column = rdh.getStringData(i, "COLUMN_NAME");
				String str_column_com = rdh.getStringData(i, "COMMENTS");

				IDBTable t = mschema.getTableResource(str_table);
				if (t != null) {
					icolumn = (IDBColumn) t.getResource(str_column
							.toUpperCase());
					if (icolumn != null) {
						icolumn.setComment(str_column_com);
						request.subTask(str_table + "." + str_column + "["
								+ str_column_com + "]");
					}
				}
			}
			if (request.canceld()) {
				return;
			}

			request.worked(1);

			for (IDBTable synonym : mschema.getSynonyms()) {
				ResultSetDataHolder rdh2 = executePrepareQuery(_extra_con,
						_SELECT_SYNOYMS, new String[] { mschema.getName(),
								synonym.getName() });
				if (rdh2.getRowCount() > 0) {
					String scm = rdh2.getStringData(0, "TABLE_OWNER");

					if (mschema.getName().equals(scm)) {
						synonym.setComment(rdh2.getStringData(0, "TABLE_NAME"));
					} else {
						synonym.setComment(scm + "."
								+ rdh2.getStringData(0, "TABLE_NAME"));
					}
				}
				setTableColumns(mschema.getName(), synonym);
				if (request.canceld()) {
					return;
				}
			}
		}
		request.worked(1);

	}

	public boolean doOperation(SQLOperationType operation, Request request)
			throws SQLException {
		TransactionRequest treq = null;
		if (request instanceof TransactionRequest) {
			treq = (TransactionRequest) request;
		}
		boolean retCode = true;
		switch (operation) {
		case EXPLAIN_PLAN:
			treq.setRDH(explainPlan(((TransactionRequest) request)
					.getSQLStatement()));
			break;
		case SELECT_SESSION:
			request.setRDH(getSessionInfo());
			break;
		case SELECT_LOCK:
			request.setRDH(getLockInfo());
			break;
		case CREATE_TRIG_FNC_PROC:
			treq.setRDH(createTrigFncProc((TransactionRequest) request));
			break;
		case WORST_SQL:
			request.setRDH(getWORST());
			break;
		case CHECK_VALIDATION:
			setValidation((GettingResourceRequest) request);
			break;
		case PREPARED_EXECUTE:
			treq.setRDH(executeOraPrepare(treq.getSQLStatement(),
					treq.getBindObjects(), treq.getIDBTable()));
			break;
		default:
			retCode = super.doOperation(operation, request);
			break;
		}

		getDBMSLines();

		return retCode;
	}

	private ResultSetDataHolder2 executeOraPrepare(String sql_statement,
			Object[] args, IDBTable idbTable) throws SQLException {
		if (_con == null) {
			return null;
		}
		if (idbTable != null) {
			BindInfo[] binds = new BindInfo[args.length];
			for (int i = 0; i < binds.length; i++) {
				binds[i] = (BindInfo) args[i];
			}
			OracleBlobInfo info = new OracleBlobInfo(idbTable, sql_statement,
					binds);
			if (fLogger.isInfoEnabled()) {
				fLogger.info("isMarkSpecialBlobExecution["
						+ info.isMarkSpecialBlobExecution() + "]");
			}
			if (info.isMarkSpecialBlobExecution()) {
				CallableStatement statement = _con.prepareCall(info
						.getChangedSql());
				ResultSetDataHolder2 rdh = createRdh2(
						new String[] { "UpdateCount" }, null);
				if (fLogger.isInfoEnabled()) {
					fLogger.info("changedSQL=" + info.getChangedSql());
				}
				try {
					int bi = 1;
					for (int i = 0; i < args.length; i++) {
						if (args[i] instanceof BindInfo) {
							BindInfo bind = (BindInfo) args[i];
							if (bind.isBlob()) {
								if (StringUtil.isEmpty(bind.getStringValue())) {
									statement.setNull(bi++, Types.BLOB);
								}
							} else if (bind.isBinary()) {
								if (bind.getValue() == null
										|| bind.getStringValue().length() == 0) {
									statement.setNull(bi++, 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(bi++, bytes);
								}
							} else if (bind.isTimeStamp()) {
								if (bind.getValue() == null
										|| bind.getStringValue().length() == 0) {
									statement.setNull(bi++, Types.TIMESTAMP);
								} else {
									statement.setTimestamp(bi++,
											SQLUtil.getTimeStamp(bind
													.getStringValue()));
								}
							} else if (bind.isDate()) {
								if (bind.getValue() == null
										|| bind.getStringValue().length() == 0) {
									statement.setNull(bi++, Types.DATE);
								} else {
									statement.setDate(bi++, SQLUtil
											.getDate(bind.getStringValue()));
								}
							} else if (bind.isTime()) {
								if (bind.getValue() == null
										|| bind.getStringValue().length() == 0) {
									statement.setNull(bi++, Types.TIME);
								} else {
									statement.setTime(bi++, SQLUtil
											.getTime(bind.getStringValue()));
								}
							} else {
								statement
										.setString(bi++, bind.getStringValue());
							}

						} else {
							statement.setString(bi++, (String) args[i]);
						}
					}
					notifyExecute(_con, SQLExecutionStatus.BEFORE_EXECUTE);
					long time = System.currentTimeMillis();
					BindInfo[] blobedInfos = info.getBlobedInfos();

					System.out.println("bi=[" + bi + "]");
					System.out.println("registerOutParameter.length["
							+ blobedInfos.length + "]");
					for (int q = 0; q < blobedInfos.length; q++) {
						System.out.println("registerOutParameter[" + (bi + q)
								+ "]");
						statement.registerOutParameter(bi + q, 2004);
					}

					int rs = statement.executeUpdate();
					if (rs > 0) {
						Class blobClazz = _con.getClass().getClassLoader()
								.loadClass("oracle.sql.BLOB");
						Class callClazz = _con
								.getClass()
								.getClassLoader()
								.loadClass(
										"oracle.jdbc.driver.OracleCallableStatement");
						if (fLogger.isInfoEnabled()) {
							fLogger.info("load oracle.sql.BLOB success["
									+ blobClazz + "]");
							fLogger.info("load oracle.jdbc.driver.OracleCallableStatement success["
									+ callClazz + "]");
						}

						Method getBlobMethod = callClazz.getMethod("getBLOB",
								int.class);

						Method getBufferSizeMethod = blobClazz.getMethod(
								"getBufferSize", new Class[0]);
						Method method = blobClazz.getMethod(
								"getBinaryOutputStream", new Class[0]);

						int size = 100;
						for (int q = 0; q < blobedInfos.length; q++) {
							Object o = getBlobMethod.invoke(statement,
									new Object[] { bi + q });
							try {
								size = (Integer) getBufferSizeMethod.invoke(o);
							} catch (Exception e) {
							}
							if (size < 5) {
								size = 5;
							}

							OutputStream outStream = (OutputStream) method
									.invoke(o);

							byte[] buffer = new byte[size];

							File f = (File) blobedInfos[q].getValue();
							FileInputStream inStream = new FileInputStream(f);

							int length = -1;
							while ((length = inStream.read(buffer)) != -1) {
								outStream.write(buffer, 0, length);
							}

							inStream.close();
							outStream.close();
						}
					} else {
						System.err.println("karaaaaaaaaaaaa.");
					}

					time = System.currentTimeMillis() - time;
					notifyExecute(_con, SQLExecutionStatus.AFTER_EXECUTE,
							String.valueOf(rs), String.valueOf(time));

					rdh.addRow(new String[] { String.valueOf(rs) });
					rdh.setWrapTime(time);
					setTransactionTime(true);
					return rdh;
				} catch (Throwable e) {
					fLogger.warn(e);
					if (e instanceof SQLException) {
						notifyExecute(_con, SQLExecutionStatus.EXCEPTION,
								e.getMessage());
						throw (SQLException) e;
					}
					return rdh;
				} finally {
					if (statement != null) {
						statement.close();
					}
				}
			} else {
				return super.executePrepare(_con, sql_statement, args);
			}
		} else {
			return super.executePrepare(_con, sql_statement, args);
		}
	}

	public synchronized String getDBMSLines() {
		if (!_info.isWritableDBMS_PutLine()) {
			return StringUtil.EMPTY_STRING;
		}
		StringBuffer buf = new StringBuffer(StringUtil.LINE_SEPARATOR);
		if (dbms != null) {
			String[] resultStrings = dbms.getLines();
			if (resultStrings.length > 0) {
				for (int i = 0; i < resultStrings.length; i++) {
					buf.append(resultStrings[i]).append(
							StringUtil.LINE_SEPARATOR);
				}
				buf.setLength(buf.length() - StringUtil.LINE_SEPARATOR.length());
				fLogger.error(buf.toString());
			}
		}
		return buf.toString();
	}

	private ResultSetDataHolder2 createTrigFncProc(TransactionRequest request)
			throws SQLException {
		PreparedStatement statement = null;
		int rs = 0;
		if (_con == null) {
			return null;
		}
		try {

			fLogger.trace(request.getSQLStatement());

			long time = System.currentTimeMillis();

			Statement st = null;
			boolean ret = false;

			try {
				st = getStatement(_con, ResultSet.TYPE_FORWARD_ONLY,
						ResultSet.CONCUR_READ_ONLY);
				String sql_statement = request.getSQLStatement().replaceAll(
						"[\r　\t]+", " ");

				fLogger.info("=== REPLASED SQL_STATEMENT START");
				fLogger.info(sql_statement);
				fLogger.info("=== REPLASED SQL_STATEMENT END");

				notifyExecute(_con, SQLExecutionStatus.BEFORE_EXECUTE);
				ret = st.execute(sql_statement);
			} finally {
				if (st != null) {
					st.close();
				}
			}

			time = System.currentTimeMillis() - time;
			notifyExecute(_con, SQLExecutionStatus.AFTER_EXECUTE,
					Boolean.toString(ret), String.valueOf(time));
			ResultSetDataHolder2 rdh = executePrepareQuery(
					"SELECT * FROM USER_ERRORS", new String[0]);
			if (rdh.getRowCount() == 0) {
				rdh = new ResultSetDataHolder2(RESULT_MESSAGE, null,
						getDatabaseType());
				rdh.addRow(new String[] { "SUCCESS" });
			}
			rdh.setWrapTime(time);

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

	/**
	 * @param operationCode
	 * @return
	 */
	public boolean canDoOperation(SQLOperationType operation) {
		switch (operation) {
		case TRUNCATE:
			if (_info == null || !_info.isConnected()) {
				return false;
			}
			return true;
		case SELECT_SESSION:
			if (_info == null) {
				return false;
			}
			return canDoGetSessionInfo();
		case SELECT_LOCK:
			if (_info == null) {
				return false;
			}
			return canDoGetSessionInfo();

		case WORST_SQL:
			if (_info == null) {
				return false;
			}
			return true;
		default:
			return super.canDoOperation(operation);
		}
	}

	// --
	public boolean canDoGetSessionInfo() {
		if (sessionChecked) {
			return canDoGetSession;
		}
		canDoGetSession = false;
		try {
			ResultSetDataHolder rdh = executePrepareQuery(_extra_con,
					SELECT_SESSION_INFO, new String[] {});
			if (rdh.getRowCount() > 0) {
				canDoGetSession = true;
			}
		} catch (SQLException e) {
		}
		sessionChecked = true;

		return canDoGetSession;
	}

	// --
	public ResultSetDataHolder2 getSessionInfo() throws SQLException {
		ResultSetDataHolder2 rdh = executePrepareQuery(_extra_con,
				SELECT_SESSION_INFO, new String[] {});
		return rdh;
	}

	public ResultSetDataHolder2 getLockInfo() throws SQLException {
		return executePrepareQuery(_extra_con, SELECT_LOCK_INFO,
				new String[] {});
	}

	public ResultSetDataHolder2 getWORST() throws SQLException {
		return executePrepareQuery(_extra_con, _SELECT_WORST, new String[] {});
	}

	@Override
	public ResultSetDataHolder2 explainPlan(String sql_statement)
			throws SQLException {
		Statement statement = null;
		ResultSetDataHolder2 sdh = null;
		try {
			String id = STATEMENT_ID + System.currentTimeMillis();
			statement = _extra_con.createStatement();
			boolean rs = execute(_extra_con, SET_EXPLAIN_PLAN_HEAD + id
					+ SET_EXPLAIN_PLAN_TAIL + sql_statement, null);

			sdh = executePrepareQuery(_extra_con, SELECT_EXPLAIN_PLAN,
					new String[] { id, id });
			execute(_extra_con, DELETE_EXPLAIN_PLAN, new String[] { id });
			return sdh;
		} finally {
			if (statement != null) {
				statement.close();
			}
		}
	}

	/**
	 * @return
	 */
	public ResultSetDataHolder getVSQL(int minute, int[] types)
			throws SQLException {
		StringBuffer buf = new StringBuffer(SELECT_V_SQLAREA);
		buf.append(minute / 1440.0).append(",'YYYY-MM-DD/HH24:MI:SS') ");
		if (types.length > 0) {
			buf.append(" AND COMMAND_TYPE IN (");
			for (int i = 0; i < types.length; i++) {
				buf.append(types[i]).append(",");
			}
			buf.setLength(buf.length() - 1);
			buf.append(")");
		}
		buf.append("ORDER BY FIRST_LOAD_TIME DESC");
		return executePrepareQuery(_extra_con, buf.toString(), (String[]) null);
	}

	public static String getSuggestURL() {
		return "jdbc:oracle:thin:@127.0.0.1:1521:SID";
	}

	public static String getLimitString() {
		return "WHERE ROWNUM < 30";
	}

	@Override
	public boolean migration(ITransactionSQL osql, DBCrossRefference cross,
			boolean drop, boolean cascade) throws SQLException {
		fLogger.info("migration DBCrossRefference " + cross);

		// IDBColumn[] columns = cross.pkList.toArray(new IDBColumn[0]);
		// String tn = columns[0].getParent().getName();
		// String sn = columns[0].getParent().getParent().getName();
		// ResultSetDataHolder rdh = executePrepareQuery(_SELECT_INDEX_CNT, new
		// String[] { sn, cross.getName() });
		// if (rdh.getIntData(0, "CNT") == 0) {
		// StringBuilder buf = new StringBuilder();
		// buf.append("ALTER TABLE ");
		// buf.append(sn).append(".").append(tn).append(StringUtil.LINE_SEPARATOR);
		// buf.append("  add constraint ").append(cross.getName()).append(Util.
		// LINE_SEPARATOR);
		// buf.append("  foreign key(");
		//
		// executePrepare(buf.toString(), EMPTY);
		// }
		//
		// commit();

		return true;
	}

	@Override
	public boolean migration(ITransactionSQL osql, IDBSequence sequence,
			boolean drop, boolean cascade, boolean noSchema)
			throws SQLException {
		fLogger.info("migration DBSequence " + sequence);
		ResultSetDataHolder rdh = null;
		String sn = sequence.getParent().getName();
		if (noSchema) {
			sn = StringUtil.EMPTY_STRING;
			rdh = executePrepareQuery(_con, _SELECT_USER_SEQUENCE_CNT,
					new String[] { sequence.getName() });
		} else {
			rdh = executePrepareQuery(_con, _SELECT_SEQUENCE_CNT, new String[] {
					sn, sequence.getName() });
		}
		boolean existsSequence = rdh.getIntDataDefaultZero(0, "CNT") > 0;
		if (existsSequence && drop) {
			if (noSchema) {
				String st = String.format("DROP SEQUENCE %s",
						sequence.getName());
				executePrepare(st, EMPTY);
			} else {
				String st = String.format("DROP SEQUENCE %s.%s", sn,
						sequence.getName());
				executePrepare(st, EMPTY);
			}
		}
		if (!existsSequence || drop) {
			if (!createSequenceBody(sn, sequence)) {
				return false;
			}
		}
		commit();

		return true;
	}

	private boolean createSequenceBody(String schemaName, IDBSequence sequence)
			throws SQLException {
		StringBuilder buf = new StringBuilder();
		buf.append("CREATE SEQUENCE ");
		if (schemaName.length() > 0) {
			buf.append(schemaName).append(".");
		}
		buf.append(sequence.getName()).append(" ")
				.append(StringUtil.LINE_SEPARATOR);
		buf.append("  INCREMENT BY ").append("1")
				.append(StringUtil.LINE_SEPARATOR);
		buf.append("  MINVALUE ").append("1").append(StringUtil.LINE_SEPARATOR);
		buf.append("  MAXVALUE ").append("10000")
				.append(StringUtil.LINE_SEPARATOR);
		buf.append("  START WITH ").append("200")
				.append(StringUtil.LINE_SEPARATOR);
		buf.append("  CACHE ").append("10").append(StringUtil.LINE_SEPARATOR);
		// CYCLE;
		executePrepare(buf.toString(), EMPTY);

		return true;
	}

	@Override
	protected boolean createSchema(String schemaName, Properties properties)
			throws SQLException {
		String st = String
				.format("CREATE USER %s identified by %s DEFAULT TABLESPACE USERS QUOTA UNLIMITED ON USERS",
						schemaName, "password");
		executePrepare(st, EMPTY);
		return true;
	}

	@Override
	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 CONSTRAINTS");
		}
		executePrepare(st.toString(), EMPTY);
		return true;
	}

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

	// @Override
	// public boolean mirroring(ITransactionSQL osql, IDBTable table,
	// MirroringRequest mirroring_request) throws SQLException {
	// fLogger.info("migration DBTable " + table);
	// ResultSetDataHolder rdh = null;
	// String sn = table.getParent().getName();
	// String tableName = sn + "." + table.getName();
	// if (noSchema) {
	// sn = StringUtil.EMPTY_STRING;
	// tableName = table.getName();
	// }
	// if (table.isTable()) {
	// if (noSchema) {
	// rdh = executePrepareQuery(_SELECT_USER_TABLE_CNT,
	// new String[] { table.getName() });
	// } else {
	// rdh = executePrepareQuery(_SELECT_TABLE_CNT, new String[] { sn,
	// tableName });
	// }
	// } else {
	// if (noSchema) {
	// rdh = executePrepareQuery(_SELECT_USER_VIEW_CNT,
	// new String[] { table.getName() });
	// } else {
	// rdh = executePrepareQuery(_SELECT_VIEW_CNT, new String[] { sn,
	// table.getName() });
	// }
	// }
	// boolean existsTable = rdh.getIntData(0, "CNT") > 0;
	// if (existsTable && drop) {
	// String st = null;
	// if (table.isTable()) {
	// st = String.format("DROP TABLE %s", tableName);
	// if (cascade) {
	// st += " CASCADE";
	// }
	// } else {
	// st = String.format("DROP VIEW %s", tableName);
	// }
	// executePrepare(st, EMPTY);
	// }
	// if (!existsTable || drop) {
	// if (createTableBody(sn, table)) {
	// createTableComment(sn, table);
	// } else {
	// return false;
	// }
	// }
	// if (!migrateTableValue(osql, table, noSchema)) {
	// return false;
	// }
	// commit();
	//
	// return true;
	// }

	// private boolean migrateTableValue(ITransactionSQL osql, IDBTable table,
	// boolean noSchema) {
	// StringBuilder buf = new StringBuilder();
	// PreparedStatement st = null;
	// ResultSet rs = null;
	// fLogger.info("" + table);
	// try {
	// buf.append("SELECT * FROM ");
	// buf.append(table.getParent().getName()).append(".");
	// buf.append(table.getName());
	// AbsTransactionSQL asql = (AbsTransactionSQL) osql;
	//
	// st = asql.getPrepareStatement(asql._con, buf.toString());
	// rs = st.executeQuery();
	//
	// doInsertFromRs(rs, table.getColumns(), noSchema);
	// } catch (SQLException e) {
	// fLogger.warn(e);
	// return false;
	// } finally {
	// try {
	// if (rs != null) {
	// rs.close();
	// }
	// if (st != null) {
	// st.close();
	// }
	// } catch (SQLException e) {
	// fLogger.warn(e);
	// return false;
	// }
	// }
	// return true;
	//
	// }

	public static void main(String[] args) {
		String moto = "CREATE OR REPLACE FORCE VIEW \"HR\".\"EMP_DETAILS_VIEW\" (\"EMPLOYEE_ID\", \"JOB";
		String vt = moto.replaceFirst(
				"([\"a-zA-Z_]+[.])?\"?([a-zA-Z_]+)\"? *[(]", "$2 (");
		System.out.println(vt);
	}

	// private boolean createTableBody(String schemaName, IDBTable table)
	// throws SQLException {
	// StringBuilder buf = new StringBuilder();
	// if (table.isTable()) {
	// buf.append("CREATE TABLE ");
	// if (schemaName.length() > 0) {
	// buf.append(schemaName).append(".");
	// }
	// buf.append(table.getName());
	// buf.append(" ( ").append(StringUtil.LINE_SEPARATOR);
	// IDBColumn[] columns = table.getColumns();
	// for (int j = 0; j < columns.length; j++) {
	// StringBuilder buf2 = new StringBuilder();
	// buf2.append("  ").append(getTypeString(columns[j]));
	// buf2.append(",").append(StringUtil.LINE_SEPARATOR);
	// buf.append(buf2);
	// }
	// if (columns.length > 0) {
	// buf.setLength(buf.length() - 1
	// - StringUtil.LINE_SEPARATOR.length());
	// }
	// buf.append(StringUtil.LINE_SEPARATOR);
	// if (table.hasPk()) {
	// buf.append("  ,PRIMARY KEY (");
	// int[] pk = table.getPkPositions();
	// for (int j = 0; j < pk.length; j++) {
	// if (j > 0) {
	// buf.append(",");
	// }
	// buf.append(table.getColumns()[pk[j]].getName());
	// }
	// buf.append(")").append(StringUtil.LINE_SEPARATOR);
	// }
	// buf.append(")");
	// } else {
	// if (StringUtil.nvl(table.getText()).length() == 0) {
	// return true;
	// }
	// String vt = table.getText().replaceFirst(
	// "([\"a-zA-Z_]+[.])?\"?([a-zA-Z_]+)\"? *[(]", "$2 (");
	// buf.append(vt);
	// buf.append(StringUtil.LINE_SEPARATOR);
	// }
	//
	// executePrepare(buf.toString(), EMPTY);
	// return true;
	// }

	private boolean createTableComment(String schemaName, IDBTable table)
			throws SQLException {
		StringBuilder buf = new StringBuilder();
		if (table.getComment().length() > 0) {
			buf = new StringBuilder();
			buf.append("COMMENT ON ");
			if (table.isTable()) {
				buf.append("TABLE ");
			} else {
				buf.append("VIEW ");
			}
			if (schemaName.length() > 0) {
				buf.append(schemaName).append(".");
			}
			buf.append(table.getName());
			buf.append(" IS '").append(table.getComment()).append("'");
			executePrepare(buf.toString(), EMPTY);
		}
		IDBColumn[] columns = table.getColumns();
		for (int j = 0; j < columns.length; j++) {
			if (columns[j].getComment().length() > 0) {
				buf = new StringBuilder();
				buf.append("COMMENT ON COLUMN ");
				if (schemaName.length() > 0) {
					buf.append(schemaName).append(".");
				}
				buf.append(table.getName()).append(".");
				buf.append(columns[j].getName()).append(" IS '");
				buf.append(columns[j].getComment()).append("'");
				executePrepare(buf.toString(), EMPTY);
			}
		}
		return true;
	}

	@Override
	public boolean existsTable(String schemaName, String tableName)
			throws SQLException {
		String sql = null;
		ResultSetDataHolder rdh = executePrepareQuery(
				_SELECT_TABLE_CNT,
				new String[] { schemaName.toUpperCase(),
						tableName.toUpperCase() });
		return rdh.getIntDataDefaultZero(0, "CNT") > 0;
	}

	// -----------------------------------------------------------------------------------
	// For
	// -----------------------------------------------------------------------------------
	@Override
	protected boolean isSkipSchemaAtGetAllMetaData(String schemaName) {
		for (String name : SKIP_SCHEMA_NAMES_AT_GET_ALL_META_DATA) {
			if (name.equals(schemaName)) {
				return true;
			}
		}
		return false;
	}
}