Skip to content

Commit 14fef3f

Browse files
authored
Add support for criteria aliases in SqlProjection and SQLCriterion (#2383)
Fixes #896
1 parent bd3fa29 commit 14fef3f

File tree

6 files changed

+388
-8
lines changed

6 files changed

+388
-8
lines changed

src/NHibernate.Test/Async/Criteria/CriteriaQueryTest.cs

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
using System.Collections.Generic;
1414
using NHibernate.Dialect;
1515
using NHibernate.Criterion;
16+
using NHibernate.Linq;
1617
using NHibernate.SqlCommand;
1718
using NHibernate.Transform;
1819
using NHibernate.Type;
@@ -922,6 +923,176 @@ public async Task ProjectionsTestAsync()
922923
s.Close();
923924
}
924925

926+
[Test]
927+
public async Task TestSQLProjectionWithAliasesAsync()
928+
{
929+
using(ISession s = OpenSession())
930+
using(ITransaction t = s.BeginTransaction())
931+
{
932+
Course course = new Course();
933+
course.CourseCode = "HIB";
934+
course.Description = "Hibernate Training";
935+
await (s.SaveAsync(course));
936+
937+
Student gavin = new Student();
938+
gavin.Name = "Gavin King";
939+
gavin.StudentNumber = 667;
940+
await (s.SaveAsync(gavin));
941+
942+
Student xam = new Student();
943+
xam.Name = "Max Rydahl Andersen";
944+
xam.StudentNumber = 101;
945+
await (s.SaveAsync(xam));
946+
947+
Enrolment enrolment = new Enrolment();
948+
enrolment.Course = course;
949+
enrolment.CourseCode = course.CourseCode;
950+
enrolment.Semester = 1;
951+
enrolment.Year = 1999;
952+
enrolment.Student = xam;
953+
enrolment.StudentNumber = xam.StudentNumber;
954+
xam.Enrolments.Add(enrolment);
955+
await (s.SaveAsync(enrolment));
956+
957+
enrolment = new Enrolment();
958+
enrolment.Course = course;
959+
enrolment.CourseCode = course.CourseCode;
960+
enrolment.Semester = 3;
961+
enrolment.Year = 1998;
962+
enrolment.Student = gavin;
963+
enrolment.StudentNumber = gavin.StudentNumber;
964+
gavin.Enrolments.Add(enrolment);
965+
await (s.SaveAsync(enrolment));
966+
await (t.CommitAsync());
967+
}
968+
969+
using (var s = OpenSession())
970+
{
971+
Student studentSubquery = null;
972+
var subquery = QueryOver.Of(() => studentSubquery)
973+
.And(
974+
Expression.Sql("{e}.studentId = 667 and {studentSubquery}.studentId = 667")).Select(Projections.Id());
975+
976+
var uniqueResult = await (s.CreateCriteria(typeof(Student))
977+
.Add(Subqueries.Exists(subquery.DetachedCriteria))
978+
.AddOrder(Order.Asc("Name"))
979+
.CreateCriteria("Enrolments", "e")
980+
.AddOrder(Order.Desc("Year"))
981+
.AddOrder(Order.Desc("Semester"))
982+
.CreateCriteria("Course", "c")
983+
.AddOrder(Order.Asc("Description"))
984+
.SetProjection(
985+
Projections.SqlProjection(
986+
"{alias}.studentId as studentNumber, {e}.Semester as semester,"
987+
+ " {c}.CourseCode as courseCode, {c}.Description as descr",
988+
new string[] {"studentNumber", "semester", "courseCode", "descr"},
989+
new[]
990+
{
991+
TypeFactory.HeuristicType(typeof(long)),
992+
TypeFactory.HeuristicType(typeof(short)),
993+
TypeFactory.HeuristicType(typeof(string)),
994+
TypeFactory.HeuristicType(typeof(string)),
995+
}))
996+
.UniqueResultAsync());
997+
998+
Assert.That(uniqueResult, Is.Not.Null);
999+
}
1000+
1001+
using (var s = OpenSession())
1002+
using (s.BeginTransaction())
1003+
{
1004+
await (s.Query<Enrolment>().DeleteAsync());
1005+
await (s.Query<Student>().DeleteAsync());
1006+
await (s.Query<Course>().DeleteAsync());
1007+
await (s.GetCurrentTransaction().CommitAsync());
1008+
}
1009+
}
1010+
1011+
[Test]
1012+
public async Task TestSQLProjectionWithDuplicateAliasesAsync()
1013+
{
1014+
using(ISession s = OpenSession())
1015+
using(ITransaction t = s.BeginTransaction())
1016+
{
1017+
Course course = new Course();
1018+
course.CourseCode = "HIB";
1019+
course.Description = "Hibernate Training";
1020+
await (s.SaveAsync(course));
1021+
1022+
Student gavin = new Student();
1023+
gavin.Name = "Gavin King";
1024+
gavin.StudentNumber = 667;
1025+
await (s.SaveAsync(gavin));
1026+
1027+
Student xam = new Student();
1028+
xam.Name = "Max Rydahl Andersen";
1029+
xam.StudentNumber = 101;
1030+
await (s.SaveAsync(xam));
1031+
1032+
Enrolment enrolment = new Enrolment();
1033+
enrolment.Course = course;
1034+
enrolment.CourseCode = course.CourseCode;
1035+
enrolment.Semester = 1;
1036+
enrolment.Year = 1999;
1037+
enrolment.Student = xam;
1038+
enrolment.StudentNumber = xam.StudentNumber;
1039+
xam.Enrolments.Add(enrolment);
1040+
await (s.SaveAsync(enrolment));
1041+
1042+
enrolment = new Enrolment();
1043+
enrolment.Course = course;
1044+
enrolment.CourseCode = course.CourseCode;
1045+
enrolment.Semester = 3;
1046+
enrolment.Year = 1998;
1047+
enrolment.Student = gavin;
1048+
enrolment.StudentNumber = gavin.StudentNumber;
1049+
gavin.Enrolments.Add(enrolment);
1050+
await (s.SaveAsync(enrolment));
1051+
await (t.CommitAsync());
1052+
}
1053+
1054+
using (var s = OpenSession())
1055+
{
1056+
Student student = null;
1057+
var subquery = QueryOver.Of(() => student)
1058+
.And(
1059+
Expression.Sql("{e}.studentId = 667 and {student}.studentId = 667")).Select(Projections.Id());
1060+
1061+
var uniqueResult = await (s.CreateCriteria(typeof(Student), "student")
1062+
.Add(Subqueries.Exists(subquery.DetachedCriteria))
1063+
.AddOrder(Order.Asc("Name"))
1064+
.CreateCriteria("Enrolments", "e")
1065+
.AddOrder(Order.Desc("Year"))
1066+
.AddOrder(Order.Desc("Semester"))
1067+
.CreateCriteria("Course", "c")
1068+
.AddOrder(Order.Asc("Description"))
1069+
.SetProjection(
1070+
Projections.SqlProjection(
1071+
"{alias}.studentId as studentNumber, {e}.Semester as semester,"
1072+
+ " {c}.CourseCode as courseCode, {c}.Description as descr",
1073+
new string[] {"studentNumber", "semester", "courseCode", "descr"},
1074+
new[]
1075+
{
1076+
TypeFactory.HeuristicType(typeof(long)),
1077+
TypeFactory.HeuristicType(typeof(short)),
1078+
TypeFactory.HeuristicType(typeof(string)),
1079+
TypeFactory.HeuristicType(typeof(string)),
1080+
}))
1081+
.UniqueResultAsync());
1082+
1083+
Assert.That(uniqueResult, Is.Not.Null);
1084+
}
1085+
1086+
using (var s = OpenSession())
1087+
using (s.BeginTransaction())
1088+
{
1089+
await (s.Query<Enrolment>().DeleteAsync());
1090+
await (s.Query<Student>().DeleteAsync());
1091+
await (s.Query<Course>().DeleteAsync());
1092+
await (s.GetCurrentTransaction().CommitAsync());
1093+
}
1094+
}
1095+
9251096
[Test]
9261097
public async Task CloningProjectionsTestAsync()
9271098
{

src/NHibernate.Test/Criteria/CriteriaQueryTest.cs

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Collections.Generic;
44
using NHibernate.Dialect;
55
using NHibernate.Criterion;
6+
using NHibernate.Linq;
67
using NHibernate.SqlCommand;
78
using NHibernate.Transform;
89
using NHibernate.Type;
@@ -1019,6 +1020,176 @@ public void ProjectionsTest()
10191020
s.Close();
10201021
}
10211022

1023+
[Test]
1024+
public void TestSQLProjectionWithAliases()
1025+
{
1026+
using(ISession s = OpenSession())
1027+
using(ITransaction t = s.BeginTransaction())
1028+
{
1029+
Course course = new Course();
1030+
course.CourseCode = "HIB";
1031+
course.Description = "Hibernate Training";
1032+
s.Save(course);
1033+
1034+
Student gavin = new Student();
1035+
gavin.Name = "Gavin King";
1036+
gavin.StudentNumber = 667;
1037+
s.Save(gavin);
1038+
1039+
Student xam = new Student();
1040+
xam.Name = "Max Rydahl Andersen";
1041+
xam.StudentNumber = 101;
1042+
s.Save(xam);
1043+
1044+
Enrolment enrolment = new Enrolment();
1045+
enrolment.Course = course;
1046+
enrolment.CourseCode = course.CourseCode;
1047+
enrolment.Semester = 1;
1048+
enrolment.Year = 1999;
1049+
enrolment.Student = xam;
1050+
enrolment.StudentNumber = xam.StudentNumber;
1051+
xam.Enrolments.Add(enrolment);
1052+
s.Save(enrolment);
1053+
1054+
enrolment = new Enrolment();
1055+
enrolment.Course = course;
1056+
enrolment.CourseCode = course.CourseCode;
1057+
enrolment.Semester = 3;
1058+
enrolment.Year = 1998;
1059+
enrolment.Student = gavin;
1060+
enrolment.StudentNumber = gavin.StudentNumber;
1061+
gavin.Enrolments.Add(enrolment);
1062+
s.Save(enrolment);
1063+
t.Commit();
1064+
}
1065+
1066+
using (var s = OpenSession())
1067+
{
1068+
Student studentSubquery = null;
1069+
var subquery = QueryOver.Of(() => studentSubquery)
1070+
.And(
1071+
Expression.Sql("{e}.studentId = 667 and {studentSubquery}.studentId = 667")).Select(Projections.Id());
1072+
1073+
var uniqueResult = s.CreateCriteria(typeof(Student))
1074+
.Add(Subqueries.Exists(subquery.DetachedCriteria))
1075+
.AddOrder(Order.Asc("Name"))
1076+
.CreateCriteria("Enrolments", "e")
1077+
.AddOrder(Order.Desc("Year"))
1078+
.AddOrder(Order.Desc("Semester"))
1079+
.CreateCriteria("Course", "c")
1080+
.AddOrder(Order.Asc("Description"))
1081+
.SetProjection(
1082+
Projections.SqlProjection(
1083+
"{alias}.studentId as studentNumber, {e}.Semester as semester,"
1084+
+ " {c}.CourseCode as courseCode, {c}.Description as descr",
1085+
new string[] {"studentNumber", "semester", "courseCode", "descr"},
1086+
new[]
1087+
{
1088+
TypeFactory.HeuristicType(typeof(long)),
1089+
TypeFactory.HeuristicType(typeof(short)),
1090+
TypeFactory.HeuristicType(typeof(string)),
1091+
TypeFactory.HeuristicType(typeof(string)),
1092+
}))
1093+
.UniqueResult();
1094+
1095+
Assert.That(uniqueResult, Is.Not.Null);
1096+
}
1097+
1098+
using (var s = OpenSession())
1099+
using (s.BeginTransaction())
1100+
{
1101+
s.Query<Enrolment>().Delete();
1102+
s.Query<Student>().Delete();
1103+
s.Query<Course>().Delete();
1104+
s.GetCurrentTransaction().Commit();
1105+
}
1106+
}
1107+
1108+
[Test]
1109+
public void TestSQLProjectionWithDuplicateAliases()
1110+
{
1111+
using(ISession s = OpenSession())
1112+
using(ITransaction t = s.BeginTransaction())
1113+
{
1114+
Course course = new Course();
1115+
course.CourseCode = "HIB";
1116+
course.Description = "Hibernate Training";
1117+
s.Save(course);
1118+
1119+
Student gavin = new Student();
1120+
gavin.Name = "Gavin King";
1121+
gavin.StudentNumber = 667;
1122+
s.Save(gavin);
1123+
1124+
Student xam = new Student();
1125+
xam.Name = "Max Rydahl Andersen";
1126+
xam.StudentNumber = 101;
1127+
s.Save(xam);
1128+
1129+
Enrolment enrolment = new Enrolment();
1130+
enrolment.Course = course;
1131+
enrolment.CourseCode = course.CourseCode;
1132+
enrolment.Semester = 1;
1133+
enrolment.Year = 1999;
1134+
enrolment.Student = xam;
1135+
enrolment.StudentNumber = xam.StudentNumber;
1136+
xam.Enrolments.Add(enrolment);
1137+
s.Save(enrolment);
1138+
1139+
enrolment = new Enrolment();
1140+
enrolment.Course = course;
1141+
enrolment.CourseCode = course.CourseCode;
1142+
enrolment.Semester = 3;
1143+
enrolment.Year = 1998;
1144+
enrolment.Student = gavin;
1145+
enrolment.StudentNumber = gavin.StudentNumber;
1146+
gavin.Enrolments.Add(enrolment);
1147+
s.Save(enrolment);
1148+
t.Commit();
1149+
}
1150+
1151+
using (var s = OpenSession())
1152+
{
1153+
Student student = null;
1154+
var subquery = QueryOver.Of(() => student)
1155+
.And(
1156+
Expression.Sql("{e}.studentId = 667 and {student}.studentId = 667")).Select(Projections.Id());
1157+
1158+
var uniqueResult = s.CreateCriteria(typeof(Student), "student")
1159+
.Add(Subqueries.Exists(subquery.DetachedCriteria))
1160+
.AddOrder(Order.Asc("Name"))
1161+
.CreateCriteria("Enrolments", "e")
1162+
.AddOrder(Order.Desc("Year"))
1163+
.AddOrder(Order.Desc("Semester"))
1164+
.CreateCriteria("Course", "c")
1165+
.AddOrder(Order.Asc("Description"))
1166+
.SetProjection(
1167+
Projections.SqlProjection(
1168+
"{alias}.studentId as studentNumber, {e}.Semester as semester,"
1169+
+ " {c}.CourseCode as courseCode, {c}.Description as descr",
1170+
new string[] {"studentNumber", "semester", "courseCode", "descr"},
1171+
new[]
1172+
{
1173+
TypeFactory.HeuristicType(typeof(long)),
1174+
TypeFactory.HeuristicType(typeof(short)),
1175+
TypeFactory.HeuristicType(typeof(string)),
1176+
TypeFactory.HeuristicType(typeof(string)),
1177+
}))
1178+
.UniqueResult();
1179+
1180+
Assert.That(uniqueResult, Is.Not.Null);
1181+
}
1182+
1183+
using (var s = OpenSession())
1184+
using (s.BeginTransaction())
1185+
{
1186+
s.Query<Enrolment>().Delete();
1187+
s.Query<Student>().Delete();
1188+
s.Query<Course>().Delete();
1189+
s.GetCurrentTransaction().Commit();
1190+
}
1191+
}
1192+
10221193
[Test]
10231194
public void CloningProjectionsTest()
10241195
{

0 commit comments

Comments
 (0)