Skip to content

Commit 6aa9c18

Browse files
NH-3488 - Protect against invalid use cases.
1 parent 1519a1d commit 6aa9c18

File tree

3 files changed

+41
-0
lines changed

3 files changed

+41
-0
lines changed

src/NHibernate.Test/LinqBulkManipulation/Fixture.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -877,6 +877,19 @@ public void UpdateSetNullOnJoinedSubclass()
877877
}
878878
}
879879

880+
[Test]
881+
public void UpdateOnOtherClassThrows()
882+
{
883+
using (var s = OpenSession())
884+
using (s.BeginTransaction())
885+
{
886+
var query = s
887+
.Query<Animal>().Where(x => x.Mother == _butterfly)
888+
.Update();
889+
Assert.That(() => query.As(a => new Human { Description = a.Description + " humanized" }), Throws.TypeOf<TypeMismatchException>());
890+
}
891+
}
892+
880893
#endregion
881894

882895
#region DELETES
@@ -1102,6 +1115,19 @@ public void DeleteSyntaxWithCompositeId()
11021115
}
11031116
}
11041117

1118+
[Test]
1119+
public void DeleteOnProjectionThrows()
1120+
{
1121+
using (var s = OpenSession())
1122+
using (s.BeginTransaction())
1123+
{
1124+
var query = s
1125+
.Query<Animal>().Where(x => x.Mother == _butterfly)
1126+
.Select(x => new Car { Id = x.Id });
1127+
Assert.That(() => query.Delete(), Throws.InvalidOperationException);
1128+
}
1129+
}
1130+
11051131
#endregion
11061132
}
11071133
}

src/NHibernate/Linq/DmlExpressionRewriter.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ public static Expression PrepareExpression<TSource>(Expression sourceExpression,
107107

108108
static Dictionary<string, Expression> ExtractAssignments<TSource, TTarget>(Expression<Func<TSource, TTarget>> expression, MemberInitExpression memberInitExpression)
109109
{
110+
if (memberInitExpression.Type != typeof(TTarget))
111+
throw new TypeMismatchException($"Expecting an expression of exact type {typeof(TTarget).AssemblyQualifiedName} but got {memberInitExpression.Type.AssemblyQualifiedName}");
110112
var instance = new DmlExpressionRewriter(expression.Parameters);
111113
instance.AddSettersFromBindings(memberInitExpression.Bindings, "");
112114
return instance._assignments;

src/NHibernate/Linq/Visitors/QueryModelVisitor.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,7 @@ public override void VisitSelectClause(SelectClause selectClause, QueryModel que
378378
switch (_queryMode)
379379
{
380380
case QueryMode.Delete:
381+
VisitDeleteClause(selectClause.Selector);
381382
return;
382383
case QueryMode.Update:
383384
case QueryMode.UpdateVersioned:
@@ -448,6 +449,18 @@ private void VisitUpdateClause(Expression expression)
448449
}
449450
}
450451

452+
private void VisitDeleteClause(Expression expression)
453+
{
454+
// We only need to check there is no unexpected select, for avoiding silently ignoring them.
455+
var visitor = new SelectClauseVisitor(typeof(object[]), VisitorParameters);
456+
visitor.VisitSelector(expression);
457+
458+
if (visitor.ProjectionExpression != null)
459+
{
460+
throw new InvalidOperationException("Delete is not allowed on projections.");
461+
}
462+
}
463+
451464
public override void VisitWhereClause(WhereClause whereClause, QueryModel queryModel, int index)
452465
{
453466
var visitor = new SimplifyConditionalVisitor();

0 commit comments

Comments
 (0)