Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
mariadb
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
mariadb
Commits
419c20f1
Commit
419c20f1
authored
Jul 12, 2011
by
Sergey Petrunya
Browse files
Options
Browse Files
Download
Plain Diff
Merge
parents
47aee198
2c28412e
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
236 additions
and
73 deletions
+236
-73
mysql-test/r/negation_elimination.result
mysql-test/r/negation_elimination.result
+115
-0
mysql-test/t/negation_elimination.test
mysql-test/t/negation_elimination.test
+29
-0
sql/item_cmpfunc.cc
sql/item_cmpfunc.cc
+35
-10
sql/item_cmpfunc.h
sql/item_cmpfunc.h
+16
-39
sql/item_func.h
sql/item_func.h
+1
-1
sql/opt_subselect.cc
sql/opt_subselect.cc
+39
-22
sql/sql_yacc.yy
sql/sql_yacc.yy
+1
-1
No files found.
mysql-test/r/negation_elimination.result
View file @
419c20f1
...
...
@@ -375,6 +375,121 @@ a
13
14
15
# XOR (Note: XOR is negated by negating one of the operands)
# Should return 6,7
SELECT * FROM t1 WHERE ((a > 5) XOR (a > 7));
a
6
7
# Should return 0..5,8..19
SELECT * FROM t1 WHERE ((NOT (a > 5)) XOR (a > 7));
a
0
1
2
3
4
5
8
9
10
11
12
13
14
15
16
17
18
19
SELECT * FROM t1 WHERE ((a > 5) XOR (NOT (a > 7)));
a
0
1
2
3
4
5
8
9
10
11
12
13
14
15
16
17
18
19
SELECT * FROM t1 WHERE NOT ((a > 5) XOR (a > 7));
a
0
1
2
3
4
5
8
9
10
11
12
13
14
15
16
17
18
19
# Should return 6,7
SELECT * FROM t1 WHERE NOT ((NOT (a > 5)) XOR (a > 7));
a
6
7
SELECT * FROM t1 WHERE NOT ((a > 5) XOR (NOT (a > 7)));
a
6
7
# Should return 0..5,8..19
SELECT * FROM t1 WHERE NOT ((NOT (a > 5)) XOR (NOT (a > 7)));
a
0
1
2
3
4
5
8
9
10
11
12
13
14
15
16
17
18
19
# Should have empty result
SELECT * FROM t1 WHERE (NULL XOR (a > 7));
a
SELECT * FROM t1 WHERE NOT (NULL XOR (a > 7));
a
# Should be simplified to "...WHERE (a XOR a)
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NOT ((NOT a) XOR (a));
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 index NULL a 5 NULL 21 100.00 Using where; Using index
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` xor `test`.`t1`.`a`)
# Should be simplified to "...WHERE (a XOR a)
EXPLAIN EXTENDED SELECT * FROM t1 WHERE NOT (a XOR (NOT a));
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 index NULL a 5 NULL 21 100.00 Using where; Using index
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` xor `test`.`t1`.`a`)
# End XOR
delete from t1 where a > 3;
select a, not(not(a)) from t1;
a not(not(a))
...
...
mysql-test/t/negation_elimination.test
View file @
419c20f1
...
...
@@ -65,6 +65,35 @@ 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
)));
--
echo
# XOR (Note: XOR is negated by negating one of the operands)
--
echo
# Should return 6,7
SELECT
*
FROM
t1
WHERE
((
a
>
5
)
XOR
(
a
>
7
));
--
echo
# Should return 0..5,8..19
SELECT
*
FROM
t1
WHERE
((
NOT
(
a
>
5
))
XOR
(
a
>
7
));
SELECT
*
FROM
t1
WHERE
((
a
>
5
)
XOR
(
NOT
(
a
>
7
)));
SELECT
*
FROM
t1
WHERE
NOT
((
a
>
5
)
XOR
(
a
>
7
));
--
echo
# Should return 6,7
SELECT
*
FROM
t1
WHERE
NOT
((
NOT
(
a
>
5
))
XOR
(
a
>
7
));
SELECT
*
FROM
t1
WHERE
NOT
((
a
>
5
)
XOR
(
NOT
(
a
>
7
)));
--
echo
# Should return 0..5,8..19
SELECT
*
FROM
t1
WHERE
NOT
((
NOT
(
a
>
5
))
XOR
(
NOT
(
a
>
7
)));
--
echo
# Should have empty result
SELECT
*
FROM
t1
WHERE
(
NULL
XOR
(
a
>
7
));
SELECT
*
FROM
t1
WHERE
NOT
(
NULL
XOR
(
a
>
7
));
--
echo
# Should be simplified to "...WHERE (a XOR a)
EXPLAIN
EXTENDED
SELECT
*
FROM
t1
WHERE
NOT
((
NOT
a
)
XOR
(
a
));
--
echo
# Should be simplified to "...WHERE (a XOR a)
EXPLAIN
EXTENDED
SELECT
*
FROM
t1
WHERE
NOT
(
a
XOR
(
NOT
a
));
--
echo
# End XOR
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
));
...
...
sql/item_cmpfunc.cc
View file @
419c20f1
...
...
@@ -5065,23 +5065,21 @@ bool Item_func_like::turboBM_matches(const char* text, int text_len) const
very fast to use.
*/
longlong
Item_
cond
_xor
::
val_int
()
longlong
Item_
func
_xor
::
val_int
()
{
DBUG_ASSERT
(
fixed
==
1
);
List_iterator
<
Item
>
li
(
list
);
Item
*
item
;
int
result
=
0
;
null_value
=
0
;
while
((
item
=
li
++
))
int
result
=
0
;
null_value
=
false
;
for
(
uint
i
=
0
;
i
<
arg_count
;
i
++
)
{
result
^=
(
item
->
val_int
()
!=
0
);
if
(
item
->
null_value
)
result
^=
(
args
[
i
]
->
val_int
()
!=
0
);
if
(
args
[
i
]
->
null_value
)
{
null_value
=
1
;
null_value
=
true
;
return
0
;
}
}
return
(
longlong
)
result
;
return
result
;
}
/**
...
...
@@ -5122,6 +5120,33 @@ Item *Item_bool_rowready_func2::neg_transformer(THD *thd)
return
item
;
}
/**
XOR can be negated by negating one of the operands:
NOT (a XOR b) => (NOT a) XOR b
=> a XOR (NOT b)
@param thd Thread handle
@return New negated item
*/
Item
*
Item_func_xor
::
neg_transformer
(
THD
*
thd
)
{
Item
*
neg_operand
;
Item_func_xor
*
new_item
;
if
((
neg_operand
=
args
[
0
]
->
neg_transformer
(
thd
)))
// args[0] has neg_tranformer
new_item
=
new
(
thd
->
mem_root
)
Item_func_xor
(
neg_operand
,
args
[
1
]);
else
if
((
neg_operand
=
args
[
1
]
->
neg_transformer
(
thd
)))
// args[1] has neg_tranformer
new_item
=
new
(
thd
->
mem_root
)
Item_func_xor
(
args
[
0
],
neg_operand
);
else
{
neg_operand
=
new
(
thd
->
mem_root
)
Item_func_not
(
args
[
0
]);
new_item
=
new
(
thd
->
mem_root
)
Item_func_xor
(
neg_operand
,
args
[
1
]);
}
return
new_item
;
}
/**
a IS NULL -> a IS NOT NULL.
...
...
sql/item_cmpfunc.h
View file @
419c20f1
...
...
@@ -391,6 +391,22 @@ public:
}
};
/**
XOR inherits from Item_bool_func2 because it is not optimized yet.
Later, when XOR is optimized, it needs to inherit from
Item_cond instead. See WL#5800.
*/
class
Item_func_xor
:
public
Item_bool_func2
{
public:
Item_func_xor
(
Item
*
i1
,
Item
*
i2
)
:
Item_bool_func2
(
i1
,
i2
)
{}
enum
Functype
functype
()
const
{
return
XOR_FUNC
;
}
const
char
*
func_name
()
const
{
return
"xor"
;
}
longlong
val_int
();
void
top_level_item
()
{}
Item
*
neg_transformer
(
THD
*
thd
);
};
class
Item_func_not
:
public
Item_bool_func
{
public:
...
...
@@ -1817,45 +1833,6 @@ inline bool is_cond_or(Item *item)
return
(
cond_item
->
functype
()
==
Item_func
::
COND_OR_FUNC
);
}
/*
XOR is Item_cond, not an Item_int_func because we could like to
optimize (a XOR b) later on. It's low prio, though
*/
class
Item_cond_xor
:
public
Item_cond
{
public:
Item_cond_xor
(
Item
*
i1
,
Item
*
i2
)
:
Item_cond
(
i1
,
i2
)
{
/*
Items must be stored in args[] as well because this Item_cond is
treated as a FUNC_ITEM (see type()). I.e., users of it will get
it's children by calling arguments(), not argument_list(). This
is a temporary solution until XOR is optimized and treated like
a full Item_cond citizen.
*/
arg_count
=
2
;
args
=
tmp_arg
;
args
[
0
]
=
i1
;
args
[
1
]
=
i2
;
}
enum
Functype
functype
()
const
{
return
COND_XOR_FUNC
;
}
/* TODO: remove the next line when implementing XOR optimization */
enum
Type
type
()
const
{
return
FUNC_ITEM
;
}
longlong
val_int
();
const
char
*
func_name
()
const
{
return
"xor"
;
}
void
top_level_item
()
{}
/* Since child Items are stored in args[], Items cannot be added.
However, since Item_cond_xor is treated as a FUNC_ITEM (see
type()), the methods below should never be called.
*/
bool
add
(
Item
*
item
)
{
DBUG_ASSERT
(
FALSE
);
return
FALSE
;
}
bool
add_at_head
(
Item
*
item
)
{
DBUG_ASSERT
(
FALSE
);
return
FALSE
;
}
bool
add_at_head
(
List
<
Item
>
*
nlist
)
{
DBUG_ASSERT
(
FALSE
);
return
FALSE
;
}
void
copy_andor_arguments
(
THD
*
thd
,
Item_cond
*
item
)
{
DBUG_ASSERT
(
FALSE
);
}
};
/* Some useful inline functions */
inline
Item
*
and_conds
(
Item
*
a
,
Item
*
b
)
...
...
sql/item_func.h
View file @
419c20f1
...
...
@@ -44,7 +44,7 @@ public:
enum
Functype
{
UNKNOWN_FUNC
,
EQ_FUNC
,
EQUAL_FUNC
,
NE_FUNC
,
LT_FUNC
,
LE_FUNC
,
GE_FUNC
,
GT_FUNC
,
FT_FUNC
,
LIKE_FUNC
,
ISNULL_FUNC
,
ISNOTNULL_FUNC
,
COND_AND_FUNC
,
COND_OR_FUNC
,
COND_
XOR_FUNC
,
COND_AND_FUNC
,
COND_OR_FUNC
,
XOR_FUNC
,
BETWEEN
,
IN_FUNC
,
MULT_EQUAL_FUNC
,
INTERVAL_FUNC
,
ISNOTNULLTEST_FUNC
,
SP_EQUALS_FUNC
,
SP_DISJOINT_FUNC
,
SP_INTERSECTS_FUNC
,
...
...
sql/opt_subselect.cc
View file @
419c20f1
...
...
@@ -183,7 +183,7 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred);
static
bool
convert_subq_to_jtbm
(
JOIN
*
parent_join
,
Item_in_subselect
*
subq_pred
,
bool
*
remove
);
static
TABLE_LIST
*
alloc_join_nest
(
THD
*
thd
);
static
uint
get_tmp_table_rec_length
(
List
<
Item
>
&
item
s
);
static
uint
get_tmp_table_rec_length
(
Item
**
p_list
,
uint
element
s
);
static
double
get_tmp_table_lookup_cost
(
THD
*
thd
,
double
row_count
,
uint
row_size
);
static
double
get_tmp_table_write_cost
(
THD
*
thd
,
double
row_count
,
...
...
@@ -1806,8 +1806,11 @@ bool optimize_semijoin_nests(JOIN *join, table_map all_table_map)
sjm
->
materialization_cost
.
convert_from_cost
(
subjoin_read_time
);
sjm
->
rows
=
subjoin_out_rows
;
List
<
Item
>
&
right_expr_list
=
sj_nest
->
sj_subq_pred
->
unit
->
first_select
()
->
item_list
;
// Don't use the following list because it has "stale" items. use
// ref_pointer_array instead:
//
//List<Item> &right_expr_list=
// sj_nest->sj_subq_pred->unit->first_select()->item_list;
/*
Adjust output cardinality estimates. If the subquery has form
...
...
@@ -1825,17 +1828,20 @@ bool optimize_semijoin_nests(JOIN *join, table_map all_table_map)
See also get_post_group_estimate().
*/
SELECT_LEX
*
subq_select
=
sj_nest
->
sj_subq_pred
->
unit
->
first_select
();
{
for
(
uint
i
=
0
;
i
<
join
->
const_tables
+
sjm
->
tables
;
i
++
)
{
JOIN_TAB
*
tab
=
join
->
best_positions
[
i
].
table
;
join
->
map2table
[
tab
->
table
->
tablenr
]
=
tab
;
}
List_iterator
<
Item
>
it
(
right_expr_list
);
Item
*
item
;
//List_iterator<Item> it(right_expr_list);
Item
**
ref_array
=
subq_select
->
ref_pointer_array
;
Item
**
ref_array_end
=
ref_array
+
subq_select
->
item_list
.
elements
;
table_map
map
=
0
;
while
((
item
=
it
++
))
map
|=
item
->
used_tables
();
//while ((item= it++))
for
(;
ref_array
<
ref_array_end
;
ref_array
++
)
map
|=
(
*
ref_array
)
->
used_tables
();
map
=
map
&
~
PSEUDO_TABLE_BITS
;
Table_map_iterator
tm_it
(
map
);
int
tableno
;
...
...
@@ -1850,7 +1856,8 @@ bool optimize_semijoin_nests(JOIN *join, table_map all_table_map)
/*
Calculate temporary table parameters and usage costs
*/
uint
rowlen
=
get_tmp_table_rec_length
(
right_expr_list
);
uint
rowlen
=
get_tmp_table_rec_length
(
subq_select
->
ref_pointer_array
,
subq_select
->
item_list
.
elements
);
double
lookup_cost
=
get_tmp_table_lookup_cost
(
join
->
thd
,
subjoin_out_rows
,
rowlen
);
double
write_cost
=
get_tmp_table_write_cost
(
join
->
thd
,
...
...
@@ -1897,13 +1904,15 @@ bool optimize_semijoin_nests(JOIN *join, table_map all_table_map)
Length of the temptable record, in bytes
*/
static
uint
get_tmp_table_rec_length
(
List
<
Item
>
&
item
s
)
static
uint
get_tmp_table_rec_length
(
Item
**
p_items
,
uint
element
s
)
{
uint
len
=
0
;
Item
*
item
;
List_iterator
<
Item
>
it
(
items
);
while
((
item
=
it
++
))
//List_iterator<Item> it(items);
Item
**
p_item
;
for
(
p_item
=
p_items
;
p_item
<
p_items
+
elements
;
p_item
++
)
{
item
=
*
p_item
;
switch
(
item
->
result_type
())
{
case
REAL_RESULT
:
len
+=
sizeof
(
double
);
...
...
@@ -2908,19 +2917,23 @@ bool setup_sj_materialization_part1(JOIN_TAB *sjm_tab)
SJ_MATERIALIZATION_INFO
*
sjm
=
emb_sj_nest
->
sj_mat_info
;
THD
*
thd
=
tab
->
join
->
thd
;
/* First the calls come to the materialization function */
List
<
Item
>
&
item_list
=
emb_sj_nest
->
sj_subq_pred
->
unit
->
first_select
()
->
item_list
;
//
List<Item> &item_list= emb_sj_nest->sj_subq_pred->unit->first_select()->item_list;
DBUG_ASSERT
(
sjm
->
is_used
);
/*
Set up the table to write to, do as select_union::create_result_table does
*/
sjm
->
sjm_table_param
.
init
();
sjm
->
sjm_table_param
.
field_count
=
item_list
.
elements
;
sjm
->
sjm_table_param
.
bit_fields_as_long
=
TRUE
;
List_iterator
<
Item
>
it
(
item_list
);
Item
*
right_expr
;
while
((
right_expr
=
it
++
))
sjm
->
sjm_table_cols
.
push_back
(
right_expr
);
//List_iterator<Item> it(item_list);
SELECT_LEX
*
subq_select
=
emb_sj_nest
->
sj_subq_pred
->
unit
->
first_select
();
Item
**
p_item
=
subq_select
->
ref_pointer_array
;
Item
**
p_end
=
p_item
+
subq_select
->
item_list
.
elements
;
//while((right_expr= it++))
for
(;
p_item
!=
p_end
;
p_item
++
)
sjm
->
sjm_table_cols
.
push_back
(
*
p_item
);
sjm
->
sjm_table_param
.
field_count
=
subq_select
->
item_list
.
elements
;
if
(
!
(
sjm
->
table
=
create_tmp_table
(
thd
,
&
sjm
->
sjm_table_param
,
sjm
->
sjm_table_cols
,
(
ORDER
*
)
0
,
...
...
@@ -2952,8 +2965,8 @@ bool setup_sj_materialization_part2(JOIN_TAB *sjm_tab)
SJ_MATERIALIZATION_INFO
*
sjm
=
emb_sj_nest
->
sj_mat_info
;
THD
*
thd
=
tab
->
join
->
thd
;
uint
i
;
List
<
Item
>
&
item_list
=
emb_sj_nest
->
sj_subq_pred
->
unit
->
first_select
()
->
item_list
;
List_iterator
<
Item
>
it
(
item_list
);
//
List<Item> &item_list= emb_sj_nest->sj_subq_pred->unit->first_select()->item_list;
//
List_iterator<Item> it(item_list);
if
(
!
sjm
->
is_sj_scan
)
{
...
...
@@ -3069,11 +3082,13 @@ bool setup_sj_materialization_part2(JOIN_TAB *sjm_tab)
*/
sjm
->
copy_field
=
new
Copy_field
[
sjm
->
sjm_table_cols
.
elements
];
//it.rewind();
Item
**
p_item
=
emb_sj_nest
->
sj_subq_pred
->
unit
->
first_select
()
->
ref_pointer_array
;
for
(
uint
i
=
0
;
i
<
sjm
->
sjm_table_cols
.
elements
;
i
++
)
{
bool
dummy
;
Item_equal
*
item_eq
;
Item
*
item
=
(
it
++
)
->
real_item
();
//Item *item= (it++)->real_item();
Item
*
item
=
(
*
(
p_item
++
))
->
real_item
();
DBUG_ASSERT
(
item
->
type
()
==
Item
::
FIELD_ITEM
);
Field
*
copy_to
=
((
Item_field
*
)
item
)
->
field
;
/*
...
...
@@ -4513,7 +4528,9 @@ bool JOIN::choose_subquery_plan(table_map join_tables)
C. Compute execution costs.
*/
/* C.1 Compute the cost of the materialization strategy. */
uint
rowlen
=
get_tmp_table_rec_length
(
unit
->
first_select
()
->
item_list
);
//uint rowlen= get_tmp_table_rec_length(unit->first_select()->item_list);
uint
rowlen
=
get_tmp_table_rec_length
(
ref_pointer_array
,
select_lex
->
item_list
.
elements
);
/* The cost of writing one row into the temporary table. */
double
write_cost
=
get_tmp_table_write_cost
(
thd
,
inner_record_count_1
,
rowlen
);
...
...
sql/sql_yacc.yy
View file @
419c20f1
...
...
@@ -7172,7 +7172,7 @@ expr:
| expr XOR expr %prec XOR
{
/* XOR is a proprietary extension */
$$ = new (YYTHD->mem_root) Item_
cond
_xor($1, $3);
$$ = new (YYTHD->mem_root) Item_
func
_xor($1, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment