Skip to content

Commit 0530838

Browse files
NH-3488 - Protect against invalid use cases.
1 parent c32732e commit 0530838

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
@@ -377,6 +377,7 @@ public override void VisitSelectClause(SelectClause selectClause, QueryModel que
377377
switch (_queryMode)
378378
{
379379
case QueryMode.Delete:
380+
VisitDeleteClause(selectClause.Selector);
380381
return;
381382
case QueryMode.Update:
382383
case QueryMode.UpdateVersioned:
@@ -447,6 +448,18 @@ private void VisitUpdateClause(Expression expression)
447448
}
448449
}
449450

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

0 commit comments

Comments
 (0)