Example #1
0
 private Value[] convert(Value[] values, int columnCount) {
   for (int i = 0; i < columnCount; i++) {
     Expression e = expressions.get(i);
     values[i] = values[i].convertTo(e.getType());
   }
   return values;
 }
Example #2
0
 @Override
 public void prepare() {
   if (columns == null) {
     // 如INSERT INTO InsertTest DEFAULT VALUES
     if (list.size() > 0 && list.get(0).length == 0) {
       // special case where table is used as a sequence
       columns = new Column[0];
     } else { // 如INSERT INTO InsertTest(SELECT * FROM tmpSelectTest)
       columns = table.getColumns();
     }
   }
   if (list.size() > 0) {
     for (Expression[] expr : list) {
       if (expr.length != columns.length) {
         throw DbException.get(ErrorCode.COLUMN_COUNT_DOES_NOT_MATCH);
       }
       for (int i = 0, len = expr.length; i < len; i++) {
         Expression e = expr[i];
         if (e != null) {
           e = e.optimize(session);
           if (e instanceof Parameter) {
             Parameter p = (Parameter) e;
             p.setColumn(columns[i]);
           }
           expr[i] = e;
         }
       }
     }
   } else {
     query.prepare();
     if (query.getColumnCount() != columns.length) {
       throw DbException.get(ErrorCode.COLUMN_COUNT_DOES_NOT_MATCH);
     }
   }
 }
Example #3
0
 public boolean isEverything(ExpressionVisitor visitor) {
   switch (visitor.getType()) {
     case ExpressionVisitor.DETERMINISTIC:
       {
         if (isForUpdate) {
           return false;
         }
         for (int i = 0, size = filters.size(); i < size; i++) {
           TableFilter f = filters.get(i);
           if (!f.getTable().isDeterministic()) {
             return false;
           }
         }
         break;
       }
     case ExpressionVisitor.SET_MAX_DATA_MODIFICATION_ID:
       {
         for (int i = 0, size = filters.size(); i < size; i++) {
           TableFilter f = filters.get(i);
           long m = f.getTable().getMaxDataModificationId();
           visitor.addDataModificationId(m);
         }
         break;
       }
     case ExpressionVisitor.EVALUATABLE:
       {
         if (!session.getDatabase().getSettings().optimizeEvaluatableSubqueries) {
           return false;
         }
         break;
       }
     case ExpressionVisitor.GET_DEPENDENCIES:
       {
         for (int i = 0, size = filters.size(); i < size; i++) {
           TableFilter f = filters.get(i);
           Table table = f.getTable();
           visitor.addDependency(table);
           table.addDependencies(visitor.getDependencies());
         }
         break;
       }
     default:
   }
   ExpressionVisitor v2 = visitor.incrementQueryLevel(1);
   boolean result = true;
   for (int i = 0, size = expressions.size(); i < size; i++) {
     Expression e = expressions.get(i);
     if (!e.isEverything(v2)) {
       result = false;
       break;
     }
   }
   if (result && condition != null && !condition.isEverything(v2)) {
     result = false;
   }
   if (result && having != null && !having.isEverything(v2)) {
     result = false;
   }
   return result;
 }
Example #4
0
 private int insertRows() {
   session.getUser().checkRight(table, Right.INSERT);
   setCurrentRowNumber(0);
   table.fire(session, Trigger.INSERT, true);
   rowNumber = 0;
   int listSize = list.size();
   if (listSize > 0) {
     int columnLen = columns.length;
     for (int x = 0; x < listSize; x++) {
       Row newRow = table.getTemplateRow(); // newRow的长度是全表字段的个数是,会>=columns的长度
       Expression[] expr = list.get(x);
       setCurrentRowNumber(x + 1);
       for (int i = 0; i < columnLen; i++) {
         Column c = columns[i];
         int index = c.getColumnId(); // 从0开始
         Expression e = expr[i];
         if (e != null) {
           // e can be null (DEFAULT)
           e = e.optimize(session);
           try {
             Value v = c.convert(e.getValue(session));
             newRow.setValue(index, v);
           } catch (DbException ex) {
             throw setRow(ex, x, getSQL(expr));
           }
         }
       }
       rowNumber++;
       table.validateConvertUpdateSequence(session, newRow);
       boolean done = table.fireBeforeRow(session, null, newRow); // INSTEAD OF触发器会返回true
       if (!done) {
         // 直到事务commit或rollback时才解琐,见org.h2.engine.Session.unlockAll()
         table.lock(session, true, false);
         table.addRow(session, newRow);
         // 在org.h2.index.PageDataIndex.addTry(Session, Row)中事先记了一次PageLog
         // 也就是org.h2.store.PageStore.logAddOrRemoveRow(Session, int, Row, boolean)
         // 这里又记了一次UndoLog
         // UndoLog在org.h2.engine.Session.commit(boolean)时就清除了
         session.log(table, UndoLogRecord.INSERT, newRow);
         table.fireAfterRow(session, null, newRow, false);
       }
     }
   } else {
     table.lock(session, true, false);
     // 这种方式主要是避免循环两次,因为query内部己循环一次了,得到记录后像else中的非insertFromSelect一样,还要循环一次
     if (insertFromSelect) {
       query.query(0, this); // 每遍历一行会回调下面的addRow方法
     } else {
       ResultInterface rows = query.query(0);
       while (rows.next()) {
         Value[] r = rows.currentRow();
         addRow(r);
       }
       rows.close();
     }
   }
   table.fire(session, Trigger.INSERT, false);
   return rowNumber;
 }
Example #5
0
 private void queryQuick(int columnCount, ResultTarget result) {
   Value[] row = new Value[columnCount];
   for (int i = 0; i < columnCount; i++) {
     Expression expr = expressions.get(i);
     row[i] = expr.getValue(session);
   }
   result.addRow(row);
 }
Example #6
0
 public void setEvaluatable(TableFilter tableFilter, boolean b) {
   for (Expression e : expressions) {
     e.setEvaluatable(tableFilter, b);
   }
   if (condition != null) {
     condition.setEvaluatable(tableFilter, b);
   }
 }
 @Override
 public String getSQL() {
   String sql = NAME + "(" + min.getSQL() + ", " + max.getSQL();
   if (step != null) {
     sql += ", " + step.getSQL();
   }
   return sql + ")";
 }
Example #8
0
 public void mapColumns(ColumnResolver resolver, int level) {
   for (Expression e : expressions) {
     e.mapColumns(resolver, level);
   }
   if (condition != null) {
     condition.mapColumns(resolver, level);
   }
 }
 private void optimize(Session s) {
   if (!optimized) {
     min = min.optimize(s);
     max = max.optimize(s);
     if (step != null) {
       step = step.optimize(s);
     }
     optimized = true;
   }
 }
 private void checkDefaultReferencesTable(Expression defaultExpression) {
   if (defaultExpression == null) {
     return;
   }
   HashSet<DbObject> dependencies = New.hashSet();
   ExpressionVisitor visitor = ExpressionVisitor.getDependenciesVisitor(dependencies);
   defaultExpression.isEverything(visitor);
   if (dependencies.contains(table)) {
     throw DbException.get(ErrorCode.COLUMN_IS_REFERENCED_1, defaultExpression.getSQL());
   }
 }
Example #11
0
 public void updateAggregate(Session s) {
   for (Expression e : expressions) {
     e.updateAggregate(s);
   }
   if (condition != null) {
     condition.updateAggregate(s);
   }
   if (having != null) {
     having.updateAggregate(s);
   }
 }
Example #12
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();
 }
Example #13
0
 @Override
 public String getPlanSQL() {
   StringBuilder buff = new StringBuilder();
   buff.append("DELETE ");
   buff.append("FROM ").append(tableFilter.getPlanSQL(false));
   if (condition != null) {
     buff.append("\nWHERE ").append(StringUtils.unEnclose(condition.getSQL()));
   }
   if (limitExpr != null) {
     buff.append("\nLIMIT (").append(StringUtils.unEnclose(limitExpr.getSQL())).append(')');
   }
   return buff.toString();
 }
 SelectListColumnResolver(Select select) {
   this.select = select;
   int columnCount = select.getColumnCount();
   columns = new Column[columnCount];
   expressions = new Expression[columnCount];
   ArrayList<Expression> columnList = select.getExpressions();
   for (int i = 0; i < columnCount; i++) {
     Expression expr = columnList.get(i);
     Column column = new Column(expr.getAlias(), Value.NULL);
     column.setTable(null, i);
     columns[i] = column;
     expressions[i] = expr.getNonAliasExpression();
   }
 }
Example #15
0
  private void expandColumnList() {
    Database db = session.getDatabase();

    // the expressions may change within the loop
    for (int i = 0; i < expressions.size(); i++) {
      Expression expr = expressions.get(i);
      if (!expr.isWildcard()) {
        continue;
      }
      String schemaName = expr.getSchemaName();
      String tableAlias = expr.getTableAlias();
      if (tableAlias == null) {
        int temp = i;
        expressions.remove(i);
        for (TableFilter filter : filters) {
          Wildcard c2 =
              new Wildcard(filter.getTable().getSchema().getName(), filter.getTableAlias());
          expressions.add(i++, c2);
        }
        i = temp - 1;
      } else {
        TableFilter filter = null;
        for (TableFilter f : filters) {
          if (db.equalsIdentifiers(tableAlias, f.getTableAlias())) {
            if (schemaName == null || db.equalsIdentifiers(schemaName, f.getSchemaName())) {
              filter = f;
              break;
            }
          }
        }
        if (filter == null) {
          throw DbException.get(ErrorCode.TABLE_OR_VIEW_NOT_FOUND_1, tableAlias);
        }
        Table t = filter.getTable();
        String alias = filter.getTableAlias();
        expressions.remove(i);
        Column[] columns = t.getColumns();
        for (Column c : columns) {
          if (filter.isNaturalJoinColumn(c)) {
            continue;
          }
          ExpressionColumn ec =
              new ExpressionColumn(session.getDatabase(), null, alias, c.getName());
          expressions.add(i++, ec);
        }
        i--;
      }
    }
  }
Example #16
0
 private void setEvaluatableRecursive(TableFilter f) {
   for (; f != null; f = f.getJoin()) {
     f.setEvaluatable(f, true);
     if (condition != null) {
       condition.setEvaluatable(f, true);
     }
     TableFilter n = f.getNestedJoin();
     if (n != null) {
       setEvaluatableRecursive(n);
     }
     Expression on = f.getJoinCondition();
     if (on != null) {
       if (!on.isEverything(ExpressionVisitor.EVALUATABLE_VISITOR)) {
         if (session.getDatabase().getSettings().nestedJoins) {
           // need to check that all added are bound to a table
           on = on.optimize(session);
           if (!f.isJoinOuter() && !f.isJoinOuterIndirect()) {
             f.removeJoinCondition();
             addCondition(on);
           }
         } else {
           if (f.isJoinOuter()) {
             // this will check if all columns exist - it may or may not throw an exception
             on = on.optimize(session);
             // it is not supported even if the columns exist
             throw DbException.get(ErrorCode.UNSUPPORTED_OUTER_JOIN_CONDITION_1, on.getSQL());
           }
           f.removeJoinCondition();
           // need to check that all added are bound to a table
           on = on.optimize(session);
           addCondition(on);
         }
       }
     }
     on = f.getFilterCondition();
     if (on != null) {
       if (!on.isEverything(ExpressionVisitor.EVALUATABLE_VISITOR)) {
         f.removeFilterCondition();
         addCondition(on);
       }
     }
     // this is only important for subqueries, so they know
     // the result columns are evaluatable
     for (Expression e : expressions) {
       e.setEvaluatable(f, true);
     }
   }
 }
 /**
  * Get the increment.
  *
  * @param session the session
  * @return the increment (1 by default)
  */
 public long getStep(Session session) {
   optimize(session);
   if (step == null) {
     return 1;
   }
   return step.getValue(session).getLong();
 }
Example #18
0
 private void addGroupSortedRow(Value[] keyValues, int columnCount, ResultTarget result) {
   Value[] row = new Value[columnCount];
   for (int j = 0; groupIndex != null && j < groupIndex.length; j++) {
     row[groupIndex[j]] = keyValues[j];
   }
   for (int j = 0; j < columnCount; j++) {
     if (groupByExpression != null && groupByExpression[j]) {
       continue;
     }
     Expression expr = expressions.get(j);
     row[j] = expr.getValue(session);
   }
   if (isHavingNullOrFalse(row)) {
     return;
   }
   row = keepOnlyDistinct(row, columnCount);
   result.addRow(row);
 }
Example #19
0
 public int update() throws SQLException {
   session.commit(true);
   session.getUser().checkAdmin();
   Database db = session.getDatabase();
   if (getSchema().findConstant(constantName) != null) {
     if (ifNotExists) {
       return 0;
     }
     throw Message.getSQLException(ErrorCode.CONSTANT_ALREADY_EXISTS_1, constantName);
   }
   int id = getObjectId(false, true);
   Constant constant = new Constant(getSchema(), id, constantName);
   expression = expression.optimize(session);
   Value value = expression.getValue(session);
   constant.setValue(value);
   db.addSchemaObject(session, constant);
   return 0;
 }
Example #20
0
 /**
  * Get the sample size, if set.
  *
  * @param session the session
  * @return the sample size
  */
 int getSampleSizeValue(Session session) {
   if (sampleSizeExpr == null) {
     return 0;
   }
   Value v = sampleSizeExpr.optimize(session).getValue(session);
   if (v == ValueNull.INSTANCE) {
     return 0;
   }
   return v.getInt();
 }
Example #21
0
 private void queryFlat(int columnCount, ResultTarget result, long limitRows) {
   // limitRows must be long, otherwise we get an int overflow
   // if limitRows is at or near Integer.MAX_VALUE
   // limitRows is never 0 here
   if (limitRows > 0 && offsetExpr != null) {
     int offset = offsetExpr.getValue(session).getInt();
     if (offset > 0) {
       limitRows += offset;
     }
   }
   int rowNumber = 0;
   setCurrentRowNumber(0);
   ArrayList<Row> forUpdateRows = null;
   if (isForUpdateMvcc) {
     forUpdateRows = New.arrayList();
   }
   while (topTableFilter.next()) {
     setCurrentRowNumber(rowNumber + 1);
     if (condition == null || Boolean.TRUE.equals(condition.getBooleanValue(session))) {
       Value[] row = new Value[columnCount];
       for (int i = 0; i < columnCount; i++) {
         Expression expr = expressions.get(i);
         row[i] = expr.getValue(session);
       }
       if (isForUpdateMvcc) {
         topTableFilter.lockRowAdd(forUpdateRows);
       }
       result.addRow(row);
       rowNumber++;
       if ((sort == null || sortUsingIndex)
           && limitRows > 0
           && result.getRowCount() >= limitRows) {
         break;
       }
       if (sampleSize > 0 && rowNumber >= sampleSize) {
         break;
       }
     }
   }
   if (isForUpdateMvcc) {
     topTableFilter.lockRows(forUpdateRows);
   }
 }
Example #22
0
 @Override
 public String getPlanSQL() {
   StatementBuilder buff = new StatementBuilder("INSERT INTO ");
   buff.append(table.getSQL()).append('(');
   for (Column c : columns) {
     buff.appendExceptFirst(", ");
     buff.append(c.getSQL());
   }
   buff.append(")\n");
   if (insertFromSelect) {
     buff.append("DIRECT ");
   }
   if (sortedInsertMode) {
     buff.append("SORTED ");
   }
   if (list.size() > 0) {
     buff.append("VALUES ");
     int row = 0;
     if (list.size() > 1) {
       buff.append('\n');
     }
     for (Expression[] expr : list) {
       if (row++ > 0) {
         buff.append(",\n");
       }
       buff.append('(');
       buff.resetCount();
       for (Expression e : expr) {
         buff.appendExceptFirst(", ");
         if (e == null) {
           buff.append("DEFAULT");
         } else {
           buff.append(e.getSQL());
         }
       }
       buff.append(')');
     }
   } else {
     buff.append(query.getPlanSQL());
   }
   return buff.toString();
 }
Example #23
0
 public void addGlobalCondition(Parameter param, int columnId, int comparisonType) {
   addParameter(param);
   Expression comp;
   Expression col = expressions.get(columnId);
   col = col.getNonAliasExpression();
   if (col.isEverything(ExpressionVisitor.QUERY_COMPARABLE_VISITOR)) {
     comp = new Comparison(session, comparisonType, col, param);
   } else {
     // this condition will always evaluate to true, but need to
     // add the parameter, so it can be set later
     comp = new Comparison(session, Comparison.EQUAL_NULL_SAFE, param, param);
   }
   comp = comp.optimize(session);
   boolean addToCondition = true;
   if (isGroupQuery) {
     addToCondition = false;
     for (int i = 0; groupIndex != null && i < groupIndex.length; i++) {
       if (groupIndex[i] == columnId) {
         addToCondition = true;
         break;
       }
     }
     if (!addToCondition) {
       if (havingIndex >= 0) {
         having = expressions.get(havingIndex);
       }
       if (having == null) {
         having = comp;
       } else {
         having = new ConditionAndOr(ConditionAndOr.AND, having, comp);
       }
     }
   }
   if (addToCondition) {
     if (condition == null) {
       condition = comp;
     } else {
       condition = new ConditionAndOr(ConditionAndOr.AND, condition, comp);
     }
   }
 }
 private void generateColumnsFromQuery() {
   int columnCount = asQuery.getColumnCount();
   ArrayList<Expression> expressions = asQuery.getExpressions();
   for (int i = 0; i < columnCount; i++) {
     Expression expr = expressions.get(i);
     int type = expr.getType();
     String name = expr.getAlias();
     long precision = expr.getPrecision();
     int displaySize = expr.getDisplaySize();
     DataType dt = DataType.getDataType(type);
     if (precision > 0
         && (dt.defaultPrecision == 0
             || (dt.defaultPrecision > precision && dt.defaultPrecision < Byte.MAX_VALUE))) {
       // dont' set precision to MAX_VALUE if this is the default
       precision = dt.defaultPrecision;
     }
     int scale = expr.getScale();
     if (scale > 0
         && (dt.defaultScale == 0 || (dt.defaultScale > scale && dt.defaultScale < precision))) {
       scale = dt.defaultScale;
     }
     if (scale > precision) {
       precision = scale;
     }
     Column col = new Column(name, type, precision, scale, displaySize);
     addColumn(col);
   }
 }
Example #25
0
 /**
  * Create a {@link SortOrder} object given the list of {@link SelectOrderBy} objects. The
  * expression list is extended if necessary.
  *
  * @param orderList a list of {@link SelectOrderBy} elements
  * @param expressionCount the number of columns in the query
  * @return the {@link SortOrder} object
  */
 public SortOrder prepareOrder(ArrayList<SelectOrderBy> orderList, int expressionCount) {
   int size = orderList.size();
   int[] index = new int[size];
   int[] sortType = new int[size];
   for (int i = 0; i < size; i++) {
     SelectOrderBy o = orderList.get(i);
     int idx;
     boolean reverse = false;
     Expression expr = o.columnIndexExpr;
     Value v = expr.getValue(null);
     if (v == ValueNull.INSTANCE) {
       // parameter not yet set - order by first column
       idx = 0;
     } else {
       idx = v.getInt();
       if (idx < 0) {
         reverse = true;
         idx = -idx;
       }
       idx -= 1;
       if (idx < 0 || idx >= expressionCount) {
         throw DbException.get(ErrorCode.ORDER_BY_NOT_IN_RESULT, "" + (idx + 1));
       }
     }
     index[i] = idx;
     boolean desc = o.descending;
     if (reverse) {
       desc = !desc;
     }
     int type = desc ? SortOrder.DESCENDING : SortOrder.ASCENDING;
     if (o.nullsFirst) {
       type += SortOrder.NULLS_FIRST;
     } else if (o.nullsLast) {
       type += SortOrder.NULLS_LAST;
     }
     sortType[i] = type;
   }
   return new SortOrder(session.getDatabase(), index, sortType, orderList);
 }
Example #26
0
  private void queryGroupSorted(int columnCount, ResultTarget result) {
    int rowNumber = 0;
    setCurrentRowNumber(0);
    Value[] previousKeyValues = null;
    while (topTableFilter.next()) {
      setCurrentRowNumber(rowNumber + 1);
      if (condition == null || Boolean.TRUE.equals(condition.getBooleanValue(session))) {
        rowNumber++;
        Value[] keyValues = new Value[groupIndex.length];
        // update group
        for (int i = 0; i < groupIndex.length; i++) {
          int idx = groupIndex[i];
          Expression expr = expressions.get(idx);
          keyValues[i] = expr.getValue(session);
        }

        if (previousKeyValues == null) {
          previousKeyValues = keyValues;
          currentGroup = New.hashMap();
        } else if (!Arrays.equals(previousKeyValues, keyValues)) {
          addGroupSortedRow(previousKeyValues, columnCount, result);
          previousKeyValues = keyValues;
          currentGroup = New.hashMap();
        }
        currentGroupRowId++;

        for (int i = 0; i < columnCount; i++) {
          if (groupByExpression == null || !groupByExpression[i]) {
            Expression expr = expressions.get(i);
            expr.updateAggregate(session);
          }
        }
      }
    }
    if (previousKeyValues != null) {
      addGroupSortedRow(previousKeyValues, columnCount, result);
    }
  }
Example #27
0
 private void initColumnsAndTables(Session session) {
   Column[] cols;
   removeViewFromTables();
   try {
     Query query = recompileQuery(session);
     tables = New.arrayList(query.getTables());
     ArrayList<Expression> expressions = query.getExpressions();
     ArrayList<Column> list = New.arrayList();
     for (int i = 0; i < query.getColumnCount(); i++) {
       Expression expr = expressions.get(i);
       String name = null;
       if (columnNames != null && columnNames.length > i) {
         name = columnNames[i];
       }
       if (name == null) {
         name = expr.getAlias();
       }
       int type = expr.getType();
       long precision = expr.getPrecision();
       int scale = expr.getScale();
       int displaySize = expr.getDisplaySize();
       Column col = new Column(name, type, precision, scale, displaySize);
       col.setTable(this, i);
       list.add(col);
     }
     cols = new Column[list.size()];
     list.toArray(cols);
     createException = null;
     viewQuery = query;
   } catch (DbException e) {
     createException = e;
     // if it can't be compiled, then it's a 'zero column table'
     // this avoids problems when creating the view when opening the
     // database
     tables = New.arrayList();
     cols = new Column[0];
     if (recursive && columnNames != null) {
       cols = new Column[columnNames.length];
       for (int i = 0; i < columnNames.length; i++) {
         cols[i] = new Column(columnNames[i], Value.STRING);
       }
       index.setRecursive(true);
       createException = null;
     }
   }
   setColumns(cols);
   if (getId() != 0) {
     addViewToTables();
   }
 }
Example #28
0
 @Override
 public int update() {
   tableFilter.startQuery(session);
   tableFilter.reset();
   Table table = tableFilter.getTable();
   session.getUser().checkRight(table, Right.DELETE);
   table.fire(session, Trigger.DELETE, true);
   // 直到事务commit或rollback时才解琐,见org.h2.engine.Session.unlockAll()
   table.lock(session, true, false);
   RowList rows = new RowList(session);
   int limitRows = -1;
   if (limitExpr != null) {
     Value v = limitExpr.getValue(session);
     if (v != ValueNull.INSTANCE) {
       limitRows = v.getInt();
     }
   }
   try {
     setCurrentRowNumber(0);
     int count = 0;
     // 比如delete from DeleteTest limit 0,
     // 此时limitRows为0,不删除任何行
     while (limitRows != 0 && tableFilter.next()) {
       setCurrentRowNumber(rows.size() + 1);
       // condition.getBooleanValue(session)内部会取当前行与之比较,
       // 比如,如果是ExpressionColumn,那么就由它对应的列,取得列id,
       // 然后在从当前行中按列id取当前行value数组中对应元素
       if (condition == null || Boolean.TRUE.equals(condition.getBooleanValue(session))) {
         Row row = tableFilter.get();
         boolean done = false;
         if (table.fireRow()) {
           done = table.fireBeforeRow(session, row, null);
         }
         if (!done) {
           rows.add(row);
         }
         count++;
         if (limitRows >= 0 && count >= limitRows) {
           break;
         }
       }
     }
     int rowScanCount = 0;
     for (rows.reset(); rows.hasNext(); ) {
       if ((++rowScanCount & 127) == 0) {
         checkCanceled();
       }
       Row row = rows.next();
       table.removeRow(session, row);
       session.log(table, UndoLogRecord.DELETE, row);
     }
     if (table.fireRow()) {
       for (rows.reset(); rows.hasNext(); ) {
         Row row = rows.next();
         table.fireAfterRow(session, row, null, false);
       }
     }
     table.fire(session, Trigger.DELETE, false);
     return count;
   } finally {
     rows.close();
   }
 }
 /**
  * Calculate and get the end value of this range.
  *
  * @param session the session
  * @return the end value
  */
 public long getMax(Session session) {
   optimize(session);
   return max.getValue(session).getLong();
 }
 /**
  * Calculate and get the start value of this range.
  *
  * @param session the session
  * @return the start value
  */
 public long getMin(Session session) {
   optimize(session);
   return min.getValue(session).getLong();
 }