Exemple #1
0
 // 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;
 }