Search in sources :

Example 21 with Change

use of org.h2.mvstore.db.TransactionStore.Change in project h2database by h2database.

the class PageBtreeLeaf method remove.

@Override
SearchRow remove(SearchRow row) {
    int at = find(row, false, false, true);
    SearchRow delete = getRow(at);
    if (index.compareRows(row, delete) != 0 || delete.getKey() != row.getKey()) {
        throw DbException.get(ErrorCode.ROW_NOT_FOUND_WHEN_DELETING_1, index.getSQL() + ": " + row);
    }
    index.getPageStore().logUndo(this, data);
    if (entryCount == 1) {
        // the page is now empty
        return row;
    }
    removeRow(at);
    memoryChange();
    index.getPageStore().update(this);
    if (at == entryCount) {
        // the last row changed
        return getRow(at - 1);
    }
    // the last row didn't change
    return null;
}
Also used : SearchRow(org.h2.result.SearchRow)

Example 22 with Change

use of org.h2.mvstore.db.TransactionStore.Change in project h2database by h2database.

the class TestDateStorage method testDateTimeTimestampWithCalendar.

private void testDateTimeTimestampWithCalendar() throws SQLException {
    Connection conn = getConnection(getTestName());
    Statement stat = conn.createStatement();
    stat.execute("create table ts(x timestamp primary key)");
    stat.execute("create table t(x time primary key)");
    stat.execute("create table d(x date)");
    Calendar utcCalendar = new GregorianCalendar(new SimpleTimeZone(0, "Z"));
    TimeZone old = TimeZone.getDefault();
    DateTimeUtils.resetCalendar();
    TimeZone.setDefault(TimeZone.getTimeZone("PST"));
    try {
        Timestamp ts1 = Timestamp.valueOf("2010-03-13 18:15:00");
        Time t1 = new Time(ts1.getTime());
        Date d1 = new Date(ts1.getTime());
        // when converted to UTC, this is 03:15, which doesn't actually
        // exist because of summer time change at that day
        Timestamp ts2 = Timestamp.valueOf("2010-03-13 19:15:00");
        Time t2 = new Time(ts2.getTime());
        Date d2 = new Date(ts2.getTime());
        PreparedStatement prep;
        ResultSet rs;
        prep = conn.prepareStatement("insert into ts values(?)");
        prep.setTimestamp(1, ts1, utcCalendar);
        prep.execute();
        prep.setTimestamp(1, ts2, utcCalendar);
        prep.execute();
        prep = conn.prepareStatement("insert into t values(?)");
        prep.setTime(1, t1, utcCalendar);
        prep.execute();
        prep.setTime(1, t2, utcCalendar);
        prep.execute();
        prep = conn.prepareStatement("insert into d values(?)");
        prep.setDate(1, d1, utcCalendar);
        prep.execute();
        prep.setDate(1, d2, utcCalendar);
        prep.execute();
        rs = stat.executeQuery("select * from ts order by x");
        rs.next();
        assertEquals("2010-03-14 02:15:00", rs.getString(1));
        assertEquals("2010-03-13 18:15:00.0", rs.getTimestamp(1, utcCalendar).toString());
        assertEquals("2010-03-14 03:15:00.0", rs.getTimestamp(1).toString());
        assertEquals("2010-03-14 02:15:00", rs.getString("x"));
        assertEquals("2010-03-13 18:15:00.0", rs.getTimestamp("x", utcCalendar).toString());
        assertEquals("2010-03-14 03:15:00.0", rs.getTimestamp("x").toString());
        rs.next();
        assertEquals("2010-03-14 03:15:00", rs.getString(1));
        assertEquals("2010-03-13 19:15:00.0", rs.getTimestamp(1, utcCalendar).toString());
        assertEquals("2010-03-14 03:15:00.0", rs.getTimestamp(1).toString());
        assertEquals("2010-03-14 03:15:00", rs.getString("x"));
        assertEquals("2010-03-13 19:15:00.0", rs.getTimestamp("x", utcCalendar).toString());
        assertEquals("2010-03-14 03:15:00.0", rs.getTimestamp("x").toString());
        rs = stat.executeQuery("select * from t order by x");
        rs.next();
        assertEquals("02:15:00", rs.getString(1));
        assertEquals("18:15:00", rs.getTime(1, utcCalendar).toString());
        assertEquals("02:15:00", rs.getTime(1).toString());
        assertEquals("02:15:00", rs.getString("x"));
        assertEquals("18:15:00", rs.getTime("x", utcCalendar).toString());
        assertEquals("02:15:00", rs.getTime("x").toString());
        rs.next();
        assertEquals("03:15:00", rs.getString(1));
        assertEquals("19:15:00", rs.getTime(1, utcCalendar).toString());
        assertEquals("03:15:00", rs.getTime(1).toString());
        assertEquals("03:15:00", rs.getString("x"));
        assertEquals("19:15:00", rs.getTime("x", utcCalendar).toString());
        assertEquals("03:15:00", rs.getTime("x").toString());
        rs = stat.executeQuery("select * from d order by x");
        rs.next();
        assertEquals("2010-03-14", rs.getString(1));
        assertEquals("2010-03-13", rs.getDate(1, utcCalendar).toString());
        assertEquals("2010-03-14", rs.getDate(1).toString());
        assertEquals("2010-03-14", rs.getString("x"));
        assertEquals("2010-03-13", rs.getDate("x", utcCalendar).toString());
        assertEquals("2010-03-14", rs.getDate("x").toString());
        rs.next();
        assertEquals("2010-03-14", rs.getString(1));
        assertEquals("2010-03-13", rs.getDate(1, utcCalendar).toString());
        assertEquals("2010-03-14", rs.getDate(1).toString());
        assertEquals("2010-03-14", rs.getString("x"));
        assertEquals("2010-03-13", rs.getDate("x", utcCalendar).toString());
        assertEquals("2010-03-14", rs.getDate("x").toString());
    } finally {
        TimeZone.setDefault(old);
        DateTimeUtils.resetCalendar();
    }
    stat.execute("drop table ts");
    stat.execute("drop table t");
    stat.execute("drop table d");
    conn.close();
}
Also used : TimeZone(java.util.TimeZone) SimpleTimeZone(java.util.SimpleTimeZone) SimpleTimeZone(java.util.SimpleTimeZone) PreparedStatement(java.sql.PreparedStatement) Statement(java.sql.Statement) GregorianCalendar(java.util.GregorianCalendar) Calendar(java.util.Calendar) Connection(java.sql.Connection) GregorianCalendar(java.util.GregorianCalendar) ResultSet(java.sql.ResultSet) Time(java.sql.Time) PreparedStatement(java.sql.PreparedStatement) Timestamp(java.sql.Timestamp) ValueTimestamp(org.h2.value.ValueTimestamp) Date(java.sql.Date) TestDate(org.h2.test.unit.TestDate)

Example 23 with Change

use of org.h2.mvstore.db.TransactionStore.Change in project h2database by h2database.

the class TestTransactionStore method testMultiStatement.

/**
 * Tests behavior when used for a sequence of SQL statements. Each statement
 * uses a savepoint. Within a statement, changes by the statement itself are
 * not seen; the change is only seen when the statement finished.
 * <p>
 * Update statements that change the key of multiple rows may use delete/add
 * pairs to do so (they don't need to first delete all entries and then
 * re-add them). Trying to add multiple values for the same key is not
 * allowed (an update statement that would result in a duplicate key).
 */
private void testMultiStatement() {
    MVStore s = MVStore.open(null);
    TransactionStore ts = new TransactionStore(s);
    ts.init();
    Transaction tx;
    TransactionMap<String, String> m;
    long startUpdate;
    tx = ts.begin();
    // start of statement
    // create table test
    startUpdate = tx.setSavepoint();
    m = tx.openMap("test");
    m.setSavepoint(startUpdate);
    // start of statement
    // insert into test(id, name) values(1, 'Hello'), (2, 'World')
    startUpdate = tx.setSavepoint();
    m.setSavepoint(startUpdate);
    assertTrue(m.trySet("1", "Hello", true));
    assertTrue(m.trySet("2", "World", true));
    // not seen yet (within the same statement)
    assertNull(m.get("1"));
    assertNull(m.get("2"));
    // start of statement
    startUpdate = tx.setSavepoint();
    // now we see the newest version
    m.setSavepoint(startUpdate);
    assertEquals("Hello", m.get("1"));
    assertEquals("World", m.get("2"));
    // update test set primaryKey = primaryKey + 1
    // (this is usually a tricky case)
    assertEquals("Hello", m.get("1"));
    assertTrue(m.trySet("1", null, true));
    assertTrue(m.trySet("2", "Hello", true));
    assertEquals("World", m.get("2"));
    // already updated by this statement, so it has no effect
    // but still returns true because it was changed by this transaction
    assertTrue(m.trySet("2", null, true));
    assertTrue(m.trySet("3", "World", true));
    // not seen within this statement
    assertEquals("Hello", m.get("1"));
    assertEquals("World", m.get("2"));
    assertNull(m.get("3"));
    // start of statement
    startUpdate = tx.setSavepoint();
    m.setSavepoint(startUpdate);
    // select * from test
    assertNull(m.get("1"));
    assertEquals("Hello", m.get("2"));
    assertEquals("World", m.get("3"));
    // start of statement
    startUpdate = tx.setSavepoint();
    m.setSavepoint(startUpdate);
    // update test set id = 1
    // should fail: duplicate key
    assertTrue(m.trySet("2", null, true));
    assertTrue(m.trySet("1", "Hello", true));
    assertTrue(m.trySet("3", null, true));
    assertFalse(m.trySet("1", "World", true));
    tx.rollbackToSavepoint(startUpdate);
    startUpdate = tx.setSavepoint();
    m.setSavepoint(startUpdate);
    assertNull(m.get("1"));
    assertEquals("Hello", m.get("2"));
    assertEquals("World", m.get("3"));
    tx.commit();
    ts.close();
    s.close();
}
Also used : MVStore(org.h2.mvstore.MVStore) TransactionStore(org.h2.mvstore.db.TransactionStore) Transaction(org.h2.mvstore.db.TransactionStore.Transaction)

Example 24 with Change

use of org.h2.mvstore.db.TransactionStore.Change in project h2database by h2database.

the class TestTransactionStore method testGetModifiedMaps.

private void testGetModifiedMaps() {
    MVStore s = MVStore.open(null);
    TransactionStore ts = new TransactionStore(s);
    ts.init();
    Transaction tx;
    TransactionMap<String, String> m1, m2, m3;
    long sp;
    tx = ts.begin();
    m1 = tx.openMap("m1");
    m2 = tx.openMap("m2");
    m3 = tx.openMap("m3");
    assertFalse(tx.getChanges(0).hasNext());
    tx.commit();
    tx = ts.begin();
    m1 = tx.openMap("m1");
    m2 = tx.openMap("m2");
    m3 = tx.openMap("m3");
    m1.put("1", "100");
    sp = tx.setSavepoint();
    m2.put("1", "100");
    m3.put("1", "100");
    Iterator<Change> it = tx.getChanges(sp);
    assertTrue(it.hasNext());
    Change c;
    c = it.next();
    assertEquals("m3", c.mapName);
    assertEquals("1", c.key.toString());
    assertNull(c.value);
    assertTrue(it.hasNext());
    c = it.next();
    assertEquals("m2", c.mapName);
    assertEquals("1", c.key.toString());
    assertNull(c.value);
    assertFalse(it.hasNext());
    it = tx.getChanges(0);
    assertTrue(it.hasNext());
    c = it.next();
    assertEquals("m3", c.mapName);
    assertEquals("1", c.key.toString());
    assertNull(c.value);
    assertTrue(it.hasNext());
    c = it.next();
    assertEquals("m2", c.mapName);
    assertEquals("1", c.key.toString());
    assertNull(c.value);
    assertTrue(it.hasNext());
    c = it.next();
    assertEquals("m1", c.mapName);
    assertEquals("1", c.key.toString());
    assertNull(c.value);
    assertFalse(it.hasNext());
    tx.rollbackToSavepoint(sp);
    it = tx.getChanges(0);
    assertTrue(it.hasNext());
    c = it.next();
    assertEquals("m1", c.mapName);
    assertEquals("1", c.key.toString());
    assertNull(c.value);
    assertFalse(it.hasNext());
    tx.commit();
    s.close();
}
Also used : MVStore(org.h2.mvstore.MVStore) TransactionStore(org.h2.mvstore.db.TransactionStore) Transaction(org.h2.mvstore.db.TransactionStore.Transaction) Change(org.h2.mvstore.db.TransactionStore.Change)

Example 25 with Change

use of org.h2.mvstore.db.TransactionStore.Change in project h2database by h2database.

the class ArchiveToolStore method compress.

private void compress(String sourceDir) throws Exception {
    start();
    long tempSize = 8 * 1024 * 1024;
    String tempFileName = fileName + ".temp";
    ArrayList<String> fileNames = New.arrayList();
    System.out.println("Reading the file list");
    long totalSize = addFiles(sourceDir, fileNames);
    System.out.println("Compressing " + totalSize / MB + " MB");
    FileUtils.delete(tempFileName);
    FileUtils.delete(fileName);
    MVStore storeTemp = new MVStore.Builder().fileName(tempFileName).autoCommitDisabled().open();
    final MVStore store = new MVStore.Builder().fileName(fileName).pageSplitSize(2 * 1024 * 1024).compressHigh().autoCommitDisabled().open();
    MVMap<String, int[]> filesTemp = storeTemp.openMap("files");
    long currentSize = 0;
    int segmentId = 1;
    int segmentLength = 0;
    ByteBuffer buff = ByteBuffer.allocate(1024 * 1024);
    for (String s : fileNames) {
        String name = s.substring(sourceDir.length() + 1);
        if (FileUtils.isDirectory(s)) {
            // directory
            filesTemp.put(name, new int[1]);
            continue;
        }
        buff.clear();
        buff.flip();
        ArrayList<Integer> posList = new ArrayList<>();
        try (FileChannel fc = FileUtils.open(s, "r")) {
            boolean eof = false;
            while (true) {
                while (!eof && buff.remaining() < 512 * 1024) {
                    int remaining = buff.remaining();
                    buff.compact();
                    buff.position(remaining);
                    int l = fc.read(buff);
                    if (l < 0) {
                        eof = true;
                    }
                    buff.flip();
                }
                if (buff.remaining() == 0) {
                    break;
                }
                int position = buff.position();
                int c = getChunkLength(buff.array(), position, buff.limit()) - position;
                byte[] bytes = Arrays.copyOfRange(buff.array(), position, position + c);
                buff.position(position + c);
                int[] key = getKey(bucket, bytes);
                key[3] = segmentId;
                while (true) {
                    MVMap<int[], byte[]> data = storeTemp.openMap("data" + segmentId);
                    byte[] old = data.get(key);
                    if (old == null) {
                        // new
                        data.put(key, bytes);
                        break;
                    }
                    if (Arrays.equals(old, bytes)) {
                        // duplicate
                        break;
                    }
                    // same checksum: change checksum
                    key[2]++;
                }
                for (int i = 0; i < key.length; i++) {
                    posList.add(key[i]);
                }
                segmentLength += c;
                currentSize += c;
                if (segmentLength > tempSize) {
                    storeTemp.commit();
                    segmentId++;
                    segmentLength = 0;
                }
                printProgress(0, 50, currentSize, totalSize);
            }
        }
        int[] posArray = new int[posList.size()];
        for (int i = 0; i < posList.size(); i++) {
            posArray[i] = posList.get(i);
        }
        filesTemp.put(name, posArray);
    }
    storeTemp.commit();
    ArrayList<Cursor<int[], byte[]>> list = New.arrayList();
    totalSize = 0;
    for (int i = 1; i <= segmentId; i++) {
        MVMap<int[], byte[]> data = storeTemp.openMap("data" + i);
        totalSize += data.sizeAsLong();
        Cursor<int[], byte[]> c = data.cursor(null);
        if (c.hasNext()) {
            c.next();
            list.add(c);
        }
    }
    segmentId = 1;
    segmentLength = 0;
    currentSize = 0;
    MVMap<int[], byte[]> data = store.openMap("data" + segmentId);
    MVMap<int[], Boolean> keepSegment = storeTemp.openMap("keep");
    while (list.size() > 0) {
        Collections.sort(list, new Comparator<Cursor<int[], byte[]>>() {

            @Override
            public int compare(Cursor<int[], byte[]> o1, Cursor<int[], byte[]> o2) {
                int[] k1 = o1.getKey();
                int[] k2 = o2.getKey();
                int comp = 0;
                for (int i = 0; i < k1.length - 1; i++) {
                    long x1 = k1[i];
                    long x2 = k2[i];
                    if (x1 > x2) {
                        comp = 1;
                        break;
                    } else if (x1 < x2) {
                        comp = -1;
                        break;
                    }
                }
                return comp;
            }
        });
        Cursor<int[], byte[]> top = list.get(0);
        int[] key = top.getKey();
        byte[] bytes = top.getValue();
        int[] k2 = Arrays.copyOf(key, key.length);
        k2[key.length - 1] = 0;
        // TODO this lookup can be avoided
        // if we remember the last entry with k[..] = 0
        byte[] old = data.get(k2);
        if (old == null) {
            if (segmentLength > tempSize) {
                // switch only for new entries
                // where segmentId is 0,
                // so that entries with the same
                // key but different segmentId
                // are in the same segment
                store.commit();
                segmentLength = 0;
                segmentId++;
                data = store.openMap("data" + segmentId);
            }
            key = k2;
            // new entry
            data.put(key, bytes);
            segmentLength += bytes.length;
        } else if (Arrays.equals(old, bytes)) {
        // duplicate
        } else {
            // almost a duplicate:
            // keep segment id
            keepSegment.put(key, Boolean.TRUE);
            data.put(key, bytes);
            segmentLength += bytes.length;
        }
        if (!top.hasNext()) {
            list.remove(0);
        } else {
            top.next();
        }
        currentSize++;
        printProgress(50, 100, currentSize, totalSize);
    }
    MVMap<String, int[]> files = store.openMap("files");
    for (Entry<String, int[]> e : filesTemp.entrySet()) {
        String k = e.getKey();
        int[] ids = e.getValue();
        if (ids.length == 1) {
            // directory
            files.put(k, ids);
            continue;
        }
        int[] newIds = Arrays.copyOf(ids, ids.length);
        for (int i = 0; i < ids.length; i += 4) {
            int[] id = new int[4];
            id[0] = ids[i];
            id[1] = ids[i + 1];
            id[2] = ids[i + 2];
            id[3] = ids[i + 3];
            if (!keepSegment.containsKey(id)) {
                newIds[i + 3] = 0;
            }
        }
        files.put(k, newIds);
    }
    store.commit();
    storeTemp.close();
    FileUtils.delete(tempFileName);
    store.close();
    System.out.println();
    System.out.println("Compressed to " + FileUtils.size(fileName) / MB + " MB");
    printDone();
}
Also used : FileChannel(java.nio.channels.FileChannel) ArrayList(java.util.ArrayList) Cursor(org.h2.mvstore.Cursor) ByteBuffer(java.nio.ByteBuffer) MVStore(org.h2.mvstore.MVStore)

Aggregations

DbException (org.h2.message.DbException)7 IOException (java.io.IOException)5 PreparedStatement (java.sql.PreparedStatement)5 Statement (java.sql.Statement)4 ArrayList (java.util.ArrayList)4 ExpressionColumn (org.h2.expression.ExpressionColumn)4 Row (org.h2.result.Row)4 SearchRow (org.h2.result.SearchRow)4 Column (org.h2.table.Column)4 SQLException (java.sql.SQLException)3 Properties (java.util.Properties)3 Index (org.h2.index.Index)3 MVStore (org.h2.mvstore.MVStore)3 Connection (java.sql.Connection)2 ResultSet (java.sql.ResultSet)2 Analyzer (org.apache.lucene.analysis.Analyzer)2 StandardAnalyzer (org.apache.lucene.analysis.standard.StandardAnalyzer)2 Document (org.apache.lucene.document.Document)2 QueryParser (org.apache.lucene.queryParser.QueryParser)2 Constraint (org.h2.constraint.Constraint)2