提交 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;
import org.h2.table.TableFilter;
import org.h2.value.Value;
import org.h2.value.ValueGeometry;
import org.h2.value.ValueNull;
import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.Geometry;
......@@ -125,11 +126,17 @@ public class SpatialTreeIndex extends BaseIndex implements SpatialIndex {
if (closed) {
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]);
if (v == ValueNull.INSTANCE) {
return null;
}
Geometry g = ((ValueGeometry) v.convertTo(Value.GEOMETRY)).getGeometryNoCopy();
Envelope env = g.getEnvelopeInternal();
return new SpatialKey(row.getKey(),
......@@ -142,7 +149,7 @@ public class SpatialTreeIndex extends BaseIndex implements SpatialIndex {
if (closed) {
throw DbException.throwInternalError();
}
if (!treeMap.remove(getEnvelope(row), row.getKey())) {
if (!treeMap.remove(getKey(row), row.getKey())) {
throw DbException.throwInternalError("row not found");
}
}
......@@ -167,7 +174,7 @@ public class SpatialTreeIndex extends BaseIndex implements SpatialIndex {
return find(filter.getSession());
}
return new SpatialCursor(
treeMap.findIntersectingKeys(getEnvelope(intersection)), table,
treeMap.findIntersectingKeys(getKey(intersection)), table,
filter.getSession());
}
......
......@@ -32,6 +32,7 @@ import org.h2.table.TableFilter;
import org.h2.value.Value;
import org.h2.value.ValueGeometry;
import org.h2.value.ValueLong;
import org.h2.value.ValueNull;
import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.Geometry;
......@@ -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
public void remove(Session session, Row row) {
SpatialKey key = getKey(row);
......@@ -213,14 +202,20 @@ public class MVSpatialIndex extends BaseIndex implements SpatialIndex, MVIndex {
return find(session);
}
Iterator<SpatialKey> cursor =
spatialMap.findIntersectingKeys(getEnvelope(intersection));
spatialMap.findIntersectingKeys(getKey(intersection));
TransactionMap<SpatialKey, Value> map = getMap(session);
Iterator<SpatialKey> it = map.wrapIterator(cursor, false);
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]);
if (v == ValueNull.INSTANCE) {
return null;
}
Geometry g = ((ValueGeometry) v.convertTo(Value.GEOMETRY)).getGeometryNoCopy();
Envelope env = g.getEnvelopeInternal();
return new SpatialKey(row.getKey(),
......@@ -228,7 +223,6 @@ public class MVSpatialIndex extends BaseIndex implements SpatialIndex, MVIndex {
(float) env.getMinY(), (float) env.getMaxY());
}
/**
* Get the row with the given index key.
*
......
......@@ -32,6 +32,13 @@ public class SpatialDataType implements DataType {
@Override
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 lb = ((SpatialKey) b).getId();
return la < lb ? -1 : la > lb ? 1 : 0;
......@@ -45,6 +52,11 @@ public class SpatialDataType implements DataType {
* @return true if they are equal
*/
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 lb = ((SpatialKey) b).getId();
return la == lb;
......
......@@ -89,6 +89,7 @@ public class TestSpatial extends TestBase {
testScanIndexOnNonSpatialQuery();
testStoreCorruption();
testExplainSpatialIndexWithPk();
testNullableGeometry();
}
private void testHashCode() {
......@@ -889,9 +890,9 @@ public class TestSpatial extends TestBase {
try {
Statement stat = conn.createStatement();
stat.execute("drop table if exists pt_cloud;");
stat.execute("CREATE TABLE PT_CLOUD(id serial, the_geom geometry) AS"
+ " SELECT null, CONCAT('POINT(',A.X,' ',B.X,')')::geometry the_geom "
+ "from system_range(0,120) A,system_range(0,10) B;");
stat.execute("CREATE TABLE PT_CLOUD(id serial, the_geom geometry) AS" +
" SELECT null, CONCAT('POINT(',A.X,' ',B.X,')')::geometry the_geom " +
"from system_range(0,120) A,system_range(0,10) B;");
stat.execute("create spatial index on pt_cloud(the_geom);");
ResultSet rs = stat.executeQuery(
"explain select * from PT_CLOUD " +
......@@ -910,4 +911,22 @@ public class TestSpatial extends TestBase {
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 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论