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
be27811f
Commit
be27811f
authored
Nov 26, 2003
by
igor@rurik.mysql.com
Browse files
Options
Browse Files
Download
Plain Diff
Post-merge after itroducing Item_equal
parents
d8603604
3938ac54
Changes
14
Show whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
1397 additions
and
113 deletions
+1397
-113
sql/item.cc
sql/item.cc
+46
-1
sql/item.h
sql/item.h
+25
-1
sql/item_cmpfunc.cc
sql/item_cmpfunc.cc
+231
-2
sql/item_cmpfunc.h
sql/item_cmpfunc.h
+63
-0
sql/item_func.cc
sql/item_func.cc
+34
-0
sql/item_func.h
sql/item_func.h
+6
-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
+150
-75
sql/opt_sum.cc
sql/opt_sum.cc
+15
-0
sql/sql_list.h
sql/sql_list.h
+29
-6
sql/sql_select.cc
sql/sql_select.cc
+775
-26
sql/sql_select.h
sql/sql_select.h
+2
-0
No files found.
sql/item.cc
View file @
be27811f
...
@@ -299,7 +299,8 @@ bool DTCollation::aggregate(DTCollation &dt)
...
@@ -299,7 +299,8 @@ bool DTCollation::aggregate(DTCollation &dt)
return
0
;
return
0
;
}
}
Item_field
::
Item_field
(
Field
*
f
)
:
Item_ident
(
NullS
,
f
->
table_name
,
f
->
field_name
)
Item_field
::
Item_field
(
Field
*
f
)
:
Item_ident
(
NullS
,
f
->
table_name
,
f
->
field_name
),
item_equal
(
0
)
{
{
set_field
(
f
);
set_field
(
f
);
collation
.
set
(
DERIVATION_IMPLICIT
);
collation
.
set
(
DERIVATION_IMPLICIT
);
...
@@ -313,6 +314,7 @@ Item_field::Item_field(THD *thd, Item_field &item)
...
@@ -313,6 +314,7 @@ Item_field::Item_field(THD *thd, Item_field &item)
result_field
(
item
.
result_field
)
result_field
(
item
.
result_field
)
{
{
collation
.
set
(
DERIVATION_IMPLICIT
);
collation
.
set
(
DERIVATION_IMPLICIT
);
item_equal
=
item
.
item_equal
;
}
}
void
Item_field
::
set_field
(
Field
*
field_par
)
void
Item_field
::
set_field
(
Field
*
field_par
)
...
@@ -969,6 +971,49 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
...
@@ -969,6 +971,49 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
return
0
;
return
0
;
}
}
Item_equal
*
Item_field
::
find_item_equal
(
COND_EQUAL
*
cond_equal
)
{
Item_equal
*
item
=
0
;
while
(
cond_equal
)
{
List_iterator_fast
<
Item_equal
>
li
(
cond_equal
->
current_level
);
while
((
item
=
li
++
))
{
if
(
item
->
contains
(
field
))
return
item
;
}
cond_equal
=
cond_equal
->
parent_level
;
}
return
item
;
}
Item
*
Item_field
::
equal_fields_propagator
(
byte
*
arg
)
{
COND_EQUAL
*
cond_equal
=
(
COND_EQUAL
*
)
arg
;
item_equal
=
find_item_equal
(
cond_equal
);
Item
*
item
=
0
;
if
(
item_equal
)
item
=
item_equal
->
get_const
();
if
(
item
)
item
->
fixed
=
0
;
else
item
=
this
;
return
item
;
}
bool
Item_field
::
replace_equal_field_processor
(
byte
*
arg
)
{
if
(
item_equal
)
{
Item_field
*
subst
=
item_equal
->
get_first
();
if
(
subst
&&
!
field
->
eq
(
subst
->
field
))
{
field
=
subst
->
field
;
return
0
;
}
}
return
0
;
}
void
Item
::
init_make_field
(
Send_field
*
tmp_field
,
void
Item
::
init_make_field
(
Send_field
*
tmp_field
,
enum
enum_field_types
field_type
)
enum
enum_field_types
field_type
)
...
...
sql/item.h
View file @
be27811f
...
@@ -83,6 +83,7 @@ public:
...
@@ -83,6 +83,7 @@ public:
};
};
typedef
bool
(
Item
::*
Item_processor
)(
byte
*
arg
);
typedef
bool
(
Item
::*
Item_processor
)(
byte
*
arg
);
typedef
Item
*
(
Item
::*
Item_calculator
)
(
byte
*
arg
);
class
Item
{
class
Item
{
Item
(
const
Item
&
);
/* Prevent use of these */
Item
(
const
Item
&
);
/* Prevent use of these */
...
@@ -201,8 +202,15 @@ public:
...
@@ -201,8 +202,15 @@ public:
return
(
this
->*
processor
)(
arg
);
return
(
this
->*
processor
)(
arg
);
}
}
virtual
Item
*
traverse
(
Item_calculator
calculator
,
byte
*
arg
)
{
return
(
this
->*
calculator
)(
arg
);
}
virtual
bool
remove_dependence_processor
(
byte
*
arg
)
{
return
0
;
}
virtual
bool
remove_dependence_processor
(
byte
*
arg
)
{
return
0
;
}
virtual
bool
remove_fixed
(
byte
*
arg
)
{
fixed
=
0
;
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_item
()
{
return
this
;
}
/* For SPs mostly. */
virtual
Item
*
this_const_item
()
const
{
return
const_cast
<
Item
*>
(
this
);
}
/* For SPs mostly. */
virtual
Item
*
this_const_item
()
const
{
return
const_cast
<
Item
*>
(
this
);
}
/* For SPs mostly. */
...
@@ -334,17 +342,21 @@ public:
...
@@ -334,17 +342,21 @@ public:
bool
remove_dependence_processor
(
byte
*
arg
);
bool
remove_dependence_processor
(
byte
*
arg
);
};
};
class
Item_equal
;
class
COND_EQUAL
;
class
Item_field
:
public
Item_ident
class
Item_field
:
public
Item_ident
{
{
void
set_field
(
Field
*
field
);
void
set_field
(
Field
*
field
);
public:
public:
Field
*
field
,
*
result_field
;
Field
*
field
,
*
result_field
;
Item_equal
*
item_equal
;
// Item_field() {}
// Item_field() {}
Item_field
(
const
char
*
db_par
,
const
char
*
table_name_par
,
Item_field
(
const
char
*
db_par
,
const
char
*
table_name_par
,
const
char
*
field_name_par
)
const
char
*
field_name_par
)
:
Item_ident
(
db_par
,
table_name_par
,
field_name_par
),
field
(
0
),
result_field
(
0
)
:
Item_ident
(
db_par
,
table_name_par
,
field_name_par
),
field
(
0
),
result_field
(
0
),
item_equal
(
0
)
{
collation
.
set
(
DERIVATION_IMPLICIT
);
}
{
collation
.
set
(
DERIVATION_IMPLICIT
);
}
// Constructor need to process subselect with temporary tables (see Item)
// Constructor need to process subselect with temporary tables (see Item)
Item_field
(
THD
*
thd
,
Item_field
&
item
);
Item_field
(
THD
*
thd
,
Item_field
&
item
);
...
@@ -378,6 +390,9 @@ public:
...
@@ -378,6 +390,9 @@ public:
bool
get_time
(
TIME
*
ltime
);
bool
get_time
(
TIME
*
ltime
);
bool
is_null
()
{
return
field
->
is_null
();
}
bool
is_null
()
{
return
field
->
is_null
();
}
Item
*
get_tmp_table_item
(
THD
*
thd
);
Item
*
get_tmp_table_item
(
THD
*
thd
);
Item_equal
*
find_item_equal
(
COND_EQUAL
*
cond_equal
);
Item
*
equal_fields_propagator
(
byte
*
arg
);
bool
replace_equal_field_processor
(
byte
*
arg
);
friend
class
Item_default_value
;
friend
class
Item_default_value
;
friend
class
Item_insert_value
;
friend
class
Item_insert_value
;
};
};
...
@@ -920,6 +935,15 @@ public:
...
@@ -920,6 +935,15 @@ public:
return
arg
->
walk
(
processor
,
args
)
||
return
arg
->
walk
(
processor
,
args
)
||
(
this
->*
processor
)(
args
);
(
this
->*
processor
)(
args
);
}
}
Item
*
traverse
(
Item_calculator
calculator
,
byte
*
args
)
{
Item
*
new_item
=
arg
->
traverse
(
calculator
,
args
);
if
(
!
new_item
)
return
0
;
arg
=
new_item
;
return
(
this
->*
calculator
)(
args
);
}
};
};
class
Item_insert_value
:
public
Item_field
class
Item_insert_value
:
public
Item_field
...
...
sql/item_cmpfunc.cc
View file @
be27811f
...
@@ -225,7 +225,7 @@ void Item_bool_func2::fix_length_and_dec()
...
@@ -225,7 +225,7 @@ void Item_bool_func2::fix_length_and_dec()
}
}
// Make a special case of compare with fields to get nicer DATE comparisons
// Make a special case of compare with fields to get nicer DATE comparisons
if
(
args
[
0
]
->
type
()
==
FIELD_ITEM
)
if
(
args
[
0
]
->
type
()
==
FIELD_ITEM
&&
!
args
[
0
]
->
const_item
()
)
{
{
Field
*
field
=
((
Item_field
*
)
args
[
0
])
->
field
;
Field
*
field
=
((
Item_field
*
)
args
[
0
])
->
field
;
if
(
field
->
store_for_compare
())
if
(
field
->
store_for_compare
())
...
@@ -238,7 +238,7 @@ void Item_bool_func2::fix_length_and_dec()
...
@@ -238,7 +238,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
;
Field
*
field
=
((
Item_field
*
)
args
[
1
])
->
field
;
if
(
field
->
store_for_compare
())
if
(
field
->
store_for_compare
())
...
@@ -1712,6 +1712,21 @@ bool Item_cond::walk(Item_processor processor, byte *arg)
...
@@ -1712,6 +1712,21 @@ bool Item_cond::walk(Item_processor processor, byte *arg)
return
Item_func
::
walk
(
processor
,
arg
);
return
Item_func
::
walk
(
processor
,
arg
);
}
}
Item
*
Item_cond
::
traverse
(
Item_calculator
calculator
,
byte
*
arg
)
{
List_iterator
<
Item
>
li
(
list
);
Item
*
item
;
while
((
item
=
li
++
))
{
Item
*
new_item
=
item
->
traverse
(
calculator
,
arg
);
if
(
!
new_item
)
return
0
;
if
(
new_item
!=
item
)
li
.
replace
(
new_item
);
}
return
Item_func
::
traverse
(
calculator
,
arg
);
}
void
Item_cond
::
split_sum_func
(
Item
**
ref_pointer_array
,
List
<
Item
>
&
fields
)
void
Item_cond
::
split_sum_func
(
Item
**
ref_pointer_array
,
List
<
Item
>
&
fields
)
{
{
List_iterator
<
Item
>
li
(
list
);
List_iterator
<
Item
>
li
(
list
);
...
@@ -2499,3 +2514,217 @@ Item *Item_cond_or::neg_transformer() /* NOT(a OR b OR ...) -> */
...
@@ -2499,3 +2514,217 @@ Item *Item_cond_or::neg_transformer() /* NOT(a OR b OR ...) -> */
neg_arguments
();
neg_arguments
();
return
new
Item_cond_and
(
list
);
return
new
Item_cond_and
(
list
);
}
}
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
);
}
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
;
}
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
;
}
void
Item_equal
::
sort
(
void
*
table_join_idx
)
{
bool
swap
;
void
**
idx
=
(
void
**
)
table_join_idx
;
List_iterator
<
Item_field
>
it
(
fields
);
do
{
Item_field
*
item1
=
it
++
;
Item_field
**
ref1
=
it
.
ref
();
Item_field
*
item2
;
Item_field
**
ref2
;
if
(
!
item1
)
break
;
swap
=
FALSE
;
while
((
item2
=
it
++
))
{
ref2
=
it
.
ref
();
if
(
idx
[
item1
->
field
->
table
->
tablenr
]
>
idx
[
item2
->
field
->
table
->
tablenr
])
{
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
;
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
::
traverse
(
Item_calculator
calculator
,
byte
*
arg
)
{
List_iterator
<
Item_field
>
it
(
fields
);
Item
*
item
;
while
((
item
=
it
++
))
{
Item
*
new_item
=
item
->
traverse
(
calculator
,
arg
);
if
(
!
new_item
)
return
0
;
if
(
new_item
!=
item
)
it
.
replace
((
Item_field
*
)
new_item
);
}
return
Item_func
::
traverse
(
calculator
,
arg
);
}
void
Item_equal
::
print
(
String
*
str
)
{
str
->
append
(
func_name
());
str
->
append
(
'('
);
List_iterator_fast
<
Item_field
>
it
(
fields
);
Item
*
item
;
if
((
item
=
it
++
))
item
->
print
(
str
);
while
((
item
=
it
++
))
{
str
->
append
(
','
);
str
->
append
(
' '
);
item
->
print
(
str
);
}
str
->
append
(
')'
);
}
sql/item_cmpfunc.h
View file @
be27811f
...
@@ -908,13 +908,76 @@ public:
...
@@ -908,13 +908,76 @@ public:
void
top_level_item
()
{
abort_on_null
=
1
;
}
void
top_level_item
()
{
abort_on_null
=
1
;
}
void
copy_andor_arguments
(
THD
*
thd
,
Item_cond
*
item
);
void
copy_andor_arguments
(
THD
*
thd
,
Item_cond
*
item
);
bool
walk
(
Item_processor
processor
,
byte
*
arg
);
bool
walk
(
Item_processor
processor
,
byte
*
arg
);
Item
*
traverse
(
Item_calculator
calculator
,
byte
*
arg
);
void
neg_arguments
();
void
neg_arguments
();
};
};
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
);
bool
is_false
()
{
return
cond_false
;
}
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
(
void
*
table_join_idx
);
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
*
traverse
(
Item_calculator
calculator
,
byte
*
arg
);
void
print
(
String
*
str
);
};
class
COND_EQUAL
{
public:
COND_EQUAL
*
parent_level
;
List
<
Item_equal
>
current_level
;
COND_EQUAL
()
{
parent_level
=
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
class
Item_cond_and
:
public
Item_cond
{
{
public:
public:
COND_EQUAL
cond_equal
;
Item_cond_and
()
:
Item_cond
()
{}
Item_cond_and
()
:
Item_cond
()
{}
Item_cond_and
(
Item
*
i1
,
Item
*
i2
)
:
Item_cond
(
i1
,
i2
)
{}
Item_cond_and
(
Item
*
i1
,
Item
*
i2
)
:
Item_cond
(
i1
,
i2
)
{}
Item_cond_and
(
THD
*
thd
,
Item_cond_and
&
item
)
:
Item_cond
(
thd
,
item
)
{}
Item_cond_and
(
THD
*
thd
,
Item_cond_and
&
item
)
:
Item_cond
(
thd
,
item
)
{}
...
...
sql/item_func.cc
View file @
be27811f
...
@@ -242,6 +242,40 @@ bool Item_func::walk (Item_processor processor, byte *argument)
...
@@ -242,6 +242,40 @@ bool Item_func::walk (Item_processor processor, byte *argument)
return
(
this
->*
processor
)(
argument
);
return
(
this
->*
processor
)(
argument
);
}
}
Item
*
Item_func
::
traverse
(
Item_calculator
calculator
,
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
)
->
traverse
(
calculator
,
argument
);
if
(
!
new_item
)
return
0
;
*
arg
=
new_item
;
}
}
return
(
this
->*
calculator
)(
argument
);
}
Item
*
Item_func
::
equal_fields_propagator
(
byte
*
argument
)
{
if
(
arg_count
)
{
Item
**
arg
,
**
arg_end
;
for
(
arg
=
args
,
arg_end
=
args
+
arg_count
;
arg
!=
arg_end
;
arg
++
)
{
if
(
!
(
*
arg
)
->
fixed
)
{
fix_fields
(
current_thd
,
0
,
0
);
break
;
}
}
}
return
this
;
}
void
Item_func
::
split_sum_func
(
Item
**
ref_pointer_array
,
List
<
Item
>
&
fields
)
void
Item_func
::
split_sum_func
(
Item
**
ref_pointer_array
,
List
<
Item
>
&
fields
)
{
{
Item
**
arg
,
**
arg_end
;
Item
**
arg
,
**
arg_end
;
...
...
sql/item_func.h
View file @
be27811f
...
@@ -40,7 +40,8 @@ public:
...
@@ -40,7 +40,8 @@ public:
enum
Functype
{
UNKNOWN_FUNC
,
EQ_FUNC
,
EQUAL_FUNC
,
NE_FUNC
,
LT_FUNC
,
LE_FUNC
,
enum
Functype
{
UNKNOWN_FUNC
,
EQ_FUNC
,
EQUAL_FUNC
,
NE_FUNC
,
LT_FUNC
,
LE_FUNC
,
GE_FUNC
,
GT_FUNC
,
FT_FUNC
,
GE_FUNC
,
GT_FUNC
,
FT_FUNC
,
LIKE_FUNC
,
NOTLIKE_FUNC
,
ISNULL_FUNC
,
ISNOTNULL_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
,
INTERVAL_FUNC
,
ISNOTNULLTEST_FUNC
,
SP_EQUALS_FUNC
,
SP_DISJOINT_FUNC
,
SP_INTERSECTS_FUNC
,
SP_EQUALS_FUNC
,
SP_DISJOINT_FUNC
,
SP_INTERSECTS_FUNC
,
SP_TOUCHES_FUNC
,
SP_CROSSES_FUNC
,
SP_WITHIN_FUNC
,
SP_TOUCHES_FUNC
,
SP_CROSSES_FUNC
,
SP_WITHIN_FUNC
,
...
@@ -49,7 +50,8 @@ public:
...
@@ -49,7 +50,8 @@ public:
SP_POINTN
,
SP_GEOMETRYN
,
SP_INTERIORRINGN
,
SP_POINTN
,
SP_GEOMETRYN
,
SP_INTERIORRINGN
,
NOT_FUNC
,
NOT_ALL_FUNC
,
NOT_FUNC
,
NOT_ALL_FUNC
,
GUSERVAR_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
;
}
enum
Type
type
()
const
{
return
FUNC_ITEM
;
}
virtual
enum
Functype
functype
()
const
{
return
UNKNOWN_FUNC
;
}
virtual
enum
Functype
functype
()
const
{
return
UNKNOWN_FUNC
;
}
Item_func
(
void
)
:
Item_func
(
void
)
:
...
@@ -146,6 +148,8 @@ public:
...
@@ -146,6 +148,8 @@ public:
bool
agg_arg_collations_for_comparison
(
DTCollation
&
c
,
Item
**
items
,
uint
nitems
);
bool
agg_arg_collations_for_comparison
(
DTCollation
&
c
,
Item
**
items
,
uint
nitems
);
bool
walk
(
Item_processor
processor
,
byte
*
arg
);
bool
walk
(
Item_processor
processor
,
byte
*
arg
);
Item
*
traverse
(
Item_calculator
calculator
,
byte
*
arg
);
Item
*
equal_fields_propagator
(
byte
*
arg
);
};
};
...
...
sql/item_row.cc
View file @
be27811f
...
@@ -140,6 +140,18 @@ bool Item_row::walk(Item_processor processor, byte *arg)
...
@@ -140,6 +140,18 @@ bool Item_row::walk(Item_processor processor, byte *arg)
return
(
this
->*
processor
)(
arg
);
return
(
this
->*
processor
)(
arg
);
}
}
Item
*
Item_row
::
traverse
(
Item_calculator
calculator
,
byte
*
arg
)
{
for
(
uint
i
=
0
;
i
<
arg_count
;
i
++
)
{
Item
*
new_item
=
items
[
i
]
->
traverse
(
calculator
,
arg
);
if
(
!
new_item
)
return
0
;
items
[
i
]
=
new_item
;
}
return
(
this
->*
calculator
)(
arg
);
}
void
Item_row
::
bring_value
()
void
Item_row
::
bring_value
()
{
{
for
(
uint
i
=
0
;
i
<
arg_count
;
i
++
)
for
(
uint
i
=
0
;
i
<
arg_count
;
i
++
)
...
...
sql/item_row.h
View file @
be27811f
...
@@ -71,6 +71,7 @@ public:
...
@@ -71,6 +71,7 @@ public:
void
print
(
String
*
str
);
void
print
(
String
*
str
);
bool
walk
(
Item_processor
processor
,
byte
*
arg
);
bool
walk
(
Item_processor
processor
,
byte
*
arg
);
Item
*
traverse
(
Item_calculator
calculator
,
byte
*
arg
);
uint
cols
()
{
return
arg_count
;
}
uint
cols
()
{
return
arg_count
;
}
Item
*
el
(
uint
i
)
{
return
items
[
i
];
}
Item
*
el
(
uint
i
)
{
return
items
[
i
];
}
...
...
sql/item_strfunc.h
View file @
be27811f
...
@@ -427,6 +427,14 @@ public:
...
@@ -427,6 +427,14 @@ public:
return
item
->
walk
(
processor
,
arg
)
||
return
item
->
walk
(
processor
,
arg
)
||
Item_str_func
::
walk
(
processor
,
arg
);
Item_str_func
::
walk
(
processor
,
arg
);
}
}
Item
*
traverse
(
Item_calculator
calculator
,
byte
*
arg
)
{
Item
*
new_item
=
item
->
traverse
(
calculator
,
arg
);
if
(
!
new_item
)
return
0
;
item
=
new_item
;
return
Item_str_func
::
traverse
(
calculator
,
arg
);
}
void
print
(
String
*
str
);
void
print
(
String
*
str
);
};
};
...
...
sql/opt_range.cc
View file @
be27811f
...
@@ -1252,11 +1252,75 @@ static int get_quick_select_params(SEL_TREE *tree, PARAM& param,
...
@@ -1252,11 +1252,75 @@ static int get_quick_select_params(SEL_TREE *tree, PARAM& param,
return
result
;
return
result
;
}
}
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"
);
if
(
cond_func
->
functype
()
==
Item_func
::
NE_FUNC
)
{
tree
=
get_mm_parts
(
param
,
field
,
Item_func
::
LT_FUNC
,
value
,
cmp_type
);
if
(
tree
)
{
tree
=
tree_or
(
param
,
tree
,
get_mm_parts
(
param
,
field
,
Item_func
::
GT_FUNC
,
value
,
cmp_type
));
}
}
else
if
(
cond_func
->
functype
()
==
Item_func
::
BETWEEN
)
{
tree
=
get_mm_parts
(
param
,
field
,
Item_func
::
GE_FUNC
,
cond_func
->
arguments
()[
1
],
cmp_type
);
if
(
tree
)
{
tree
=
tree_and
(
param
,
tree
,
get_mm_parts
(
param
,
field
,
Item_func
::
LE_FUNC
,
cond_func
->
arguments
()[
2
],
cmp_type
));
}
}
else
if
(
cond_func
->
functype
()
==
Item_func
::
IN_FUNC
)
{
Item_func_in
*
func
=
(
Item_func_in
*
)
cond_func
;
tree
=
get_mm_parts
(
param
,
field
,
Item_func
::
EQ_FUNC
,
func
->
arguments
()[
1
],
cmp_type
);
if
(
tree
)
{
for
(
uint
i
=
2
;
i
<
func
->
argument_count
()
;
i
++
)
{
tree
=
tree_or
(
param
,
tree
,
get_mm_parts
(
param
,
field
,
Item_func
::
EQ_FUNC
,
func
->
arguments
()[
i
],
cmp_type
));
}
}
}
else
{
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
,
field
,
func_type
,
value
,
cmp_type
);
}
DBUG_RETURN
(
tree
);
}
/* make a select tree of all keys in condition */
/* make a select tree of all keys in condition */
static
SEL_TREE
*
get_mm_tree
(
PARAM
*
param
,
COND
*
cond
)
static
SEL_TREE
*
get_mm_tree
(
PARAM
*
param
,
COND
*
cond
)
{
{
SEL_TREE
*
tree
=
0
;
SEL_TREE
*
tree
=
0
;
SEL_TREE
*
ftree
=
0
;
Item_field
*
field_item
=
0
;
Item
*
value
;
DBUG_ENTER
(
"get_mm_tree"
);
DBUG_ENTER
(
"get_mm_tree"
);
if
(
cond
->
type
()
==
Item
::
COND_ITEM
)
if
(
cond
->
type
()
==
Item
::
COND_ITEM
)
...
@@ -1304,9 +1368,12 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
...
@@ -1304,9 +1368,12 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
DBUG_RETURN
(
new
SEL_TREE
(
SEL_TREE
::
IMPOSSIBLE
));
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
)
if
(
cond
->
type
()
!=
Item
::
FUNC_ITEM
)
{
// Should be a field
{
// Should be a field
ref_tables
=
cond
->
used_tables
();
if
((
ref_tables
&
param
->
current_table
)
||
if
((
ref_tables
&
param
->
current_table
)
||
(
ref_tables
&
~
(
param
->
prev_tables
|
param
->
read_tables
)))
(
ref_tables
&
~
(
param
->
prev_tables
|
param
->
read_tables
)))
DBUG_RETURN
(
0
);
DBUG_RETURN
(
0
);
...
@@ -1321,73 +1388,95 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
...
@@ -1321,73 +1388,95 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
{
{
if
(
cond_func
->
arguments
()[
0
]
->
type
()
==
Item
::
FIELD_ITEM
)
if
(
cond_func
->
arguments
()[
0
]
->
type
()
==
Item
::
FIELD_ITEM
)
{
{
Field
*
field
=
((
Item_field
*
)
(
cond_func
->
arguments
()[
0
]))
->
field
;
field_item
=
(
Item_field
*
)
(
cond_func
->
arguments
()[
0
]);
Item_result
cmp_type
=
field
->
cmp_type
();
value
=
NULL
;
DBUG_RETURN
(
tree_and
(
param
,
get_mm_parts
(
param
,
field
,
Item_func
::
GE_FUNC
,
cond_func
->
arguments
()[
1
],
cmp_type
),
get_mm_parts
(
param
,
field
,
Item_func
::
LE_FUNC
,
cond_func
->
arguments
()[
2
],
cmp_type
)));
}
}
else
DBUG_RETURN
(
0
);
DBUG_RETURN
(
0
);
}
}
if
(
cond_func
->
functype
()
==
Item_func
::
IN_FUNC
)
else
if
(
cond_func
->
functype
()
==
Item_func
::
IN_FUNC
)
{
// COND OR
{
Item_func_in
*
func
=
(
Item_func_in
*
)
cond_func
;
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
)
{
{
Field
*
field
=
((
Item_field
*
)
(
func
->
key_item
()))
->
field
;
field_item
=
(
Item_field
*
)
(
func
->
key_item
())
;
Item_result
cmp_type
=
field
->
cmp_type
()
;
value
=
NULL
;
tree
=
get_mm_parts
(
param
,
field
,
Item_func
::
EQ_FUNC
,
}
func
->
arguments
()[
1
],
cmp_type
);
else
if
(
!
tree
)
DBUG_RETURN
(
0
);
DBUG_RETURN
(
tree
);
// Not key field
}
for
(
uint
i
=
2
;
i
<
func
->
argument_count
();
i
++
)
else
if
(
cond_func
->
functype
()
==
Item_func
::
MULT_EQUAL_FUNC
)
{
{
SEL_TREE
*
new_tree
=
get_mm_parts
(
param
,
field
,
Item_func
::
EQ_FUNC
,
Item_equal
*
item_equal
=
(
Item_equal
*
)
cond
;
func
->
arguments
()[
i
],
cmp_type
);
Item_equal_iterator
it
(
*
item_equal
);
tree
=
tree_or
(
param
,
tree
,
new_tree
);
if
(
!
(
value
=
item_equal
->
get_const
()))
value
=
it
++
;
while
(
value
)
{
ref_tables
=
value
->
used_tables
();
Item_equal_iterator
li
(
*
item_equal
);
while
((
field_item
=
li
++
))
{
if
(
field_item
!=
value
)
{
Field
*
field
=
field_item
->
field
;
Item_result
cmp_type
=
field
->
cmp_type
();
if
(
!
((
ref_tables
|
field
->
table
->
map
)
&
param_comp
))
{
tree
=
get_mm_parts
(
param
,
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
(
item_equal
->
get_const
())
if
(
ref_tables
&
~
(
param
->
prev_tables
|
param
->
read_tables
|
break
;
param
->
current_table
))
value
=
it
++
;
DBUG_RETURN
(
0
);
// Can't be calculated yet
}
if
(
!
(
ref_tables
&
param
->
current_table
))
DBUG_RETURN
(
ftree
);
DBUG_RETURN
(
new
SEL_TREE
(
SEL_TREE
::
MAYBE
));
// This may be false or true
}
else
if
(
cond_func
->
arguments
()[
0
]
->
type
()
==
Item
::
FIELD_ITEM
)
/* 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
,
field_item
=
(
Item_field
*
)
(
cond_func
->
arguments
()[
0
]);
((
Item_field
*
)
(
cond_func
->
arguments
()[
0
]))
->
field
,
value
=
cond_func
->
arg_count
>
1
?
cond_func
->
arguments
()[
1
]
:
0
;
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 */
else
if
(
cond_func
->
have_rev_func
()
&&
if
(
!
tree
&&
cond_func
->
have_rev_func
()
&&
cond_func
->
arguments
()[
1
]
->
type
()
==
Item
::
FIELD_ITEM
)
cond_func
->
arguments
()[
1
]
->
type
()
==
Item
::
FIELD_ITEM
)
{
{
DBUG_RETURN
(
get_mm_parts
(
param
,
field_item
=
(
Item_field
*
)
(
cond_func
->
arguments
()[
1
]);
((
Item_field
*
)
value
=
cond_func
->
arguments
()[
0
];
(
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
);
else
DBUG_RETURN
(
0
);
for
(
uint
i
=
0
;
i
<
cond_func
->
arg_count
;
i
++
)
{
Item
*
arg
=
cond_func
->
arguments
()[
i
];
if
(
arg
!=
field_item
)
ref_tables
|=
arg
->
used_tables
();
}
Field
*
field
=
field_item
->
field
;
Item_result
cmp_type
=
field
->
cmp_type
();
if
(
!
((
ref_tables
|
field
->
table
->
map
)
&
param_comp
))
ftree
=
get_func_mm_tree
(
param
,
cond_func
,
field
,
value
,
cmp_type
);
Item_equal
*
item_equal
=
field_item
->
item_equal
;
if
(
item_equal
)
{
Item_equal_iterator
it
(
*
item_equal
);
Item_field
*
item
;
while
((
item
=
it
++
))
{
Field
*
f
=
item
->
field
;
if
(
field
->
eq
(
f
))
continue
;
if
(
!
((
ref_tables
|
f
->
table
->
map
)
&
param_comp
))
{
tree
=
get_func_mm_tree
(
param
,
cond_func
,
f
,
value
,
cmp_type
);
ftree
=
!
ftree
?
tree
:
tree_and
(
param
,
ftree
,
tree
);
}
}
}
DBUG_RETURN
(
ftree
);
}
}
...
@@ -1395,17 +1484,10 @@ static SEL_TREE *
...
@@ -1395,17 +1484,10 @@ static SEL_TREE *
get_mm_parts
(
PARAM
*
param
,
Field
*
field
,
Item_func
::
Functype
type
,
get_mm_parts
(
PARAM
*
param
,
Field
*
field
,
Item_func
::
Functype
type
,
Item
*
value
,
Item_result
cmp_type
)
Item
*
value
,
Item_result
cmp_type
)
{
{
bool
ne_func
=
FALSE
;
DBUG_ENTER
(
"get_mm_parts"
);
DBUG_ENTER
(
"get_mm_parts"
);
if
(
field
->
table
!=
param
->
table
)
if
(
field
->
table
!=
param
->
table
)
DBUG_RETURN
(
0
);
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
*
key_part
=
param
->
key_parts
;
KEY_PART
*
end
=
param
->
key_parts_end
;
KEY_PART
*
end
=
param
->
key_parts_end
;
SEL_TREE
*
tree
=
0
;
SEL_TREE
*
tree
=
0
;
...
@@ -1442,13 +1524,6 @@ get_mm_parts(PARAM *param, Field *field, Item_func::Functype type,
...
@@ -1442,13 +1524,6 @@ get_mm_parts(PARAM *param, Field *field, Item_func::Functype type,
}
}
}
}
if
(
ne_func
)
{
SEL_TREE
*
tree2
=
get_mm_parts
(
param
,
field
,
Item_func
::
GT_FUNC
,
value
,
cmp_type
);
if
(
tree2
)
tree
=
tree_or
(
param
,
tree
,
tree2
);
}
DBUG_RETURN
(
tree
);
DBUG_RETURN
(
tree
);
}
}
...
...
sql/opt_sum.cc
View file @
be27811f
...
@@ -352,6 +352,18 @@ static bool simple_pred(Item_func *func_item, Item **args, bool *inv_order)
...
@@ -352,6 +352,18 @@ static bool simple_pred(Item_func *func_item, Item **args, bool *inv_order)
Item
*
item
;
Item
*
item
;
*
inv_order
=
0
;
*
inv_order
=
0
;
switch
(
func_item
->
argument_count
())
{
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
:
case
1
:
/* field IS NULL */
/* field IS NULL */
item
=
func_item
->
arguments
()[
0
];
item
=
func_item
->
arguments
()[
0
];
...
@@ -492,6 +504,9 @@ static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo,
...
@@ -492,6 +504,9 @@ static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo,
case
Item_func
:
:
BETWEEN
:
case
Item_func
:
:
BETWEEN
:
between
=
1
;
between
=
1
;
break
;
break
;
case
Item_func
:
:
MULT_EQUAL_FUNC
:
eq_type
=
1
;
break
;
default:
default:
return
0
;
// Can't optimize function
return
0
;
// Can't optimize function
}
}
...
...
sql/sql_list.h
View file @
be27811f
...
@@ -121,10 +121,12 @@ public:
...
@@ -121,10 +121,12 @@ public:
void
remove
(
list_node
**
prev
)
void
remove
(
list_node
**
prev
)
{
{
list_node
*
node
=
(
*
prev
)
->
next
;
list_node
*
node
=
(
*
prev
)
->
next
;
delete
*
prev
;
*
prev
=
node
;
if
(
!--
elements
)
if
(
!--
elements
)
last
=
&
first
;
last
=
&
first
;
else
if
(
last
==
&
(
*
prev
)
->
next
)
last
=
prev
;
delete
*
prev
;
*
prev
=
node
;
}
}
inline
void
*
pop
(
void
)
inline
void
*
pop
(
void
)
{
{
...
@@ -136,11 +138,29 @@ public:
...
@@ -136,11 +138,29 @@ public:
return
tmp
->
info
;
return
tmp
->
info
;
}
}
inline
void
concat
(
base_list
*
list
)
inline
void
concat
(
base_list
*
list
)
{
if
(
!
list
->
is_empty
())
{
{
*
last
=
list
->
first
;
*
last
=
list
->
first
;
last
=
list
->
last
;
last
=
list
->
last
;
elements
+=
list
->
elements
;
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
list_node
*
last_node
()
{
return
*
last
;
}
inline
list_node
*
last_node
()
{
return
*
last
;
}
inline
list_node
*
first_node
()
{
return
first
;}
inline
list_node
*
first_node
()
{
return
first
;}
inline
void
*
head
()
{
return
first
->
info
;
}
inline
void
*
head
()
{
return
first
->
info
;
}
...
@@ -251,6 +271,8 @@ public:
...
@@ -251,6 +271,8 @@ public:
inline
T
*
head
()
{
return
(
T
*
)
base_list
::
head
();
}
inline
T
*
head
()
{
return
(
T
*
)
base_list
::
head
();
}
inline
T
**
head_ref
()
{
return
(
T
**
)
base_list
::
head_ref
();
}
inline
T
**
head_ref
()
{
return
(
T
**
)
base_list
::
head_ref
();
}
inline
T
*
pop
()
{
return
(
T
*
)
base_list
::
pop
();
}
inline
T
*
pop
()
{
return
(
T
*
)
base_list
::
pop
();
}
inline
void
concat
(
List
<
T
>
*
list
)
{
return
base_list
::
concat
(
list
);
}
inline
void
disjoin
(
List
<
T
>
*
list
)
{
return
base_list
::
disjoin
(
list
);
}
void
delete_elements
(
void
)
void
delete_elements
(
void
)
{
{
list_node
*
element
,
*
next
;
list_node
*
element
,
*
next
;
...
@@ -261,7 +283,6 @@ public:
...
@@ -261,7 +283,6 @@ public:
}
}
empty
();
empty
();
}
}
inline
void
concat
(
List
<
T
>
*
list
)
{
base_list
::
concat
(
list
);
}
};
};
...
@@ -272,6 +293,8 @@ public:
...
@@ -272,6 +293,8 @@ public:
inline
T
*
operator
++
(
int
)
{
return
(
T
*
)
base_list_iterator
::
next
();
}
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
(
T
*
a
)
{
return
(
T
*
)
base_list_iterator
::
replace
(
a
);
}
inline
T
*
replace
(
List
<
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
void
after
(
T
*
a
)
{
base_list_iterator
::
after
(
a
);
}
inline
T
**
ref
(
void
)
{
return
(
T
**
)
base_list_iterator
::
ref
();
}
inline
T
**
ref
(
void
)
{
return
(
T
**
)
base_list_iterator
::
ref
();
}
};
};
...
...
sql/sql_select.cc
View file @
be27811f
...
@@ -73,6 +73,11 @@ static int return_zero_rows(JOIN *join, select_result *res,TABLE_LIST *tables,
...
@@ -73,6 +73,11 @@ static int return_zero_rows(JOIN *join, select_result *res,TABLE_LIST *tables,
uint
select_options
,
const
char
*
info
,
uint
select_options
,
const
char
*
info
,
Item
*
having
,
Procedure
*
proc
,
Item
*
having
,
Procedure
*
proc
,
SELECT_LEX_UNIT
*
unit
);
SELECT_LEX_UNIT
*
unit
);
static
Item
*
flatten_condition
(
COND
*
cond
);
static
COND
*
build_all_equal_items
(
COND
*
cond
,
COND_EQUAL
*
inherited
);
static
COND
*
substitute_for_best_equal_field
(
COND
*
cond
,
void
*
table_join_idx
);
static
COND
*
optimize_cond
(
COND
*
conds
,
Item
::
cond_result
*
cond_value
);
static
COND
*
optimize_cond
(
COND
*
conds
,
Item
::
cond_result
*
cond_value
);
static
COND
*
remove_eq_conds
(
COND
*
cond
,
Item
::
cond_result
*
cond_value
);
static
COND
*
remove_eq_conds
(
COND
*
cond
,
Item
::
cond_result
*
cond_value
);
static
bool
const_expression_in_where
(
COND
*
conds
,
Item
*
item
,
Item
**
comp_item
);
static
bool
const_expression_in_where
(
COND
*
conds
,
Item
*
item
,
Item
**
comp_item
);
...
@@ -527,6 +532,56 @@ JOIN::optimize()
...
@@ -527,6 +532,56 @@ JOIN::optimize()
}
}
#endif
#endif
/* eliminate NOT operators */
conds
=
eliminate_not_funcs
(
conds
);
DBUG_EXECUTE
(
"where"
,
print_where
(
conds
,
"after negation elimination"
););
/* Eliminate nested AND/OR in conditions */
if
(
conds
)
conds
=
flatten_condition
(
conds
);
{
TABLE_LIST
*
tables
;
for
(
tables
=
tables_list
;
tables
;
tables
=
tables
->
next
)
{
if
(
tables
->
on_expr
)
tables
->
on_expr
=
flatten_condition
(
tables
->
on_expr
);
}
}
/*
Build all multiple equality predicates and eliminate equality
predicates that can be inferred from these multiple equalities.
For each reference of a field included into a multiple equality
that occurs in a function set a pointer to the multiple equality
predicate. Substitute a constant instead of this field if the
multiple equality contains a constant.
*/
if
(
conds
)
{
conds
=
build_all_equal_items
(
conds
,
NULL
);
conds
->
update_used_tables
();
if
(
conds
->
type
()
==
Item
::
COND_ITEM
&&
((
Item_cond
*
)
conds
)
->
functype
()
==
Item_func
::
COND_AND_FUNC
)
cond_equal
=
&
((
Item_cond_and
*
)
conds
)
->
cond_equal
;
else
if
(
conds
->
type
()
==
Item
::
FUNC_ITEM
&&
((
Item_cond
*
)
conds
)
->
functype
()
==
Item_func
::
MULT_EQUAL_FUNC
)
{
cond_equal
=
new
COND_EQUAL
;
cond_equal
->
current_level
.
push_back
((
Item_equal
*
)
conds
);
}
}
{
TABLE_LIST
*
tables
;
for
(
tables
=
tables_list
;
tables
;
tables
=
tables
->
next
)
{
if
(
tables
->
on_expr
)
{
tables
->
on_expr
=
build_all_equal_items
(
tables
->
on_expr
,
cond_equal
);
tables
->
on_expr
->
update_used_tables
();
}
}
}
conds
=
optimize_cond
(
conds
,
&
cond_value
);
conds
=
optimize_cond
(
conds
,
&
cond_value
);
if
(
thd
->
net
.
report_error
)
if
(
thd
->
net
.
report_error
)
{
{
...
@@ -627,6 +682,30 @@ JOIN::optimize()
...
@@ -627,6 +682,30 @@ JOIN::optimize()
}
}
mysql_unlock_some_tables
(
thd
,
this
->
table
,
const_tables
);
mysql_unlock_some_tables
(
thd
,
this
->
table
,
const_tables
);
}
}
/*
Among the equal fields belonging to the same multiple equality
choose the one that is to be retrieved first and substitute
all references to these in where condition for a reference for
the selected field.
*/
if
(
conds
)
{
conds
=
substitute_for_best_equal_field
(
conds
,
map2table
);
conds
->
update_used_tables
();
}
{
TABLE_LIST
*
tables
;
for
(
tables
=
tables_list
;
tables
;
tables
=
tables
->
next
)
{
if
(
tables
->
on_expr
)
{
tables
->
on_expr
=
substitute_for_best_equal_field
(
tables
->
on_expr
,
map2table
);
tables
->
on_expr
->
update_used_tables
();
map2table
[
tables
->
table
->
tablenr
]
->
on_expr
=
tables
->
on_expr
;
}
}
}
if
(
!
conds
&&
outer_join
)
if
(
!
conds
&&
outer_join
)
{
{
/* Handle the case where we have an OUTER JOIN without a WHERE */
/* Handle the case where we have an OUTER JOIN without a WHERE */
...
@@ -2203,6 +2282,35 @@ add_key_field(KEY_FIELD **key_fields,uint and_level,
...
@@ -2203,6 +2282,35 @@ add_key_field(KEY_FIELD **key_fields,uint and_level,
}
}
static
void
add_key_equal_fields
(
KEY_FIELD
**
key_fields
,
uint
and_level
,
Item_field
*
field_item
,
bool
eq_func
,
Item
**
val
,
uint
num_values
,
table_map
usable_tables
)
{
Field
*
field
=
field_item
->
field
;
add_key_field
(
key_fields
,
and_level
,
field
,
eq_func
,
val
,
num_values
,
usable_tables
);
Item_equal
*
item_equal
=
field_item
->
item_equal
;
if
(
item_equal
)
{
/*
Add to the set of possible key values every substitution of
the field for an equal field included into item_equal
*/
Item_equal_iterator
it
(
*
item_equal
);
Item_field
*
item
;
while
((
item
=
it
++
))
{
if
(
!
field
->
eq
(
item
->
field
))
{
add_key_field
(
key_fields
,
and_level
,
item
->
field
,
eq_func
,
val
,
num_values
,
usable_tables
);
}
}
}
}
static
void
static
void
add_key_fields
(
JOIN_TAB
*
stat
,
KEY_FIELD
**
key_fields
,
uint
*
and_level
,
add_key_fields
(
JOIN_TAB
*
stat
,
KEY_FIELD
**
key_fields
,
uint
*
and_level
,
COND
*
cond
,
table_map
usable_tables
)
COND
*
cond
,
table_map
usable_tables
)
...
@@ -2248,10 +2356,10 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
...
@@ -2248,10 +2356,10 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
// BETWEEN or IN
// BETWEEN or IN
if
(
cond_func
->
key_item
()
->
real_item
()
->
type
()
==
Item
::
FIELD_ITEM
&&
if
(
cond_func
->
key_item
()
->
real_item
()
->
type
()
==
Item
::
FIELD_ITEM
&&
!
(
cond_func
->
used_tables
()
&
OUTER_REF_TABLE_BIT
))
!
(
cond_func
->
used_tables
()
&
OUTER_REF_TABLE_BIT
))
add_key_
field
(
key_fields
,
*
and_level
,
add_key_
equal_fields
(
key_fields
,
*
and_level
,
((
Item_field
*
)
(
cond_func
->
key_item
()
->
real_item
()))
->
(
Item_field
*
)
(
cond_func
->
key_item
()
->
real_item
()),
field
,
0
,
0
,
cond_func
->
arguments
()
+
1
,
cond_func
->
arguments
()
+
1
,
cond_func
->
argument_count
()
-
1
,
cond_func
->
argument_count
()
-
1
,
usable_tables
);
usable_tables
);
break
;
break
;
case
Item_func
:
:
OPTIMIZE_OP
:
case
Item_func
:
:
OPTIMIZE_OP
:
...
@@ -2262,9 +2370,8 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
...
@@ -2262,9 +2370,8 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
if
(
cond_func
->
arguments
()[
0
]
->
real_item
()
->
type
()
==
Item
::
FIELD_ITEM
&&
if
(
cond_func
->
arguments
()[
0
]
->
real_item
()
->
type
()
==
Item
::
FIELD_ITEM
&&
!
(
cond_func
->
arguments
()[
0
]
->
used_tables
()
&
OUTER_REF_TABLE_BIT
))
!
(
cond_func
->
arguments
()[
0
]
->
used_tables
()
&
OUTER_REF_TABLE_BIT
))
{
{
add_key_field
(
key_fields
,
*
and_level
,
add_key_equal_fields
(
key_fields
,
*
and_level
,
((
Item_field
*
)
(
cond_func
->
arguments
()[
0
])
->
real_item
())
(
Item_field
*
)
(
cond_func
->
arguments
()[
0
])
->
real_item
(),
->
field
,
equal_func
,
equal_func
,
cond_func
->
arguments
()
+
1
,
1
,
usable_tables
);
cond_func
->
arguments
()
+
1
,
1
,
usable_tables
);
}
}
...
@@ -2272,9 +2379,8 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
...
@@ -2272,9 +2379,8 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
cond_func
->
functype
()
!=
Item_func
::
LIKE_FUNC
&&
cond_func
->
functype
()
!=
Item_func
::
LIKE_FUNC
&&
!
(
cond_func
->
arguments
()[
1
]
->
used_tables
()
&
OUTER_REF_TABLE_BIT
))
!
(
cond_func
->
arguments
()[
1
]
->
used_tables
()
&
OUTER_REF_TABLE_BIT
))
{
{
add_key_field
(
key_fields
,
*
and_level
,
add_key_equal_fields
(
key_fields
,
*
and_level
,
((
Item_field
*
)
(
cond_func
->
arguments
()[
1
])
->
real_item
())
(
Item_field
*
)
(
cond_func
->
arguments
()[
1
])
->
real_item
(),
->
field
,
equal_func
,
equal_func
,
cond_func
->
arguments
(),
1
,
usable_tables
);
cond_func
->
arguments
(),
1
,
usable_tables
);
}
}
...
@@ -2288,15 +2394,55 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
...
@@ -2288,15 +2394,55 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
Item
*
tmp
=
new
Item_null
;
Item
*
tmp
=
new
Item_null
;
if
(
!
tmp
)
// Should never be true
if
(
!
tmp
)
// Should never be true
return
;
return
;
add_key_field
(
key_fields
,
*
and_level
,
add_key_equal_fields
(
key_fields
,
*
and_level
,
((
Item_field
*
)
(
cond_func
->
arguments
()[
0
])
->
real_item
())
(
Item_field
*
)
(
cond_func
->
arguments
()[
0
])
->
real_item
(),
->
field
,
cond_func
->
functype
()
==
Item_func
::
ISNULL_FUNC
,
cond_func
->
functype
()
==
Item_func
::
ISNULL_FUNC
,
&
tmp
,
1
,
usable_tables
);
&
tmp
,
1
,
usable_tables
);
}
}
break
;
break
;
case
Item_func
:
:
OPTIMIZE_EQUAL
:
Item_equal
*
item_equal
=
(
Item_equal
*
)
cond
;
Item
*
const_item
=
item_equal
->
get_const
();
Item_equal_iterator
it
(
*
item_equal
);
Item_field
*
item
;
if
(
const_item
)
{
/*
For each field field1 from item_equal consider the equality
field1=const_item as a condition allowing an index access of the table
with field1 by the keys value of field1.
*/
while
((
item
=
it
++
))
{
add_key_field
(
key_fields
,
*
and_level
,
item
->
field
,
TRUE
,
&
const_item
,
1
,
usable_tables
);
}
}
else
{
/*
Consider all pairs of different fields included into item_equal.
For each of them (field1, field1) consider the equality
field1=field2 as a condition allowing an index access of the table
with field1 by the keys value of field2.
*/
Item_equal_iterator
fi
(
*
item_equal
);
while
((
item
=
fi
++
))
{
Field
*
field
=
item
->
field
;
while
((
item
=
it
++
))
{
if
(
!
field
->
eq
(
item
->
field
))
{
add_key_field
(
key_fields
,
*
and_level
,
field
,
TRUE
,
(
Item
**
)
&
item
,
1
,
usable_tables
);
}
}
it
.
rewind
();
}
}
break
;
}
}
return
;
}
}
/*
/*
...
@@ -2670,21 +2816,33 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
...
@@ -2670,21 +2816,33 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
{
{
uint
keypart
=
keyuse
->
keypart
;
uint
keypart
=
keyuse
->
keypart
;
uint
found_part_ref_or_null
=
KEY_OPTIMIZE_REF_OR_NULL
;
uint
found_part_ref_or_null
=
KEY_OPTIMIZE_REF_OR_NULL
;
bool
usable
=
0
;
table_map
best_part_found_ref
=
0
;
double
best_prev_record_reads
=
DBL_MAX
;
do
do
{
{
if
(
!
(
rest_tables
&
keyuse
->
used_tables
)
&&
if
(
!
(
rest_tables
&
keyuse
->
used_tables
)
&&
!
(
found_ref_or_null
&
keyuse
->
optimize
))
!
(
found_ref_or_null
&
keyuse
->
optimize
))
{
{
found_part
|=
keyuse
->
keypart_map
;
found_part
|=
keyuse
->
keypart_map
;
found_ref
|=
keyuse
->
used_tables
;
double
tmp
=
prev_record_reads
(
join
,
(
table_map
)
(
found_ref
|
keyuse
->
used_tables
));
if
(
tmp
<
best_prev_record_reads
)
{
best_part_found_ref
=
keyuse
->
used_tables
;
best_prev_record_reads
=
tmp
;
}
if
(
rec
>
keyuse
->
ref_table_rows
)
if
(
rec
>
keyuse
->
ref_table_rows
)
rec
=
keyuse
->
ref_table_rows
;
rec
=
keyuse
->
ref_table_rows
;
found_part_ref_or_null
&=
keyuse
->
optimize
;
found_part_ref_or_null
&=
keyuse
->
optimize
;
usable
=
1
;
}
}
keyuse
++
;
keyuse
++
;
found_ref_or_null
|=
found_part_ref_or_null
;
found_ref
|=
best_part_found_ref
;
}
while
(
keyuse
->
table
==
table
&&
keyuse
->
key
==
key
&&
}
while
(
keyuse
->
table
==
table
&&
keyuse
->
key
==
key
&&
keyuse
->
keypart
==
keypart
);
keyuse
->
keypart
==
keypart
);
if
(
usable
)
found_ref_or_null
|=
found_part_ref_or_null
;
}
while
(
keyuse
->
table
==
table
&&
keyuse
->
key
==
key
);
}
while
(
keyuse
->
table
==
table
&&
keyuse
->
key
==
key
);
/*
/*
...
@@ -3395,7 +3553,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
...
@@ -3395,7 +3553,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
}
}
COND
*
tmp
=
make_cond_for_table
(
cond
,
used_tables
,
current_map
);
COND
*
tmp
=
make_cond_for_table
(
cond
,
used_tables
,
current_map
);
if
(
!
tmp
&&
tab
->
quick
)
if
(
!
tmp
&&
tab
->
quick
&&
tab
->
type
==
JT_ALL
)
{
// Outer join
{
// Outer join
/*
/*
Hack to handle the case where we only refer to a table
Hack to handle the case where we only refer to a table
...
@@ -4090,6 +4248,583 @@ template class List<Item_func_match>;
...
@@ -4090,6 +4248,583 @@ template class List<Item_func_match>;
template
class
List_iterator
<
Item_func_match
>;
template
class
List_iterator
<
Item_func_match
>;
#endif
#endif
/*
Eliminate nesting in AND/OR subexpressions od a condition
SYNOPSIS
flatten_condition()
cond condition where to eliminate nesting
DESCRIPTION
The function traverse the condition and recursively eliminates
nesting for AND/OR subexpressions:
... AND (p AND ... r) AND ... => ... AND p AND ... r AND ...
... OR (p OR ... r) OR ... => ... OR p OR ... r OR ...
NOTES
Nesting in AND/OR subexpresions inside of NOT/XOR formulas is not
eliminated.
RETURN
The transformed condition
*/
static
Item
*
flatten_condition
(
COND
*
cond
)
{
if
(
cond
->
type
()
==
Item
::
COND_ITEM
)
{
Item_func
::
Functype
functype
=
((
Item_cond
*
)
cond
)
->
functype
();
if
(
functype
==
Item_func
::
COND_AND_FUNC
||
functype
==
Item_func
::
COND_OR_FUNC
)
{
List
<
Item
>
*
args
=
((
Item_cond
*
)
cond
)
->
argument_list
();
List_iterator
<
Item
>
li
(
*
args
);
Item
*
item
;
List
<
Item
>
list
;
while
((
item
=
li
++
))
{
item
=
flatten_condition
(
item
);
if
(
item
->
type
()
==
Item
::
COND_ITEM
&&
((
Item_func
*
)
item
)
->
functype
()
==
functype
)
{
list
.
concat
(((
Item_cond
*
)
item
)
->
argument_list
());
li
.
remove
();
}
}
args
->
concat
(
&
list
);
}
}
return
cond
;
}
/*
Find the multiple equality predicate containing a field
SYNOPSIS
find_item_equal()
cond_equal multiple equalities to search in
field field to look for
inherited_fl :out set up to TRUE iff multiple equality is found
on upper levels (not on current level of cond_equal)
DESCRIPTION
The function retrieves the multiple equalities accessed through
the con_equal structure from current level and up looking for
an equality containing field. It stops retrieval as soon as the equality
is found and set up inherited_fl to TRUE if it's found on upper levels.
RETURN
Item_equal for the found multiple equality predicate if a success;
NULL - otherwise.
*/
Item_equal
*
find_item_equal
(
COND_EQUAL
*
cond_equal
,
Field
*
field
,
bool
*
inherited_fl
)
{
Item_equal
*
item
=
0
;
bool
in_upper_level
=
FALSE
;
while
(
cond_equal
)
{
List_iterator_fast
<
Item_equal
>
li
(
cond_equal
->
current_level
);
while
((
item
=
li
++
))
{
if
(
item
->
contains
(
field
))
goto
finish
;
}
in_upper_level
=
TRUE
;
cond_equal
=
cond_equal
->
parent_level
;
}
in_upper_level
=
FALSE
;
finish:
if
(
inherited_fl
)
*
inherited_fl
=
in_upper_level
;
return
item
;
}
/*
Check whether an item is a simple equality predicate and if so
create/find a multiple equality for this predicate
SYNOPSIS
check_equality()
item item to check
cond_equal multiple equalities that must hold together with the predicate
DESCRIPTION
This function first checks whether an item is a simple equality i.e.
the one that equates a field with another field or a constant.
If this is the case the function looks a for a multiple equality
in the lists referenced directly or indirectly by cond_equal. If it
doesn't find any it builds a multiple equality that covers
the predicate, i.e. the predicate can be inferred from it. The built
multiple equality could be obtained in such a way: create a binary
multiple equality equivalent to the predicate, than merge it, if
possible, with one of old multiple equalities. This guarantees that
the set of multiple equalities covering equality predicates will
be minimal.
NOTES
Now only fields that have the same type defintions (verified by
the Field::eq_def method) are placed to the same multiple equalities.
Because of this some equality predicates are not eliminated and
can be used in constant propagation procedure.
We could weeken the equlity test as soon as at least one of the
equal fields is to be equal to a constant. It would require a
more complicated implementation: we would have to store, in
general case, its own constant for each fields from the multiple
equality. But at the same time it would allow us to get rid
of constant propagation completely: it would be done by the call
to build_all_equal_items.
IMPLEMENTATION
The implementation does not follow exactly the above rules to
build a new multiple equality for the equality predicate.
If it processes the equality of the form field1=field2, it
looks for multiple equalities me1 containig field1 and me2 containing
field2. If only one of them is found the fuction expand it by
the lacking field. If multiple equalities for both fields are
found they are merged. If both searches fail a new multiple equality
containing just field1 and field2 is added to the existing
multiple equalities.
If the function processes the predicate of the form field1=const,
it looks for a multiple equality containing field1. If found, the
function checks the constant of the multiple equality. If the value
is unknown, it is setup to const. Otherwise the value is compared with
const and the evaluation of the equality predicate is performed.
When expanding/merging equality predicates from the upper levels
the function first copies them for the current level. It looks
acceptable, as this happens rarely. The implementation without
copying would be much more complicated.
RETURN
TRUE - if the predicate is a simple equality predicate
FALSE - otherwise
*/
static
bool
check_equality
(
Item
*
item
,
COND_EQUAL
*
cond_equal
)
{
if
(
item
->
type
()
==
Item
::
FUNC_ITEM
&&
((
Item_func
*
)
item
)
->
functype
()
==
Item_func
::
EQ_FUNC
)
{
Item
*
left_item
=
((
Item_func
*
)
item
)
->
arguments
()[
0
];
Item
*
right_item
=
((
Item_func
*
)
item
)
->
arguments
()[
1
];
if
(
left_item
->
type
()
==
Item
::
FIELD_ITEM
&&
right_item
->
type
()
==
Item
::
FIELD_ITEM
)
{
/* The predicate the form field1=field2 is processed */
Field
*
left_field
=
((
Item_field
*
)
left_item
)
->
field
;
Field
*
right_field
=
((
Item_field
*
)
right_item
)
->
field
;
if
(
!
left_field
->
eq_def
(
right_field
))
return
FALSE
;
if
(
left_field
->
eq
(
right_field
))
return
TRUE
;
/* Search for multiple equalities containing field1 and/or field2 */
bool
left_copyfl
,
right_copyfl
;
Item_equal
*
left_item_equal
=
find_item_equal
(
cond_equal
,
left_field
,
&
left_copyfl
);
Item_equal
*
right_item_equal
=
find_item_equal
(
cond_equal
,
right_field
,
&
right_copyfl
);
if
(
left_item_equal
&&
left_item_equal
==
right_item_equal
)
{
/*
The equality predicate is inference of one of the existing
multiple equalities
*/
return
TRUE
;
}
/* Copy the found multiple equalities at the current level if needed */
if
(
left_copyfl
)
{
left_item_equal
=
new
Item_equal
(
left_item_equal
);
cond_equal
->
current_level
.
push_back
(
left_item_equal
);
}
if
(
right_copyfl
)
{
right_item_equal
=
new
Item_equal
(
right_item_equal
);
cond_equal
->
current_level
.
push_back
(
right_item_equal
);
}
if
(
left_item_equal
)
{
if
(
!
right_item_equal
)
left_item_equal
->
add
((
Item_field
*
)
right_item
);
else
{
/* Merge two multiple equalities forming a new one */
left_item_equal
->
merge
(
right_item_equal
);
/* Remove the merged multiple equality from the list */
List_iterator
<
Item_equal
>
li
(
cond_equal
->
current_level
);
while
((
li
++
)
!=
right_item_equal
);
li
.
remove
();
}
}
else
{
if
(
right_item_equal
)
right_item_equal
->
add
((
Item_field
*
)
left_item
);
else
{
/* Multiple equalities for neither of the fields has been found */
Item_equal
*
item
=
new
Item_equal
((
Item_field
*
)
left_item
,
(
Item_field
*
)
right_item
);
cond_equal
->
current_level
.
push_back
(
item
);
}
}
return
TRUE
;
}
else
{
/* The predicate of the form field=const/const=field is processed */
Item
*
const_item
=
0
;
Item_field
*
field_item
=
0
;
if
(
left_item
->
type
()
==
Item
::
FIELD_ITEM
&&
right_item
->
const_item
())
{
field_item
=
(
Item_field
*
)
left_item
;
const_item
=
right_item
;
}
else
if
(
right_item
->
type
()
==
Item
::
FIELD_ITEM
&&
left_item
->
const_item
())
{
field_item
=
(
Item_field
*
)
right_item
;
const_item
=
left_item
;
}
if
(
const_item
&&
field_item
->
result_type
()
==
const_item
->
result_type
())
{
bool
copyfl
;
Item_equal
*
item_equal
=
find_item_equal
(
cond_equal
,
field_item
->
field
,
&
copyfl
);
if
(
copyfl
)
{
item_equal
=
new
Item_equal
(
item_equal
);
cond_equal
->
current_level
.
push_back
(
item_equal
);
}
if
(
item_equal
)
{
/*
The flag cond_false will be set to 1 after this, if item_equal
already contains a constant and its value is not equal to
the value of const_item.
*/
item_equal
->
add
(
const_item
);
}
else
{
item_equal
=
new
Item_equal
(
const_item
,
field_item
);
cond_equal
->
current_level
.
push_back
(
item_equal
);
}
return
TRUE
;
}
}
}
return
FALSE
;
}
/*
Replace all equality predicates in a condition by multiple equality items
SYNOPSIS
build_all_equal_items()
cond condition(expression) where to make replacement
inherited path to all inherited multiple equality items
DESCRIPTION
At each 'and' level the function detects items for equality predicates
and replaced them by a set of multiple equality items of class Item_equal,
taking into account inherited equalities from upper levels.
If an equality predicate is used not in a conjunction it's just
replaced by a multiple equality predicate.
The functuion also traverse the cond tree and and for each field reference
sets a ponter to the multiple equality item containing the field, if there
is any. If this multiple equality equates fields to a constant the
function replace the field reference by the constant.
NOTES
Multiple equality predicate =(f1,..fn) is equivalent to the conjuction of
f1=f2, .., fn-1=fn. It substitutes any inference from these
equality predicates that is equivalent to the conjunction.
Thus, =(a1,a2,a3) can substitute for ((a1=a3) AND (a2=a3) AND (a2=a1)) as
it is equivalent to ((a1=a2) AND (a2=a3)).
The function always makes a subsitution of all equality predicates occured
in a conjuction for a minimal set of multiple equality predicates.
This set can be considered as a canonical representation of the
sub-conjunction of the equality predicates.
E.g. (t1.a=t2.b AND t2.b>5 AND t1.a=t3.c) is replaced by
(=(t1.a,t2.b,t3.c) AND t2.b>5), not by
(=(t1.a,t2.b) AND =(t1.a,t3.c) AND t2.b>5);
while (t1.a=t2.b AND t2.b>5 AND t3.c,t4.d) is replaced by
(=(t1.a,t2.b) AND =(t3.c=t4.d) AND t2.b>5),
but if additionally =(t4.d,t2.b) is inherited, it
will be replaced by (=(t1.a,t2.b,t3.c,t4.d) AND t2.b>5)
IMPLEMENTATION
The function performs the substitution in a recursive descent by
the condtion tree, passing to the next AND level a chain of multiple
equality predicates which have been built at the upper levels.
The Item_equal items built at the level are attached to other
non-equality conjucts as a sublist. The pointer to the inherited
multiple equalities is saved in the and condition object (Item_cond_and).
This chain allows us for any field reference occurence easyly to find a
multiple equality that must be held for this occurence.
RETURN
pointer to the transformed condition
*/
static
COND
*
build_all_equal_items
(
COND
*
cond
,
COND_EQUAL
*
inherited
)
{
COND_EQUAL
cond_equal
;
cond_equal
.
parent_level
=
inherited
;
if
(
cond
->
type
()
==
Item
::
COND_ITEM
)
{
bool
and_level
=
((
Item_cond
*
)
cond
)
->
functype
()
==
Item_func
::
COND_AND_FUNC
;
List
<
Item
>
*
args
=
((
Item_cond
*
)
cond
)
->
argument_list
();
List_iterator
<
Item
>
li
(
*
args
);
Item
*
item
;
if
(
and_level
)
{
/*
Retrieve all conjucts of this level detecting the equality
that are subject to substitution by multiple equality items and
removing each such predicate from the conjunction after after having
found/created a multiple equality whose inference the predicate is.
*/
while
((
item
=
li
++
))
{
if
(
check_equality
(
item
,
&
cond_equal
))
li
.
remove
();
}
List_iterator_fast
<
Item_equal
>
it
(
cond_equal
.
current_level
);
while
((
item
=
it
++
))
{
item
->
fix_fields
(
current_thd
,
0
,
0
);
}
((
Item_cond_and
*
)
cond
)
->
cond_equal
=
cond_equal
;
inherited
=
&
(((
Item_cond_and
*
)
cond
)
->
cond_equal
);
}
/*
Make replacement of equality predicates for lower levels
of the condition expression.
*/
List_iterator
<
Item
>
it
(
*
args
);
while
((
item
=
it
++
))
{
Item
*
new_item
;
if
((
new_item
=
build_all_equal_items
(
item
,
inherited
))
!=
item
)
{
/* This replacement happens only for standalone equalities */
it
.
replace
(
new_item
);
}
}
if
(
and_level
)
args
->
concat
((
List
<
Item
>
*
)
&
cond_equal
.
current_level
);
}
else
if
(
cond
->
type
()
==
Item
::
FUNC_ITEM
)
{
/* Standalone equalities are handled here */
Item_equal
*
item_equal
;
if
(
check_equality
(
cond
,
&
cond_equal
)
&&
(
item_equal
=
cond_equal
.
current_level
.
pop
()))
{
item_equal
->
fix_fields
(
current_thd
,
0
,
0
);
return
item_equal
;
}
else
{
cond
=
cond
->
traverse
(
&
Item
::
equal_fields_propagator
,
(
byte
*
)
inherited
);
cond
->
update_used_tables
();
}
}
return
cond
;
}
/*
Generate minimal set of simple equalities equivalent to a multiple equality
SYNOPSIS
eliminate_item_equal()
cond condition to add the generated equality to
cond_equal structure to access multiple equality of upper levels
item_equal multiple equality to generate simple equality from
DESCRIPTION
The function retrieves the fields of the multiple equality item
item_equal and for each field f:
- if item_equal contains const it generates the equality f=const_item;
- otherwise, if f is not the first field, generates the equality
f=item_equal->get_first().
All generated equality are added to the cond conjunction.
NOTES
Before generating an equality function checks that it has not
been generated for multiple equalies of the upper levels.
If cond is equal to 0, then not more then one equality is generated
and a pointer to it is returned as the result of the function.
RETURN
The condition with generated simple equalities or
a pointer to the simple generated equality.
*/
static
Item
*
eliminate_item_equal
(
COND
*
cond
,
COND_EQUAL
*
cond_equal
,
Item_equal
*
item_equal
)
{
Item
*
item_const
=
item_equal
->
get_const
();
Item_equal_iterator
it
(
*
item_equal
);
Item
*
head
;
if
(
item_const
)
head
=
item_const
;
else
{
head
=
item_equal
->
get_first
();
it
++
;
}
Item_field
*
item_field
;
Item
*
new_item
=
0
;
while
((
item_field
=
it
++
))
{
Item_equal
*
upper
=
item_field
->
find_item_equal
(
cond_equal
);
Item_field
*
item
=
item_field
;
if
(
upper
)
{
if
(
item_const
)
{
if
(
upper
->
get_const
())
item
=
0
;
}
else
{
Item_equal_iterator
li
(
*
item_equal
);
while
((
item
=
li
++
)
!=
item_field
)
{
if
(
item
->
find_item_equal
(
cond_equal
)
==
upper
)
break
;
}
}
}
if
(
item
==
item_field
)
{
if
(
!
cond
&&
new_item
)
{
cond
=
new
Item_cond_and
();
((
Item_cond
*
)
cond
)
->
add
(
new_item
);
}
item_field
->
item_equal
=
item_equal
;
new_item
=
new
Item_func_eq
(
item_field
,
head
);
((
Item_func_eq
*
)
new_item
)
->
fix_length_and_dec
();
if
(
cond
)
((
Item_cond
*
)
cond
)
->
add
(
new_item
);
}
}
if
(
!
cond
)
cond
=
(
COND
*
)
new_item
;
return
cond
;
}
/*
Substitute every field reference in a condition by the best equal field
and eliminate all multiplle equality predicates
SYNOPSIS
substitute_for_best_equal_field()
cond condition to process
table_join_idx index to tables determining field preference
DESCRIPTION
The function retrieves the cond condition and for each encountered
multiple equality predicate it sorts the field references in it
according to the order of tables specified by the table_join_idx
parameter. Then it eliminates the multiple equality predicate it
replacing it by the conjunction of simple equality predicates
equating every field from the multiple equality to the first
field in it, or to the constant, if there is any.
After this the function retrieves all other conjuncted
predicates substitute every field reference by the field reference
to the first equal field or equal constant if there are any.
NOTES
At the first glance full sort of fields in multiple equality
seems to be an overkill. Yet it's not the case due to possible
new fields in multiple equality item of lower levels. We want
the order in them to comply with the order of upper levels.
RETURN
The transformed condition
*/
static
COND
*
substitute_for_best_equal_field
(
COND
*
cond
,
void
*
table_join_idx
)
{
Item_equal
*
item_equal
;
if
(
cond
->
type
()
==
Item
::
COND_ITEM
)
{
List
<
Item
>
*
cond_list
=
((
Item_cond
*
)
cond
)
->
argument_list
();
COND_EQUAL
*
cond_equal
=
0
;
bool
and_level
=
((
Item_cond
*
)
cond
)
->
functype
()
==
Item_func
::
COND_AND_FUNC
;
if
(
and_level
)
{
cond_equal
=
&
((
Item_cond_and
*
)
cond
)
->
cond_equal
;
cond_list
->
disjoin
((
List
<
Item
>
*
)
&
cond_equal
->
current_level
);
List_iterator_fast
<
Item_equal
>
it
(
cond_equal
->
current_level
);
while
((
item_equal
=
it
++
))
{
item_equal
->
sort
(
table_join_idx
);
}
}
List_iterator
<
Item
>
li
(
*
cond_list
);
Item
*
item
;
while
((
item
=
li
++
))
{
Item
*
new_item
=
substitute_for_best_equal_field
(
item
,
table_join_idx
);
if
(
new_item
!=
item
)
li
.
replace
(
new_item
);
}
if
(
and_level
)
{
List_iterator_fast
<
Item_equal
>
it
(
cond_equal
->
current_level
);
while
((
item_equal
=
it
++
))
{
eliminate_item_equal
(
cond
,
cond_equal
->
parent_level
,
item_equal
);
}
}
}
else
if
(
cond
->
type
()
==
Item
::
FUNC_ITEM
&&
((
Item_cond
*
)
cond
)
->
functype
()
==
Item_func
::
MULT_EQUAL_FUNC
)
{
item_equal
=
(
Item_equal
*
)
cond
;
item_equal
->
sort
(
table_join_idx
);
return
eliminate_item_equal
(
0
,
0
,
item_equal
);
}
else
cond
->
walk
(
&
Item
::
replace_equal_field_processor
,
0
);
return
cond
;
}
/*
/*
change field = field to field = const for each found field = const in the
change field = field to field = const for each found field = const in the
and_level
and_level
...
@@ -4319,9 +5054,6 @@ optimize_cond(COND *conds,Item::cond_result *cond_value)
...
@@ -4319,9 +5054,6 @@ optimize_cond(COND *conds,Item::cond_result *cond_value)
return
conds
;
return
conds
;
}
}
DBUG_EXECUTE
(
"where"
,
print_where
(
conds
,
"original"
););
DBUG_EXECUTE
(
"where"
,
print_where
(
conds
,
"original"
););
/* eliminate NOT operators */
conds
=
eliminate_not_funcs
(
conds
);
DBUG_EXECUTE
(
"where"
,
print_where
(
conds
,
"after negation elimination"
););
/* change field = field to field = const for each found field = const */
/* change field = field to field = const for each found field = const */
propagate_cond_constants
((
I_List
<
COND_CMP
>
*
)
0
,
conds
,
conds
);
propagate_cond_constants
((
I_List
<
COND_CMP
>
*
)
0
,
conds
,
conds
);
/*
/*
...
@@ -4413,7 +5145,8 @@ remove_eq_conds(COND *cond,Item::cond_result *cond_value)
...
@@ -4413,7 +5145,8 @@ remove_eq_conds(COND *cond,Item::cond_result *cond_value)
}
}
}
}
else
if
(
cond
->
type
()
==
Item
::
FUNC_ITEM
&&
else
if
(
cond
->
type
()
==
Item
::
FUNC_ITEM
&&
((
Item_func
*
)
cond
)
->
functype
()
==
Item_func
::
ISNULL_FUNC
)
((
Item_func
*
)
cond
)
->
functype
()
==
Item_func
::
ISNULL_FUNC
&&
!
cond
->
const_item
())
{
{
/*
/*
Handles this special case for some ODBC applications:
Handles this special case for some ODBC applications:
...
@@ -4464,6 +5197,22 @@ remove_eq_conds(COND *cond,Item::cond_result *cond_value)
...
@@ -4464,6 +5197,22 @@ remove_eq_conds(COND *cond,Item::cond_result *cond_value)
}
}
}
}
}
}
else
if
(
cond
->
type
()
==
Item
::
FUNC_ITEM
&&
((
Item_func
*
)
cond
)
->
functype
()
==
Item_func
::
MULT_EQUAL_FUNC
)
{
/*
The is_false method for an multiple equality item returns 1
when the conjunction with this item originally contained an
equality that was inconsistent with the multiple equality
predicate or has been inherited from other multiple equality
for which is_false returns 1.
*/
if
(((
Item_equal
*
)
cond
)
->
is_false
())
{
*
cond_value
=
Item
::
COND_FALSE
;
return
(
COND
*
)
0
;
}
}
else
if
(
cond
->
const_item
())
else
if
(
cond
->
const_item
())
{
{
*
cond_value
=
eval_const_cond
(
cond
)
?
Item
::
COND_TRUE
:
Item
::
COND_FALSE
;
*
cond_value
=
eval_const_cond
(
cond
)
?
Item
::
COND_TRUE
:
Item
::
COND_FALSE
;
...
...
sql/sql_select.h
View file @
be27811f
...
@@ -184,6 +184,7 @@ class JOIN :public Sql_alloc
...
@@ -184,6 +184,7 @@ class JOIN :public Sql_alloc
ORDER
*
order
,
*
group_list
,
*
proc_param
;
//hold parameters of mysql_select
ORDER
*
order
,
*
group_list
,
*
proc_param
;
//hold parameters of mysql_select
COND
*
conds
;
// ---"---
COND
*
conds
;
// ---"---
Item
*
conds_history
;
// store WHERE for explain
Item
*
conds_history
;
// store WHERE for explain
COND_EQUAL
*
cond_equal
;
TABLE_LIST
*
tables_list
;
//hold 'tables' parameter of mysql_selec
TABLE_LIST
*
tables_list
;
//hold 'tables' parameter of mysql_selec
SQL_SELECT
*
select
;
//created in optimisation phase
SQL_SELECT
*
select
;
//created in optimisation phase
Item
**
ref_pointer_array
;
//used pointer reference for this select
Item
**
ref_pointer_array
;
//used pointer reference for this select
...
@@ -243,6 +244,7 @@ class JOIN :public Sql_alloc
...
@@ -243,6 +244,7 @@ class JOIN :public Sql_alloc
ref_pointer_array_size
=
0
;
ref_pointer_array_size
=
0
;
zero_result_cause
=
0
;
zero_result_cause
=
0
;
optimized
=
0
;
optimized
=
0
;
cond_equal
=
0
;
fields_list
=
fields
;
fields_list
=
fields
;
bzero
((
char
*
)
&
keyuse
,
sizeof
(
keyuse
));
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