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 [email protected].
To post to this group, send email to [email protected].
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