📄 select.java
字号:
/* Copyright (c) 1995-2000, The Hypersonic SQL Group.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the Hypersonic SQL Group nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE HYPERSONIC SQL GROUP,
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* on behalf of the Hypersonic SQL Group.
*
*
* For work added by the HSQL Development Group:
*
* Copyright (c) 2001-2005, The HSQL Development Group
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the HSQL Development Group nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.hsqldb;import org.hsqldb.HsqlNameManager.HsqlName;import org.hsqldb.lib.HashMap;import org.hsqldb.lib.HashSet;import org.hsqldb.lib.HsqlArrayList;import org.hsqldb.lib.Iterator;// fredt@users 20010701 - patch 1.6.1 by hybris// basic implementation of LIMIT n m// fredt@users 20020130 - patch 471710 by fredt - LIMIT rewritten// for SELECT LIMIT n m DISTINCT// fredt@users 20020221 - patch 513005 by sqlbob@users (RMP)// type and logging attributes of sIntotable// fredt@users 20020230 - patch 495938 by johnhobs@users - GROUP BY order// fred@users 20020522 - patch 1.7.0 - aggregate functions with DISTINCT// rougier@users 20020522 - patch 552830 - COUNT(DISTINCT)// fredt@users 20020804 - patch 580347 by dkkopp - view speedup// tony_lai@users 20021020 - patch 1.7.2 - improved aggregates and HAVING// boucherb@users 20030811 - patch 1.7.2 - prepared statement support// fredt@users 20031012 - patch 1.7.2 - better OUTER JOIN implementation// fredt@users 20031012 - patch 1.7.2 - SQL standard ORDER BY with UNION and other set queries// fredt@users 200408xx - patch 1.7.2 - correct evaluation of the precedence of nested UNION and other set query/** * The compiled representation of an SQL SELECT. * * Extended in successive versions of HSQLDB. * * @author Thomas Mueller (Hypersonic SQL Group) * @version 1.8.0 * @since Hypersonic SQL */class Select { boolean isDistinctSelect; boolean isAggregated; private boolean isGrouped; private HashSet groupColumnNames; TableFilter[] tFilter; Expression limitCondition; Expression queryCondition; // null means no condition Expression havingCondition; // null means none Expression[] exprColumns; // 'result', 'group' and 'order' columns int iResultLen; // number of columns that are 'result' int iGroupLen; // number of columns that are 'group' int iHavingLen; // number of columns that are 'group' int iOrderLen; // number of columns that are 'order' int[] sortOrder; int[] sortDirection; boolean sortUnion; // if true, sort the result of the full union HsqlName sIntoTable; // null means not select..into int intoType; Select[] unionArray; // only set in the first Select in a union chain int unionMaxDepth; // max unionDepth in chain Select unionSelect; // null means no union select int unionType; int unionDepth; static final int NOUNION = 0, UNION = 1, UNIONALL = 2, INTERSECT = 3, EXCEPT = 4; private boolean simpleLimit; // true if maxrows can be uses as is Result.ResultMetaData resultMetaData; /** * Experimental. * * Map the column aliases to expressions in order to resolve alias names * in WHERE clauses * */ HashMap getColumnAliases() { HashMap aliasMap = new HashMap(); for (int i = 0; i < iResultLen; i++) { String alias = exprColumns[i].getAlias(); if (alias != null) { aliasMap.put(alias, exprColumns[i]); } } return aliasMap; } /** * Method declaration * * * @throws HsqlException */ void resolve(Session session) throws HsqlException { resolveTables(); resolveTypes(session); setFilterConditions(session); } /** * Method declaration * * * @throws HsqlException */ private void resolveTables() throws HsqlException { // replace the aliases with expressions for (int i = iResultLen; i < exprColumns.length; i++) { if (exprColumns[i].exprType == Expression.COLUMN) { if (exprColumns[i].joinedTableColumnIndex == -1) { exprColumns[i] = exprColumns[i].getExpressionForAlias(exprColumns, iResultLen); } } else { exprColumns[i].replaceAliases(exprColumns, iResultLen); } } if (queryCondition != null) { queryCondition.replaceAliases(exprColumns, iResultLen); } int len = tFilter.length; for (int i = 0; i < len; i++) { resolveTables(tFilter[i]); } } /** * Sets the types of all the expressions that have so far resolved. * * @throws HsqlException */ void resolveTypes(Session session) throws HsqlException { int len = exprColumns.length; for (int i = 0; i < len; i++) { exprColumns[i].resolveTypes(session); } if (queryCondition != null) { queryCondition.resolveTypes(session); } } void resolveTablesUnion(TableFilter f) throws HsqlException { if (unionArray == null) { resolveTables(f); } else { for (int i = 0; i < unionArray.length; i++) { unionArray[i].resolveTables(f); } } } /** * Resolves the tables for all the Expression in the Select object * if it is possible to do so with the given TableFilter. * * @param f * * @throws HsqlException */ void resolveTables(TableFilter f) throws HsqlException { int len = exprColumns.length; for (int i = 0; i < len; i++) { exprColumns[i].resolveTables(f); } if (queryCondition != null) { queryCondition.resolveTables(f); } } private void setFilterConditions(Session session) throws HsqlException { if (queryCondition == null) { return; } for (int i = 0; i < tFilter.length; i++) { tFilter[i].setConditions(session, queryCondition); } } /** * Check all Expression have resolved. Return true or false as a result. * Throw if false and check parameter is true. * * @throws HsqlException */ boolean checkResolved(boolean check) throws HsqlException { boolean result = true; int len = exprColumns.length; for (int i = 0; i < len; i++) { result = result && exprColumns[i].checkResolved(check); } if (queryCondition != null) { result = result && queryCondition.checkResolved(check); } if (havingCondition != null) { result = result && havingCondition.checkResolved(check); } for (int i = 0; i < tFilter.length; i++) { if (tFilter[i].filterIndex == null) { tFilter[i].filterIndex = tFilter[i].filterTable.getPrimaryIndex(); } } return result; } /** * Removes all the TableFilters from the Expressions. * * @throws HsqlException *//* void removeFilters() throws HsqlException { int len = eColumn.length; for (int i = 0; i < len; i++) { eColumn[i].removeFilters(); } if (eCondition != null) { eCondition.removeFilters(); } }*/ /** * Returns a single value result or throws if the result has more than * one row with one value. * * @param type data type * @param session context * @return the single valued result * @throws HsqlException */ Object getValue(Session session, int type) throws HsqlException { resolve(session); Result r = getResult(session, 2); // 2 records are required for test int size = r.getSize(); int len = r.getColumnCount(); if (len == 1) { if (size == 0) { return null; } else if (size == 1) { Object o = r.rRoot.data[0]; return r.metaData.colTypes[0] == type ? o : Column.convertObject( o, type); } else { throw Trace.error(Trace.CARDINALITY_VIOLATION_NO_SUBCLASS); } } HsqlException e = Trace.error(Trace.CARDINALITY_VIOLATION_NO_SUBCLASS); throw new HsqlInternalException(e); } /** * Resolves expressions and pepares thre metadata for the result. */ void prepareResult(Session session) throws HsqlException { resolveAll(session, true); if (iGroupLen > 0) { // has been set in Parser isGrouped = true; groupColumnNames = new HashSet(); for (int i = iResultLen; i < iResultLen + iGroupLen; i++) { exprColumns[i].collectColumnName(groupColumnNames); } } int len = exprColumns.length; resultMetaData = new Result.ResultMetaData(len); Result.ResultMetaData rmd = resultMetaData; // tony_lai@users having int groupByStart = iResultLen; int groupByEnd = groupByStart + iGroupLen; int orderByStart = groupByEnd + iHavingLen; int orderByEnd = orderByStart + iOrderLen; for (int i = 0; i < len; i++) { Expression e = exprColumns[i]; rmd.colTypes[i] = e.getDataType(); rmd.colSizes[i] = e.getColumnSize(); rmd.colScales[i] = e.getColumnScale(); if (e.isAggregate()) { isAggregated = true; } if (i >= groupByStart && i < groupByEnd &&!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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -