diff options
author | unknown <monty@mysql.com> | 2004-10-29 19:26:52 +0300 |
---|---|---|
committer | unknown <monty@mysql.com> | 2004-10-29 19:26:52 +0300 |
commit | f095274fe8c3d3394d6c0ce0a68f4bea04311999 (patch) | |
tree | 23bcc9a71fe7237887a111b158e30f5a6bb665d3 /sql/sql_union.cc | |
parent | f41bba8c6156a7adf4c67dfa75e16112767a5d3c (diff) | |
parent | 5be6c328f5a9f78f37176bbbd88a538fa3b65fe9 (diff) | |
download | mariadb-git-f095274fe8c3d3394d6c0ce0a68f4bea04311999.tar.gz |
merge with 4.1
BitKeeper/etc/ignore:
auto-union
BitKeeper/etc/logging_ok:
auto-union
BitKeeper/triggers/post-commit:
Auto merged
Docs/Support/texi2html:
Auto merged
Makefile.am:
Auto merged
client/Makefile.am:
Auto merged
client/mysql.cc:
Auto merged
client/mysqldump.c:
Auto merged
include/my_base.h:
Auto merged
include/my_global.h:
Auto merged
include/my_pthread.h:
Auto merged
include/my_sys.h:
Auto merged
include/my_time.h:
Auto merged
include/mysql.h:
Auto merged
include/mysql_com.h:
Auto merged
innobase/buf/buf0buf.c:
Auto merged
innobase/include/row0mysql.h:
Auto merged
innobase/row/row0sel.c:
Auto merged
libmysql/libmysql.c:
Auto merged
libmysqld/examples/Makefile.am:
Auto merged
myisam/mi_check.c:
Auto merged
mysql-test/include/ps_modify.inc:
Auto merged
mysql-test/install_test_db.sh:
Auto merged
mysql-test/r/alter_table.result:
Auto merged
mysql-test/r/auto_increment.result:
Auto merged
mysql-test/r/bdb.result:
Auto merged
mysql-test/r/ctype_latin1_de.result:
Auto merged
mysql-test/r/ctype_recoding.result:
Auto merged
mysql-test/r/fulltext.result:
Auto merged
mysql-test/r/func_gconcat.result:
Auto merged
mysql-test/r/func_group.result:
Auto merged
mysql-test/r/func_if.result:
Auto merged
mysql-test/t/derived.test:
Auto merged
mysql-test/t/insert.test:
merge with 4.1
Fixed test case to not use 'if exists' when it shouldn't
mysql-test/t/range.test:
merge with 4.1
Added missing drop table
sql/ha_ndbcluster.cc:
merge with 4.1
Simple optimization: use max() instead of ? :
sql/item_func.cc:
merge with 4.1
(Added back old variable names for easier merges)
sql/opt_range.cc:
merge with 4.1
Removed argument 'parent_alloc' from QUICK_RANGE_SELECT as this was not used
Added assert if using QUICK_GROUP_MIN_MAX_SELECT with parent_alloc as the init() function can't handle this
Changed back get_quick_select_for_ref() to use it's own alloc root becasue this function may be called several times for one query
sql/sql_handler.cc:
merge with 4.1
change variable 'err' to 'error' as same function had a label named 'err'
sql/sql_update.cc:
Use multi-update code from 5.0 instead of 4.1
We will fix the locking code shortly in 5.0 to be faster than in 4.1
Diffstat (limited to 'sql/sql_union.cc')
-rw-r--r-- | sql/sql_union.cc | 73 |
1 files changed, 57 insertions, 16 deletions
diff --git a/sql/sql_union.cc b/sql/sql_union.cc index cf4203bf5b8..46f11683e4e 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -153,6 +153,7 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, SELECT_LEX *lex_select_save= thd_arg->lex->current_select; SELECT_LEX *sl, *first_select; select_result *tmp_result; + bool is_union; DBUG_ENTER("st_select_lex_unit::prepare"); describe= test(additional_options & SELECT_DESCRIBE); @@ -189,10 +190,11 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, thd_arg->lex->current_select= sl= first_select= first_select_in_union(); found_rows_for_union= first_select->options & OPTION_FOUND_ROWS; + is_union= test(first_select->next_select()); /* Global option */ - if (first_select->next_select()) + if (is_union) { if (!(tmp_result= union_result= new select_union(0))) goto err; @@ -201,14 +203,11 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, tmp_result= sel_result; } else - { tmp_result= sel_result; - // single select should be processed like select in p[arantses - first_select->braces= 1; - } for (;sl; sl= sl->next_select()) { + bool can_skip_order_by; sl->options|= SELECT_NO_UNLOCK; JOIN *join= new JOIN(thd_arg, sl->item_list, sl->options | thd_arg->options | additional_options, @@ -220,18 +219,26 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, set_limit(sl, sl); if (sl->braces) sl->options&= ~OPTION_FOUND_ROWS; + + can_skip_order_by= is_union && + (!sl->braces || select_limit_cnt == HA_POS_ERROR); res= join->prepare(&sl->ref_pointer_array, (TABLE_LIST*) sl->table_list.first, sl->with_wild, sl->where, - ((sl->braces) ? sl->order_list.elements : 0) + - sl->group_list.elements, - (sl->braces) ? - (ORDER *)sl->order_list.first : (ORDER *) 0, + (can_skip_order_by ? 0 : sl->order_list.elements) + + sl->group_list.elements, + can_skip_order_by ? + (ORDER*) 0 : (ORDER *)sl->order_list.first, (ORDER*) sl->group_list.first, sl->having, - (ORDER*) NULL, + (is_union ? (ORDER*) 0 : + (ORDER*) thd_arg->lex->proc_list.first), sl, this); + /* There are no * in the statement anymore (for PS) */ + sl->with_wild= 0; + last_procedure= join->procedure; + if (res || thd_arg->is_fatal_error) goto err; if (sl == first_select) @@ -267,9 +274,26 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, } } - // it is not single select - if (first_select->next_select()) + if (is_union) { + /* + Check that it was possible to aggregate + all collations together for UNION. + */ + List_iterator_fast<Item> tp(types); + Item_arena *arena= thd->current_arena; + Item *type; + + while ((type= tp++)) + { + if (type->result_type() == STRING_RESULT && + type->collation.derivation == DERIVATION_NONE) + { + my_error(ER_CANT_AGGREGATE_NCOLLATIONS, MYF(0), "UNION"); + goto err; + } + } + union_result->tmp_table_param.field_count= types.elements; if (!(table= create_tmp_table(thd_arg, &union_result->tmp_table_param, types, @@ -291,7 +315,6 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, if (!item_list.elements) { Field **field; - Item_arena *arena= thd->current_arena; Item_arena backup; if (arena->is_conventional()) arena= 0; @@ -334,14 +357,27 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, 0, 0, fake_select_lex->order_list.elements, (ORDER*) fake_select_lex->order_list.first, - (ORDER*) NULL, NULL, (ORDER*) NULL, + (ORDER*) NULL, NULL, + (ORDER*) NULL, fake_select_lex, this); fake_select_lex->table_list.empty(); } } + else if (!arena->is_conventional()) + { + /* + We're in execution of a prepared statement or stored procedure: + reset field items to point at fields from the created temporary table. + */ + List_iterator_fast<Item> it(item_list); + for (Field **field= table->field; *field; field++) + { + Item_field *item_field= (Item_field*) it++; + DBUG_ASSERT(item_field); + item_field->reset_field(*field); + } + } } - else - first_select->braces= 0; // remove our changes thd_arg->lex->current_select= lex_select_save; @@ -358,6 +394,7 @@ int st_select_lex_unit::exec() SELECT_LEX *lex_select_save= thd->lex->current_select; SELECT_LEX *select_cursor=first_select_in_union(); ulonglong add_rows=0; + ha_rows examined_rows= 0; DBUG_ENTER("st_select_lex_unit::exec"); if (executed && !uncacheable && !describe) @@ -438,6 +475,7 @@ int st_select_lex_unit::exec() offset_limit_cnt= sl->offset_limit; if (!res && union_result->flush()) { + examined_rows+= thd->examined_row_count; thd->lex->current_select= lex_select_save; DBUG_RETURN(1); } @@ -516,7 +554,10 @@ int st_select_lex_unit::exec() fake_select_lex->table_list.empty(); if (!res) + { thd->limit_found_rows = (ulonglong)table->file->records + add_rows; + thd->examined_row_count+= examined_rows; + } /* Mark for slow query log if any of the union parts didn't use indexes efficiently |