Do not treat anywhere/nowhere as single operand boolean groups
Change-Id: I2fb964af57436aad94981b3c5af39f3bb6b19bcf
diff --git a/lib/Krawfish/Koral/Corpus.pm b/lib/Krawfish/Koral/Corpus.pm
index e34234a..47aefea 100644
--- a/lib/Krawfish/Koral/Corpus.pm
+++ b/lib/Krawfish/Koral/Corpus.pm
@@ -104,6 +104,9 @@
print_log('kq_corpus', 'Do an "and" on anywhere') if DEBUG;
+ # Do not wrap already satisfied queries
+ return $self if $self->is_anywhere || $self->is_nowhere;
+
return $self->builder->bool_and(
$self->builder->anywhere,
$self
diff --git a/lib/Krawfish/Koral/Corpus/FieldGroup.pm b/lib/Krawfish/Koral/Corpus/FieldGroup.pm
index ef5add8..89e0415 100644
--- a/lib/Krawfish/Koral/Corpus/FieldGroup.pm
+++ b/lib/Krawfish/Koral/Corpus/FieldGroup.pm
@@ -21,7 +21,9 @@
# TODO:
# In normalization phase make
-# X geq Y & X leq Y -> X eq Y
+# - X >= Y & X <= Y -> X eq Y
+# - X > 4 & X > 3 -> X > 4
+# - X < 4 & X < 3 -> X < 3
use constant DEBUG => 0;
diff --git a/lib/Krawfish/Koral/Util/Boolean.pm b/lib/Krawfish/Koral/Util/Boolean.pm
index bb661ac..501a0b0 100644
--- a/lib/Krawfish/Koral/Util/Boolean.pm
+++ b/lib/Krawfish/Koral/Util/Boolean.pm
@@ -12,7 +12,7 @@
# - Koral::Query::TermGroup
# - Koral::Query::Or
-use constant DEBUG => 1;
+use constant DEBUG => 0;
requires qw/bool_and_query
bool_or_query/;
@@ -137,6 +137,10 @@
$self = $self->_clean_and_flatten;
+ unless (Role::Tiny::does_role($self, 'Krawfish::Koral::Util::Boolean')) {
+ return $self->normalize;
+ };
+
# Recursive normalize
my @ops = ();
foreach my $op (@{$self->operands}) {
@@ -154,9 +158,13 @@
# but an andNot or a leaf after the final step
#
# The order is important!
- return $self
- ->_clean_and_flatten
- ->_resolve_idempotence
+ $self = $self->_clean_and_flatten;
+
+ unless (Role::Tiny::does_role($self, 'Krawfish::Koral::Util::Boolean')) {
+ return $self->normalize;
+ };
+
+ return $self->_resolve_idempotence
->_resolve_demorgan
->_remove_nested_idempotence
->_replace_negative;
@@ -404,15 +412,13 @@
# Check if there is only a single operand
# (because [1] or [] was removed)
if (scalar(@$ops) == 1) {
- if ($op->is_nowhere) {
- @$ops = ();
- $self->is_nowhere(1);
- }
- elsif ($op->is_anywhere) {
- @$ops = ();
- $self->is_anywhere(1);
+
+ # Revert negativity on single operands
+ if ($self->is_negative) {
+ $op = $op->toggle_negative;
};
- return $self;
+
+ return $op;
};
# Remove empty elements
@@ -430,10 +436,7 @@
print_log('kq_bool', 'Group can be simplified to [0]') if DEBUG;
- # Matches nowhere!
- @$ops = ();
- $self->is_nowhere(1);
- last;
+ return $op;
}
# A | B | [0] -> A | B
@@ -459,9 +462,7 @@
print_log('kq_bool', 'Group can be simplified to [1]') if DEBUG;
# Matches everywhere
- @$ops = ();
- $self->is_anywhere(1);
- last;
+ return $op;
}
}
diff --git a/t/compile/segment/group_fields_aggregate_values.t b/t/compile/segment/group_fields_aggregate_values.t
index 39862fb..bf6b500 100644
--- a/t/compile/segment/group_fields_aggregate_values.t
+++ b/t/compile/segment/group_fields_aggregate_values.t
@@ -71,11 +71,11 @@
# TODO:
# Simplify [1]&[1]!!!
-is($query->to_string, "gaggr(values:['age']:gFields('author':[1]&[1]))", 'string');
+is($query->to_string, "gaggr(values:['age']:gFields('author':[1]))", 'string');
ok($query = $query->identify($index->dict)->optimize($index->segment), 'Optimize');
-is($query->to_string(1), 'gFields(#3;groupAggr([values:#1]):and([1],[1]))', 'Optimized query');
+is($query->to_string(1), 'gFields(#3;groupAggr([values:#1]):[1])', 'Optimized query');
diag 'Implement Group::Aggregate!!';
diff --git a/t/corpus/and.t b/t/corpus/and.t
index 29a8706..3d2889d 100644
--- a/t/corpus/and.t
+++ b/t/corpus/and.t
@@ -123,32 +123,6 @@
ok(!$plan->next, 'No more next');
-ok($query = $cb->bool_and(
- $cb->anywhere,
- $cb->anywhere
-), "And with everywhere");
-
-is($query->to_string, '[1]&[1]', 'Stringification');
-ok($plan = $query->normalize, 'Normalization');
-is($plan->to_string, "", 'Stringification');
-ok($plan->is_anywhere, 'Query is anywhere');
-# ok($plan = $plan->finalize, 'Planning');
-# is($plan->to_string, "[1]", 'Stringification');
-
-ok($query = $cb->bool_and(
- $cb->nowhere,
- $cb->nowhere
-), "And with nowhere");
-
-is($query->to_string, '[0]&[0]', 'Stringification');
-ok($plan = $query->normalize, 'Normalization');
-is($plan->to_string, "", 'Stringification');
-ok($plan->is_nowhere, 'Is nowhere');
-
-
-# TODO:
-# Check [1]|[1]
-
done_testing;
__END__
diff --git a/t/corpus/or.t b/t/corpus/or.t
index c1e8535..3a7c9d6 100644
--- a/t/corpus/or.t
+++ b/t/corpus/or.t
@@ -61,27 +61,6 @@
# matches($plan, [qw/[0] [1] [2] [3] [4]/], 'Matches');
-ok($query = $cb->bool_or(
- $cb->anywhere,
- $cb->anywhere
-), "Or with everywhere");
-
-is($query->to_string, '[1]|[1]', 'Stringification');
-ok($plan = $query->normalize, 'Normalization');
-is($plan->to_string, "", 'Stringification');
-ok($plan->is_anywhere, 'Is anywhere');
-
-
-ok($query = $cb->bool_or(
- $cb->nowhere,
- $cb->nowhere
-), "Or with nowhere");
-
-is($query->to_string, '[0]|[0]', 'Stringification');
-ok($plan = $query->normalize, 'Normalization');
-is($plan->to_string, "", 'Stringification');
-ok($plan->is_nowhere, 'Is nowhere');
-
TODO: {
diff --git a/t/koral/corpus/boolean.t b/t/koral/corpus/boolean.t
index 4733de7..42889f9 100644
--- a/t/koral/corpus/boolean.t
+++ b/t/koral/corpus/boolean.t
@@ -7,20 +7,21 @@
ok(my $cb = Krawfish::Koral::Corpus::Builder->new, 'Create CorpusBuilder');
+my $tree;
+
# Get tree
-my $tree = $cb->bool_and(
+$tree = $cb->bool_and(
$cb->string('age')->eq('4'),
$cb->string('author')->eq('Peter'),
undef,
$cb->string('age')->eq('4')
);
+
# Remove empty elements
ok($tree = $tree->normalize, 'Query normalization');
is($tree->to_string, 'age=4&author=Peter', 'Resolve idempotence');
-
-
# Solve grouping
$tree = $cb->bool_and(
$cb->string('a')->eq('1'),
@@ -180,9 +181,9 @@
);
is($tree->to_string, '[0]&x=1&z=1', 'Plain groups');
-$tree->normalize;
+ok($tree = $tree->normalize, 'Normalize');
ok($tree->is_nowhere, 'Nowhere');
-is($tree->to_string, '', 'Nowhere');
+is($tree->to_string, '[0]', 'Nowhere');
# Check flattening with ANY
@@ -194,10 +195,10 @@
);
is($tree->to_string, '[1]|x=1|z=1', 'Plain groups');
-$tree->normalize;
+ok($tree = $tree->normalize, 'Normalize');
ok(!$tree->is_nowhere, 'No Nowhere');
ok($tree->is_anywhere, 'Anything');
-is($tree->to_string, '', 'no string');
+is($tree->to_string, '[1]', 'no string');
# Check flattening with ANY
@@ -209,7 +210,7 @@
);
is($tree->to_string, '[1]&x=1&z=1', 'Plain groups');
-$tree->normalize;
+ok($tree = $tree->normalize, 'Normalize');
ok(!$tree->is_nowhere, 'No Nowhere');
ok(!$tree->is_anywhere, 'No Anything');
is($tree->to_string, 'x=1&z=1', 'no string');
@@ -224,7 +225,7 @@
);
is($tree->to_string, 'x!=1|y!=1|z!=1', 'Plain groups');
-$tree->normalize;
+ok($tree = $tree->normalize, 'Normalize');
is($tree->to_string, '!(x=1&y=1&z=1)', 'no string');
@@ -237,7 +238,7 @@
);
is($tree->to_string, 'x!=1&y!=1&z!=1', 'Plain groups');
-$tree->normalize;
+ok($tree = $tree->normalize, 'Normalize');
is($tree->to_string, '!(x=1|y=1|z=1)', 'no string');
@@ -252,7 +253,7 @@
);
is($tree->to_string, 'a!=1|b=1|c!=1|d=1|e!=1|f=1', 'Plain groups');
-$tree->normalize;
+ok($tree = $tree->normalize, 'Normalize');
is($tree->to_string, '([1]&!(a=1&c=1&e=1))' . '|b=1|d=1|f=1', 'no string');
# DeMorgan grouping with AND
@@ -266,7 +267,7 @@
);
is($tree->to_string, 'a!=1&b=1&c!=1&d=1&e!=1&f=1', 'Plain groups');
-$tree = $tree->normalize;
+ok($tree = $tree->normalize, 'Normalize');
# TODO: This may require a direct andNot() serialization with the all-query
is($tree->to_string, '((b=1&d=1&f=1)&!(a=1|c=1|e=1))', 'no string');
@@ -279,7 +280,7 @@
)->toggle_negative;
is($tree->to_string, '!(a!=1)', 'Plain groups');
-$tree = $tree->normalize;
+ok($tree = $tree->normalize, 'Normalize');
is($tree->to_string, 'a=1', 'simple string');
@@ -290,7 +291,7 @@
)->toggle_negative;
is($tree->to_string, '!(a!=1&b!=1)', 'Plain groups');
-$tree = $tree->normalize;
+ok($tree = $tree->normalize, 'Normalize');
is($tree->to_string, 'a=1|b=1', 'simple string');
@@ -325,6 +326,60 @@
is($tree->to_string, '([1]&!(([1]&!b=1)|c=1|d=1))', 'simple string');
+# Check [1/0]&/|[1/0]
+ok($tree = $cb->bool_and(
+ $cb->anywhere,
+ $cb->anywhere
+), "And with everywhere");
+
+is($tree->to_string, '[1]&[1]', 'Stringification');
+ok($tree = $tree->normalize, 'Normalization');
+is($tree->to_string, '[1]', 'Stringification');
+ok($tree->is_anywhere, 'Query is anywhere');
+ok($tree = $tree->finalize, 'Planning');
+is($tree->to_string, "[1]", 'Stringification');
+
+ok($tree = $cb->bool_and(
+ $cb->nowhere,
+ $cb->nowhere
+), "And with nowhere");
+
+is($tree->to_string, '[0]&[0]', 'Stringification');
+ok($tree = $tree->normalize, 'Normalization');
+is($tree->to_string, '[0]', 'Stringification');
+ok($tree->is_nowhere, 'Is nowhere');
+ok($tree = $tree->finalize, 'Planning');
+is($tree->to_string, "[0]", 'Stringification');
+
+
+ok($tree = $cb->bool_or(
+ $cb->anywhere,
+ $cb->anywhere
+), "Or with everywhere");
+
+is($tree->to_string, '[1]|[1]', 'Stringification');
+ok($tree = $tree->normalize, 'Normalization');
+is($tree->to_string, '[1]', 'Stringification');
+ok($tree->is_anywhere, 'Is anywhere');
+ok($tree = $tree->finalize, 'Planning');
+is($tree->to_string, "[1]", 'Stringification');
+
+
+
+ok($tree = $cb->bool_or(
+ $cb->nowhere,
+ $cb->nowhere
+), "Or with nowhere");
+
+is($tree->to_string, '[0]|[0]', 'Stringification');
+ok($tree = $tree->normalize, 'Normalization');
+is($tree->to_string, '[0]', 'Stringification');
+ok($tree->is_nowhere, 'Is nowhere');
+ok($tree = $tree->finalize, 'Planning');
+is($tree->to_string, "[0]", 'Stringification');
+
+
+
TODO: {
local $TODO = 'Check with negativity for >=, <=, exists etc.'
@@ -383,4 +438,9 @@
$tree->remove_empty->resolve_idempotence;
is($tree->to_string, 'age!=4&author!=Peter', 'Resolve idempotence');
+
+
+
+
+
done_testing;