sqlquery.java

来自「数据仓库展示程序」· Java 代码 · 共 874 行 · 第 1/2 页

JAVA
874
字号
    }

    private class ClauseList extends ArrayList {
        private final boolean allowDups;

        ClauseList(final boolean allowDups) {
            this.allowDups = allowDups;
        }


        /**
         * Parameter element is added if either duplicates are allowed or if
         * it has not already been added.
         *
         * @param element
         */
        void add(final String element) {
            if (allowDups || !contains(element)) {
                super.add(element);
            }
        }

        void toBuffer(final StringBuffer buf,
                      final String first,
                      final String sep) {
            Iterator it = iterator();
            boolean firstTime = true;
            while (it.hasNext()) {
                String s = (String) it.next();

                if (firstTime) {
                    buf.append(first);
                    firstTime = false;
                } else {
                    buf.append(sep);
                }

                buf.append(s);
            }
        }
        void print(final PrintWriter pw,
                   final String prefix,
                   final String first,
                   final String sep) {
            String subprefix = prefix + "    ";
            boolean firstTime = true;
            for (Iterator it = iterator(); it.hasNext(); ) {
                String s = (String) it.next();

                if (firstTime) {
                    pw.print(prefix);
                    pw.print(first);
                    firstTime = false;
                } else {
                    pw.print(sep);
                }
                pw.println();
                pw.print(subprefix);
                pw.print(s);
            }
            if (! firstTime) {
                pw.println();
            }
        }
    }

    /**
     * Description of a SQL dialect. It is immutable.
     */
    public static class Dialect {
        private final String quoteIdentifierString;
        private final String productName;
        private final String productVersion;

        Dialect(
                String quoteIdentifierString,
                String productName,
                String productVersion) {
            this.quoteIdentifierString = quoteIdentifierString;
            this.productName = productName;
            this.productVersion = productVersion;
        }

        /**
         * Creates a {@link Dialect} from a {@link DatabaseMetaData}.
         */
        public static Dialect create(final DatabaseMetaData databaseMetaData) {
            String productName;
            try {
                productName = databaseMetaData.getDatabaseProductName();
            } catch (SQLException e1) {
                throw Util.newInternal(e1, "while detecting database product");
            }

            String quoteIdentifierString;
            try {
                quoteIdentifierString =
                        databaseMetaData.getIdentifierQuoteString();
            } catch (SQLException e) {
                throw Util.newInternal(e, "while quoting identifier");
            }

            if ((quoteIdentifierString == null) ||
                    (quoteIdentifierString.trim().length() == 0)) {
                if (productName.toUpperCase().equals("MYSQL")) {
                    // mm.mysql.2.0.4 driver lies. We know better.
                    quoteIdentifierString = "`";
                } else {
                    // Quoting not supported
                    quoteIdentifierString = null;
                }
            }

            String productVersion;
            try {
                productVersion = databaseMetaData.getDatabaseProductVersion();
            } catch (SQLException e11) {
                throw Util.newInternal(e11,
                        "while detecting database product version");
            }

            return new Dialect(
                    quoteIdentifierString,
                    productName,
                    productVersion);
        }

        // -- detect various databases --

        public boolean isAccess() {
            return productName.equals("ACCESS");
        }

        public boolean isDerby() {
            return productName.trim().toUpperCase().equals("APACHE DERBY");
        }

        public boolean isCloudscape() {
            return productName.trim().toUpperCase().equals("DBMS:CLOUDSCAPE");
        }

        public boolean isDB2() {
            // DB2 on NT returns "DB2/NT"
            return productName.startsWith("DB2");
        }

        public boolean isAS400() {
            // DB2/AS400 Product String = "DB2 UDB for AS/400"
            return productName.startsWith("DB2 UDB for AS/400");
        }

        public boolean isOldAS400() {
            if (!isAS400()) {
                return false;
            }
            // TB "04.03.0000 V4R3m0"
            //  this version cannot handle subqueries and is considered "old"
            // DEUKA "05.01.0000 V5R1m0" is ok
            String[] version_release = productVersion.split("\\.", 3);
            /*
            if ( version_release.length > 2 &&
                "04".compareTo(version_release[0]) > 0 ||
                ("04".compareTo(version_release[0]) == 0
                && "03".compareTo(version_release[1]) >= 0) )
                return true;
            */
            // assume, that version <= 04 is "old"
            return ("04".compareTo(version_release[0]) >= 0);
        }

        // Note: its not clear that caching the best name would actually save
        // very much time, so we do not do so.
        private String getBestName() {
            String best;
            if (isOracle()) {
                best = "oracle";
            } else if (isMSSQL()) {
                best = "mssql";
            } else if (isMySQL()) {
                best = "mysql";
            } else if (isAccess()) {
                best = "access";
            } else if (isPostgres()) {
                best = "postgres";
            } else if (isSybase()) {
                best = "sybase";
            } else if (isCloudscape() || isDerby()) {
                best = "derby";
            } else if (isDB2()) {
                best = "db2";
            } else if (isFirebird()) {
                best = "firebird";
            } else {
                best = "generic";
            }
            return best;
        }

        /**
         * Encloses an identifier in quotation marks appropriate for the
         * current SQL dialect. For example,
         * <code>quoteIdentifier("emp")</code> yields a string containing
         * <code>"emp"</code> in Oracle, and a string containing
         * <code>[emp]</code> in Access.
         **/
        public String quoteIdentifier(final String val) {
            int size = val.length() + SINGLE_QUOTE_SIZE;
            StringBuffer buf = new StringBuffer(size);

            quoteIdentifier(val, buf);

            return buf.toString();
        }

        /**
         * This is the implementation of the quoteIdentifier method which quotes the
         * the val parameter (identifier) placing the result in the StringBuffer
         * parameter.
         *
         * @param val identifier to quote (must not be null).
         * @param buf
         */
        public void quoteIdentifier(final String val, final StringBuffer buf) {
            String q = getQuoteIdentifierString();
            if (q == null) {
                // quoting is not supported
                buf.append(val);
                return;
            }
            // if the value is already quoted, do nothing
            //  if not, then check for a dot qualified expression
            //  like "owner.table".
            //  In that case, prefix the single parts separately.
            if (val.startsWith(q) && val.endsWith(q)) {
                // already quoted - nothing to do
                buf.append(val);
                return;
            }

            int k = val.indexOf('.');
            if (k > 0) {
                // qualified
                String val1 = Util.replace(val.substring(0,k), q, q + q);
                String val2 = Util.replace(val.substring(k+1), q, q + q);
                buf.append(q);
                buf.append(val1);
                buf.append(q);
                buf.append(".");
                buf.append(q);
                buf.append(val2);
                buf.append(q);

            } else {
                // not Qualified
                String val2 = Util.replace(val, q, q + q);
                buf.append(q);
                buf.append(val2);
                buf.append(q);
            }
        }

        /**
         * Encloses an identifier in quotation marks appropriate for the
         * current SQL dialect. For example, in Oracle, where the identifiers
         * are quoted using double-quotes,
         * <code>quoteIdentifier("schema","table")</code> yields a string
         * containing <code>"schema"."table"</code>.
         *
         * @param qual Qualifier. If it is not null,
         *             <code>"<em>qual</em>".</code> is prepended.
         * @param name Name to be quoted.
         **/
        public String quoteIdentifier(final String qual, final String name) {
            // We know if the qalifier is null, then only the name is going
            // to be quoted.
            int size = name.length()
                + ((qual == null)
                    ? SINGLE_QUOTE_SIZE
                    : (qual.length() + DOUBLE_QUOTE_SIZE));
            StringBuffer buf = new StringBuffer(size);

            quoteIdentifier(qual, name, buf);

            return buf.toString();
        }

        /**
         * This implements the quoting of a qualifier and name allowing one to
         * pass in a StringBuffer thus saving the allocation and copying.
         *
         * @param qual optional qualifier to be quoted.
         * @param name name to be quoted (must not be null).
         * @param buf
         */
        public void quoteIdentifier(final String qual,
                                    final String name,
                                    final StringBuffer buf) {
            if (qual == null) {
                quoteIdentifier(name, buf);

            } else {
                Util.assertTrue(
                    (qual.length() != 0),
                    "qual should probably be null, not empty");

                quoteIdentifier(qual, buf);
                buf.append('.');
                quoteIdentifier(name, buf);
            }
        }

        public String getQuoteIdentifierString() {
            if (isDB2()) {
                return "";
            } else {
                return quoteIdentifierString;
            }
        }

        /**
         * Converts a string into a SQL single-quoted string.
         * For example, <code>quoteString("Can't")</code> returns
         * <code>'Can''t'</code>.
         */
        public String quoteString(String s) {
            return Util.singleQuoteString(s);
        }

        /**
         * Returns whether the underlying database is Firebird.
         */
        public boolean isFirebird() {
            return productName.toUpperCase().indexOf("FIREBIRD") >= 0;
        }

        /**
         * Returns whether the underlying database is Informix.
         */
        public boolean isInformix() {
            return productName.startsWith("Informix");
        }

        /**
         * Returns whether the underlying database is Microsoft SQL Server.
         */
        public boolean isMSSQL() {
            return productName.toUpperCase().indexOf("SQL SERVER") >= 0;
        }
        /**
         * Returns whether the underlying database is Oracle.
         */
        public boolean isOracle() {
            return productName.equals("Oracle");
        }
        /**
         * Returns whether the underlying database is Postgres.
         */
        public boolean isPostgres() {
            return productName.toUpperCase().indexOf("POSTGRE") >= 0;
        }
        /**
         * Returns whether the underlying database is MySQL.
         */
        public boolean isMySQL() {
            return productName.toUpperCase().equals("MYSQL");
        }
        /**
         * Returns whether the underlying database is Sybase.
         */
        public boolean isSybase() {
            return productName.toUpperCase().indexOf("SYBASE") >= 0;
        }

        // -- behaviors --
        protected boolean requiresAliasForFromItems() {
            return isPostgres();
        }

        /**
         * Returns whether the SQL dialect allows "AS" in the FROM clause.
         * If so, "SELECT * FROM t AS alias" is a valid query.
         */
        protected boolean allowsAs() {
            return !isOracle() && !isSybase() && !isFirebird();
        }

        /**
         * Whether "select * from (select * from t)" is OK.
         */
        public boolean allowsFromQuery() {
            // older versions of AS400 do not allow FROM subqueries
            return !isMySQL() && !isOldAS400() && !isInformix() && !isSybase();
        }

        /**
         * Whether "select count(distinct x, y) from t" is OK.
         */
        public boolean allowsCompoundCountDistinct() {
            return isMySQL();
        }

        /**
         * Whether "select count(distinct x) from t" is OK.
         */
        public boolean allowsCountDistinct() {
            return !isAccess();
        }

        /**
         * Chooses the variant within an array of {@link
         * mondrian.olap.MondrianDef.SQL} which best matches the current SQL
         * dialect.
         */
        public String chooseQuery(final MondrianDef.SQL[] sqls) {
            String best = getBestName();

            String generic = null;
            for (int i = 0; i < sqls.length; i++) {
                MondrianDef.SQL sql = sqls[i];
                if (sql.dialect.equals(best)) {
                    return sql.cdata;
                }
                if (sql.dialect.equals("generic")) {
                    generic = sql.cdata;
                }
            }
            if (generic == null) {
                throw Util.newError("View has no 'generic' variant");
            }
            return generic;
        }

    }
}

// End SqlQuery.java

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?