提交 24b4a0b0 authored 作者: Noel Grandin's avatar Noel Grandin

Merge remote-tracking branch 'upstream/master' into testing_pagestore

/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.dml;
import java.util.ArrayList;
import java.util.HashMap;
import org.h2.expression.ExpressionVisitor;
import org.h2.table.Column;
import org.h2.table.Table;
import org.h2.table.TableFilter;
/**
* This information is expensive to compute for large queries, so do so
* on-demand. Also store the information pre-mapped by table to avoid expensive
* traversal.
*/
public class AllColumnsForPlan {
private final TableFilter[] filters;
private HashMap<Table, ArrayList<Column>> map;
public AllColumnsForPlan(TableFilter[] filters) {
this.filters = filters;
}
/** Called by ExpressionVisitor. */
public void add(Column newCol) {
ArrayList<Column> cols = map.get(newCol.getTable());
if (cols == null) {
cols = new ArrayList<>();
map.put(newCol.getTable(), cols);
}
if (!cols.contains(newCol))
cols.add(newCol);
}
public ArrayList<Column> get(Table table) {
if (map == null) {
map = new HashMap<>();
ExpressionVisitor.allColumnsForTableFilters(filters, this);
}
return map.get(table);
}
}
......@@ -12,7 +12,6 @@ import org.h2.engine.Right;
import org.h2.engine.Session;
import org.h2.engine.UndoLogRecord;
import org.h2.expression.Expression;
import org.h2.expression.ExpressionVisitor;
import org.h2.result.ResultInterface;
import org.h2.result.Row;
import org.h2.result.RowList;
......@@ -148,7 +147,7 @@ public class Delete extends Prepared {
filters = new TableFilter[] { targetTableFilter, sourceTableFilter };
}
PlanItem item = targetTableFilter.getBestPlanItem(session, filters, 0,
ExpressionVisitor.allColumnsForTableFilters(filters));
new AllColumnsForPlan(filters));
targetTableFilter.setPlanItem(item);
targetTableFilter.prepare();
}
......
......@@ -8,7 +8,6 @@ package org.h2.command.dml;
import java.util.BitSet;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import org.h2.engine.Session;
import org.h2.expression.Expression;
import org.h2.table.Plan;
......@@ -48,11 +47,13 @@ class Optimizer {
private TableFilter topFilter;
private double cost;
private Random random;
final AllColumnsForPlan allColumnsSet;
Optimizer(TableFilter[] filters, Expression condition, Session session) {
this.filters = filters;
this.condition = condition;
this.session = session;
allColumnsSet = new AllColumnsForPlan(filters);
}
/**
......@@ -134,7 +135,7 @@ class Optimizer {
}
list[i] = filters[j];
Plan part = new Plan(list, i+1, condition);
double costNow = part.calculateCost(session);
double costNow = part.calculateCost(session, allColumnsSet);
if (costPart < 0 || costNow < costPart) {
costPart = costNow;
bestPart = j;
......@@ -177,7 +178,7 @@ class Optimizer {
private boolean testPlan(TableFilter[] list) {
Plan p = new Plan(list, list.length, condition);
double costNow = p.calculateCost(session);
double costNow = p.calculateCost(session, allColumnsSet);
if (cost < 0 || costNow < cost) {
cost = costNow;
bestPlan = p;
......
......@@ -8,7 +8,6 @@ package org.h2.command.dml;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Objects;
import org.h2.api.ErrorCode;
import org.h2.api.Trigger;
import org.h2.command.CommandInterface;
......@@ -16,7 +15,6 @@ import org.h2.command.Prepared;
import org.h2.engine.Right;
import org.h2.engine.Session;
import org.h2.expression.Expression;
import org.h2.expression.ExpressionVisitor;
import org.h2.expression.Parameter;
import org.h2.expression.ValueExpression;
import org.h2.message.DbException;
......@@ -236,7 +234,7 @@ public class Update extends Prepared {
filters = new TableFilter[] { targetTableFilter, sourceTableFilter };
}
PlanItem item = targetTableFilter.getBestPlanItem(session, filters, 0,
ExpressionVisitor.allColumnsForTableFilters(filters));
new AllColumnsForPlan(filters));
targetTableFilter.setPlanItem(item);
targetTableFilter.prepare();
}
......
......@@ -133,7 +133,8 @@ public class ConditionInConstantSet extends Condition {
case ExpressionVisitor.NOT_FROM_RESOLVER:
case ExpressionVisitor.GET_DEPENDENCIES:
case ExpressionVisitor.QUERY_COMPARABLE:
case ExpressionVisitor.GET_COLUMNS:
case ExpressionVisitor.GET_COLUMNS1:
case ExpressionVisitor.GET_COLUMNS2:
return true;
default:
throw DbException.throwInternalError("type=" + visitor.getType());
......
......@@ -311,8 +311,11 @@ public class ExpressionColumn extends Expression {
visitor.addDependency(column.getTable());
}
return true;
case ExpressionVisitor.GET_COLUMNS:
visitor.addColumn(column);
case ExpressionVisitor.GET_COLUMNS1:
visitor.addColumn1(column);
return true;
case ExpressionVisitor.GET_COLUMNS2:
visitor.addColumn2(column);
return true;
default:
throw DbException.throwInternalError("type=" + visitor.getType());
......
......@@ -6,6 +6,7 @@
package org.h2.expression;
import java.util.HashSet;
import org.h2.command.dml.AllColumnsForPlan;
import org.h2.engine.DbObject;
import org.h2.table.Column;
import org.h2.table.ColumnResolver;
......@@ -95,10 +96,15 @@ public class ExpressionVisitor {
*/
public static final int QUERY_COMPARABLE = 8;
/**
* Get all referenced columns for the optimiser.
*/
public static final int GET_COLUMNS1 = 9;
/**
* Get all referenced columns.
*/
public static final int GET_COLUMNS = 9;
public static final int GET_COLUMNS2 = 10;
/**
* The visitor singleton for the type QUERY_COMPARABLE.
......@@ -109,30 +115,34 @@ public class ExpressionVisitor {
private final int type;
private final int queryLevel;
private final HashSet<DbObject> dependencies;
private final HashSet<Column> columns;
private final AllColumnsForPlan columns1;
private final Table table;
private final long[] maxDataModificationId;
private final ColumnResolver resolver;
private final HashSet<Column> columns2;
private ExpressionVisitor(int type,
int queryLevel,
HashSet<DbObject> dependencies,
HashSet<Column> columns, Table table, ColumnResolver resolver,
long[] maxDataModificationId) {
AllColumnsForPlan columns1, Table table, ColumnResolver resolver,
long[] maxDataModificationId,
HashSet<Column> columns2) {
this.type = type;
this.queryLevel = queryLevel;
this.dependencies = dependencies;
this.columns = columns;
this.columns1 = columns1;
this.table = table;
this.resolver = resolver;
this.maxDataModificationId = maxDataModificationId;
this.columns2 = columns2;
}
private ExpressionVisitor(int type) {
this.type = type;
this.queryLevel = 0;
this.dependencies = null;
this.columns = null;
this.columns1 = null;
this.columns2 = null;
this.table = null;
this.resolver = null;
this.maxDataModificationId = null;
......@@ -147,7 +157,7 @@ public class ExpressionVisitor {
public static ExpressionVisitor getDependenciesVisitor(
HashSet<DbObject> dependencies) {
return new ExpressionVisitor(GET_DEPENDENCIES, 0, dependencies, null,
null, null, null);
null, null, null, null);
}
/**
......@@ -158,7 +168,7 @@ public class ExpressionVisitor {
*/
public static ExpressionVisitor getOptimizableVisitor(Table table) {
return new ExpressionVisitor(OPTIMIZABLE_MIN_MAX_COUNT_ALL, 0, null,
null, table, null, null);
null, table, null, null, null);
}
/**
......@@ -170,7 +180,17 @@ public class ExpressionVisitor {
*/
static ExpressionVisitor getNotFromResolverVisitor(ColumnResolver resolver) {
return new ExpressionVisitor(NOT_FROM_RESOLVER, 0, null, null, null,
resolver, null);
resolver, null, null);
}
/**
* Create a new visitor to get all referenced columns.
*
* @param columns the columns map
* @return the new visitor
*/
public static ExpressionVisitor getColumnsVisitor(AllColumnsForPlan columns) {
return new ExpressionVisitor(GET_COLUMNS1, 0, null, columns, null, null, null, null);
}
/**
......@@ -180,12 +200,12 @@ public class ExpressionVisitor {
* @return the new visitor
*/
public static ExpressionVisitor getColumnsVisitor(HashSet<Column> columns) {
return new ExpressionVisitor(GET_COLUMNS, 0, null, columns, null, null, null);
return new ExpressionVisitor(GET_COLUMNS2, 0, null, null, null, null, null, columns);
}
public static ExpressionVisitor getMaxModificationIdVisitor() {
return new ExpressionVisitor(SET_MAX_DATA_MODIFICATION_ID, 0, null,
null, null, null, new long[1]);
null, null, null, new long[1], null);
}
/**
......@@ -204,8 +224,11 @@ public class ExpressionVisitor {
*
* @param column the additional column.
*/
void addColumn(Column column) {
columns.add(column);
void addColumn1(Column column) {
columns1.add(column);
}
void addColumn2(Column column) {
columns2.add(column);
}
/**
......@@ -226,7 +249,7 @@ public class ExpressionVisitor {
*/
public ExpressionVisitor incrementQueryLevel(int offset) {
return new ExpressionVisitor(type, queryLevel + offset, dependencies,
columns, table, resolver, maxDataModificationId);
columns1, table, resolver, maxDataModificationId, columns2);
}
/**
......@@ -290,16 +313,13 @@ public class ExpressionVisitor {
* Get the set of columns of all tables.
*
* @param filters the filters
* @return the set of columns
*/
public static HashSet<Column> allColumnsForTableFilters(TableFilter[] filters) {
HashSet<Column> allColumnsSet = new HashSet<>();
public static void allColumnsForTableFilters(TableFilter[] filters, AllColumnsForPlan allColumnsSet) {
for (TableFilter filter : filters) {
if (filter.getSelect() != null) {
filter.getSelect().isEverything(ExpressionVisitor.getColumnsVisitor(allColumnsSet));
}
}
return allColumnsSet;
}
}
......@@ -2649,7 +2649,8 @@ public class Function extends Expression implements FunctionCall {
case ExpressionVisitor.NOT_FROM_RESOLVER:
case ExpressionVisitor.OPTIMIZABLE_MIN_MAX_COUNT_ALL:
case ExpressionVisitor.SET_MAX_DATA_MODIFICATION_ID:
case ExpressionVisitor.GET_COLUMNS:
case ExpressionVisitor.GET_COLUMNS1:
case ExpressionVisitor.GET_COLUMNS2:
return true;
default:
throw DbException.throwInternalError("type=" + visitor.getType());
......
......@@ -159,7 +159,8 @@ public class Parameter extends Expression implements ParameterInterface {
case ExpressionVisitor.OPTIMIZABLE_MIN_MAX_COUNT_ALL:
case ExpressionVisitor.DETERMINISTIC:
case ExpressionVisitor.READONLY:
case ExpressionVisitor.GET_COLUMNS:
case ExpressionVisitor.GET_COLUMNS1:
case ExpressionVisitor.GET_COLUMNS2:
return true;
case ExpressionVisitor.INDEPENDENT:
return value != null;
......
......@@ -90,7 +90,8 @@ public class Rownum extends Expression {
case ExpressionVisitor.NOT_FROM_RESOLVER:
case ExpressionVisitor.GET_DEPENDENCIES:
case ExpressionVisitor.SET_MAX_DATA_MODIFICATION_ID:
case ExpressionVisitor.GET_COLUMNS:
case ExpressionVisitor.GET_COLUMNS1:
case ExpressionVisitor.GET_COLUMNS2:
// if everything else is the same, the rownum is the same
return true;
default:
......
......@@ -83,7 +83,8 @@ public class SequenceValue extends Expression {
case ExpressionVisitor.EVALUATABLE:
case ExpressionVisitor.OPTIMIZABLE_MIN_MAX_COUNT_ALL:
case ExpressionVisitor.NOT_FROM_RESOLVER:
case ExpressionVisitor.GET_COLUMNS:
case ExpressionVisitor.GET_COLUMNS1:
case ExpressionVisitor.GET_COLUMNS2:
return true;
case ExpressionVisitor.DETERMINISTIC:
case ExpressionVisitor.READONLY:
......
......@@ -159,7 +159,8 @@ public class ValueExpression extends Expression {
case ExpressionVisitor.NOT_FROM_RESOLVER:
case ExpressionVisitor.GET_DEPENDENCIES:
case ExpressionVisitor.QUERY_COMPARABLE:
case ExpressionVisitor.GET_COLUMNS:
case ExpressionVisitor.GET_COLUMNS1:
case ExpressionVisitor.GET_COLUMNS2:
return true;
default:
throw DbException.throwInternalError("type=" + visitor.getType());
......
......@@ -75,7 +75,8 @@ public class Variable extends Expression {
case ExpressionVisitor.NOT_FROM_RESOLVER:
case ExpressionVisitor.QUERY_COMPARABLE:
case ExpressionVisitor.GET_DEPENDENCIES:
case ExpressionVisitor.GET_COLUMNS:
case ExpressionVisitor.GET_COLUMNS1:
case ExpressionVisitor.GET_COLUMNS2:
return true;
case ExpressionVisitor.DETERMINISTIC:
return false;
......
......@@ -5,8 +5,9 @@
*/
package org.h2.index;
import java.util.HashSet;
import java.util.ArrayList;
import org.h2.api.ErrorCode;
import org.h2.command.dml.AllColumnsForPlan;
import org.h2.engine.Constants;
import org.h2.engine.DbObject;
import org.h2.engine.Session;
......@@ -163,7 +164,7 @@ public abstract class BaseIndex extends SchemaObjectBase implements Index {
*/
protected final long getCostRangeIndex(int[] masks, long rowCount,
TableFilter[] filters, int filter, SortOrder sortOrder,
boolean isScanIndex, HashSet<Column> allColumnsSet) {
boolean isScanIndex, AllColumnsForPlan allColumnsSet) {
rowCount += Constants.COST_ROW_OFFSET;
int totalSelectivity = 0;
long rowsCost = rowCount;
......@@ -246,10 +247,12 @@ public abstract class BaseIndex extends SchemaObjectBase implements Index {
// satisfy the query without needing to read from the primary table
// (scan index), make that one slightly lower cost.
boolean needsToReadFromScanIndex = true;
if (!isScanIndex && allColumnsSet != null && !allColumnsSet.isEmpty()) {
if (!isScanIndex && allColumnsSet != null) {
boolean foundAllColumnsWeNeed = true;
for (Column c : allColumnsSet) {
if (c.getTable() == getTable()) {
ArrayList<Column> foundCols = allColumnsSet.get(getTable());
if (foundCols != null)
{
for (Column c : foundCols) {
boolean found = false;
for (Column c2 : columns) {
if (c == c2) {
......
......@@ -5,13 +5,12 @@
*/
package org.h2.index;
import java.util.HashSet;
import org.h2.command.dml.AllColumnsForPlan;
import org.h2.engine.Session;
import org.h2.message.DbException;
import org.h2.result.Row;
import org.h2.result.SearchRow;
import org.h2.result.SortOrder;
import org.h2.table.Column;
import org.h2.table.FunctionTable;
import org.h2.table.IndexColumn;
import org.h2.table.TableFilter;
......@@ -61,7 +60,7 @@ public class FunctionIndex extends BaseIndex {
@Override
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
AllColumnsForPlan allColumnsSet) {
if (masks != null) {
throw DbException.getUnsupportedException("ALIAS");
}
......
......@@ -5,7 +5,7 @@
*/
package org.h2.index;
import java.util.HashSet;
import org.h2.command.dml.AllColumnsForPlan;
import org.h2.engine.Session;
import org.h2.message.DbException;
import org.h2.result.Row;
......@@ -116,7 +116,7 @@ public class HashIndex extends BaseIndex {
@Override
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
AllColumnsForPlan allColumnsSet) {
for (Column column : columns) {
int index = column.getColumnId();
int mask = masks[index];
......
......@@ -5,7 +5,7 @@
*/
package org.h2.index;
import java.util.HashSet;
import org.h2.command.dml.AllColumnsForPlan;
import org.h2.engine.Session;
import org.h2.result.Row;
import org.h2.result.SearchRow;
......@@ -98,7 +98,7 @@ public interface Index extends SchemaObject {
* @return the estimated cost
*/
double getCost(Session session, int[] masks, TableFilter[] filters, int filter,
SortOrder sortOrder, HashSet<Column> allColumnsSet);
SortOrder sortOrder, AllColumnsForPlan allColumnsSet);
/**
* Remove the index.
......
......@@ -8,7 +8,7 @@ package org.h2.index;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.HashSet;
import org.h2.command.dml.AllColumnsForPlan;
import org.h2.engine.Constants;
import org.h2.engine.Session;
import org.h2.message.DbException;
......@@ -144,7 +144,7 @@ public class LinkedIndex extends BaseIndex {
@Override
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
AllColumnsForPlan allColumnsSet) {
return 100 + getCostRangeIndex(masks, rowCount +
Constants.COST_ROW_OFFSET, filters, filter, sortOrder, false, allColumnsSet);
}
......
......@@ -6,7 +6,7 @@
package org.h2.index;
import java.util.ArrayList;
import java.util.HashSet;
import org.h2.command.dml.AllColumnsForPlan;
import org.h2.engine.Session;
import org.h2.message.DbException;
import org.h2.result.Row;
......@@ -55,7 +55,7 @@ public class MetaIndex extends BaseIndex {
@Override
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
AllColumnsForPlan allColumnsSet) {
if (scan) {
return 10 * MetaTable.ROW_COUNT_APPROXIMATION;
}
......
......@@ -6,8 +6,8 @@
package org.h2.index;
import java.util.ArrayList;
import java.util.HashSet;
import org.h2.api.ErrorCode;
import org.h2.command.dml.AllColumnsForPlan;
import org.h2.engine.Database;
import org.h2.engine.DbObject;
import org.h2.engine.Session;
......@@ -148,7 +148,7 @@ public class MultiVersionIndex implements Index {
@Override
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
AllColumnsForPlan allColumnsSet) {
return base.getCost(session, masks, filters, filter, sortOrder, allColumnsSet);
}
......
......@@ -6,7 +6,7 @@
package org.h2.index;
import java.util.ArrayList;
import java.util.HashSet;
import org.h2.command.dml.AllColumnsForPlan;
import org.h2.engine.Session;
import org.h2.message.DbException;
import org.h2.result.Row;
......@@ -133,7 +133,7 @@ public class NonUniqueHashIndex extends BaseIndex {
@Override
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
AllColumnsForPlan allColumnsSet) {
for (Column column : columns) {
int index = column.getColumnId();
int mask = masks[index];
......
......@@ -5,8 +5,8 @@
*/
package org.h2.index;
import java.util.HashSet;
import org.h2.api.ErrorCode;
import org.h2.command.dml.AllColumnsForPlan;
import org.h2.engine.Constants;
import org.h2.engine.Session;
import org.h2.engine.SysProperties;
......@@ -220,7 +220,7 @@ public class PageBtreeIndex extends PageIndex {
@Override
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
AllColumnsForPlan allColumnsSet) {
return 10 * getCostRangeIndex(masks, tableData.getRowCount(session),
filters, filter, sortOrder, false, allColumnsSet);
}
......
......@@ -11,6 +11,7 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import org.h2.api.ErrorCode;
import org.h2.command.dml.AllColumnsForPlan;
import org.h2.engine.Constants;
import org.h2.engine.Session;
import org.h2.engine.SysProperties;
......@@ -310,7 +311,7 @@ public class PageDataIndex extends PageIndex {
@Override
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
AllColumnsForPlan allColumnsSet) {
return 10 * (tableData.getRowCountApproximation() +
Constants.COST_ROW_OFFSET);
}
......
......@@ -5,7 +5,7 @@
*/
package org.h2.index;
import java.util.HashSet;
import org.h2.command.dml.AllColumnsForPlan;
import org.h2.engine.Session;
import org.h2.message.DbException;
import org.h2.result.Row;
......@@ -104,7 +104,7 @@ public class PageDelegateIndex extends PageIndex {
@Override
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
AllColumnsForPlan allColumnsSet) {
return 10 * getCostRangeIndex(masks, mainIndex.getRowCount(session),
filters, filter, sortOrder, false, allColumnsSet);
}
......
......@@ -5,13 +5,12 @@
*/
package org.h2.index;
import java.util.HashSet;
import org.h2.command.dml.AllColumnsForPlan;
import org.h2.engine.Session;
import org.h2.message.DbException;
import org.h2.result.Row;
import org.h2.result.SearchRow;
import org.h2.result.SortOrder;
import org.h2.table.Column;
import org.h2.table.IndexColumn;
import org.h2.table.RangeTable;
import org.h2.table.TableFilter;
......@@ -84,7 +83,7 @@ public class RangeIndex extends BaseIndex {
@Override
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
AllColumnsForPlan allColumnsSet) {
return 1;
}
......
......@@ -12,6 +12,7 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import org.h2.api.ErrorCode;
import org.h2.command.dml.AllColumnsForPlan;
import org.h2.engine.Constants;
import org.h2.engine.Session;
import org.h2.engine.UndoLogRecord;
......@@ -175,7 +176,7 @@ public class ScanIndex extends BaseIndex {
@Override
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
AllColumnsForPlan allColumnsSet) {
return tableData.getRowCountApproximation() + Constants.COST_ROW_OFFSET;
}
......
......@@ -5,8 +5,8 @@
*/
package org.h2.index;
import java.util.HashSet;
import java.util.Iterator;
import org.h2.command.dml.AllColumnsForPlan;
import org.h2.engine.Session;
import org.h2.message.DbException;
import org.h2.mvstore.MVStore;
......@@ -201,7 +201,7 @@ public class SpatialTreeIndex extends BaseIndex implements SpatialIndex {
@Override
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
AllColumnsForPlan allColumnsSet) {
return getCostRangeIndex(masks, columns);
}
......
......@@ -5,14 +5,13 @@
*/
package org.h2.index;
import java.util.HashSet;
import org.h2.command.dml.AllColumnsForPlan;
import org.h2.engine.Session;
import org.h2.engine.SysProperties;
import org.h2.message.DbException;
import org.h2.result.Row;
import org.h2.result.SearchRow;
import org.h2.result.SortOrder;
import org.h2.table.Column;
import org.h2.table.IndexColumn;
import org.h2.table.RegularTable;
import org.h2.table.TableFilter;
......@@ -321,7 +320,7 @@ public class TreeIndex extends BaseIndex {
@Override
public double getCost(Session session, int[] masks, TableFilter[] filters, int filter,
SortOrder sortOrder, HashSet<Column> allColumnsSet) {
SortOrder sortOrder, AllColumnsForPlan allColumnsSet) {
return getCostRangeIndex(masks, tableData.getRowCountApproximation(),
filters, filter, sortOrder, false, allColumnsSet);
}
......
......@@ -6,11 +6,11 @@
package org.h2.index;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.concurrent.TimeUnit;
import org.h2.api.ErrorCode;
import org.h2.command.Parser;
import org.h2.command.Prepared;
import org.h2.command.dml.AllColumnsForPlan;
import org.h2.command.dml.Query;
import org.h2.command.dml.SelectUnion;
import org.h2.engine.Constants;
......@@ -151,7 +151,7 @@ public class ViewIndex extends BaseIndex implements SpatialIndex {
@Override
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
AllColumnsForPlan allColumnsSet) {
return recursive ? 1000 : query.getCost();
}
......
......@@ -5,8 +5,8 @@
*/
package org.h2.mvstore.db;
import java.util.HashSet;
import java.util.List;
import org.h2.command.dml.AllColumnsForPlan;
import org.h2.engine.Session;
import org.h2.index.BaseIndex;
import org.h2.index.Cursor;
......@@ -94,7 +94,7 @@ public class MVDelegateIndex extends BaseIndex implements MVIndex {
@Override
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
AllColumnsForPlan allColumnsSet) {
return 10 * getCostRangeIndex(masks, mainIndex.getRowCountApproximation(),
filters, filter, sortOrder, true, allColumnsSet);
}
......
......@@ -6,12 +6,12 @@
package org.h2.mvstore.db;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.concurrent.atomic.AtomicLong;
import org.h2.api.ErrorCode;
import org.h2.command.dml.AllColumnsForPlan;
import org.h2.engine.Database;
import org.h2.engine.Session;
import org.h2.index.BaseIndex;
......@@ -209,7 +209,7 @@ public class MVPrimaryIndex extends BaseIndex {
@Override
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
AllColumnsForPlan allColumnsSet) {
try {
return 10 * getCostRangeIndex(masks, dataMap.sizeAsLongMax(),
filters, filter, sortOrder, true, allColumnsSet);
......
......@@ -7,12 +7,12 @@ package org.h2.mvstore.db;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Queue;
import org.h2.api.ErrorCode;
import org.h2.command.dml.AllColumnsForPlan;
import org.h2.engine.Database;
import org.h2.engine.Session;
import org.h2.index.BaseIndex;
......@@ -358,7 +358,7 @@ public final class MVSecondaryIndex extends BaseIndex implements MVIndex {
@Override
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
AllColumnsForPlan allColumnsSet) {
try {
return 10 * getCostRangeIndex(masks, dataMap.sizeAsLongMax(),
filters, filter, sortOrder, false, allColumnsSet);
......
......@@ -5,10 +5,10 @@
*/
package org.h2.mvstore.db;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import org.h2.api.ErrorCode;
import org.h2.command.dml.AllColumnsForPlan;
import org.h2.engine.Database;
import org.h2.engine.Session;
import org.h2.index.BaseIndex;
......@@ -17,16 +17,15 @@ import org.h2.index.IndexType;
import org.h2.index.SpatialIndex;
import org.h2.index.SpatialTreeIndex;
import org.h2.message.DbException;
import org.h2.mvstore.tx.Transaction;
import org.h2.mvstore.tx.TransactionMap;
import org.h2.mvstore.tx.VersionedValue;
import org.h2.mvstore.rtree.MVRTreeMap;
import org.h2.mvstore.rtree.MVRTreeMap.RTreeCursor;
import org.h2.mvstore.rtree.SpatialKey;
import org.h2.mvstore.tx.Transaction;
import org.h2.mvstore.tx.TransactionMap;
import org.h2.mvstore.tx.VersionedValue;
import org.h2.result.Row;
import org.h2.result.SearchRow;
import org.h2.result.SortOrder;
import org.h2.table.Column;
import org.h2.table.IndexColumn;
import org.h2.table.TableFilter;
import org.h2.value.Value;
......@@ -251,7 +250,7 @@ public class MVSpatialIndex extends BaseIndex implements SpatialIndex, MVIndex {
@Override
public double getCost(Session session, int[] masks, TableFilter[] filters,
int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
AllColumnsForPlan allColumnsSet) {
return SpatialTreeIndex.getCostRangeIndex(masks, columns);
}
......
......@@ -8,7 +8,7 @@ package org.h2.table;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import org.h2.command.dml.AllColumnsForPlan;
import org.h2.engine.Session;
import org.h2.expression.Expression;
import org.h2.expression.ExpressionVisitor;
......@@ -104,15 +104,13 @@ public class Plan {
* @param session the session
* @return the cost
*/
public double calculateCost(Session session) {
public double calculateCost(Session session, AllColumnsForPlan allColumnsSet) {
Trace t = session.getTrace();
if (t.isDebugEnabled()) {
t.debug("Plan : calculate cost for plan {0}", Arrays.toString(allFilters));
}
double cost = 1;
boolean invalidPlan = false;
final HashSet<Column> allColumnsSet = ExpressionVisitor
.allColumnsForTableFilters(allFilters);
for (int i = 0; i < allFilters.length; i++) {
TableFilter tableFilter = allFilters[i];
if (t.isDebugEnabled()) {
......
......@@ -13,6 +13,7 @@ import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import org.h2.api.ErrorCode;
import org.h2.command.Prepared;
import org.h2.command.dml.AllColumnsForPlan;
import org.h2.constraint.Constraint;
import org.h2.engine.Constants;
import org.h2.engine.DbObject;
......@@ -236,7 +237,7 @@ public abstract class Table extends SchemaObjectBase {
@SuppressWarnings("unused")
public Index getScanIndex(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
AllColumnsForPlan allColumnsSet) {
return getScanIndex(session);
}
......@@ -712,7 +713,7 @@ public abstract class Table extends SchemaObjectBase {
*/
public PlanItem getBestPlanItem(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
AllColumnsForPlan allColumnsSet) {
PlanItem item = new PlanItem();
item.setIndex(getScanIndex(session));
item.cost = item.getIndex().getCost(session, null, filters, filter, null, allColumnsSet);
......
......@@ -7,9 +7,9 @@ package org.h2.table;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import org.h2.api.ErrorCode;
import org.h2.command.Parser;
import org.h2.command.dml.AllColumnsForPlan;
import org.h2.command.dml.Select;
import org.h2.engine.Right;
import org.h2.engine.Session;
......@@ -194,7 +194,7 @@ public class TableFilter implements ColumnResolver {
* @return the best plan item
*/
public PlanItem getBestPlanItem(Session s, TableFilter[] filters, int filter,
HashSet<Column> allColumnsSet) {
AllColumnsForPlan allColumnsSet) {
PlanItem item1 = null;
SortOrder sortOrder = null;
if (select != null) {
......
......@@ -13,6 +13,7 @@ import java.util.Map;
import org.h2.api.ErrorCode;
import org.h2.command.Prepared;
import org.h2.command.ddl.CreateTableData;
import org.h2.command.dml.AllColumnsForPlan;
import org.h2.command.dml.Query;
import org.h2.engine.Constants;
import org.h2.engine.Database;
......@@ -268,7 +269,7 @@ public class TableView extends Table {
@Override
public PlanItem getBestPlanItem(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
AllColumnsForPlan allColumnsSet) {
final CacheKey cacheKey = new CacheKey(masks, this);
Map<Object, ViewIndex> indexCache = session.getViewIndexCache(topQuery != null);
ViewIndex i = indexCache.get(cacheKey);
......@@ -481,7 +482,7 @@ public class TableView extends Table {
@Override
public Index getScanIndex(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
AllColumnsForPlan allColumnsSet) {
if (createException != null) {
String msg = createException.getMessage();
throw DbException.get(ErrorCode.VIEW_IS_INVALID_2,
......
......@@ -348,7 +348,7 @@ public class Profiler implements Runnable {
return;
}
try {
Thread.sleep(interval);
Thread.sleep(interval, 0);
} catch (Exception e) {
// ignore
}
......
......@@ -64,8 +64,8 @@ public class TestSelectCountNonNullColumn extends TestBase {
assertEquals(expect, rs.getLong(1));
} else {
// System.out.println(rs.getString(1));
assertEquals("SELECT\n" + " COUNT(*)\n" + "FROM PUBLIC.SIMPLE\n"
+ " /* PUBLIC.SIMPLE.tableScan */\n"
assertEquals("SELECT\n COUNT(*)\nFROM PUBLIC.SIMPLE\n"
+ " /* PUBLIC.PRIMARY_KEY_9 */\n"
+ "/* direct lookup */", rs.getString(1));
}
}
......
......@@ -14,7 +14,6 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
......@@ -28,6 +27,7 @@ import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
import org.h2.api.TableEngine;
import org.h2.command.ddl.CreateTableData;
import org.h2.command.dml.AllColumnsForPlan;
import org.h2.engine.Session;
import org.h2.expression.Expression;
import org.h2.index.BaseIndex;
......@@ -41,7 +41,13 @@ import org.h2.message.DbException;
import org.h2.result.Row;
import org.h2.result.SearchRow;
import org.h2.result.SortOrder;
import org.h2.table.*;
import org.h2.table.IndexColumn;
import org.h2.table.RegularTable;
import org.h2.table.SubQueryInfo;
import org.h2.table.Table;
import org.h2.table.TableBase;
import org.h2.table.TableFilter;
import org.h2.table.TableType;
import org.h2.test.TestBase;
import org.h2.util.DoneFuture;
import org.h2.util.New;
......@@ -950,7 +956,7 @@ public class TestTableEngines extends TestBase {
@Override
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
AllColumnsForPlan allColumnsSet) {
return 0;
}
......@@ -1174,7 +1180,7 @@ public class TestTableEngines extends TestBase {
@Override
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
AllColumnsForPlan allColumnsSet) {
return 0;
}
......@@ -1345,7 +1351,7 @@ public class TestTableEngines extends TestBase {
@Override
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
AllColumnsForPlan allColumnsSet) {
doTests(session);
return getCostRangeIndex(masks, getRowCount(session), filters,
filter, sortOrder, true, allColumnsSet);
......@@ -1695,7 +1701,7 @@ public class TestTableEngines extends TestBase {
@Override
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
AllColumnsForPlan allColumnsSet) {
doTests(session);
return getCostRangeIndex(masks, set.size(), filters, filter,
sortOrder, false, allColumnsSet);
......
......@@ -86,6 +86,7 @@ public class TestScript extends TestBase {
testScript("testScript.sql");
testScript("derived-column-names.sql");
testScript("indexes.sql");
testScript("information_schema.sql");
if (config.mvStore) {
// we get slightly different explain plan stuff here in PageStore mode
......
-- Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
-- and the EPL 1.0 (http://h2database.com/html/license.html).
-- Initial Developer: H2 Group
--
-- Test all possible order modes
CREATE TABLE TEST(A INT);
> ok
INSERT INTO TEST VALUES (NULL), (0), (1);
> update count: 3
-- default
SELECT A FROM TEST ORDER BY A;
> A
> ----
> null
> 0
> 1
> rows (ordered): 3
CREATE INDEX A_IDX ON TEST(A);
> ok
SELECT A FROM TEST ORDER BY A;
> A
> ----
> null
> 0
> 1
> rows (ordered): 3
EXPLAIN SELECT A FROM TEST ORDER BY A;
>> SELECT A FROM PUBLIC.TEST /* PUBLIC.A_IDX */ ORDER BY 1 /* index sorted */
DROP INDEX A_IDX;
> ok
-- ASC
SELECT A FROM TEST ORDER BY A ASC;
> A
> ----
> null
> 0
> 1
> rows (ordered): 3
CREATE INDEX A_IDX ON TEST(A ASC);
> ok
SELECT A FROM TEST ORDER BY A ASC;
> A
> ----
> null
> 0
> 1
> rows (ordered): 3
EXPLAIN SELECT A FROM TEST ORDER BY A ASC;
>> SELECT A FROM PUBLIC.TEST /* PUBLIC.A_IDX */ ORDER BY 1 /* index sorted */
DROP INDEX A_IDX;
> ok
-- ASC NULLS FIRST
SELECT A FROM TEST ORDER BY A ASC NULLS FIRST;
> A
> ----
> null
> 0
> 1
> rows (ordered): 3
CREATE INDEX A_IDX ON TEST(A ASC NULLS FIRST);
> ok
SELECT A FROM TEST ORDER BY A ASC NULLS FIRST;
> A
> ----
> null
> 0
> 1
> rows (ordered): 3
EXPLAIN SELECT A FROM TEST ORDER BY A ASC NULLS FIRST;
>> SELECT A FROM PUBLIC.TEST /* PUBLIC.A_IDX */ ORDER BY 1 NULLS FIRST /* index sorted */
DROP INDEX A_IDX;
> ok
-- ASC NULLS LAST
SELECT A FROM TEST ORDER BY A ASC NULLS LAST;
> A
> ----
> 0
> 1
> null
> rows (ordered): 3
CREATE INDEX A_IDX ON TEST(A ASC NULLS LAST);
> ok
SELECT A FROM TEST ORDER BY A ASC NULLS LAST;
> A
> ----
> 0
> 1
> null
> rows (ordered): 3
EXPLAIN SELECT A FROM TEST ORDER BY A ASC NULLS LAST;
>> SELECT A FROM PUBLIC.TEST /* PUBLIC.A_IDX */ ORDER BY 1 NULLS LAST /* index sorted */
DROP INDEX A_IDX;
> ok
-- DESC
SELECT A FROM TEST ORDER BY A DESC;
> A
> ----
> 1
> 0
> null
> rows (ordered): 3
CREATE INDEX A_IDX ON TEST(A DESC);
> ok
SELECT A FROM TEST ORDER BY A DESC;
> A
> ----
> 1
> 0
> null
> rows (ordered): 3
EXPLAIN SELECT A FROM TEST ORDER BY A DESC;
>> SELECT A FROM PUBLIC.TEST /* PUBLIC.A_IDX */ ORDER BY 1 DESC /* index sorted */
DROP INDEX A_IDX;
> ok
-- DESC NULLS FIRST
SELECT A FROM TEST ORDER BY A DESC NULLS FIRST;
> A
> ----
> null
> 1
> 0
> rows (ordered): 3
CREATE INDEX A_IDX ON TEST(A DESC NULLS FIRST);
> ok
SELECT A FROM TEST ORDER BY A DESC NULLS FIRST;
> A
> ----
> null
> 1
> 0
> rows (ordered): 3
EXPLAIN SELECT A FROM TEST ORDER BY A DESC NULLS FIRST;
>> SELECT A FROM PUBLIC.TEST /* PUBLIC.A_IDX */ ORDER BY 1 DESC NULLS FIRST /* index sorted */
DROP INDEX A_IDX;
> ok
-- DESC NULLS LAST
SELECT A FROM TEST ORDER BY A DESC NULLS LAST;
> A
> ----
> 1
> 0
> null
> rows (ordered): 3
CREATE INDEX A_IDX ON TEST(A DESC NULLS LAST);
> ok
SELECT A FROM TEST ORDER BY A DESC NULLS LAST;
> A
> ----
> 1
> 0
> null
> rows (ordered): 3
EXPLAIN SELECT A FROM TEST ORDER BY A DESC NULLS LAST;
>> SELECT A FROM PUBLIC.TEST /* PUBLIC.A_IDX */ ORDER BY 1 DESC NULLS LAST /* index sorted */
DROP INDEX A_IDX;
> ok
-- Index selection
CREATE INDEX A_IDX_ASC ON TEST(A ASC);
> ok
CREATE INDEX A_IDX_ASC_NL ON TEST(A ASC NULLS LAST);
> ok
CREATE INDEX A_IDX_DESC ON TEST(A DESC);
> ok
CREATE INDEX A_IDX_DESC_NF ON TEST(A DESC NULLS FIRST);
> ok
EXPLAIN SELECT A FROM TEST ORDER BY A;
>> SELECT A FROM PUBLIC.TEST /* PUBLIC.A_IDX_ASC */ ORDER BY 1 /* index sorted */
EXPLAIN SELECT A FROM TEST ORDER BY A ASC;
>> SELECT A FROM PUBLIC.TEST /* PUBLIC.A_IDX_ASC */ ORDER BY 1 /* index sorted */
EXPLAIN SELECT A FROM TEST ORDER BY A NULLS FIRST;
>> SELECT A FROM PUBLIC.TEST /* PUBLIC.A_IDX_ASC */ ORDER BY 1 NULLS FIRST /* index sorted */
EXPLAIN SELECT A FROM TEST ORDER BY A NULLS LAST;
>> SELECT A FROM PUBLIC.TEST /* PUBLIC.A_IDX_ASC_NL */ ORDER BY 1 NULLS LAST /* index sorted */
EXPLAIN SELECT A FROM TEST ORDER BY A DESC;
>> SELECT A FROM PUBLIC.TEST /* PUBLIC.A_IDX_DESC */ ORDER BY 1 DESC /* index sorted */
EXPLAIN SELECT A FROM TEST ORDER BY A DESC NULLS FIRST;
>> SELECT A FROM PUBLIC.TEST /* PUBLIC.A_IDX_DESC_NF */ ORDER BY 1 DESC NULLS FIRST /* index sorted */
EXPLAIN SELECT A FROM TEST ORDER BY A DESC NULLS LAST;
>> SELECT A FROM PUBLIC.TEST /* PUBLIC.A_IDX_DESC */ ORDER BY 1 DESC NULLS LAST /* index sorted */
DROP INDEX A_IDX_ASC;
> ok
DROP INDEX A_IDX_DESC;
> ok
CREATE INDEX A_IDX_ASC_NF ON TEST(A ASC NULLS FIRST);
> ok
CREATE INDEX A_IDX_DESC_NL ON TEST(A DESC NULLS LAST);
> ok
EXPLAIN SELECT A FROM TEST ORDER BY A;
>> SELECT A FROM PUBLIC.TEST /* PUBLIC.A_IDX_ASC_NF */ ORDER BY 1 /* index sorted */
EXPLAIN SELECT A FROM TEST ORDER BY A ASC;
>> SELECT A FROM PUBLIC.TEST /* PUBLIC.A_IDX_ASC_NF */ ORDER BY 1 /* index sorted */
EXPLAIN SELECT A FROM TEST ORDER BY A NULLS FIRST;
>> SELECT A FROM PUBLIC.TEST /* PUBLIC.A_IDX_ASC_NF */ ORDER BY 1 NULLS FIRST /* index sorted */
EXPLAIN SELECT A FROM TEST ORDER BY A NULLS LAST;
>> SELECT A FROM PUBLIC.TEST /* PUBLIC.A_IDX_ASC_NL */ ORDER BY 1 NULLS LAST /* index sorted */
EXPLAIN SELECT A FROM TEST ORDER BY A DESC;
>> SELECT A FROM PUBLIC.TEST /* PUBLIC.A_IDX_DESC_NL */ ORDER BY 1 DESC /* index sorted */
EXPLAIN SELECT A FROM TEST ORDER BY A DESC NULLS FIRST;
>> SELECT A FROM PUBLIC.TEST /* PUBLIC.A_IDX_DESC_NF */ ORDER BY 1 DESC NULLS FIRST /* index sorted */
EXPLAIN SELECT A FROM TEST ORDER BY A DESC NULLS LAST;
>> SELECT A FROM PUBLIC.TEST /* PUBLIC.A_IDX_DESC_NL */ ORDER BY 1 DESC NULLS LAST /* index sorted */
DROP TABLE TEST;
> ok
-- Other tests
create table test(a int, b int);
> ok
insert into test values(1, 1);
> update count: 1
create index on test(a, b desc);
> ok
select * from test where a = 1;
> A B
> - -
> 1 1
> rows: 1
drop table test;
> ok
create table test(x int);
> ok
create hash index on test(x);
> ok
select 1 from test group by x;
> 1
> -
> rows: 0
drop table test;
> ok
......@@ -90,24 +90,6 @@ AND studentID = 2;
drop table results;
> ok
create table test(a int, b int);
> ok
insert into test values(1, 1);
> update count: 1
create index on test(a, b desc);
> ok
select * from test where a = 1;
> A B
> - -
> 1 1
> rows: 1
drop table test;
> ok
create table test(id int, name varchar) as select 1, 'a';
> ok
......@@ -132,20 +114,6 @@ select case seq.nextval when 2 then 'two' when 3 then 'three' when 1 then 'one'
drop sequence seq;
> ok
create table test(x int);
> ok
create hash index on test(x);
> ok
select 1 from test group by x;
> 1
> -
> rows: 0
drop table test;
> ok
select * from dual where x = x + 1 or x in(2, 0);
> X
> -
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论