Skip to content

Wrong join/leftjoin sql translation (key expression is variable, join same table) #323

@letarak

Description

@letarak

Hello
DO 7.0.3

If join/left use same table and key expression is variable then sql query translation result is wrong

Example:

using System.Data.SqlClient;
using DoTest;
using NUnit.Framework;
using Xtensive.Orm;
using Xtensive.Orm.Configuration;

internal class Program
{
    private static async Task Main(string[] args)
    {
        try
        {
            DbHelper.ExecuteNonQuery("DROP DATABASE [DO-Tests]");
        }
        catch (Exception)
        {
        }

        DbHelper.ExecuteNonQuery("CREATE DATABASE [DO-Tests]");

        var currentConnection = new SqlConnectionStringBuilder(DbHelper.ConnectionString());

        var dc = new DomainConfiguration("sqlserver", currentConnection.ToString());

        dc.Types.Register(typeof(TestEntity));

        dc.UpgradeMode = DomainUpgradeMode.Recreate;

        await using var d = await Domain.BuildAsync(dc);

        await using (var s = await d.OpenSessionAsync())
        await using (var t = await s.OpenTransactionAsync())
        {
            _ = new TestEntity(s) { Name = "1", Description = "test", Text = "text" };
            _ = new TestEntity(s) { Name = "1", Description = "test", Text = "text" };

            t.Complete();
        }

        System.Linq.Expressions.Expression<Func<TestEntity, bool>> filter = it => it.Description == null;

        System.Linq.Expressions.Expression<Func<TestEntity, int>> key = it => it.Id;

        await using (var s = await d.OpenSessionAsync())
        using (s.Activate())
        await using (await s.OpenTransactionAsync())
        {
            /*SELECT DISTINCT
    [a].[Id]
FROM [dbo].[TestEntity] [a]
    LEFT OUTER JOIN
    (
        SELECT [b].[Id] AS [#a.Id],
               282 AS [#a.TypeId],
               [b].[Description] AS [#a.Description],
               [b].[Text] AS [#a.Text]
        FROM [dbo].[TestEntity] [b]
        WHERE ([b].[Description] IS NULL)
    ) [c]
        ON ([a].[Id] = [c].[#a.Id])
WHERE ([a].[Text] IS NOT NULL);*/
            var leftJoinWithExpression = Query.All<TestEntity>().LeftJoin(
                    Query.All<TestEntity>().Where(filter),
                    o => o.Id,
                    i => i.Id,
                    (o, i) => o)
                .Where(it => it.Text != null)
                .Select(it => it.Id)
                .Distinct()
                .ToList();

            Assert.AreEqual(2, leftJoinWithExpression.Count);


/*SELECT DISTINCT
    [a].[Id]
FROM [dbo].[TestEntity] [a]
    LEFT OUTER JOIN
    (
        SELECT [b].[Id] AS [#a.Id],
               282 AS [#a.TypeId],
               [b].[Description] AS [#a.Description],
               [b].[Text] AS [#a.Text]
        FROM [dbo].[TestEntity] [b]
        WHERE ([b].[Description] IS NULL)
    ) [c]
        ON ([a].[Id] = [c].[#a.Id])
WHERE (
          ([a].[Description] IS NULL)
          AND ([a].[Text] IS NOT NULL)
      );*/
            var leftJoinWithExpressionVariable = Query.All<TestEntity>().LeftJoin(
                    Query.All<TestEntity>().Where(filter),
                    key,
                    key,
                    (o, i) => o)
                .Where(it => it.Text != null)
                .Select(it => it.Id)
                .Distinct()
                .ToList();

            Assert.AreEqual(2, leftJoinWithExpressionVariable.Count);

/*SELECT DISTINCT
    [a].[Id]
FROM [dbo].[TestEntity] [a]
    INNER JOIN [dbo].[TestEntity] [b]
        ON ([a].[Id] = [b].[Id])
WHERE (
          ([b].[Description] IS NULL)
          AND ([a].[Text] IS NOT NULL)
      );*/
            var joinWithExpression = Query.All<TestEntity>().Join(
                    Query.All<TestEntity>().Where(filter),
                    o => o.Id,
                    i => i.Id,
                    (o, i) => o)
                .Where(it => it.Text != null)
                .Select(it => it.Id)
                .Distinct()
                .ToList();

            Assert.AreEqual(2, joinWithExpression.Count);

/*SELECT DISTINCT
    [a].[Id]
FROM [dbo].[TestEntity] [a]
    INNER JOIN [dbo].[TestEntity] [b]
        ON ([a].[Id] = [b].[Id])
WHERE (
          ([a].[Description] IS NULL)
          AND ([b].[Description] IS NULL)
          AND ([a].[Text] IS NOT NULL)
      );*/
            var joinWithExpressionVariable = Query.All<TestEntity>().Join(
                    Query.All<TestEntity>().Where(filter),
                    key,
                    key,
                    (o, i) => o)
                .Where(it => it.Text != null)
                .Select(it => it.Id)
                .Distinct()
                .ToList();

            Assert.AreEqual(2, joinWithExpressionVariable.Count);
        }
    }

    [HierarchyRoot]
    public class TestEntity : Entity
    {
        public TestEntity(Session session) : base(session)
        {
        }

        [Key] [Field(Nullable = false)] public int Id { get; set; }

        [Field(Nullable = false)] public string Name { get; set; }

        [Field] public string? Description { get; set; }

        [Field] public string? Text { get; set; }
    }
}

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions