@@ -217,6 +217,197 @@ public async Task CanSelectNewGuidAsync()
217
217
}
218
218
}
219
219
220
+ [ Test ]
221
+ public async Task CanQueryByRandomDoubleAsync ( )
222
+ {
223
+ using ( var spy = new SqlLogSpy ( ) )
224
+ {
225
+ var random = new Random ( ) ;
226
+ var x = await ( db . Orders . CountAsync ( o => o . OrderId > random . NextDouble ( ) ) ) ;
227
+
228
+ Assert . That ( x , Is . GreaterThan ( 0 ) ) ;
229
+ AssertFunctionInSql ( "random" , spy ) ;
230
+ }
231
+ }
232
+
233
+ [ Test ]
234
+ public async Task CanSelectRandomDoubleAsync ( )
235
+ {
236
+ using ( var spy = new SqlLogSpy ( ) )
237
+ {
238
+ var random = new Random ( ) ;
239
+ var x =
240
+ await ( db
241
+ . Orders . Select ( o => new { id = o . OrderId , r = random . NextDouble ( ) } )
242
+ . OrderBy ( o => o . id ) . ToListAsync ( ) ) ;
243
+
244
+ Assert . That ( x , Has . Count . GreaterThan ( 0 ) ) ;
245
+ var randomValues = x . Select ( o => o . r ) . Distinct ( ) . ToArray ( ) ;
246
+ Assert . That ( randomValues , Has . All . GreaterThanOrEqualTo ( 0 ) . And . LessThan ( 1 ) ) ;
247
+
248
+ if ( ! LegacyPreEvaluation && IsFunctionSupported ( "random" ) )
249
+ {
250
+ // Naïve randomness check
251
+ Assert . That (
252
+ randomValues ,
253
+ Has . Length . GreaterThan ( x . Count / 2 ) ,
254
+ "Generated values do not seem very random" ) ;
255
+ }
256
+
257
+ AssertFunctionInSql ( "random" , spy ) ;
258
+ }
259
+ }
260
+
261
+ [ Test ]
262
+ public async Task CanQueryByRandomIntAsync ( )
263
+ {
264
+ var idMin = await ( db . Orders . MinAsync ( o => o . OrderId ) ) ;
265
+ using ( var spy = new SqlLogSpy ( ) )
266
+ {
267
+ var random = new Random ( ) ;
268
+ // Dodge a Firebird driver limitation by putting the constants before the order id.
269
+ // This driver cast parameters to their types in some cases for avoiding Firebird complaining of not
270
+ // knowing the type of the condition. For some reasons the driver considers the casting should not be
271
+ // done next to the conditional operator. Having the cast only on one side is enough for avoiding
272
+ // Firebird complain, so moving the constants on the left side have been put before the order id, in
273
+ // order for these constants to be casted by the driver.
274
+ var x = await ( db . Orders . CountAsync ( o => - idMin - 1 + o . OrderId < random . Next ( ) ) ) ;
275
+
276
+ Assert . That ( x , Is . GreaterThan ( 0 ) ) ;
277
+ // Next requires support of both floor and rand
278
+ AssertFunctionInSql ( IsFunctionSupported ( "floor" ) ? "random" : "floor" , spy ) ;
279
+ }
280
+ }
281
+
282
+ [ Test ]
283
+ public async Task CanSelectRandomIntAsync ( )
284
+ {
285
+ using ( var spy = new SqlLogSpy ( ) )
286
+ {
287
+ var random = new Random ( ) ;
288
+ var x =
289
+ await ( db
290
+ . Orders . Select ( o => new { id = o . OrderId , r = random . Next ( ) } )
291
+ . OrderBy ( o => o . id ) . ToListAsync ( ) ) ;
292
+
293
+ Assert . That ( x , Has . Count . GreaterThan ( 0 ) ) ;
294
+ var randomValues = x . Select ( o => o . r ) . Distinct ( ) . ToArray ( ) ;
295
+ Assert . That ( randomValues , Has . All . GreaterThanOrEqualTo ( 0 ) . And . LessThan ( int . MaxValue ) . And . TypeOf < int > ( ) ) ;
296
+
297
+ if ( ! LegacyPreEvaluation && IsFunctionSupported ( "random" ) && IsFunctionSupported ( "floor" ) )
298
+ {
299
+ // Naïve randomness check
300
+ Assert . That (
301
+ randomValues ,
302
+ Has . Length . GreaterThan ( x . Count / 2 ) ,
303
+ "Generated values do not seem very random" ) ;
304
+ }
305
+
306
+ // Next requires support of both floor and rand
307
+ AssertFunctionInSql ( IsFunctionSupported ( "floor" ) ? "random" : "floor" , spy ) ;
308
+ }
309
+ }
310
+
311
+ [ Test ]
312
+ public async Task CanQueryByRandomIntWithMaxAsync ( )
313
+ {
314
+ var idMin = await ( db . Orders . MinAsync ( o => o . OrderId ) ) ;
315
+ using ( var spy = new SqlLogSpy ( ) )
316
+ {
317
+ var random = new Random ( ) ;
318
+ // Dodge a Firebird driver limitation by putting the constants before the order id.
319
+ // This driver cast parameters to their types in some cases for avoiding Firebird complaining of not
320
+ // knowing the type of the condition. For some reasons the driver considers the casting should not be
321
+ // done next to the conditional operator. Having the cast only on one side is enough for avoiding
322
+ // Firebird complain, so moving the constants on the left side have been put before the order id, in
323
+ // order for these constants to be casted by the driver.
324
+ var x = await ( db . Orders . CountAsync ( o => - idMin + o . OrderId <= random . Next ( 10 ) ) ) ;
325
+
326
+ Assert . That ( x , Is . GreaterThan ( 0 ) . And . LessThan ( 11 ) ) ;
327
+ // Next requires support of both floor and rand
328
+ AssertFunctionInSql ( IsFunctionSupported ( "floor" ) ? "random" : "floor" , spy ) ;
329
+ }
330
+ }
331
+
332
+ [ Test ]
333
+ public async Task CanSelectRandomIntWithMaxAsync ( )
334
+ {
335
+ using ( var spy = new SqlLogSpy ( ) )
336
+ {
337
+ var random = new Random ( ) ;
338
+ var x =
339
+ await ( db
340
+ . Orders . Select ( o => new { id = o . OrderId , r = random . Next ( 10 ) } )
341
+ . OrderBy ( o => o . id ) . ToListAsync ( ) ) ;
342
+
343
+ Assert . That ( x , Has . Count . GreaterThan ( 0 ) ) ;
344
+ var randomValues = x . Select ( o => o . r ) . Distinct ( ) . ToArray ( ) ;
345
+ Assert . That ( randomValues , Has . All . GreaterThanOrEqualTo ( 0 ) . And . LessThan ( 10 ) . And . TypeOf < int > ( ) ) ;
346
+
347
+ if ( ! LegacyPreEvaluation && IsFunctionSupported ( "random" ) && IsFunctionSupported ( "floor" ) )
348
+ {
349
+ // Naïve randomness check
350
+ Assert . That (
351
+ randomValues ,
352
+ Has . Length . GreaterThan ( Math . Min ( 10 , x . Count ) / 2 ) ,
353
+ "Generated values do not seem very random" ) ;
354
+ }
355
+
356
+ // Next requires support of both floor and rand
357
+ AssertFunctionInSql ( IsFunctionSupported ( "floor" ) ? "random" : "floor" , spy ) ;
358
+ }
359
+ }
360
+
361
+ [ Test ]
362
+ public async Task CanQueryByRandomIntWithMinMaxAsync ( )
363
+ {
364
+ var idMin = await ( db . Orders . MinAsync ( o => o . OrderId ) ) ;
365
+ using ( var spy = new SqlLogSpy ( ) )
366
+ {
367
+ var random = new Random ( ) ;
368
+ // Dodge a Firebird driver limitation by putting the constants before the order id.
369
+ // This driver cast parameters to their types in some cases for avoiding Firebird complaining of not
370
+ // knowing the type of the condition. For some reasons the driver considers the casting should not be
371
+ // done next to the conditional operator. Having the cast only on one side is enough for avoiding
372
+ // Firebird complain, so moving the constants on the left side have been put before the order id, in
373
+ // order for these constants to be casted by the driver.
374
+ var x = await ( db . Orders . CountAsync ( o => - idMin + o . OrderId < random . Next ( 1 , 10 ) ) ) ;
375
+
376
+ Assert . That ( x , Is . GreaterThan ( 0 ) . And . LessThan ( 10 ) ) ;
377
+ // Next requires support of both floor and rand
378
+ AssertFunctionInSql ( IsFunctionSupported ( "floor" ) ? "random" : "floor" , spy ) ;
379
+ }
380
+ }
381
+
382
+ [ Test ]
383
+ public async Task CanSelectRandomIntWithMinMaxAsync ( )
384
+ {
385
+ using ( var spy = new SqlLogSpy ( ) )
386
+ {
387
+ var random = new Random ( ) ;
388
+ var x =
389
+ await ( db
390
+ . Orders . Select ( o => new { id = o . OrderId , r = random . Next ( 1 , 11 ) } )
391
+ . OrderBy ( o => o . id ) . ToListAsync ( ) ) ;
392
+
393
+ Assert . That ( x , Has . Count . GreaterThan ( 0 ) ) ;
394
+ var randomValues = x . Select ( o => o . r ) . Distinct ( ) . ToArray ( ) ;
395
+ Assert . That ( randomValues , Has . All . GreaterThanOrEqualTo ( 1 ) . And . LessThan ( 11 ) . And . TypeOf < int > ( ) ) ;
396
+
397
+ if ( ! LegacyPreEvaluation && IsFunctionSupported ( "random" ) && IsFunctionSupported ( "floor" ) )
398
+ {
399
+ // Naïve randomness check
400
+ Assert . That (
401
+ randomValues ,
402
+ Has . Length . GreaterThan ( Math . Min ( 10 , x . Count ) / 2 ) ,
403
+ "Generated values do not seem very random" ) ;
404
+ }
405
+
406
+ // Next requires support of both floor and rand
407
+ AssertFunctionInSql ( IsFunctionSupported ( "floor" ) ? "random" : "floor" , spy ) ;
408
+ }
409
+ }
410
+
220
411
private void AssertFunctionInSql ( string functionName , SqlLogSpy spy )
221
412
{
222
413
if ( ! IsFunctionSupported ( functionName ) )
0 commit comments