提交 deb43030 authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov

Remove tricks for distinct operations on non-distinct external results

上级 acd95c24
......@@ -5,8 +5,6 @@
*/
package org.h2.mvstore.db;
import java.util.Arrays;
import org.h2.engine.Database;
import org.h2.expression.Expression;
import org.h2.message.DbException;
......@@ -22,11 +20,6 @@ import org.h2.value.ValueArray;
*/
class MVPlainTempResult extends MVTempResult {
/**
* The type of the distinct values.
*/
private final ValueDataType distinctType;
/**
* Map with identities of rows as keys rows as values.
*/
......@@ -39,12 +32,6 @@ class MVPlainTempResult extends MVTempResult {
*/
private long counter;
/**
* Optional index. This index is created only if {@link #contains(Value[])}
* method is invoked. Only the root result should have an index if required.
*/
private MVMap<ValueArray, Boolean> index;
/**
* Cursor for the {@link #next()} method.
*/
......@@ -58,7 +45,6 @@ class MVPlainTempResult extends MVTempResult {
*/
private MVPlainTempResult(MVPlainTempResult parent) {
super(parent);
this.distinctType = null;
this.map = parent.map;
}
......@@ -75,46 +61,20 @@ class MVPlainTempResult extends MVTempResult {
MVPlainTempResult(Database database, Expression[] expressions, int visibleColumnCount) {
super(database, expressions.length, visibleColumnCount);
ValueDataType valueType = new ValueDataType(database.getCompareMode(), database, new int[columnCount]);
if (columnCount == visibleColumnCount) {
distinctType = valueType;
} else {
distinctType = new ValueDataType(database.getCompareMode(), database, new int[visibleColumnCount]);
}
Builder<Long, ValueArray> builder = new MVMap.Builder<Long, ValueArray>().valueType(valueType);
map = store.openMap("tmp", builder);
}
@Override
public int addRow(Value[] values) {
assert parent == null && index == null;
assert parent == null;
map.put(counter++, ValueArray.get(values));
return ++rowCount;
}
@Override
public boolean contains(Value[] values) {
// Only parent result maintains the index
if (parent != null) {
return parent.contains(values);
}
if (index == null) {
createIndex();
}
return index.containsKey(ValueArray.get(values));
}
private void createIndex() {
Builder<ValueArray, Boolean> builder = new MVMap.Builder<ValueArray, Boolean>().keyType(distinctType);
index = store.openMap("idx", builder);
Cursor<Long, ValueArray> c = map.cursor(null);
while (c.hasNext()) {
c.next();
ValueArray row = c.getValue();
if (columnCount != visibleColumnCount) {
row = ValueArray.get(Arrays.copyOf(row.getList(), visibleColumnCount));
}
index.putIfAbsent(row, true);
}
throw DbException.getUnsupportedException("contains()");
}
@Override
......
......@@ -171,7 +171,9 @@ class MVSortedTempResult extends MVTempResult {
} else {
distinctType = new ValueDataType(database.getCompareMode(), database, new int[visibleColumnCount]);
if (distinct) {
createIndex(false);
Builder<ValueArray, Boolean> indexBuilder = new MVMap.Builder<ValueArray, Boolean>()
.keyType(distinctType);
index = store.openMap("idx", indexBuilder);
}
}
}
......@@ -209,29 +211,13 @@ class MVSortedTempResult extends MVTempResult {
if (parent != null) {
return parent.contains(values);
}
assert distinct;
if (columnCount != visibleColumnCount) {
if (index == null) {
createIndex(true);
}
return index.containsKey(ValueArray.get(values));
}
return map.containsKey(getKey(values));
}
private void createIndex(boolean fill) {
Builder<ValueArray, Boolean> indexBuilder = new MVMap.Builder<ValueArray, Boolean>()
.keyType(distinctType);
index = store.openMap("idx", indexBuilder);
if (fill) {
Cursor<ValueArray, Long> c = map.cursor(null);
while (c.hasNext()) {
Value[] v = getValue(c.next().getList());
ValueArray distinctRow = ValueArray.get(Arrays.copyOf(v, visibleColumnCount));
index.putIfAbsent(distinctRow, true);
}
}
}
@Override
public synchronized ResultExternal createShallowCopy() {
if (parent != null) {
......
......@@ -144,13 +144,48 @@ public class ResultTempTable implements ResultExternal {
closeable = new CloseImpl(session, table);
fileRef = tempFileDeleter.addFile(closeable, this);
}
/*
* If ORDER BY or DISTINCT is specified create the index immediately. If
* they are not specified index still may be created later if required
* for IN (SELECT ...) etc.
*/
if (sort != null || distinct) {
getIndex();
IndexColumn[] indexCols;
if (sort != null) {
int[] colIndex = sort.getQueryColumnIndexes();
int len = colIndex.length;
if (distinct) {
BitSet used = new BitSet();
indexCols = new IndexColumn[columnCount];
for (int i = 0; i < len; i++) {
int idx = colIndex[i];
used.set(idx);
IndexColumn indexColumn = createIndexColumn(idx);
indexColumn.sortType = sort.getSortTypes()[i];
indexCols[i] = indexColumn;
}
int idx = 0;
for (int i = len; i < columnCount; i++) {
idx = used.nextClearBit(idx);
indexCols[i] = createIndexColumn(idx);
idx++;
}
} else {
indexCols = new IndexColumn[len];
for (int i = 0; i < len; i++) {
IndexColumn indexColumn = createIndexColumn(colIndex[i]);
indexColumn.sortType = sort.getSortTypes()[i];
indexCols[i] = indexColumn;
}
}
} else {
indexCols = new IndexColumn[columnCount];
for (int i = 0; i < columnCount; i++) {
indexCols[i] = createIndexColumn(i);
}
}
String indexName = table.getSchema().getUniqueIndexName(session, table, Constants.PREFIX_INDEX);
int indexId = session.getDatabase().allocateObjectId();
IndexType indexType = IndexType.createNonUnique(true);
index = table.addIndex(session, indexName, indexId, indexCols, indexType, true, null);
if (closeable != null) {
closeable.index = index;
}
}
}
......@@ -171,50 +206,6 @@ public class ResultTempTable implements ResultExternal {
if (parent != null) {
return parent.getIndex();
}
if (index != null) {
return index;
}
IndexColumn[] indexCols;
if (sort != null) {
int[] colIndex = sort.getQueryColumnIndexes();
int len = colIndex.length;
if (distinct) {
BitSet used = new BitSet();
indexCols = new IndexColumn[columnCount];
for (int i = 0; i < len; i++) {
int idx = colIndex[i];
used.set(idx);
IndexColumn indexColumn = createIndexColumn(idx);
indexColumn.sortType = sort.getSortTypes()[i];
indexCols[i] = indexColumn;
}
int idx = 0;
for (int i = len; i < columnCount; i++) {
idx = used.nextClearBit(idx);
indexCols[i] = createIndexColumn(idx);
idx++;
}
} else {
indexCols = new IndexColumn[len];
for (int i = 0; i < len; i++) {
IndexColumn indexColumn = createIndexColumn(colIndex[i]);
indexColumn.sortType = sort.getSortTypes()[i];
indexCols[i] = indexColumn;
}
}
} else {
indexCols = new IndexColumn[columnCount];
for (int i = 0; i < columnCount; i++) {
indexCols[i] = createIndexColumn(i);
}
}
String indexName = table.getSchema().getUniqueIndexName(session, table, Constants.PREFIX_INDEX);
int indexId = session.getDatabase().allocateObjectId();
IndexType indexType = IndexType.createNonUnique(true);
index = table.addIndex(session, indexName, indexId, indexCols, indexType, true, null);
if (closeable != null) {
closeable.index = index;
}
return index;
}
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论