⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 select.java

📁 hsqldb是100%java实现的数据库,是一个开放源代码的JAVA数据库 l 具有标准的SQL语法和JAVA接口 l HSQLDB可以自由使用和分发 l 非常简洁和快速的
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
                    &&!exprColumns[i].canBeInGroupBy()) {
                Trace.error(Trace.INVALID_GROUP_BY, exprColumns[i]);
            }

            if (i >= groupByEnd && i < groupByEnd + iHavingLen
                    &&!exprColumns[i].isConditional()) {
                Trace.error(Trace.INVALID_HAVING, exprColumns[i]);
            }

            if (i >= orderByStart && i < orderByEnd
                    &&!exprColumns[i].canBeInOrderBy()) {
                Trace.error(Trace.INVALID_ORDER_BY, exprColumns[i]);
            }

            if (i < iResultLen) {
                rmd.colLabels[i]     = e.getAlias();
                rmd.isLabelQuoted[i] = e.isAliasQuoted();
                rmd.schemaNames[i]   = e.getTableSchemaName();
                rmd.tableNames[i]    = e.getTableName();
                rmd.colNames[i]      = e.getColumnName();

                if (rmd.isTableColumn(i)) {
                    rmd.colNullable[i] = e.nullability;
                    rmd.isIdentity[i]  = e.isIdentity;
                    rmd.isWritable[i]  = e.isWritable;
                }

                rmd.classNames[i] = e.getValueClassName();
            }
        }

        // selected columns
        checkAggregateOrGroupByColumns(0, iResultLen);

        // having columns
        checkAggregateOrGroupByColumns(groupByEnd, orderByStart);

        // order by columns
        checkAggregateOrGroupByOrderColumns(orderByStart, orderByEnd);        prepareSort();

        simpleLimit = (isDistinctSelect == false && isGrouped == false
                       && unionSelect == null && iOrderLen == 0);
    }

    /**
     * This is called externally only on the first Select in a UNION chain.
     */
    void prepareUnions() throws HsqlException {

        int count = 0;

        for (Select current = this; current != null;
                current = current.unionSelect, count++) {}

        if (count == 1) {
            if (unionDepth != 0) {
                throw Trace.error(Trace.MISSING_CLOSEBRACKET);
            }

            return;
        }

        unionArray = new Select[count];
        count      = 0;

        for (Select current = this; current != null;
                current = current.unionSelect, count++) {
            unionArray[count] = current;
            unionMaxDepth = current.unionDepth > unionMaxDepth
                            ? current.unionDepth
                            : unionMaxDepth;
        }

        if (unionArray[unionArray.length - 1].unionDepth != 0) {
            throw Trace.error(Trace.MISSING_CLOSEBRACKET);
        }
    }

    /**
     * Returns the result of executing this Select.
     *
     * @param maxrows may be 0 to indicate no limit on the number of rows.
     * Positive values limit the size of the result set.
     * @return the result of executing this Select
     * @throws HsqlException if a database access error occurs
     */
    Result getResult(Session session, int maxrows) throws HsqlException {

        Result r;

        if (unionArray == null) {
            r = getSingleResult(session, maxrows);
        } else {
            r = getResultMain(session);

            if (sortUnion) {
                sortResult(session, r);
                r.trimResult(getLimitStart(session),
                             getLimitCount(session, maxrows));
            }
        }

        // fredt - now there is no need for the sort and group columns
        r.setColumnCount(iResultLen);

        return r;
    }

    private Result getResultMain(Session session) throws HsqlException {

        Result[] unionResults = new Result[unionArray.length];

        for (int i = 0; i < unionArray.length; i++) {
            unionResults[i] = unionArray[i].getSingleResult(session,
                    Integer.MAX_VALUE);
        }

        for (int depth = unionMaxDepth; depth >= 0; depth--) {
            for (int pass = 0; pass < 2; pass++) {
                for (int i = 0; i < unionArray.length - 1; i++) {
                    if (unionResults[i] != null
                            && unionArray[i].unionDepth >= depth) {
                        if (pass == 0
                                && unionArray[i].unionType
                                   != Select.INTERSECT) {
                            continue;
                        }

                        if (pass == 1
                                && unionArray[i].unionType
                                   == Select.INTERSECT) {
                            continue;
                        }

                        int nextIndex = i + 1;

                        for (; nextIndex < unionArray.length; nextIndex++) {
                            if (unionResults[nextIndex] != null) {
                                break;
                            }
                        }

                        if (nextIndex == unionArray.length) {
                            break;
                        }

                        unionArray[i].mergeResults(session, unionResults[i],
                                                   unionResults[nextIndex]);

                        unionResults[nextIndex] = unionResults[i];
                        unionResults[i]         = null;
                    }
                }
            }
        }

        return unionResults[unionResults.length - 1];
    }

    /**
     * Merges the second result into the first using the unionMode
     * set operation.
     */
    private void mergeResults(Session session, Result first,
                              Result second) throws HsqlException {

        switch (unionType) {

            case UNION :
                first.append(second);
                first.removeDuplicates(session, iResultLen);
                break;

            case UNIONALL :
                first.append(second);
                break;

            case INTERSECT :
                first.removeDifferent(session, second, iResultLen);
                break;

            case EXCEPT :
                first.removeSecond(session, second, iResultLen);
                break;
        }
    }

    int getLimitStart(Session session) throws HsqlException {

        if (limitCondition != null) {
            Integer limit =
                (Integer) limitCondition.getArg().getValue(session);

            if (limit != null) {
                return limit.intValue();
            }
        }

        return 0;
    }

    /**
     * For SELECT LIMIT n m ....
     * finds cases where the result does not have to be fully built and
     * returns an adjusted rowCount with LIMIT params.
     */
    int getLimitCount(Session session, int rowCount) throws HsqlException {

        int limitCount = 0;

        if (limitCondition != null) {
            Integer limit =
                (Integer) limitCondition.getArg2().getValue(session);

            if (limit != null) {
                limitCount = limit.intValue();
            }
        }

        if (rowCount != 0 && (limitCount == 0 || rowCount < limitCount)) {
            limitCount = rowCount;
        }

        return limitCount;
    }

    /**
     * translate the rowCount into total number of rows needed from query,
     * including any rows skipped at the beginning
     */
    int getMaxRowCount(Session session, int rowCount) throws HsqlException {

        int limitStart = getLimitStart(session);
        int limitCount = getLimitCount(session, rowCount);

        if (!simpleLimit) {
            rowCount = Integer.MAX_VALUE;
        } else {
            if (rowCount == 0) {
                rowCount = limitCount;
            }

            if (rowCount == 0 || rowCount > Integer.MAX_VALUE - limitStart) {
                rowCount = Integer.MAX_VALUE;
            } else {
                rowCount += limitStart;
            }
        }

        return rowCount;
    }

    private Result getSingleResult(Session session,
                                   int rowCount) throws HsqlException {

        if (resultMetaData == null) {
            prepareResult(session);
        }

        Result r = buildResult(session, getMaxRowCount(session, rowCount));

        // the result is perhaps wider (due to group and order by)
        // so use the visible columns to remove duplicates
        if (isDistinctSelect) {
            r.removeDuplicates(session, iResultLen);
        }

        if (!sortUnion) {
            sortResult(session, r);
            r.trimResult(getLimitStart(session),
                         getLimitCount(session, rowCount));
        }

        return r;
    }

    private void prepareSort() {

        if (iOrderLen == 0) {
            return;
        }

        sortOrder     = new int[iOrderLen];
        sortDirection = new int[iOrderLen];

        int startCol = iResultLen + iGroupLen + iHavingLen;

        for (int i = startCol, j = 0; j < iOrderLen; i++, j++) {
            int colindex = i;

            // fredt - when a union, use the visible select columns for sort comparison
            // also whenever a column alias is used
            if (exprColumns[i].joinedTableColumnIndex != -1) {
                colindex = exprColumns[i].joinedTableColumnIndex;
            }

            sortOrder[j]     = colindex;
            sortDirection[j] = exprColumns[i].isDescending() ? -1
                                                             : 1;
        }
    }

    private void sortResult(Session session, Result r) throws HsqlException {

        if (iOrderLen == 0) {
            return;
        }

        r.sortResult(session, sortOrder, sortDirection);
    }

    /**
     * Check result columns for aggregate or group by violation.
     * If any result column is aggregated, then all result columns need to be
     * aggregated, unless it is included in the group by clause.
     */
    private void checkAggregateOrGroupByColumns(int start,
            int end) throws HsqlException {

        if (start < end) {
            HsqlArrayList colExps = new HsqlArrayList();

            for (int i = start; i < end; i++) {
                exprColumns[i].collectInGroupByExpressions(colExps);
            }

            for (int i = 0, size = colExps.size(); i < size; i++) {
                Expression exp = (Expression) colExps.get(i);

                if (inAggregateOrGroupByClause(exp)) {
                    continue;
                }

                throw Trace.error(Trace.NOT_IN_AGGREGATE_OR_GROUP_BY, exp);            }        }    }    private void checkAggregateOrGroupByOrderColumns(int start,            int end) throws HsqlException {        checkAggregateOrGroupByColumns(start, end);        if (start < end && isDistinctSelect) {            HsqlArrayList colExps = new HsqlArrayList();            for (int i = start; i < end; i++) {                exprColumns[i].collectInGroupByExpressions(colExps);            }            for (int i = 0, size = colExps.size(); i < size; i++) {                Expression exp = (Expression) colExps.get(i);                if (isSimilarIn(exp, 0, iResultLen)) {                    continue;                }
                throw Trace.error(Trace.INVALID_ORDER_BY_IN_DISTINCT_SELECT,                                  exp);            }
        }
    }

    /**
     * Check if the given expression is acceptable in a select that may
     * include aggregate function and/or group by clause.
     * <p>
     * The expression is acceptable if:
     * <UL>
     * <LI>The select does not containt any aggregate function;
     * <LI>The expression itself can be included in an aggregate select;
     * <LI>The expression is defined in the group by clause;
     * <LI>All the columns in the expression are defined in the group by clause;
     * </UL)
     */
    private boolean inAggregateOrGroupByClause(Expression exp) {

        if (isGrouped) {
            return isSimilarIn(exp, iResultLen, iResultLen + iGroupLen)
                   || allColumnsAreDefinedIn(exp, groupColumnNames);
        } else if (isAggregated) {
            return exp.canBeInAggregate();
        } else {
            return true;
        }
    }

    /**
     * Check if the given expression is similar to any of the eColumn
     * expressions within the given range.
     */
    private boolean isSimilarIn(Expression exp, int start, int end) {

        for (int i = start; i < end; i++) {
            if (exp.similarTo(exprColumns[i])) {
                return true;
            }
        }

        return false;
    }

    /**
     * Check if all the column names used in the given expression are defined
     * in the given defined column names.
     */
    static boolean allColumnsAreDefinedIn(Expression exp,
                                          HashSet definedColumns) {

        HashSet colNames = new HashSet();

        exp.collectAllColumnNames(colNames);

        if ((colNames.size() > 0) && (definedColumns == null)) {
            return false;
        }

        Iterator i = colNames.iterator();

        while (i.hasNext()) {
            if (!definedColumns.contains(i.next())) {
                return false;
            }
        }

⌨️ 快捷键说明

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