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();
}
}