We are experiencing null pointer exceptions when we attempt to store a null 
geometry in H2 when we close the connection

Attached is a small test.

org.h2.jdbc.JdbcSQLException: General error: 
"java.lang.NullPointerException" [50000-186]
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:295)
at org.h2.message.DbException.toSQLException(DbException.java:268)
at org.h2.message.TraceObject.logAndConvert(TraceObject.java:352)
at org.h2.jdbc.JdbcConnection.close(JdbcConnection.java:392)
at com.intergraph.test.NullGeometryTest.startTest(NullGeometryTest.java:46)
at com.intergraph.test.NullGeometryTest.main(NullGeometryTest.java:21)
Caused by: java.lang.NullPointerException
at org.h2.mvstore.rtree.SpatialDataType.write(SpatialDataType.java:89)
at org.h2.mvstore.rtree.SpatialDataType.write(SpatialDataType.java:80)
at org.h2.mvstore.Page.write(Page.java:735)
at org.h2.mvstore.Page.writeUnsavedRecursive(Page.java:818)
at org.h2.mvstore.MVStore.storeNowTry(MVStore.java:1057)
at org.h2.mvstore.MVStore.storeNow(MVStore.java:973)
at org.h2.mvstore.MVStore.commitAndSave(MVStore.java:962)
at org.h2.mvstore.MVStore.commit(MVStore.java:923)
at org.h2.mvstore.db.TransactionStore.close(TransactionStore.java:217)
at org.h2.mvstore.db.MVTableEngine$Store.close(MVTableEngine.java:346)
at org.h2.engine.Database.closeOpenFilesAndUnlock(Database.java:1359)
at org.h2.engine.Database.close(Database.java:1259)
at org.h2.engine.Database.removeSession(Database.java:1143)
at org.h2.engine.Session.close(Session.java:678)
at org.h2.jdbc.JdbcConnection.close(JdbcConnection.java:384)

We found that a simple null check wasn't sufficient as it messes up the 
index.

We instead added a line of code that created a dummy SpatialKey when the 
given key is null. This works for now but isn't a perfect solution.

    @Override
    public void write(WriteBuffer buff, Object obj) {
        SpatialKey k = (SpatialKey) obj;
        int flags = 0;
        for (int i = 0; i < dimensions; i++) {
            if (k.min(i) == k.max(i)) {
                flags |= 1 << i;
            }
        }
        buff.putVarInt(flags);
        for (int i = 0; i < dimensions; i++) {
            buff.putFloat(k.min(i));
            if ((flags & (1 << i)) == 0) {
                buff.putFloat(k.max(i));
            }
        }
        buff.putVarLong(k.getId());
    }


    @Override
    public void write(WriteBuffer buff, Object obj) {
    if ( obj == null ){
    obj = new SpatialKey(0,0,0,0,0);
    }
        SpatialKey k = (SpatialKey) obj;
        int flags = 0;
        for (int i = 0; i < dimensions; i++) {
            if (k.min(i) == k.max(i)) {
                flags |= 1 << i;
            }
        }
        buff.putVarInt(flags);
        for (int i = 0; i < dimensions; i++) {
            buff.putFloat(k.min(i));
            if ((flags & (1 << i)) == 0) {
                buff.putFloat(k.max(i));
            }
        }
        buff.putVarLong(k.getId());
    }

-- 
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 http://groups.google.com/group/h2-database.
For more options, visit https://groups.google.com/d/optout.
package com.intergraph.test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;

import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;

public class NullGeometryTest {

	/**
	 * @param args
	 */
	public static void main(String[] args) {

		NullGeometryTest test = new NullGeometryTest();
		test.startTest();
		
	}
	
	private void startTest(){
		Connection con = null;
		try {
			con = getConnection();
			
			createTable(con);
			
			insertNullGeom(con);
			
		} catch (Exception e) {

			e.printStackTrace();
		}
		finally{
			try {
//				dropTable( con );
				con.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	
	public Connection getConnection() throws Exception{
        
		Class.forName("org.h2.Driver");
        
        Connection conn = DriverManager.getConnection("jdbc:h2:~/test", "sa", "");
        
        return conn;
	}
	
	public void createTable( Connection con ) throws Exception{
		
		String tableSql = " CREATE TABLE GEOM_TEST ( GID IDENTITY, COMMENTS VARCHAR2(32), GEOM GEOMETRY)";
		
		String indexSql = " CREATE SPATIAL INDEX GEOM_TEST_SPATIALINDEX ON GEOM_TEST( GEOM )";

		Statement stmt = con.createStatement();
		
		stmt.execute(tableSql);
		
		stmt.execute(indexSql);
		
		stmt.close();
		
	}

	
	public void dropTable( Connection con ) throws Exception{
		
		String tableSql = " DROP TABLE IF EXISTS GEOM_TEST";
		
		Statement stmt = con.createStatement();
		
		stmt.execute(tableSql);
		
		stmt.close();
		
	}

	public void insertNullGeom( Connection con ) throws Exception{
	
		String sql = "insert into geom_test ( comments ) values ( 'Null geometry' )";
		
		PreparedStatement stmt = con.prepareStatement(sql);
		
		stmt.executeUpdate();
		
		stmt.close();
		
	}



}

Reply via email to