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
71f6ab7a
Commit
71f6ab7a
authored
Oct 09, 2004
by
igor@rurik.mysql.com
Browse files
Options
Browse Files
Download
Plain Diff
Merge for Item_equal.
parents
80d2d8d6
0dcc255b
Changes
22
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
1658 additions
and
138 deletions
+1658
-138
.bzrignore
.bzrignore
+2
-0
mysql-test/r/func_group.result
mysql-test/r/func_group.result
+1
-1
mysql-test/r/func_test.result
mysql-test/r/func_test.result
+1
-1
mysql-test/r/index_merge.result
mysql-test/r/index_merge.result
+2
-2
mysql-test/r/odbc.result
mysql-test/r/odbc.result
+1
-1
mysql-test/r/range.result
mysql-test/r/range.result
+17
-7
mysql-test/r/select.result
mysql-test/r/select.result
+1
-1
mysql-test/t/range.test
mysql-test/t/range.test
+4
-0
sql/item.cc
sql/item.cc
+26
-1
sql/item.h
sql/item.h
+28
-1
sql/item_cmpfunc.cc
sql/item_cmpfunc.cc
+325
-1
sql/item_cmpfunc.h
sql/item_cmpfunc.h
+144
-0
sql/item_func.cc
sql/item_func.cc
+39
-0
sql/item_func.h
sql/item_func.h
+5
-2
sql/item_row.cc
sql/item_row.cc
+12
-0
sql/item_row.h
sql/item_row.h
+1
-0
sql/item_strfunc.h
sql/item_strfunc.h
+8
-0
sql/opt_range.cc
sql/opt_range.cc
+121
-86
sql/opt_sum.cc
sql/opt_sum.cc
+15
-0
sql/sql_list.h
sql/sql_list.h
+39
-6
sql/sql_select.cc
sql/sql_select.cc
+864
-28
sql/sql_select.h
sql/sql_select.h
+2
-0
No files found.
.bzrignore
View file @
71f6ab7a
...
...
@@ -508,6 +508,7 @@ mysql-test/install_test_db
mysql-test/mysql-test-run
mysql-test/ndb/ndbcluster
mysql-test/r/*.reject
mysql-test/r/index_merge_load.result
mysql-test/r/rpl000001.eval
mysql-test/r/rpl000002.eval
mysql-test/r/rpl000014.eval
...
...
@@ -518,6 +519,7 @@ mysql-test/r/slave-running.eval
mysql-test/r/slave-stopped.eval
mysql-test/share/mysql
mysql-test/std_data/*.pem
mysql-test/t/index_merge.load
mysql-test/var/*
mysql.kdevprj
mysql.proj
...
...
mysql-test/r/func_group.result
View file @
71f6ab7a
...
...
@@ -476,7 +476,7 @@ CHI Los Angeles
explain
select max(a3) from t1 where a2 is null and a2 = 2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
noticed after reading const tables
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
select max(a3) from t1 where a2 is null and a2 = 2;
max(a3)
NULL
...
...
mysql-test/r/func_test.result
View file @
71f6ab7a
...
...
@@ -77,7 +77,7 @@ select * from t1 where 1 xor 1;
a
explain extended select * from t1 where 1 xor 1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
noticed after reading const tables
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (1 xor 1)
select - a from t1;
...
...
mysql-test/r/index_merge.result
View file @
71f6ab7a
...
...
@@ -76,13 +76,13 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t0 ALL i1,i2 NULL NULL NULL 1024 Using where
explain select * from t0 where key2 = 45 or key1 is null;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t0 r
ange i1,i2 i2 4 NULL 1 Using where
1 SIMPLE t0 r
ef i2 i2 4 const 1
explain select * from t0 where key2=10 or key3=3 or key4 <=> null;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t0 index_merge i2,i3,i4 i2,i3 4,4 NULL 2 Using union(i2,i3); Using where
explain select * from t0 where key2=10 or key3=3 or key4 is null;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t0 index_merge i2,i3
,i4 i2,i3 4,4 NULL 2 Using union(i2,i3);
Using where
1 SIMPLE t0 index_merge i2,i3
i2,i3 4,4 NULL 2
Using where
explain select key1 from t0 where (key1 <=> null) or (key2 < 5) or
(key3=10) or (key4 <=> null);
id select_type table type possible_keys key key_len ref rows Extra
...
...
mysql-test/r/odbc.result
View file @
71f6ab7a
...
...
@@ -12,5 +12,5 @@ select * from t1 where a is null;
a b
explain select * from t1 where b is null;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
noticed after reading const tables
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
drop table t1;
mysql-test/r/range.result
View file @
71f6ab7a
...
...
@@ -220,24 +220,22 @@ insert into t1 (x) values (1),(2),(3),(4),(5),(6),(7),(8),(9);
update t1 set y=x;
explain select * from t1, t1 t2 where t1.y = 2 and t2.x between 7 and t1.y+0;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref y y 5 const 1 Using where
1 SIMPLE t2 range x x 5 NULL 4 Using where
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
explain select * from t1, t1 t2 where t1.y = 2 and t2.x >= 7 and t2.x <= t1.y+0;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref y y 5 const 1 Using where
1 SIMPLE t2 range x x 5 NULL 4 Using where
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
explain select * from t1, t1 t2 where t1.y = 2 and t2.x between t1.y-1 and t1.y+1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref y y 5 const 1 Using where
1 SIMPLE t2
ALL x NULL NULL NULL 9 Range checked for each record (index map: 0x1)
1 SIMPLE t2
range x x 5 NULL 3 Using where
explain select * from t1, t1 t2 where t1.y = 2 and t2.x >= t1.y-1 and t2.x <= t1.y+1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref y y 5 const 1 Using where
1 SIMPLE t2
ALL x NULL NULL NULL 9 Range checked for each record (index map: 0x1)
1 SIMPLE t2
range x x 5 NULL 3 Using where
explain select * from t1, t1 t2 where t1.y = 2 and t2.x between 0 and t1.y;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref y y 5 const 1 Using where
1 SIMPLE t2
ALL x NULL NULL NULL 9
Using where
1 SIMPLE t2
range x x 5 NULL 2
Using where
explain select * from t1, t1 t2 where t1.y = 2 and t2.x >= 0 and t2.x <= t1.y;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref y y 5 const 1 Using where
...
...
@@ -415,14 +413,26 @@ count(*)
select count(*) from t2;
count(*)
1026
analyze table t1,t2;
Table Op Msg_type Msg_text
test.t1 analyze status OK
test.t2 analyze status Table is already up to date
explain select * from t1, t2 where t1.uid=t2.uid AND t1.uid > 0;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range uid_index uid_index 4 NULL 128 Using where
1 SIMPLE t2 ref uid_index uid_index 4 test.t1.uid 38
explain select * from t1, t2 where t1.uid=t2.uid AND t2.uid > 0;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range uid_index uid_index 4 NULL 128 Using where
1 SIMPLE t2 ref uid_index uid_index 4 test.t1.uid 38
explain select * from t1, t2 where t1.uid=t2.uid AND t1.uid != 0;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range uid_index uid_index 4 NULL 129 Using where
1 SIMPLE t2 ref uid_index uid_index 4 test.t1.uid 38
explain select * from t1, t2 where t1.uid=t2.uid AND t2.uid != 0;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range uid_index uid_index 4 NULL 129 Using where
1 SIMPLE t2 ref uid_index uid_index 4 test.t1.uid 38
select * from t1, t2 where t1.uid=t2.uid AND t1.uid > 0;
id name uid id name uid
1001 A 1 1001 A 1
...
...
mysql-test/r/select.result
View file @
71f6ab7a
...
...
@@ -1375,7 +1375,7 @@ id select_type table type possible_keys key key_len ref rows Extra
explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 and t4.companynr > 0;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where
1 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1
Using where
1 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1
explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr is null;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t4 ALL NULL NULL NULL NULL 12
...
...
mysql-test/t/range.test
View file @
71f6ab7a
...
...
@@ -378,8 +378,12 @@ insert into t2(id, uid, name) select id, uid, name from t1;
select
count
(
*
)
from
t1
;
select
count
(
*
)
from
t2
;
analyze
table
t1
,
t2
;
explain
select
*
from
t1
,
t2
where
t1
.
uid
=
t2
.
uid
AND
t1
.
uid
>
0
;
explain
select
*
from
t1
,
t2
where
t1
.
uid
=
t2
.
uid
AND
t2
.
uid
>
0
;
explain
select
*
from
t1
,
t2
where
t1
.
uid
=
t2
.
uid
AND
t1
.
uid
!=
0
;
explain
select
*
from
t1
,
t2
where
t1
.
uid
=
t2
.
uid
AND
t2
.
uid
!=
0
;
select
*
from
t1
,
t2
where
t1
.
uid
=
t2
.
uid
AND
t1
.
uid
>
0
;
select
*
from
t1
,
t2
where
t1
.
uid
=
t2
.
uid
AND
t1
.
uid
!=
0
;
...
...
sql/item.cc
View file @
71f6ab7a
...
...
@@ -408,6 +408,7 @@ bool DTCollation::aggregate(DTCollation &dt, bool superset_conversion)
Item_field
::
Item_field
(
Field
*
f
)
:
Item_ident
(
NullS
,
f
->
table_name
,
f
->
field_name
),
item_equal
(
0
),
have_privileges
(
0
),
any_privileges
(
0
)
{
set_field
(
f
);
...
...
@@ -418,6 +419,7 @@ Item_field::Item_field(Field *f)
Item_field
::
Item_field
(
THD
*
thd
,
Field
*
f
)
:
Item_ident
(
NullS
,
thd
->
strdup
(
f
->
table_name
),
thd
->
strdup
(
f
->
field_name
)),
item_equal
(
0
),
have_privileges
(
0
),
any_privileges
(
0
)
{
set_field
(
f
);
...
...
@@ -434,6 +436,7 @@ Item_field::Item_field(THD *thd, Item_field *item)
any_privileges
(
item
->
any_privileges
)
{
collation
.
set
(
DERIVATION_IMPLICIT
);
item_equal
=
item
->
item_equal
;
}
void
Item_field
::
set_field
(
Field
*
field_par
)
...
...
@@ -1582,7 +1585,29 @@ void Item_field::cleanup()
I.e. we can drop 'field'.
*/
field
=
result_field
=
0
;
DBUG_VOID_RETURN
;
}
/*
Find a field among specified multiple equalities
SYNOPSIS
find_item_equal()
cond_equal reference to list of multiple equalities where
the field (this object) is to be looked for
DESCRIPTION
The function first searches the field among multiple equalities
of the current level (in the cond_equal->current_level list).
If it fails, it continues searching in upper levels accessed
through a pointer cond_equal->upper_levels.
The search terminates as soon as a multiple equality containing
the field is found.
RETURN VALUES
First Item_equal containing the field, if success
0, otherwise
*/
}
void
Item
::
init_make_field
(
Send_field
*
tmp_field
,
...
...
sql/item.h
View file @
71f6ab7a
...
...
@@ -90,6 +90,7 @@ public:
};
typedef
bool
(
Item
::*
Item_processor
)(
byte
*
arg
);
typedef
Item
*
(
Item
::*
Item_transformer
)
(
byte
*
arg
);
class
Item
{
Item
(
const
Item
&
);
/* Prevent use of these */
...
...
@@ -261,8 +262,15 @@ public:
return
(
this
->*
processor
)(
arg
);
}
virtual
Item
*
transform
(
Item_transformer
transformer
,
byte
*
arg
)
{
return
(
this
->*
transformer
)(
arg
);
}
virtual
bool
remove_dependence_processor
(
byte
*
arg
)
{
return
0
;
}
virtual
bool
remove_fixed
(
byte
*
arg
)
{
fixed
=
0
;
return
0
;
}
virtual
Item
*
equal_fields_propagator
(
byte
*
arg
)
{
return
this
;
}
virtual
bool
replace_equal_field_processor
(
byte
*
arg
)
{
return
0
;
}
virtual
Item
*
this_item
()
{
return
this
;
}
/* For SPs mostly. */
virtual
Item
*
this_const_item
()
const
{
return
const_cast
<
Item
*>
(
this
);
}
/* For SPs mostly. */
...
...
@@ -440,6 +448,8 @@ public:
bool
any_privileges
,
bool
allocate_view_names
);
};
class
Item_equal
;
class
COND_EQUAL
;
class
Item_field
:
public
Item_ident
{
...
...
@@ -458,7 +468,8 @@ public:
Item_field
(
const
char
*
db_par
,
const
char
*
table_name_par
,
const
char
*
field_name_par
)
:
Item_ident
(
db_par
,
table_name_par
,
field_name_par
),
field
(
0
),
result_field
(
0
),
have_privileges
(
0
),
any_privileges
(
0
)
field
(
0
),
result_field
(
0
),
item_equal
(
0
),}
have_privileges
(
0
),
any_privileges
(
0
)
{
collation
.
set
(
DERIVATION_IMPLICIT
);
}
// Constructor need to process subselect with temporary tables (see Item)
Item_field
(
THD
*
thd
,
Item_field
*
item
);
...
...
@@ -498,6 +509,9 @@ public:
bool
is_null
()
{
return
field
->
is_null
();
}
Item
*
get_tmp_table_item
(
THD
*
thd
);
void
cleanup
();
Item_equal
*
find_item_equal
(
COND_EQUAL
*
cond_equal
);
Item
*
equal_fields_propagator
(
byte
*
arg
);
bool
replace_equal_field_processor
(
byte
*
arg
);
inline
uint32
max_disp_length
()
{
return
field
->
max_length
();
}
Item_field
*
filed_for_view_update
()
{
return
this
;
}
friend
class
Item_default_value
;
...
...
@@ -1173,6 +1187,19 @@ public:
return
arg
->
walk
(
processor
,
args
)
||
(
this
->*
processor
)(
args
);
}
/*
This method like the walk method traverses the item tree, but
at the same time it can replace some nodes in the tree
*/
Item
*
transform
(
Item_transformer
transformer
,
byte
*
args
)
{
Item
*
new_item
=
arg
->
transform
(
transformer
,
args
);
if
(
!
new_item
)
return
0
;
arg
=
new_item
;
return
(
this
->*
transformer
)(
args
);
}
};
class
Item_insert_value
:
public
Item_field
...
...
sql/item_cmpfunc.cc
View file @
71f6ab7a
...
...
@@ -256,7 +256,7 @@ void Item_bool_func2::fix_length_and_dec()
}
}
}
if
(
args
[
1
]
->
type
()
==
FIELD_ITEM
)
if
(
args
[
1
]
->
type
()
==
FIELD_ITEM
/* && !args[1]->const_item() */
)
{
Field
*
field
=
((
Item_field
*
)
args
[
1
])
->
field
;
if
(
field
->
store_for_compare
())
...
...
@@ -2008,6 +2008,44 @@ bool Item_cond::walk(Item_processor processor, byte *arg)
return
Item_func
::
walk
(
processor
,
arg
);
}
/*
Transform an Item_cond object with a transformer callback function
SYNOPSIS
transform()
transformer the transformer callback function to be applied to the nodes
of the tree of the object
arg parameter to be passed to the transformer
DESCRIPTION
The function recursively applies the transform method with the
same transformer to each member item of the codition list.
If the call of the method for a member item returns a new item
the old item is substituted for a new one.
After this the transform method is applied to the root node
of the Item_cond object.
RETURN VALUES
Item returned as the result of transformation of the root node
*/
Item
*
Item_cond
::
transform
(
Item_transformer
transformer
,
byte
*
arg
)
{
List_iterator
<
Item
>
li
(
list
);
Item
*
item
;
while
((
item
=
li
++
))
{
Item
*
new_item
=
item
->
transform
(
transformer
,
arg
);
if
(
!
new_item
)
return
0
;
if
(
new_item
!=
item
)
li
.
replace
(
new_item
);
}
return
Item_func
::
transform
(
transformer
,
arg
);
}
void
Item_cond
::
split_sum_func
(
Item
**
ref_pointer_array
,
List
<
Item
>
&
fields
)
{
List_iterator
<
Item
>
li
(
list
);
...
...
@@ -2854,3 +2892,289 @@ Item *Item_bool_rowready_func2::negated_item()
DBUG_ASSERT
(
0
);
return
0
;
}
Item_equal
::
Item_equal
(
Item_field
*
f1
,
Item_field
*
f2
)
:
Item_bool_func
(),
const_item
(
0
),
eval_item
(
0
),
cond_false
(
0
)
{
const_item_cache
=
0
;
fields
.
push_back
(
f1
);
fields
.
push_back
(
f2
);
}
Item_equal
::
Item_equal
(
Item
*
c
,
Item_field
*
f
)
:
Item_bool_func
(),
eval_item
(
0
),
cond_false
(
0
)
{
const_item_cache
=
0
;
fields
.
push_back
(
f
);
const_item
=
c
;
}
Item_equal
::
Item_equal
(
Item_equal
*
item_equal
)
:
Item_bool_func
(),
eval_item
(
0
),
cond_false
(
0
)
{
const_item_cache
=
0
;
List_iterator_fast
<
Item_field
>
li
(
item_equal
->
fields
);
Item_field
*
item
;
while
((
item
=
li
++
))
{
fields
.
push_back
(
item
);
}
const_item
=
item_equal
->
const_item
;
cond_false
=
item_equal
->
cond_false
;
}
void
Item_equal
::
add
(
Item
*
c
)
{
if
(
cond_false
)
return
;
if
(
!
const_item
)
{
const_item
=
c
;
return
;
}
Item_func_eq
*
func
=
new
Item_func_eq
(
c
,
const_item
);
func
->
set_cmp_func
();
cond_false
=
!
(
func
->
val_int
());
}
void
Item_equal
::
add
(
Item_field
*
f
)
{
fields
.
push_back
(
f
);
}
uint
Item_equal
::
members
()
{
uint
count
=
0
;
List_iterator_fast
<
Item_field
>
li
(
fields
);
Item_field
*
item
;
while
((
item
=
li
++
))
count
++
;
return
count
;
}
/*
Check whether a field is referred in the multiple equality
SYNOPSIS
contains()
field field whose occurence is to be checked
DESCRIPTION
The function checks whether field is occured in the Item_equal object
RETURN VALUES
1 if nultiple equality contains a reference to field
0 otherwise
*/
bool
Item_equal
::
contains
(
Field
*
field
)
{
List_iterator_fast
<
Item_field
>
it
(
fields
);
Item_field
*
item
;
while
((
item
=
it
++
))
{
if
(
field
->
eq
(
item
->
field
))
return
1
;
}
return
0
;
}
/*
Join members of another Item_equal object
SYNOPSIS
merge()
item multiple equality whose members are to be joined
DESCRIPTION
The function actually merges two multiple equalitis.
After this operation the Item_equal object additionally contains
the field items of another item of the type Item_equal.
If the optional constant items are not equal the cond_false flag is
set to 1.
RETURN VALUES
none
*/
void
Item_equal
::
merge
(
Item_equal
*
item
)
{
fields
.
concat
(
&
item
->
fields
);
Item
*
c
=
item
->
const_item
;
if
(
c
)
{
/*
The flag cond_false will be set to 1 after this, if
the multiple equality already contains a constant and its
value is not equal to the value of c.
*/
add
(
const_item
);
}
cond_false
|=
item
->
cond_false
;
}
/*
Order field items in multiple equality according to a sorting criteria
SYNOPSIS
sort()
cmp function to compare field item
arg context extra parameter for the cmp function
DESCRIPTION
The function perform ordering of the field items in the Item_equal
object according to the criteria determined by the cmp callback parameter.
If cmp(item_field1,item_field2,arg)<0 than item_field1 must be
placed after item_fiel2.
IMPLEMENTATION
The function sorts field items by the exchange sort algorithm.
The list of field items is looked through and whenever two neighboring
members follow in a wrong order they are swapped. This is performed
again and again until we get all members in a right order.
RETURN VALUES
None
*/
void
Item_equal
::
sort
(
Item_field_cmpfunc
cmp
,
void
*
arg
)
{
bool
swap
;
List_iterator
<
Item_field
>
it
(
fields
);
do
{
Item_field
*
item1
=
it
++
;
Item_field
**
ref1
=
it
.
ref
();
Item_field
*
item2
;
swap
=
FALSE
;
while
((
item2
=
it
++
))
{
Item_field
**
ref2
=
it
.
ref
();
if
(
cmp
(
item1
,
item2
,
arg
)
<
0
)
{
Item_field
*
item
=
*
ref1
;
*
ref1
=
*
ref2
;
*
ref2
=
item
;
swap
=
TRUE
;
}
else
{
item1
=
item2
;
ref1
=
ref2
;
}
}
it
.
rewind
();
}
while
(
swap
);
}
bool
Item_equal
::
fix_fields
(
THD
*
thd
,
TABLE_LIST
*
tables
,
Item
**
ref
)
{
List_iterator_fast
<
Item_field
>
li
(
fields
);
Item
*
item
;
not_null_tables_cache
=
used_tables_cache
=
0
;
const_item_cache
=
0
;
while
((
item
=
li
++
))
{
table_map
tmp_table_map
;
used_tables_cache
|=
item
->
used_tables
();
tmp_table_map
=
item
->
not_null_tables
();
not_null_tables_cache
|=
tmp_table_map
;
if
(
item
->
maybe_null
)
maybe_null
=
1
;
}
fix_length_and_dec
();
fixed
=
1
;
return
0
;
}
void
Item_equal
::
update_used_tables
()
{
List_iterator_fast
<
Item_field
>
li
(
fields
);
Item
*
item
;
not_null_tables_cache
=
used_tables_cache
=
0
;
if
((
const_item_cache
=
cond_false
))
return
;
while
((
item
=
li
++
))
{
item
->
update_used_tables
();
used_tables_cache
|=
item
->
used_tables
();
const_item_cache
&=
item
->
const_item
();
}
}
longlong
Item_equal
::
val_int
()
{
if
(
cond_false
)
return
0
;
List_iterator_fast
<
Item_field
>
it
(
fields
);
Item
*
item
=
const_item
?
const_item
:
it
++
;
if
((
null_value
=
item
->
null_value
))
return
0
;
eval_item
->
store_value
(
item
);
while
((
item
=
it
++
))
{
if
((
null_value
=
item
->
null_value
)
||
eval_item
->
cmp
(
item
))
return
0
;
}
return
1
;
}
void
Item_equal
::
fix_length_and_dec
()
{
Item
*
item
=
const_item
?
const_item
:
get_first
();
eval_item
=
cmp_item
::
get_comparator
(
item
);
if
(
item
->
result_type
()
==
STRING_RESULT
)
eval_item
->
cmp_charset
=
cmp_collation
.
collation
;
}
bool
Item_equal
::
walk
(
Item_processor
processor
,
byte
*
arg
)
{
List_iterator_fast
<
Item_field
>
it
(
fields
);
Item
*
item
;
while
((
item
=
it
++
))
if
(
item
->
walk
(
processor
,
arg
))
return
1
;
return
Item_func
::
walk
(
processor
,
arg
);
}
Item
*
Item_equal
::
transform
(
Item_transformer
transformer
,
byte
*
arg
)
{
List_iterator
<
Item_field
>
it
(
fields
);
Item
*
item
;
while
((
item
=
it
++
))
{
Item
*
new_item
=
item
->
transform
(
transformer
,
arg
);
if
(
!
new_item
)
return
0
;
if
(
new_item
!=
item
)
it
.
replace
((
Item_field
*
)
new_item
);
}
return
Item_func
::
transform
(
transformer
,
arg
);
}
void
Item_equal
::
print
(
String
*
str
)
{
str
->
append
(
func_name
());
str
->
append
(
'('
);
List_iterator_fast
<
Item_field
>
it
(
fields
);
Item
*
item
;
if
(
const_item
)
const_item
->
print
(
str
);
else
{
item
=
it
++
;
item
->
print
(
str
);
}
while
((
item
=
it
++
))
{
str
->
append
(
','
);
str
->
append
(
' '
);
item
->
print
(
str
);
}
str
->
append
(
')'
);
}
sql/item_cmpfunc.h
View file @
71f6ab7a
...
...
@@ -20,6 +20,9 @@
#ifdef __GNUC__
#pragma interface
/* gcc class implementation */
#endif
#ifdef __GNUC__
template
class
List_iterator_fast
<
Item_field
>;
#endif
extern
Item_result
item_cmp_type
(
Item_result
a
,
Item_result
b
);
class
Item_bool_func2
;
...
...
@@ -27,6 +30,8 @@ class Arg_comparator;
typedef
int
(
Arg_comparator
::*
arg_cmp_func
)();
typedef
int
(
*
Item_field_cmpfunc
)(
Item_field
*
f1
,
Item_field
*
f2
,
void
*
arg
);
class
Arg_comparator
:
public
Sql_alloc
{
Item
**
a
,
**
b
;
...
...
@@ -957,6 +962,7 @@ public:
Item_cond
(
List
<
Item
>
&
nlist
)
:
Item_bool_func
(),
list
(
nlist
),
abort_on_null
(
0
)
{}
bool
add
(
Item
*
item
)
{
return
list
.
push_back
(
item
);
}
void
add_at_head
(
List
<
Item
>
*
nlist
)
{
list
.
prepand
(
nlist
);
}
bool
fix_fields
(
THD
*
,
struct
st_table_list
*
,
Item
**
ref
);
enum
Type
type
()
const
{
return
COND_ITEM
;
}
...
...
@@ -969,13 +975,151 @@ public:
void
top_level_item
()
{
abort_on_null
=
1
;
}
void
copy_andor_arguments
(
THD
*
thd
,
Item_cond
*
item
);
bool
walk
(
Item_processor
processor
,
byte
*
arg
);
Item
*
transform
(
Item_transformer
transformer
,
byte
*
arg
);
void
neg_arguments
(
THD
*
thd
);
};
/*
The class Item_equal is used to represent conjuctions of equality
predicates of the form field1 = field2, and field=const in where
conditions and on expressions.
All equality predicates of the form field1=field2 contained in a
conjuction are substituted for a sequence of items of this class.
An item of this class Item_equal(f1,f2,...fk) respresents a
multiple equality f1=f2=...=fk.
If a conjuction contains predicates f1=f2 and f2=f3, a new item of
this class is created Item_equal(f1,f2,f3) representing the multiple
equality f1=f2=f3 that substitutes the above equality predicates in
the conjuction.
A conjuction of the predicates f2=f1 and f3=f1 and f3=f2 will be
substituted for the item representing the same multiple equality
f1=f2=f3.
An item Item_equal(f1,f2) can appear instead of a conjuction of
f2=f1 and f1=f2, or instead of just the predicate f1=f2.
An item of the class Item_equal inherites equalities from outer
conjunctive levels.
Suppose we have a where condition of the following form:
WHERE f1=f2 AND f3=f4 AND f3=f5 AND ... AND (...OR (f1=f3 AND ...)).
In this case:
f1=f2 will be substituted for Item_equal(f1,f2);
f3=f4 and f3=f5 will be substituted for Item_equal(f3,f4,f5);
f1=f3 will be substituted for Item_equal(f1,f2,f3,f4,f5);
An object of the class Item_equal can contain an optional constant
item c. Thenit represents a multiple equality of the form
c=f1=...=fk.
Objects of the class Item_equal are used for the following:
1. An object Item_equal(t1.f1,...,tk.fk) allows us to consider any
pair of tables ti and tj as joined by an equi-condition.
Thus it provide us with additional access paths from table to table.
2. An object Item_equal(t1.f1,...,tk.fk) is applied to deduce new
SARGable predicates:
f1=...=fk AND P(fi) => f1=...=fk AND P(fi) AND P(fj).
It also can give us additional index scans and can allow us to
improve selectivity estimates.
3. An object Item_equal(t1.f1,...,tk.fk) is used to optimize the
selected execution plan for the query: if table ti is accessed
before the table tj then in any predicate P in the where condition
the occurence of tj.fj is substituted for ti.fi. This can allow
an evaluation of the predicate at an earlier step.
When feature 1 is supported they say that join transitive closure
is employed.
When feature 2 is supported they say that search argument transitive
closure is employed.
Both features are usually supported by preprocessing original query and
adding additional predicates.
We do not just add predicates, we rather dynamically replace some
predicates that can not be used to access tables in the investigated
plan for those, obtained by substitution of some fields for equal fields,
that can be used.
*/
class
Item_equal
:
public
Item_bool_func
{
List
<
Item_field
>
fields
;
/* list of equal field items */
Item
*
const_item
;
/* optional constant item equal to fields items */
cmp_item
*
eval_item
;
bool
cond_false
;
DTCollation
cmp_collation
;
public:
inline
Item_equal
()
:
Item_bool_func
(),
const_item
(
0
),
eval_item
(
0
),
cond_false
(
0
)
{
const_item_cache
=
0
;}
Item_equal
(
Item_field
*
f1
,
Item_field
*
f2
);
Item_equal
(
Item
*
c
,
Item_field
*
f
);
Item_equal
(
Item_equal
*
item_equal
);
inline
Item
*
get_const
()
{
return
const_item
;
}
void
add
(
Item
*
c
);
void
add
(
Item_field
*
f
);
uint
members
();
bool
contains
(
Field
*
field
);
Item_field
*
get_first
()
{
return
fields
.
head
();
}
void
merge
(
Item_equal
*
item
);
enum
Functype
functype
()
const
{
return
MULT_EQUAL_FUNC
;
}
longlong
val_int
();
const
char
*
func_name
()
const
{
return
"multiple equal"
;
}
optimize_type
select_optimize
()
const
{
return
OPTIMIZE_EQUAL
;
}
void
sort
(
Item_field_cmpfunc
cmp
,
void
*
arg
);
friend
class
Item_equal_iterator
;
void
fix_length_and_dec
();
bool
fix_fields
(
THD
*
thd
,
TABLE_LIST
*
tables
,
Item
**
ref
);
void
update_used_tables
();
bool
walk
(
Item_processor
processor
,
byte
*
arg
);
Item
*
transform
(
Item_transformer
transformer
,
byte
*
arg
);
void
print
(
String
*
str
);
CHARSET_INFO
*
compare_collation
()
{
return
fields
.
head
()
->
collation
.
collation
;
}
};
class
COND_EQUAL
{
public:
uint
max_members
;
/* max number of members the current level
list and all lower level lists */
COND_EQUAL
*
upper_levels
;
/* multiple equalities of upper and levels */
List
<
Item_equal
>
current_level
;
/* list of multiple equalities of
the current and level */
COND_EQUAL
()
{
max_members
=
0
;
upper_levels
=
0
;
}
};
class
Item_equal_iterator
:
List_iterator_fast
<
Item_field
>
{
public:
inline
Item_equal_iterator
(
Item_equal
&
item_equal
)
:
List_iterator_fast
<
Item_field
>
(
item_equal
.
fields
)
{}
inline
Item_field
*
operator
++
(
int
)
{
Item_field
*
item
=
(
*
(
List_iterator_fast
<
Item_field
>
*
)
this
)
++
;
return
item
;
}
inline
void
rewind
(
void
)
{
List_iterator_fast
<
Item_field
>::
rewind
();
}
};
class
Item_cond_and
:
public
Item_cond
{
public:
COND_EQUAL
cond_equal
;
/* contains list of Item_equal objects for
the current and level and reference
to multiple equalities of upper and levels */
Item_cond_and
()
:
Item_cond
()
{}
Item_cond_and
(
Item
*
i1
,
Item
*
i2
)
:
Item_cond
(
i1
,
i2
)
{}
Item_cond_and
(
THD
*
thd
,
Item_cond_and
*
item
)
:
Item_cond
(
thd
,
item
)
{}
...
...
sql/item_func.cc
View file @
71f6ab7a
...
...
@@ -260,6 +260,45 @@ bool Item_func::walk (Item_processor processor, byte *argument)
return
(
this
->*
processor
)(
argument
);
}
/*
Transform an Item_func object with a transformer callback function
SYNOPSIS
transform()
transformer the transformer callback function to be applied to the nodes
of the tree of the object
argument parameter to be passed to the transformer
DESCRIPTION
The function recursively applies the transform method with the
same transformer to each argument the function.
If the call of the method for a member item returns a new item
the old item is substituted for a new one.
After this the transform method is applied to the root node
of the Item_func object.
RETURN VALUES
Item returned as the result of transformation of the root node
*/
Item
*
Item_func
::
transform
(
Item_transformer
transformer
,
byte
*
argument
)
{
if
(
arg_count
)
{
Item
**
arg
,
**
arg_end
;
for
(
arg
=
args
,
arg_end
=
args
+
arg_count
;
arg
!=
arg_end
;
arg
++
)
{
Item
*
new_item
=
(
*
arg
)
->
transform
(
transformer
,
argument
);
if
(
!
new_item
)
return
0
;
*
arg
=
new_item
;
}
}
return
(
this
->*
transformer
)(
argument
);
}
void
Item_func
::
split_sum_func
(
Item
**
ref_pointer_array
,
List
<
Item
>
&
fields
)
{
Item
**
arg
,
**
arg_end
;
...
...
sql/item_func.h
View file @
71f6ab7a
...
...
@@ -40,7 +40,8 @@ public:
enum
Functype
{
UNKNOWN_FUNC
,
EQ_FUNC
,
EQUAL_FUNC
,
NE_FUNC
,
LT_FUNC
,
LE_FUNC
,
GE_FUNC
,
GT_FUNC
,
FT_FUNC
,
LIKE_FUNC
,
NOTLIKE_FUNC
,
ISNULL_FUNC
,
ISNOTNULL_FUNC
,
COND_AND_FUNC
,
COND_OR_FUNC
,
COND_XOR_FUNC
,
BETWEEN
,
IN_FUNC
,
COND_AND_FUNC
,
COND_OR_FUNC
,
COND_XOR_FUNC
,
BETWEEN
,
IN_FUNC
,
MULT_EQUAL_FUNC
,
INTERVAL_FUNC
,
ISNOTNULLTEST_FUNC
,
SP_EQUALS_FUNC
,
SP_DISJOINT_FUNC
,
SP_INTERSECTS_FUNC
,
SP_TOUCHES_FUNC
,
SP_CROSSES_FUNC
,
SP_WITHIN_FUNC
,
...
...
@@ -50,7 +51,8 @@ public:
NOT_FUNC
,
NOT_ALL_FUNC
,
NOW_FUNC
,
TRIG_COND_FUNC
,
GUSERVAR_FUNC
};
enum
optimize_type
{
OPTIMIZE_NONE
,
OPTIMIZE_KEY
,
OPTIMIZE_OP
,
OPTIMIZE_NULL
};
enum
optimize_type
{
OPTIMIZE_NONE
,
OPTIMIZE_KEY
,
OPTIMIZE_OP
,
OPTIMIZE_NULL
,
OPTIMIZE_EQUAL
};
enum
Type
type
()
const
{
return
FUNC_ITEM
;
}
virtual
enum
Functype
functype
()
const
{
return
UNKNOWN_FUNC
;
}
Item_func
(
void
)
:
...
...
@@ -150,6 +152,7 @@ public:
bool
allow_superset_comversion
=
FALSE
);
bool
walk
(
Item_processor
processor
,
byte
*
arg
);
Item
*
transform
(
Item_transformer
transformer
,
byte
*
arg
);
};
...
...
sql/item_row.cc
View file @
71f6ab7a
...
...
@@ -145,6 +145,18 @@ bool Item_row::walk(Item_processor processor, byte *arg)
return
(
this
->*
processor
)(
arg
);
}
Item
*
Item_row
::
transform
(
Item_transformer
transformer
,
byte
*
arg
)
{
for
(
uint
i
=
0
;
i
<
arg_count
;
i
++
)
{
Item
*
new_item
=
items
[
i
]
->
transform
(
transformer
,
arg
);
if
(
!
new_item
)
return
0
;
items
[
i
]
=
new_item
;
}
return
(
this
->*
transformer
)(
arg
);
}
void
Item_row
::
bring_value
()
{
for
(
uint
i
=
0
;
i
<
arg_count
;
i
++
)
...
...
sql/item_row.h
View file @
71f6ab7a
...
...
@@ -65,6 +65,7 @@ public:
void
print
(
String
*
str
);
bool
walk
(
Item_processor
processor
,
byte
*
arg
);
Item
*
transform
(
Item_transformer
transformer
,
byte
*
arg
);
uint
cols
()
{
return
arg_count
;
}
Item
*
el
(
uint
i
)
{
return
items
[
i
];
}
...
...
sql/item_strfunc.h
View file @
71f6ab7a
...
...
@@ -428,6 +428,14 @@ public:
return
item
->
walk
(
processor
,
arg
)
||
Item_str_func
::
walk
(
processor
,
arg
);
}
Item
*
transform
(
Item_transformer
transformer
,
byte
*
arg
)
{
Item
*
new_item
=
item
->
transform
(
transformer
,
arg
);
if
(
!
new_item
)
return
0
;
item
=
new_item
;
return
Item_str_func
::
transform
(
transformer
,
arg
);
}
void
print
(
String
*
str
);
};
...
...
sql/opt_range.cc
View file @
71f6ab7a
...
...
@@ -3148,12 +3148,98 @@ QUICK_SELECT_I *TRP_ROR_UNION::make_quick(PARAM *param,
DBUG_RETURN
(
quick_roru
);
}
/****************************************************************************/
/*
Build a SEL_TREE for a simple predicate
SYNOPSIS
get_func_mm_tree()
param PARAM from SQL_SELECT::test_quick_select
cond_func item for the predicate
field field in the predicate
value constant in the predicate
cmp_type compare type for the field
RETURN
Pointer to thre built tree
*/
static
SEL_TREE
*
get_func_mm_tree
(
PARAM
*
param
,
Item_func
*
cond_func
,
Field
*
field
,
Item
*
value
,
Item_result
cmp_type
)
{
SEL_TREE
*
tree
=
0
;
DBUG_ENTER
(
"get_func_mm_tree"
);
switch
(
cond_func
->
functype
())
{
case
Item_func
:
:
NE_FUNC
:
tree
=
get_mm_parts
(
param
,
cond_func
,
field
,
Item_func
::
LT_FUNC
,
value
,
cmp_type
);
if
(
tree
)
{
tree
=
tree_or
(
param
,
tree
,
get_mm_parts
(
param
,
cond_func
,
field
,
Item_func
::
GT_FUNC
,
value
,
cmp_type
));
}
break
;
case
Item_func
:
:
BETWEEN
:
tree
=
get_mm_parts
(
param
,
cond_func
,
field
,
Item_func
::
GE_FUNC
,
cond_func
->
arguments
()[
1
],
cmp_type
);
if
(
tree
)
{
tree
=
tree_and
(
param
,
tree
,
get_mm_parts
(
param
,
cond_func
,
field
,
Item_func
::
LE_FUNC
,
cond_func
->
arguments
()[
2
],
cmp_type
));
}
break
;
case
Item_func
:
:
IN_FUNC
:
{
Item_func_in
*
func
=
(
Item_func_in
*
)
cond_func
;
tree
=
get_mm_parts
(
param
,
cond_func
,
field
,
Item_func
::
EQ_FUNC
,
func
->
arguments
()[
1
],
cmp_type
);
if
(
tree
)
{
Item
**
arg
,
**
end
;
for
(
arg
=
func
->
arguments
()
+
2
,
end
=
arg
+
func
->
argument_count
()
-
2
;
arg
<
end
;
arg
++
)
{
tree
=
tree_or
(
param
,
tree
,
get_mm_parts
(
param
,
cond_func
,
field
,
Item_func
::
EQ_FUNC
,
*
arg
,
cmp_type
));
}
}
break
;
}
default:
{
/*
Here the function for the following predicates are processed:
<, <=, =, >=, >, LIKE, IS NULL, IS NOT NULL.
If the predicate is of the form (value op field) it is handled
as the equivalent predicate (field rev_op value), e.g.
2 <= a is handled as a >= 2.
*/
Item_func
::
Functype
func_type
=
(
value
!=
cond_func
->
arguments
()[
0
])
?
cond_func
->
functype
()
:
((
Item_bool_func2
*
)
cond_func
)
->
rev_functype
();
tree
=
get_mm_parts
(
param
,
cond_func
,
field
,
func_type
,
value
,
cmp_type
);
}
}
DBUG_RETURN
(
tree
);
}
/* make a select tree of all keys in condition */
static
SEL_TREE
*
get_mm_tree
(
PARAM
*
param
,
COND
*
cond
)
{
SEL_TREE
*
tree
=
0
;
SEL_TREE
*
ftree
=
0
;
Item_field
*
field_item
=
0
;
Item
*
value
;
DBUG_ENTER
(
"get_mm_tree"
);
if
(
cond
->
type
()
==
Item
::
COND_ITEM
)
...
...
@@ -3201,9 +3287,12 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
DBUG_RETURN
(
new
SEL_TREE
(
SEL_TREE
::
IMPOSSIBLE
));
}
table_map
ref_tables
=
cond
->
used_tables
();
table_map
ref_tables
=
0
;
table_map
param_comp
=
~
(
param
->
prev_tables
|
param
->
read_tables
|
param
->
current_table
);
if
(
cond
->
type
()
!=
Item
::
FUNC_ITEM
)
{
// Should be a field
ref_tables
=
cond
->
used_tables
();
if
((
ref_tables
&
param
->
current_table
)
||
(
ref_tables
&
~
(
param
->
prev_tables
|
param
->
read_tables
)))
DBUG_RETURN
(
0
);
...
...
@@ -3214,80 +3303,42 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
if
(
cond_func
->
select_optimize
()
==
Item_func
::
OPTIMIZE_NONE
)
DBUG_RETURN
(
0
);
// Can't be calculated
param
->
cond
=
cond
;
if
(
cond_func
->
functype
()
==
Item_func
::
BETWEEN
)
switch
(
cond_func
->
functype
())
{
case
Item_func
:
:
BETWEEN
:
if
(
cond_func
->
arguments
()[
0
]
->
type
()
!=
Item
::
FIELD_ITEM
)
DBUG_RETURN
(
0
);
field_item
=
(
Item_field
*
)
(
cond_func
->
arguments
()[
0
]);
value
=
NULL
;
break
;
case
Item_func
:
:
IN_FUNC
:
{
if
(
cond_func
->
arguments
()[
0
]
->
type
()
==
Item
::
FIELD_ITEM
)
{
Field
*
field
=
((
Item_field
*
)
(
cond_func
->
arguments
()[
0
]))
->
field
;
Item_result
cmp_type
=
field
->
cmp_type
();
DBUG_RETURN
(
tree_and
(
param
,
get_mm_parts
(
param
,
cond_func
,
field
,
Item_func
::
GE_FUNC
,
cond_func
->
arguments
()[
1
],
cmp_type
),
get_mm_parts
(
param
,
cond_func
,
field
,
Item_func
::
LE_FUNC
,
cond_func
->
arguments
()[
2
],
cmp_type
)));
}
DBUG_RETURN
(
0
);
}
if
(
cond_func
->
functype
()
==
Item_func
::
IN_FUNC
)
{
// COND OR
Item_func_in
*
func
=
(
Item_func_in
*
)
cond_func
;
if
(
func
->
key_item
()
->
type
()
==
Item
::
FIELD_ITEM
)
if
(
func
->
key_item
()
->
type
()
!=
Item
::
FIELD_ITEM
)
DBUG_RETURN
(
0
);
field_item
=
(
Item_field
*
)
(
func
->
key_item
());
value
=
NULL
;
break
;
}
case
Item_func
:
:
MULT_EQUAL_FUNC
:
{
Item_equal
*
item_equal
=
(
Item_equal
*
)
cond
;
if
(
!
(
value
=
item_equal
->
get_const
()))
DBUG_RETURN
(
0
);
Item_equal_iterator
it
(
*
item_equal
);
ref_tables
=
value
->
used_tables
();
while
((
field_item
=
it
++
))
{
Field
*
field
=
((
Item_field
*
)
(
func
->
key_item
()))
->
field
;
Item_result
cmp_type
=
field
->
cmp_type
();
tree
=
get_mm_parts
(
param
,
cond_func
,
field
,
Item_func
::
EQ_FUNC
,
func
->
arguments
()[
1
],
cmp_type
);
if
(
!
tree
)
DBUG_RETURN
(
tree
);
// Not key field
for
(
uint
i
=
2
;
i
<
func
->
argument_count
();
i
++
)
Field
*
field
=
field_item
->
field
;
Item_result
cmp_type
=
field
->
cmp_type
();
if
(
!
((
ref_tables
|
field
->
table
->
map
)
&
param_comp
))
{
SEL_TREE
*
new_tree
=
get_mm_parts
(
param
,
cond_func
,
field
,
Item_func
::
EQ_FUNC
,
func
->
arguments
()[
i
],
cmp_type
);
tree
=
tree_or
(
param
,
tree
,
new_tree
);
tree
=
get_mm_parts
(
param
,
cond
,
field
,
Item_func
::
EQ_FUNC
,
value
,
cmp_type
);
ftree
=
!
ftree
?
tree
:
tree_and
(
param
,
ftree
,
tree
);
}
DBUG_RETURN
(
tree
);
}
DBUG_RETURN
(
0
);
// Can't optimize this IN
}
if
(
ref_tables
&
~
(
param
->
prev_tables
|
param
->
read_tables
|
param
->
current_table
))
DBUG_RETURN
(
0
);
// Can't be calculated yet
if
(
!
(
ref_tables
&
param
->
current_table
))
DBUG_RETURN
(
new
SEL_TREE
(
SEL_TREE
::
MAYBE
));
// This may be FALSE or TRUE
/* check field op const */
/* btw, ft_func's arguments()[0] isn't FIELD_ITEM. SerG*/
if
(
cond_func
->
arguments
()[
0
]
->
type
()
==
Item
::
FIELD_ITEM
)
{
tree
=
get_mm_parts
(
param
,
cond_func
,
((
Item_field
*
)
(
cond_func
->
arguments
()[
0
]))
->
field
,
cond_func
->
functype
(),
cond_func
->
arg_count
>
1
?
cond_func
->
arguments
()[
1
]
:
0
,
((
Item_field
*
)
(
cond_func
->
arguments
()[
0
]))
->
field
->
cmp_type
());
}
/* check const op field */
if
(
!
tree
&&
cond_func
->
have_rev_func
()
&&
cond_func
->
arguments
()[
1
]
->
type
()
==
Item
::
FIELD_ITEM
)
{
DBUG_RETURN
(
get_mm_parts
(
param
,
cond_func
,
((
Item_field
*
)
(
cond_func
->
arguments
()[
1
]))
->
field
,
((
Item_bool_func2
*
)
cond_func
)
->
rev_functype
(),
cond_func
->
arguments
()[
0
],
((
Item_field
*
)
(
cond_func
->
arguments
()[
1
]))
->
field
->
cmp_type
()
));
}
DBUG_RETURN
(
tree
);
DBUG_RETURN
(
ftree
);
}
...
...
@@ -3296,17 +3347,10 @@ get_mm_parts(PARAM *param, COND *cond_func, Field *field,
Item_func
::
Functype
type
,
Item
*
value
,
Item_result
cmp_type
)
{
bool
ne_func
=
FALSE
;
DBUG_ENTER
(
"get_mm_parts"
);
if
(
field
->
table
!=
param
->
table
)
DBUG_RETURN
(
0
);
if
(
type
==
Item_func
::
NE_FUNC
)
{
ne_func
=
TRUE
;
type
=
Item_func
::
LT_FUNC
;
}
KEY_PART
*
key_part
=
param
->
key_parts
;
KEY_PART
*
end
=
param
->
key_parts_end
;
SEL_TREE
*
tree
=
0
;
...
...
@@ -3344,15 +3388,6 @@ get_mm_parts(PARAM *param, COND *cond_func, Field *field,
}
}
if
(
ne_func
)
{
SEL_TREE
*
tree2
=
get_mm_parts
(
param
,
cond_func
,
field
,
Item_func
::
GT_FUNC
,
value
,
cmp_type
);
if
(
tree2
)
tree
=
tree_or
(
param
,
tree
,
tree2
);
}
DBUG_RETURN
(
tree
);
}
...
...
sql/opt_sum.cc
View file @
71f6ab7a
...
...
@@ -341,6 +341,18 @@ static bool simple_pred(Item_func *func_item, Item **args, bool *inv_order)
Item
*
item
;
*
inv_order
=
0
;
switch
(
func_item
->
argument_count
())
{
case
0
:
/* MULT_EQUAL_FUNC */
{
Item_equal
*
item_equal
=
(
Item_equal
*
)
func_item
;
Item_equal_iterator
it
(
*
item_equal
);
args
[
0
]
=
it
++
;
if
(
it
++
)
return
0
;
if
(
!
(
args
[
1
]
=
item_equal
->
get_const
()))
return
0
;
}
break
;
case
1
:
/* field IS NULL */
item
=
func_item
->
arguments
()[
0
];
...
...
@@ -481,6 +493,9 @@ static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo,
case
Item_func
:
:
BETWEEN
:
between
=
1
;
break
;
case
Item_func
:
:
MULT_EQUAL_FUNC
:
eq_type
=
1
;
break
;
default:
return
0
;
// Can't optimize function
}
...
...
sql/sql_list.h
View file @
71f6ab7a
...
...
@@ -127,10 +127,12 @@ public:
void
remove
(
list_node
**
prev
)
{
list_node
*
node
=
(
*
prev
)
->
next
;
delete
*
prev
;
*
prev
=
node
;
if
(
!--
elements
)
last
=
&
first
;
else
if
(
last
==
&
(
*
prev
)
->
next
)
last
=
prev
;
delete
*
prev
;
*
prev
=
node
;
}
inline
void
*
pop
(
void
)
{
...
...
@@ -143,9 +145,36 @@ public:
}
inline
void
concat
(
base_list
*
list
)
{
*
last
=
list
->
first
;
last
=
list
->
last
;
elements
+=
list
->
elements
;
if
(
!
list
->
is_empty
())
{
*
last
=
list
->
first
;
last
=
list
->
last
;
elements
+=
list
->
elements
;
}
}
inline
void
disjoin
(
base_list
*
list
)
{
list_node
**
prev
=
&
first
;
list_node
*
node
=
first
;
list_node
*
list_first
=
list
->
first
;
elements
=
0
;
while
(
node
&&
node
!=
list_first
)
{
prev
=
&
node
->
next
;
node
=
node
->
next
;
elements
++
;
}
*
prev
=
*
last
;
last
=
prev
;
}
inline
void
prepand
(
base_list
*
list
)
{
if
(
!
list
->
is_empty
())
{
*
list
->
last
=
first
;
first
=
list
->
first
;
elements
+=
list
->
elements
;
}
}
inline
list_node
*
last_node
()
{
return
*
last
;
}
inline
list_node
*
first_node
()
{
return
first
;}
...
...
@@ -257,6 +286,9 @@ public:
inline
T
*
head
()
{
return
(
T
*
)
base_list
::
head
();
}
inline
T
**
head_ref
()
{
return
(
T
**
)
base_list
::
head_ref
();
}
inline
T
*
pop
()
{
return
(
T
*
)
base_list
::
pop
();
}
inline
void
concat
(
List
<
T
>
*
list
)
{
base_list
::
concat
(
list
);
}
inline
void
disjoin
(
List
<
T
>
*
list
)
{
base_list
::
disjoin
(
list
);
}
inline
void
prepand
(
List
<
T
>
*
list
)
{
base_list
::
prepand
(
list
);
}
void
delete_elements
(
void
)
{
list_node
*
element
,
*
next
;
...
...
@@ -267,7 +299,6 @@ public:
}
empty
();
}
inline
void
concat
(
List
<
T
>
*
list
)
{
base_list
::
concat
(
list
);
}
};
...
...
@@ -278,6 +309,8 @@ public:
inline
T
*
operator
++
(
int
)
{
return
(
T
*
)
base_list_iterator
::
next
();
}
inline
T
*
replace
(
T
*
a
)
{
return
(
T
*
)
base_list_iterator
::
replace
(
a
);
}
inline
T
*
replace
(
List
<
T
>
&
a
)
{
return
(
T
*
)
base_list_iterator
::
replace
(
a
);
}
inline
void
rewind
(
void
)
{
base_list_iterator
::
rewind
();
}
inline
void
remove
()
{
base_list_iterator
::
remove
();
}
inline
void
after
(
T
*
a
)
{
base_list_iterator
::
after
(
a
);
}
inline
T
**
ref
(
void
)
{
return
(
T
**
)
base_list_iterator
::
ref
();
}
};
...
...
sql/sql_select.cc
View file @
71f6ab7a
This diff is collapsed.
Click to expand it.
sql/sql_select.h
View file @
71f6ab7a
...
...
@@ -222,6 +222,7 @@ class JOIN :public Sql_alloc
Item
*
conds_history
;
// store WHERE for explain
TABLE_LIST
*
tables_list
;
//hold 'tables' parameter of mysql_select
List
<
TABLE_LIST
>
*
join_list
;
// list of joined tables in reverse order
COND_EQUAL
*
cond_equal
;
SQL_SELECT
*
select
;
//created in optimisation phase
JOIN_TAB
*
return_tab
;
//used only for outer joins
Item
**
ref_pointer_array
;
//used pointer reference for this select
...
...
@@ -284,6 +285,7 @@ class JOIN :public Sql_alloc
ref_pointer_array_size
=
0
;
zero_result_cause
=
0
;
optimized
=
0
;
cond_equal
=
0
;
fields_list
=
fields_arg
;
bzero
((
char
*
)
&
keyuse
,
sizeof
(
keyuse
));
...
...
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