Skip to content

Commit a1a0da2

Browse files
committed
Improve select clause transformation for Linq provider
1 parent e444607 commit a1a0da2

File tree

13 files changed

+1637
-145
lines changed

13 files changed

+1637
-145
lines changed

src/NHibernate.DomainModel/Northwind/Entities/Animal.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ public class Animal
1212
public virtual Animal Father { get; set; }
1313
public virtual IList<Animal> Children { get; set; }
1414
public virtual string SerialNumber { get; set; }
15-
}
15+
public virtual string FatherSerialNumber => Father?.SerialNumber;
16+
public virtual bool HasFather => Father != null;
17+
}
1618

1719
public abstract class Reptile : Animal
1820
{
@@ -30,4 +32,4 @@ public abstract class Mammal : Animal
3032
public class Dog : Mammal { }
3133

3234
public class Cat : Mammal { }
33-
}
35+
}

src/NHibernate.DomainModel/Northwind/Entities/UserComponent.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,17 @@ public class UserComponent
55
public string Property1 { get; set; }
66
public string Property2 { get; set; }
77
public UserComponent2 OtherComponent { get; set; }
8+
9+
public string Property3 => $"{Property1}{Property2}";
10+
811
}
912

1013
public class UserComponent2
1114
{
1215
public string OtherProperty1 { get; set; }
16+
17+
public string OtherProperty2 { get; set; }
18+
19+
public string OtherProperty3 => OtherProperty1;
1320
}
14-
}
21+
}

src/NHibernate.DomainModel/Northwind/Mappings/User.hbm.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030

3131
<component name="OtherComponent" class="UserComponent2">
3232
<property name="OtherProperty1" type="AnsiString" />
33+
<property name="OtherProperty2" type="AnsiString" formula="OtherProperty1"/>
3334
</component>
3435
</component>
3536
</class>

src/NHibernate.Test/Async/Linq/SelectionTests.cs

Lines changed: 457 additions & 17 deletions
Large diffs are not rendered by default.

src/NHibernate.Test/Linq/SelectionTests.cs

Lines changed: 486 additions & 17 deletions
Large diffs are not rendered by default.

src/NHibernate/Hql/Ast/HqlTreeNode.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,30 @@ internal HqlIdent(IASTFactory factory, System.Type type)
257257
throw new NotSupportedException(string.Format("Don't currently support idents of type {0}", type.Name));
258258
}
259259
}
260+
261+
internal static bool SupportsType(System.Type type)
262+
{
263+
type = type.UnwrapIfNullable();
264+
switch (System.Type.GetTypeCode(type))
265+
{
266+
case TypeCode.Boolean:
267+
case TypeCode.Int16:
268+
case TypeCode.Int32:
269+
case TypeCode.Int64:
270+
case TypeCode.Decimal:
271+
case TypeCode.Single:
272+
case TypeCode.DateTime:
273+
case TypeCode.String:
274+
case TypeCode.Double:
275+
return true;
276+
default:
277+
return new[]
278+
{
279+
typeof(Guid),
280+
typeof(DateTimeOffset)
281+
}.Contains(type);
282+
}
283+
}
260284
}
261285

262286
public class HqlRange : HqlStatement

src/NHibernate/Linq/Functions/StringGenerator.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Linq;
55
using System.Linq.Expressions;
66
using System.Reflection;
7+
using NHibernate.Engine;
78
using NHibernate.Hql.Ast;
89
using NHibernate.Linq.Visitors;
910
using NHibernate.Util;
@@ -70,6 +71,23 @@ public LengthGenerator()
7071

7172
public override HqlTreeNode BuildHql(MemberInfo member, Expression expression, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
7273
{
74+
if (visitor.SessionFactory is ISessionFactoryImplementor sessionFactory)
75+
{
76+
var sqlFunction = sessionFactory.SQLFunctionRegistry.FindSQLFunction("length");
77+
if (sqlFunction == null)
78+
{
79+
throw new InvalidOperationException("Sql function length is not supported for the current dialect.");
80+
}
81+
82+
var returnType = sqlFunction.ReturnType(NHibernateUtil.Int32, sessionFactory);
83+
if (!NHibernateUtil.Int32.Equals(returnType))
84+
{
85+
return treeBuilder.Cast(
86+
treeBuilder.MethodCall("length", visitor.Visit(expression).AsExpression()),
87+
typeof(int));
88+
}
89+
}
90+
7391
return treeBuilder.MethodCall("length", visitor.Visit(expression).AsExpression());
7492
}
7593
}

src/NHibernate/Linq/NestedSelects/NestedSelectRewriter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ private static Expression GetIdentifier(ISessionFactory sessionFactory, Expressi
217217

218218
var classMetadata = sessionFactory.GetClassMetadata(expression.Type);
219219
if (classMetadata == null)
220-
return Expression.Constant(null);
220+
return null;
221221

222222
var propertyName=classMetadata.IdentifierPropertyName;
223223
NHibernate.Type.EmbeddedComponentType componentType;

src/NHibernate/Linq/NestedSelects/SelectClauseRewriter.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,11 @@ public SelectClauseRewriter(Expression parameter, ICollection<ExpressionHolder>
2323
this.expressions = expressions;
2424
this.parameter = parameter;
2525
this.tuple = tuple;
26-
this.expressions.Add(new ExpressionHolder { Expression = expression, Tuple = tuple }); //ID placeholder
26+
if (expression != null)
27+
{
28+
this.expressions.Add(new ExpressionHolder { Expression = expression, Tuple = tuple }); //ID placeholder
29+
}
30+
2731
_dictionary = dictionary;
2832
}
2933

@@ -59,4 +63,4 @@ private Expression AddAndConvertExpression(Expression expression)
5963
expression.Type);
6064
}
6165
}
62-
}
66+
}

0 commit comments

Comments
 (0)