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
71c4cc4a
Commit
71c4cc4a
authored
Nov 11, 2004
by
timour@mysql.com
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
WL#1972 - manual merge with latest bk source
parent
866abfdd
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
277 additions
and
197 deletions
+277
-197
sql/sql_select.cc
sql/sql_select.cc
+277
-197
No files found.
sql/sql_select.cc
View file @
71c4cc4a
...
@@ -91,7 +91,7 @@ static int return_zero_rows(JOIN *join, select_result *res,TABLE_LIST *tables,
...
@@ -91,7 +91,7 @@ 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
COND
*
build_equal_items
(
COND
*
cond
,
static
COND
*
build_equal_items
(
THD
*
thd
,
COND
*
cond
,
COND_EQUAL
*
inherited
,
COND_EQUAL
*
inherited
,
List
<
TABLE_LIST
>
*
join_list
,
List
<
TABLE_LIST
>
*
join_list
,
COND_EQUAL
**
cond_equal_ref
);
COND_EQUAL
**
cond_equal_ref
);
...
@@ -101,6 +101,7 @@ static COND* substitute_for_best_equal_field(COND *cond,
...
@@ -101,6 +101,7 @@ static COND* substitute_for_best_equal_field(COND *cond,
static
COND
*
simplify_joins
(
JOIN
*
join
,
List
<
TABLE_LIST
>
*
join_list
,
static
COND
*
simplify_joins
(
JOIN
*
join
,
List
<
TABLE_LIST
>
*
join_list
,
COND
*
conds
,
bool
top
);
COND
*
conds
,
bool
top
);
static
COND
*
optimize_cond
(
JOIN
*
join
,
COND
*
conds
,
static
COND
*
optimize_cond
(
JOIN
*
join
,
COND
*
conds
,
List
<
TABLE_LIST
>
*
join_list
,
Item
::
cond_result
*
cond_value
);
Item
::
cond_result
*
cond_value
);
static
bool
resolve_nested_join
(
TABLE_LIST
*
table
);
static
bool
resolve_nested_join
(
TABLE_LIST
*
table
);
static
COND
*
remove_eq_conds
(
THD
*
thd
,
COND
*
cond
,
static
COND
*
remove_eq_conds
(
THD
*
thd
,
COND
*
cond
,
...
@@ -191,6 +192,7 @@ static void init_tmptable_sum_functions(Item_sum **func);
...
@@ -191,6 +192,7 @@ static void init_tmptable_sum_functions(Item_sum **func);
static
void
update_tmptable_sum_func
(
Item_sum
**
func
,
TABLE
*
tmp_table
);
static
void
update_tmptable_sum_func
(
Item_sum
**
func
,
TABLE
*
tmp_table
);
static
void
copy_sum_funcs
(
Item_sum
**
func_ptr
);
static
void
copy_sum_funcs
(
Item_sum
**
func_ptr
);
static
bool
add_ref_to_table_cond
(
THD
*
thd
,
JOIN_TAB
*
join_tab
);
static
bool
add_ref_to_table_cond
(
THD
*
thd
,
JOIN_TAB
*
join_tab
);
static
bool
setup_sum_funcs
(
THD
*
thd
,
Item_sum
**
func_ptr
);
static
bool
init_sum_functions
(
Item_sum
**
func
,
Item_sum
**
end
);
static
bool
init_sum_functions
(
Item_sum
**
func
,
Item_sum
**
end
);
static
bool
update_sum_func
(
Item_sum
**
func
);
static
bool
update_sum_func
(
Item_sum
**
func
);
static
void
select_describe
(
JOIN
*
join
,
bool
need_tmp_table
,
bool
need_order
,
static
void
select_describe
(
JOIN
*
join
,
bool
need_tmp_table
,
bool
need_order
,
...
@@ -228,16 +230,11 @@ int handle_select(THD *thd, LEX *lex, select_result *result)
...
@@ -228,16 +230,11 @@ int handle_select(THD *thd, LEX *lex, select_result *result)
select_lex
->
options
|
thd
->
options
,
select_lex
->
options
|
thd
->
options
,
result
,
unit
,
select_lex
);
result
,
unit
,
select_lex
);
}
}
/* Don't set res if it's -1 as we may want this later */
DBUG_PRINT
(
"info"
,(
"res: %d report_error: %d"
,
res
,
DBUG_PRINT
(
"info"
,(
"res: %d report_error: %d"
,
res
,
thd
->
net
.
report_error
));
thd
->
net
.
report_error
));
if
(
thd
->
net
.
report_error
)
if
(
thd
->
net
.
report_error
||
res
<
0
)
res
=
1
;
if
(
unlikely
(
res
))
{
{
if
(
res
>
0
)
result
->
send_error
(
0
,
NullS
);
result
->
send_error
(
0
,
NullS
);
result
->
abort
();
result
->
abort
();
res
=
1
;
// Error sent to client
res
=
1
;
// Error sent to client
}
}
...
@@ -333,7 +330,7 @@ JOIN::prepare(Item ***rref_pointer_array,
...
@@ -333,7 +330,7 @@ JOIN::prepare(Item ***rref_pointer_array,
if
(
having_fix_rc
||
thd
->
net
.
report_error
)
if
(
having_fix_rc
||
thd
->
net
.
report_error
)
DBUG_RETURN
(
-
1
);
/* purecov: inspected */
DBUG_RETURN
(
-
1
);
/* purecov: inspected */
if
(
having
->
with_sum_func
)
if
(
having
->
with_sum_func
)
having
->
split_sum_func
(
ref_pointer_array
,
all_fields
);
having
->
split_sum_func
(
thd
,
ref_pointer_array
,
all_fields
);
}
}
if
(
!
thd
->
lex
->
view_prepare_mode
)
if
(
!
thd
->
lex
->
view_prepare_mode
)
...
@@ -558,17 +555,7 @@ JOIN::optimize()
...
@@ -558,17 +555,7 @@ JOIN::optimize()
thd
->
restore_backup_item_arena
(
arena
,
&
backup
);
thd
->
restore_backup_item_arena
(
arena
,
&
backup
);
}
}
/*
conds
=
optimize_cond
(
this
,
conds
,
join_list
,
&
cond_value
);
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.
*/
conds
=
build_equal_items
(
conds
,
NULL
,
join_list
,
&
cond_equal
);
conds
=
optimize_cond
(
this
,
conds
,
&
cond_value
);
if
(
thd
->
net
.
report_error
)
if
(
thd
->
net
.
report_error
)
{
{
error
=
1
;
error
=
1
;
...
@@ -686,6 +673,7 @@ JOIN::optimize()
...
@@ -686,6 +673,7 @@ JOIN::optimize()
{
{
conds
=
substitute_for_best_equal_field
(
conds
,
cond_equal
,
map2table
);
conds
=
substitute_for_best_equal_field
(
conds
,
cond_equal
,
map2table
);
conds
->
update_used_tables
();
conds
->
update_used_tables
();
DBUG_EXECUTE
(
"where"
,
print_where
(
conds
,
"after substitute_best_equal"
););
}
}
/*
/*
Permorm the the optimization on fields evaluation mentioned above
Permorm the the optimization on fields evaluation mentioned above
...
@@ -1003,13 +991,15 @@ JOIN::optimize()
...
@@ -1003,13 +991,15 @@ JOIN::optimize()
if
(
create_sort_index
(
thd
,
this
,
group_list
,
if
(
create_sort_index
(
thd
,
this
,
group_list
,
HA_POS_ERROR
,
HA_POS_ERROR
)
||
HA_POS_ERROR
,
HA_POS_ERROR
)
||
alloc_group_fields
(
this
,
group_list
)
||
alloc_group_fields
(
this
,
group_list
)
||
make_sum_func_list
(
all_fields
,
fields_list
,
1
))
make_sum_func_list
(
all_fields
,
fields_list
,
1
)
||
setup_sum_funcs
(
thd
,
sum_funcs
))
DBUG_RETURN
(
1
);
DBUG_RETURN
(
1
);
group_list
=
0
;
group_list
=
0
;
}
}
else
else
{
{
if
(
make_sum_func_list
(
all_fields
,
fields_list
,
0
))
if
(
make_sum_func_list
(
all_fields
,
fields_list
,
0
)
||
setup_sum_funcs
(
thd
,
sum_funcs
))
DBUG_RETURN
(
1
);
DBUG_RETURN
(
1
);
if
(
!
group_list
&&
!
exec_tmp_table1
->
distinct
&&
order
&&
simple_order
)
if
(
!
group_list
&&
!
exec_tmp_table1
->
distinct
&&
order
&&
simple_order
)
{
{
...
@@ -1385,6 +1375,7 @@ JOIN::exec()
...
@@ -1385,6 +1375,7 @@ JOIN::exec()
}
}
if
(
curr_join
->
make_sum_func_list
(
*
curr_all_fields
,
*
curr_fields_list
,
if
(
curr_join
->
make_sum_func_list
(
*
curr_all_fields
,
*
curr_fields_list
,
1
,
TRUE
)
||
1
,
TRUE
)
||
setup_sum_funcs
(
curr_join
->
thd
,
curr_join
->
sum_funcs
)
||
(
tmp_error
=
do_select
(
curr_join
,
(
List
<
Item
>
*
)
0
,
curr_tmp_table
,
(
tmp_error
=
do_select
(
curr_join
,
(
List
<
Item
>
*
)
0
,
curr_tmp_table
,
0
)))
0
)))
{
{
...
@@ -1472,7 +1463,9 @@ JOIN::exec()
...
@@ -1472,7 +1463,9 @@ JOIN::exec()
set_items_ref_array
(
items3
);
set_items_ref_array
(
items3
);
if
(
curr_join
->
make_sum_func_list
(
*
curr_all_fields
,
*
curr_fields_list
,
if
(
curr_join
->
make_sum_func_list
(
*
curr_all_fields
,
*
curr_fields_list
,
1
,
TRUE
)
||
thd
->
is_fatal_error
)
1
,
TRUE
)
||
setup_sum_funcs
(
curr_join
->
thd
,
curr_join
->
sum_funcs
)
||
thd
->
is_fatal_error
)
DBUG_VOID_RETURN
;
DBUG_VOID_RETURN
;
}
}
if
(
curr_join
->
group_list
||
curr_join
->
order
)
if
(
curr_join
->
group_list
||
curr_join
->
order
)
...
@@ -1665,9 +1658,13 @@ Cursor::init_from_thd(THD *thd)
...
@@ -1665,9 +1658,13 @@ Cursor::init_from_thd(THD *thd)
/*
/*
We need to save and reset thd->mem_root, otherwise it'll be freed
We need to save and reset thd->mem_root, otherwise it'll be freed
later in mysql_parse.
later in mysql_parse.
We can't just change the thd->mem_root here as we want to keep the things
that is already allocated in thd->mem_root for Cursor::fetch()
*/
*/
mem_root
=
thd
->
mem_root
;
main_mem_root
=
*
thd
->
mem_root
;
init_sql_alloc
(
&
thd
->
mem_root
,
/* Allocate new memory root for thd */
init_sql_alloc
(
thd
->
mem_root
,
thd
->
variables
.
query_alloc_block_size
,
thd
->
variables
.
query_alloc_block_size
,
thd
->
variables
.
query_prealloc_size
);
thd
->
variables
.
query_prealloc_size
);
...
@@ -1681,7 +1678,7 @@ Cursor::init_from_thd(THD *thd)
...
@@ -1681,7 +1678,7 @@ Cursor::init_from_thd(THD *thd)
open_tables
=
thd
->
open_tables
;
open_tables
=
thd
->
open_tables
;
lock
=
thd
->
lock
;
lock
=
thd
->
lock
;
query_id
=
thd
->
query_id
;
query_id
=
thd
->
query_id
;
free_list
=
thd
->
free_list
;
free_list
=
thd
->
free_list
;
reset_thd
(
thd
);
reset_thd
(
thd
);
/*
/*
XXX: thd->locked_tables is not changed.
XXX: thd->locked_tables is not changed.
...
@@ -1696,8 +1693,6 @@ Cursor::init_from_thd(THD *thd)
...
@@ -1696,8 +1693,6 @@ Cursor::init_from_thd(THD *thd)
void
void
Cursor
::
init_thd
(
THD
*
thd
)
Cursor
::
init_thd
(
THD
*
thd
)
{
{
thd
->
mem_root
=
mem_root
;
DBUG_ASSERT
(
thd
->
derived_tables
==
0
);
DBUG_ASSERT
(
thd
->
derived_tables
==
0
);
thd
->
derived_tables
=
derived_tables
;
thd
->
derived_tables
=
derived_tables
;
...
@@ -1707,7 +1702,6 @@ Cursor::init_thd(THD *thd)
...
@@ -1707,7 +1702,6 @@ Cursor::init_thd(THD *thd)
DBUG_ASSERT
(
thd
->
lock
==
0
);
DBUG_ASSERT
(
thd
->
lock
==
0
);
thd
->
lock
=
lock
;
thd
->
lock
=
lock
;
thd
->
query_id
=
query_id
;
thd
->
query_id
=
query_id
;
thd
->
free_list
=
free_list
;
}
}
...
@@ -1725,11 +1719,10 @@ int
...
@@ -1725,11 +1719,10 @@ int
Cursor
::
open
(
JOIN
*
join_arg
)
Cursor
::
open
(
JOIN
*
join_arg
)
{
{
join
=
join_arg
;
join
=
join_arg
;
THD
*
thd
=
join
->
thd
;
THD
*
thd
=
join
->
thd
;
/* First non-constant table */
/* First non-constant table */
JOIN_TAB
*
join_tab
=
join
->
join_tab
+
join
->
const_tables
;
JOIN_TAB
*
join_tab
=
join
->
join_tab
+
join
->
const_tables
;
DBUG_ENTER
(
"Cursor::open"
);
/*
/*
Send fields description to the client; server_status is sent
Send fields description to the client; server_status is sent
...
@@ -1751,7 +1744,9 @@ Cursor::open(JOIN *join_arg)
...
@@ -1751,7 +1744,9 @@ Cursor::open(JOIN *join_arg)
join
->
fetch_limit
=
join
->
unit
->
offset_limit_cnt
;
join
->
fetch_limit
=
join
->
unit
->
offset_limit_cnt
;
/* Disable JOIN CACHE as it is not working with cursors yet */
/* Disable JOIN CACHE as it is not working with cursors yet */
for
(
JOIN_TAB
*
tab
=
join_tab
;
tab
!=
join
->
join_tab
+
join
->
tables
-
1
;
++
tab
)
for
(
JOIN_TAB
*
tab
=
join_tab
;
tab
!=
join
->
join_tab
+
join
->
tables
-
1
;
tab
++
)
{
{
if
(
tab
->
next_select
==
sub_select_cache
)
if
(
tab
->
next_select
==
sub_select_cache
)
tab
->
next_select
=
sub_select
;
tab
->
next_select
=
sub_select
;
...
@@ -1765,7 +1760,7 @@ Cursor::open(JOIN *join_arg)
...
@@ -1765,7 +1760,7 @@ Cursor::open(JOIN *join_arg)
*/
*/
DBUG_ASSERT
(
join_tab
->
table
->
null_row
==
0
);
DBUG_ASSERT
(
join_tab
->
table
->
null_row
==
0
);
return
join_tab
->
read_first_record
(
join_tab
);
DBUG_RETURN
(
join_tab
->
read_first_record
(
join_tab
)
);
}
}
...
@@ -1784,13 +1779,15 @@ int
...
@@ -1784,13 +1779,15 @@ int
Cursor
::
fetch
(
ulong
num_rows
)
Cursor
::
fetch
(
ulong
num_rows
)
{
{
THD
*
thd
=
join
->
thd
;
THD
*
thd
=
join
->
thd
;
JOIN_TAB
*
join_tab
=
join
->
join_tab
+
join
->
const_tables
;
;
JOIN_TAB
*
join_tab
=
join
->
join_tab
+
join
->
const_tables
;
COND
*
on_expr
=
*
join_tab
->
on_expr_ref
;
COND
*
on_expr
=
*
join_tab
->
on_expr_ref
;
COND
*
select_cond
=
join_tab
->
select_cond
;
COND
*
select_cond
=
join_tab
->
select_cond
;
READ_RECORD
*
info
=
&
join_tab
->
read_record
;
READ_RECORD
*
info
=
&
join_tab
->
read_record
;
int
error
=
0
;
int
error
=
0
;
/* save references to memory, allocated during fetch */
thd
->
set_n_backup_item_arena
(
this
,
&
thd
->
stmt_backup
);
join
->
fetch_limit
+=
num_rows
;
join
->
fetch_limit
+=
num_rows
;
/*
/*
...
@@ -1855,53 +1852,37 @@ Cursor::fetch(ulong num_rows)
...
@@ -1855,53 +1852,37 @@ Cursor::fetch(ulong num_rows)
if
(
thd
->
net
.
report_error
)
if
(
thd
->
net
.
report_error
)
error
=
-
1
;
error
=
-
1
;
switch
(
error
)
{
if
(
error
==
-
3
)
/* LIMIT clause worked */
/* Fetch limit worked, possibly more rows are there */
error
=
0
;
case
-
4
:
#ifdef USING_TRANSACTIONS
if
(
thd
->
transaction
.
all
.
innobase_tid
)
if
(
thd
->
transaction
.
all
.
innobase_tid
)
ha_release_temporary_latches
(
thd
);
ha_release_temporary_latches
(
thd
);
#endif
thd
->
restore_backup_item_arena
(
this
,
&
thd
->
stmt_backup
);
if
(
error
==
-
4
)
{
/* Fetch limit worked, possibly more rows are there */
thd
->
server_status
|=
SERVER_STATUS_CURSOR_EXISTS
;
thd
->
server_status
|=
SERVER_STATUS_CURSOR_EXISTS
;
::
send_eof
(
thd
);
::
send_eof
(
thd
);
thd
->
server_status
&=
~
SERVER_STATUS_CURSOR_EXISTS
;
thd
->
server_status
&=
~
SERVER_STATUS_CURSOR_EXISTS
;
/* save references to memory, allocated during fetch */
}
mem_root
=
thd
->
mem_root
;
else
free_list
=
thd
->
free_list
;
{
break
;
/* Limit clause worked: this is the same as 'no more rows' */
case
-
3
:
/* LIMIT clause worked */
error
=
0
;
/* fallthrough */
case
0
:
/* No more rows */
if
(
thd
->
transaction
.
all
.
innobase_tid
)
ha_release_temporary_latches
(
thd
);
close
();
thd
->
server_status
|=
SERVER_STATUS_LAST_ROW_SENT
;
::
send_eof
(
thd
);
thd
->
server_status
&=
~
SERVER_STATUS_LAST_ROW_SENT
;
join
=
0
;
unit
=
0
;
free_items
(
thd
->
free_list
);
thd
->
free_list
=
free_list
=
0
;
/*
Must be last, as some memory might be allocated for free purposes,
like in free_tmp_table() (TODO: fix this issue)
*/
mem_root
=
thd
->
mem_root
;
free_root
(
&
mem_root
,
MYF
(
0
));
break
;
default:
close
();
close
();
join
=
0
;
if
(
error
==
0
)
unit
=
0
;
{
free_items
(
thd
->
free_list
);
thd
->
server_status
|=
SERVER_STATUS_LAST_ROW_SENT
;
thd
->
free_list
=
free_list
=
0
;
::
send_eof
(
thd
);
/*
thd
->
server_status
&=
~
SERVER_STATUS_LAST_ROW_SENT
;
Must be last, as some memory might be allocated for free purposes,
}
like in free_tmp_table() (TODO: fix this issue)
else
*/
send_error
(
thd
,
ER_OUT_OF_RESOURCES
);
mem_root
=
thd
->
mem_root
;
/* free cursor memory */
free_root
(
&
mem_root
,
MYF
(
0
));
free_items
(
free_list
);
break
;
free_list
=
0
;
free_root
(
&
main_mem_root
,
MYF
(
0
));
}
}
return
error
;
return
error
;
}
}
...
@@ -1939,6 +1920,8 @@ Cursor::close()
...
@@ -1939,6 +1920,8 @@ Cursor::close()
thd
->
derived_tables
=
tmp_derived_tables
;
thd
->
derived_tables
=
tmp_derived_tables
;
thd
->
lock
=
tmp_lock
;
thd
->
lock
=
tmp_lock
;
}
}
join
=
0
;
unit
=
0
;
}
}
...
@@ -1951,7 +1934,7 @@ Cursor::~Cursor()
...
@@ -1951,7 +1934,7 @@ Cursor::~Cursor()
Must be last, as some memory might be allocated for free purposes,
Must be last, as some memory might be allocated for free purposes,
like in free_tmp_table() (TODO: fix this issue)
like in free_tmp_table() (TODO: fix this issue)
*/
*/
free_root
(
&
mem_root
,
MYF
(
0
));
free_root
(
&
m
ain_m
em_root
,
MYF
(
0
));
}
}
/*********************************************************************/
/*********************************************************************/
...
@@ -5030,7 +5013,7 @@ add_found_match_trig_cond(JOIN_TAB *tab, COND *cond, JOIN_TAB *root_tab)
...
@@ -5030,7 +5013,7 @@ add_found_match_trig_cond(JOIN_TAB *tab, COND *cond, JOIN_TAB *root_tab)
{
{
tmp
=
new
Item_func_trig_cond
(
tmp
,
&
tab
->
found
);
tmp
=
new
Item_func_trig_cond
(
tmp
,
&
tab
->
found
);
}
}
if
(
!
tmp
)
if
(
tmp
)
tmp
->
quick_fix_field
();
tmp
->
quick_fix_field
();
return
tmp
;
return
tmp
;
}
}
...
@@ -5304,8 +5287,17 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
...
@@ -5304,8 +5287,17 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
/* Join with outer join condition */
/* Join with outer join condition */
COND
*
orig_cond
=
sel
->
cond
;
COND
*
orig_cond
=
sel
->
cond
;
sel
->
cond
=
and_conds
(
sel
->
cond
,
*
tab
->
on_expr_ref
);
sel
->
cond
=
and_conds
(
sel
->
cond
,
*
tab
->
on_expr_ref
);
/*
We can't call sel->cond->fix_fields,
as it will break tab->on_expr if it's AND condition
(fix_fields currently removes extra AND/OR levels).
Yet attributes of the just built condition are not needed.
Thus we call sel->cond->quick_fix_field for safety.
*/
if
(
sel
->
cond
&&
!
sel
->
cond
->
fixed
)
if
(
sel
->
cond
&&
!
sel
->
cond
->
fixed
)
sel
->
cond
->
fix_fields
(
join
->
thd
,
0
,
&
sel
->
cond
);
sel
->
cond
->
quick_fix_field
();
if
(
sel
->
test_quick_select
(
join
->
thd
,
tab
->
keys
,
if
(
sel
->
test_quick_select
(
join
->
thd
,
tab
->
keys
,
used_tables
&
~
current_map
,
used_tables
&
~
current_map
,
(
join
->
select_options
&
(
join
->
select_options
&
...
@@ -6030,7 +6022,7 @@ template class List_iterator<Item_func_match>;
...
@@ -6030,7 +6022,7 @@ template class List_iterator<Item_func_match>;
find_item_equal()
find_item_equal()
cond_equal multiple equalities to search in
cond_equal multiple equalities to search in
field field to look for
field field to look for
inherited_fl :out set up to TRUE if
f
multiple equality is found
inherited_fl :out set up to TRUE if multiple equality is found
on upper levels (not on current level of cond_equal)
on upper levels (not on current level of cond_equal)
DESCRIPTION
DESCRIPTION
...
@@ -6448,12 +6440,14 @@ static COND *build_equal_items_for_cond(COND *cond,
...
@@ -6448,12 +6440,14 @@ static COND *build_equal_items_for_cond(COND *cond,
return
cond
;
return
cond
;
}
}
/*
/*
Build multiple equalities for a condition and all on expressions that
Build multiple equalities for a condition and all on expressions that
inherit these multiple equalities
inherit these multiple equalities
SYNOPSIS
SYNOPSIS
build_equal_items()
build_equal_items()
thd Thread handler
cond condition to build the multiple equalities for
cond condition to build the multiple equalities for
inherited path to all inherited multiple equality items
inherited path to all inherited multiple equality items
join_list list of join tables to which the condition refers to
join_list list of join tables to which the condition refers to
...
@@ -6505,7 +6499,7 @@ static COND *build_equal_items_for_cond(COND *cond,
...
@@ -6505,7 +6499,7 @@ static COND *build_equal_items_for_cond(COND *cond,
pointer to the transformed condition containing multiple equalities
pointer to the transformed condition containing multiple equalities
*/
*/
static
COND
*
build_equal_items
(
COND
*
cond
,
static
COND
*
build_equal_items
(
THD
*
thd
,
COND
*
cond
,
COND_EQUAL
*
inherited
,
COND_EQUAL
*
inherited
,
List
<
TABLE_LIST
>
*
join_list
,
List
<
TABLE_LIST
>
*
join_list
,
COND_EQUAL
**
cond_equal_ref
)
COND_EQUAL
**
cond_equal_ref
)
...
@@ -6542,12 +6536,13 @@ static COND *build_equal_items(COND *cond,
...
@@ -6542,12 +6536,13 @@ static COND *build_equal_items(COND *cond,
{
{
if
(
table
->
on_expr
)
if
(
table
->
on_expr
)
{
{
Item
*
expr
;
List
<
TABLE_LIST
>
*
join_list
=
table
->
nested_join
?
List
<
TABLE_LIST
>
*
join_list
=
table
->
nested_join
?
&
table
->
nested_join
->
join_list
:
NULL
;
&
table
->
nested_join
->
join_list
:
NULL
;
table
->
on_expr
=
build_equal_items
(
table
->
on_expr
,
expr
=
build_equal_items
(
thd
,
table
->
on_expr
,
inherited
,
join_list
,
inherited
,
&
table
->
cond_equal
);
join_list
,
if
(
expr
!=
table
->
on_expr
)
&
table
->
cond_equal
);
thd
->
change_item_tree
(
&
table
->
on_expr
,
expr
);
}
}
}
}
}
}
...
@@ -6555,6 +6550,7 @@ static COND *build_equal_items(COND *cond,
...
@@ -6555,6 +6550,7 @@ static COND *build_equal_items(COND *cond,
return
cond
;
return
cond
;
}
}
/*
/*
Compare field items by table order in the execution plan
Compare field items by table order in the execution plan
...
@@ -6649,10 +6645,7 @@ static Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels,
...
@@ -6649,10 +6645,7 @@ static Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels,
List
<
Item
>
eq_list
;
List
<
Item
>
eq_list
;
Item_func_eq
*
eq_item
=
0
;
Item_func_eq
*
eq_item
=
0
;
if
(((
Item
*
)
item_equal
)
->
const_item
()
&&
!
item_equal
->
val_int
())
if
(((
Item
*
)
item_equal
)
->
const_item
()
&&
!
item_equal
->
val_int
())
{
return
new
Item_int
((
longlong
)
0
,
1
);
cond
=
new
Item_int
((
char
*
)
"FALSE"
,
0
,
1
);
return
cond
;
}
Item
*
item_const
=
item_equal
->
get_const
();
Item
*
item_const
=
item_equal
->
get_const
();
Item_equal_iterator
it
(
*
item_equal
);
Item_equal_iterator
it
(
*
item_equal
);
Item
*
head
;
Item
*
head
;
...
@@ -6695,9 +6688,14 @@ static Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels,
...
@@ -6695,9 +6688,14 @@ static Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels,
}
}
if
(
!
cond
&&
!
eq_list
.
head
())
if
(
!
cond
&&
!
eq_list
.
head
())
{
if
(
!
eq_item
)
return
new
Item_int
((
longlong
)
1
,
1
);
return
eq_item
;
return
eq_item
;
}
eq_list
.
push_back
(
eq_item
);
if
(
eq_item
)
eq_list
.
push_back
(
eq_item
);
if
(
!
cond
)
if
(
!
cond
)
cond
=
new
Item_cond_and
(
eq_list
);
cond
=
new
Item_cond_and
(
eq_list
);
else
else
...
@@ -6799,14 +6797,16 @@ static COND* substitute_for_best_equal_field(COND *cond,
...
@@ -6799,14 +6797,16 @@ static COND* substitute_for_best_equal_field(COND *cond,
return
cond
;
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
*/
*/
static
void
static
void
change_cond_ref_to_const
(
I_List
<
COND_CMP
>
*
save_list
,
Item
*
and_father
,
change_cond_ref_to_const
(
THD
*
thd
,
I_List
<
COND_CMP
>
*
save_list
,
Item
*
cond
,
Item
*
field
,
Item
*
value
)
Item
*
and_father
,
Item
*
cond
,
Item
*
field
,
Item
*
value
)
{
{
if
(
cond
->
type
()
==
Item
::
COND_ITEM
)
if
(
cond
->
type
()
==
Item
::
COND_ITEM
)
{
{
...
@@ -6815,7 +6815,7 @@ change_cond_ref_to_const(I_List<COND_CMP> *save_list,Item *and_father,
...
@@ -6815,7 +6815,7 @@ change_cond_ref_to_const(I_List<COND_CMP> *save_list,Item *and_father,
List_iterator
<
Item
>
li
(
*
((
Item_cond
*
)
cond
)
->
argument_list
());
List_iterator
<
Item
>
li
(
*
((
Item_cond
*
)
cond
)
->
argument_list
());
Item
*
item
;
Item
*
item
;
while
((
item
=
li
++
))
while
((
item
=
li
++
))
change_cond_ref_to_const
(
save_list
,
and_level
?
cond
:
item
,
item
,
change_cond_ref_to_const
(
thd
,
save_list
,
and_level
?
cond
:
item
,
item
,
field
,
value
);
field
,
value
);
return
;
return
;
}
}
...
@@ -6823,8 +6823,9 @@ change_cond_ref_to_const(I_List<COND_CMP> *save_list,Item *and_father,
...
@@ -6823,8 +6823,9 @@ change_cond_ref_to_const(I_List<COND_CMP> *save_list,Item *and_father,
return
;
// Not a boolean function
return
;
// Not a boolean function
Item_bool_func2
*
func
=
(
Item_bool_func2
*
)
cond
;
Item_bool_func2
*
func
=
(
Item_bool_func2
*
)
cond
;
Item
*
left_item
=
func
->
arguments
()[
0
];
Item
**
args
=
func
->
arguments
();
Item
*
right_item
=
func
->
arguments
()[
1
];
Item
*
left_item
=
args
[
0
];
Item
*
right_item
=
args
[
1
];
Item_func
::
Functype
functype
=
func
->
functype
();
Item_func
::
Functype
functype
=
func
->
functype
();
if
(
right_item
->
eq
(
field
,
0
)
&&
left_item
!=
value
&&
if
(
right_item
->
eq
(
field
,
0
)
&&
left_item
!=
value
&&
...
@@ -6835,7 +6836,7 @@ change_cond_ref_to_const(I_List<COND_CMP> *save_list,Item *and_father,
...
@@ -6835,7 +6836,7 @@ change_cond_ref_to_const(I_List<COND_CMP> *save_list,Item *and_father,
Item
*
tmp
=
value
->
new_item
();
Item
*
tmp
=
value
->
new_item
();
if
(
tmp
)
if
(
tmp
)
{
{
func
->
arguments
()[
1
]
=
tmp
;
thd
->
change_item_tree
(
args
+
1
,
tmp
)
;
func
->
update_used_tables
();
func
->
update_used_tables
();
if
((
functype
==
Item_func
::
EQ_FUNC
||
functype
==
Item_func
::
EQUAL_FUNC
)
if
((
functype
==
Item_func
::
EQ_FUNC
||
functype
==
Item_func
::
EQUAL_FUNC
)
&&
and_father
!=
cond
&&
!
left_item
->
const_item
())
&&
and_father
!=
cond
&&
!
left_item
->
const_item
())
...
@@ -6856,13 +6857,14 @@ change_cond_ref_to_const(I_List<COND_CMP> *save_list,Item *and_father,
...
@@ -6856,13 +6857,14 @@ change_cond_ref_to_const(I_List<COND_CMP> *save_list,Item *and_father,
Item
*
tmp
=
value
->
new_item
();
Item
*
tmp
=
value
->
new_item
();
if
(
tmp
)
if
(
tmp
)
{
{
func
->
arguments
()[
0
]
=
value
=
tmp
;
thd
->
change_item_tree
(
args
,
tmp
);
value
=
tmp
;
func
->
update_used_tables
();
func
->
update_used_tables
();
if
((
functype
==
Item_func
::
EQ_FUNC
||
functype
==
Item_func
::
EQUAL_FUNC
)
if
((
functype
==
Item_func
::
EQ_FUNC
||
functype
==
Item_func
::
EQUAL_FUNC
)
&&
and_father
!=
cond
&&
!
right_item
->
const_item
())
&&
and_father
!=
cond
&&
!
right_item
->
const_item
())
{
{
func
->
arguments
()[
0
]
=
func
->
arguments
()[
1
];
// For easy check
args
[
0
]
=
args
[
1
];
// For easy check
func
->
arguments
()[
1
]
=
value
;
thd
->
change_item_tree
(
args
+
1
,
value
)
;
cond
->
marker
=
1
;
cond
->
marker
=
1
;
COND_CMP
*
tmp2
;
COND_CMP
*
tmp2
;
if
((
tmp2
=
new
COND_CMP
(
and_father
,
func
)))
if
((
tmp2
=
new
COND_CMP
(
and_father
,
func
)))
...
@@ -6908,8 +6910,8 @@ static Item *remove_additional_cond(Item* conds)
...
@@ -6908,8 +6910,8 @@ static Item *remove_additional_cond(Item* conds)
}
}
static
void
static
void
propagate_cond_constants
(
I_List
<
COND_CMP
>
*
save_list
,
COND
*
and_father
,
propagate_cond_constants
(
THD
*
thd
,
I_List
<
COND_CMP
>
*
save_list
,
COND
*
cond
)
COND
*
and_father
,
COND
*
cond
)
{
{
if
(
cond
->
type
()
==
Item
::
COND_ITEM
)
if
(
cond
->
type
()
==
Item
::
COND_ITEM
)
{
{
...
@@ -6920,18 +6922,19 @@ propagate_cond_constants(I_List<COND_CMP> *save_list,COND *and_father,
...
@@ -6920,18 +6922,19 @@ propagate_cond_constants(I_List<COND_CMP> *save_list,COND *and_father,
I_List
<
COND_CMP
>
save
;
I_List
<
COND_CMP
>
save
;
while
((
item
=
li
++
))
while
((
item
=
li
++
))
{
{
propagate_cond_constants
(
&
save
,
and_level
?
cond
:
item
,
item
);
propagate_cond_constants
(
thd
,
&
save
,
and_level
?
cond
:
item
,
item
);
}
}
if
(
and_level
)
if
(
and_level
)
{
// Handle other found items
{
// Handle other found items
I_List_iterator
<
COND_CMP
>
cond_itr
(
save
);
I_List_iterator
<
COND_CMP
>
cond_itr
(
save
);
COND_CMP
*
cond_cmp
;
COND_CMP
*
cond_cmp
;
while
((
cond_cmp
=
cond_itr
++
))
while
((
cond_cmp
=
cond_itr
++
))
if
(
!
cond_cmp
->
cmp_func
->
arguments
()[
0
]
->
const_item
())
{
change_cond_ref_to_const
(
&
save
,
cond_cmp
->
and_level
,
Item
**
args
=
cond_cmp
->
cmp_func
->
arguments
();
cond_cmp
->
and_level
,
if
(
!
args
[
0
]
->
const_item
())
cond_cmp
->
cmp_func
->
arguments
()[
0
],
change_cond_ref_to_const
(
thd
,
&
save
,
cond_cmp
->
and_level
,
cond_cmp
->
cmp_func
->
arguments
()[
1
]);
cond_cmp
->
and_level
,
args
[
0
],
args
[
1
]);
}
}
}
}
}
else
if
(
and_father
!=
cond
&&
!
cond
->
marker
)
// In a AND group
else
if
(
and_father
!=
cond
&&
!
cond
->
marker
)
// In a AND group
...
@@ -6941,29 +6944,25 @@ propagate_cond_constants(I_List<COND_CMP> *save_list,COND *and_father,
...
@@ -6941,29 +6944,25 @@ propagate_cond_constants(I_List<COND_CMP> *save_list,COND *and_father,
((
Item_func
*
)
cond
)
->
functype
()
==
Item_func
::
EQUAL_FUNC
))
((
Item_func
*
)
cond
)
->
functype
()
==
Item_func
::
EQUAL_FUNC
))
{
{
Item_func_eq
*
func
=
(
Item_func_eq
*
)
cond
;
Item_func_eq
*
func
=
(
Item_func_eq
*
)
cond
;
bool
left_const
=
func
->
arguments
()[
0
]
->
const_item
();
Item
**
args
=
func
->
arguments
();
bool
right_const
=
func
->
arguments
()[
1
]
->
const_item
();
bool
left_const
=
args
[
0
]
->
const_item
();
bool
right_const
=
args
[
1
]
->
const_item
();
if
(
!
(
left_const
&&
right_const
)
&&
if
(
!
(
left_const
&&
right_const
)
&&
(
func
->
arguments
()[
0
]
->
result_type
()
==
args
[
0
]
->
result_type
()
==
args
[
1
]
->
result_type
())
(
func
->
arguments
()[
1
]
->
result_type
())))
{
{
if
(
right_const
)
if
(
right_const
)
{
{
func
->
arguments
()[
1
]
=
resolve_const_item
(
func
->
arguments
()[
1
],
resolve_const_item
(
thd
,
&
args
[
1
],
args
[
0
]);
func
->
arguments
()[
0
]);
func
->
update_used_tables
();
func
->
update_used_tables
();
change_cond_ref_to_const
(
save_list
,
and_father
,
and_father
,
change_cond_ref_to_const
(
thd
,
save_list
,
and_father
,
and_father
,
func
->
arguments
()[
0
],
args
[
0
],
args
[
1
]);
func
->
arguments
()[
1
]);
}
}
else
if
(
left_const
)
else
if
(
left_const
)
{
{
func
->
arguments
()[
0
]
=
resolve_const_item
(
func
->
arguments
()[
0
],
resolve_const_item
(
thd
,
&
args
[
0
],
args
[
1
]);
func
->
arguments
()[
1
]);
func
->
update_used_tables
();
func
->
update_used_tables
();
change_cond_ref_to_const
(
save_list
,
and_father
,
and_father
,
change_cond_ref_to_const
(
thd
,
save_list
,
and_father
,
and_father
,
func
->
arguments
()[
1
],
args
[
1
],
args
[
0
]);
func
->
arguments
()[
0
]);
}
}
}
}
}
}
...
@@ -7091,6 +7090,7 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top)
...
@@ -7091,6 +7090,7 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top)
*/
*/
if
(
table
->
on_expr
)
if
(
table
->
on_expr
)
{
{
Item
*
expr
;
/*
/*
If an on expression E is attached to the table,
If an on expression E is attached to the table,
check all null rejected predicates in this expression.
check all null rejected predicates in this expression.
...
@@ -7099,8 +7099,9 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top)
...
@@ -7099,8 +7099,9 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top)
the outer join is converted to an inner join and
the outer join is converted to an inner join and
the corresponding on expression is added to E.
the corresponding on expression is added to E.
*/
*/
table
->
on_expr
=
simplify_joins
(
join
,
&
nested_join
->
join_list
,
expr
=
simplify_joins
(
join
,
&
nested_join
->
join_list
,
table
->
on_expr
,
FALSE
);
table
->
on_expr
,
FALSE
);
table
->
on_expr
=
expr
;
}
}
nested_join
->
used_tables
=
(
table_map
)
0
;
nested_join
->
used_tables
=
(
table_map
)
0
;
nested_join
->
not_null_tables
=
(
table_map
)
0
;
nested_join
->
not_null_tables
=
(
table_map
)
0
;
...
@@ -7209,8 +7210,10 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top)
...
@@ -7209,8 +7210,10 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top)
DBUG_RETURN
(
conds
);
DBUG_RETURN
(
conds
);
}
}
static
COND
*
static
COND
*
optimize_cond
(
JOIN
*
join
,
COND
*
conds
,
Item
::
cond_result
*
cond_value
)
optimize_cond
(
JOIN
*
join
,
COND
*
conds
,
List
<
TABLE_LIST
>
*
join_list
,
Item
::
cond_result
*
cond_value
)
{
{
THD
*
thd
=
join
->
thd
;
THD
*
thd
=
join
->
thd
;
SELECT_LEX
*
select
=
thd
->
lex
->
current_select
;
SELECT_LEX
*
select
=
thd
->
lex
->
current_select
;
...
@@ -7223,9 +7226,21 @@ optimize_cond(JOIN *join, COND *conds, Item::cond_result *cond_value)
...
@@ -7223,9 +7226,21 @@ optimize_cond(JOIN *join, COND *conds, Item::cond_result *cond_value)
}
}
else
else
{
{
/*
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.
*/
DBUG_EXECUTE
(
"where"
,
print_where
(
conds
,
"original"
););
DBUG_EXECUTE
(
"where"
,
print_where
(
conds
,
"original"
););
conds
=
build_equal_items
(
join
->
thd
,
conds
,
NULL
,
join_list
,
&
join
->
cond_equal
);
DBUG_EXECUTE
(
"where"
,
print_where
(
conds
,
"after equal_items"
););
/* 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
(
thd
,
(
I_List
<
COND_CMP
>
*
)
0
,
conds
,
conds
);
/*
/*
Remove all instances of item == item
Remove all instances of item == item
Remove all and-levels where CONST item != CONST item
Remove all and-levels where CONST item != CONST item
...
@@ -7461,21 +7476,28 @@ const_expression_in_where(COND *cond, Item *comp_item, Item **const_item)
...
@@ -7461,21 +7476,28 @@ const_expression_in_where(COND *cond, Item *comp_item, Item **const_item)
the record in the original table.
the record in the original table.
If modify_item is 0 then fill_record() will update
If modify_item is 0 then fill_record() will update
the temporary table
the temporary table
convert_blob_length If >0 create a varstring(convert_blob_length) field
instead of blob.
RETURN
RETURN
0 on error
0 on error
new_created field
new_created field
*/
*/
static
Field
*
create_tmp_field_from_field
(
THD
*
thd
,
Field
*
org_field
,
static
Field
*
create_tmp_field_from_field
(
THD
*
thd
,
Field
*
org_field
,
Item
*
item
,
Item
*
item
,
TABLE
*
table
,
TABLE
*
table
,
bool
modify_item
,
bool
modify_item
)
uint
convert_blob_length
)
{
{
Field
*
new_field
;
Field
*
new_field
;
// The following should always be true
if
(
convert_blob_length
&&
org_field
->
flags
&
BLOB_FLAG
)
if
((
new_field
=
org_field
->
new_field
(
&
thd
->
mem_root
,
table
)))
new_field
=
new
Field_varstring
(
convert_blob_length
,
org_field
->
maybe_null
(),
org_field
->
field_name
,
table
,
org_field
->
charset
());
else
new_field
=
org_field
->
new_field
(
thd
->
mem_root
,
table
);
if
(
new_field
)
{
{
if
(
modify_item
)
if
(
modify_item
)
((
Item_field
*
)
item
)
->
result_field
=
new_field
;
((
Item_field
*
)
item
)
->
result_field
=
new_field
;
...
@@ -7506,16 +7528,16 @@ static Field* create_tmp_field_from_field(THD *thd,
...
@@ -7506,16 +7528,16 @@ static Field* create_tmp_field_from_field(THD *thd,
the record in the original table.
the record in the original table.
If modify_item is 0 then fill_record() will update
If modify_item is 0 then fill_record() will update
the temporary table
the temporary table
convert_blob_length If >0 create a varstring(convert_blob_length) field
instead of blob.
RETURN
RETURN
0 on error
0 on error
new_created field
new_created field
*/
*/
static
Field
*
create_tmp_field_from_item
(
THD
*
thd
,
static
Field
*
create_tmp_field_from_item
(
THD
*
thd
,
Item
*
item
,
TABLE
*
table
,
Item
*
item
,
Item
***
copy_func
,
bool
modify_item
,
TABLE
*
table
,
uint
convert_blob_length
)
Item
***
copy_func
,
bool
modify_item
)
{
{
bool
maybe_null
=
item
->
maybe_null
;
bool
maybe_null
=
item
->
maybe_null
;
Field
*
new_field
;
Field
*
new_field
;
...
@@ -7532,13 +7554,18 @@ static Field* create_tmp_field_from_item(THD *thd,
...
@@ -7532,13 +7554,18 @@ static Field* create_tmp_field_from_item(THD *thd,
break
;
break
;
case
STRING_RESULT
:
case
STRING_RESULT
:
if
(
item
->
max_length
>
255
)
if
(
item
->
max_length
>
255
)
new_field
=
new
Field_blob
(
item
->
max_length
,
maybe_null
,
{
item
->
name
,
table
,
if
(
convert_blob_length
)
item
->
collation
.
collation
);
new_field
=
new
Field_varstring
(
convert_blob_length
,
maybe_null
,
item
->
name
,
table
,
item
->
collation
.
collation
);
else
new_field
=
new
Field_blob
(
item
->
max_length
,
maybe_null
,
item
->
name
,
table
,
item
->
collation
.
collation
);
}
else
else
new_field
=
new
Field_string
(
item
->
max_length
,
maybe_null
,
new_field
=
new
Field_string
(
item
->
max_length
,
maybe_null
,
item
->
name
,
item
->
name
,
table
,
table
,
item
->
collation
.
collation
);
item
->
collation
.
collation
);
break
;
break
;
case
ROW_RESULT
:
case
ROW_RESULT
:
default:
default:
...
@@ -7575,6 +7602,8 @@ static Field* create_tmp_field_from_item(THD *thd,
...
@@ -7575,6 +7602,8 @@ static Field* create_tmp_field_from_item(THD *thd,
the record in the original table.
the record in the original table.
If modify_item is 0 then fill_record() will update
If modify_item is 0 then fill_record() will update
the temporary table
the temporary table
convert_blob_length If >0 create a varstring(convert_blob_length) field
instead of blob.
RETURN
RETURN
0 on error
0 on error
...
@@ -7582,8 +7611,8 @@ static Field* create_tmp_field_from_item(THD *thd,
...
@@ -7582,8 +7611,8 @@ static Field* create_tmp_field_from_item(THD *thd,
*/
*/
Field
*
create_tmp_field
(
THD
*
thd
,
TABLE
*
table
,
Item
*
item
,
Item
::
Type
type
,
Field
*
create_tmp_field
(
THD
*
thd
,
TABLE
*
table
,
Item
*
item
,
Item
::
Type
type
,
Item
***
copy_func
,
Field
**
from_field
,
Item
***
copy_func
,
Field
**
from_field
,
bool
group
,
bool
modify_item
)
bool
group
,
bool
modify_item
,
uint
convert_blob_length
)
{
{
switch
(
type
)
{
switch
(
type
)
{
case
Item
:
:
SUM_FUNC_ITEM
:
case
Item
:
:
SUM_FUNC_ITEM
:
...
@@ -7618,8 +7647,15 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
...
@@ -7618,8 +7647,15 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
item
->
name
,
table
,
item
->
unsigned_flag
);
item
->
name
,
table
,
item
->
unsigned_flag
);
case
STRING_RESULT
:
case
STRING_RESULT
:
if
(
item_sum
->
max_length
>
255
)
if
(
item_sum
->
max_length
>
255
)
return
new
Field_blob
(
item_sum
->
max_length
,
maybe_null
,
{
item
->
name
,
table
,
item
->
collation
.
collation
);
if
(
convert_blob_length
)
return
new
Field_varstring
(
convert_blob_length
,
maybe_null
,
item
->
name
,
table
,
item
->
collation
.
collation
);
else
return
new
Field_blob
(
item_sum
->
max_length
,
maybe_null
,
item
->
name
,
table
,
item
->
collation
.
collation
);
}
return
new
Field_string
(
item_sum
->
max_length
,
maybe_null
,
return
new
Field_string
(
item_sum
->
max_length
,
maybe_null
,
item
->
name
,
table
,
item
->
collation
.
collation
);
item
->
name
,
table
,
item
->
collation
.
collation
);
case
ROW_RESULT
:
case
ROW_RESULT
:
...
@@ -7636,8 +7672,8 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
...
@@ -7636,8 +7672,8 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
case
Item
:
:
DEFAULT_VALUE_ITEM
:
case
Item
:
:
DEFAULT_VALUE_ITEM
:
{
{
Item_field
*
field
=
(
Item_field
*
)
item
;
Item_field
*
field
=
(
Item_field
*
)
item
;
return
create_tmp_field_from_field
(
thd
,
(
*
from_field
=
field
->
field
),
return
create_tmp_field_from_field
(
thd
,
(
*
from_field
=
field
->
field
),
item
,
item
,
table
,
modify_item
);
table
,
modify_item
,
convert_blob_length
);
}
}
case
Item
:
:
FUNC_ITEM
:
case
Item
:
:
FUNC_ITEM
:
case
Item
:
:
COND_ITEM
:
case
Item
:
:
COND_ITEM
:
...
@@ -7652,14 +7688,16 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
...
@@ -7652,14 +7688,16 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
case
Item
:
:
REF_ITEM
:
case
Item
:
:
REF_ITEM
:
case
Item
:
:
NULL_ITEM
:
case
Item
:
:
NULL_ITEM
:
case
Item
:
:
VARBIN_ITEM
:
case
Item
:
:
VARBIN_ITEM
:
return
create_tmp_field_from_item
(
thd
,
item
,
table
,
return
create_tmp_field_from_item
(
thd
,
item
,
table
,
copy_func
,
modify_item
,
copy_func
,
modify_item
);
convert_blob_length
);
case
Item
:
:
TYPE_HOLDER
:
case
Item
:
:
TYPE_HOLDER
:
{
{
Field
*
example
=
((
Item_type_holder
*
)
item
)
->
example
();
Field
*
example
=
((
Item_type_holder
*
)
item
)
->
example
();
if
(
example
)
if
(
example
)
return
create_tmp_field_from_field
(
thd
,
example
,
item
,
table
,
0
);
return
create_tmp_field_from_field
(
thd
,
example
,
item
,
table
,
0
,
return
create_tmp_field_from_item
(
thd
,
item
,
table
,
copy_func
,
0
);
convert_blob_length
);
return
create_tmp_field_from_item
(
thd
,
item
,
table
,
copy_func
,
0
,
convert_blob_length
);
}
}
default:
// Dosen't have to be stored
default:
// Dosen't have to be stored
return
0
;
return
0
;
...
@@ -7818,12 +7856,14 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
...
@@ -7818,12 +7856,14 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
((
Item_sum
*
)
item
)
->
result_field
=
0
;
((
Item_sum
*
)
item
)
->
result_field
=
0
;
for
(
i
=
0
;
i
<
((
Item_sum
*
)
item
)
->
arg_count
;
i
++
)
for
(
i
=
0
;
i
<
((
Item_sum
*
)
item
)
->
arg_count
;
i
++
)
{
{
Item
*
arg
=
((
Item_sum
*
)
item
)
->
args
[
i
];
Item
**
argp
=
((
Item_sum
*
)
item
)
->
args
+
i
;
Item
*
arg
=
*
argp
;
if
(
!
arg
->
const_item
())
if
(
!
arg
->
const_item
())
{
{
Field
*
new_field
=
Field
*
new_field
=
create_tmp_field
(
thd
,
table
,
arg
,
arg
->
type
(),
&
copy_func
,
create_tmp_field
(
thd
,
table
,
arg
,
arg
->
type
(),
&
copy_func
,
tmp_from_field
,
group
!=
0
,
not_all_columns
);
tmp_from_field
,
group
!=
0
,
not_all_columns
,
param
->
convert_blob_length
);
if
(
!
new_field
)
if
(
!
new_field
)
goto
err
;
// Should be OOM
goto
err
;
// Should be OOM
tmp_from_field
++
;
tmp_from_field
++
;
...
@@ -7834,7 +7874,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
...
@@ -7834,7 +7874,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
*
blob_field
++=
new_field
;
*
blob_field
++=
new_field
;
blob_count
++
;
blob_count
++
;
}
}
((
Item_sum
*
)
item
)
->
args
[
i
]
=
new
Item_field
(
new_field
);
thd
->
change_item_tree
(
argp
,
new
Item_field
(
new_field
)
);
if
(
!
(
new_field
->
flags
&
NOT_NULL_FLAG
))
if
(
!
(
new_field
->
flags
&
NOT_NULL_FLAG
))
{
{
null_count
++
;
null_count
++
;
...
@@ -7842,7 +7882,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
...
@@ -7842,7 +7882,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
new_field->maybe_null() is still false, it will be
new_field->maybe_null() is still false, it will be
changed below. But we have to setup Item_field correctly
changed below. But we have to setup Item_field correctly
*/
*/
(
(
Item_sum
*
)
item
)
->
args
[
i
]
->
maybe_null
=
1
;
(
*
argp
)
->
maybe_null
=
1
;
}
}
}
}
}
}
...
@@ -7859,9 +7899,10 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
...
@@ -7859,9 +7899,10 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
We here distinguish between UNION and multi-table-updates by the fact
We here distinguish between UNION and multi-table-updates by the fact
that in the later case group is set to the row pointer.
that in the later case group is set to the row pointer.
*/
*/
Field
*
new_field
=
create_tmp_field
(
thd
,
table
,
item
,
type
,
&
copy_func
,
Field
*
new_field
=
create_tmp_field
(
thd
,
table
,
item
,
type
,
&
copy_func
,
tmp_from_field
,
group
!=
0
,
tmp_from_field
,
group
!=
0
,
not_all_columns
||
group
!=
0
);
not_all_columns
||
group
!=
0
,
param
->
convert_blob_length
);
if
(
!
new_field
)
if
(
!
new_field
)
{
{
if
(
thd
->
is_fatal_error
)
if
(
thd
->
is_fatal_error
)
...
@@ -8058,7 +8099,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
...
@@ -8058,7 +8099,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
if
(
!
using_unique_constraint
)
if
(
!
using_unique_constraint
)
{
{
group
->
buff
=
(
char
*
)
group_buff
;
group
->
buff
=
(
char
*
)
group_buff
;
if
(
!
(
group
->
field
=
field
->
new_field
(
&
thd
->
mem_root
,
table
)))
if
(
!
(
group
->
field
=
field
->
new_field
(
thd
->
mem_root
,
table
)))
goto
err
;
/* purecov: inspected */
goto
err
;
/* purecov: inspected */
if
(
maybe_null
)
if
(
maybe_null
)
{
{
...
@@ -8569,7 +8610,7 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
...
@@ -8569,7 +8610,7 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
DBUG_PRINT
(
"error"
,(
"Error: do_select() failed"
));
DBUG_PRINT
(
"error"
,(
"Error: do_select() failed"
));
}
}
#endif
#endif
DBUG_RETURN
(
error
||
join
->
thd
->
net
.
report_
error
);
DBUG_RETURN
(
join
->
thd
->
net
.
report_error
?
-
1
:
error
);
}
}
...
@@ -9050,6 +9091,7 @@ join_read_const_table(JOIN_TAB *tab, POSITION *pos)
...
@@ -9050,6 +9091,7 @@ join_read_const_table(JOIN_TAB *tab, POSITION *pos)
{
{
table
->
key_read
=
1
;
table
->
key_read
=
1
;
table
->
file
->
extra
(
HA_EXTRA_KEYREAD
);
table
->
file
->
extra
(
HA_EXTRA_KEYREAD
);
tab
->
index
=
tab
->
ref
.
key
;
}
}
if
((
error
=
join_read_const
(
tab
)))
if
((
error
=
join_read_const
(
tab
)))
{
{
...
@@ -10037,10 +10079,23 @@ part_of_refkey(TABLE *table,Field *field)
...
@@ -10037,10 +10079,23 @@ part_of_refkey(TABLE *table,Field *field)
/*****************************************************************************
/*****************************************************************************
Test if one can use the key to resolve ORDER BY
Test if one can use the key to resolve ORDER BY
Returns: 1 if key is ok.
0 if key can't be used
SYNOPSIS
-1 if reverse key can be used
test_if_order_by_key()
used_key_parts is set to key parts used if length != 0
order Sort order
table Table to sort
idx Index to check
used_key_parts Return value for used key parts.
NOTES
used_key_parts is set to correct key parts used if return value != 0
(On other cases, used_key_part may be changed)
RETURN
1 key is ok.
0 Key can't be used
-1 Reverse key can be used
*****************************************************************************/
*****************************************************************************/
static
int
test_if_order_by_key
(
ORDER
*
order
,
TABLE
*
table
,
uint
idx
,
static
int
test_if_order_by_key
(
ORDER
*
order
,
TABLE
*
table
,
uint
idx
,
...
@@ -10069,13 +10124,17 @@ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx,
...
@@ -10069,13 +10124,17 @@ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx,
DBUG_RETURN
(
0
);
DBUG_RETURN
(
0
);
/* set flag to 1 if we can use read-next on key, else to -1 */
/* set flag to 1 if we can use read-next on key, else to -1 */
flag
=
((
order
->
asc
==
!
(
key_part
->
key_part_flag
&
HA_REVERSE_SORT
))
?
1
:
-
1
);
flag
=
((
order
->
asc
==
!
(
key_part
->
key_part_flag
&
HA_REVERSE_SORT
))
?
1
:
-
1
);
if
(
reverse
&&
flag
!=
reverse
)
if
(
reverse
&&
flag
!=
reverse
)
DBUG_RETURN
(
0
);
DBUG_RETURN
(
0
);
reverse
=
flag
;
// Remember if reverse
reverse
=
flag
;
// Remember if reverse
key_part
++
;
key_part
++
;
}
}
*
used_key_parts
=
(
uint
)
(
key_part
-
table
->
key_info
[
idx
].
key_part
);
*
used_key_parts
=
(
uint
)
(
key_part
-
table
->
key_info
[
idx
].
key_part
);
if
(
reverse
==
-
1
&&
!
(
table
->
file
->
index_flags
(
idx
,
*
used_key_parts
-
1
,
1
)
&
HA_READ_PREV
))
reverse
=
0
;
// Index can't be used
DBUG_RETURN
(
reverse
);
DBUG_RETURN
(
reverse
);
}
}
...
@@ -10288,14 +10347,11 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
...
@@ -10288,14 +10347,11 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
if
(
!
select
->
quick
->
reverse_sorted
())
if
(
!
select
->
quick
->
reverse_sorted
())
{
{
int
quick_type
=
select
->
quick
->
get_type
();
int
quick_type
=
select
->
quick
->
get_type
();
/* here used_key_parts >0 */
if
(
quick_type
==
QUICK_SELECT_I
::
QS_TYPE_INDEX_MERGE
||
if
(
!
(
table
->
file
->
index_flags
(
ref_key
,
used_key_parts
-
1
,
1
)
&
HA_READ_PREV
)
||
quick_type
==
QUICK_SELECT_I
::
QS_TYPE_INDEX_MERGE
||
quick_type
==
QUICK_SELECT_I
::
QS_TYPE_ROR_INTERSECT
||
quick_type
==
QUICK_SELECT_I
::
QS_TYPE_ROR_INTERSECT
||
quick_type
==
QUICK_SELECT_I
::
QS_TYPE_ROR_UNION
||
quick_type
==
QUICK_SELECT_I
::
QS_TYPE_ROR_UNION
||
quick_type
==
QUICK_SELECT_I
::
QS_TYPE_GROUP_MIN_MAX
)
quick_type
==
QUICK_SELECT_I
::
QS_TYPE_GROUP_MIN_MAX
)
DBUG_RETURN
(
0
);
// Use filesort
DBUG_RETURN
(
0
);
// Use filesort
/* ORDER BY range_key DESC */
/* ORDER BY range_key DESC */
QUICK_SELECT_DESC
*
tmp
=
new
QUICK_SELECT_DESC
((
QUICK_RANGE_SELECT
*
)(
select
->
quick
),
QUICK_SELECT_DESC
*
tmp
=
new
QUICK_SELECT_DESC
((
QUICK_RANGE_SELECT
*
)(
select
->
quick
),
...
@@ -10317,9 +10373,6 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
...
@@ -10317,9 +10373,6 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
Use a traversal function that starts by reading the last row
Use a traversal function that starts by reading the last row
with key part (A) and then traverse the index backwards.
with key part (A) and then traverse the index backwards.
*/
*/
if
(
!
(
table
->
file
->
index_flags
(
ref_key
,
used_key_parts
-
1
,
1
)
&
HA_READ_PREV
))
DBUG_RETURN
(
0
);
// Use filesort
tab
->
read_first_record
=
join_read_last_key
;
tab
->
read_first_record
=
join_read_last_key
;
tab
->
read_record
.
read_record
=
join_read_prev_same
;
tab
->
read_record
.
read_record
=
join_read_prev_same
;
/* fall through */
/* fall through */
...
@@ -10365,7 +10418,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
...
@@ -10365,7 +10418,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
if
(
keys
.
is_set
(
nr
))
if
(
keys
.
is_set
(
nr
))
{
{
int
flag
;
int
flag
;
if
((
flag
=
test_if_order_by_key
(
order
,
table
,
nr
,
&
not_used
)))
if
((
flag
=
test_if_order_by_key
(
order
,
table
,
nr
,
&
not_used
)))
{
{
if
(
!
no_changes
)
if
(
!
no_changes
)
{
{
...
@@ -11150,7 +11203,7 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
...
@@ -11150,7 +11203,7 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
ORDER
*
order
,
List
<
Item
>
&
fields
,
List
<
Item
>
&
all_fields
,
ORDER
*
order
,
List
<
Item
>
&
fields
,
List
<
Item
>
&
all_fields
,
bool
is_group_field
)
bool
is_group_field
)
{
{
Item
*
order_item
=*
order
->
item
;
/* The item from the GROUP/ORDER caluse. */
Item
*
order_item
=
*
order
->
item
;
/* The item from the GROUP/ORDER caluse. */
Item
::
Type
order_item_type
;
Item
::
Type
order_item_type
;
Item
**
select_item
;
/* The corresponding item from the SELECT clause. */
Item
**
select_item
;
/* The corresponding item from the SELECT clause. */
Field
*
from_field
;
/* The corresponding field from the FROM clause. */
Field
*
from_field
;
/* The corresponding field from the FROM clause. */
...
@@ -11161,8 +11214,7 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
...
@@ -11161,8 +11214,7 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
if
(
!
count
||
count
>
fields
.
elements
)
if
(
!
count
||
count
>
fields
.
elements
)
{
{
my_printf_error
(
ER_BAD_FIELD_ERROR
,
ER
(
ER_BAD_FIELD_ERROR
),
my_printf_error
(
ER_BAD_FIELD_ERROR
,
ER
(
ER_BAD_FIELD_ERROR
),
MYF
(
0
),
order_item
->
full_name
(),
MYF
(
0
),
order_item
->
full_name
(),
thd
->
where
);
thd
->
where
);
return
1
;
return
1
;
}
}
order
->
item
=
ref_pointer_array
+
count
-
1
;
order
->
item
=
ref_pointer_array
+
count
-
1
;
...
@@ -11173,8 +11225,9 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
...
@@ -11173,8 +11225,9 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
}
}
/* Lookup the current GROUP/ORDER field in the SELECT clause. */
/* Lookup the current GROUP/ORDER field in the SELECT clause. */
uint
counter
;
uint
counter
;
bool
unaliased
;
select_item
=
find_item_in_list
(
order_item
,
fields
,
&
counter
,
select_item
=
find_item_in_list
(
order_item
,
fields
,
&
counter
,
REPORT_EXCEPT_NOT_FOUND
);
REPORT_EXCEPT_NOT_FOUND
,
&
unaliased
);
if
(
!
select_item
)
if
(
!
select_item
)
return
1
;
/* Some error occured. */
return
1
;
/* Some error occured. */
...
@@ -11182,6 +11235,14 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
...
@@ -11182,6 +11235,14 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
/* Check whether the resolved field is not ambiguos. */
/* Check whether the resolved field is not ambiguos. */
if
(
select_item
!=
not_found_item
)
if
(
select_item
!=
not_found_item
)
{
{
/*
If we have found field not by its alias in select list but by its
original field name, we should additionaly check if we have conflict
for this name (in case if we would perform lookup in all tables).
*/
if
(
unaliased
&&
!
order_item
->
fixed
&&
order_item
->
fix_fields
(
thd
,
tables
,
order
->
item
))
return
1
;
/* Lookup the current GROUP field in the FROM clause. */
/* Lookup the current GROUP field in the FROM clause. */
order_item_type
=
order_item
->
type
();
order_item_type
=
order_item
->
type
();
if
(
is_group_field
&&
if
(
is_group_field
&&
...
@@ -11215,16 +11276,15 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
...
@@ -11215,16 +11276,15 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
}
}
order
->
in_field_list
=
0
;
order
->
in_field_list
=
0
;
Item
*
it
=
*
order
->
item
;
/*
/*
We check
it
->fixed because Item_func_group_concat can put
We check
order_item
->fixed because Item_func_group_concat can put
arguments for which fix_fields already was called.
arguments for which fix_fields already was called.
'it' reassigned in if condition because fix_field can change it.
'it' reassigned in if condition because fix_field can change it.
*/
*/
if
(
!
it
->
fixed
&&
if
(
!
order_item
->
fixed
&&
(
it
->
fix_fields
(
thd
,
tables
,
order
->
item
)
||
(
order_item
->
fix_fields
(
thd
,
tables
,
order
->
item
)
||
(
it
=
*
order
->
item
)
->
check_cols
(
1
)
||
(
order_item
=
*
order
->
item
)
->
check_cols
(
1
)
||
thd
->
is_fatal_error
))
thd
->
is_fatal_error
))
return
1
;
// Wrong field
return
1
;
// Wrong field
uint
el
=
all_fields
.
elements
;
uint
el
=
all_fields
.
elements
;
...
@@ -11234,6 +11294,7 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
...
@@ -11234,6 +11294,7 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
return
0
;
return
0
;
}
}
/*
/*
Change order to point at item in select list. If item isn't a number
Change order to point at item in select list. If item isn't a number
and doesn't exits in the select list, add it the the field list.
and doesn't exits in the select list, add it the the field list.
...
@@ -11344,10 +11405,11 @@ setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields,
...
@@ -11344,10 +11405,11 @@ setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields,
thd
->
set_query_id
=
1
;
// Not really needed, but...
thd
->
set_query_id
=
1
;
// Not really needed, but...
uint
counter
;
uint
counter
;
bool
not_used
;
for
(;
new_field
;
new_field
=
new_field
->
next
)
for
(;
new_field
;
new_field
=
new_field
->
next
)
{
{
if
((
item
=
find_item_in_list
(
*
new_field
->
item
,
fields
,
&
counter
,
if
((
item
=
find_item_in_list
(
*
new_field
->
item
,
fields
,
&
counter
,
IGNORE_ERRORS
)))
IGNORE_ERRORS
,
&
not_used
)))
new_field
->
item
=
item
;
/* Change to shared Item */
new_field
->
item
=
item
;
/* Change to shared Item */
else
else
{
{
...
@@ -11695,7 +11757,7 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
...
@@ -11695,7 +11757,7 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
saved value
saved value
*/
*/
Field
*
field
=
item
->
field
;
Field
*
field
=
item
->
field
;
item
->
result_field
=
field
->
new_field
(
&
thd
->
mem_root
,
field
->
table
);
item
->
result_field
=
field
->
new_field
(
thd
->
mem_root
,
field
->
table
);
char
*
tmp
=
(
char
*
)
sql_alloc
(
field
->
pack_length
()
+
1
);
char
*
tmp
=
(
char
*
)
sql_alloc
(
field
->
pack_length
()
+
1
);
if
(
!
tmp
)
if
(
!
tmp
)
goto
err
;
goto
err
;
...
@@ -11705,6 +11767,8 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
...
@@ -11705,6 +11767,8 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
}
}
}
}
else
if
((
pos
->
type
()
==
Item
::
FUNC_ITEM
||
else
if
((
pos
->
type
()
==
Item
::
FUNC_ITEM
||
pos
->
type
()
==
Item
::
SUBSELECT_ITEM
||
pos
->
type
()
==
Item
::
CACHE_ITEM
||
pos
->
type
()
==
Item
::
COND_ITEM
)
&&
pos
->
type
()
==
Item
::
COND_ITEM
)
&&
!
pos
->
with_sum_func
)
!
pos
->
with_sum_func
)
{
// Save for send fields
{
// Save for send fields
...
@@ -11812,9 +11876,6 @@ bool JOIN::alloc_func_list()
...
@@ -11812,9 +11876,6 @@ bool JOIN::alloc_func_list()
before_group_by Set to 1 if this is called before GROUP BY handling
before_group_by Set to 1 if this is called before GROUP BY handling
recompute Set to TRUE if sum_funcs must be recomputed
recompute Set to TRUE if sum_funcs must be recomputed
NOTES
Calls ::setup() for all item_sum objects in field_list
RETURN
RETURN
0 ok
0 ok
1 error
1 error
...
@@ -11835,12 +11896,7 @@ bool JOIN::make_sum_func_list(List<Item> &field_list, List<Item> &send_fields,
...
@@ -11835,12 +11896,7 @@ bool JOIN::make_sum_func_list(List<Item> &field_list, List<Item> &send_fields,
while
((
item
=
it
++
))
while
((
item
=
it
++
))
{
{
if
(
item
->
type
()
==
Item
::
SUM_FUNC_ITEM
&&
!
item
->
const_item
())
if
(
item
->
type
()
==
Item
::
SUM_FUNC_ITEM
&&
!
item
->
const_item
())
{
*
func
++=
(
Item_sum
*
)
item
;
*
func
++=
(
Item_sum
*
)
item
;
/* let COUNT(DISTINCT) create the temporary table */
if
(((
Item_sum
*
)
item
)
->
setup
(
thd
))
DBUG_RETURN
(
TRUE
);
}
}
}
if
(
before_group_by
&&
rollup
.
state
==
ROLLUP
::
STATE_INITED
)
if
(
before_group_by
&&
rollup
.
state
==
ROLLUP
::
STATE_INITED
)
{
{
...
@@ -11985,6 +12041,30 @@ change_refs_to_tmp_fields(THD *thd, Item **ref_pointer_array,
...
@@ -11985,6 +12041,30 @@ change_refs_to_tmp_fields(THD *thd, Item **ref_pointer_array,
Code for calculating functions
Code for calculating functions
******************************************************************************/
******************************************************************************/
/*
Call ::setup for all sum functions
SYNOPSIS
setup_sum_funcs()
thd thread handler
func_ptr sum function list
RETURN
FALSE ok
TRUE error
*/
static
bool
setup_sum_funcs
(
THD
*
thd
,
Item_sum
**
func_ptr
)
{
Item_sum
*
func
;
while
((
func
=
*
(
func_ptr
++
)))
if
(
func
->
setup
(
thd
))
return
TRUE
;
return
FALSE
;
}
static
void
static
void
init_tmptable_sum_functions
(
Item_sum
**
func_ptr
)
init_tmptable_sum_functions
(
Item_sum
**
func_ptr
)
{
{
...
@@ -12140,7 +12220,7 @@ bool JOIN::rollup_init()
...
@@ -12140,7 +12220,7 @@ bool JOIN::rollup_init()
return
1
;
return
1
;
rollup
.
ref_pointer_arrays
=
(
Item
***
)
(
rollup
.
fields
+
send_group_parts
);
rollup
.
ref_pointer_arrays
=
(
Item
***
)
(
rollup
.
fields
+
send_group_parts
);
ref_array
=
(
Item
**
)
(
rollup
.
ref_pointer_arrays
+
send_group_parts
);
ref_array
=
(
Item
**
)
(
rollup
.
ref_pointer_arrays
+
send_group_parts
);
rollup
.
item_null
=
new
(
&
thd
->
mem_root
)
Item_null
();
rollup
.
item_null
=
new
(
thd
->
mem_root
)
Item_null
();
/*
/*
Prepare space for field list for the different levels
Prepare space for field list for the different levels
...
...
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