Hi devs,

It seems that there is a bug in the latest officially released version of 
H2 that causes database files (regardless of the backing storage) to grow 
even if the whole transaction gets rolled back. The problem occurs with 
BLOBs, switching to other datatype (e.g. VARCHAR) makes the issue disappear.

I'm attaching a standalone testcase.


Regards,
wburzyns

-- 
You received this message because you are subscribed to the Google Groups "H2 
Database" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/h2-database.
For more options, visit https://groups.google.com/d/optout.

import java.io.File;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Random;
import org.h2.jdbcx.JdbcDataSource;
import org.h2.store.fs.FileUtils;


public class H2IncreasingSizeTest
{
    public static void main(final String[] args)
    {
        try {
            // remove previous DB, if any
            File testDbDir = new File(System.getProperty("java.io.tmpdir"), "H2SizeTest");
            FileUtils.deleteRecursive(testDbDir.getCanonicalPath(), false);
            testDbDir.mkdirs();

            // create a new DB
            JdbcDataSource dataSource = new JdbcDataSource();
            dataSource.setURL("jdbc:h2:" + testDbDir.getCanonicalPath() + File.separator + "H2SizeTest" + ";MAX_LOG_SIZE=1");
            Connection dbConn = dataSource.getConnection();

            Statement st = dbConn.createStatement();
            st.executeUpdate("CREATE SEQUENCE IF NOT EXISTS dataStampSequence CACHE 1024");
            st.executeUpdate("CREATE TABLE IF NOT EXISTS dataTable("
                    + "dataStamp BIGINT NOT NULL DEFAULT NEXT VALUE FOR dataStampSequence PRIMARY KEY, "
                    + "data1 BLOB, "
                    + "data2 BLOB)");
            st.close();

            // push data
            Random rnd = new Random(0xBAD);
            PreparedStatement dataInsertSt = dbConn.prepareStatement("INSERT INTO dataTable VALUES("
                    + "DEFAULT, "
                    + "?, "
                    + "?)");
            dbConn.setAutoCommit(false);
            for (int i = 0; i < 10000; ++i) {
                if (dbConn.getAutoCommit() == true) {
                    throw new AssertionError();
                }

                byte[] data1 = new byte[rnd.nextInt(4096) + 1];
                rnd.nextBytes(data1);
                dataInsertSt.setBytes(1, data1);

                byte[] data2 = new byte[rnd.nextInt(4096) + 1];
                rnd.nextBytes(data2);
                dataInsertSt.setBytes(2, data2);

                dataInsertSt.executeUpdate();
                dataInsertSt.clearParameters();

                dbConn.rollback();
            }
            dataInsertSt.close();

            // make sure that the only table has no rows
            st = dbConn.createStatement();
            ResultSet rs = st.executeQuery("SELECT COUNT(*) FROM dataTable");
            rs.first();
            long numRows = rs.getLong(1);
            if (numRows != 0) {
                throw new AssertionError();
            }
            st.close();

            dbConn.close();

            // the test DB is now closed; its only table has no rows but size of the DB file is almost 20 MB
        } catch (final Exception e) {
            e.printStackTrace();
        }
    }
}

Reply via email to