diff --git a/lib/sparkql/evaluator.rb b/lib/sparkql/evaluator.rb index db2ae20..9f78c99 100644 --- a/lib/sparkql/evaluator.rb +++ b/lib/sparkql/evaluator.rb @@ -71,8 +71,8 @@ def evaluate_node(node, result) end if node[:conjunction] == 'Not' && (node[:conjunction_level] == node[:level] || - node[:conjunction_level] == @index[:level]) - @index[:match] = !result + node[:conjunction_level] == @index[:level]) + @index[:match] = !result if @index[:match] elsif node[:conjunction] == 'And' || @index[:expressions] == 0 @index[:match] = result if @index[:match] elsif node[:conjunction] == 'Or' && result diff --git a/test/unit/evaluator_test.rb b/test/unit/evaluator_test.rb index 9f66635..e28e2a4 100644 --- a/test/unit/evaluator_test.rb +++ b/test/unit/evaluator_test.rb @@ -46,6 +46,20 @@ def test_ands_stay_bad assert !sample(filter), "Filter: #{filter}" end end + + # One failing Not expression in a set should always fail. Here we ensure every + # permutation of one failing + def test_nots_stay_bad + 5.times do |i| + expressions = [] + 5.times do |j| + expressions << "Test Eq #{i == j}" + end + # Add the unary not to the front! + filter = "Not " + expressions.join(" Not ") + assert !sample(filter), "Filter: #{filter}" + end + end def test_dropped_field_handling assert sample("Test Eq 'Drop' And Test Eq true") @@ -83,6 +97,24 @@ def test_nots assert !sample("Test Eq true Not (Not Test Eq false)") assert sample("Not (Not Test Eq true)") assert sample("Not (Not(Not Test Eq true))") + assert !sample("Test Eq false And Test Eq true Not Test Eq false") + end + + def test_examples + # This one is based on a real life example that had problems. + # + # CurrentPrice Bt 130000.00,180000.00 And PropertySubType Eq 'Single Family Residence' And + # SchoolDistrict Eq 'Byron Center','Grandville','Jenison' And MlsStatus Eq 'Active' And + # BathsTotal Bt 1.50,9999.00 And BedsTotal Bt 3,99 And PropertyType Eq 'A' + # Not "Garage"."Garage2" Eq 'No' And "Pool"."OutdoorAbove" Eq true + # And "Pool"."OutdoorInground" Eq true Not "Substructure"."Michigan Basement" Eq true + + assert !sample("Test Eq false And Test Eq true And " + + "Test Eq false And Test Eq true And " + + "Test Eq true And Test Eq true And Test Eq true " + + "Not Test Eq false And Test Eq false " + + "And Test Eq false Not Test Eq false" + ) end def test_optimizations