package hiro.yoshioka.sql;

import hiro.yoshioka.ast.sql.oracle.WolfSQLParserConstants;
import hiro.yoshioka.ast.sql.util.ParserUtil;
import hiro.yoshioka.sdh.DatabaseType;
import hiro.yoshioka.sdh.ResultSetDataHolder;
import hiro.yoshioka.sdh2.ReflectionPreparedStatement;
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.params.ConnectionProperties;
import hiro.yoshioka.sql.resource.DBColumn;
import hiro.yoshioka.sql.resource.DBCrossRefference;
import hiro.yoshioka.sql.resource.DBResourceType;
import hiro.yoshioka.sql.resource.DBRoot;
import hiro.yoshioka.sql.resource.DBSequence;
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.util.SQLDataType;
import hiro.yoshioka.util.SQLUtil;
import hiro.yoshioka.util.StringUtil;

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.Savepoint;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class PostgresSQL extends AbsTransactionSQL implements IPostgresDBConst,
		IDoExplainPlan {
	static final String DEFAULT_SCHEMA_NAME = "public";
	Savepoint fSavePoint;

	public static String getSuggestURL() {
		return JDBC_URL_EXAMPLE;
	}

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

	@Override
	public boolean connect(ConnectionProperties properties) throws SQLException {
		boolean ret = super.connect(properties);
		if (_extra_con != null) {
			execute(_extra_con, "SET statement_timeout TO 3500",
					StringUtil.EMPTY_STRING_ARRAY);
		}
		return ret;
	}

	@Override
	public boolean close() throws SQLException {
		boolean status = true;
		try {
			if (_con != null) {
				if (!_con.isClosed() && !_info.isAutoCommit()) {
					_con.rollback();
					_con.close();
					fLogger.info("Closed connection"); //$NON-NLS-1$
				}
				// fTrunsactionTime = false;
			}
			if (_extra_con != null) {
				if (!_extra_con.isClosed()) {
					_extra_con.close();
					fLogger.info("Closed background connection"); //$NON-NLS-1$
				}
				// fTrunsactionTime = false;
			}
		} finally {
			_con = null;
			_extra_con = null;
			_info.setConnected(false);
			fLogger.debug("_info.setConnected(false)"); //$NON-NLS-1$
			for (int i = 0; i < fConnectionListenerList.size(); i++) {
				fConnectionListenerList.get(i).disconnected();
			}
		}
		return status;
	}

	@Override
	public ResultSetDataHolder2 explainPlan(String sql_statement)
			throws SQLException {
		Statement statement = null;
		ResultSetDataHolder2 sdh = null;
		try {
			statement = _extra_con.createStatement();
			sdh = executePrepareQuery(_extra_con, "EXPLAIN ANALYZE "
					+ sql_statement, StringUtil.EMPTY_STRING_ARRAY);

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

	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();
	}

	private Savepoint createSavePoint(Connection con) {
		if (con != null && !autoCommitMode) {
			try {
				return con.setSavepoint(savepointName);
			} catch (Exception e) {
				fLogger.info(
						"you must execute rollback ,after every sqlstatement executed.",
						e);
			}
		}
		return null;
	}

	private void releaseSavePoint() throws SQLException {
		if (fSavePoint != null) {
			_con.rollback(fSavePoint);
		}
	}

	public boolean doOperation(SQLOperationType operation, Request request)
			throws SQLException {
		boolean retCode = true;
		if (operation != SQLOperationType.CLOSE
				&& operation != SQLOperationType.ROLLBACK
				&& operation != SQLOperationType.CANSEL) {
			this.fSavePoint = createSavePoint(_con);
		}

		try {
			switch (operation) {
			case SELECT_SESSION:
				request.setRDH(getSessionInfo());
				break;
			default:
				retCode = super.doOperation(operation, request);
				break;
			}
		} catch (SQLException e) {
			fLogger.warn("MES:" + e.getMessage());
			fLogger.warn("MES:" + e.getLocalizedMessage());
			fLogger.warn("MES:" + e.getSQLState());
			releaseSavePoint();
			throw e;
		}
		return retCode;
	}

	@Override
	public boolean execute(ReflectionPreparedStatement ref) throws SQLException {
		this.fSavePoint = createSavePoint(_con);

		try {
			return super.execute(ref);
		} catch (SQLException e) {
			fLogger.warn("MES:" + e.getMessage());
			fLogger.warn("MES:" + e.getLocalizedMessage());
			fLogger.warn("MES:" + e.getSQLState());
			releaseSavePoint();
			throw e;
		}
	}

	/**
	 * @param operationCode
	 * @return
	 */
	public boolean canDoOperation(SQLOperationType operation) {
		switch (operation) {
		case SELECT_SESSION:
			return connected();
		case SELECT_LOCK:
			return false;
		default:
			return super.canDoOperation(operation);
		}
	}

	protected void setComments(GettingResourceRequest request)
			throws SQLException {
		DBRoot root = getRoot();
		request.beginTask("Grab comment (POSTGRE NATIVE)",
				3 * root.getSchemas().length);
		IDBSchema[] schemas = null;
		boolean withColumn = request.getConnectionProperties()
				.isCaptureWithColumnInfo() || request.targetType.isOnlyTable();
		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() };
			try {
				ResultSetDataHolder rdh = executePrepareQuery(_extra_con,
						_SELECT_TAB_COL_COMMENTS, params);

				request.worked(1);
				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 + "]");
						}
					}
				}
			} catch (SQLException e) {
				fLogger.warn(e.getMessage());
			}
			request.worked(1);
		}

	}

	private void setTableComments(IDBSchema schema) throws SQLException {
		ResultSet rsC = null;
		PreparedStatement pre = 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();
			}
		}
	}

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

	public ResultSetDataHolder2 getLockInfo() throws SQLException {
		return null;
	}

	@Override
	protected void createDBTableDef(GettingResourceRequest request)
			throws SQLException {
		try {
			fLogger.info("start");
			ConnectionProperties cp = request.getConnectionProperties();
			List<String> typesList = new ArrayList<String>();
			if (request.targetType.isOnlySchema()
					|| cp.isCaptureWithTableInfo()) {
				typesList.add("TABLE");
				// typesList.add("SYSTEM TABLE");
			}
			if (cp.isCaptureWithViewInfo()) {
				typesList.add("VIEW");
				// typesList.add("SYSTEM TABLE");
			}
			if (cp.isCaptureWithSynonymInfo()) {
				typesList.add("SYNONYM");
			}
			// if (type == null || type.endsWith("INDEX")
			// || type.endsWith("SEQUENCE")) {
			// continue;
			// }

			String[] types = typesList.toArray(new String[typesList.size()]);
			if (request.targetType.isOnlySchema()) {
				IDBSchema mschema = (IDBSchema) request.selectionResource;
				String sn = mschema.getName();
				createTableDefSub(request, mschema, sn, types);
			} else {
				for (IDBSchema mschema : getRoot().getSchemas()) {
					String sn = mschema.getName();
					if (isSkipSchemaAtGetAllMetaData(sn)) {
						continue;
					}
					createTableDefSub(request, mschema, sn, types);
					if (request.canceld()) {
						return;
					}
				}
			}

		} catch (SQLException e) {
			fLogger.trace(StringUtil.EMPTY_STRING, e);
		}
	}

	@Override
	protected boolean setTableText(GettingResourceRequest request)
			throws SQLException {
		boolean ret = true;
		if (request.targetType.isOnlySelectedResouce()) {
			if (request.selectionResource instanceof IDBTable) {
				IDBTable tbl = (IDBTable) request.selectionResource;
				if (tbl.isTable()) {
					setDDLOfTable(tbl.getParent().getName(), tbl);
				} else if (tbl.isView()) {
					setViewText(tbl);
				} else if (tbl.isFunction() || tbl.isProcudeure()) {
					setProcText(tbl);
				}
			}
		} else {
			IDBSchema[] schemas = getRoot().getSchemas();
			for (int i = 0; i < schemas.length; i++) {
				try {
					IDBTable[] prs = schemas[i].getProcedures();
					for (int j = 0; j < prs.length; j++) {
						setProcText(prs[j]);
					}
					prs = schemas[i].getFunctions();
					for (int j = 0; j < prs.length; j++) {
						setProcText(prs[j]);
					}
					IDBTable[] tbl = schemas[i].getTableOrViews();
					for (int j = 0; j < tbl.length; j++) {
						if (tbl[j].isTable()) {
							setDDLOfTable(schemas[i].getName(), tbl[j]);
						} else if (tbl[j].isView()) {
							setViewText(tbl[j]);
						}
					}
				} catch (SQLException e) {
					fLogger.trace(e.getMessage());
					ret = false;
				}
				if (i % 3 == 0 && request.canceld()) {
					return false;
				}
			}
		}
		return ret;
	}

	public void setTableColumns(String schema, IDBTable table)
			throws SQLException {
		if (table.isProcudeure() || table.isFunction()) {
			table.setResources(getProcedureColumns(schema, table));
			return;
		}
		List<String> pkey = null;
		if (table.isSynonym()) {
			if (!StringUtil.isEmpty(table.getComment())) {
				String[] spl = table.getComment().split("[.]");
				if (spl.length == 2) {
					pkey = getTablePrimaryKeys(StringUtil.EMPTY_STRING, spl[0],
							spl[1]);
				}
			}
		} else {
			if (table.isTable()) {
				pkey = getTablePrimaryKeys(StringUtil.EMPTY_STRING, schema,
						table.getName());
			}
		}

		ResultSet rs = null;
		Statement st = null;
		StringBuilder sql = new StringBuilder();
		try {
			if (table.isView()) {
				st = _extra_con.prepareStatement(_SELECT_COL_OF_VIEW);
				PreparedStatement pst = (PreparedStatement) st;
				pst.setString(1, schema.toUpperCase());
				pst.setString(2, table.getUName());
				rs = pst.executeQuery();
				while (rs.next()) {
					DBColumn col = new DBColumn(table);
					col.setName(rs.getString("column_name"));
					col.setDataType(SQLDataType.parse(rs.getString("data_type")));
					col.setSize(0);
					boolean isNullable = rs.getString("is_nullable")
							.equalsIgnoreCase("YES");
					col.setNotNull(!isNullable);
					col.setDataTypeString(rs.getString("data_type"));
					col.setMaxColumnNameLength(SQLUtil
							.getMaxColumnNameBytes(_extra_con));
					table.putResource(col.getUName(), col);
				}
			} else {
				sql.append("SELECT * FROM ");
				if (schema.trim().length() > 0) {
					sql.append(schema).append(".");
				}
				sql.append(table.getName());
				sql.append(" LIMIT 1");
				st = _extra_con.createStatement();
				st.setMaxRows(1);

				rs = st.executeQuery(sql.toString());
				ResultSetMetaData md = rs.getMetaData();
				for (int i = 1; i <= md.getColumnCount(); i++) {
					DBColumn col = new DBColumn(table);
					col.setName(md.getColumnName(i));
					col.setDataType(SQLDataType.parse(md.getColumnType(i)));
					try {
						col.setSize(md.getPrecision(i));
					} catch (Exception e) {
						col.setSize(0);
					}
					try {
						col.setDecimalDigits(md.getScale(i));
					} catch (Exception e) {
						col.setDecimalDigits(0);
					}

					col.setNullable((short) md.isNullable(i));
					if (pkey != null) {
						col.setPKey(pkey);
					}
					col.setDataTypeString(md.getColumnTypeName(i));
					col.setMaxColumnNameLength(SQLUtil
							.getMaxColumnNameBytes(_extra_con));

					table.putResource(col.getUName(), col);
				}
			}
		} catch (SQLException e) {
			fLogger.info("sql=" + sql);
			fLogger.warn(e.getMessage());
			return;
		} finally {
			if (rs != null) {
				rs.close();
			}
			if (st != null) {
				st.close();
			}
		}
	}

	protected void setProcText(IDBTable proc) throws SQLException {
		ResultSetDataHolder rdh = null;

		rdh = executePrepareQuery(_extra_con, _SELECT_FUNCTION_TEXT,
				new String[] { proc.getParent().getName(), proc.getName() });
		for (int i = 0; i < rdh.getRowCount(); i++) {
			String tn = ParserUtil.breakKeyWord(rdh.getStringData(i, "TEXT"));
			proc.setText(tn);
		}
	}

	protected void setViewText(IDBTable table) throws SQLException {
		ResultSetDataHolder rdh = null;

		rdh = executePrepareQuery(_extra_con, _SELECT_VIEW_TEXT, new String[] {
				table.getParent().getUName(), table.getUName() });
		for (int i = 0; i < rdh.getRowCount(); i++) {
			String tn = ParserUtil.breakKeyWord(rdh.getStringData(i, "TEXT"));
			table.setText(String.format("CREATE OR REPLACE VIEW %s AS %n%s",
					table.getName(), tn));
		}
	}

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

		boolean withTrigger = request.getConnectionProperties()
				.isCaptureWithTriggerInfo();
		if (!withTrigger) {
			return;
		}
		IDBSchema[] schemas = getRoot().getSchemas();
		try {
			for (int i = 0; i < schemas.length; i++) {
				if (schemas[i].getName().length() == 0) {
					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;
				}
			}
		} finally {
		}
	}

	public static String getLimitString() {
		return "LIMIT 0, 30";
	}

	@Override
	protected void getSequence(GettingResourceRequest request)
			throws SQLException {

		ResultSetDataHolder rdh = null;
		ResultSetDataHolder rdh2 = null;
		IDBSchema[] schemas = getRoot().getSchemas();
		try {
			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_ALL_SEQUENCE,
						new String[] { schemas[i].getName() });
				DBSequence sequence = null;
				for (int j = 0; j < rdh.getRowCount(); j++) {
					try {
						rdh2 = null;
						sequence = new DBSequence(schemas[i]);
						String name = rdh.getStringData(j, "NAME");
						sequence.setName(name);
						String text = _SELECT_SEQUENCE_BODY
								+ schemas[i].getName() + "." + name;
						rdh2 = executePrepareQuery(_extra_con, text, EMPTY);
						if (rdh2.getRowCount() > 0) {
							setResourceProperties(sequence, 0, rdh2);
						}
						schemas[i].putSequence(sequence);
					} catch (SQLException e) {
						fLogger.trace(StringUtil.EMPTY_STRING, e);
					}
					// setViewText(trigger);
				}
				if (request.canceld()) {
					return;
				}
			}
		} finally {
		}
	}

	// ----------------------------------------------------------------
	// [4] DIFF
	// ----------------------------------------------------------------
	@Override
	public ResultSetDataHolder2 getDiffInfoOf(DBResourceType resourceType,
			String schemaName, boolean withValue) {
		ResultSetDataHolder2 ret = null;
		try {
			switch (resourceType) {
			case TABLE:
				ret = executePrepareQuery(_SELECT_DIFF_TABLE,
						new String[] { schemaName });
				break;
			case VIEW:
				ret = executePrepareQuery(_SELECT_DIFF_VIEW,
						new String[] { schemaName });
				break;
			case FUNCTION:
				ret = executePrepareQuery(_SELECT_DIFF_FNCTIONS,
						new String[] { schemaName });
				break;
			case SEQUENCE:
				ResultSetDataHolder2 rdh_s = executePrepareQuery(_con,
						_SELECT_ALL_SEQUENCE, new String[] { schemaName });
				ret = new ResultSetDataHolder2(
						_SELECT_DIFF_A_SEQUENCE_INFO_COLUMNS, null,
						DatabaseType.POSTGRES);

				for (int j = 0; j < rdh_s.getRowCount(); j++) {
					String name = rdh_s.getStringData(j, "NAME");
					if (!StringUtil.isEmpty(schemaName)) {
						name = schemaName + "." + name;
					}
					ResultSetDataHolder2 r = executePrepareQuery(_con,
							String.format(_SELECT_DIFF_A_SEQUENCE_INFO, name),
							StringUtil.EMPTY_STRING_ARRAY);
					for (int i = 0; i < r.getRowCount(); i++) {
						ret.addRow(r.getRowWithoutRowColumn(i));
					}
				}
				break;
			}
		} catch (SQLException e) {
			fLogger.error(StringUtil.EMPTY_STRING, e);
		}
		if (ret != null) {
			ret.setTableNameE(String.format("DEF_%s_%s", schemaName,
					resourceType.name()));
		}
		fLogger.debug("[" + _info.getDisplayString() + "] ret:[" + ret + "]");
		return ret;
	}

	// ----------------------------------------------------------------
	// [5] MIRRORING
	// ----------------------------------------------------------------
	@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.getIntDataDefaultZero(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(StringUtil.LINE_SEPARATOR);
			buf.append("  foreign key(");

			executePrepare(buf.toString(), EMPTY);
		}

		commit();

		return true;
	}

	@Override
	public boolean createDatabase(String databaseName, Properties properties)
			throws SQLException {
		StringBuilder buf = new StringBuilder();
		buf.append("CREATE DATABASE ").append(databaseName);
		if (properties.containsKey("encoding")) {
			buf.append(String.format(" WITH ENCODING='%s' ",
					properties.getProperty("encoding")));
		} else {
			buf.append(" WITH ENCODING='UTF-8' ");
		}
		if (properties.containsKey("owner")) {
			buf.append(String.format(" OWNER='%s' ",
					properties.getProperty("owner")));
		}
		buf.append("CONNECTION LIMIT=-1");
		executePrepare(buf.toString(), EMPTY);
		if (properties.containsKey("remarks")) {
			executePrepare(String.format("COMMENT ON DATABASE %s IS '%s'",
					databaseName, properties.getProperty("remarks")),
					StringUtil.EMPTY_STRING_ARRAY);
		}
		return true;
	}

	@Override
	protected boolean createSchema(String schemaName, Properties properties)
			throws SQLException {
		String st = null;
		if (properties.containsKey("owner")) {
			st = String.format("CREATE SCHEMA %s AUTHORIZATION %s", schemaName,
					properties.getProperty("owner"));
		} else {
			st = String.format("CREATE SCHEMA %s ", schemaName);
		}
		executePrepare(st, EMPTY);
		if (properties.containsKey("remarks")) {
			executePrepare(String.format("COMMENT ON SCHEMA %s IS '%s'",
					schemaName, properties.getProperty("remarks")),
					StringUtil.EMPTY_STRING_ARRAY);
		}
		return true;
	}

	@Override
	public Set<String> getSchemas() {
		Set<String> retSet = super.getSchemas();
		retSet.remove("pg_catalog");
		return retSet;
	}

	@Override
	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;
	}

	@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 = _info.getDBRootResource().getDefaultSchema().getUName();
		}
		rdh = executePrepareQuery(_con, _SELECT_SEQUENCE_CNT, new String[] {
				sn, sequence.getName() });
		boolean existsSequence = rdh.getIntDataDefaultZero(0, "CNT") > 0;
		if (existsSequence && drop) {
			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 ");
		buf.append(schemaName).append(".");
		buf.append(sequence.getName()).append(" ")
				.append(StringUtil.LINE_SEPARATOR);
		buf.append("  INCREMENT ").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 ").append("200").append(StringUtil.LINE_SEPARATOR);
		buf.append("  CACHE ").append("1").append(StringUtil.LINE_SEPARATOR);
		// CYCLE;
		executePrepare(buf.toString(), EMPTY);

		return true;
	}

	@Override
	public boolean existsTable(String schemaName, String tableName)
			throws SQLException {
		if (StringUtil.isEmpty(schemaName)) {
			schemaName = DEFAULT_SCHEMA_NAME;
		}
		ResultSetDataHolder rdh = null;
		// if (table.isTable()) {
		rdh = executePrepareQuery(_SELECT_TABLE_CNT, new String[] { schemaName,
				tableName });
		// } else {
		// rdh = executePrepareQuery(_SELECT_VIEW_CNT, new String[] { sn,
		// tableName });
		// }
		return rdh.getIntDataDefaultZero(0, "CNT") > 0;
	}

	// 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.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;
	//
	// }

	// private boolean createTableBody(String schemaName, IDBTable table,
	// Set<SQL_TYPES_CONVERT_MODE> sqlTypesConvertSet) throws SQLException {
	// StringBuilder buf = new StringBuilder();
	// if (table.isTable()) {
	// buf.append("CREATE TABLE ");
	// buf.append(schemaName).append(".").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], sqlTypesConvertSet));
	// 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;
	// }
	// buf.append("CREATE VIEW ");
	// buf.append(schemaName).append(".").append(table.getName());
	// buf.append(" AS ").append(StringUtil.LINE_SEPARATOR);
	// buf.append(table.getText());
	// 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 ");
			}
			buf.append(schemaName).append(".").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 ");
				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;
	}

}