diff options
author | Alexey Kopytov <Alexey.Kopytov@Sun.com> | 2010-08-24 19:51:32 +0400 |
---|---|---|
committer | Alexey Kopytov <Alexey.Kopytov@Sun.com> | 2010-08-24 19:51:32 +0400 |
commit | 756076bd23d9e194d5730745d07ee86aa543d4e5 (patch) | |
tree | d51bc34d86979999da310f2aa07b4fd57c7e5581 /sql/opt_range.cc | |
parent | 6973c354de11570f5575abdbd40bb47dce636d34 (diff) | |
download | mariadb-git-756076bd23d9e194d5730745d07ee86aa543d4e5.tar.gz |
Bug #54802: 'NOT BETWEEN' evaluation is incorrect
Queries involving predicates of the form "const NOT BETWEEN
not_indexed_column AND indexed_column" could return wrong data
due to incorrect handling by the range optimizer.
For "c NOT BETWEEN f1 AND f2" predicates, get_mm_tree()
produces a disjunction of the SEL_ARG trees for "f1 > c" and
"f2 < c". If one of the trees is empty (i.e. one of the
arguments is not sargable) the resulting tree should be empty
as well, since the whole expression in this case is not
sargable.
The above logic is implemented in get_mm_tree() as follows. The
initial state of the resulting tree is NULL (aka empty). We
then iterate through arguments and compute the corresponding
SEL_ARG tree (either "f1 > c" or "f2 < c"). If the resulting
tree is NULL, it is simply replaced by the generated
tree. Otherwise it is replaced by a disjunction of itself and
the generated tree. The obvious flaw in this implementation is
that if the first argument is not sargable and thus produces a
NULL tree, the resulting tree will simply be replaced by the
tree for the second argument. As a result, "c NOT BETWEEN f1
AND f2" will end up as just "f2 < c".
Fixed by adding a check so that when the first argument
produces an empty tree for the NOT BETWEEN case, the loop is
aborted with an empty tree as a result. The whole idea of using
a loop for 2 arguments does not make much sense, but it was
probably used to avoid code duplication for several BETWEEN
variants.
Diffstat (limited to 'sql/opt_range.cc')
-rw-r--r-- | sql/opt_range.cc | 4 |
1 files changed, 4 insertions, 0 deletions
diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 1f42d0567a7..eae79e63c19 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -5526,7 +5526,11 @@ static SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param,COND *cond) SEL_TREE *tmp= get_full_func_mm_tree(param, cond_func, field_item, (Item*)(intptr)i, inv); if (inv) + { tree= !tree ? tmp : tree_or(param, tree, tmp); + if (tree == NULL) + break; + } else tree= tree_and(param, tree, tmp); } |