mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
after review patch
This commit is contained in:
@ -375,4 +375,17 @@ a
|
||||
13
|
||||
14
|
||||
15
|
||||
delete from t1 where a > 3;
|
||||
select a, not(not(a)) from t1;
|
||||
a not(not(a))
|
||||
NULL NULL
|
||||
0 0
|
||||
1 1
|
||||
2 1
|
||||
3 1
|
||||
explain extended select a, not(not(a)), not(a <= 2 and not(a)), not(a not like "1"), not (a not in (1,2)), not(a != 2) from t1 where not(not(a)) having not(not(a));
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 index NULL a 5 NULL 5 Using where; Using index
|
||||
Warnings:
|
||||
Note 1003 select test.t1.a AS `a`,(test.t1.a <> 0) AS `not(not(a))`,((test.t1.a > 2) or test.t1.a) AS `not(a <= 2 and not(a))`,(test.t1.a like _latin1'1') AS `not(a not like "1")`,(test.t1.a in (1,2)) AS `not (a not in (1,2))`,(test.t1.a = 2) AS `not(a != 2)` from test.t1 where test.t1.a having test.t1.a
|
||||
drop table t1;
|
||||
|
@ -65,4 +65,8 @@ select * from t1 where not((a < 5 and a < 10) and (not(a > 16) or a > 17));
|
||||
explain select * from t1 where ((a between 5 and 15) and (not(a like 10)));
|
||||
select * from t1 where ((a between 5 and 15) and (not(a like 10)));
|
||||
|
||||
delete from t1 where a > 3;
|
||||
select a, not(not(a)) from t1;
|
||||
explain extended select a, not(not(a)), not(a <= 2 and not(a)), not(a not like "1"), not (a not in (1,2)), not(a != 2) from t1 where not(not(a)) having not(not(a));
|
||||
|
||||
drop table t1;
|
||||
|
@ -239,6 +239,7 @@ public:
|
||||
virtual void top_level_item() {}
|
||||
virtual void set_result_field(Field *field) {}
|
||||
virtual bool is_result_field() { return 0; }
|
||||
virtual bool is_bool_func() { return 0; }
|
||||
virtual void save_in_result_field(bool no_conversions) {}
|
||||
virtual void no_rows_in_result() {}
|
||||
virtual Item *copy_or_same(THD *thd) { return this; }
|
||||
@ -269,7 +270,6 @@ public:
|
||||
|
||||
Field *tmp_table_field_from_field_type(TABLE *table);
|
||||
|
||||
/* Used in sql_select.cc:eliminate_not_funcs() */
|
||||
virtual Item *neg_transformer(THD *thd) { return NULL; }
|
||||
void delete_self()
|
||||
{
|
||||
|
@ -2707,9 +2707,6 @@ longlong Item_cond_xor::val_int()
|
||||
IS NULL(a) -> IS NOT NULL(a)
|
||||
IS NOT NULL(a) -> IS NULL(a)
|
||||
|
||||
NOTE
|
||||
This method is used in the eliminate_not_funcs() function.
|
||||
|
||||
RETURN
|
||||
New item or
|
||||
NULL if we cannot apply NOT transformation (see Item::neg_transformer()).
|
||||
@ -2718,7 +2715,7 @@ longlong Item_cond_xor::val_int()
|
||||
Item *Item_func_not::neg_transformer(THD *thd) /* NOT(x) -> x */
|
||||
{
|
||||
// We should apply negation elimination to the argument of the NOT function
|
||||
return eliminate_not_funcs(thd, args[0]);
|
||||
return args[0];
|
||||
}
|
||||
|
||||
|
||||
|
@ -89,6 +89,7 @@ public:
|
||||
Item_bool_func(Item *a) :Item_int_func(a) {}
|
||||
Item_bool_func(Item *a,Item *b) :Item_int_func(a,b) {}
|
||||
Item_bool_func(THD *thd, Item_bool_func *item) :Item_int_func(thd, item) {}
|
||||
bool is_bool_func() { return 1; }
|
||||
void fix_length_and_dec() { decimals=0; max_length=1; }
|
||||
};
|
||||
|
||||
@ -201,6 +202,7 @@ public:
|
||||
bool have_rev_func() const { return rev_functype() != UNKNOWN_FUNC; }
|
||||
void print(String *str) { Item_func::print_op(str); }
|
||||
bool is_null() { return test(args[0]->is_null() || args[1]->is_null()); }
|
||||
bool is_bool_func() { return 1; }
|
||||
CHARSET_INFO *compare_collation() { return cmp.cmp_collation.collation; }
|
||||
|
||||
friend class Arg_comparator;
|
||||
@ -748,6 +750,7 @@ class Item_func_in :public Item_int_func
|
||||
enum Functype functype() const { return IN_FUNC; }
|
||||
const char *func_name() const { return " IN "; }
|
||||
bool nulls_in_row();
|
||||
bool is_bool_func() { return 1; }
|
||||
CHARSET_INFO *compare_collation() { return cmp_collation.collation; }
|
||||
};
|
||||
|
||||
|
@ -297,7 +297,8 @@ enum enum_parsing_place
|
||||
{
|
||||
NO_MATTER,
|
||||
IN_HAVING,
|
||||
SELECT_LIST
|
||||
SELECT_LIST,
|
||||
IN_WHERE
|
||||
};
|
||||
|
||||
struct st_table;
|
||||
@ -376,6 +377,7 @@ int delete_precheck(THD *thd, TABLE_LIST *tables);
|
||||
int insert_precheck(THD *thd, TABLE_LIST *tables, bool update);
|
||||
int create_table_precheck(THD *thd, TABLE_LIST *tables,
|
||||
TABLE_LIST *create_table);
|
||||
Item *negate_expression(THD *thd, Item *expr);
|
||||
#include "sql_class.h"
|
||||
#include "opt_range.h"
|
||||
|
||||
|
@ -5401,3 +5401,39 @@ int create_table_precheck(THD *thd, TABLE_LIST *tables,
|
||||
check_grant(thd, want_priv, create_table, 0, UINT_MAX, 0)) ?
|
||||
1 : 0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
negate given expression
|
||||
|
||||
SYNOPSIS
|
||||
negate_expression()
|
||||
thd therad handler
|
||||
expr expression for negation
|
||||
|
||||
RETURN
|
||||
negated expression
|
||||
*/
|
||||
|
||||
Item *negate_expression(THD *thd, Item *expr)
|
||||
{
|
||||
Item *negated;
|
||||
if (expr->type() == Item::FUNC_ITEM &&
|
||||
((Item_func *) expr)->functype() == Item_func::NOT_FUNC)
|
||||
{
|
||||
/* it is NOT(NOT( ... )) */
|
||||
Item *arg= ((Item_func *) expr)->arguments()[0];
|
||||
enum_parsing_place place= thd->lex->current_select->parsing_place;
|
||||
if (arg->is_bool_func() || place == IN_WHERE || place == IN_HAVING)
|
||||
return arg;
|
||||
/*
|
||||
if it is not boolean function then we have to emulate value of
|
||||
not(not(a)), it will be a != 0
|
||||
*/
|
||||
return new Item_func_ne(arg, new Item_int((char*) "0", 0, 1));
|
||||
}
|
||||
|
||||
if ((negated= expr->neg_transformer(thd)) != 0)
|
||||
return negated;
|
||||
return new Item_func_not(expr);
|
||||
}
|
||||
|
@ -4339,60 +4339,6 @@ propagate_cond_constants(I_List<COND_CMP> *save_list,COND *and_father,
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Eliminate NOT functions from the condition tree.
|
||||
|
||||
SYNPOSIS
|
||||
eliminate_not_funcs()
|
||||
thd thread handler
|
||||
cond condition tree
|
||||
|
||||
DESCRIPTION
|
||||
Eliminate NOT functions from the condition tree where it's possible.
|
||||
Recursively traverse condition tree to find all NOT functions.
|
||||
Call neg_transformer() method for negated arguments.
|
||||
|
||||
NOTE
|
||||
If neg_transformer() returned a new condition we call fix_fields().
|
||||
We don't delete any items as it's not needed. They will be deleted
|
||||
later at once.
|
||||
|
||||
RETURN
|
||||
New condition tree
|
||||
*/
|
||||
|
||||
COND *eliminate_not_funcs(THD *thd, COND *cond)
|
||||
{
|
||||
if (!cond)
|
||||
return cond;
|
||||
if (cond->type() == Item::COND_ITEM) /* OR or AND */
|
||||
{
|
||||
List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
|
||||
Item *item;
|
||||
while ((item= li++))
|
||||
{
|
||||
Item *new_item= eliminate_not_funcs(thd, item);
|
||||
if (item != new_item)
|
||||
VOID(li.replace(new_item)); /* replace item with a new condition */
|
||||
}
|
||||
}
|
||||
else if (cond->type() == Item::FUNC_ITEM && /* 'NOT' operation? */
|
||||
((Item_func*) cond)->functype() == Item_func::NOT_FUNC)
|
||||
{
|
||||
COND *new_cond= ((Item_func*) cond)->arguments()[0]->neg_transformer(thd);
|
||||
if (new_cond)
|
||||
{
|
||||
/*
|
||||
Here we can delete the NOT function. Something like: delete cond;
|
||||
But we don't need to do it. All items will be deleted later at once.
|
||||
*/
|
||||
cond= new_cond;
|
||||
}
|
||||
}
|
||||
return cond;
|
||||
}
|
||||
|
||||
|
||||
static COND *
|
||||
optimize_cond(THD *thd, COND *conds, Item::cond_result *cond_value)
|
||||
{
|
||||
|
@ -438,4 +438,3 @@ bool cp_buffer_from_ref(TABLE_REF *ref);
|
||||
bool error_if_full_join(JOIN *join);
|
||||
int report_error(TABLE *table, int error);
|
||||
int safe_index_read(JOIN_TAB *tab);
|
||||
COND *eliminate_not_funcs(THD *thd, COND *cond);
|
||||
|
@ -2757,13 +2757,11 @@ simple_expr:
|
||||
| '~' expr %prec NEG { $$= new Item_func_bit_neg($2); }
|
||||
| NOT expr %prec NEG
|
||||
{
|
||||
if (($$= $2->neg_transformer(YYTHD)) == 0)
|
||||
$$= new Item_func_not($2);
|
||||
$$= negate_expression(YYTHD, $2);
|
||||
}
|
||||
| '!' expr %prec NEG
|
||||
{
|
||||
if (($$= $2->neg_transformer(YYTHD)) == 0)
|
||||
$$= new Item_func_not($2);
|
||||
$$= negate_expression(YYTHD, $2);
|
||||
}
|
||||
| '(' expr ')' { $$= $2; }
|
||||
| '(' expr ',' expr_list ')'
|
||||
@ -3606,11 +3604,17 @@ opt_all:
|
||||
|
||||
where_clause:
|
||||
/* empty */ { Select->where= 0; }
|
||||
| WHERE expr
|
||||
| WHERE
|
||||
{
|
||||
Select->parsing_place= IN_WHERE;
|
||||
}
|
||||
expr
|
||||
{
|
||||
Select->where= $2;
|
||||
if ($2)
|
||||
$2->top_level_item();
|
||||
SELECT_LEX *select= Select;
|
||||
select->where= $3;
|
||||
select->parsing_place= NO_MATTER;
|
||||
if ($3)
|
||||
$3->top_level_item();
|
||||
}
|
||||
;
|
||||
|
||||
|
Reference in New Issue
Block a user