📄 select.java
字号:
&&!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(); } } checkAggregateOrGroupByColumns(0, iResultLen); checkAggregateOrGroupByColumns(groupByEnd, orderByStart); checkAggregateOrGroupByColumns(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(), getLimitCount(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() throws HsqlException { if (limitCondition != null) { Integer limit = (Integer) limitCondition.getArg().getValue(null); 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(int rowCount) throws HsqlException { int limitCount = 0; if (limitCondition != null) { Integer limit = (Integer) limitCondition.getArg2().getValue(null); 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(int rowCount) throws HsqlException { int limitStart = getLimitStart(); int limitCount = getLimitCount(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(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(), getLimitCount(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; } if (isDistinctSelect) { throw Trace.error( Trace.INVALID_ORDER_BY_IN_DISTINCT_SELECT, exp); } else { throw Trace.error(Trace.NOT_IN_AGGREGATE_OR_GROUP_BY, 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 if (isDistinctSelect) { return isSimilarIn(exp, 0, iResultLen); } 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; } } return true; }// fredt@users 20030810 - patch 1.7.2 - OUTER JOIN rewrite private Result buildResult(Session session, int limitcount) throws HsqlException { GroupedResult gResult = new GroupedResult(this, resultMetaData); final int len = exprColumns.length; final int filter = tFilter.length;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -