Hi,

in my application using H2 (1.4.196) i need to insert very large CLOB 
values.
Unfortunately H2 fails here with the following error:

org.h2.jdbc.JdbcSQLException: Out of memory. [90108-196]
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:345)
    at org.h2.message.DbException.get(DbException.java:168)
    at org.h2.message.DbException.convert(DbException.java:289)
    at org.h2.server.TcpServerThread.sendError(TcpServerThread.java:220)
    at org.h2.server.TcpServerThread.run(TcpServerThread.java:160)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Arrays.java:2367)
    at java.lang.String.<init>(String.java:168)
    at org.h2.value.Transfer.readValue(Transfer.java:673)
    at org.h2.server.TcpServerThread.setParameters(TcpServerThread.java:251)
    at org.h2.server.TcpServerThread.process(TcpServerThread.java:350)
    at org.h2.server.TcpServerThread.run(TcpServerThread.java:158)
    ... 1 more

    at org.h2.engine.SessionRemote.done(SessionRemote.java:629)
    at org.h2.command.CommandRemote.executeUpdate(CommandRemote.java:209)
    at 
org.h2.jdbc.JdbcPreparedStatement.executeUpdateInternal(JdbcPreparedStatement.java:164)
    at 
org.h2.jdbc.JdbcPreparedStatement.executeUpdate(JdbcPreparedStatement.java:150)
    at ClobInsert.insertClob(ClobInsert.java:82)
    at ClobInsert.main(ClobInsert.java:36)

The H2Server was started like this:
java.exe -Xmx512M -cp ".\h2\bin\h2-1.4.196.jar" org.h2.tools.Server 
-tcpPort 9092 -tcp

The connect String is:
jdbc:h2:tcp://localhost:9092/C:\temp\testdb


My sample program for reproduction (attached at the end) is capable of 
inserting a 50MB CLOB, for 100MB it fails.
Increasing XMX only has a little impact, and especially for 32bit I cannot 
increase XMX to much more than 1200M, so that I am unable to insert a 200MB 
CLOB on 32bit java running the H2 Server.

Is there any setting to work around this problem or is this simply a bug?


Sample Program for reproduction:

public class ClobInsert {

    /**
     * Main
     * @param args Unused
     */
    public static void main(String[] args) {
        String url = "jdbc:h2:tcp://localhost:9092/C:\\temp\\testdb";
        try (Connection connection = DriverManager.getConnection(url, "user"
, "psw")) {
            createTable(connection);
            
            try {
                insertClob(connection, 50);
                insertClob(connection, 100);
                insertClob(connection, 200);
                insertClob(connection, 300);
                insertClob(connection, 400);
                insertClob(connection, 500);
                insertClob(connection, 600);
                insertClob(connection, 700);
            } finally {
                dropTable(connection);
            }
        } catch (SQLException | IOException ex) {
            ex.printStackTrace();
        }
    }

    /**
     * Inserts a single CLOB of the given size
     * @param connection H2 Connection
     * @param mb The amount of MB to insert as CLOB
     * @throws IOException If file writing failed
     * @throws SQLException If database error occurred
     */
    private static void insertClob(Connection connection, int mb) throws 
IOException, SQLException {
        System.out.print("Attempting to insert " + mb + " MB of data...");
        File temp = File.createTempFile("tmp", ".clob");
        temp.deleteOnExit();
        writeBytes(temp, mb);

        try {
            Reader reader = new InputStreamReader(new FileInputStream(temp
));
            try (PreparedStatement st = connection.prepareStatement(
                    "insert into CLOBTAB (ID, value) values (?, ?)")) {
                st.setInt(1, mb);
                try {
                    st.setCharacterStream(2, reader);
                } catch (AbstractMethodError err) {
                    /*
                     * As of JDBC 1.0, only setCharacterStream(int index, 
Reader
                     * reader, int length) is specified. The method without 
an
                     * integer length is specified by JDBC 4.0, and might 
not be
                     * implemented by the driver.
                     */
                    st.setCharacterStream(2,
                            reader,
                            (int)temp.length());
                }
                st.executeUpdate();
            }
            connection.commit();
            System.out.println(" done.");
        } catch (SQLException ex) {
            System.out.println(" failed.");
            throw ex;
        }
    }

    /**
     * Writes sample bytes into the given file
     * @param temp Afile
     * @param mb The abount of MB to write
     * @throws IOException If file writing failed
     */
    private static void writeBytes(File temp, int mb) throws IOException {
        char[] buffer = new char[1_000_000];
        for (int j = 0; j < 1_000_000; j++) {
            buffer[j] = ((char)(35 + (j % 90)));
        }
        try (FileWriter writer = new FileWriter(temp)) {
            for (int i = 0; i < mb; i++) {
                writer.write(buffer);
            }
            writer.flush();
        }
    }

    /**
     * Creates tes ttable
     * @param connection H2 Connection
     * @throws SQLException If table cration failed
     */
    private static void createTable(Connection connection) throws 
SQLException {
        try (PreparedStatement st = connection.prepareStatement(
                "create table if not exists CLOBTAB (ID integer, value 
CLOB)")) {
            st.executeUpdate();
        }
    }

    /**
     * Drops test table
     * @param connection H2 Connection
     * @throws SQLException If tablecould not be dropped
     */
    private static void dropTable(Connection connection) throws SQLException 
{
        try (PreparedStatement st = connection.prepareStatement(
                "drop table if exists CLOBTAB")) {
            st.executeUpdate();
        }
    }
}




-- 
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.

Reply via email to