@@ -3,6 +3,7 @@ use crate::generation::{one_of, Arbitrary, ArbitraryFrom};
33
44use crate :: model:: query:: { Create , Delete , Insert , Predicate , Query , Select } ;
55use crate :: model:: table:: { Table , Value } ;
6+ use rand:: seq:: SliceRandom as _;
67use rand:: Rng ;
78
89use super :: { frequency, pick} ;
@@ -174,7 +175,7 @@ impl ArbitraryFrom<(&Table, bool)> for CompoundPredicate {
174175 let len = booleans. len ( ) ;
175176
176177 // Make sure at least one of them is false
177- if booleans. iter ( ) . all ( |b| * b) {
178+ if !booleans . is_empty ( ) && booleans. iter ( ) . all ( |b| * b) {
178179 booleans[ rng. gen_range ( 0 ..len) ] = false ;
179180 }
180181
@@ -195,7 +196,7 @@ impl ArbitraryFrom<(&Table, bool)> for CompoundPredicate {
195196 . collect :: < Vec < _ > > ( ) ;
196197 let len = booleans. len ( ) ;
197198 // Make sure at least one of them is true
198- if booleans. iter ( ) . all ( |b| !* b) {
199+ if !booleans . is_empty ( ) && booleans. iter ( ) . all ( |b| !* b) {
199200 booleans[ rng. gen_range ( 0 ..len) ] = true ;
200201 }
201202
@@ -246,16 +247,155 @@ impl ArbitraryFrom<(&str, &Value)> for Predicate {
246247 }
247248}
248249
249- impl ArbitraryFrom < ( & Table , & Predicate ) > for Predicate {
250- fn arbitrary_from < R : Rng > ( rng : & mut R , ( t, p) : & ( & Table , & Predicate ) ) -> Self {
251- if rng. gen_bool ( 0.5 ) {
252- // produce a true predicate
253- let p_t = CompoundPredicate :: arbitrary_from ( rng, & ( * t, true ) ) . 0 ;
254- Predicate :: And ( vec ! [ p_t, ( * p) . clone( ) ] )
255- } else {
256- // produce a false predicate
257- let p_f = CompoundPredicate :: arbitrary_from ( rng, & ( * t, false ) ) . 0 ;
258- Predicate :: Or ( vec ! [ p_f, ( * p) . clone( ) ] )
250+ /// Produces a predicate that is true for the provided row in the given table
251+ fn produce_true_predicate < R : Rng > ( rng : & mut R , ( t, row) : & ( & Table , & Vec < Value > ) ) -> Predicate {
252+ // Pick a column
253+ let column_index = rng. gen_range ( 0 ..t. columns . len ( ) ) ;
254+ let column = & t. columns [ column_index] ;
255+ let value = & row[ column_index] ;
256+ one_of (
257+ vec ! [
258+ Box :: new( |_| Predicate :: Eq ( column. name. clone( ) , value. clone( ) ) ) ,
259+ Box :: new( |rng| {
260+ let v = loop {
261+ let v = Value :: arbitrary_from( rng, & column. column_type) ;
262+ if & v != value {
263+ break v;
264+ }
265+ } ;
266+ Predicate :: Neq ( column. name. clone( ) , v)
267+ } ) ,
268+ Box :: new( |rng| {
269+ Predicate :: Gt ( column. name. clone( ) , LTValue :: arbitrary_from( rng, value) . 0 )
270+ } ) ,
271+ Box :: new( |rng| {
272+ Predicate :: Lt ( column. name. clone( ) , GTValue :: arbitrary_from( rng, value) . 0 )
273+ } ) ,
274+ ] ,
275+ rng,
276+ )
277+ }
278+
279+ /// Produces a predicate that is false for the provided row in the given table
280+ fn produce_false_predicate < R : Rng > ( rng : & mut R , ( t, row) : & ( & Table , & Vec < Value > ) ) -> Predicate {
281+ // Pick a column
282+ let column_index = rng. gen_range ( 0 ..t. columns . len ( ) ) ;
283+ let column = & t. columns [ column_index] ;
284+ let value = & row[ column_index] ;
285+ one_of (
286+ vec ! [
287+ Box :: new( |_| Predicate :: Neq ( column. name. clone( ) , value. clone( ) ) ) ,
288+ Box :: new( |rng| {
289+ let v = loop {
290+ let v = Value :: arbitrary_from( rng, & column. column_type) ;
291+ if & v != value {
292+ break v;
293+ }
294+ } ;
295+ Predicate :: Eq ( column. name. clone( ) , v)
296+ } ) ,
297+ Box :: new( |rng| {
298+ Predicate :: Gt ( column. name. clone( ) , GTValue :: arbitrary_from( rng, value) . 0 )
299+ } ) ,
300+ Box :: new( |rng| {
301+ Predicate :: Lt ( column. name. clone( ) , LTValue :: arbitrary_from( rng, value) . 0 )
302+ } ) ,
303+ ] ,
304+ rng,
305+ )
306+ }
307+
308+ impl ArbitraryFrom < ( & Table , & Vec < Value > ) > for Predicate {
309+ fn arbitrary_from < R : Rng > ( rng : & mut R , ( t, row) : & ( & Table , & Vec < Value > ) ) -> Self {
310+ // We want to produce a predicate that is true for the row
311+ // We can do this by creating several predicates that
312+ // are true, some that are false, combiend them in ways that correspond to the creation of a true predicate
313+
314+ // Produce some true and false predicates
315+ let mut true_predicates = ( 1 ..=rng. gen_range ( 1 ..=4 ) )
316+ . map ( |_| produce_true_predicate ( rng, & ( * t, row) ) )
317+ . collect :: < Vec < _ > > ( ) ;
318+
319+ let false_predicates = ( 0 ..=rng. gen_range ( 0 ..=3 ) )
320+ . map ( |_| produce_false_predicate ( rng, & ( * t, row) ) )
321+ . collect :: < Vec < _ > > ( ) ;
322+
323+ // Start building a top level predicate from a true predicate
324+ let mut result = true_predicates. pop ( ) . unwrap ( ) ;
325+ println ! ( "True predicate: {:?}" , result) ;
326+
327+ let mut predicates = true_predicates
328+ . iter ( )
329+ . map ( |p| ( true , p. clone ( ) ) )
330+ . chain ( false_predicates. iter ( ) . map ( |p| ( false , p. clone ( ) ) ) )
331+ . collect :: < Vec < _ > > ( ) ;
332+
333+ predicates. shuffle ( rng) ;
334+
335+ while !predicates. is_empty ( ) {
336+ // Create a new predicate from at least 1 and at most 3 predicates
337+ let context =
338+ predicates[ 0 ..rng. gen_range ( 0 ..=usize:: min ( 3 , predicates. len ( ) ) ) ] . to_vec ( ) ;
339+ // Shift `predicates` to remove the predicates in the context
340+ predicates = predicates[ context. len ( ) ..] . to_vec ( ) ;
341+
342+ // `result` is true, so we have the following three options to make a true predicate:
343+ // T or F
344+ // T or T
345+ // T and T
346+
347+ result = one_of (
348+ vec ! [
349+ // T or (X1 or X2 or ... or Xn)
350+ Box :: new( |_| {
351+ Predicate :: Or ( vec![
352+ result. clone( ) ,
353+ Predicate :: Or ( context. iter( ) . map( |( _, p) | p. clone( ) ) . collect( ) ) ,
354+ ] )
355+ } ) ,
356+ // T or (T1 and T2 and ... and Tn)
357+ Box :: new( |_| {
358+ Predicate :: Or ( vec![
359+ result. clone( ) ,
360+ Predicate :: And ( context. iter( ) . map( |( _, p) | p. clone( ) ) . collect( ) ) ,
361+ ] )
362+ } ) ,
363+ // T and T
364+ Box :: new( |_| {
365+ // Check if all the predicates in the context are true
366+ if context. iter( ) . all( |( b, _) | * b) {
367+ // T and (X1 or X2 or ... or Xn)
368+ Predicate :: And ( vec![
369+ result. clone( ) ,
370+ Predicate :: And ( context. iter( ) . map( |( _, p) | p. clone( ) ) . collect( ) ) ,
371+ ] )
372+ }
373+ // Check if there is at least one true predicate
374+ else if context. iter( ) . any( |( b, _) | * b) {
375+ // T and (X1 or X2 or ... or Xn)
376+ Predicate :: And ( vec![
377+ result. clone( ) ,
378+ Predicate :: Or ( context. iter( ) . map( |( _, p) | p. clone( ) ) . collect( ) ) ,
379+ ] )
380+ } else {
381+ // T and (X1 or X2 or ... or Xn or TRUE)
382+ Predicate :: And ( vec![
383+ result. clone( ) ,
384+ Predicate :: Or (
385+ context
386+ . iter( )
387+ . map( |( _, p) | p. clone( ) )
388+ . chain( std:: iter:: once( Predicate :: true_( ) ) )
389+ . collect( ) ,
390+ ) ,
391+ ] )
392+ }
393+ } ) ,
394+ ] ,
395+ rng,
396+ ) ;
259397 }
398+
399+ result
260400 }
261401}
0 commit comments