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
|
13
|
||||||
14
|
14
|
||||||
15
|
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;
|
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)));
|
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)));
|
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;
|
drop table t1;
|
||||||
|
@ -239,6 +239,7 @@ public:
|
|||||||
virtual void top_level_item() {}
|
virtual void top_level_item() {}
|
||||||
virtual void set_result_field(Field *field) {}
|
virtual void set_result_field(Field *field) {}
|
||||||
virtual bool is_result_field() { return 0; }
|
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 save_in_result_field(bool no_conversions) {}
|
||||||
virtual void no_rows_in_result() {}
|
virtual void no_rows_in_result() {}
|
||||||
virtual Item *copy_or_same(THD *thd) { return this; }
|
virtual Item *copy_or_same(THD *thd) { return this; }
|
||||||
@ -268,8 +269,7 @@ public:
|
|||||||
virtual void bring_value() {}
|
virtual void bring_value() {}
|
||||||
|
|
||||||
Field *tmp_table_field_from_field_type(TABLE *table);
|
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; }
|
virtual Item *neg_transformer(THD *thd) { return NULL; }
|
||||||
void delete_self()
|
void delete_self()
|
||||||
{
|
{
|
||||||
|
@ -2707,9 +2707,6 @@ longlong Item_cond_xor::val_int()
|
|||||||
IS NULL(a) -> IS NOT NULL(a)
|
IS NULL(a) -> IS NOT NULL(a)
|
||||||
IS NOT NULL(a) -> IS NULL(a)
|
IS NOT NULL(a) -> IS NULL(a)
|
||||||
|
|
||||||
NOTE
|
|
||||||
This method is used in the eliminate_not_funcs() function.
|
|
||||||
|
|
||||||
RETURN
|
RETURN
|
||||||
New item or
|
New item or
|
||||||
NULL if we cannot apply NOT transformation (see Item::neg_transformer()).
|
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 */
|
Item *Item_func_not::neg_transformer(THD *thd) /* NOT(x) -> x */
|
||||||
{
|
{
|
||||||
// We should apply negation elimination to the argument of the NOT function
|
// 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_int_func(a) {}
|
||||||
Item_bool_func(Item *a,Item *b) :Item_int_func(a,b) {}
|
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) {}
|
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; }
|
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; }
|
bool have_rev_func() const { return rev_functype() != UNKNOWN_FUNC; }
|
||||||
void print(String *str) { Item_func::print_op(str); }
|
void print(String *str) { Item_func::print_op(str); }
|
||||||
bool is_null() { return test(args[0]->is_null() || args[1]->is_null()); }
|
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; }
|
CHARSET_INFO *compare_collation() { return cmp.cmp_collation.collation; }
|
||||||
|
|
||||||
friend class Arg_comparator;
|
friend class Arg_comparator;
|
||||||
@ -748,6 +750,7 @@ class Item_func_in :public Item_int_func
|
|||||||
enum Functype functype() const { return IN_FUNC; }
|
enum Functype functype() const { return IN_FUNC; }
|
||||||
const char *func_name() const { return " IN "; }
|
const char *func_name() const { return " IN "; }
|
||||||
bool nulls_in_row();
|
bool nulls_in_row();
|
||||||
|
bool is_bool_func() { return 1; }
|
||||||
CHARSET_INFO *compare_collation() { return cmp_collation.collation; }
|
CHARSET_INFO *compare_collation() { return cmp_collation.collation; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -297,7 +297,8 @@ enum enum_parsing_place
|
|||||||
{
|
{
|
||||||
NO_MATTER,
|
NO_MATTER,
|
||||||
IN_HAVING,
|
IN_HAVING,
|
||||||
SELECT_LIST
|
SELECT_LIST,
|
||||||
|
IN_WHERE
|
||||||
};
|
};
|
||||||
|
|
||||||
struct st_table;
|
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 insert_precheck(THD *thd, TABLE_LIST *tables, bool update);
|
||||||
int create_table_precheck(THD *thd, TABLE_LIST *tables,
|
int create_table_precheck(THD *thd, TABLE_LIST *tables,
|
||||||
TABLE_LIST *create_table);
|
TABLE_LIST *create_table);
|
||||||
|
Item *negate_expression(THD *thd, Item *expr);
|
||||||
#include "sql_class.h"
|
#include "sql_class.h"
|
||||||
#include "opt_range.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)) ?
|
check_grant(thd, want_priv, create_table, 0, UINT_MAX, 0)) ?
|
||||||
1 : 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 *
|
static COND *
|
||||||
optimize_cond(THD *thd, COND *conds, Item::cond_result *cond_value)
|
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);
|
bool error_if_full_join(JOIN *join);
|
||||||
int report_error(TABLE *table, int error);
|
int report_error(TABLE *table, int error);
|
||||||
int safe_index_read(JOIN_TAB *tab);
|
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); }
|
| '~' expr %prec NEG { $$= new Item_func_bit_neg($2); }
|
||||||
| NOT expr %prec NEG
|
| NOT expr %prec NEG
|
||||||
{
|
{
|
||||||
if (($$= $2->neg_transformer(YYTHD)) == 0)
|
$$= negate_expression(YYTHD, $2);
|
||||||
$$= new Item_func_not($2);
|
|
||||||
}
|
}
|
||||||
| '!' expr %prec NEG
|
| '!' expr %prec NEG
|
||||||
{
|
{
|
||||||
if (($$= $2->neg_transformer(YYTHD)) == 0)
|
$$= negate_expression(YYTHD, $2);
|
||||||
$$= new Item_func_not($2);
|
|
||||||
}
|
}
|
||||||
| '(' expr ')' { $$= $2; }
|
| '(' expr ')' { $$= $2; }
|
||||||
| '(' expr ',' expr_list ')'
|
| '(' expr ',' expr_list ')'
|
||||||
@ -3606,11 +3604,17 @@ opt_all:
|
|||||||
|
|
||||||
where_clause:
|
where_clause:
|
||||||
/* empty */ { Select->where= 0; }
|
/* empty */ { Select->where= 0; }
|
||||||
| WHERE expr
|
| WHERE
|
||||||
|
{
|
||||||
|
Select->parsing_place= IN_WHERE;
|
||||||
|
}
|
||||||
|
expr
|
||||||
{
|
{
|
||||||
Select->where= $2;
|
SELECT_LEX *select= Select;
|
||||||
if ($2)
|
select->where= $3;
|
||||||
$2->top_level_item();
|
select->parsing_place= NO_MATTER;
|
||||||
|
if ($3)
|
||||||
|
$3->top_level_item();
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user