提交 c1a0982e authored 作者: Thomas Mueller's avatar Thomas Mueller

New experimental page store.

上级 724518e5
...@@ -20,7 +20,7 @@ Change Log ...@@ -20,7 +20,7 @@ Change Log
<h2>Next Version (unreleased)</h2> <h2>Next Version (unreleased)</h2>
<ul><li>ResultSetMetaData.getColumnClassName returned the wrong <ul><li>ResultSetMetaData.getColumnClassName returned the wrong
class for CLOB and BLOB columns. class for CLOB and BLOB columns.
</li><li>Fulltext search: Data is no longer deleted and </li><li>Fulltext search: Data is no longer deleted and
re-inserted if the indexed columns didn't change. re-inserted if the indexed columns didn't change.
</li><li>In some situations, an ArrayIndexOutOfBoundsException was thrown when adding rows. </li><li>In some situations, an ArrayIndexOutOfBoundsException was thrown when adding rows.
This was caused by a bug in the b-tree code. This was caused by a bug in the b-tree code.
......
...@@ -419,6 +419,8 @@ See also <a href="build.html#providing_patches">Providing Patches</a>. ...@@ -419,6 +419,8 @@ See also <a href="build.html#providing_patches">Providing Patches</a>.
</li><li>MySQL compatibility: DatabaseMetaData.stores*() methods should return the same values. Test with SquirrelSQL. </li><li>MySQL compatibility: DatabaseMetaData.stores*() methods should return the same values. Test with SquirrelSQL.
</li><li>MS SQL Server compatibility: support DATEPART syntax. </li><li>MS SQL Server compatibility: support DATEPART syntax.
</li><li>Oracle compatibility: support CREATE OR REPLACE VIEW syntax. </li><li>Oracle compatibility: support CREATE OR REPLACE VIEW syntax.
</li><li>Sybase/DB2/Oracle compatibility: support out parameters in stored procedures - See http://code.google.com/p/h2database/issues/detail?id=83
</li><li>Support INTERVAL data type (see Oracle and others).
</li></ul> </li></ul>
<h2>Not Planned</h2> <h2>Not Planned</h2>
......
...@@ -97,7 +97,7 @@ public class Set extends Prepared { ...@@ -97,7 +97,7 @@ public class Set extends Prepared {
CompareMode compareMode; CompareMode compareMode;
StringBuilder buff = new StringBuilder(stringValue); StringBuilder buff = new StringBuilder(stringValue);
if (stringValue.equals(CompareMode.OFF)) { if (stringValue.equals(CompareMode.OFF)) {
compareMode = new CompareMode(null, 0); compareMode = CompareMode.getInstance(null, 0);
} else { } else {
int strength = getIntValue(); int strength = getIntValue();
buff.append(" STRENGTH "); buff.append(" STRENGTH ");
...@@ -110,7 +110,7 @@ public class Set extends Prepared { ...@@ -110,7 +110,7 @@ public class Set extends Prepared {
} else if (strength == Collator.TERTIARY) { } else if (strength == Collator.TERTIARY) {
buff.append("TERTIARY"); buff.append("TERTIARY");
} }
compareMode = new CompareMode(stringValue, strength); compareMode = CompareMode.getInstance(stringValue, strength);
} }
addOrUpdateSetting(name, buff.toString(), 0); addOrUpdateSetting(name, buff.toString(), 0);
database.setCompareMode(compareMode); database.setCompareMode(compareMode);
......
...@@ -330,7 +330,8 @@ public class ConstraintReferential extends Constraint { ...@@ -330,7 +330,8 @@ public class ConstraintReferential extends Constraint {
} }
private boolean found(Session session, Index searchIndex, SearchRow check, Row excluding) throws SQLException { private boolean found(Session session, Index searchIndex, SearchRow check, Row excluding) throws SQLException {
searchIndex.getTable().lock(session, false, false); Table table = searchIndex.getTable();
table.lock(session, false, false);
Cursor cursor = searchIndex.find(session, check, check); Cursor cursor = searchIndex.find(session, check, check);
while (cursor.next()) { while (cursor.next()) {
SearchRow found; SearchRow found;
...@@ -344,7 +345,7 @@ public class ConstraintReferential extends Constraint { ...@@ -344,7 +345,7 @@ public class ConstraintReferential extends Constraint {
int idx = cols[i].getColumnId(); int idx = cols[i].getColumnId();
Value c = check.getValue(idx); Value c = check.getValue(idx);
Value f = found.getValue(idx); Value f = found.getValue(idx);
if (database.compareTypeSave(c, f) != 0) { if (table.compareTypeSave(c, f) != 0) {
allEqual = false; allEqual = false;
break; break;
} }
......
...@@ -169,7 +169,7 @@ public class Database implements DataHandler { ...@@ -169,7 +169,7 @@ public class Database implements DataHandler {
private boolean reconnectChangePending; private boolean reconnectChangePending;
public Database(String name, ConnectionInfo ci, String cipher) throws SQLException { public Database(String name, ConnectionInfo ci, String cipher) throws SQLException {
this.compareMode = new CompareMode(null, 0); this.compareMode = CompareMode.getInstance(null, 0);
this.persistent = ci.isPersistent(); this.persistent = ci.isPersistent();
this.filePasswordHash = ci.getFilePasswordHash(); this.filePasswordHash = ci.getFilePasswordHash();
this.databaseName = name; this.databaseName = name;
......
...@@ -291,7 +291,7 @@ public abstract class BaseIndex extends SchemaObjectBase implements Index { ...@@ -291,7 +291,7 @@ public abstract class BaseIndex extends SchemaObjectBase implements Index {
} }
return SortOrder.compareNull(aNull, bNull, sortType); return SortOrder.compareNull(aNull, bNull, sortType);
} }
int comp = database.compareTypeSave(a, b); int comp = table.compareTypeSave(a, b);
if ((sortType & SortOrder.DESCENDING) != 0) { if ((sortType & SortOrder.DESCENDING) != 0) {
comp = -comp; comp = -comp;
} }
......
...@@ -21,6 +21,7 @@ import org.h2.index.PageScanIndex; ...@@ -21,6 +21,7 @@ import org.h2.index.PageScanIndex;
import org.h2.log.SessionState; import org.h2.log.SessionState;
import org.h2.message.Message; import org.h2.message.Message;
import org.h2.message.Trace; import org.h2.message.Trace;
import org.h2.message.TraceSystem;
import org.h2.result.Row; import org.h2.result.Row;
import org.h2.schema.Schema; import org.h2.schema.Schema;
import org.h2.table.Column; import org.h2.table.Column;
...@@ -35,6 +36,7 @@ import org.h2.util.FileUtils; ...@@ -35,6 +36,7 @@ import org.h2.util.FileUtils;
import org.h2.util.New; import org.h2.util.New;
import org.h2.util.ObjectArray; import org.h2.util.ObjectArray;
import org.h2.util.StringUtils; import org.h2.util.StringUtils;
import org.h2.value.CompareMode;
import org.h2.value.Value; import org.h2.value.Value;
import org.h2.value.ValueInt; import org.h2.value.ValueInt;
import org.h2.value.ValueString; import org.h2.value.ValueString;
...@@ -174,7 +176,7 @@ public class PageStore implements CacheWriter { ...@@ -174,7 +176,7 @@ public class PageStore implements CacheWriter {
this.database = database; this.database = database;
trace = database.getTrace(Trace.PAGE_STORE); trace = database.getTrace(Trace.PAGE_STORE);
int test; int test;
// trace.setLevel(TraceSystem.DEBUG); trace.setLevel(TraceSystem.DEBUG);
this.cacheSize = cacheSizeDefault; this.cacheSize = cacheSizeDefault;
String cacheType = database.getCacheType(); String cacheType = database.getCacheType();
this.cache = CacheLRU.getCache(this, cacheType, cacheSize); this.cache = CacheLRU.getCache(this, cacheType, cacheSize);
...@@ -809,8 +811,8 @@ public class PageStore implements CacheWriter { ...@@ -809,8 +811,8 @@ public class PageStore implements CacheWriter {
cols.add(new Column("TYPE", Value.INT)); cols.add(new Column("TYPE", Value.INT));
cols.add(new Column("PARENT", Value.INT)); cols.add(new Column("PARENT", Value.INT));
cols.add(new Column("HEAD", Value.INT)); cols.add(new Column("HEAD", Value.INT));
cols.add(new Column("OPTIONS", Value.STRING));
cols.add(new Column("COLUMNS", Value.STRING)); cols.add(new Column("COLUMNS", Value.STRING));
// new CompareMode()
metaSchema = new Schema(database, 0, "", null, true); metaSchema = new Schema(database, 0, "", null, true);
int headPos = metaTableRootPageId; int headPos = metaTableRootPageId;
metaTable = new TableData(metaSchema, "PAGE_INDEX", metaTable = new TableData(metaSchema, "PAGE_INDEX",
...@@ -843,7 +845,8 @@ public class PageStore implements CacheWriter { ...@@ -843,7 +845,8 @@ public class PageStore implements CacheWriter {
int type = row.getValue(1).getInt(); int type = row.getValue(1).getInt();
int parent = row.getValue(2).getInt(); int parent = row.getValue(2).getInt();
int headPos = row.getValue(3).getInt(); int headPos = row.getValue(3).getInt();
String columnList = row.getValue(4).getString(); String options = row.getValue(4).getString();
String columnList = row.getValue(5).getString();
String[] columns = StringUtils.arraySplit(columnList, ',', false); String[] columns = StringUtils.arraySplit(columnList, ',', false);
IndexType indexType = IndexType.createNonUnique(true); IndexType indexType = IndexType.createNonUnique(true);
Index meta; Index meta;
...@@ -857,6 +860,9 @@ public class PageStore implements CacheWriter { ...@@ -857,6 +860,9 @@ public class PageStore implements CacheWriter {
columnArray.add(col); columnArray.add(col);
} }
TableData table = new TableData(metaSchema, "T" + id, id, columnArray, true, true, false, headPos, session); TableData table = new TableData(metaSchema, "T" + id, id, columnArray, true, true, false, headPos, session);
String[] ops = StringUtils.arraySplit(options, ',', true);
CompareMode mode = CompareMode.getInstance(ops[0], Integer.parseInt(ops[1]));
table.setCompareMode(mode);
meta = table.getScanIndex(session); meta = table.getScanIndex(session);
} else { } else {
PageScanIndex p = (PageScanIndex) metaObjects.get(parent); PageScanIndex p = (PageScanIndex) metaObjects.get(parent);
...@@ -889,16 +895,20 @@ public class PageStore implements CacheWriter { ...@@ -889,16 +895,20 @@ public class PageStore implements CacheWriter {
columnIndexes[i] = String.valueOf(columns[i].getColumnId()); columnIndexes[i] = String.valueOf(columns[i].getColumnId());
} }
String columnList = StringUtils.arrayCombine(columnIndexes, ','); String columnList = StringUtils.arrayCombine(columnIndexes, ',');
addMeta(index.getId(), type, index.getTable().getId(), index.getHeadPos(), columnList, session); Table table = index.getTable();
CompareMode mode = table.getCompareMode();
String options = mode.getName()+ "," + mode.getStrength();
addMeta(index.getId(), type, table.getId(), index.getHeadPos(), options, columnList, session);
} }
private void addMeta(int id, int type, int parent, int headPos, String columnList, Session session) throws SQLException { private void addMeta(int id, int type, int parent, int headPos, String options, String columnList, Session session) throws SQLException {
Row row = metaTable.getTemplateRow(); Row row = metaTable.getTemplateRow();
row.setValue(0, ValueInt.get(id)); row.setValue(0, ValueInt.get(id));
row.setValue(1, ValueInt.get(type)); row.setValue(1, ValueInt.get(type));
row.setValue(2, ValueInt.get(parent)); row.setValue(2, ValueInt.get(parent));
row.setValue(3, ValueInt.get(headPos)); row.setValue(3, ValueInt.get(headPos));
row.setValue(4, ValueString.get(columnList)); row.setValue(4, ValueString.get(options));
row.setValue(5, ValueString.get(columnList));
row.setPos(id + 1); row.setPos(id + 1);
metaIndex.add(session, row); metaIndex.add(session, row);
} }
......
...@@ -35,6 +35,7 @@ import org.h2.schema.Sequence; ...@@ -35,6 +35,7 @@ import org.h2.schema.Sequence;
import org.h2.schema.TriggerObject; import org.h2.schema.TriggerObject;
import org.h2.util.New; import org.h2.util.New;
import org.h2.util.ObjectArray; import org.h2.util.ObjectArray;
import org.h2.value.CompareMode;
import org.h2.value.DataType; import org.h2.value.DataType;
import org.h2.value.Value; import org.h2.value.Value;
import org.h2.value.ValueNull; import org.h2.value.ValueNull;
...@@ -85,6 +86,11 @@ public abstract class Table extends SchemaObjectBase { ...@@ -85,6 +86,11 @@ public abstract class Table extends SchemaObjectBase {
*/ */
protected int memoryPerRow; protected int memoryPerRow;
/**
* The compare mode used for this table.
*/
protected CompareMode compareMode;
private final HashMap<String, Column> columnMap = New.hashMap(); private final HashMap<String, Column> columnMap = New.hashMap();
private boolean persistIndexes; private boolean persistIndexes;
private boolean persistData; private boolean persistData;
...@@ -100,6 +106,7 @@ public abstract class Table extends SchemaObjectBase { ...@@ -100,6 +106,7 @@ public abstract class Table extends SchemaObjectBase {
initSchemaObjectBase(schema, id, name, Trace.TABLE); initSchemaObjectBase(schema, id, name, Trace.TABLE);
this.persistIndexes = persistIndexes; this.persistIndexes = persistIndexes;
this.persistData = persistData; this.persistData = persistData;
compareMode = schema.getDatabase().getCompareMode();
} }
public void rename(String newName) throws SQLException { public void rename(String newName) throws SQLException {
...@@ -904,4 +911,21 @@ public abstract class Table extends SchemaObjectBase { ...@@ -904,4 +911,21 @@ public abstract class Table extends SchemaObjectBase {
return persistData; return persistData;
} }
/**
* Compare two values with the current comparison mode. The values must be
* of the same type.
*
* @param a the first value
* @param b the second value
* @return 0 if both values are equal, -1 if the first value is smaller, and
* 1 otherwise
*/
public int compareTypeSave(Value a, Value b) throws SQLException {
return a.compareTypeSave(b, compareMode);
}
public CompareMode getCompareMode() {
return compareMode;
}
} }
...@@ -43,6 +43,7 @@ import org.h2.util.New; ...@@ -43,6 +43,7 @@ import org.h2.util.New;
import org.h2.util.ObjectArray; import org.h2.util.ObjectArray;
import org.h2.util.StatementBuilder; import org.h2.util.StatementBuilder;
import org.h2.util.StringUtils; import org.h2.util.StringUtils;
import org.h2.value.CompareMode;
import org.h2.value.DataType; import org.h2.value.DataType;
import org.h2.value.Value; import org.h2.value.Value;
...@@ -699,4 +700,8 @@ public class TableData extends Table implements RecordReader { ...@@ -699,4 +700,8 @@ public class TableData extends Table implements RecordReader {
return scanIndex.getRowCountApproximation(); return scanIndex.getRowCountApproximation();
} }
public void setCompareMode(CompareMode compareMode) {
this.compareMode = compareMode;
}
} }
...@@ -27,19 +27,16 @@ public class CompareMode { ...@@ -27,19 +27,16 @@ public class CompareMode {
*/ */
public static final String OFF = "OFF"; public static final String OFF = "OFF";
private final Collator collator; private static CompareMode lastUsed;
private final String name; private final String name;
private final int strength;
private final Collator collator;
private final SmallLRUCache<String, CollationKey> collationKeys; private final SmallLRUCache<String, CollationKey> collationKeys;
/** private CompareMode(String name, int strength) {
* Create a new compare mode with the given collator and cache size. this.name = name;
* The cache is used to speed up comparison when using a collator; this.strength = strength;
* CollationKey objects are cached.
*
* @param name the collation name or null
* @param strength the collation strength
*/
public CompareMode(String name, int strength) {
this.collator = CompareMode.getCollator(name); this.collator = CompareMode.getCollator(name);
int cacheSize = 0; int cacheSize = 0;
if (collator != null) { if (collator != null) {
...@@ -51,7 +48,28 @@ public class CompareMode { ...@@ -51,7 +48,28 @@ public class CompareMode {
} else { } else {
collationKeys = null; collationKeys = null;
} }
this.name = name == null ? OFF : name; }
/**
* Create a new compare mode with the given collator and strength. If
* required, a new CompareMode is created, or if possible the last one is
* returned. A cache is used to speed up comparison when using a collator;
* CollationKey objects are cached.
*
* @param name the collation name or null
* @param strength the collation strength
* @return the compare mode
*/
public static CompareMode getInstance(String name, int strength) {
if (lastUsed != null) {
if (StringUtils.equals(lastUsed.name, name)) {
if (lastUsed.strength == strength) {
return lastUsed;
}
}
}
lastUsed = new CompareMode(name, strength);
return lastUsed;
} }
/** /**
...@@ -178,7 +196,11 @@ public class CompareMode { ...@@ -178,7 +196,11 @@ public class CompareMode {
} }
public String getName() { public String getName() {
return name; return name == null ? OFF : name;
}
public int getStrength() {
return strength;
} }
} }
...@@ -295,12 +295,9 @@ java org.h2.test.TestAll timer ...@@ -295,12 +295,9 @@ java org.h2.test.TestAll timer
shell tool: document encoding problem. mac: use shell tool: document encoding problem. mac: use
java -Dfile.encoding=UTF-8; java -Dfile.encoding=UTF-8;
BaseIndex or TableData should have its own compareMode TableData should have its own compareMode
(default is: Database.compareMode when created). (copy of Database.compareMode when created).
standard: COLLATE for each column (MySQL, SQL Server)
stored in the pageStore as well. stored in the pageStore as well.
check syntax in other databases.
this mean changing the collation is allowed if there are tables.
test case for running out of disk space (using a special file system) test case for running out of disk space (using a special file system)
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
package org.h2.test.unit; package org.h2.test.unit;
import java.sql.SQLException; import java.sql.SQLException;
import java.text.Collator;
import org.h2.expression.CompareLike; import org.h2.expression.CompareLike;
import org.h2.test.TestBase; import org.h2.test.TestBase;
...@@ -27,7 +28,24 @@ public class TestPattern extends TestBase { ...@@ -27,7 +28,24 @@ public class TestPattern extends TestBase {
} }
public void test() throws SQLException { public void test() throws SQLException {
CompareMode mode = new CompareMode(null, 0); testCompareModeReuse();
testPattern();
}
private void testCompareModeReuse() {
CompareMode mode1, mode2;
mode1 = CompareMode.getInstance(null, 0);
mode2 = CompareMode.getInstance(null, 0);
assertTrue(mode1 == mode2);
mode1 = CompareMode.getInstance("DE", Collator.SECONDARY);
assertFalse(mode1 == mode2);
mode2 = CompareMode.getInstance("DE", Collator.SECONDARY);
assertTrue(mode1 == mode2);
}
private void testPattern() throws SQLException {
CompareMode mode = CompareMode.getInstance(null, 0);
CompareLike comp = new CompareLike(mode, null, null, null, false); CompareLike comp = new CompareLike(mode, null, null, null, false);
test(comp, "B", "%_"); test(comp, "B", "%_");
test(comp, "A", "A%"); test(comp, "A", "A%");
......
...@@ -31,7 +31,7 @@ import org.h2.value.ValueInt; ...@@ -31,7 +31,7 @@ import org.h2.value.ValueInt;
*/ */
public class TestValueHashMap extends TestBase implements DataHandler { public class TestValueHashMap extends TestBase implements DataHandler {
CompareMode compareMode = new CompareMode(null, 0); CompareMode compareMode = CompareMode.getInstance(null, 0);
/** /**
* Run just this test. * Run just this test.
......
...@@ -589,4 +589,5 @@ handing bonita placed euros embeds reliability singular unregister quotas ...@@ -589,4 +589,5 @@ handing bonita placed euros embeds reliability singular unregister quotas
overall httpdocs tigris eclemma separates underscore yajsw she her truncating overall httpdocs tigris eclemma separates underscore yajsw she her truncating
relocating smtps smtp osde joist catching guesses delimiters shortlist sheet relocating smtps smtp osde joist catching guesses delimiters shortlist sheet
rowspan cheat partitioning datepart dreamsource toussi locates fred rowspan cheat partitioning datepart dreamsource toussi locates fred
longnvarchar collate localdb nan bootclasspath bcp retrotranslator iterable longnvarchar collate localdb nan bootclasspath bcp retrotranslator iterable
\ No newline at end of file ops
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论