orientdb: Incorrect MATCH result with if/eval on a datetime value

OrientDB Version: 2.2.14 and 2.2.15

Java Version: Java 8

OS: OSX and Ubuntu Linux

Expected behavior

In the repro section, all MATCH queries are equivalent and should produce identical results – returning one row with all of the created vertices in it.

Actual behavior

Except for the first query (without any if/eval), all subsequent queries incorrectly return no results.

Steps to reproduce

Database setup:

CREATE CLASS Foo EXTENDS V
CREATE CLASS Event EXTENDS V
CREATE PROPERTY Event.name String
CREATE PROPERTY Event.event_date Datetime

CREATE CLASS Foo_Start EXTENDS E
CREATE CLASS Foo_End EXTENDS E
CREATE CLASS Foo_Center EXTENDS E

CREATE VERTEX Foo

CREATE VERTEX Event SET name = 'start', event_date = '1990-01-01 00:00:00'
CREATE VERTEX Event SET name = 'end', event_date = '2017-01-01 00:00:00'
CREATE VERTEX Event SET name = 'center', event_date = '2000-01-01 00:00:00'

CREATE EDGE Foo_Start FROM (SELECT * FROM Foo) TO (SELECT * FROM Event WHERE name = 'start')
CREATE EDGE Foo_End FROM (SELECT * FROM Foo) TO (SELECT * FROM Event WHERE name = 'end')
CREATE EDGE Foo_Center FROM (SELECT * FROM Foo) TO (SELECT * FROM Event WHERE name = 'center')

All of the following queries attempt to ensure that the center Event has an event_date between the start and end.

The following query returns one result, as expected:

MATCH {
    class: Foo,
    as: foo
}.out('Foo_Start') {
    as: start
}, {
    class: Foo,
    as: foo
}.out('Foo_End') {
    as: end
}, {
    class: Foo,
    as: foo
}.out('Foo_Center') {
    where: (($matched.start.event_date <= event_date) AND (event_date <= $matched.end.event_date)),
    as: center
}
RETURN $matches

Let’s allow the Foo_End edge to be optional. That means that before using the as: end matched value, we must check it against null. However, the following query returns no results:

MATCH {
    class: Foo,
    as: foo
}.out('Foo_Start') {
    as: start
}, {
    class: Foo,
    as: foo
}.out('Foo_End') {
    optional: true,
    as: end
}, {
    class: Foo,
    as: foo
}.out('Foo_Center') {
    where: (
        (event_date >= $matched.start.event_date) AND 
        (
            if(eval("($matched.end IS NOT null)"), 
               if(eval("(event_date <= $matched.end.event_date)"), 
                  true, 
                  false
               ), 
               true
            ) = true
        )
    ),
    as: center
}
RETURN $matches

The following equivalent query with only a single if/eval also returns no results:

MATCH {
    class: Foo,
    as: foo
}.out('Foo_Start') {
    as: start
}, {
    class: Foo,
    as: foo
}.out('Foo_End') {
    optional: true,
    as: end
}, {
    class: Foo,
    as: foo
}.out('Foo_Center') {
    where: (
        (event_date >= $matched.start.event_date) AND 
        (
            if(eval("(($matched.end IS null) OR (event_date <= $matched.end.event_date))"), 
               true,
               false
            ) = true
        )
    ),
    as: center
}
RETURN $matches

Even getting rid of the optionality of the Foo_End edge doesn’t fix the problem – this variant also returns no results:

MATCH {
    class: Foo,
    as: foo
}.out('Foo_Start') {
    as: start
}, {
    class: Foo,
    as: foo
}.out('Foo_End') {
    as: end
}, {
    class: Foo,
    as: foo
}.out('Foo_Center') {
    where: (
        (event_date >= $matched.start.event_date) AND 
        (
            if(eval("(($matched.end IS null) OR (event_date <= $matched.end.event_date))"), 
               true,
               false
            ) = true
        )
    ),
    as: center
}
RETURN $matches

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 22 (22 by maintainers)

Commits related to this issue

Most upvoted comments

Hi @obi1kenobi

Yes, the eval() function still has this problem, but please consider that eval() is no longer needed in v 3.0, as you can write complex math expressions in plain SQL

Thanks

Luigi