提交 00df2d41 authored 作者: Thomas Mueller's avatar Thomas Mueller

Page store: long keys

上级 c670a577
...@@ -737,6 +737,11 @@ CREATE USER statement. If you run the script against a database that was created ...@@ -737,6 +737,11 @@ CREATE USER statement. If you run the script against a database that was created
user, or if there are conflicting users, running the script will fail. Consider running the script user, or if there are conflicting users, running the script will fail. Consider running the script
against a database that was created with a user name that is not in the script. against a database that was created with a user name that is not in the script.
</p> </p>
<p>
The recover tool creates a SQL script from the .data.db file. It also processes the transaction log file(s),
however it does not automatically apply those changes. Usually, many of those changes are already
applied in the .data.db file.
</p>
<br /><a name="file_locking_protocols"></a> <br /><a name="file_locking_protocols"></a>
<h2>File Locking Protocols</h2> <h2>File Locking Protocols</h2>
...@@ -760,10 +765,10 @@ The two methods are 'file method' and 'socket methods'. ...@@ -760,10 +765,10 @@ The two methods are 'file method' and 'socket methods'.
The default method for database file locking is the 'File Method'. The algorithm is: The default method for database file locking is the 'File Method'. The algorithm is:
</p> </p>
<ul> <ul>
<li>When the lock file does not exist, it is created (using the atomic operation File.createNewFile). <li>If the lock file does not exist, it is created (using the atomic operation File.createNewFile).
Then, the process waits a little bit (20ms) and checks the file again. If the file was changed Then, the process waits a little bit (20ms) and checks the file again. If the file was changed
during this time, the operation is aborted. This protects against a race condition during this time, the operation is aborted. This protects against a race condition
when a process deletes the lock file just after one create it, and a third process creates when one process deletes the lock file just after another one create it, and a third process creates
the file again. It does not occur if there are only two writers. the file again. It does not occur if there are only two writers.
</li><li> </li><li>
If the file can be created, a random number is inserted together with the locking method If the file can be created, a random number is inserted together with the locking method
...@@ -775,7 +780,7 @@ not get through undetected even if the system is very busy. However, the watchdo ...@@ -775,7 +780,7 @@ not get through undetected even if the system is very busy. However, the watchdo
does use very little resources (CPU time), because it waits most of the time. Also, the watchdog only reads from the hard disk does use very little resources (CPU time), because it waits most of the time. Also, the watchdog only reads from the hard disk
and does not write to it. and does not write to it.
</li><li> </li><li>
If the lock file exists, and it was modified in the 20 ms, the process waits for some time (up to 10 times). If the lock file exists and was recently modified, the process waits for some time (up to two seconds).
If it was still changed, an exception is thrown (database is locked). This is done to eliminate race conditions with many concurrent If it was still changed, an exception is thrown (database is locked). This is done to eliminate race conditions with many concurrent
writers. Afterwards, the file is overwritten with a new version (challenge). writers. Afterwards, the file is overwritten with a new version (challenge).
After that, the thread waits for 2 seconds. After that, the thread waits for 2 seconds.
......
...@@ -18,7 +18,9 @@ Change Log ...@@ -18,7 +18,9 @@ Change Log
<h1>Change Log</h1> <h1>Change Log</h1>
<h2>Next Version (unreleased)</h2> <h2>Next Version (unreleased)</h2>
<ul><li>New sample application that shows how to pass data to a trigger. <ul><li>The Recover tool now also processes the log files, however applying those changes
is still a manual process.
</li><li>New sample application that shows how to pass data to a trigger.
</li><li>More bugs in the server-less multi-connection mode have been fixed: </li><li>More bugs in the server-less multi-connection mode have been fixed:
On Windows, two processes could write to the same database at the same time. On Windows, two processes could write to the same database at the same time.
</li><li>When loading triggers or other client classes </li><li>When loading triggers or other client classes
......
...@@ -336,7 +336,7 @@ public class ConstraintReferential extends Constraint { ...@@ -336,7 +336,7 @@ public class ConstraintReferential extends Constraint {
while (cursor.next()) { while (cursor.next()) {
SearchRow found; SearchRow found;
found = cursor.getSearchRow(); found = cursor.getSearchRow();
if (excluding != null && found.getPos() == excluding.getPos()) { if (excluding != null && found.getKey() == excluding.getKey()) {
continue; continue;
} }
Column[] cols = searchIndex.getColumns(); Column[] cols = searchIndex.getColumns();
......
...@@ -270,8 +270,8 @@ public abstract class BaseIndex extends SchemaObjectBase implements Index { ...@@ -270,8 +270,8 @@ public abstract class BaseIndex extends SchemaObjectBase implements Index {
} }
public int compareKeys(SearchRow rowData, SearchRow compare) { public int compareKeys(SearchRow rowData, SearchRow compare) {
int k1 = rowData.getPos(); long k1 = rowData.getKey();
int k2 = compare.getPos(); long k2 = compare.getKey();
if (k1 == k2) { if (k1 == k2) {
if (isMultiVersion) { if (isMultiVersion) {
int v1 = rowData.getVersion(); int v1 = rowData.getVersion();
......
...@@ -76,7 +76,7 @@ public class BtreeCursor implements Cursor { ...@@ -76,7 +76,7 @@ public class BtreeCursor implements Cursor {
public Row get() throws SQLException { public Row get() throws SQLException {
if (currentRow == null && currentSearchRow != null) { if (currentRow == null && currentSearchRow != null) {
currentRow = index.getRow(session, currentSearchRow.getPos()); currentRow = index.getRow(session, currentSearchRow.getKey());
} }
return currentRow; return currentRow;
} }
...@@ -85,8 +85,8 @@ public class BtreeCursor implements Cursor { ...@@ -85,8 +85,8 @@ public class BtreeCursor implements Cursor {
return currentSearchRow; return currentSearchRow;
} }
public int getPos() { public long getKey() {
return currentSearchRow.getPos(); return currentSearchRow.getKey();
} }
public boolean next() throws SQLException { public boolean next() throws SQLException {
......
...@@ -217,7 +217,7 @@ public class BtreeIndex extends BaseIndex implements RecordReader { ...@@ -217,7 +217,7 @@ public class BtreeIndex extends BaseIndex implements RecordReader {
// create a row that only contains the key values // create a row that only contains the key values
setChanged(session); setChanged(session);
Row row = table.getTemplateRow(); Row row = table.getTemplateRow();
row.setPosAndVersion(r); row.setKeyAndVersion(r);
for (int i = 0; i < columns.length; i++) { for (int i = 0; i < columns.length; i++) {
Column col = columns[i]; Column col = columns[i];
int idx = col.getColumnId(); int idx = col.getColumnId();
...@@ -247,7 +247,7 @@ public class BtreeIndex extends BaseIndex implements RecordReader { ...@@ -247,7 +247,7 @@ public class BtreeIndex extends BaseIndex implements RecordReader {
*/ */
SearchRow getSearchRow(Row row) { SearchRow getSearchRow(Row row) {
SearchRow r = table.getTemplateSimpleRow(columns.length == 1); SearchRow r = table.getTemplateSimpleRow(columns.length == 1);
r.setPosAndVersion(row); r.setKeyAndVersion(row);
for (int j = 0; j < columns.length; j++) { for (int j = 0; j < columns.length; j++) {
int idx = columns[j].getColumnId(); int idx = columns[j].getColumnId();
r.setValue(idx, row.getValue(idx)); r.setValue(idx, row.getValue(idx));
...@@ -324,7 +324,7 @@ public class BtreeIndex extends BaseIndex implements RecordReader { ...@@ -324,7 +324,7 @@ public class BtreeIndex extends BaseIndex implements RecordReader {
r = null; r = null;
} else { } else {
r = table.getTemplateSimpleRow(columns.length == 1); r = table.getTemplateSimpleRow(columns.length == 1);
r.setPos(pos); r.setKey(pos);
for (int j = 0; j < columns.length; j++) { for (int j = 0; j < columns.length; j++) {
int idx = columns[j].getColumnId(); int idx = columns[j].getColumnId();
r.setValue(idx, s.readValue()); r.setValue(idx, s.readValue());
...@@ -339,11 +339,11 @@ public class BtreeIndex extends BaseIndex implements RecordReader { ...@@ -339,11 +339,11 @@ public class BtreeIndex extends BaseIndex implements RecordReader {
* Get a row from the data file. * Get a row from the data file.
* *
* @param session the session * @param session the session
* @param pos the position in the data file * @param key the unique key
* @return the row * @return the row
*/ */
Row getRow(Session session, int pos) throws SQLException { Row getRow(Session session, long key) throws SQLException {
return tableData.getRow(session, pos); return tableData.getRow(session, key);
} }
private void flushHead(Session session) throws SQLException { private void flushHead(Session session) throws SQLException {
......
...@@ -245,7 +245,7 @@ public class BtreeLeaf extends BtreePage { ...@@ -245,7 +245,7 @@ public class BtreeLeaf extends BtreePage {
Column[] columns = index.getColumns(); Column[] columns = index.getColumns();
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
SearchRow row = pageData.get(i); SearchRow row = pageData.get(i);
buff.writeInt(row.getPos()); buff.writeInt((int) row.getKey());
if (!writePos) { if (!writePos) {
for (int j = 0; j < columns.length; j++) { for (int j = 0; j < columns.length; j++) {
Value v = row.getValue(columns[j].getColumnId()); Value v = row.getValue(columns[j].getColumnId());
......
...@@ -350,7 +350,7 @@ public class BtreeNode extends BtreePage { ...@@ -350,7 +350,7 @@ public class BtreeNode extends BtreePage {
buff.writeInt(-1); buff.writeInt(-1);
} else { } else {
SearchRow row = getData(i); SearchRow row = getData(i);
buff.writeInt(row.getPos()); buff.writeInt((int) row.getKey());
for (int j = 0; j < columns.length; j++) { for (int j = 0; j < columns.length; j++) {
Value v = row.getValue(columns[j].getColumnId()); Value v = row.getValue(columns[j].getColumnId());
buff.writeValue(v); buff.writeValue(v);
......
...@@ -39,11 +39,11 @@ public interface Cursor { ...@@ -39,11 +39,11 @@ public interface Cursor {
SearchRow getSearchRow() throws SQLException; SearchRow getSearchRow() throws SQLException;
/** /**
* Get the position of the current row. * Get the unique key of the current row.
* *
* @return the position * @return the key
*/ */
int getPos(); long getKey();
/** /**
* Skip to the next row if one is available. * Skip to the next row if one is available.
......
...@@ -41,7 +41,7 @@ public class FunctionCursor implements Cursor { ...@@ -41,7 +41,7 @@ public class FunctionCursor implements Cursor {
return get(); return get();
} }
public int getPos() { public long getKey() {
throw Message.throwInternalError(); throw Message.throwInternalError();
} }
......
...@@ -30,8 +30,8 @@ public class HashCursor implements Cursor { ...@@ -30,8 +30,8 @@ public class HashCursor implements Cursor {
return row; return row;
} }
public int getPos() { public long getKey() {
return row.getPos(); return row.getKey();
} }
public boolean next() { public boolean next() {
......
...@@ -47,7 +47,7 @@ public class HashIndex extends BaseHashIndex { ...@@ -47,7 +47,7 @@ public class HashIndex extends BaseHashIndex {
public void add(Session session, Row row) throws SQLException { public void add(Session session, Row row) throws SQLException {
if (intMap != null) { if (intMap != null) {
int key = row.getValue(columns[0].getColumnId()).getInt(); int key = row.getValue(columns[0].getColumnId()).getInt();
intMap.put(key, row.getPos()); intMap.put(key, (int) row.getKey());
} else { } else {
Value key = getKey(row); Value key = getKey(row);
Object old = rows.get(key); Object old = rows.get(key);
...@@ -55,7 +55,7 @@ public class HashIndex extends BaseHashIndex { ...@@ -55,7 +55,7 @@ public class HashIndex extends BaseHashIndex {
// TODO index duplicate key for hash indexes: is this allowed? // TODO index duplicate key for hash indexes: is this allowed?
throw getDuplicateKeyException(); throw getDuplicateKeyException();
} }
rows.put(getKey(row), row.getPos()); rows.put(getKey(row), (int) row.getKey());
} }
} }
......
...@@ -147,8 +147,8 @@ public class IndexCursor implements Cursor { ...@@ -147,8 +147,8 @@ public class IndexCursor implements Cursor {
return cursor.get(); return cursor.get();
} }
public int getPos() { public long getKey() {
return cursor.getPos(); return cursor.getKey();
} }
public SearchRow getSearchRow() throws SQLException { public SearchRow getSearchRow() throws SQLException {
......
...@@ -52,7 +52,7 @@ public class LinkedCursor implements Cursor { ...@@ -52,7 +52,7 @@ public class LinkedCursor implements Cursor {
return current; return current;
} }
public int getPos() { public long getKey() {
throw Message.throwInternalError(); throw Message.throwInternalError();
} }
......
...@@ -33,7 +33,7 @@ public class MetaCursor implements Cursor { ...@@ -33,7 +33,7 @@ public class MetaCursor implements Cursor {
return current; return current;
} }
public int getPos() { public long getKey() {
throw Message.throwInternalError(); throw Message.throwInternalError();
} }
......
...@@ -82,12 +82,12 @@ public class MultiVersionCursor implements Cursor { ...@@ -82,12 +82,12 @@ public class MultiVersionCursor implements Cursor {
} }
} }
public int getPos() { public long getKey() {
synchronized (sync) { synchronized (sync) {
if (SysProperties.CHECK && end) { if (SysProperties.CHECK && end) {
Message.throwInternalError(); Message.throwInternalError();
} }
return onBase ? baseCursor.getPos() : deltaCursor.getPos(); return onBase ? baseCursor.getKey() : deltaCursor.getKey();
} }
} }
...@@ -147,8 +147,8 @@ public class MultiVersionCursor implements Cursor { ...@@ -147,8 +147,8 @@ public class MultiVersionCursor implements Cursor {
if (compare == 0) { if (compare == 0) {
// can't use compareKeys because the // can't use compareKeys because the
// version would be compared as well // version would be compared as well
int k1 = deltaRow.getPos(); long k1 = deltaRow.getKey();
int k2 = baseRow.getPos(); long k2 = baseRow.getKey();
compare = k1 == k2 ? 0 : k1 > k2 ? 1 : -1; compare = k1 == k2 ? 0 : k1 > k2 ? 1 : -1;
} }
if (compare == 0) { if (compare == 0) {
......
...@@ -128,7 +128,7 @@ public class MultiVersionIndex implements Index { ...@@ -128,7 +128,7 @@ public class MultiVersionIndex implements Index {
Cursor c = delta.find(session, row, row); Cursor c = delta.find(session, row, row);
while (c.next()) { while (c.next()) {
Row r = c.get(); Row r = c.get();
if (r.getPos() == row.getPos() && r.getVersion() == row.getVersion()) { if (r.getKey() == row.getKey() && r.getVersion() == row.getVersion()) {
if (r != row && table.getScanIndex(session).compareRows(r, row) != 0) { if (r != row && table.getScanIndex(session).compareRows(r, row) != 0) {
row.setVersion(r.getVersion() + 1); row.setVersion(r.getVersion() + 1);
} else { } else {
......
...@@ -39,7 +39,7 @@ public class NonUniqueHashCursor implements Cursor { ...@@ -39,7 +39,7 @@ public class NonUniqueHashCursor implements Cursor {
return tableData.getRow(session, positions.get(index)); return tableData.getRow(session, positions.get(index));
} }
public int getPos() { public long getKey() {
return index; return index;
} }
......
...@@ -50,7 +50,7 @@ public class NonUniqueHashIndex extends BaseHashIndex { ...@@ -50,7 +50,7 @@ public class NonUniqueHashIndex extends BaseHashIndex {
positions = new IntArray(1); positions = new IntArray(1);
rows.put(key, positions); rows.put(key, positions);
} }
positions.add(row.getPos()); positions.add((int) row.getKey());
rowCount++; rowCount++;
} }
...@@ -65,7 +65,7 @@ public class NonUniqueHashIndex extends BaseHashIndex { ...@@ -65,7 +65,7 @@ public class NonUniqueHashIndex extends BaseHashIndex {
// last row with such key // last row with such key
rows.remove(key); rows.remove(key);
} else { } else {
positions.removeValue(row.getPos()); positions.removeValue((int) row.getKey());
} }
rowCount--; rowCount--;
} }
......
...@@ -43,13 +43,13 @@ public class PageBtreeCursor implements Cursor { ...@@ -43,13 +43,13 @@ public class PageBtreeCursor implements Cursor {
public Row get() throws SQLException { public Row get() throws SQLException {
if (currentRow == null && currentSearchRow != null) { if (currentRow == null && currentSearchRow != null) {
currentRow = index.getRow(session, currentSearchRow.getPos()); currentRow = index.getRow(session, currentSearchRow.getKey());
} }
return currentRow; return currentRow;
} }
public int getPos() { public long getKey() {
return currentSearchRow.getPos(); return currentSearchRow.getKey();
} }
public SearchRow getSearchRow() { public SearchRow getSearchRow() {
......
...@@ -74,7 +74,7 @@ public class PageBtreeIndex extends PageIndex { ...@@ -74,7 +74,7 @@ public class PageBtreeIndex extends PageIndex {
public void add(Session session, Row row) throws SQLException { public void add(Session session, Row row) throws SQLException {
if (trace.isDebugEnabled()) { if (trace.isDebugEnabled()) {
trace.debug("add " + row.getPos()); trace.debug("add " + row.getKey());
} }
// safe memory // safe memory
SearchRow newRow = getSearchRow(row); SearchRow newRow = getSearchRow(row);
...@@ -113,7 +113,7 @@ public class PageBtreeIndex extends PageIndex { ...@@ -113,7 +113,7 @@ public class PageBtreeIndex extends PageIndex {
*/ */
private SearchRow getSearchRow(Row row) { private SearchRow getSearchRow(Row row) {
SearchRow r = table.getTemplateSimpleRow(columns.length == 1); SearchRow r = table.getTemplateSimpleRow(columns.length == 1);
r.setPosAndVersion(row); r.setKeyAndVersion(row);
for (int j = 0; j < columns.length; j++) { for (int j = 0; j < columns.length; j++) {
int idx = columns[j].getColumnId(); int idx = columns[j].getColumnId();
r.setValue(idx, row.getValue(idx)); r.setValue(idx, row.getValue(idx));
...@@ -199,7 +199,7 @@ public class PageBtreeIndex extends PageIndex { ...@@ -199,7 +199,7 @@ public class PageBtreeIndex extends PageIndex {
public void remove(Session session, Row row) throws SQLException { public void remove(Session session, Row row) throws SQLException {
if (trace.isDebugEnabled()) { if (trace.isDebugEnabled()) {
trace.debug("remove " + row.getPos()); trace.debug("remove " + row.getKey());
} }
if (tableData.getContainsLargeObject()) { if (tableData.getContainsLargeObject()) {
for (int i = 0; i < row.getColumnCount(); i++) { for (int i = 0; i < row.getColumnCount(); i++) {
...@@ -260,7 +260,7 @@ public class PageBtreeIndex extends PageIndex { ...@@ -260,7 +260,7 @@ public class PageBtreeIndex extends PageIndex {
* @param key the row key * @param key the row key
* @return the row * @return the row
*/ */
Row getRow(Session session, int key) throws SQLException { Row getRow(Session session, long key) throws SQLException {
return tableData.getRow(session, key); return tableData.getRow(session, key);
} }
...@@ -293,12 +293,12 @@ public class PageBtreeIndex extends PageIndex { ...@@ -293,12 +293,12 @@ public class PageBtreeIndex extends PageIndex {
*/ */
SearchRow readRow(Data data, int offset, boolean onlyPosition) throws SQLException { SearchRow readRow(Data data, int offset, boolean onlyPosition) throws SQLException {
data.setPos(offset); data.setPos(offset);
long pos = data.readVarLong(); long key = data.readVarLong();
if (onlyPosition) { if (onlyPosition) {
return tableData.getRow(null, (int) pos); return tableData.getRow(null, key);
} }
SearchRow row = table.getTemplateSimpleRow(columns.length == 1); SearchRow row = table.getTemplateSimpleRow(columns.length == 1);
row.setPos((int) pos); row.setKey(key);
for (Column col : columns) { for (Column col : columns) {
int idx = col.getColumnId(); int idx = col.getColumnId();
row.setValue(idx, data.readValue()); row.setValue(idx, data.readValue());
...@@ -316,7 +316,7 @@ public class PageBtreeIndex extends PageIndex { ...@@ -316,7 +316,7 @@ public class PageBtreeIndex extends PageIndex {
*/ */
void writeRow(Data data, int offset, SearchRow row, boolean onlyPosition) throws SQLException { void writeRow(Data data, int offset, SearchRow row, boolean onlyPosition) throws SQLException {
data.setPos(offset); data.setPos(offset);
data.writeVarLong(row.getPos()); data.writeVarLong(row.getKey());
if (!onlyPosition) { if (!onlyPosition) {
for (Column col : columns) { for (Column col : columns) {
int idx = col.getColumnId(); int idx = col.getColumnId();
......
...@@ -194,7 +194,7 @@ public class PageBtreeLeaf extends PageBtree { ...@@ -194,7 +194,7 @@ public class PageBtreeLeaf extends PageBtree {
SearchRow remove(SearchRow row) throws SQLException { SearchRow remove(SearchRow row) throws SQLException {
int at = find(row, false, false, true); int at = find(row, false, false, true);
SearchRow delete = getRow(at); SearchRow delete = getRow(at);
if (index.compareRows(row, delete) != 0 || delete.getPos() != row.getPos()) { if (index.compareRows(row, delete) != 0 || delete.getKey() != row.getKey()) {
throw Message.getSQLException(ErrorCode.ROW_NOT_FOUND_WHEN_DELETING_1, index.getSQL() + ": " + row); throw Message.getSQLException(ErrorCode.ROW_NOT_FOUND_WHEN_DELETING_1, index.getSQL() + ": " + row);
} }
if (entryCount == 1) { if (entryCount == 1) {
......
...@@ -30,7 +30,7 @@ abstract class PageData extends Page { ...@@ -30,7 +30,7 @@ abstract class PageData extends Page {
/** /**
* The index. * The index.
*/ */
protected final PageScanIndex index; protected final PageDataIndex index;
/** /**
* The page number of the parent. * The page number of the parent.
...@@ -57,7 +57,7 @@ abstract class PageData extends Page { ...@@ -57,7 +57,7 @@ abstract class PageData extends Page {
*/ */
protected boolean written; protected boolean written;
PageData(PageScanIndex index, int pageId, Data data) { PageData(PageDataIndex index, int pageId, Data data) {
this.index = index; this.index = index;
this.data = data; this.data = data;
setPos(pageId); setPos(pageId);
...@@ -184,7 +184,7 @@ abstract class PageData extends Page { ...@@ -184,7 +184,7 @@ abstract class PageData extends Page {
* @param key the key of the row to remove * @param key the key of the row to remove
* @return true if this page is now empty * @return true if this page is now empty
*/ */
abstract boolean remove(int key) throws SQLException; abstract boolean remove(long key) throws SQLException;
/** /**
* Free up all child pages. * Free up all child pages.
......
...@@ -17,7 +17,7 @@ import org.h2.result.SearchRow; ...@@ -17,7 +17,7 @@ import org.h2.result.SearchRow;
/** /**
* The cursor implementation for the page scan index. * The cursor implementation for the page scan index.
*/ */
class PageScanCursor implements Cursor { class PageDataCursor implements Cursor {
private PageDataLeaf current; private PageDataLeaf current;
private int idx; private int idx;
...@@ -27,7 +27,7 @@ class PageScanCursor implements Cursor { ...@@ -27,7 +27,7 @@ class PageScanCursor implements Cursor {
private final Session session; private final Session session;
private Iterator<Row> delta; private Iterator<Row> delta;
PageScanCursor(Session session, PageDataLeaf current, int idx, long max, boolean multiVersion) { PageDataCursor(Session session, PageDataLeaf current, int idx, long max, boolean multiVersion) {
this.current = current; this.current = current;
this.idx = idx; this.idx = idx;
this.max = max; this.max = max;
...@@ -42,8 +42,8 @@ class PageScanCursor implements Cursor { ...@@ -42,8 +42,8 @@ class PageScanCursor implements Cursor {
return row; return row;
} }
public int getPos() { public long getKey() {
return row.getPos(); return row.getKey();
} }
public SearchRow getSearchRow() { public SearchRow getSearchRow() {
......
...@@ -34,7 +34,7 @@ import org.h2.value.ValueNull; ...@@ -34,7 +34,7 @@ import org.h2.value.ValueNull;
* all rows of a table. Each regular table has one such object, even if no * all rows of a table. Each regular table has one such object, even if no
* primary key or indexes are defined. * primary key or indexes are defined.
*/ */
public class PageScanIndex extends PageIndex implements RowIndex { public class PageDataIndex extends PageIndex implements RowIndex {
private PageStore store; private PageStore store;
private TableData tableData; private TableData tableData;
...@@ -47,7 +47,7 @@ public class PageScanIndex extends PageIndex implements RowIndex { ...@@ -47,7 +47,7 @@ public class PageScanIndex extends PageIndex implements RowIndex {
private SQLException fastDuplicateKeyException; private SQLException fastDuplicateKeyException;
private int memorySizePerPage; private int memorySizePerPage;
public PageScanIndex(TableData table, int id, IndexColumn[] columns, IndexType indexType, int headPos, Session session) throws SQLException { public PageDataIndex(TableData table, int id, IndexColumn[] columns, IndexType indexType, int headPos, Session session) throws SQLException {
initBaseIndex(table, id, table.getName() + "_TABLE_SCAN", columns, indexType); initBaseIndex(table, id, table.getName() + "_TABLE_SCAN", columns, indexType);
// trace.setLevel(TraceSystem.DEBUG); // trace.setLevel(TraceSystem.DEBUG);
if (database.isMultiVersion()) { if (database.isMultiVersion()) {
...@@ -83,7 +83,8 @@ public class PageScanIndex extends PageIndex implements RowIndex { ...@@ -83,7 +83,8 @@ public class PageScanIndex extends PageIndex implements RowIndex {
table.setRowCount(rowCount); table.setRowCount(rowCount);
fastDuplicateKeyException = super.getDuplicateKeyException(); fastDuplicateKeyException = super.getDuplicateKeyException();
// estimate the memory usage as follows: // estimate the memory usage as follows:
// the less column, the more memory is required, because the more rows fit on a page // the less column, the more memory is required,
// because the more rows fit on a page
memorySizePerPage = store.getPageSize(); memorySizePerPage = store.getPageSize();
int estimatedRowsPerPage = store.getPageSize() / ((1 + columns.length) * 8); int estimatedRowsPerPage = store.getPageSize() / ((1 + columns.length) * 8);
memorySizePerPage += estimatedRowsPerPage * 64; memorySizePerPage += estimatedRowsPerPage * 64;
...@@ -96,10 +97,10 @@ public class PageScanIndex extends PageIndex implements RowIndex { ...@@ -96,10 +97,10 @@ public class PageScanIndex extends PageIndex implements RowIndex {
public void add(Session session, Row row) throws SQLException { public void add(Session session, Row row) throws SQLException {
boolean retry = false; boolean retry = false;
if (mainIndexColumn != -1) { if (mainIndexColumn != -1) {
row.setPos(row.getValue(mainIndexColumn).getInt()); row.setKey(row.getValue(mainIndexColumn).getLong());
} else { } else {
if (row.getPos() == 0) { if (row.getKey() == 0) {
row.setPos((int) ++lastKey); row.setKey((int) ++lastKey);
retry = true; retry = true;
} }
} }
...@@ -135,16 +136,14 @@ public class PageScanIndex extends PageIndex implements RowIndex { ...@@ -135,16 +136,14 @@ public class PageScanIndex extends PageIndex implements RowIndex {
if (add == 0) { if (add == 0) {
// in the first re-try add a small random number, // in the first re-try add a small random number,
// to avoid collisions after a re-start // to avoid collisions after a re-start
// TODO use long row.setKey((long) (row.getKey() + Math.random() * 10000));
row.setPos((int) (row.getPos() + Math.random() * 10000));
} else { } else {
// TODO use long row.setKey(row.getKey() + add);
row.setPos((int) (row.getPos() + add));
} }
add++; add++;
} }
} }
lastKey = Math.max(lastKey, row.getPos() + 1); lastKey = Math.max(lastKey, row.getKey() + 1);
} }
private void addTry(Session session, Row row) throws SQLException { private void addTry(Session session, Row row) throws SQLException {
...@@ -157,7 +156,7 @@ public class PageScanIndex extends PageIndex implements RowIndex { ...@@ -157,7 +156,7 @@ public class PageScanIndex extends PageIndex implements RowIndex {
if (trace.isDebugEnabled()) { if (trace.isDebugEnabled()) {
trace.debug("split " + splitPoint); trace.debug("split " + splitPoint);
} }
long pivot = splitPoint == 0 ? row.getPos() : root.getKey(splitPoint - 1); long pivot = splitPoint == 0 ? row.getKey() : root.getKey(splitPoint - 1);
PageData page1 = root; PageData page1 = root;
PageData page2 = root.split(splitPoint); PageData page2 = root.split(splitPoint);
int rootPageId = root.getPos(); int rootPageId = root.getPos();
...@@ -284,7 +283,7 @@ public class PageScanIndex extends PageIndex implements RowIndex { ...@@ -284,7 +283,7 @@ public class PageScanIndex extends PageIndex implements RowIndex {
public void remove(Session session, Row row) throws SQLException { public void remove(Session session, Row row) throws SQLException {
if (trace.isDebugEnabled()) { if (trace.isDebugEnabled()) {
trace.debug("remove " + row.getPos()); trace.debug("remove " + row.getKey());
} }
if (tableData.getContainsLargeObject()) { if (tableData.getContainsLargeObject()) {
for (int i = 0; i < row.getColumnCount(); i++) { for (int i = 0; i < row.getColumnCount(); i++) {
...@@ -297,7 +296,7 @@ public class PageScanIndex extends PageIndex implements RowIndex { ...@@ -297,7 +296,7 @@ public class PageScanIndex extends PageIndex implements RowIndex {
if (rowCount == 1) { if (rowCount == 1) {
removeAllRows(); removeAllRows();
} else { } else {
int key = row.getPos(); long key = row.getKey();
PageData root = getPage(rootPageId, 0); PageData root = getPage(rootPageId, 0);
root.remove(key); root.remove(key);
invalidateRowCount(); invalidateRowCount();
...@@ -361,7 +360,7 @@ public class PageScanIndex extends PageIndex implements RowIndex { ...@@ -361,7 +360,7 @@ public class PageScanIndex extends PageIndex implements RowIndex {
throw Message.getUnsupportedException("PAGE"); throw Message.getUnsupportedException("PAGE");
} }
public Row getRow(Session session, int key) throws SQLException { public Row getRow(Session session, long key) throws SQLException {
return getRow(key); return getRow(key);
} }
......
...@@ -67,7 +67,7 @@ public class PageDataLeaf extends PageData { ...@@ -67,7 +67,7 @@ public class PageDataLeaf extends PageData {
private int memorySize; private int memorySize;
private PageDataLeaf(PageScanIndex index, int pageId, Data data) { private PageDataLeaf(PageDataIndex index, int pageId, Data data) {
super(index, pageId, data); super(index, pageId, data);
} }
...@@ -79,7 +79,7 @@ public class PageDataLeaf extends PageData { ...@@ -79,7 +79,7 @@ public class PageDataLeaf extends PageData {
* @param parentPageId the parent * @param parentPageId the parent
* @return the page * @return the page
*/ */
static PageDataLeaf create(PageScanIndex index, int pageId, int parentPageId) { static PageDataLeaf create(PageDataIndex index, int pageId, int parentPageId) {
PageDataLeaf p = new PageDataLeaf(index, pageId, index.getPageStore().createData()); PageDataLeaf p = new PageDataLeaf(index, pageId, index.getPageStore().createData());
p.parentPageId = parentPageId; p.parentPageId = parentPageId;
p.columnCount = index.getTable().getColumns().length; p.columnCount = index.getTable().getColumns().length;
...@@ -96,7 +96,7 @@ public class PageDataLeaf extends PageData { ...@@ -96,7 +96,7 @@ public class PageDataLeaf extends PageData {
* @param pageId the page id * @param pageId the page id
* @return the page * @return the page
*/ */
public static Page read(PageScanIndex index, Data data, int pageId) throws SQLException { public static Page read(PageDataIndex index, Data data, int pageId) throws SQLException {
PageDataLeaf p = new PageDataLeaf(index, pageId, data); PageDataLeaf p = new PageDataLeaf(index, pageId, data);
p.read(); p.read();
return p; return p;
...@@ -139,9 +139,9 @@ public class PageDataLeaf extends PageData { ...@@ -139,9 +139,9 @@ public class PageDataLeaf extends PageData {
int rowLength = getRowLength(row); int rowLength = getRowLength(row);
int pageSize = index.getPageStore().getPageSize(); int pageSize = index.getPageStore().getPageSize();
int last = entryCount == 0 ? pageSize : offsets[entryCount - 1]; int last = entryCount == 0 ? pageSize : offsets[entryCount - 1];
int keyOffsetPairLen = 2 + data.getVarLongLen(row.getPos()); int keyOffsetPairLen = 2 + data.getVarLongLen(row.getKey());
if (entryCount > 0 && last - rowLength < start + keyOffsetPairLen) { if (entryCount > 0 && last - rowLength < start + keyOffsetPairLen) {
int x = find(row.getPos()); int x = find(row.getKey());
if (entryCount > 1) { if (entryCount > 1) {
if (entryCount < 5) { if (entryCount < 5) {
// required, otherwise the index doesn't work correctly // required, otherwise the index doesn't work correctly
...@@ -164,8 +164,8 @@ public class PageDataLeaf extends PageData { ...@@ -164,8 +164,8 @@ public class PageDataLeaf extends PageData {
x = 0; x = 0;
} else { } else {
readAllRows(); readAllRows();
x = find(row.getPos()); x = find(row.getKey());
if (x < keys.length && keys[x] == row.getPos()) { if (x < keys.length && keys[x] == row.getKey()) {
throw index.getDuplicateKeyException(); throw index.getDuplicateKeyException();
} }
System.arraycopy(offsets, 0, newOffsets, 0, x); System.arraycopy(offsets, 0, newOffsets, 0, x);
...@@ -185,7 +185,7 @@ public class PageDataLeaf extends PageData { ...@@ -185,7 +185,7 @@ public class PageDataLeaf extends PageData {
entryCount++; entryCount++;
start += keyOffsetPairLen; start += keyOffsetPairLen;
newOffsets[x] = offset; newOffsets[x] = offset;
newKeys[x] = row.getPos(); newKeys[x] = row.getKey();
newRows[x] = row; newRows[x] = row;
memorySize += row.getMemorySize(); memorySize += row.getMemorySize();
offsets = newOffsets; offsets = newOffsets;
...@@ -270,7 +270,7 @@ public class PageDataLeaf extends PageData { ...@@ -270,7 +270,7 @@ public class PageDataLeaf extends PageData {
Cursor find(Session session, long min, long max, boolean multiVersion) { Cursor find(Session session, long min, long max, boolean multiVersion) {
int x = find(min); int x = find(min);
return new PageScanCursor(session, this, x, max, multiVersion); return new PageDataCursor(session, this, x, max, multiVersion);
} }
/** /**
...@@ -302,12 +302,11 @@ public class PageDataLeaf extends PageData { ...@@ -302,12 +302,11 @@ public class PageDataLeaf extends PageData {
PageDataOverflow page = index.getPageOverflow(next); PageDataOverflow page = index.getPageOverflow(next);
next = page.readInto(buff); next = page.readInto(buff);
} while (next != 0); } while (next != 0);
int checkRequired;
overflowRowSize = pageSize + buff.length(); overflowRowSize = pageSize + buff.length();
buff.setPos(0); buff.setPos(0);
r = index.readRow(buff, columnCount); r = index.readRow(buff, columnCount);
} }
r.setPos((int) keys[at]); r.setKey(keys[at]);
if (firstOverflowPageId != 0) { if (firstOverflowPageId != 0) {
rowRef = new SoftReference<Row>(r); rowRef = new SoftReference<Row>(r);
} else { } else {
...@@ -337,7 +336,7 @@ int checkRequired; ...@@ -337,7 +336,7 @@ int checkRequired;
if (entryCount == 0) { if (entryCount == 0) {
return 0; return 0;
} }
return getRowAt(entryCount - 1).getPos(); return getRowAt(entryCount - 1).getKey();
} }
PageDataLeaf getNextPage() throws SQLException { PageDataLeaf getNextPage() throws SQLException {
...@@ -361,7 +360,7 @@ int checkRequired; ...@@ -361,7 +360,7 @@ int checkRequired;
index.getPageStore().updateRecord(overflow, true, null); index.getPageStore().updateRecord(overflow, true, null);
} }
boolean remove(int key) throws SQLException { boolean remove(long key) throws SQLException {
int i = find(key); int i = find(key);
if (keys[i] != key) { if (keys[i] != key) {
throw Message.getSQLException(ErrorCode.ROW_NOT_FOUND_WHEN_DELETING_1, index.getSQL() + ": " + key); throw Message.getSQLException(ErrorCode.ROW_NOT_FOUND_WHEN_DELETING_1, index.getSQL() + ": " + key);
...@@ -436,10 +435,10 @@ int checkRequired; ...@@ -436,10 +435,10 @@ int checkRequired;
} }
readAllRows(); readAllRows();
data.reset(); data.reset();
data.checkCapacity(overflowRowSize);
writeHead(); writeHead();
if (firstOverflowPageId != 0) { if (firstOverflowPageId != 0) {
data.writeInt(firstOverflowPageId); data.writeInt(firstOverflowPageId);
data.checkCapacity(overflowRowSize);
} }
for (int i = 0; i < entryCount; i++) { for (int i = 0; i < entryCount; i++) {
data.writeVarLong(keys[i]); data.writeVarLong(keys[i]);
......
...@@ -48,7 +48,7 @@ public class PageDataNode extends PageData { ...@@ -48,7 +48,7 @@ public class PageDataNode extends PageData {
*/ */
private int length; private int length;
private PageDataNode(PageScanIndex index, int pageId, Data data) { private PageDataNode(PageDataIndex index, int pageId, Data data) {
super(index, pageId, data); super(index, pageId, data);
} }
...@@ -60,7 +60,7 @@ public class PageDataNode extends PageData { ...@@ -60,7 +60,7 @@ public class PageDataNode extends PageData {
* @param parentPageId the parent * @param parentPageId the parent
* @return the page * @return the page
*/ */
static PageDataNode create(PageScanIndex index, int pageId, int parentPageId) { static PageDataNode create(PageDataIndex index, int pageId, int parentPageId) {
PageDataNode p = new PageDataNode(index, pageId, index.getPageStore().createData()); PageDataNode p = new PageDataNode(index, pageId, index.getPageStore().createData());
p.parentPageId = parentPageId; p.parentPageId = parentPageId;
p.writeHead(); p.writeHead();
...@@ -77,7 +77,7 @@ public class PageDataNode extends PageData { ...@@ -77,7 +77,7 @@ public class PageDataNode extends PageData {
* @param pageId the page id * @param pageId the page id
* @return the page * @return the page
*/ */
public static Page read(PageScanIndex index, Data data, int pageId) throws SQLException { public static Page read(PageDataIndex index, Data data, int pageId) throws SQLException {
PageDataNode p = new PageDataNode(index, pageId, data); PageDataNode p = new PageDataNode(index, pageId, data);
p.read(); p.read();
return p; return p;
...@@ -129,9 +129,9 @@ public class PageDataNode extends PageData { ...@@ -129,9 +129,9 @@ public class PageDataNode extends PageData {
} }
int addRowTry(Row row) throws SQLException { int addRowTry(Row row) throws SQLException {
int keyOffsetPairLen = 4 + data.getVarLongLen(row.getPos()); int keyOffsetPairLen = 4 + data.getVarLongLen(row.getKey());
while (true) { while (true) {
int x = find(row.getPos()); int x = find(row.getKey());
PageData page = index.getPage(childPageIds[x], getPos()); PageData page = index.getPage(childPageIds[x], getPos());
int splitPoint = page.addRowTry(row); int splitPoint = page.addRowTry(row);
if (splitPoint == -1) { if (splitPoint == -1) {
...@@ -140,7 +140,7 @@ public class PageDataNode extends PageData { ...@@ -140,7 +140,7 @@ public class PageDataNode extends PageData {
if (length + keyOffsetPairLen > index.getPageStore().getPageSize()) { if (length + keyOffsetPairLen > index.getPageStore().getPageSize()) {
return entryCount / 2; return entryCount / 2;
} }
long pivot = splitPoint == 0 ? row.getPos() : page.getKey(splitPoint - 1); long pivot = splitPoint == 0 ? row.getKey() : page.getKey(splitPoint - 1);
PageData page2 = page.split(splitPoint); PageData page2 = page.split(splitPoint);
index.getPageStore().updateRecord(page, true, page.data); index.getPageStore().updateRecord(page, true, page.data);
index.getPageStore().updateRecord(page2, true, page2.data); index.getPageStore().updateRecord(page2, true, page2.data);
...@@ -234,7 +234,7 @@ public class PageDataNode extends PageData { ...@@ -234,7 +234,7 @@ public class PageDataNode extends PageData {
return index.getPage(child, getPos()).getFirstLeaf(); return index.getPage(child, getPos()).getFirstLeaf();
} }
boolean remove(int key) throws SQLException { boolean remove(long key) throws SQLException {
int at = find(key); int at = find(key);
// merge is not implemented to allow concurrent usage // merge is not implemented to allow concurrent usage
// TODO maybe implement merge // TODO maybe implement merge
......
...@@ -21,9 +21,9 @@ import org.h2.table.TableData; ...@@ -21,9 +21,9 @@ import org.h2.table.TableData;
*/ */
public class PageDelegateIndex extends PageIndex { public class PageDelegateIndex extends PageIndex {
private final PageScanIndex mainIndex; private final PageDataIndex mainIndex;
public PageDelegateIndex(TableData table, int id, String name, IndexType indexType, PageScanIndex mainIndex, int headPos, Session session) throws SQLException { public PageDelegateIndex(TableData table, int id, String name, IndexType indexType, PageDataIndex mainIndex, int headPos, Session session) throws SQLException {
IndexColumn[] columns = IndexColumn.wrap(new Column[] { table.getColumn(mainIndex.getMainIndexColumn())}); IndexColumn[] columns = IndexColumn.wrap(new Column[] { table.getColumn(mainIndex.getMainIndexColumn())});
this.initBaseIndex(table, id, name, columns, indexType); this.initBaseIndex(table, id, name, columns, indexType);
this.mainIndex = mainIndex; this.mainIndex = mainIndex;
......
...@@ -36,7 +36,7 @@ class RangeCursor implements Cursor { ...@@ -36,7 +36,7 @@ class RangeCursor implements Cursor {
return currentRow; return currentRow;
} }
public int getPos() { public long getKey() {
throw Message.throwInternalError(); throw Message.throwInternalError();
} }
......
...@@ -20,9 +20,9 @@ public interface RowIndex extends Index { ...@@ -20,9 +20,9 @@ public interface RowIndex extends Index {
* Get the row with the given key. * Get the row with the given key.
* *
* @param session the session * @param session the session
* @param key the position * @param key the unique key
* @return the row * @return the row
*/ */
Row getRow(Session session, int key) throws SQLException; Row getRow(Session session, long key) throws SQLException;
} }
...@@ -41,8 +41,8 @@ public class ScanCursor implements Cursor { ...@@ -41,8 +41,8 @@ public class ScanCursor implements Cursor {
return row; return row;
} }
public int getPos() { public long getKey() {
return row.getPos(); return row.getKey();
} }
public boolean next() throws SQLException { public boolean next() throws SQLException {
......
...@@ -35,7 +35,7 @@ import org.h2.value.ValueLob; ...@@ -35,7 +35,7 @@ import org.h2.value.ValueLob;
* indexes are defined. * indexes are defined.
*/ */
public class ScanIndex extends BaseIndex implements RowIndex { public class ScanIndex extends BaseIndex implements RowIndex {
private int firstFree = -1; private long firstFree = -1;
private ObjectArray<Row> rows = ObjectArray.newInstance(); private ObjectArray<Row> rows = ObjectArray.newInstance();
private Storage storage; private Storage storage;
private TableData tableData; private TableData tableData;
...@@ -95,11 +95,11 @@ public class ScanIndex extends BaseIndex implements RowIndex { ...@@ -95,11 +95,11 @@ public class ScanIndex extends BaseIndex implements RowIndex {
} }
} }
public Row getRow(Session session, int key) throws SQLException { public Row getRow(Session session, long key) throws SQLException {
if (storage != null) { if (storage != null) {
return (Row) storage.getRecord(session, key); return (Row) storage.getRecord(session, (int) key);
} }
return rows.get(key); return rows.get((int) key);
} }
public void add(Session session, Row row) throws SQLException { public void add(Session session, Row row) throws SQLException {
...@@ -121,14 +121,16 @@ public class ScanIndex extends BaseIndex implements RowIndex { ...@@ -121,14 +121,16 @@ public class ScanIndex extends BaseIndex implements RowIndex {
// in-memory // in-memory
if (firstFree == -1) { if (firstFree == -1) {
int key = rows.size(); int key = rows.size();
row.setKey(key);
row.setPos(key); row.setPos(key);
rows.add(row); rows.add(row);
} else { } else {
int key = firstFree; long key = firstFree;
Row free = rows.get(key); Row free = rows.get((int) key);
firstFree = free.getPos(); firstFree = free.getKey();
row.setPos(key); row.setPos((int) key);
rows.set(key, row); row.setKey(key);
rows.set((int) key, row);
} }
row.setDeleted(false); row.setDeleted(false);
} }
...@@ -166,7 +168,7 @@ public class ScanIndex extends BaseIndex implements RowIndex { ...@@ -166,7 +168,7 @@ public class ScanIndex extends BaseIndex implements RowIndex {
public void remove(Session session, Row row) throws SQLException { public void remove(Session session, Row row) throws SQLException {
if (storage != null) { if (storage != null) {
storage.removeRecord(session, row.getPos()); storage.removeRecord(session, (int) row.getKey());
if (tableData.getContainsLargeObject()) { if (tableData.getContainsLargeObject()) {
for (int i = 0; i < row.getColumnCount(); i++) { for (int i = 0; i < row.getColumnCount(); i++) {
Value v = row.getValue(i); Value v = row.getValue(i);
...@@ -182,9 +184,10 @@ public class ScanIndex extends BaseIndex implements RowIndex { ...@@ -182,9 +184,10 @@ public class ScanIndex extends BaseIndex implements RowIndex {
firstFree = -1; firstFree = -1;
} else { } else {
Row free = new Row(null, 0); Row free = new Row(null, 0);
free.setPos(firstFree); free.setPos((int) firstFree);
int key = row.getPos(); free.setKey(firstFree);
rows.set(key, free); long key = row.getKey();
rows.set((int) key, free);
firstFree = key; firstFree = key;
} }
} }
...@@ -235,18 +238,18 @@ public class ScanIndex extends BaseIndex implements RowIndex { ...@@ -235,18 +238,18 @@ public class ScanIndex extends BaseIndex implements RowIndex {
*/ */
Row getNextRow(Session session, Row row) throws SQLException { Row getNextRow(Session session, Row row) throws SQLException {
if (storage == null) { if (storage == null) {
int key; long key;
if (row == null) { if (row == null) {
key = -1; key = -1;
} else { } else {
key = row.getPos(); key = row.getKey();
} }
while (true) { while (true) {
key++; key++;
if (key >= rows.size()) { if (key >= rows.size()) {
return null; return null;
} }
row = rows.get(key); row = rows.get((int) key);
if (!row.isEmpty()) { if (!row.isEmpty()) {
return row; return row;
} }
......
...@@ -36,8 +36,8 @@ public class TreeCursor implements Cursor { ...@@ -36,8 +36,8 @@ public class TreeCursor implements Cursor {
return get(); return get();
} }
public int getPos() { public long getKey() {
return node.row.getPos(); return node.row.getKey();
} }
public boolean next() throws SQLException { public boolean next() throws SQLException {
......
...@@ -38,7 +38,7 @@ public class ViewCursor implements Cursor { ...@@ -38,7 +38,7 @@ public class ViewCursor implements Cursor {
return current; return current;
} }
public int getPos() { public long getKey() {
throw Message.throwInternalError(); throw Message.throwInternalError();
} }
......
...@@ -115,7 +115,7 @@ public class UndoLogRecord { ...@@ -115,7 +115,7 @@ public class UndoLogRecord {
break; break;
case DELETE: case DELETE:
try { try {
row.setPos(0); row.setKey(0);
table.addRow(session, row); table.addRow(session, row);
// reset session id, otherwise other session think // reset session id, otherwise other session think
// that this row was inserted by this session // that this row was inserted by this session
......
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
package org.h2.result; package org.h2.result;
import java.sql.SQLException; import java.sql.SQLException;
import org.h2.store.DataPage; import org.h2.store.DataPage;
import org.h2.store.DiskFile; import org.h2.store.DiskFile;
import org.h2.store.Record; import org.h2.store.Record;
...@@ -19,6 +18,7 @@ import org.h2.value.Value; ...@@ -19,6 +18,7 @@ import org.h2.value.Value;
*/ */
public class Row extends Record implements SearchRow { public class Row extends Record implements SearchRow {
public static final int MEMORY_CALCULATE = -1; public static final int MEMORY_CALCULATE = -1;
private long key;
private final Value[] data; private final Value[] data;
private final int memory; private final int memory;
private int version; private int version;
...@@ -28,8 +28,8 @@ public class Row extends Record implements SearchRow { ...@@ -28,8 +28,8 @@ public class Row extends Record implements SearchRow {
this.memory = memory; this.memory = memory;
} }
public void setPosAndVersion(SearchRow row) { public void setKeyAndVersion(SearchRow row) {
setPos(row.getPos()); setKey(row.getKey());
setVersion(row.getVersion()); setVersion(row.getVersion());
} }
...@@ -41,6 +41,19 @@ public class Row extends Record implements SearchRow { ...@@ -41,6 +41,19 @@ public class Row extends Record implements SearchRow {
this.version = version; this.version = version;
} }
public long getKey() {
return key;
}
public void setKey(long key) {
this.key = key;
}
public void setPos(int pos) {
super.setPos(pos);
key = pos;
}
public Value getValue(int i) { public Value getValue(int i) {
return data[i]; return data[i];
} }
...@@ -86,8 +99,8 @@ public class Row extends Record implements SearchRow { ...@@ -86,8 +99,8 @@ public class Row extends Record implements SearchRow {
} }
public String toString() { public String toString() {
StatementBuilder buff = new StatementBuilder("( /* pos:"); StatementBuilder buff = new StatementBuilder("( /* key:");
buff.append(getPos()); buff.append(getKey());
if (version != 0) { if (version != 0) {
buff.append(" v:" + version); buff.append(" v:" + version);
} }
......
...@@ -55,7 +55,7 @@ public class RowList { ...@@ -55,7 +55,7 @@ public class RowList {
buff.writeByte((byte) 1); buff.writeByte((byte) 1);
buff.writeInt(r.getMemorySize()); buff.writeInt(r.getMemorySize());
buff.writeInt(r.getColumnCount()); buff.writeInt(r.getColumnCount());
buff.writeInt(r.getPos()); buff.writeLong(r.getKey());
buff.writeInt(r.getVersion()); buff.writeInt(r.getVersion());
buff.writeInt(r.isDeleted() ? 1 : 0); buff.writeInt(r.isDeleted() ? 1 : 0);
buff.writeInt(r.getSessionId()); buff.writeInt(r.getSessionId());
...@@ -170,10 +170,10 @@ public class RowList { ...@@ -170,10 +170,10 @@ public class RowList {
} }
int memory = buff.readInt(); int memory = buff.readInt();
int columnCount = buff.readInt(); int columnCount = buff.readInt();
int pos = buff.readInt(); long key = buff.readLong();
int version = buff.readInt(); int version = buff.readInt();
if (readUncached) { if (readUncached) {
pos = 0; key = 0;
} }
boolean deleted = buff.readInt() == 1; boolean deleted = buff.readInt() == 1;
int sessionId = buff.readInt(); int sessionId = buff.readInt();
...@@ -191,14 +191,14 @@ public class RowList { ...@@ -191,14 +191,14 @@ public class RowList {
} }
values[i] = v; values[i] = v;
} }
if (pos != 0 && cache != null) { if (key != 0 && cache != null) {
CacheObject found = cache.find(pos); CacheObject found = cache.find((int) key);
if (found != null) { if (found != null) {
return (Row) found; return (Row) found;
} }
} }
Row row = new Row(values, memory); Row row = new Row(values, memory);
row.setPos(pos); row.setKey(key);
row.setVersion(version); row.setVersion(version);
row.setDeleted(deleted); row.setDeleted(deleted);
row.setSessionId(sessionId); row.setSessionId(sessionId);
......
...@@ -42,27 +42,27 @@ public interface SearchRow { ...@@ -42,27 +42,27 @@ public interface SearchRow {
* *
* @param old the other row. * @param old the other row.
*/ */
void setPosAndVersion(SearchRow old); void setKeyAndVersion(SearchRow old);
/** /**
* Set the position (where the row is stored in the data file). * Get the version of the row.
* *
* @param pos the position. * @return the version
*/ */
void setPos(int pos); int getVersion();
/** /**
* Get the position of the row in the data file. * Set the unique key of the row.
* *
* @return the position * @param key the key
*/ */
int getPos(); void setKey(long key);
/** /**
* Get the version of the row. * Get the unique key of the row.
* *
* @return the version * @return the key
*/ */
int getVersion(); long getKey();
} }
...@@ -14,7 +14,7 @@ import org.h2.value.Value; ...@@ -14,7 +14,7 @@ import org.h2.value.Value;
*/ */
public class SimpleRow implements SearchRow { public class SimpleRow implements SearchRow {
private int pos; private long key;
private int version; private int version;
private Value[] data; private Value[] data;
...@@ -26,16 +26,16 @@ public class SimpleRow implements SearchRow { ...@@ -26,16 +26,16 @@ public class SimpleRow implements SearchRow {
return data.length; return data.length;
} }
public int getPos() { public long getKey() {
return pos; return key;
} }
public void setPos(int pos) { public void setKey(long key) {
this.pos = pos; this.key = key;
} }
public void setPosAndVersion(SearchRow row) { public void setKeyAndVersion(SearchRow row) {
pos = row.getPos(); key = row.getKey();
version = row.getVersion(); version = row.getVersion();
} }
...@@ -52,8 +52,8 @@ public class SimpleRow implements SearchRow { ...@@ -52,8 +52,8 @@ public class SimpleRow implements SearchRow {
} }
public String toString() { public String toString() {
StatementBuilder buff = new StatementBuilder("( /* pos:"); StatementBuilder buff = new StatementBuilder("( /* key:");
buff.append(getPos()); buff.append(getKey());
if (version != 0) { if (version != 0) {
buff.append(" v:" + version); buff.append(" v:" + version);
} }
......
...@@ -13,7 +13,7 @@ import org.h2.value.Value; ...@@ -13,7 +13,7 @@ import org.h2.value.Value;
*/ */
public class SimpleRowValue implements SearchRow { public class SimpleRowValue implements SearchRow {
private int pos; private long key;
private int version; private int version;
private int index; private int index;
private int virtualColumnCount; private int virtualColumnCount;
...@@ -23,8 +23,8 @@ public class SimpleRowValue implements SearchRow { ...@@ -23,8 +23,8 @@ public class SimpleRowValue implements SearchRow {
this.virtualColumnCount = columnCount; this.virtualColumnCount = columnCount;
} }
public void setPosAndVersion(SearchRow row) { public void setKeyAndVersion(SearchRow row) {
pos = row.getPos(); key = row.getKey();
version = row.getVersion(); version = row.getVersion();
} }
...@@ -35,15 +35,26 @@ public class SimpleRowValue implements SearchRow { ...@@ -35,15 +35,26 @@ public class SimpleRowValue implements SearchRow {
public int getColumnCount() { public int getColumnCount() {
return virtualColumnCount; return virtualColumnCount;
} }
public int getPos() { public int getPos() {
return pos; return (int) key;
}
public void setPos(int pos) {
this.key = pos;
}
public long getKey() {
return key;
} }
public void setKey(long key) {
this.key = key;
}
public Value getValue(int idx) { public Value getValue(int idx) {
return idx == index ? data : null; return idx == index ? data : null;
} }
public void setPos(int pos) {
this.pos = pos;
}
public void setValue(int idx, Value v) { public void setValue(int idx, Value v) {
index = idx; index = idx;
...@@ -51,7 +62,7 @@ public class SimpleRowValue implements SearchRow { ...@@ -51,7 +62,7 @@ public class SimpleRowValue implements SearchRow {
} }
public String toString() { public String toString() {
return "( /* " + pos + " */ " + data.getTraceSQL() + " )"; return "( /* " + key + " */ " + data.getTraceSQL() + " )";
} }
} }
...@@ -397,7 +397,7 @@ public class PageLog { ...@@ -397,7 +397,7 @@ public class PageLog {
* @return the row * @return the row
*/ */
public static Row readRow(DataReader in, Data data) throws IOException, SQLException { public static Row readRow(DataReader in, Data data) throws IOException, SQLException {
long pos = in.readVarLong(); long key = in.readVarLong();
int len = in.readVarInt(); int len = in.readVarInt();
data.reset(); data.reset();
data.checkCapacity(len); data.checkCapacity(len);
...@@ -409,7 +409,7 @@ public class PageLog { ...@@ -409,7 +409,7 @@ public class PageLog {
} }
// TODO maybe calculate the memory usage // TODO maybe calculate the memory usage
Row row = new Row(values, 0); Row row = new Row(values, 0);
row.setPos((int) pos); row.setKey(key);
return row; return row;
} }
...@@ -462,7 +462,7 @@ public class PageLog { ...@@ -462,7 +462,7 @@ public class PageLog {
outBuffer.writeByte((byte) FREE_LOG); outBuffer.writeByte((byte) FREE_LOG);
outBuffer.writeVarInt(pages.size()); outBuffer.writeVarInt(pages.size());
for (int i = 0; i < pages.size(); i++) { for (int i = 0; i < pages.size(); i++) {
outBuffer.writeInt(pages.get(i)); outBuffer.writeVarInt(pages.get(i));
} }
flushOut(); flushOut();
} catch (IOException e) { } catch (IOException e) {
...@@ -566,7 +566,7 @@ public class PageLog { ...@@ -566,7 +566,7 @@ public class PageLog {
outBuffer.writeByte((byte) (add ? ADD : REMOVE)); outBuffer.writeByte((byte) (add ? ADD : REMOVE));
outBuffer.writeVarInt(session.getId()); outBuffer.writeVarInt(session.getId());
outBuffer.writeVarInt(tableId); outBuffer.writeVarInt(tableId);
outBuffer.writeVarLong(row.getPos()); outBuffer.writeVarLong(row.getKey());
if (add) { if (add) {
outBuffer.writeVarInt(data.length()); outBuffer.writeVarInt(data.length());
outBuffer.checkCapacity(data.length()); outBuffer.checkCapacity(data.length());
......
...@@ -27,7 +27,7 @@ import org.h2.index.PageDataNode; ...@@ -27,7 +27,7 @@ import org.h2.index.PageDataNode;
import org.h2.index.PageDataOverflow; import org.h2.index.PageDataOverflow;
import org.h2.index.PageDelegateIndex; import org.h2.index.PageDelegateIndex;
import org.h2.index.PageIndex; import org.h2.index.PageIndex;
import org.h2.index.PageScanIndex; import org.h2.index.PageDataIndex;
import org.h2.log.InDoubtTransaction; import org.h2.log.InDoubtTransaction;
import org.h2.log.LogSystem; import org.h2.log.LogSystem;
import org.h2.message.Message; import org.h2.message.Message;
...@@ -80,9 +80,7 @@ import org.h2.value.ValueString; ...@@ -80,9 +80,7 @@ import org.h2.value.ValueString;
public class PageStore implements CacheWriter { public class PageStore implements CacheWriter {
// TODO check commit delay // TODO check commit delay
// TODO do not trim large databases fully, only up to x seconds
// TODO record: replace getPos() with long getKey() in page store
// TODO long primary keys don't use delegating index yet (setPos(): int)
// TODO implement checksum; 0 for empty pages // TODO implement checksum; 0 for empty pages
// TODO undo log: don't store empty space between head and data // TODO undo log: don't store empty space between head and data
...@@ -103,6 +101,7 @@ public class PageStore implements CacheWriter { ...@@ -103,6 +101,7 @@ public class PageStore implements CacheWriter {
// synchronized correctly (on the index?) // synchronized correctly (on the index?)
// TODO remove trace or use isDebugEnabled // TODO remove trace or use isDebugEnabled
// TODO recover tool: don't re-do uncommitted operations // TODO recover tool: don't re-do uncommitted operations
// TODO recover tool: support syntax to delete a row with a key
// TODO don't store default values (store a special value) // TODO don't store default values (store a special value)
// TODO split files (1 GB max size) // TODO split files (1 GB max size)
// TODO add a setting (that can be changed at runtime) to call fsync // TODO add a setting (that can be changed at runtime) to call fsync
...@@ -119,6 +118,7 @@ public class PageStore implements CacheWriter { ...@@ -119,6 +118,7 @@ public class PageStore implements CacheWriter {
// remove Record.getByteCount // remove Record.getByteCount
// remove Database.objectIds // remove Database.objectIds
// remove TableData.checkRowCount // remove TableData.checkRowCount
// remove Row.setPos
/** /**
* The smallest possible page size. * The smallest possible page size.
...@@ -186,7 +186,7 @@ public class PageStore implements CacheWriter { ...@@ -186,7 +186,7 @@ public class PageStore implements CacheWriter {
private Schema metaSchema; private Schema metaSchema;
private TableData metaTable; private TableData metaTable;
private PageScanIndex metaIndex; private PageDataIndex metaIndex;
private IntIntHashMap metaRootPageId = new IntIntHashMap(); private IntIntHashMap metaRootPageId = new IntIntHashMap();
private HashMap<Integer, Index> metaObjects = New.hashMap(); private HashMap<Integer, Index> metaObjects = New.hashMap();
...@@ -456,7 +456,7 @@ public class PageStore implements CacheWriter { ...@@ -456,7 +456,7 @@ public class PageStore implements CacheWriter {
break; break;
case Page.TYPE_DATA_LEAF: { case Page.TYPE_DATA_LEAF: {
int indexId = data.readVarInt(); int indexId = data.readVarInt();
PageScanIndex index = (PageScanIndex) metaObjects.get(indexId); PageDataIndex index = (PageDataIndex) metaObjects.get(indexId);
if (index == null) { if (index == null) {
Message.throwInternalError("index not found " + indexId); Message.throwInternalError("index not found " + indexId);
} }
...@@ -465,7 +465,7 @@ public class PageStore implements CacheWriter { ...@@ -465,7 +465,7 @@ public class PageStore implements CacheWriter {
} }
case Page.TYPE_DATA_NODE: { case Page.TYPE_DATA_NODE: {
int indexId = data.readVarInt(); int indexId = data.readVarInt();
PageScanIndex index = (PageScanIndex) metaObjects.get(indexId); PageDataIndex index = (PageDataIndex) metaObjects.get(indexId);
if (index == null) { if (index == null) {
Message.throwInternalError("index not found " + indexId); Message.throwInternalError("index not found " + indexId);
} }
...@@ -709,12 +709,12 @@ public class PageStore implements CacheWriter { ...@@ -709,12 +709,12 @@ public class PageStore implements CacheWriter {
private PageFreeList getFreeList(int i) throws SQLException { private PageFreeList getFreeList(int i) throws SQLException {
PageFreeList list = null; PageFreeList list = null;
if (i < freeLists.size()) { // if (i < freeLists.size()) {
list = freeLists.get(i); // list = freeLists.get(i);
if (list != null) { // if (list != null) {
return list; // return list;
} // }
} // }
int p = PAGE_ID_FREE_LIST_ROOT + i * freeListPagesPerList; int p = PAGE_ID_FREE_LIST_ROOT + i * freeListPagesPerList;
while (p >= pageCount) { while (p >= pageCount) {
increaseFileSize(INCREMENT_PAGES); increaseFileSize(INCREMENT_PAGES);
...@@ -958,7 +958,7 @@ public class PageStore implements CacheWriter { ...@@ -958,7 +958,7 @@ public class PageStore implements CacheWriter {
setReadOnly = true; setReadOnly = true;
} }
} }
PageScanIndex systemTable = (PageScanIndex) metaObjects.get(0); PageDataIndex systemTable = (PageDataIndex) metaObjects.get(0);
if (systemTable == null) { if (systemTable == null) {
systemTableHeadPos = Index.EMPTY_HEAD; systemTableHeadPos = Index.EMPTY_HEAD;
} else { } else {
...@@ -1060,7 +1060,7 @@ public class PageStore implements CacheWriter { ...@@ -1060,7 +1060,7 @@ public class PageStore implements CacheWriter {
*/ */
void redoDelete(int logPos, int tableId, long key) throws SQLException { void redoDelete(int logPos, int tableId, long key) throws SQLException {
Index index = metaObjects.get(tableId); Index index = metaObjects.get(tableId);
PageScanIndex scan = (PageScanIndex) index; PageDataIndex scan = (PageDataIndex) index;
Row row = scan.getRow(key); Row row = scan.getRow(key);
redo(logPos, tableId, row, false); redo(logPos, tableId, row, false);
} }
...@@ -1123,7 +1123,7 @@ public class PageStore implements CacheWriter { ...@@ -1123,7 +1123,7 @@ public class PageStore implements CacheWriter {
data.headPos = 0; data.headPos = 0;
data.session = systemSession; data.session = systemSession;
metaTable = new TableData(data); metaTable = new TableData(data);
metaIndex = (PageScanIndex) metaTable.getScanIndex( metaIndex = (PageDataIndex) metaTable.getScanIndex(
systemSession); systemSession);
metaObjects.clear(); metaObjects.clear();
metaObjects.put(-1, metaIndex); metaObjects.put(-1, metaIndex);
...@@ -1250,7 +1250,7 @@ public class PageStore implements CacheWriter { ...@@ -1250,7 +1250,7 @@ public class PageStore implements CacheWriter {
* @param session the session * @param session the session
*/ */
public void addMeta(PageIndex index, Session session) throws SQLException { public void addMeta(PageIndex index, Session session) throws SQLException {
int type = index instanceof PageScanIndex ? META_TYPE_SCAN_INDEX : META_TYPE_BTREE_INDEX; int type = index instanceof PageDataIndex ? META_TYPE_SCAN_INDEX : META_TYPE_BTREE_INDEX;
IndexColumn[] columns = index.getIndexColumns(); IndexColumn[] columns = index.getIndexColumns();
StatementBuilder buff = new StatementBuilder(); StatementBuilder buff = new StatementBuilder();
for (IndexColumn col : columns) { for (IndexColumn col : columns) {
......
...@@ -1681,7 +1681,7 @@ public class MetaTable extends Table { ...@@ -1681,7 +1681,7 @@ public class MetaTable extends Table {
values[i] = v; values[i] = v;
} }
Row row = new Row(values, 0); Row row = new Row(values, 0);
row.setPos(rows.size()); row.setKey(rows.size());
rows.add(row); rows.add(row);
} }
......
...@@ -29,7 +29,7 @@ import org.h2.index.MultiVersionIndex; ...@@ -29,7 +29,7 @@ import org.h2.index.MultiVersionIndex;
import org.h2.index.NonUniqueHashIndex; import org.h2.index.NonUniqueHashIndex;
import org.h2.index.PageBtreeIndex; import org.h2.index.PageBtreeIndex;
import org.h2.index.PageDelegateIndex; import org.h2.index.PageDelegateIndex;
import org.h2.index.PageScanIndex; import org.h2.index.PageDataIndex;
import org.h2.index.RowIndex; import org.h2.index.RowIndex;
import org.h2.index.ScanIndex; import org.h2.index.ScanIndex;
import org.h2.index.TreeIndex; import org.h2.index.TreeIndex;
...@@ -66,7 +66,7 @@ public class TableData extends Table implements RecordReader { ...@@ -66,7 +66,7 @@ public class TableData extends Table implements RecordReader {
private final ObjectArray<Index> indexes = ObjectArray.newInstance(); private final ObjectArray<Index> indexes = ObjectArray.newInstance();
private long lastModificationId; private long lastModificationId;
private boolean containsLargeObject; private boolean containsLargeObject;
private PageScanIndex mainIndex; private PageDataIndex mainIndex;
public TableData(CreateTableData data) throws SQLException { public TableData(CreateTableData data) throws SQLException {
super(data.schema, data.id, data.tableName, data.persistIndexes, data.persistData); super(data.schema, data.id, data.tableName, data.persistIndexes, data.persistData);
...@@ -75,7 +75,7 @@ public class TableData extends Table implements RecordReader { ...@@ -75,7 +75,7 @@ public class TableData extends Table implements RecordReader {
setColumns(cols); setColumns(cols);
setTemporary(data.temporary); setTemporary(data.temporary);
if (database.isPageStoreEnabled() && data.persistData && database.isPersistent()) { if (database.isPageStoreEnabled() && data.persistData && database.isPersistent()) {
mainIndex = new PageScanIndex(this, data.id, IndexColumn.wrap(cols), IndexType.createScan(data.persistData), data.headPos, data.session); mainIndex = new PageDataIndex(this, data.id, IndexColumn.wrap(cols), IndexType.createScan(data.persistData), data.headPos, data.session);
scanIndex = mainIndex; scanIndex = mainIndex;
} else { } else {
scanIndex = new ScanIndex(this, data.id, IndexColumn.wrap(cols), IndexType.createScan(data.persistData)); scanIndex = new ScanIndex(this, data.id, IndexColumn.wrap(cols), IndexType.createScan(data.persistData));
...@@ -104,10 +104,10 @@ public class TableData extends Table implements RecordReader { ...@@ -104,10 +104,10 @@ public class TableData extends Table implements RecordReader {
* Read the given row. * Read the given row.
* *
* @param session the session * @param session the session
* @param key the position of the row in the file * @param key unique key
* @return the row * @return the row
*/ */
public Row getRow(Session session, int key) throws SQLException { public Row getRow(Session session, long key) throws SQLException {
return scanIndex.getRow(session, key); return scanIndex.getRow(session, key);
} }
...@@ -302,8 +302,7 @@ public class TableData extends Table implements RecordReader { ...@@ -302,8 +302,7 @@ public class TableData extends Table implements RecordReader {
case Value.BYTE: case Value.BYTE:
case Value.SHORT: case Value.SHORT:
case Value.INT: case Value.INT:
int todoPosIsInt; case Value.LONG:
// case Value.LONG:
break; break;
default: default:
return -1; return -1;
......
...@@ -126,6 +126,10 @@ public class ValueInt extends Value { ...@@ -126,6 +126,10 @@ public class ValueInt extends Value {
return value; return value;
} }
public long getLong() {
return value;
}
protected int compareSecure(Value o, CompareMode mode) { protected int compareSecure(Value o, CompareMode mode) {
ValueInt v = (ValueInt) o; ValueInt v = (ValueInt) o;
if (value == v.value) { if (value == v.value) {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论