fsprojects / SQLProvider

A general F# SQL database erasing type provider, supporting LINQ queries, schema exploration, individuals, CRUD operations and much more besides.
https://fsprojects.github.io/SQLProvider
Other
564 stars 144 forks source link

Unexpected composed query behavior #732

Open halcwb opened 3 years ago

halcwb commented 3 years ago

Describe the bug When using composed queries an unexpected behavior occurs when a join is involved in a query. This results in a select with wrong values. See code examples below.

To Reproduce

let ctx = DataContext.getDataContextWithLog()

// === normal query with expected result
query { 
    for p in ctx.Dbo.Parameters do
    join c in ctx.Dbo.ParametersCategories on 
            (p.CategoryId = c.CategoryId)
    select p
} 
|> Seq.toList
|> List.take 3        
|> List.map (fun p -> p.ParameterId, p.ParameterName)
// Result:
// val it : (int16 * string) list =
//   [(3743s, "Allerg (T1) IgE-totaal"); (3744s, "Allerg (T1) Tryptase");
//    (3745s, "Allerg (T1) Huisstofmijt")]

// === composed query with unexpected result
let get (ctx : DataContext.sql.dataContext) =
    <@ fun _ ->
        query { 
            for p in ctx.Dbo.Parameters do
            join c in ctx.Dbo.ParametersCategories on 
                    (p.CategoryId = c.CategoryId)
            select (p)
        } @>

query {
for (p) in ((%get ctx) ()) do
    select (p.ParameterId, p.ParameterName)
}
|> Seq.toList
|> List.take 3        
// Result:
// val get :
//   ctx:FSharp.Data.Sql.SqlDataProvider<...>.dataContext ->
//     Quotations.Expr<('a ->
//                        Linq.IQueryable<FSharp.Data.Sql.SqlDataProvider<...>.dataContext.dbo.ParametersEntity>)>
// val it : (int16 * string) list = [(0s, ""); (0s, ""); (0s, "")]

// == composed query without join with expected result
let get (ctx : DataContext.sql.dataContext) =
    <@ fun _ ->
        query { 
            for p in ctx.Dbo.Parameters do
            // join c in ctx.Dbo.ParametersCategories on 
            //         (p.CategoryId = c.CategoryId)
            select (p)
        } @>

query {
for (p) in ((%get ctx) ()) do
    select (p.ParameterId, p.ParameterName)
}
|> Seq.toList
|> List.take 3        
// Result:
// val get :
//   ctx:FSharp.Data.Sql.SqlDataProvider<...>.dataContext ->
//     Quotations.Expr<('a ->
//                        Linq.IQueryable<FSharp.Data.Sql.SqlDataProvider<...>.dataContext.dbo.ParametersEntity>)>
// val it : (int16 * string) list =
//   [(3743s, "Allerg (T1) IgE-totaal"); (3744s, "Allerg (T1) Tryptase");
//    (3745s, "Allerg (T1) Huisstofmijt")]

// == composed query with a tuple return with a 'dummy' unit value returns expected result!?
let get (ctx : DataContext.sql.dataContext) =
    <@ fun _ ->
        query { 
            for p in ctx.Dbo.Parameters do
            join c in ctx.Dbo.ParametersCategories on 
                    (p.CategoryId = c.CategoryId)
            select (p, ())
        } @>

query {
for (p, _) in ((%get ctx) ()) do
    select (p.ParameterId, p.ParameterName)
}
|> Seq.toList
|> List.take 3        
// Result:
// val it : (int16 * string) list =
//   [(3743s, "Allerg (T1) IgE-totaal"); (3744s, "Allerg (T1) Tryptase");
//    (3745s, "Allerg (T1) Huisstofmijt")]

Expected behavior Clearly the second query result is inconsistent with the other queries.

Desktop (please complete the following information): .NET SDK (reflecting any global.json): Version: 5.0.202 Commit: db7cc87d51

Runtime Environment: OS Name: Windows OS Version: 10.0.17763 OS Platform: Windows RID: win10-x64 Base Path: C:\Program Files\dotnet\sdk\5.0.202\

Host (useful for support): Version: 5.0.5 Commit: 2f740adc14

.NET SDKs installed: 5.0.200-preview.21077.7 [C:\Program Files\dotnet\sdk] 5.0.201 [C:\Program Files\dotnet\sdk] 5.0.202 [C:\Program Files\dotnet\sdk]

Thorium commented 3 years ago

Just a quick look into this one, it seems that something in this.ReadEntities goes wrong:

halcwb commented 3 years ago

@Thorium So, is this something you can reproduce? Or do you need the generated SQL output?