Hello,

suppose I have a table with Geometries. This kind of datatype is handled by 
the ValueGeometry class, and an entry appears to be handled in a *Page, *that 
organizes its entries in an R-Tree, using the *SpatialKey *class as keys. 
Getting an entry can then be effectively performed by a simple 
contains-relation that is well-defined on the bounding box of 
each SpatialKey - unless the Geometry is null.

The *contains *Function in *SpatialDataType.java *always returns false when 
a key to be found is null. In that case, one can never access a row with a 
null-geometry, and I end up with an exception like this

Caused by: org.h2.jdbc.JdbcSQLException: Row not found when trying to 
delete from index "PUBLIC.GEOMETRIES: 105" [90112-192]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:345)
at org.h2.message.DbException.get(DbException.java:179)
at org.h2.message.DbException.get(DbException.java:155)
at org.h2.mvstore.db.MVSpatialIndex.remove(MVSpatialIndex.java:177)
at org.h2.mvstore.db.MVTable.removeRow(MVTable.java:677)
at org.h2.table.Table.updateRows(Table.java:489)
at org.h2.command.dml.Update.update(Update.java:145)
at org.h2.command.CommandContainer.update(CommandContainer.java:98)
at org.h2.command.Command.executeUpdate(Command.java:258)
... 10 more


This is caused by the following function in SpatialDataType.java:

public boolean contains(Object objA, Object objB) {
        SpatialKey a = (SpatialKey) objA;
        SpatialKey b = (SpatialKey) objB;
        if (a.isNull() || b.isNull()) {
            return false;
        }
        for (int i = 0; i < dimensions; i++) {
            if (a.min(i) > b.min(i) || a.max(i) < b.max(i)) {
                return false;
            }
        }
        return true;
    }


Now in order for the key to be found, a at least some contains-relation HAS 
to be present for empty SpatialKeys, for which we only have the ID.

What *seems *to work is a simple relation that works on the IDs abusing the 
<= relation:

public boolean contains(Object objA, Object objB) {
        SpatialKey a = (SpatialKey) objA;
        SpatialKey b = (SpatialKey) objB;
        if (a.isNull() || b.isNull()) {
            return a.getId() <= b.getId(); // <-----------
        }
        for (int i = 0; i < dimensions; i++) {
            if (a.min(i) > b.min(i) || a.max(i) < b.max(i)) {
                return false;
            }
        }
        return true;
    }


Even simpler seems to be to always return true:

  public boolean contains(Object objA, Object objB) {
        SpatialKey a = (SpatialKey) objA;
        SpatialKey b = (SpatialKey) objB;
        if (a.isNull() || b.isNull()) {
            return true; // <------------
        }
        for (int i = 0; i < dimensions; i++) {
            if (a.min(i) > b.min(i) || a.max(i) < b.max(i)) {
                return false;
            }
        }
        return true;
    }

However, I have no insight as to how the MVTree is then built up, and how 
that may affect performance. 

In any case, this change will *never work on existing databases, and any 
changes to this relation will render all empty Geometries unreachable.*


Does anyone have a deeper understanding of this kind of data retrieval, or 
do you have a remark on the fixes I suggest? I would greatly appreciate any 
remark...

Kind regards,

Sven

-- 
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 h2-database+unsubscr...@googlegroups.com.
To post to this group, send email to h2-database@googlegroups.com.
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