// limitExpr在org.h2.command.Parser.parseDelete()中调用过optimize了,所以在这里不用再调用 // 因为limitExpr不会涉及到列,所以也不需要调用mapColumns @Override public void prepare() { if (condition != null) { condition.mapColumns(tableFilter, 0); condition = condition.optimize(session); condition.createIndexConditions(session, tableFilter); } // 为什么不能像mapColumns把level设为0,因为getBestPlanItem内部会把level当被除数,所以不行。 PlanItem item = tableFilter.getBestPlanItem(session, 1); tableFilter.setPlanItem(item); tableFilter.prepare(); }
public void prepare() { if (isPrepared) { // sometimes a subquery is prepared twice (CREATE TABLE AS SELECT) return; } if (SysProperties.CHECK && !checkInit) { DbException.throwInternalError("not initialized"); } if (orderList != null) { sort = prepareOrder(orderList, expressions.size()); orderList = null; } for (int i = 0; i < expressions.size(); i++) { Expression e = expressions.get(i); expressions.set(i, e.optimize(session)); } if (condition != null) { condition = condition.optimize(session); for (TableFilter f : filters) { // outer joins: must not add index conditions such as // "c is null" - example: // create table parent(p int primary key) as select 1; // create table child(c int primary key, pc int); // insert into child values(2, 1); // select p, c from parent // left outer join child on p = pc where c is null; if (!f.isJoinOuter() && !f.isJoinOuterIndirect()) { condition.createIndexConditions(session, f); } } } if (isGroupQuery && groupIndex == null && havingIndex < 0 && filters.size() == 1) { if (condition == null) { Table t = filters.get(0).getTable(); ExpressionVisitor optimizable = ExpressionVisitor.getOptimizableVisitor(t); isQuickAggregateQuery = isEverything(optimizable); } } cost = preparePlan(); if (distinct && session.getDatabase().getSettings().optimizeDistinct && !isGroupQuery && filters.size() == 1 && expressions.size() == 1 && condition == null) { Expression expr = expressions.get(0); expr = expr.getNonAliasExpression(); if (expr instanceof ExpressionColumn) { Column column = ((ExpressionColumn) expr).getColumn(); int selectivity = column.getSelectivity(); Index columnIndex = topTableFilter.getTable().getIndexForColumn(column); if (columnIndex != null && selectivity != Constants.SELECTIVITY_DEFAULT && selectivity < 20) { // the first column must be ascending boolean ascending = columnIndex.getIndexColumns()[0].sortType == SortOrder.ASCENDING; Index current = topTableFilter.getIndex(); // if another index is faster if (columnIndex.canFindNext() && ascending && (current == null || current.getIndexType().isScan() || columnIndex == current)) { IndexType type = columnIndex.getIndexType(); // hash indexes don't work, and unique single column indexes don't work if (!type.isHash() && (!type.isUnique() || columnIndex.getColumns().length > 1)) { topTableFilter.setIndex(columnIndex); isDistinctQuery = true; } } } } } if (sort != null && !isQuickAggregateQuery && !isGroupQuery) { Index index = getSortIndex(); if (index != null) { Index current = topTableFilter.getIndex(); if (current.getIndexType().isScan() || current == index) { topTableFilter.setIndex(index); if (!topTableFilter.hasInComparisons()) { // in(select ...) and in(1,2,3) my return the key in another order sortUsingIndex = true; } } else if (index.getIndexColumns().length >= current.getIndexColumns().length) { IndexColumn[] sortColumns = index.getIndexColumns(); IndexColumn[] currentColumns = current.getIndexColumns(); boolean swapIndex = false; for (int i = 0; i < currentColumns.length; i++) { if (sortColumns[i].column != currentColumns[i].column) { swapIndex = false; break; } if (sortColumns[i].sortType != currentColumns[i].sortType) { swapIndex = true; } } if (swapIndex) { topTableFilter.setIndex(index); sortUsingIndex = true; } } } } if (!isQuickAggregateQuery && isGroupQuery && getGroupByExpressionCount() > 0) { Index index = getGroupSortedIndex(); Index current = topTableFilter.getIndex(); if (index != null && (current.getIndexType().isScan() || current == index)) { topTableFilter.setIndex(index); isGroupSortedQuery = true; } } expressionArray = new Expression[expressions.size()]; expressions.toArray(expressionArray); isPrepared = true; }