提交 8f89554c authored 作者: Thomas Mueller's avatar Thomas Mueller

Issue 609: the spatial index did not support NULL (ClassCastException).

上级 0d26b2ae
...@@ -23,6 +23,7 @@ import org.h2.table.Table; ...@@ -23,6 +23,7 @@ import org.h2.table.Table;
import org.h2.table.TableFilter; import org.h2.table.TableFilter;
import org.h2.value.Value; import org.h2.value.Value;
import org.h2.value.ValueGeometry; import org.h2.value.ValueGeometry;
import org.h2.value.ValueNull;
import com.vividsolutions.jts.geom.Envelope; import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.Geometry;
...@@ -125,11 +126,17 @@ public class SpatialTreeIndex extends BaseIndex implements SpatialIndex { ...@@ -125,11 +126,17 @@ public class SpatialTreeIndex extends BaseIndex implements SpatialIndex {
if (closed) { if (closed) {
throw DbException.throwInternalError(); throw DbException.throwInternalError();
} }
treeMap.add(getEnvelope(row), row.getKey()); treeMap.add(getKey(row), row.getKey());
} }
private SpatialKey getEnvelope(SearchRow row) { private SpatialKey getKey(SearchRow row) {
if (row == null) {
return null;
}
Value v = row.getValue(columnIds[0]); Value v = row.getValue(columnIds[0]);
if (v == ValueNull.INSTANCE) {
return null;
}
Geometry g = ((ValueGeometry) v.convertTo(Value.GEOMETRY)).getGeometryNoCopy(); Geometry g = ((ValueGeometry) v.convertTo(Value.GEOMETRY)).getGeometryNoCopy();
Envelope env = g.getEnvelopeInternal(); Envelope env = g.getEnvelopeInternal();
return new SpatialKey(row.getKey(), return new SpatialKey(row.getKey(),
...@@ -142,7 +149,7 @@ public class SpatialTreeIndex extends BaseIndex implements SpatialIndex { ...@@ -142,7 +149,7 @@ public class SpatialTreeIndex extends BaseIndex implements SpatialIndex {
if (closed) { if (closed) {
throw DbException.throwInternalError(); throw DbException.throwInternalError();
} }
if (!treeMap.remove(getEnvelope(row), row.getKey())) { if (!treeMap.remove(getKey(row), row.getKey())) {
throw DbException.throwInternalError("row not found"); throw DbException.throwInternalError("row not found");
} }
} }
...@@ -167,7 +174,7 @@ public class SpatialTreeIndex extends BaseIndex implements SpatialIndex { ...@@ -167,7 +174,7 @@ public class SpatialTreeIndex extends BaseIndex implements SpatialIndex {
return find(filter.getSession()); return find(filter.getSession());
} }
return new SpatialCursor( return new SpatialCursor(
treeMap.findIntersectingKeys(getEnvelope(intersection)), table, treeMap.findIntersectingKeys(getKey(intersection)), table,
filter.getSession()); filter.getSession());
} }
......
...@@ -32,6 +32,7 @@ import org.h2.table.TableFilter; ...@@ -32,6 +32,7 @@ import org.h2.table.TableFilter;
import org.h2.value.Value; import org.h2.value.Value;
import org.h2.value.ValueGeometry; import org.h2.value.ValueGeometry;
import org.h2.value.ValueLong; import org.h2.value.ValueLong;
import org.h2.value.ValueNull;
import com.vividsolutions.jts.geom.Envelope; import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.Geometry;
...@@ -161,18 +162,6 @@ public class MVSpatialIndex extends BaseIndex implements SpatialIndex, MVIndex { ...@@ -161,18 +162,6 @@ public class MVSpatialIndex extends BaseIndex implements SpatialIndex, MVIndex {
} }
} }
private SpatialKey getKey(SearchRow r) {
if (r == null) {
return null;
}
Value v = r.getValue(columnIds[0]);
Geometry g = ((ValueGeometry) v.convertTo(Value.GEOMETRY)).getGeometryNoCopy();
Envelope env = g.getEnvelopeInternal();
return new SpatialKey(r.getKey(),
(float) env.getMinX(), (float) env.getMaxX(),
(float) env.getMinY(), (float) env.getMaxY());
}
@Override @Override
public void remove(Session session, Row row) { public void remove(Session session, Row row) {
SpatialKey key = getKey(row); SpatialKey key = getKey(row);
...@@ -213,14 +202,20 @@ public class MVSpatialIndex extends BaseIndex implements SpatialIndex, MVIndex { ...@@ -213,14 +202,20 @@ public class MVSpatialIndex extends BaseIndex implements SpatialIndex, MVIndex {
return find(session); return find(session);
} }
Iterator<SpatialKey> cursor = Iterator<SpatialKey> cursor =
spatialMap.findIntersectingKeys(getEnvelope(intersection)); spatialMap.findIntersectingKeys(getKey(intersection));
TransactionMap<SpatialKey, Value> map = getMap(session); TransactionMap<SpatialKey, Value> map = getMap(session);
Iterator<SpatialKey> it = map.wrapIterator(cursor, false); Iterator<SpatialKey> it = map.wrapIterator(cursor, false);
return new MVStoreCursor(session, it); return new MVStoreCursor(session, it);
} }
private SpatialKey getEnvelope(SearchRow row) { private SpatialKey getKey(SearchRow row) {
if (row == null) {
return null;
}
Value v = row.getValue(columnIds[0]); Value v = row.getValue(columnIds[0]);
if (v == ValueNull.INSTANCE) {
return null;
}
Geometry g = ((ValueGeometry) v.convertTo(Value.GEOMETRY)).getGeometryNoCopy(); Geometry g = ((ValueGeometry) v.convertTo(Value.GEOMETRY)).getGeometryNoCopy();
Envelope env = g.getEnvelopeInternal(); Envelope env = g.getEnvelopeInternal();
return new SpatialKey(row.getKey(), return new SpatialKey(row.getKey(),
...@@ -228,7 +223,6 @@ public class MVSpatialIndex extends BaseIndex implements SpatialIndex, MVIndex { ...@@ -228,7 +223,6 @@ public class MVSpatialIndex extends BaseIndex implements SpatialIndex, MVIndex {
(float) env.getMinY(), (float) env.getMaxY()); (float) env.getMinY(), (float) env.getMaxY());
} }
/** /**
* Get the row with the given index key. * Get the row with the given index key.
* *
......
...@@ -32,6 +32,13 @@ public class SpatialDataType implements DataType { ...@@ -32,6 +32,13 @@ public class SpatialDataType implements DataType {
@Override @Override
public int compare(Object a, Object b) { public int compare(Object a, Object b) {
if (a == b) {
return 0;
} else if (a == null) {
return -1;
} else if (b == null) {
return 1;
}
long la = ((SpatialKey) a).getId(); long la = ((SpatialKey) a).getId();
long lb = ((SpatialKey) b).getId(); long lb = ((SpatialKey) b).getId();
return la < lb ? -1 : la > lb ? 1 : 0; return la < lb ? -1 : la > lb ? 1 : 0;
...@@ -45,6 +52,11 @@ public class SpatialDataType implements DataType { ...@@ -45,6 +52,11 @@ public class SpatialDataType implements DataType {
* @return true if they are equal * @return true if they are equal
*/ */
public boolean equals(Object a, Object b) { public boolean equals(Object a, Object b) {
if (a == b) {
return true;
} else if (a == null || b == null) {
return false;
}
long la = ((SpatialKey) a).getId(); long la = ((SpatialKey) a).getId();
long lb = ((SpatialKey) b).getId(); long lb = ((SpatialKey) b).getId();
return la == lb; return la == lb;
......
...@@ -89,6 +89,7 @@ public class TestSpatial extends TestBase { ...@@ -89,6 +89,7 @@ public class TestSpatial extends TestBase {
testScanIndexOnNonSpatialQuery(); testScanIndexOnNonSpatialQuery();
testStoreCorruption(); testStoreCorruption();
testExplainSpatialIndexWithPk(); testExplainSpatialIndexWithPk();
testNullableGeometry();
} }
private void testHashCode() { private void testHashCode() {
...@@ -889,9 +890,9 @@ public class TestSpatial extends TestBase { ...@@ -889,9 +890,9 @@ public class TestSpatial extends TestBase {
try { try {
Statement stat = conn.createStatement(); Statement stat = conn.createStatement();
stat.execute("drop table if exists pt_cloud;"); stat.execute("drop table if exists pt_cloud;");
stat.execute("CREATE TABLE PT_CLOUD(id serial, the_geom geometry) AS" stat.execute("CREATE TABLE PT_CLOUD(id serial, the_geom geometry) AS" +
+ " SELECT null, CONCAT('POINT(',A.X,' ',B.X,')')::geometry the_geom " " SELECT null, CONCAT('POINT(',A.X,' ',B.X,')')::geometry the_geom " +
+ "from system_range(0,120) A,system_range(0,10) B;"); "from system_range(0,120) A,system_range(0,10) B;");
stat.execute("create spatial index on pt_cloud(the_geom);"); stat.execute("create spatial index on pt_cloud(the_geom);");
ResultSet rs = stat.executeQuery( ResultSet rs = stat.executeQuery(
"explain select * from PT_CLOUD " + "explain select * from PT_CLOUD " +
...@@ -909,5 +910,23 @@ public class TestSpatial extends TestBase { ...@@ -909,5 +910,23 @@ public class TestSpatial extends TestBase {
} }
deleteDb("spatial"); deleteDb("spatial");
} }
private void testNullableGeometry() throws SQLException {
deleteDb("spatial");
Connection conn = getConnection(url);
Statement stat = conn.createStatement();
stat.execute("create memory table test"
+ "(id int primary key, the_geom geometry)");
stat.execute("create spatial index on test(the_geom)");
stat.execute("insert into test values(1, null)");
ResultSet rs = stat.executeQuery("select * from test");
assertTrue(rs.next());
assertEquals(1, rs.getInt(1));
assertNull(rs.getObject(2));
stat.execute("drop table test");
conn.close();
deleteDb("spatial");
}
} }
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论