11using System ;
22using System . Collections ;
3+ using System . Collections . Concurrent ;
4+ using System . Collections . Generic ;
5+ using System . Threading ;
6+ using System . Threading . Tasks ;
37using NHibernate . Dialect ;
48using NUnit . Framework ;
59
@@ -21,6 +25,18 @@ static HQLFunctions()
2125 { "locate" , new [ ] { typeof ( SQLiteDialect ) } } ,
2226 { "bit_length" , new [ ] { typeof ( SQLiteDialect ) } } ,
2327 { "extract" , new [ ] { typeof ( SQLiteDialect ) } } ,
28+ {
29+ "bxor" ,
30+ new [ ]
31+ {
32+ // Could be supported like Oracle, with a template
33+ typeof ( SQLiteDialect ) ,
34+ // Could be supported by overriding registration with # instead of ^
35+ typeof ( PostgreSQLDialect ) ,
36+ typeof ( PostgreSQL81Dialect ) ,
37+ typeof ( PostgreSQL82Dialect )
38+ }
39+ } ,
2440 { "nullif" , new [ ] { typeof ( Oracle8iDialect ) } }
2541 } ;
2642 }
@@ -1014,7 +1030,202 @@ public void ParameterLikeArgument()
10141030 Assert . AreEqual ( 1 , l . Count ) ;
10151031 }
10161032 }
1033+
1034+ [ Test ]
1035+ public void BitwiseAnd ( )
1036+ {
1037+ IgnoreIfNotSupported ( "band" ) ;
1038+ CreateMaterialResources ( ) ;
1039+
1040+ using ( var s = OpenSession ( ) )
1041+ using ( var tx = s . BeginTransaction ( ) )
1042+ {
1043+ var query = s . CreateQuery ( "from MaterialResource m where (m.State & 1) > 0" ) ;
1044+ var result = query . List ( ) ;
1045+ Assert . That ( result , Has . Count . EqualTo ( 1 ) , "& 1" ) ;
1046+
1047+ query = s . CreateQuery ( "from MaterialResource m where (m.State & 2) > 0" ) ;
1048+ result = query . List ( ) ;
1049+ Assert . That ( result , Has . Count . EqualTo ( 1 ) , "& 2" ) ;
1050+
1051+ query = s . CreateQuery ( "from MaterialResource m where (m.State & 3) > 0" ) ;
1052+ result = query . List ( ) ;
1053+ Assert . That ( result , Has . Count . EqualTo ( 2 ) , "& 3" ) ;
1054+
1055+ tx . Commit ( ) ;
1056+ }
1057+ DeleteMaterialResources ( ) ;
1058+ }
1059+
1060+ [ Test ]
1061+ public void BitwiseOr ( )
1062+ {
1063+ IgnoreIfNotSupported ( "bor" ) ;
1064+ CreateMaterialResources ( ) ;
1065+
1066+ using ( var s = OpenSession ( ) )
1067+ using ( var tx = s . BeginTransaction ( ) )
1068+ {
1069+ var query = s . CreateQuery ( "from MaterialResource m where (m.State | 1) > 0" ) ;
1070+ var result = query . List ( ) ;
1071+ Assert . That ( result , Has . Count . EqualTo ( 3 ) , "| 1) > 0" ) ;
1072+
1073+ query = s . CreateQuery ( "from MaterialResource m where (m.State | 1) > 1" ) ;
1074+ result = query . List ( ) ;
1075+ Assert . That ( result , Has . Count . EqualTo ( 1 ) , "| 1) > 1" ) ;
1076+
1077+ query = s . CreateQuery ( "from MaterialResource m where (m.State | 0) > 0" ) ;
1078+ result = query . List ( ) ;
1079+ Assert . That ( result , Has . Count . EqualTo ( 2 ) , "| 0) > 0" ) ;
1080+
1081+ tx . Commit ( ) ;
1082+ }
1083+ DeleteMaterialResources ( ) ;
1084+ }
1085+
1086+ [ Test ]
1087+ public void BitwiseXor ( )
1088+ {
1089+ IgnoreIfNotSupported ( "bxor" ) ;
1090+ CreateMaterialResources ( ) ;
1091+
1092+ using ( var s = OpenSession ( ) )
1093+ using ( var tx = s . BeginTransaction ( ) )
1094+ {
1095+ var query = s . CreateQuery ( "from MaterialResource m where (m.State ^ 1) > 0" ) ;
1096+ var result = query . List ( ) ;
1097+ Assert . That ( result , Has . Count . EqualTo ( 2 ) , "^ 1" ) ;
1098+
1099+ query = s . CreateQuery ( "from MaterialResource m where (m.State ^ 2) > 0" ) ;
1100+ result = query . List ( ) ;
1101+ Assert . That ( result , Has . Count . EqualTo ( 2 ) , "^ 2" ) ;
1102+
1103+ query = s . CreateQuery ( "from MaterialResource m where (m.State ^ 3) > 0" ) ;
1104+ result = query . List ( ) ;
1105+ Assert . That ( result , Has . Count . EqualTo ( 3 ) , "^ 3" ) ;
1106+
1107+ tx . Commit ( ) ;
1108+ }
1109+ DeleteMaterialResources ( ) ;
1110+ }
1111+
1112+ [ Test ]
1113+ public void BitwiseNot ( )
1114+ {
1115+ IgnoreIfNotSupported ( "bnot" ) ;
1116+ IgnoreIfNotSupported ( "band" ) ;
1117+ CreateMaterialResources ( ) ;
1118+
1119+ using ( var s = OpenSession ( ) )
1120+ using ( var tx = s . BeginTransaction ( ) )
1121+ {
1122+ // ! takes not precedence over & at least with some dialects (maybe all).
1123+ var query = s . CreateQuery ( "from MaterialResource m where ((!m.State) & 3) = 3" ) ;
1124+ var result = query . List ( ) ;
1125+ Assert . That ( result , Has . Count . EqualTo ( 1 ) , "((!m.State) & 3) = 3" ) ;
1126+
1127+ query = s . CreateQuery ( "from MaterialResource m where ((!m.State) & 3) = 2" ) ;
1128+ result = query . List ( ) ;
1129+ Assert . That ( result , Has . Count . EqualTo ( 1 ) , "((!m.State) & 3) = 2" ) ;
1130+
1131+ query = s . CreateQuery ( "from MaterialResource m where ((!m.State) & 3) = 1" ) ;
1132+ result = query . List ( ) ;
1133+ Assert . That ( result , Has . Count . EqualTo ( 1 ) , "((!m.State) & 3) = 1" ) ;
1134+
1135+ tx . Commit ( ) ;
1136+ }
1137+ DeleteMaterialResources ( ) ;
1138+ }
1139+
1140+ // #1670
1141+ [ Test ]
1142+ public void BitwiseIsThreadsafe ( )
1143+ {
1144+ IgnoreIfNotSupported ( "band" ) ;
1145+ IgnoreIfNotSupported ( "bor" ) ;
1146+ IgnoreIfNotSupported ( "bxor" ) ;
1147+ IgnoreIfNotSupported ( "bnot" ) ;
1148+ var queries = new List < Tuple < string , int > >
1149+ {
1150+ new Tuple < string , int > ( "select count(*) from MaterialResource m where (m.State & 1) > 0" , 1 ) ,
1151+ new Tuple < string , int > ( "select count(*) from MaterialResource m where (m.State & 2) > 0" , 1 ) ,
1152+ new Tuple < string , int > ( "select count(*) from MaterialResource m where (m.State & 3) > 0" , 2 ) ,
1153+ new Tuple < string , int > ( "select count(*) from MaterialResource m where (m.State | 1) > 0" , 3 ) ,
1154+ new Tuple < string , int > ( "select count(*) from MaterialResource m where (m.State | 1) > 1" , 1 ) ,
1155+ new Tuple < string , int > ( "select count(*) from MaterialResource m where (m.State | 0) > 0" , 2 ) ,
1156+ new Tuple < string , int > ( "select count(*) from MaterialResource m where (m.State ^ 1) > 0" , 2 ) ,
1157+ new Tuple < string , int > ( "select count(*) from MaterialResource m where (m.State ^ 2) > 0" , 2 ) ,
1158+ new Tuple < string , int > ( "select count(*) from MaterialResource m where (m.State ^ 3) > 0" , 3 ) ,
1159+ new Tuple < string , int > ( "select count(*) from MaterialResource m where ((!m.State) & 3) = 3" , 1 ) ,
1160+ new Tuple < string , int > ( "select count(*) from MaterialResource m where ((!m.State) & 3) = 2" , 1 ) ,
1161+ new Tuple < string , int > ( "select count(*) from MaterialResource m where ((!m.State) & 3) = 1" , 1 )
1162+ } ;
1163+ // Do not use a ManualResetEventSlim, it does not support async and exhausts the task thread pool in the
1164+ // async counterparts of this test. SemaphoreSlim has the async support and release the thread when waiting.
1165+ var semaphore = new SemaphoreSlim ( 0 ) ;
1166+ var failures = new ConcurrentBag < Exception > ( ) ;
1167+
1168+ CreateMaterialResources ( ) ;
1169+
1170+ Parallel . For (
1171+ 0 , queries . Count + 1 ,
1172+ i =>
1173+ {
1174+ if ( i >= queries . Count )
1175+ {
1176+ // Give some time to threads for reaching the wait, having all of them ready to do the
1177+ // critical part of their job concurrently.
1178+ Thread . Sleep ( 100 ) ;
1179+ semaphore . Release ( queries . Count ) ;
1180+ return ;
1181+ }
1182+
1183+ try
1184+ {
1185+ var query = queries [ i ] ;
1186+ using ( var s = OpenSession ( ) )
1187+ using ( var tx = s . BeginTransaction ( ) )
1188+ {
1189+ semaphore . Wait ( ) ;
1190+ var q = s . CreateQuery ( query . Item1 ) ;
1191+ var result = q . UniqueResult < long > ( ) ;
1192+ Assert . That ( result , Is . EqualTo ( query . Item2 ) , query . Item1 ) ;
1193+ tx . Commit ( ) ;
1194+ }
1195+ }
1196+ catch ( Exception e )
1197+ {
1198+ failures . Add ( e ) ;
1199+ }
1200+ } ) ;
1201+
1202+ Assert . That ( failures , Is . Empty , $ "{ failures . Count } task(s) failed.") ;
1203+ DeleteMaterialResources ( ) ;
1204+ }
1205+
1206+ private void CreateMaterialResources ( )
1207+ {
1208+ using ( var s = OpenSession ( ) )
1209+ using ( var tx = s . BeginTransaction ( ) )
1210+ {
1211+ s . Save ( new MaterialResource ( "m1" , "18" , MaterialResource . MaterialState . Available ) ) ;
1212+ s . Save ( new MaterialResource ( "m2" , "19" , MaterialResource . MaterialState . Reserved ) ) ;
1213+ s . Save ( new MaterialResource ( "m3" , "20" , MaterialResource . MaterialState . Discarded ) ) ;
1214+ tx . Commit ( ) ;
1215+ }
1216+ }
1217+
1218+ private void DeleteMaterialResources ( )
1219+ {
1220+ using ( var s = OpenSession ( ) )
1221+ using ( var tx = s . BeginTransaction ( ) )
1222+ {
1223+ s . CreateQuery ( "delete from MaterialResource" ) . ExecuteUpdate ( ) ;
1224+ tx . Commit ( ) ;
1225+ }
1226+ }
10171227 }
1228+
10181229 public class ForNh1725
10191230 {
10201231 public string Description { get ; set ; }
0 commit comments