Skip to content

Commit eb137cc

Browse files
authored
Fix invalid alias inside Dml subquery (#2595)
Fixes #2594
1 parent 18667cf commit eb137cc

File tree

9 files changed

+374
-97
lines changed

9 files changed

+374
-97
lines changed

src/NHibernate.Test/Async/Hql/Ast/BulkManipulation.cs

Lines changed: 87 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,8 @@ public async Task InsertAcrossMappedJoinFailsAsync()
223223
await (data.CleanupAsync());
224224
}
225225

226-
public async Task InsertWithGeneratedIdAsync(CancellationToken cancellationToken = default(CancellationToken))
226+
[Test]
227+
public async Task InsertWithGeneratedIdAsync()
227228
{
228229
// Make sure the env supports bulk inserts with generated ids...
229230
IEntityPersister persister = Sfi.GetEntityPersister(typeof (PettingZoo).FullName);
@@ -238,30 +239,30 @@ public async Task InsertAcrossMappedJoinFailsAsync()
238239

239240
ISession s = OpenSession();
240241
ITransaction t = s.BeginTransaction();
241-
await (s.SaveAsync(zoo, cancellationToken));
242-
await (t.CommitAsync(cancellationToken));
242+
await (s.SaveAsync(zoo));
243+
await (t.CommitAsync());
243244
s.Close();
244245

245246
s = OpenSession();
246247
t = s.BeginTransaction();
247-
int count = await (s.CreateQuery("insert into PettingZoo (name) select name from Zoo").ExecuteUpdateAsync(cancellationToken));
248-
await (t.CommitAsync(cancellationToken));
248+
int count = await (s.CreateQuery("insert into PettingZoo (name) select name from Zoo").ExecuteUpdateAsync());
249+
await (t.CommitAsync());
249250
s.Close();
250251
Assert.That(count, Is.EqualTo(1), "unexpected insertion count");
251252

252253
s = OpenSession();
253254
t = s.BeginTransaction();
254-
var pz = (PettingZoo) await (s.CreateQuery("from PettingZoo").UniqueResultAsync(cancellationToken));
255-
await (t.CommitAsync(cancellationToken));
255+
var pz = (PettingZoo) await (s.CreateQuery("from PettingZoo").UniqueResultAsync());
256+
await (t.CommitAsync());
256257
s.Close();
257258

258259
Assert.That(zoo.Name, Is.EqualTo(pz.Name));
259260
Assert.That(zoo.Id != pz.Id);
260261

261262
s = OpenSession();
262263
t = s.BeginTransaction();
263-
await (s.CreateQuery("delete Zoo").ExecuteUpdateAsync(cancellationToken));
264-
await (t.CommitAsync(cancellationToken));
264+
await (s.CreateQuery("delete Zoo").ExecuteUpdateAsync());
265+
await (t.CommitAsync());
265266
s.Close();
266267
}
267268

@@ -826,6 +827,31 @@ public async Task UpdateSetNullOnJoinedSubclassAsync()
826827
await (data.CleanupAsync());
827828
}
828829

830+
[Test]
831+
public async Task UpdateMultitableWithWhereExistsSubqueryAsync()
832+
{
833+
if (!Dialect.SupportsTemporaryTables)
834+
Assert.Ignore("Cannot perform multi-table updates using dialect not supporting temp tables.");
835+
836+
if(!Dialect.SupportsScalarSubSelects)
837+
Assert.Ignore("Dialect does not support scalar sub-select");
838+
839+
using (var s = OpenSession())
840+
using (var t = s.BeginTransaction())
841+
{
842+
String updateQryString = "update Human h " +
843+
"set h.description = 'updated' " +
844+
"where exists (" +
845+
" select f.id " +
846+
" from h.friends f " +
847+
" where f.name.last = 'Public' " +
848+
")";
849+
await (s.CreateQuery(updateQryString).ExecuteUpdateAsync());
850+
851+
await (t.CommitAsync());
852+
}
853+
}
854+
829855
#endregion
830856

831857
#region DELETES
@@ -834,25 +860,7 @@ public async Task UpdateSetNullOnJoinedSubclassAsync()
834860
public async Task DeleteWithSubqueryAsync()
835861
{
836862
// setup the test data...
837-
using (var s = OpenSession())
838-
using (var t = s.BeginTransaction())
839-
{
840-
var owner = new SimpleEntityWithAssociation { Name = "myEntity-1" };
841-
owner.AddAssociation("assoc-1");
842-
owner.AddAssociation("assoc-2");
843-
owner.AddAssociation("assoc-3");
844-
await (s.SaveAsync(owner));
845-
var owner2 = new SimpleEntityWithAssociation { Name = "myEntity-2" };
846-
owner2.AddAssociation("assoc-1");
847-
owner2.AddAssociation("assoc-2");
848-
owner2.AddAssociation("assoc-3");
849-
owner2.AddAssociation("assoc-4");
850-
await (s.SaveAsync(owner2));
851-
var owner3 = new SimpleEntityWithAssociation { Name = "myEntity-3" };
852-
await (s.SaveAsync(owner3));
853-
await (t.CommitAsync());
854-
s.Close();
855-
}
863+
await (CreateSimpleEntityWithAssociationDataAsync());
856864

857865
// now try the bulk delete
858866
using (var s = OpenSession())
@@ -868,14 +876,7 @@ public async Task DeleteWithSubqueryAsync()
868876
}
869877

870878
// finally, clean up
871-
using (var s = OpenSession())
872-
using (var t = s.BeginTransaction())
873-
{
874-
await (s.CreateQuery("delete SimpleAssociatedEntity").ExecuteUpdateAsync());
875-
await (s.CreateQuery("delete SimpleEntityWithAssociation").ExecuteUpdateAsync());
876-
await (t.CommitAsync());
877-
s.Close();
878-
}
879+
await (CleanSimpleEntityWithAssociationDataAsync());
879880
}
880881

881882
[Test]
@@ -1079,6 +1080,56 @@ public async Task DeleteSyntaxWithCompositeIdAsync()
10791080
s.Close();
10801081
}
10811082

1083+
[Test]
1084+
public async Task DeleteSubQueryReferencingTargetPropertAsync()
1085+
{
1086+
await (CreateSimpleEntityWithAssociationDataAsync());
1087+
1088+
using (var s = OpenSession())
1089+
using (var t = s.BeginTransaction())
1090+
{
1091+
var count = await (s.CreateQuery("delete from SimpleEntityWithAssociation m where not exists (select d from SimpleAssociatedEntity d where d.Owner = m) and m.Name like 'myEntity%'").ExecuteUpdateAsync());
1092+
Assert.That(count, Is.EqualTo(1), "Incorrect delete count");
1093+
await (t.CommitAsync());
1094+
}
1095+
1096+
await (CleanSimpleEntityWithAssociationDataAsync());
1097+
}
1098+
1099+
private async Task CreateSimpleEntityWithAssociationDataAsync(CancellationToken cancellationToken = default(CancellationToken))
1100+
{
1101+
using (var s = OpenSession())
1102+
using (var t = s.BeginTransaction())
1103+
{
1104+
var owner = new SimpleEntityWithAssociation {Name = "myEntity-1"};
1105+
owner.AddAssociation("assoc-1");
1106+
owner.AddAssociation("assoc-2");
1107+
owner.AddAssociation("assoc-3");
1108+
await (s.SaveAsync(owner, cancellationToken));
1109+
var owner2 = new SimpleEntityWithAssociation {Name = "myEntity-2"};
1110+
owner2.AddAssociation("assoc-1");
1111+
owner2.AddAssociation("assoc-2");
1112+
owner2.AddAssociation("assoc-3");
1113+
owner2.AddAssociation("assoc-4");
1114+
await (s.SaveAsync(owner2, cancellationToken));
1115+
var owner3 = new SimpleEntityWithAssociation {Name = "myEntity-3"};
1116+
await (s.SaveAsync(owner3, cancellationToken));
1117+
await (t.CommitAsync(cancellationToken));
1118+
s.Close();
1119+
}
1120+
}
1121+
1122+
private async Task CleanSimpleEntityWithAssociationDataAsync(CancellationToken cancellationToken = default(CancellationToken))
1123+
{
1124+
using (var s = OpenSession())
1125+
using (var t = s.BeginTransaction())
1126+
{
1127+
await (s.CreateQuery("delete SimpleAssociatedEntity").ExecuteUpdateAsync(cancellationToken));
1128+
await (s.CreateQuery("delete SimpleEntityWithAssociation").ExecuteUpdateAsync(cancellationToken));
1129+
await (t.CommitAsync(cancellationToken));
1130+
s.Close();
1131+
}
1132+
}
10821133
#endregion
10831134

10841135
private class TestData

src/NHibernate.Test/Async/LinqBulkManipulation/Fixture.cs

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,76 @@ public async Task InsertWithClientSideRequirementsThrowsExceptionAsync()
300300
}
301301
}
302302

303+
[Test(Description = "GH2594")]
304+
public async Task InsertIntoWithSubqueryAsync()
305+
{
306+
if(!Dialect.SupportsScalarSubSelects)
307+
Assert.Ignore("Dialect does not support scalar sub-select");
308+
309+
using (var s = OpenSession())
310+
using (var t = s.BeginTransaction())
311+
{
312+
await (s
313+
.Query<Car>()
314+
.InsertIntoAsync(
315+
x => new Pickup
316+
{
317+
Id = -s.Query<Car>().Where(c => c.Id == x.Id).Select(c => c.Id).FirstOrDefault(),
318+
Vin = x.Vin,
319+
Owner = x.Owner
320+
}));
321+
322+
await (t.CommitAsync());
323+
}
324+
}
325+
326+
[Test]
327+
public async Task UpdateWithSubqueryAsync()
328+
{
329+
if(!TestDialect.SupportsModifyAndSelectSameTable || !Dialect.SupportsScalarSubSelects)
330+
Assert.Ignore("Not supported by dialect");
331+
332+
using (var s = OpenSession())
333+
using (var t = s.BeginTransaction())
334+
{
335+
await (s
336+
.Query<Car>()
337+
.UpdateAsync(
338+
x => new
339+
{
340+
Id = -s.Query<Car>().Where(c => c.Id == x.Id).Select(c => c.Id).FirstOrDefault(),
341+
Vin = x.Vin,
342+
Owner = x.Owner
343+
}));
344+
345+
await (t.CommitAsync());
346+
}
347+
}
348+
349+
[Test]
350+
public async Task MultiTableUpdateWithSubqueryAsync()
351+
{
352+
if (!Dialect.SupportsTemporaryTables)
353+
Assert.Ignore("Cannot perform multi-table updates using dialect not supporting temp tables.");
354+
355+
if(!TestDialect.SupportsModifyAndSelectSameTable || !Dialect.SupportsScalarSubSelects)
356+
Assert.Ignore("Not supported by dialect");
357+
358+
using (var s = OpenSession())
359+
using (var t = s.BeginTransaction())
360+
{
361+
await (s
362+
.Query<Animal>()
363+
.UpdateAsync(
364+
x => new
365+
{
366+
Description = s.Query<DomesticAnimal>().Where(c => c.Id == x.Id).Select(c => c.Description).FirstOrDefault(),
367+
}));
368+
369+
await (t.CommitAsync());
370+
}
371+
}
372+
303373
[Test]
304374
public async Task InsertWithManyToOneAsync()
305375
{
@@ -990,6 +1060,24 @@ public async Task DeleteWithSubqueryAsync()
9901060
}
9911061
}
9921062

1063+
[Test]
1064+
public async Task DeleteWithSubquery2Async()
1065+
{
1066+
if(!TestDialect.SupportsModifyAndSelectSameTable || !Dialect.SupportsScalarSubSelects)
1067+
Assert.Ignore("Not supported by dialect");
1068+
1069+
using (var s = OpenSession())
1070+
using (var t = s.BeginTransaction())
1071+
{
1072+
await (s
1073+
.Query<Car>()
1074+
.Where(x => x.Id == -s.Query<Car>().Where(c => c.Id == x.Id).Select(c => c.Id).FirstOrDefault())
1075+
.DeleteAsync());
1076+
1077+
await (t.CommitAsync());
1078+
}
1079+
}
1080+
9931081
[Test]
9941082
public async Task SimpleDeleteOnAnimalAsync()
9951083
{

0 commit comments

Comments
 (0)