google-code-export / dataobjectsdotnet

Automatically exported from code.google.com/p/dataobjectsdotnet
0 stars 0 forks source link

LINQ translation bug with nullable comparison #699

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
Version: 4.2.0

Model:

[HierarchyRoot]
class AnEntity: Entity
{
    [Field, Key]
    public long Id { get; private set; }

    [Field]
    public string StringField { get; set; }

    [Field]
    public char? NullableChar { get; set; }
}

Test:

[Test]
public void TestStringComparison()
{
    using(Session.Open(TheDomain))
    using(var tx = Transaction.Open())
    {
        var entity = new AnEntity();
        var list = (from e in Query.All<AnEntity>()
                where e == entity && e.StringField == e.StringField
                select e).ToList();
        Assert.AreEqual(1, list.Count);
    }
}

[Test]
public void TestCharComparison()
{
    using(Session.Open(TheDomain))
    using(var tx = Transaction.Open())
    {
        var entity = new AnEntity();
        var list = (from e in Query.All<AnEntity>()
                        where e == entity && e.NullableChar == e.NullableChar
                        select e).ToList();
        Assert.AreEqual(1, list.Count);
    }
}

SQL:

SELECT "a"."Id", 101 AS "TypeId", "a"."StringField", "a"."NullableChar" FROM 
"public"."AnEntity" "a" WHERE (("a"."Id" = ((2)::int8)) AND ("a"."StringField" 
= "a"."StringField"));

SELECT "a"."Id", 101 AS "TypeId", "a"."StringField", "a"."NullableChar" FROM 
"public"."AnEntity" "a" WHERE (("a"."Id" = ((1)::int8)) AND ("a"."NullableChar" 
= "a"."NullableChar"));

Here 2 NULLs are compared, which results in NULL and finally false in the WHERE 
clause. However in C# null==null is true, and this is the behaviour that is 
expected.

Original issue reported on code.google.com by havasvol...@gmail.com on 13 Jun 2010 at 1:36

GoogleCodeExporter commented 9 years ago
In PostgreSQL 8.0 there is a 

expression1 IS DISTINCT FROM expression2

construct.

As of 8.2 there is also 

expression1 IS NOT DISTINCT FROM expression2

Quote (from 
http://www.postgresql.org/docs/8.2/static/functions-comparison.html):

"
For non-null inputs, IS DISTINCT FROM is the same as the <> operator. However, 
when both inputs are null it will return false, and when just one input is null 
it will return true. Similarly, IS NOT DISTINCT FROM is identical to = for 
non-null inputs, but it returns true when both inputs are null, and false when 
only one input is null. Thus, these constructs effectively act as though null 
were a normal data value, rather than "unknown".
"

SqlDom could be extended with these operators, and every provider would 
translate to SQL as it can.

Original comment by havasvol...@gmail.com on 14 Jun 2010 at 11:26

GoogleCodeExporter commented 9 years ago
This is also true for entity reference fields:

[Test]
public void TestRefToRefComparison()
{
    using(Session.Open(TheDomain))
    using(var tx = Transaction.Open())
    {
        var entity = new AnEntity();
        Assert.IsNull(entity.ReferenceField);
        var list = (from e in Query.All<AnEntity>()
            where e == entity && e.ReferenceField == e.ReferenceField
            select e).ToList();
        Assert.AreEqual(1, list.Count);
    }
}

Original comment by havasvol...@gmail.com on 15 Jun 2010 at 10:19

GoogleCodeExporter commented 9 years ago

Original comment by havasvol...@gmail.com on 7 Jul 2010 at 11:02

GoogleCodeExporter commented 9 years ago

Original comment by alex.yakunin on 12 Jul 2010 at 7:35