Unverified 提交 006fe1b0 authored 作者: Andrei Tokar's avatar Andrei Tokar 提交者: GitHub

Merge pull request #1328 from h2database/issue#1327

Change MVSecondaryIndex uniqueness check
...@@ -465,12 +465,16 @@ public class Comparison extends Condition { ...@@ -465,12 +465,16 @@ public class Comparison extends Condition {
} }
if (addIndex) { if (addIndex) {
if (l != null) { if (l != null) {
filter.addIndexCondition( if (l.getType() == right.getType() || right.getType() != Value.STRING_IGNORECASE) {
IndexCondition.get(compareType, l, right)); filter.addIndexCondition(
IndexCondition.get(compareType, l, right));
}
} else if (r != null) { } else if (r != null) {
int compareRev = getReversedCompareType(compareType); if (r.getType() == left.getType() || left.getType() != Value.STRING_IGNORECASE) {
filter.addIndexCondition( int compareRev = getReversedCompareType(compareType);
IndexCondition.get(compareRev, r, left)); filter.addIndexCondition(
IndexCondition.get(compareRev, r, left));
}
} }
} }
} }
......
...@@ -199,7 +199,7 @@ public class ExpressionColumn extends Expression { ...@@ -199,7 +199,7 @@ public class ExpressionColumn extends Expression {
@Override @Override
public int getType() { public int getType() {
return column.getType(); return column == null ? Value.UNKNOWN : column.getType();
} }
@Override @Override
......
...@@ -60,7 +60,7 @@ class MVPlainTempResult extends MVTempResult { ...@@ -60,7 +60,7 @@ class MVPlainTempResult extends MVTempResult {
*/ */
MVPlainTempResult(Database database, Expression[] expressions, int visibleColumnCount) { MVPlainTempResult(Database database, Expression[] expressions, int visibleColumnCount) {
super(database, expressions.length, visibleColumnCount); super(database, expressions.length, visibleColumnCount);
ValueDataType valueType = new ValueDataType(database.getCompareMode(), database, new int[columnCount]); ValueDataType valueType = new ValueDataType(database, new int[columnCount]);
Builder<Long, ValueArray> builder = new MVMap.Builder<Long, ValueArray>() Builder<Long, ValueArray> builder = new MVMap.Builder<Long, ValueArray>()
.valueType(valueType).singleWriter(); .valueType(valueType).singleWriter();
map = store.openMap("tmp", builder); map = store.openMap("tmp", builder);
......
...@@ -51,9 +51,8 @@ public class MVPrimaryIndex extends BaseIndex { ...@@ -51,9 +51,8 @@ public class MVPrimaryIndex extends BaseIndex {
for (int i = 0; i < columns.length; i++) { for (int i = 0; i < columns.length; i++) {
sortTypes[i] = SortOrder.ASCENDING; sortTypes[i] = SortOrder.ASCENDING;
} }
ValueDataType keyType = new ValueDataType(null, null, null); ValueDataType keyType = new ValueDataType();
ValueDataType valueType = new ValueDataType(db.getCompareMode(), db, ValueDataType valueType = new ValueDataType(db, sortTypes);
sortTypes);
mapName = "table." + getId(); mapName = "table." + getId();
Transaction t = mvTable.getTransactionBegin(); Transaction t = mvTable.getTransactionBegin();
dataMap = t.openMap(mapName, keyType, valueType); dataMap = t.openMap(mapName, keyType, valueType);
......
...@@ -166,12 +166,12 @@ class MVSortedTempResult extends MVTempResult { ...@@ -166,12 +166,12 @@ class MVSortedTempResult extends MVTempResult {
indexes = null; indexes = null;
} }
this.indexes = indexes; this.indexes = indexes;
ValueDataType keyType = new ValueDataType(database.getCompareMode(), database, sortTypes); ValueDataType keyType = new ValueDataType(database, sortTypes);
Builder<ValueArray, Long> builder = new MVMap.Builder<ValueArray, Long>().keyType(keyType); Builder<ValueArray, Long> builder = new MVMap.Builder<ValueArray, Long>().keyType(keyType);
map = store.openMap("tmp", builder); map = store.openMap("tmp", builder);
if (distinct && length != visibleColumnCount || distinctIndexes != null) { if (distinct && length != visibleColumnCount || distinctIndexes != null) {
int count = distinctIndexes != null ? distinctIndexes.length : visibleColumnCount; int count = distinctIndexes != null ? distinctIndexes.length : visibleColumnCount;
ValueDataType distinctType = new ValueDataType(database.getCompareMode(), database, new int[count]); ValueDataType distinctType = new ValueDataType(database, new int[count]);
Builder<ValueArray, Boolean> indexBuilder = new MVMap.Builder<ValueArray, Boolean>().keyType(distinctType); Builder<ValueArray, Boolean> indexBuilder = new MVMap.Builder<ValueArray, Boolean>().keyType(distinctType);
index = store.openMap("idx", indexBuilder); index = store.openMap("idx", indexBuilder);
} }
......
...@@ -93,7 +93,7 @@ public class MVSpatialIndex extends BaseIndex implements SpatialIndex, MVIndex { ...@@ -93,7 +93,7 @@ public class MVSpatialIndex extends BaseIndex implements SpatialIndex, MVIndex {
checkIndexColumnTypes(columns); checkIndexColumnTypes(columns);
} }
String mapName = "index." + getId(); String mapName = "index." + getId();
ValueDataType vt = new ValueDataType(null, null, null); ValueDataType vt = new ValueDataType(db, null);
VersionedValue.Type valueType = new VersionedValue.Type(vt); VersionedValue.Type valueType = new VersionedValue.Type(vt);
MVRTreeMap.Builder<VersionedValue> mapBuilder = MVRTreeMap.Builder<VersionedValue> mapBuilder =
new MVRTreeMap.Builder<VersionedValue>(). new MVRTreeMap.Builder<VersionedValue>().
......
...@@ -160,9 +160,8 @@ public class MVTableEngine implements TableEngine { ...@@ -160,9 +160,8 @@ public class MVTableEngine implements TableEngine {
if (!db.getSettings().reuseSpace) { if (!db.getSettings().reuseSpace) {
store.setReuseSpace(false); store.setReuseSpace(false);
} }
this.transactionStore = new TransactionStore( this.transactionStore = new TransactionStore(store,
store, new ValueDataType(db, null), db.getLockTimeout());
new ValueDataType(db.getCompareMode(), db, null), db.getLockTimeout());
} catch (IllegalStateException e) { } catch (IllegalStateException e) {
throw convertIllegalStateException(e); throw convertIllegalStateException(e);
} }
......
...@@ -12,7 +12,10 @@ import java.sql.ResultSet; ...@@ -12,7 +12,10 @@ import java.sql.ResultSet;
import java.sql.ResultSetMetaData; import java.sql.ResultSetMetaData;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Arrays; import java.util.Arrays;
import java.util.Objects;
import org.h2.api.ErrorCode; import org.h2.api.ErrorCode;
import org.h2.engine.Database;
import org.h2.engine.Mode;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.mvstore.DataUtils; import org.h2.mvstore.DataUtils;
import org.h2.mvstore.WriteBuffer; import org.h2.mvstore.WriteBuffer;
...@@ -33,6 +36,7 @@ import org.h2.value.ValueBytes; ...@@ -33,6 +36,7 @@ import org.h2.value.ValueBytes;
import org.h2.value.ValueDate; import org.h2.value.ValueDate;
import org.h2.value.ValueDecimal; import org.h2.value.ValueDecimal;
import org.h2.value.ValueDouble; import org.h2.value.ValueDouble;
import org.h2.value.ValueEnum;
import org.h2.value.ValueFloat; import org.h2.value.ValueFloat;
import org.h2.value.ValueGeometry; import org.h2.value.ValueGeometry;
import org.h2.value.ValueInt; import org.h2.value.ValueInt;
...@@ -73,12 +77,22 @@ public class ValueDataType implements DataType { ...@@ -73,12 +77,22 @@ public class ValueDataType implements DataType {
final DataHandler handler; final DataHandler handler;
final CompareMode compareMode; final CompareMode compareMode;
protected final Mode mode;
final int[] sortTypes; final int[] sortTypes;
SpatialDataType spatialType; SpatialDataType spatialType;
public ValueDataType(CompareMode compareMode, DataHandler handler, public ValueDataType() {
this(CompareMode.getInstance(null, 0), Mode.getRegular(), null, null);
}
public ValueDataType(Database database, int[] sortTypes) {
this(database.getCompareMode(), database.getMode(), database, sortTypes);
}
private ValueDataType(CompareMode compareMode, Mode mode, DataHandler handler,
int[] sortTypes) { int[] sortTypes) {
this.compareMode = compareMode; this.compareMode = compareMode;
this.mode = mode;
this.handler = handler; this.handler = handler;
this.sortTypes = sortTypes; this.sortTypes = sortTypes;
} }
...@@ -103,7 +117,13 @@ public class ValueDataType implements DataType { ...@@ -103,7 +117,13 @@ public class ValueDataType implements DataType {
int len = Math.min(al, bl); int len = Math.min(al, bl);
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
int sortType = sortTypes == null ? SortOrder.ASCENDING : sortTypes[i]; int sortType = sortTypes == null ? SortOrder.ASCENDING : sortTypes[i];
int comp = compareValues(ax[i], bx[i], sortType); Value one = ax[i];
Value two = bx[i];
if (one == null || two == null) {
return compareValues(ax[len - 1], bx[len - 1], SortOrder.ASCENDING);
}
int comp = compareValues(one, two, sortType);
if (comp != 0) { if (comp != 0) {
return comp; return comp;
} }
...@@ -136,7 +156,18 @@ public class ValueDataType implements DataType { ...@@ -136,7 +156,18 @@ public class ValueDataType implements DataType {
if (aNull || bNull) { if (aNull || bNull) {
return SortOrder.compareNull(aNull, sortType); return SortOrder.compareNull(aNull, sortType);
} }
int t2 = Value.getHigherOrder(a.getType(), b.getType());
if (t2 == Value.ENUM) {
String[] enumerators = ValueEnum.getEnumeratorsForBinaryOperation(a, b);
a = a.convertToEnum(enumerators);
b = b.convertToEnum(enumerators);
} else {
a = a.convertTo(t2, -1, mode);
b = b.convertTo(t2, -1, mode);
}
int comp = a.compareTypeSafe(b, compareMode); int comp = a.compareTypeSafe(b, compareMode);
if ((sortType & SortOrder.DESCENDING) != 0) { if ((sortType & SortOrder.DESCENDING) != 0) {
comp = -comp; comp = -comp;
} }
......
...@@ -616,18 +616,14 @@ public class Recover extends Tool implements DataHandler { ...@@ -616,18 +616,14 @@ public class Recover extends Tool implements DataHandler {
} }
try { try {
// extract the metadata so we can dump the settings // extract the metadata so we can dump the settings
ValueDataType type = new ValueDataType();
for (String mapName : mv.getMapNames()) { for (String mapName : mv.getMapNames()) {
if (!mapName.startsWith("table.")) { if (!mapName.startsWith("table.")) {
continue; continue;
} }
String tableId = mapName.substring("table.".length()); String tableId = mapName.substring("table.".length());
if (Integer.parseInt(tableId) == 0) { if (Integer.parseInt(tableId) == 0) {
ValueDataType keyType = new ValueDataType( TransactionMap<Value, Value> dataMap = store.begin().openMap(mapName, type, type);
null, this, null);
ValueDataType valueType = new ValueDataType(
null, this, null);
TransactionMap<Value, Value> dataMap = store.begin().openMap(
mapName, keyType, valueType);
Iterator<Value> dataIt = dataMap.keyIterator(null); Iterator<Value> dataIt = dataMap.keyIterator(null);
while (dataIt.hasNext()) { while (dataIt.hasNext()) {
Value rowId = dataIt.next(); Value rowId = dataIt.next();
...@@ -660,12 +656,7 @@ public class Recover extends Tool implements DataHandler { ...@@ -660,12 +656,7 @@ public class Recover extends Tool implements DataHandler {
if (Integer.parseInt(tableId) == 0) { if (Integer.parseInt(tableId) == 0) {
continue; continue;
} }
ValueDataType keyType = new ValueDataType( TransactionMap<Value, Value> dataMap = store.begin().openMap(mapName, type, type);
null, this, null);
ValueDataType valueType = new ValueDataType(
null, this, null);
TransactionMap<Value, Value> dataMap = store.begin().openMap(
mapName, keyType, valueType);
Iterator<Value> dataIt = dataMap.keyIterator(null); Iterator<Value> dataIt = dataMap.keyIterator(null);
boolean init = false; boolean init = false;
while (dataIt.hasNext()) { while (dataIt.hasNext()) {
......
...@@ -2866,7 +2866,7 @@ CREATE TABLE TEST2(ID INT PRIMARY KEY, NAME VARCHAR(255)); ...@@ -2866,7 +2866,7 @@ CREATE TABLE TEST2(ID INT PRIMARY KEY, NAME VARCHAR(255));
create unique index idx_test2_name on test2(name); create unique index idx_test2_name on test2(name);
> ok > ok
INSERT INTO TEST2 VALUES(1, 'HElLo'); INSERT INTO TEST2 VALUES(1, 'hElLo');
> update count: 1 > update count: 1
INSERT INTO TEST2 VALUES(2, 'World'); INSERT INTO TEST2 VALUES(2, 'World');
...@@ -2886,7 +2886,7 @@ select * from test where name='HELLO'; ...@@ -2886,7 +2886,7 @@ select * from test where name='HELLO';
select * from test2 where name='HELLO'; select * from test2 where name='HELLO';
> ID NAME > ID NAME
> -- ----- > -- -----
> 1 HElLo > 1 hElLo
> rows: 1 > rows: 1
select * from test where name like 'HELLO'; select * from test where name like 'HELLO';
...@@ -2897,26 +2897,26 @@ select * from test where name like 'HELLO'; ...@@ -2897,26 +2897,26 @@ select * from test where name like 'HELLO';
select * from test2 where name like 'HELLO'; select * from test2 where name like 'HELLO';
> ID NAME > ID NAME
> -- ----- > -- -----
> 1 HElLo > 1 hElLo
> rows: 1 > rows: 1
explain plan for select * from test2, test where test2.name = test.name; explain plan for select * from test2, test where test2.name = test.name;
>> SELECT TEST2.ID, TEST2.NAME, TEST.ID, TEST.NAME FROM PUBLIC.TEST2 /* PUBLIC.TEST2.tableScan */ INNER JOIN PUBLIC.TEST /* PUBLIC.IDX_TEST_NAME: NAME = TEST2.NAME */ ON 1=1 WHERE TEST2.NAME = TEST.NAME >> SELECT TEST2.ID, TEST2.NAME, TEST.ID, TEST.NAME FROM PUBLIC.TEST2 /* PUBLIC.TEST2.tableScan */ INNER JOIN PUBLIC.TEST /* PUBLIC.TEST.tableScan */ ON 1=1 WHERE TEST2.NAME = TEST.NAME
select * from test2, test where test2.name = test.name; select * from test2, test where test2.name = test.name;
> ID NAME ID NAME > ID NAME ID NAME
> -- ----- -- ----- > -- ----- -- -----
> 1 HElLo 1 Hello > 1 hElLo 1 Hello
> 2 World 2 World > 2 World 2 World
> rows: 2 > rows: 2
explain plan for select * from test, test2 where test2.name = test.name; explain plan for select * from test, test2 where test2.name = test.name;
>> SELECT TEST.ID, TEST.NAME, TEST2.ID, TEST2.NAME FROM PUBLIC.TEST2 /* PUBLIC.TEST2.tableScan */ INNER JOIN PUBLIC.TEST /* PUBLIC.IDX_TEST_NAME: NAME = TEST2.NAME */ ON 1=1 WHERE TEST2.NAME = TEST.NAME >> SELECT TEST.ID, TEST.NAME, TEST2.ID, TEST2.NAME FROM PUBLIC.TEST2 /* PUBLIC.TEST2.tableScan */ INNER JOIN PUBLIC.TEST /* PUBLIC.TEST.tableScan */ ON 1=1 WHERE TEST2.NAME = TEST.NAME
select * from test, test2 where test2.name = test.name; select * from test, test2 where test2.name = test.name;
> ID NAME ID NAME > ID NAME ID NAME
> -- ----- -- ----- > -- ----- -- -----
> 1 Hello 1 HElLo > 1 Hello 1 hElLo
> 2 World 2 World > 2 World 2 World
> rows: 2 > rows: 2
...@@ -2924,12 +2924,12 @@ create index idx_test2_name on test2(name); ...@@ -2924,12 +2924,12 @@ create index idx_test2_name on test2(name);
> ok > ok
explain plan for select * from test2, test where test2.name = test.name; explain plan for select * from test2, test where test2.name = test.name;
>> SELECT TEST2.ID, TEST2.NAME, TEST.ID, TEST.NAME FROM PUBLIC.TEST2 /* PUBLIC.TEST2.tableScan */ INNER JOIN PUBLIC.TEST /* PUBLIC.IDX_TEST_NAME: NAME = TEST2.NAME */ ON 1=1 WHERE TEST2.NAME = TEST.NAME >> SELECT TEST2.ID, TEST2.NAME, TEST.ID, TEST.NAME FROM PUBLIC.TEST /* PUBLIC.TEST.tableScan */ INNER JOIN PUBLIC.TEST2 /* PUBLIC.IDX_TEST2_NAME: NAME = TEST.NAME */ ON 1=1 WHERE TEST2.NAME = TEST.NAME
select * from test2, test where test2.name = test.name; select * from test2, test where test2.name = test.name;
> ID NAME ID NAME > ID NAME ID NAME
> -- ----- -- ----- > -- ----- -- -----
> 1 HElLo 1 Hello > 1 hElLo 1 Hello
> 2 World 2 World > 2 World 2 World
> rows: 2 > rows: 2
...@@ -2939,7 +2939,7 @@ explain plan for select * from test, test2 where test2.name = test.name; ...@@ -2939,7 +2939,7 @@ explain plan for select * from test, test2 where test2.name = test.name;
select * from test, test2 where test2.name = test.name; select * from test, test2 where test2.name = test.name;
> ID NAME ID NAME > ID NAME ID NAME
> -- ----- -- ----- > -- ----- -- -----
> 1 Hello 1 HElLo > 1 Hello 1 hElLo
> 2 World 2 World > 2 World 2 World
> rows: 2 > rows: 2
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论