提交 411255cd authored 作者: Thomas Mueller's avatar Thomas Mueller

Hash indexes now are only used for single column indexes.

上级 62c5f801
/*
* Copyright 2004-2010 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.index;
import org.h2.engine.Session;
import org.h2.message.DbException;
import org.h2.result.SearchRow;
import org.h2.table.Column;
import org.h2.table.IndexColumn;
import org.h2.table.TableData;
import org.h2.value.Value;
import org.h2.value.ValueArray;
/**
* Base of hash indexes.
*/
public abstract class BaseHashIndex extends BaseIndex {
public BaseHashIndex(TableData table, int id, String indexName, IndexColumn[] columns, IndexType indexType) {
initBaseIndex(table, id, indexName, columns, indexType);
}
public void close(Session session) {
// nothing to do
}
public void remove(Session session) {
// nothing to do
}
/**
* Generate the search key from a row. Single column indexes are mapped to
* the value, multi-column indexes are mapped to an value array.
*
* @param row the row
* @return the value
*/
protected Value getKey(SearchRow row) {
if (columns.length == 1) {
Column column = columns[0];
int index = column.getColumnId();
Value v = row.getValue(index);
return v;
}
Value[] list = new Value[columns.length];
for (int i = 0; i < columns.length; i++) {
Column column = columns[i];
int index = column.getColumnId();
list[i] = row.getValue(index);
}
return ValueArray.get(list);
}
public double getCost(Session session, int[] masks) {
for (Column column : columns) {
int index = column.getColumnId();
int mask = masks[index];
if ((mask & IndexCondition.EQUALITY) != IndexCondition.EQUALITY) {
return Long.MAX_VALUE;
}
}
return 2;
}
public void checkRename() {
// ok
}
public boolean needRebuild() {
return true;
}
public boolean canGetFirstOrLast() {
return false;
}
public Cursor findFirstOrLast(Session session, boolean first) {
throw DbException.getUnsupportedException("HASH");
}
}
......@@ -10,33 +10,30 @@ import org.h2.engine.Session;
import org.h2.message.DbException;
import org.h2.result.Row;
import org.h2.result.SearchRow;
import org.h2.table.Column;
import org.h2.table.IndexColumn;
import org.h2.table.TableData;
import org.h2.util.IntIntHashMap;
import org.h2.util.ValueHashMap;
import org.h2.value.Value;
/**
* An unique index based on an in-memory hash map.
*/
public class HashIndex extends BaseHashIndex {
public class HashIndex extends BaseIndex {
private ValueHashMap<Integer> rows;
private IntIntHashMap intMap;
private TableData tableData;
protected final int indexColumn;
private final TableData tableData;
private ValueHashMap<Long> rows;
public HashIndex(TableData table, int id, String indexName, IndexColumn[] columns, IndexType indexType) {
super(table, id, indexName, columns, indexType);
initBaseIndex(table, id, indexName, columns, indexType);
this.indexColumn = columns[0].column.getColumnId();
this.tableData = table;
reset();
}
private void reset() {
if (columns.length == 1 && columns[0].getType() == Value.INT) {
intMap = new IntIntHashMap();
} else {
rows = ValueHashMap.newInstance(table.getDatabase());
}
rows = ValueHashMap.newInstance(table.getDatabase());
}
public void truncate(Session session) {
......@@ -44,27 +41,17 @@ public class HashIndex extends BaseHashIndex {
}
public void add(Session session, Row row) {
if (intMap != null) {
int key = row.getValue(columns[0].getColumnId()).getInt();
intMap.put(key, (int) row.getKey());
} else {
Value key = getKey(row);
Object old = rows.get(key);
if (old != null) {
// TODO index duplicate key for hash indexes: is this allowed?
throw getDuplicateKeyException();
}
rows.put(getKey(row), (int) row.getKey());
Value key = row.getValue(indexColumn);
Object old = rows.get(key);
if (old != null) {
// TODO index duplicate key for hash indexes: is this allowed?
throw getDuplicateKeyException();
}
rows.put(key, row.getKey());
}
public void remove(Session session, Row row) {
if (intMap != null) {
int key = row.getValue(columns[0].getColumnId()).getInt();
intMap.remove(key);
} else {
rows.remove(getKey(row));
}
rows.remove(row.getValue(indexColumn));
}
public Cursor find(Session session, SearchRow first, SearchRow last) {
......@@ -73,21 +60,11 @@ public class HashIndex extends BaseHashIndex {
throw DbException.throwInternalError();
}
Row result;
if (intMap != null) {
int key = first.getValue(columns[0].getColumnId()).getInt();
int pos = intMap.get(key);
if (pos != IntIntHashMap.NOT_FOUND) {
result = tableData.getRow(session, pos);
} else {
result = null;
}
Long pos = rows.get(first.getValue(indexColumn));
if (pos == null) {
result = null;
} else {
Integer pos = rows.get(getKey(first));
if (pos == null) {
result = null;
} else {
result = tableData.getRow(session, pos.intValue());
}
result = tableData.getRow(session, pos.intValue());
}
return new HashCursor(result);
}
......@@ -97,7 +74,51 @@ public class HashIndex extends BaseHashIndex {
}
public long getRowCountApproximation() {
return intMap != null ? intMap.size() : rows.size();
return rows.size();
}
public void close(Session session) {
// nothing to do
}
public void remove(Session session) {
// nothing to do
}
/**
* Generate the search key from a row. Only single column indexes are
* supported (multi-column indexes could be mapped to an value array, but
* that is much slower than using a tree based index).
*
* @param row the row
* @return the value
*/
public double getCost(Session session, int[] masks) {
for (Column column : columns) {
int index = column.getColumnId();
int mask = masks[index];
if ((mask & IndexCondition.EQUALITY) != IndexCondition.EQUALITY) {
return Long.MAX_VALUE;
}
}
return 2;
}
public void checkRename() {
// ok
}
public boolean needRebuild() {
return true;
}
public boolean canGetFirstOrLast() {
return false;
}
public Cursor findFirstOrLast(Session session, boolean first) {
throw DbException.getUnsupportedException("HASH");
}
}
......@@ -10,6 +10,7 @@ package org.h2.index;
* Represents information about the properties of an index
*/
public class IndexType {
private boolean primaryKey, persistent, unique, hash, scan;
private boolean belongsToConstraint;
......
......@@ -6,11 +6,11 @@
*/
package org.h2.index;
import java.util.ArrayList;
import org.h2.engine.Session;
import org.h2.result.Row;
import org.h2.result.SearchRow;
import org.h2.table.TableData;
import org.h2.util.IntArray;
/**
* Cursor implementation for non-unique hash index
......@@ -20,12 +20,12 @@ import org.h2.util.IntArray;
public class NonUniqueHashCursor implements Cursor {
private final Session session;
private final IntArray positions;
private final ArrayList<Long> positions;
private final TableData tableData;
private int index = -1;
public NonUniqueHashCursor(Session session, TableData tableData, IntArray positions) {
public NonUniqueHashCursor(Session session, TableData tableData, ArrayList<Long> positions) {
this.session = session;
this.tableData = tableData;
this.positions = positions;
......
......@@ -6,13 +6,14 @@
*/
package org.h2.index;
import java.util.ArrayList;
import org.h2.engine.Session;
import org.h2.message.DbException;
import org.h2.result.Row;
import org.h2.result.SearchRow;
import org.h2.table.IndexColumn;
import org.h2.table.TableData;
import org.h2.util.IntArray;
import org.h2.util.New;
import org.h2.util.ValueHashMap;
import org.h2.value.Value;
......@@ -21,9 +22,9 @@ import org.h2.value.Value;
*
* @author Sergi Vladykin
*/
public class NonUniqueHashIndex extends BaseHashIndex {
public class NonUniqueHashIndex extends HashIndex {
private ValueHashMap<IntArray> rows;
private ValueHashMap<ArrayList<Long>> rows;
private TableData tableData;
private long rowCount;
......@@ -43,13 +44,13 @@ public class NonUniqueHashIndex extends BaseHashIndex {
}
public void add(Session session, Row row) {
Value key = getKey(row);
IntArray positions = rows.get(key);
Value key = row.getValue(indexColumn);
ArrayList<Long> positions = rows.get(key);
if (positions == null) {
positions = new IntArray(1);
positions = New.arrayList();
rows.put(key, positions);
}
positions.add((int) row.getKey());
positions.add(row.getKey());
rowCount++;
}
......@@ -58,13 +59,13 @@ public class NonUniqueHashIndex extends BaseHashIndex {
// last row in table
reset();
} else {
Value key = getKey(row);
IntArray positions = rows.get(key);
Value key = row.getValue(indexColumn);
ArrayList<Long> positions = rows.get(key);
if (positions.size() == 1) {
// last row with such key
rows.remove(key);
} else {
positions.removeValue((int) row.getKey());
positions.remove(row.getKey());
}
rowCount--;
}
......@@ -79,7 +80,7 @@ public class NonUniqueHashIndex extends BaseHashIndex {
throw DbException.throwInternalError();
}
}
IntArray positions = rows.get(getKey(first));
ArrayList<Long> positions = rows.get(first.getValue(indexColumn));
return new NonUniqueHashCursor(session, tableData, positions);
}
......
......@@ -196,7 +196,7 @@ public class TableData extends Table {
index = new PageBtreeIndex(this, indexId, indexName, cols, indexType, create, session);
}
} else {
if (indexType.isHash()) {
if (indexType.isHash() && cols.length <= 1) {
if (indexType.isUnique()) {
index = new HashIndex(this, indexId, indexName, cols, indexType);
} else {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论