Release notes for re-motion version 1.13.77

List of Issues

Bugfixes

New Features

Details

[RM-3317] Subqueries are not detected if they are nested inside an expression that acts as the main source of a query

Component/s: Data.Linq
Issue Type: Bug
Resolution: Fixed
Status: Closed


from c in Cooks
select new { Result = (from k in Kitchens select k) }.Result.Count()

The inner query is not detected as a sub-query because the sub-query preparation takes place in MethodCallExpressionParser, and MethodCallExpressionParser is never called for the "new { Result = (from k in Kitchens select k) }.Result" expression.

[RM-3312] SQL Backend: The in-memory projection is incorrect if a NamedExpression contains another NamedExpression, entity expression, convert expression, etc.

Component/s: Data.Linq
Issue Type: Bug
Resolution: Fixed
Status: Closed


SqlGeneratingOuterSelectExpressionVisitor's methods must set the projection body after calling the base methods, otherwise, the base methods might cause reentrancy that overwrites the projection.

[RM-3269] SQL Backend: Invalid in-memory projection generated when a binary (or other) expression contains a conversion

Component/s: Data.Linq
Issue Type: Bug
Resolution: Fixed
Status: Closed


var q =
  from p in DB.Products
  select new { p.ProductName, Availability = (int) p.UnitsInStock - (int) p.UnitsOnOrder < 0 ? "Out Of Stock" : "In Stock" };

The problem is that the conversion of p.UnitsInStock to int will cause SqlGeneratingOuterSelectExpressionVisitor to emit a cast in the in-memory expression even though that is never represented as a column in the SQL. We probably just need to stop emitting projections at the first NamedExpression we find.

[RM-3266] SQL Backend: SubStatementReferenceResolver creates references of an invalid type when a ConvertedBoolExpression's inner expression is automatically resolved

Component/s: Data.Linq
Issue Type: Bug
Resolution: Fixed
Status: Closed


Questions:

  • Should there even be an automatic resolution of inner expressions in SubStatementReferenceResolver?
  • Why do we use the type of the outermost expression when creating the reference rather than the type of the expression we're currently creating a reference for?

[RM-3016] SQL Backend: Exception thrown when selecting from a sequence that returns boolean values

Component/s: Data.Linq
Issue Type: Bug
Resolution: Fixed
Status: Closed


from c in Cooks
group c.IsFullTimeCook by c.Name into fullTimeCooksByName
from isFullTime in fullTimeCooksByName
select new { fullTimeCooksByName.Key, Value = isFullTime }

[RM-3309] SQL Backend: Support for additional string manipulation routines: Trim, Insert

Component/s: Data.Linq
Issue Type: New Feature
Resolution: Fixed
Status: Closed


Support for queries that call the string.Trim or string.Insert.

[RM-3126] SQL Backend: Support fully qualified table names

Component/s: Data.Linq
Issue Type: New Feature
Resolution: Fixed
Status: Closed


Currently, resolved table infos can only hold a table without schema names. This feature adds support for two-part table names ("dbo.Table" instead of just "Table").

[RM-3079] SQL Backend: Support member access on subquery expressions

Component/s: Data.Linq
Issue Type: New Feature
Resolution: Fixed
Status: Closed


Support queries of the following form:

Cooks.Select (c => c.Assistants.First().Name)

For SQL generation, the member access is simply moved to the subquey.

[RM-3012] SQL Backend: When Single is used in a subquery that is moved to the SqlTables, TOP 1 should be used, not TOP 2

Component/s: Data.Linq
Issue Type: New Feature
Resolution: Fixed
Status: Closed


Normally, using Single should throw an exception when the respective query returns more than one element. This works fine in expressions such as:

from c in Cooks
where c.Assistants.Single() == c
select c

This leads to SQL containing something similar to the following:

SELECT [t0].*
FROM [CookTable] [t0]
WHERE (SELECT TOP 2 [t1].[ID] FROM [AssistantTable] [t1] WHERE [t1].[AssistedID] = [t0].[ID]) == [t0].[ID]

In that case, if the subquery returns more than one element, a SqlException is thrown.

In the following case, however, it does not work:

from c in Cooks
select c.Assistants.Single()

Because a subquery in a select clause might return an entity, we need to move it to the SQL's FROM clause:

SELECT [q1].*
FROM [CookTable] [t0] CROSS APPLY (SELECT TOP 2 [t1].[*] FROM [AssistantTable] [t1] WHERE [t1].[AssistedID] = [t0].[ID]) AS [q1]

In this case, the TOP 2 in conjunction with a non-single sequence will not trigger an exception but return too many result rows.

To mitigate, TOP 1 should be used instead in exactly this case.