package cn.gov.customs.data.dm;

import java.sql.CallableStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import org.hibernate.LockMode;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.function.CastFunction;
import org.hibernate.dialect.function.NoArgSQLFunction;
import org.hibernate.dialect.function.SQLFunctionTemplate;
import org.hibernate.dialect.function.StandardSQLFunction;
import org.hibernate.dialect.function.VarArgsSQLFunction;
import org.hibernate.dialect.identity.IdentityColumnSupport;
import org.hibernate.dialect.pagination.AbstractLimitHandler;
import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.dialect.pagination.LimitHelper;
import org.hibernate.engine.spi.RowSelection;
import org.hibernate.exception.internal.SQLStateConverter;
import org.hibernate.exception.spi.SQLExceptionConverter;
import org.hibernate.exception.spi.ViolatedConstraintNameExtracter;
import org.hibernate.hql.spi.id.IdTableSupportStandardImpl;
import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy;
import org.hibernate.hql.spi.id.global.GlobalTemporaryTableBulkIdStrategy;
import org.hibernate.hql.spi.id.local.AfterUseAction;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
import org.hibernate.type.StandardBasicTypes;


public class Dm8Dialect extends Dialect {
    private static final AbstractLimitHandler LIMIT_HANDLER = new AbstractLimitHandler() {
        public String processSql(String sql, RowSelection selection) {
            boolean hasOffset = LimitHelper.hasFirstRow(selection);

            for(sql = sql.trim(); sql.endsWith(";"); sql = sql.substring(0, sql.length() - 1)) {
            }

            boolean isForUpdate = false;
            if (sql.toLowerCase().endsWith(" for update")) {
                sql = sql.substring(0, sql.length() - 11);
                isForUpdate = true;
            }

            StringBuilder pagingSelect = new StringBuilder(sql.length() + 100);
            if (hasOffset) {
                pagingSelect.append(sql).append(" limit ? offset ? ");
            } else {
                pagingSelect.append(sql).append(" limit ? ");
            }

            if (isForUpdate) {
                pagingSelect.append(" for update");
            }

            return pagingSelect.toString();
        }

        public boolean supportsLimit() {
            return true;
        }

        public boolean supportsLimitOffset() {
            return this.supportsLimit();
        }

        public boolean supportsVariableLimit() {
            return this.supportsLimit();
        }

        public boolean bindLimitParametersInReverseOrder() {
            return true;
        }

        public boolean bindLimitParametersFirst() {
            return false;
        }

        public boolean useMaxForLimit() {
            return false;
        }

        public boolean forceLimitUsage() {
            return false;
        }

        public int convertToFirstRowValue(int zeroBasedFirstResult) {
            return zeroBasedFirstResult;
        }
    };
    int dmdbtype_cursor = 0;
    private static final ViolatedConstraintNameExtracter EXTRACTER = new ViolatedConstraintNameExtracter() {
        public String extractConstraintName(SQLException sqle) {
            return null;
        }
    };

    public Dm8Dialect() {
        this.registerColumnType(-7, "bit");
        this.registerColumnType(16, "bit");
        this.registerColumnType(-6, "tinyint");
        this.registerColumnType(5, "smallint");
        this.registerColumnType(4, "integer");
        this.registerColumnType(-5, "bigint");
        this.registerColumnType(6, "float");
        this.registerColumnType(8, "double");
        this.registerColumnType(2, "numeric($p,$s)");
        this.registerColumnType(7, "real");
        this.registerColumnType(3, "decimal($p,$s)");
        this.registerColumnType(91, "date");
        this.registerColumnType(92, "time");
        this.registerColumnType(93, "datetime");
        this.registerColumnType(-2, "binary($l)");
        this.registerColumnType(-3, "varbinary($l)");
        this.registerColumnType(-4, "image");
        this.registerColumnType(2004, "blob");
        this.registerColumnType(1, "char(1)");
        this.registerColumnType(12, "varchar($l)");
        this.registerColumnType(-1, "text");
        this.registerColumnType(2005, "clob");
        this.registerColumnType(-15, "char(1)");
        this.registerColumnType(-9, "varchar($l)");
        this.registerColumnType(-16, "text");
        this.registerColumnType(2011, "clob");
        this.registerHibernateType(Types.OTHER, StandardBasicTypes.TIMESTAMP.getName());
        this.registerKeyword("last");
        this.registerKeyword("size");
        this.registerHibernateType(5, StandardBasicTypes.SHORT.getName());
        this.registerFunction("substring", new SQLFunctionTemplate(StandardBasicTypes.STRING, "substring(?1, ?2, ?3)"));
        this.registerFunction("locate", new SQLFunctionTemplate(StandardBasicTypes.INTEGER, "locate(?1, ?2, ?3)"));
        this.registerFunction("trim", new SQLFunctionTemplate(StandardBasicTypes.STRING, "trim(?1 ?2 ?3 ?4)"));
        this.registerFunction("length", new StandardSQLFunction("length", StandardBasicTypes.INTEGER));
        this.registerFunction("bit_length", new StandardSQLFunction("bit_length", StandardBasicTypes.INTEGER));
        this.registerFunction("coalesce", new StandardSQLFunction("coalesce"));
        this.registerFunction("nullif", new StandardSQLFunction("nullif"));
        this.registerFunction("abs", new StandardSQLFunction("abs"));
        this.registerFunction("mod", new StandardSQLFunction("mod", StandardBasicTypes.LONG));
        this.registerFunction("sqrt", new StandardSQLFunction("sqrt", StandardBasicTypes.DOUBLE));
        this.registerFunction("upper", new StandardSQLFunction("upper"));
        this.registerFunction("lower", new StandardSQLFunction("lower"));
        this.registerFunction("cast", new CastFunction());
        this.registerFunction("extract", new SQLFunctionTemplate(StandardBasicTypes.INTEGER, "extract(?1 ?2 ?3)"));
        this.registerFunction("second", new StandardSQLFunction("second", StandardBasicTypes.INTEGER));
        this.registerFunction("minute", new StandardSQLFunction("minute", StandardBasicTypes.INTEGER));
        this.registerFunction("hour", new StandardSQLFunction("hour", StandardBasicTypes.INTEGER));
        this.registerFunction("day", new StandardSQLFunction("day", StandardBasicTypes.INTEGER));
        this.registerFunction("month", new StandardSQLFunction("month", StandardBasicTypes.INTEGER));
        this.registerFunction("year", new StandardSQLFunction("year", StandardBasicTypes.INTEGER));
        this.registerFunction("str", new StandardSQLFunction("to_char", StandardBasicTypes.STRING));
        this.registerFunction("asin", new StandardSQLFunction("asin", StandardBasicTypes.DOUBLE));
        this.registerFunction("acos", new StandardSQLFunction("acos", StandardBasicTypes.DOUBLE));
        this.registerFunction("atan", new StandardSQLFunction("atan", StandardBasicTypes.DOUBLE));
        this.registerFunction("atan2", new StandardSQLFunction("atan2", StandardBasicTypes.DOUBLE));
        this.registerFunction("ceil", new StandardSQLFunction("ceil", StandardBasicTypes.INTEGER));
        this.registerFunction("ceiling", new StandardSQLFunction("ceiling", StandardBasicTypes.INTEGER));
        this.registerFunction("cos", new StandardSQLFunction("cos", StandardBasicTypes.DOUBLE));
        this.registerFunction("cot", new StandardSQLFunction("cot", StandardBasicTypes.DOUBLE));
        this.registerFunction("cosh", new StandardSQLFunction("cosh", StandardBasicTypes.DOUBLE));
        this.registerFunction("degrees", new StandardSQLFunction("degrees"));
        this.registerFunction("exp", new StandardSQLFunction("exp", StandardBasicTypes.DOUBLE));
        this.registerFunction("GREATEST", new StandardSQLFunction("GREATEST", StandardBasicTypes.DOUBLE));
        this.registerFunction("floor", new StandardSQLFunction("floor", StandardBasicTypes.INTEGER));
        this.registerFunction("ln", new StandardSQLFunction("ln", StandardBasicTypes.DOUBLE));
        this.registerFunction("log", new StandardSQLFunction("log", StandardBasicTypes.DOUBLE));
        this.registerFunction("log10", new StandardSQLFunction("log10", StandardBasicTypes.DOUBLE));
        this.registerFunction("pi", new NoArgSQLFunction("pi", StandardBasicTypes.DOUBLE));
        this.registerFunction("power", new StandardSQLFunction("power", StandardBasicTypes.DOUBLE));
        this.registerFunction("radians", new StandardSQLFunction("radians"));
        this.registerFunction("rand", new NoArgSQLFunction("rand", StandardBasicTypes.DOUBLE));
        this.registerFunction("round", new StandardSQLFunction("round"));
        this.registerFunction("sign", new StandardSQLFunction("sign", StandardBasicTypes.INTEGER));
        this.registerFunction("sin", new StandardSQLFunction("sin", StandardBasicTypes.DOUBLE));
        this.registerFunction("sinh", new StandardSQLFunction("sinh", StandardBasicTypes.DOUBLE));
        this.registerFunction("tan", new StandardSQLFunction("tan", StandardBasicTypes.DOUBLE));
        this.registerFunction("tanh", new StandardSQLFunction("tanh", StandardBasicTypes.DOUBLE));
        this.registerFunction("trunc", new StandardSQLFunction("trunc"));
        this.registerFunction("truncate", new StandardSQLFunction("truncate"));
        this.registerFunction("stddev", new StandardSQLFunction("stddev", StandardBasicTypes.DOUBLE));
        this.registerFunction("variance", new StandardSQLFunction("variance", StandardBasicTypes.DOUBLE));
        this.registerFunction("concat", new VarArgsSQLFunction(StandardBasicTypes.STRING, "", "||", ""));
        this.registerFunction("ascii", new StandardSQLFunction("ascii", StandardBasicTypes.INTEGER));
        this.registerFunction("char", new StandardSQLFunction("char", StandardBasicTypes.CHARACTER));
        this.registerFunction("difference", new StandardSQLFunction("difference", StandardBasicTypes.INTEGER));
        this.registerFunction("char_length", new StandardSQLFunction("char_length", StandardBasicTypes.LONG));
        this.registerFunction("character_length", new StandardSQLFunction("character_length", StandardBasicTypes.LONG));
        this.registerFunction("chr", new StandardSQLFunction("chr", StandardBasicTypes.CHARACTER));
        this.registerFunction("initcap", new StandardSQLFunction("initcap", StandardBasicTypes.STRING));
        this.registerFunction("insert", new StandardSQLFunction("insert", StandardBasicTypes.STRING));
        this.registerFunction("insstr", new StandardSQLFunction("insstr", StandardBasicTypes.STRING));
        this.registerFunction("instr", new StandardSQLFunction("instr", StandardBasicTypes.LONG));
        this.registerFunction("instrb", new StandardSQLFunction("instrb", StandardBasicTypes.LONG));
        this.registerFunction("lcase", new StandardSQLFunction("lcase", StandardBasicTypes.STRING));
        this.registerFunction("left", new StandardSQLFunction("left", StandardBasicTypes.STRING));
        this.registerFunction("leftstr", new StandardSQLFunction("leftstr", StandardBasicTypes.STRING));
        this.registerFunction("len", new StandardSQLFunction("len", StandardBasicTypes.INTEGER));
        this.registerFunction("LENGTHB", new StandardSQLFunction("LENGTHB", StandardBasicTypes.INTEGER));
        this.registerFunction("octet_length", new StandardSQLFunction("octet_length", StandardBasicTypes.LONG));
        this.registerFunction("lpad", new StandardSQLFunction("lpad", StandardBasicTypes.STRING));
        this.registerFunction("ltrim", new StandardSQLFunction("ltrim", StandardBasicTypes.STRING));
        this.registerFunction("position", new StandardSQLFunction("position", StandardBasicTypes.INTEGER));
        this.registerFunction("INS", new StandardSQLFunction("INS", StandardBasicTypes.STRING));
        this.registerFunction("repeat", new StandardSQLFunction("repeat", StandardBasicTypes.STRING));
        this.registerFunction("REPLICATE", new StandardSQLFunction("REPLICATE", StandardBasicTypes.STRING));
        this.registerFunction("STUFF", new StandardSQLFunction("STUFF", StandardBasicTypes.STRING));
        this.registerFunction("repeatstr", new StandardSQLFunction("repeatstr", StandardBasicTypes.STRING));
        this.registerFunction("replace", new StandardSQLFunction("replace", StandardBasicTypes.STRING));
        this.registerFunction("reverse", new StandardSQLFunction("reverse", StandardBasicTypes.STRING));
        this.registerFunction("right", new StandardSQLFunction("right", StandardBasicTypes.STRING));
        this.registerFunction("rightstr", new StandardSQLFunction("rightstr", StandardBasicTypes.STRING));
        this.registerFunction("rpad", new StandardSQLFunction("rpad", StandardBasicTypes.STRING));
        this.registerFunction("TO_NUMBER", new StandardSQLFunction("TO_NUMBER"));
        this.registerFunction("rtrim", new StandardSQLFunction("rtrim", StandardBasicTypes.STRING));
        this.registerFunction("soundex", new StandardSQLFunction("soundex", StandardBasicTypes.STRING));
        this.registerFunction("space", new StandardSQLFunction("space", StandardBasicTypes.STRING));
        this.registerFunction("substr", new StandardSQLFunction("substr", StandardBasicTypes.STRING));
        this.registerFunction("substrb", new StandardSQLFunction("substrb", StandardBasicTypes.STRING));
        this.registerFunction("to_char", new StandardSQLFunction("to_char", StandardBasicTypes.STRING));
        this.registerFunction("STRPOSDEC", new StandardSQLFunction("STRPOSDEC", StandardBasicTypes.STRING));
        this.registerFunction("STRPOSINC", new StandardSQLFunction("STRPOSINC", StandardBasicTypes.STRING));
        this.registerFunction("VSIZE", new StandardSQLFunction("VSIZE", StandardBasicTypes.INTEGER));
        this.registerFunction("translate", new StandardSQLFunction("translate", StandardBasicTypes.STRING));
        this.registerFunction("ucase", new StandardSQLFunction("ucase", StandardBasicTypes.STRING));
        this.registerFunction("OVERLAPS", new StandardSQLFunction("OVERLAPS"));
        this.registerFunction("DATEPART", new StandardSQLFunction("DATEPART"));
        this.registerFunction("DATE_PART", new StandardSQLFunction("DATE_PART"));
        this.registerFunction("add_days", new StandardSQLFunction("add_days"));
        this.registerFunction("add_months", new StandardSQLFunction("add_months"));
        this.registerFunction("add_weeks", new StandardSQLFunction("add_weeks"));
        this.registerFunction("curdate", new NoArgSQLFunction("curdate", StandardBasicTypes.DATE));
        this.registerFunction("curtime", new NoArgSQLFunction("curtime", StandardBasicTypes.TIME));
        this.registerFunction("current_date", new NoArgSQLFunction("current_date", StandardBasicTypes.DATE));
        this.registerFunction("current_time", new NoArgSQLFunction("current_time", StandardBasicTypes.TIME));
        this.registerFunction("current_timestamp", new NoArgSQLFunction("current_timestamp", StandardBasicTypes.TIMESTAMP));
        this.registerFunction("dateadd", new StandardSQLFunction("dateadd", StandardBasicTypes.TIMESTAMP));
        this.registerFunction("CUR_TICK_TIME", new StandardSQLFunction("CUR_TICK_TIME"));
        this.registerFunction("datediff", new StandardSQLFunction("datediff", StandardBasicTypes.INTEGER));
        this.registerFunction("datepart", new StandardSQLFunction("datepart", StandardBasicTypes.INTEGER));
        this.registerFunction("dayname", new StandardSQLFunction("dayname", StandardBasicTypes.STRING));
        this.registerFunction("dayofmonth", new StandardSQLFunction("dayofmonth", StandardBasicTypes.INTEGER));
        this.registerFunction("dayofweek", new StandardSQLFunction("dayofweek", StandardBasicTypes.INTEGER));
        this.registerFunction("dayofyear", new StandardSQLFunction("dayofyear", StandardBasicTypes.INTEGER));
        this.registerFunction("days_between", new StandardSQLFunction("days_between", StandardBasicTypes.INTEGER));
        this.registerFunction("getdate", new StandardSQLFunction("getdate", StandardBasicTypes.TIMESTAMP));
        this.registerFunction("LOCALTIMESTAMP", new StandardSQLFunction("LOCALTIMESTAMP"));
        this.registerFunction("NOW", new StandardSQLFunction("NOW"));
        this.registerFunction("last_day", new StandardSQLFunction("last_day"));
        this.registerFunction("month", new StandardSQLFunction("month", StandardBasicTypes.INTEGER));
        this.registerFunction("monthname", new StandardSQLFunction("monthname", StandardBasicTypes.STRING));
        this.registerFunction("months_between", new StandardSQLFunction("months_between"));
        this.registerFunction("GREATEST", new StandardSQLFunction("GREATEST", StandardBasicTypes.DATE));
        this.registerFunction("TO_DATETIME", new StandardSQLFunction("TO_DATETIME"));
        this.registerFunction("next_day", new StandardSQLFunction("next_day"));
        this.registerFunction("quarter", new StandardSQLFunction("quarter", StandardBasicTypes.INTEGER));
        this.registerFunction("round", new StandardSQLFunction("round"));
        this.registerFunction("timestampadd", new StandardSQLFunction("timestampadd", StandardBasicTypes.TIMESTAMP));
        this.registerFunction("timestampdiff", new StandardSQLFunction("timestampdiff", StandardBasicTypes.INTEGER));
        this.registerFunction("BIGDATEDIFF", new StandardSQLFunction("BIGDATEDIFF", StandardBasicTypes.BIG_INTEGER));
        this.registerFunction("sysdate", new StandardSQLFunction("sysdate", StandardBasicTypes.TIME));
        this.registerFunction("LEAST", new StandardSQLFunction("LEAST"));
        this.registerFunction("trunc", new StandardSQLFunction("trunc"));
        this.registerFunction("week", new StandardSQLFunction("week", StandardBasicTypes.INTEGER));
        this.registerFunction("weekday", new StandardSQLFunction("weekday", StandardBasicTypes.INTEGER));
        this.registerFunction("weeks_between", new StandardSQLFunction("weeks_between", StandardBasicTypes.INTEGER));
        this.registerFunction("year", new StandardSQLFunction("year", StandardBasicTypes.INTEGER));
        this.registerFunction("years_between", new StandardSQLFunction("years_between", StandardBasicTypes.INTEGER));
        this.registerFunction("to_date", new StandardSQLFunction("to_date", StandardBasicTypes.TIMESTAMP));
        this.registerFunction("systimestamp", new NoArgSQLFunction("systimestamp", StandardBasicTypes.TIMESTAMP));
        this.registerFunction("ifnull", new StandardSQLFunction("ifnull"));
        this.registerFunction("isnull", new StandardSQLFunction("isnull"));
        this.registerFunction("nvl", new StandardSQLFunction("nvl"));
        this.registerFunction("decode", new StandardSQLFunction("decode"));
        this.registerFunction("cur_database", new StandardSQLFunction("cur_database", StandardBasicTypes.STRING));
        this.registerFunction("page", new StandardSQLFunction("page", StandardBasicTypes.INTEGER));
        this.registerFunction("sessid", new StandardSQLFunction("sessid", StandardBasicTypes.LONG));
        this.registerFunction("uid", new StandardSQLFunction("uid", StandardBasicTypes.LONG));
        this.registerFunction("user", new StandardSQLFunction("user", StandardBasicTypes.STRING));
        this.registerFunction("vsize", new StandardSQLFunction("vsize", StandardBasicTypes.INTEGER));
        this.registerFunction("tabledef", new StandardSQLFunction("tabledef", StandardBasicTypes.STRING));
        this.getDefaultProperties().setProperty("hibernate.use_outer_join", "true");
        this.getDefaultProperties().setProperty("hibernate.jdbc.batch_size", "0");
    }

    public IdentityColumnSupport getIdentityColumnSupport() {
        return new DM8IdentityColumnSupport();
    }

    public boolean supportsSequences() {
        return true;
    }

    public boolean supportsPooledSequences() {
        return true;
    }

    public String getSequenceNextValString(String sequenceName) {
        return "select " + this.getSelectSequenceNextValString(sequenceName);
    }

    public String getSelectSequenceNextValString(String sequenceName) {
        return sequenceName + ".nextval";
    }

    /** @deprecated */
    public String[] getCreateSequenceStrings(String sequenceName) {
        return new String[]{this.getCreateSequenceString(sequenceName)};
    }

    public String[] getCreateSequenceStrings(String sequenceName, int initialValue, int incrementSize) {
        return new String[]{this.getCreateSequenceString(sequenceName, initialValue, incrementSize)};
    }

    protected String getCreateSequenceString(String sequenceName) {
        return "create sequence " + sequenceName;
    }

    protected String getCreateSequenceString(String sequenceName, int initialValue, int incrementSize) {
        return this.getCreateSequenceString(sequenceName) + " increment by " + incrementSize + " start with " + initialValue;
    }

    public String[] getDropSequenceStrings(String sequenceName) {
        return new String[]{this.getDropSequenceString(sequenceName)};
    }

    protected String getDropSequenceString(String sequenceName) {
        return "drop sequence " + sequenceName;
    }

    public String getQuerySequencesString() {
        return "select * from all_sequences";
    }

    public SequenceInformationExtractor getSequenceInformationExtractor() {
        return SequenceInformationExtractorDMDatabaseImpl.INSTANCE;
    }

    public String getSelectGUIDString() {
        return "select GUID()";
    }

    public LimitHandler getLimitHandler() {
        return LIMIT_HANDLER;
    }

    static int getAfterSelectInsertPoint(String sql) {
        int selectIndex = sql.toLowerCase().indexOf("select");
        int selectDistinctIndex = sql.toLowerCase().indexOf("select distinct");
        return selectIndex + (selectDistinctIndex != selectIndex ? 6 : 15);
    }

    public boolean supportsLockTimeouts() {
        return true;
    }

    public boolean isLockTimeoutParameterized() {
        return false;
    }

    public String getForUpdateString() {
        return " for update";
    }

    public String getWriteLockString(int timeout) {
        if (timeout == 0) {
            return " for update nowait";
        } else if (timeout > 0) {
            float seconds = (float)timeout / 1000.0F;
            timeout = Math.round(seconds);
            return " for update wait " + timeout;
        } else {
            return " for update";
        }
    }

    public String getReadLockString(int timeout) {
        return this.getWriteLockString(timeout);
    }

    public boolean forUpdateOfColumns() {
        return true;
    }

    public boolean supportsOuterJoinForUpdate() {
        return true;
    }

    public String getForUpdateString(String aliases) {
        return this.getForUpdateString() + " of " + aliases;
    }

    public String getForUpdateNowaitString() {
        return this.getForUpdateString() + " nowait";
    }

    public String getForUpdateNowaitString(String aliases) {
        return this.getForUpdateString() + " of " + aliases + " nowait";
    }

    public String appendLockHint(LockMode mode, String tableName) {
        return tableName;
    }

    public int registerResultSetOutParameter(CallableStatement statement, int col) throws SQLException {
        if (this.dmdbtype_cursor == 0) {
            try {
                Class types = ReflectHelper.classForName("dm.jdbc.driver.DmdbType");
                this.dmdbtype_cursor = types.getField("CURSOR").getInt(types.newInstance());
            } catch (Exception var4) {
                throw new SQLException("Problem while trying to load or access DmdbType.CURSOR value", var4);
            }
        }

        statement.registerOutParameter(col, this.dmdbtype_cursor);
        ++col;
        return col;
    }

    public ResultSet getResultSet(CallableStatement statement) throws SQLException {
        statement.execute();
        return (ResultSet)statement.getObject(1);
    }

    public boolean supportsCurrentTimestampSelection() {
        return true;
    }

    public boolean isCurrentTimestampSelectStringCallable() {
        return false;
    }

    public String getCurrentTimestampSelectString() {
        return "select current_timestamp()";
    }

    public String getCurrentTimestampSQLFunctionName() {
        return "current_timestamp";
    }

    public SQLExceptionConverter buildSQLExceptionConverter() {
        return new SQLStateConverter(this.getViolatedConstraintNameExtracter());
    }

    public ViolatedConstraintNameExtracter getViolatedConstraintNameExtracter() {
        return EXTRACTER;
    }

    public String getSelectClauseNullString(int sqlType) {
        return "null";
    }

    public boolean supportsUnionAll() {
        return true;
    }

    public String getLowercaseFunction() {
        return "lower";
    }

    public String transformSelectString(String select) {
        return select;
    }

    public String toBooleanValueString(boolean bool) {
        return bool ? "1" : "0";
    }

    public char openQuote() {
        return '"';
    }

    public char closeQuote() {
        return '"';
    }

    public boolean hasAlterTable() {
        return true;
    }

    public boolean dropConstraints() {
        return false;
    }

    public boolean qualifyIndexName() {
        return true;
    }

    public boolean supportsUnique() {
        return true;
    }

    public boolean supportsUniqueConstraintInCreateAlterTable() {
        return true;
    }

    public String getAddColumnString() {
        return " add column ";
    }

    public String getDropForeignKeyString() {
        return " drop constraint ";
    }

    public String getTableTypeString() {
        return "";
    }

    public String getAddForeignKeyConstraintString(String constraintName, String[] foreignKey, String referencedTable, String[] primaryKey, boolean referencesPrimaryKey) {
        StringBuffer res = new StringBuffer(30);
        res.append(" add constraint ").append(constraintName).append(" foreign key (").append(this.join(", ", foreignKey)).append(") references ").append(referencedTable);
        if (!referencesPrimaryKey) {
            res.append(" (").append(this.join(", ", primaryKey)).append(')');
        }

        return res.toString();
    }

    public String getAddPrimaryKeyConstraintString(String constraintName) {
        return " add constraint " + constraintName + " primary key ";
    }

    public boolean hasSelfReferentialForeignKeyBug() {
        return false;
    }

    public String getNullColumnString() {
        return "";
    }

    public boolean supportsCommentOn() {
        return false;
    }

    public String getTableComment(String comment) {
        return "";
    }

    public String getColumnComment(String comment) {
        return "";
    }

    public boolean supportsIfExistsBeforeTableName() {
        return false;
    }

    public boolean supportsIfExistsAfterTableName() {
        return false;
    }

    public boolean supportsColumnCheck() {
        return true;
    }

    public boolean supportsTableCheck() {
        return true;
    }

    public boolean supportsCascadeDelete() {
        return true;
    }

    public boolean supportsNotNullUnique() {
        return true;
    }

    public String getCascadeConstraintsString() {
        return " cascade ";
    }

    public String getCrossJoinSeparator() {
        return " cross join ";
    }

    public boolean supportsEmptyInList() {
        return false;
    }

    public boolean supportsRowValueConstructorSyntax() {
        return false;
    }

    public boolean supportsRowValueConstructorSyntaxInInList() {
        return true;
    }

    public boolean useInputStreamToInsertBlob() {
        return true;
    }

    public boolean replaceResultVariableInOrderByClauseWithPosition() {
        return false;
    }

    public boolean requiresCastingOfParametersInSelectClause() {
        return false;
    }

    public boolean supportsResultSetPositionQueryMethodsOnForwardOnlyCursor() {
        return true;
    }

    public boolean supportsCircularCascadeDeleteConstraints() {
        return false;
    }

    public boolean supportsSubselectAsInPredicateLHS() {
        return true;
    }

    public boolean supportsExpectedLobUsagePattern() {
        return true;
    }

    public boolean supportsLobValueChangePropogation() {
        return false;
    }

    public boolean supportsUnboundedLobLocatorMaterialization() {
        return false;
    }

    public boolean supportsSubqueryOnMutatingTable() {
        return true;
    }

    public boolean supportsExistsInSelect() {
        return false;
    }

    public boolean doesReadCommittedCauseWritersToBlockReaders() {
        return false;
    }

    public boolean doesRepeatableReadCauseReadersToBlockWriters() {
        return false;
    }

    public boolean supportsBindAsCallableArgument() {
        return true;
    }

    public boolean supportsTupleCounts() {
        return false;
    }

    public boolean supportsTupleDistinctCounts() {
        return false;
    }

    public MultiTableBulkIdStrategy getDefaultMultiTableBulkIdStrategy() {
        return new GlobalTemporaryTableBulkIdStrategy(new IdTableSupportStandardImpl() {
            public String generateIdTableName(String baseName) {
                String name = super.generateIdTableName(baseName);
                return name.length() > 30 ? name.substring(0, 30) : name;
            }

            public String getCreateIdTableCommand() {
                return "create global temporary table";
            }

            public String getCreateIdTableStatementOptions() {
                return "on commit delete rows";
            }
        }, AfterUseAction.CLEAN);
    }

    public boolean supportsPartitionBy() {
        return true;
    }

    private String join(String seperator, String[] strings) {
        int length = strings.length;
        if (length == 0) {
            return "";
        } else {
            StringBuffer buf = (new StringBuffer(length * strings[0].length())).append(strings[0]);

            for(int i = 1; i < length; ++i) {
                buf.append(seperator).append(strings[i]);
            }

            return buf.toString();
        }
    }
}
