diff options
-rw-r--r-- | client/mysqltest.c | 2 | ||||
-rw-r--r-- | mysql-test/r/group_by.result | 4 | ||||
-rw-r--r-- | mysql-test/r/heap_hash.result | 10 | ||||
-rw-r--r-- | mysql-test/r/subselect.result | 38 | ||||
-rw-r--r-- | mysql-test/r/user_var.result | 4 | ||||
-rw-r--r-- | mysql-test/t/group_by.test | 3 | ||||
-rw-r--r-- | mysql-test/t/heap_hash.test | 6 | ||||
-rw-r--r-- | mysql-test/t/subselect.test | 30 | ||||
-rw-r--r-- | mysys/my_rename.c | 2 | ||||
-rw-r--r-- | ndb/src/kernel/vm/FastScheduler.cpp | 42 | ||||
-rw-r--r-- | netware/mysql_test_run.c | 5 | ||||
-rw-r--r-- | sql/ha_heap.cc | 13 | ||||
-rw-r--r-- | sql/item.cc | 52 | ||||
-rw-r--r-- | sql/item.h | 3 | ||||
-rw-r--r-- | sql/item_cmpfunc.cc | 56 | ||||
-rw-r--r-- | sql/item_func.cc | 19 | ||||
-rw-r--r-- | sql/item_row.cc | 18 | ||||
-rw-r--r-- | sql/item_strfunc.cc | 14 | ||||
-rw-r--r-- | sql/item_subselect.cc | 6 | ||||
-rw-r--r-- | sql/sql_list.h | 9 | ||||
-rw-r--r-- | sql/sql_select.cc | 15 |
21 files changed, 161 insertions, 190 deletions
diff --git a/client/mysqltest.c b/client/mysqltest.c index 4d03746a5e5..7bdcf6db3e5 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -2379,6 +2379,8 @@ void usage() #include <help_end.h> +#include <help_end.h> + static my_bool get_one_option(int optid, const struct my_option *opt __attribute__((unused)), diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result index 24740442821..a43e67d57e6 100644 --- a/mysql-test/r/group_by.result +++ b/mysql-test/r/group_by.result @@ -655,9 +655,9 @@ insert into t1 (a,b) values (1,2),(1,3),(2,5); select a, 0.1*0+1 r2, sum(1) r1 from t1 where a = 1 group by a having r1>1 and r2=1; a r2 r1 1 1.0 2 -select a, rand()*0+1 r2, sum(1) r1 from t1 where a = 1 group by a having r1>1 and r2=1; +select a, round(rand(100)*10) r2, sum(1) r1 from t1 where a = 1 group by a having r1>1 and r2<=2; a r2 r1 -1 1 2 +1 2 2 select a,sum(b) from t1 where a=1 group by c; a sum(b) 1 5 diff --git a/mysql-test/r/heap_hash.result b/mysql-test/r/heap_hash.result index 287e17a264d..1e6eb866fd6 100644 --- a/mysql-test/r/heap_hash.result +++ b/mysql-test/r/heap_hash.result @@ -355,3 +355,13 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t3 ref a a 44 const,const 6 Using where 1 SIMPLE t1 ref heap_idx heap_idx 22 const 7 Using where drop table t1, t2, t3; +create temporary table t1 ( a int, index (a) ) engine=memory; +insert into t1 values (1),(2),(3),(4),(5); +select a from t1 where a in (1,3); +a +1 +3 +explain select a from t1 where a in (1,3); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range a a 5 NULL 2 Using where +drop table t1; diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 2e9f199e8bb..67d3287c16f 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -1433,7 +1433,7 @@ Note 1003 (select `test`.`t1`.`s1` AS `s1` from `test`.`t1`) s1 tttt drop table t1; -create table t1 (s1 char(5) not null, index s1(s1)); +create table t1 (s1 char(5), index s1(s1)); create table t2 (s1 char(5), index s1(s1)); insert into t1 values ('a1'),('a2'),('a3'); insert into t2 values ('a1'),('a2'); @@ -1459,25 +1459,25 @@ a2 1 a3 1 explain extended select s1, s1 NOT IN (SELECT s1 FROM t2) from t1; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 index NULL s1 5 NULL 3 Using index +1 PRIMARY t1 index NULL s1 6 NULL 3 Using index 2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 2 Using index Warnings: Note 1003 select `test`.`t1`.`s1` AS `s1`,not(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL)))) AS `s1 NOT IN (SELECT s1 FROM t2)` from `test`.`t1` explain extended select s1, s1 = ANY (SELECT s1 FROM t2) from t1; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 index NULL s1 5 NULL 3 Using index +1 PRIMARY t1 index NULL s1 6 NULL 3 Using index 2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 2 Using index Warnings: Note 1003 select `test`.`t1`.`s1` AS `s1`,<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL))) AS `s1 = ANY (SELECT s1 FROM t2)` from `test`.`t1` explain extended select s1, s1 <> ALL (SELECT s1 FROM t2) from t1; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 index NULL s1 5 NULL 3 Using index +1 PRIMARY t1 index NULL s1 6 NULL 3 Using index 2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 2 Using index Warnings: Note 1003 select `test`.`t1`.`s1` AS `s1`,not(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL)))) AS `s1 <> ALL (SELECT s1 FROM t2)` from `test`.`t1` explain extended select s1, s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2') from t1; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 index NULL s1 5 NULL 3 Using index +1 PRIMARY t1 index NULL s1 6 NULL 3 Using index 2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 1 Using index; Using where Warnings: Note 1003 select `test`.`t1`.`s1` AS `s1`,not(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL where (`test`.`t2`.`s1` < _latin1'a2'))))) AS `s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2')` from `test`.`t1` @@ -2133,34 +2133,6 @@ SELECT DISTINCT Continent AS c FROM t1 WHERE Code <> SOME ( SELECT Code FROM t1 c Oceania drop table t1; -CREATE TABLE t1 ( f1 BIGINT ); -INSERT INTO t1 SET f1= NULL; -INSERT INTO t1 SET f1= 1; -CREATE TABLE t2 ( f1 BIGINT ); -SELECT f1 FROM t1 -WHERE f1 <> ALL ( SELECT f1 FROM t2 ); -f1 -NULL -1 -INSERT INTO t2 VALUES (1), (2); -SELECT f1 FROM t1 -WHERE f1 <> ALL ( SELECT f1 FROM t2 WHERE f1 > 2 ); -f1 -NULL -1 -SELECT f1 FROM t1 -WHERE f1 <> ALL ( SELECT f1 FROM t2 WHERE f1 > 2 -UNION -SELECT f1 FROM t2 WHERE f1 > 3); -f1 -NULL -1 -SELECT f1 FROM t1 -WHERE f1 <> ALL ( SELECT SUM(f1) AS sf1 FROM t2 HAVING sf1 > 10000); -f1 -NULL -1 -drop table t1,t2; create table t1 (a1 int); create table t2 (b1 int); select * from t1 where a2 > any(select b1 from t2); diff --git a/mysql-test/r/user_var.result b/mysql-test/r/user_var.result index ba5cb264013..bacd8311a1e 100644 --- a/mysql-test/r/user_var.result +++ b/mysql-test/r/user_var.result @@ -113,8 +113,8 @@ select @a:=0; select @a, @a:=@a+count(*), count(*), @a from t1 group by i; @a @a:=@a+count(*) count(*) @a 0 1 1 0 -0 3 2 0 -0 6 3 0 +0 2 2 0 +0 3 3 0 select @a:=0; @a:=0 0 diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test index 379f668df1a..afd479c520e 100644 --- a/mysql-test/t/group_by.test +++ b/mysql-test/t/group_by.test @@ -480,7 +480,8 @@ drop table t1; create table t1 (a integer, b integer, c integer); insert into t1 (a,b) values (1,2),(1,3),(2,5); select a, 0.1*0+1 r2, sum(1) r1 from t1 where a = 1 group by a having r1>1 and r2=1; -select a, rand()*0+1 r2, sum(1) r1 from t1 where a = 1 group by a having r1>1 and r2=1; +# rand(100)*10 will be < 2 only for the first row (of 6) +select a, round(rand(100)*10) r2, sum(1) r1 from t1 where a = 1 group by a having r1>1 and r2<=2; select a,sum(b) from t1 where a=1 group by c; select a*sum(b) from t1 where a=1 group by c; select sum(a)*sum(b) from t1 where a=1 group by c; diff --git a/mysql-test/t/heap_hash.test b/mysql-test/t/heap_hash.test index 6d8fdec4b9e..6d27f19dfad 100644 --- a/mysql-test/t/heap_hash.test +++ b/mysql-test/t/heap_hash.test @@ -251,3 +251,9 @@ explain select * from t1 ignore key(btree_idx), t3 where t1.name='matt' and t3.a drop table t1, t2, t3; +# Fix for BUG#8371: wrong rec_per_key value for hash index on temporary table +create temporary table t1 ( a int, index (a) ) engine=memory; +insert into t1 values (1),(2),(3),(4),(5); +select a from t1 where a in (1,3); +explain select a from t1 where a in (1,3); +drop table t1; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 9baf082487f..7b75686ab4e 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -894,7 +894,7 @@ drop table t1; # # IN optimisation test results # -create table t1 (s1 char(5) not null, index s1(s1)); +create table t1 (s1 char(5), index s1(s1)); create table t2 (s1 char(5), index s1(s1)); insert into t1 values ('a1'),('a2'),('a3'); insert into t2 values ('a1'),('a2'); @@ -1393,34 +1393,6 @@ SELECT DISTINCT Continent AS c FROM t1 WHERE Code <> SOME ( SELECT Code FROM t1 drop table t1; # -# Test cases for bug #7351: -# quantified predicate with subquery returning empty result set -# - -CREATE TABLE t1 ( f1 BIGINT ); -INSERT INTO t1 SET f1= NULL; -INSERT INTO t1 SET f1= 1; -CREATE TABLE t2 ( f1 BIGINT ); - -SELECT f1 FROM t1 - WHERE f1 <> ALL ( SELECT f1 FROM t2 ); - -INSERT INTO t2 VALUES (1), (2); - -SELECT f1 FROM t1 - WHERE f1 <> ALL ( SELECT f1 FROM t2 WHERE f1 > 2 ); - -SELECT f1 FROM t1 - WHERE f1 <> ALL ( SELECT f1 FROM t2 WHERE f1 > 2 - UNION - SELECT f1 FROM t2 WHERE f1 > 3); - -SELECT f1 FROM t1 - WHERE f1 <> ALL ( SELECT SUM(f1) AS sf1 FROM t2 HAVING sf1 > 10000); - -drop table t1,t2; - -# # Test for BUG#7885: Server crash when 'any' subselect compared to # non-existant field. # diff --git a/mysys/my_rename.c b/mysys/my_rename.c index d4f99e83247..b5d813ad787 100644 --- a/mysys/my_rename.c +++ b/mysys/my_rename.c @@ -45,7 +45,7 @@ int my_rename(const char *from, const char *to, myf MyFlags) } #endif #if defined(HAVE_RENAME) -#ifdef __WIN__ +#if defined(__WIN__) || defined(__NETWARE__) /* On windows we can't rename over an existing file: Remove any conflicting files: diff --git a/ndb/src/kernel/vm/FastScheduler.cpp b/ndb/src/kernel/vm/FastScheduler.cpp index a883882e452..a2d806571fe 100644 --- a/ndb/src/kernel/vm/FastScheduler.cpp +++ b/ndb/src/kernel/vm/FastScheduler.cpp @@ -85,7 +85,7 @@ FastScheduler::activateSendPacked() void FastScheduler::doJob() { - Uint32 init_loopCount = 0; + Uint32 loopCount = 0; Uint32 TminLoops = getBOccupancy() + EXTRA_SIGNALS_PER_DO_JOB; Uint32 TloopMax = (Uint32)globalData.loopMax; if (TminLoops < TloopMax) { @@ -94,10 +94,9 @@ FastScheduler::doJob() if (TloopMax < MIN_NUMBER_OF_SIG_PER_DO_JOB) { TloopMax = MIN_NUMBER_OF_SIG_PER_DO_JOB; }//if + register Signal* signal = getVMSignals(); + register Uint32 tHighPrio= globalData.highestAvailablePrio; do{ - Uint32 loopCount = init_loopCount; - register Uint32 tHighPrio = globalData.highestAvailablePrio; - register Signal* signal = getVMSignals(); while ((tHighPrio < LEVEL_IDLE) && (loopCount < TloopMax)) { // signal->garbage_register(); // To ensure we find bugs quickly @@ -155,24 +154,27 @@ FastScheduler::doJob() }//if loopCount++; }//while - if (globalData.sendPackedActivated == 1) { - Uint32 t1 = theDoJobTotalCounter; - Uint32 t2 = theDoJobCallCounter; - t1 += (loopCount - init_loopCount); - t2++; - theDoJobTotalCounter = t1; - theDoJobCallCounter = t2; - if (t2 == 8192) { - reportDoJobStatistics(t1 >> 13); - theDoJobCallCounter = 0; - theDoJobTotalCounter = 0; - }//if - }//if - init_loopCount = loopCount; sendPacked(); + tHighPrio = globalData.highestAvailablePrio; + if(getBOccupancy() > MAX_OCCUPANCY) + { + if(loopCount != TloopMax) + abort(); + assert( loopCount == TloopMax ); + TloopMax += 512; + } } while ((getBOccupancy() > MAX_OCCUPANCY) || - ((init_loopCount < TloopMax) && - (globalData.highestAvailablePrio < LEVEL_IDLE))); + ((loopCount < TloopMax) && + (tHighPrio < LEVEL_IDLE))); + + theDoJobCallCounter ++; + theDoJobTotalCounter += loopCount; + if (theDoJobCallCounter == 8192) { + reportDoJobStatistics(theDoJobTotalCounter >> 13); + theDoJobCallCounter = 0; + theDoJobTotalCounter = 0; + }//if + }//FastScheduler::doJob() void FastScheduler::sendPacked() diff --git a/netware/mysql_test_run.c b/netware/mysql_test_run.c index fd5725a6414..d8cfb79c1cb 100644 --- a/netware/mysql_test_run.c +++ b/netware/mysql_test_run.c @@ -192,7 +192,7 @@ void install_db(char *datadir) char error[PATH_MAX]; // input file - snprintf(input, PATH_MAX, "%s/bin/init_db.sql", base_dir); + snprintf(input, PATH_MAX, "%s/bin/test_db.sql", base_dir); snprintf(output, PATH_MAX, "%s/install.out", datadir); snprintf(error, PATH_MAX, "%s/install.err", datadir); @@ -1160,7 +1160,8 @@ void setup(char *file) setenv("MASTER_MYPORT", "9306", 1); setenv("SLAVE_MYPORT", "9307", 1); setenv("MYSQL_TCP_PORT", "3306", 1); - + snprintf(file_path, PATH_MAX*2, "%s/mysql_client_test --no-defaults --testcase--user=root --port=%u ", bin_dir, master_port); + setenv("MYSQL_CLIENT_TEST",file_path,1); } /****************************************************************************** diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc index 02d81882e7a..d30435310dc 100644 --- a/sql/ha_heap.cc +++ b/sql/ha_heap.cc @@ -60,8 +60,7 @@ int ha_heap::open(const char *name, int mode, uint test_if_locked) { /* Initialize variables for the opened table */ set_keys_for_scanning(); - if (table->s->tmp_table == NO_TMP_TABLE) - update_key_stats(); + update_key_stats(); } return (file ? 0 : 1); } @@ -104,6 +103,8 @@ void ha_heap::update_key_stats() for (uint i= 0; i < table->s->keys; i++) { KEY *key=table->key_info+i; + if (!key->rec_per_key) + continue; if (key->algorithm != HA_KEY_ALG_BTREE) { ha_rows hash_buckets= file->s->keydef[i].hash_buckets; @@ -124,8 +125,8 @@ int ha_heap::write_row(byte * buf) if (table->next_number_field && buf == table->record[0]) update_auto_increment(); res= heap_write(file,buf); - if (!res && table->s->tmp_table == NO_TMP_TABLE && - ++records_changed*HEAP_STATS_UPDATE_THRESHOLD > file->s->records) + if (!res && (++records_changed*HEAP_STATS_UPDATE_THRESHOLD > + file->s->records)) update_key_stats(); return res; } @@ -137,8 +138,8 @@ int ha_heap::update_row(const byte * old_data, byte * new_data) if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE) table->timestamp_field->set_time(); res= heap_update(file,old_data,new_data); - if (!res && table->s->tmp_table == NO_TMP_TABLE && - ++records_changed*HEAP_STATS_UPDATE_THRESHOLD > file->s->records) + if (!res && ++records_changed*HEAP_STATS_UPDATE_THRESHOLD > + file->s->records) update_key_stats(); return res; } diff --git a/sql/item.cc b/sql/item.cc index 17ded05766f..96806ea2ed1 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -543,6 +543,58 @@ void Item_splocal::print(String *str) /* + Move SUM items out from item tree and replace with reference + + SYNOPSIS + split_sum_func2() + thd Thread handler + ref_pointer_array Pointer to array of reference fields + fields All fields in select + ref Pointer to item + + NOTES + This is from split_sum_func2() for items that should be split + + All found SUM items are added FIRST in the fields list and + we replace the item with a reference. + + thd->fatal_error() may be called if we are out of memory +*/ + + +void Item::split_sum_func2(THD *thd, Item **ref_pointer_array, + List<Item> &fields, Item **ref) +{ + if (type() != SUM_FUNC_ITEM && with_sum_func) + { + /* Will split complicated items and ignore simple ones */ + split_sum_func(thd, ref_pointer_array, fields); + } + else if ((type() == SUM_FUNC_ITEM || + (used_tables() & ~PARAM_TABLE_BIT)) && + type() != REF_ITEM) + { + /* + Replace item with a reference so that we can easily calculate + it (in case of sum functions) or copy it (in case of fields) + + The test above is to ensure we don't do a reference for things + that are constants (PARAM_TABLE_BIT is in effect a constant) + or already referenced (for example an item in HAVING) + */ + uint el= fields.elements; + Item *new_item; + ref_pointer_array[el]= this; + if (!(new_item= new Item_ref(ref_pointer_array + el, 0, name))) + return; // fatal_error is set + fields.push_front(this); + ref_pointer_array[el]= this; + thd->change_item_tree(ref, new_item); + } +} + + +/* Aggregate two collations together taking into account their coercibility (aka derivation): diff --git a/sql/item.h b/sql/item.h index ccbc00470e5..e2e72dbee40 100644 --- a/sql/item.h +++ b/sql/item.h @@ -334,6 +334,9 @@ public: virtual void update_used_tables() {} virtual void split_sum_func(THD *thd, Item **ref_pointer_array, List<Item> &fields) {} + /* Called for items that really have to be split */ + void split_sum_func2(THD *thd, Item **ref_pointer_array, List<Item> &fields, + Item **ref); virtual bool get_date(TIME *ltime,uint fuzzydate); virtual bool get_time(TIME *ltime); virtual bool get_date_result(TIME *ltime,uint fuzzydate) diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 71a4e4dda53..c26365e3f0e 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -704,13 +704,12 @@ longlong Item_in_optimizer::val_int() { DBUG_ASSERT(fixed == 1); cache->store(args[0]); - longlong tmp= args[1]->val_int_result(); if (cache->null_value) { - if (tmp) - null_value= 1; + null_value= 1; return 0; } + longlong tmp= args[1]->val_int_result(); null_value= args[1]->null_value; return tmp; } @@ -2349,10 +2348,10 @@ Item *Item_cond::transform(Item_transformer transformer, byte *arg) Move SUM items out from item tree and replace with reference SYNOPSIS - split_sum_func() - thd Thread handler - ref_pointer_array Pointer to array of reference fields - fields All fields in select + split_sum_func() + thd Thread handler + ref_pointer_array Pointer to array of reference fields + fields All fields in select NOTES This function is run on all expression (SELECT list, WHERE, HAVING etc) @@ -2362,16 +2361,6 @@ Item *Item_cond::transform(Item_transformer transformer, byte *arg) so that we can easily find and calculate them. (Calculation done by update_sum_func() and copy_sum_funcs() in sql_select.cc) - - All found SUM items are added FIRST in the fields list and - we replace the item with a reference. - - We also replace all functions without side effects (like RAND() or UDF's) - that uses columns as arguments. - For functions with side effects, we just remember any fields referred - by the function to ensure that we get a copy of the field value for the - first accepted row. This ensures that we can do things like - SELECT a*SUM(b) FROM t1 WHERE a=1 */ void Item_cond::split_sum_func(THD *thd, Item **ref_pointer_array, @@ -2379,37 +2368,8 @@ void Item_cond::split_sum_func(THD *thd, Item **ref_pointer_array, { List_iterator<Item> li(list); Item *item; - used_tables_cache=0; - const_item_cache=1; - while ((item=li++)) - { - /* with_sum_func is set for items that contains a SUM expression */ - if (item->type() != SUM_FUNC_ITEM && - (item->with_sum_func || - (item->used_tables() & PSEUDO_TABLE_BITS))) - item->split_sum_func(thd, ref_pointer_array, fields); - else if (item->type() == SUM_FUNC_ITEM || - (item->used_tables() && item->type() != REF_ITEM)) - { - /* - Replace item with a reference so that we can easily calculate - it (in case of sum functions) or copy it (in case of fields) - - The test above is to ensure we don't do a reference for things - that are constants or are not yet calculated as in: - SELECT RAND() as r1, SUM(a) as r2 FROM t1 HAVING r1 > 1 AND r2 > 0 - */ - Item **ref= li.ref(); - uint el= fields.elements; - ref_pointer_array[el]= item; - Item *new_item= new Item_ref(ref_pointer_array + el, 0, item->name); - fields.push_front(item); - thd->change_item_tree(ref, new_item); - } - item->update_used_tables(); - used_tables_cache|=item->used_tables(); - const_item_cache&=item->const_item(); - } + while ((item= li++)) + item->split_sum_func2(thd, ref_pointer_array, fields, li.ref()); } diff --git a/sql/item_func.cc b/sql/item_func.cc index a4c1110da32..1e61474f412 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -401,27 +401,14 @@ Item *Item_func::transform(Item_transformer transformer, byte *argument) } +/* See comments in Item_cmp_func::split_sum_func() */ + void Item_func::split_sum_func(THD *thd, Item **ref_pointer_array, List<Item> &fields) { Item **arg, **arg_end; for (arg= args, arg_end= args+arg_count; arg != arg_end ; arg++) - { - Item *item=* arg; - if (item->type() != SUM_FUNC_ITEM && - (item->with_sum_func || - (item->used_tables() & PSEUDO_TABLE_BITS))) - item->split_sum_func(thd, ref_pointer_array, fields); - else if (item->type() == SUM_FUNC_ITEM || - (item->used_tables() && item->type() != REF_ITEM)) - { - uint el= fields.elements; - ref_pointer_array[el]= item; - Item *new_item= new Item_ref(ref_pointer_array + el, 0, item->name); - fields.push_front(item); - thd->change_item_tree(arg, new_item); - } - } + (*arg)->split_sum_func2(thd, ref_pointer_array, fields, arg); } diff --git a/sql/item_row.cc b/sql/item_row.cc index 08c682afa85..00d849e55de 100644 --- a/sql/item_row.cc +++ b/sql/item_row.cc @@ -90,24 +90,10 @@ void Item_row::split_sum_func(THD *thd, Item **ref_pointer_array, { Item **arg, **arg_end; for (arg= items, arg_end= items+arg_count; arg != arg_end ; arg++) - { - Item *item= *arg; - if (item->type() != SUM_FUNC_ITEM && - (item->with_sum_func || - (item->used_tables() & PSEUDO_TABLE_BITS))) - item->split_sum_func(thd, ref_pointer_array, fields); - else if (item->type() == SUM_FUNC_ITEM || - (item->used_tables() && item->type() != REF_ITEM)) - { - uint el= fields.elements; - ref_pointer_array[el]= *arg; - Item *new_item= new Item_ref(ref_pointer_array + el, 0, (*arg)->name); - fields.push_front(*arg); - thd->change_item_tree(arg, new_item); - } - } + (*arg)->split_sum_func2(thd, ref_pointer_array, fields, arg); } + void Item_row::update_used_tables() { used_tables_cache= 0; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 55185a5f75b..02f33d39465 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1778,19 +1778,7 @@ String *Item_func_elt::val_str(String *str) void Item_func_make_set::split_sum_func(THD *thd, Item **ref_pointer_array, List<Item> &fields) { - if (item->type() != SUM_FUNC_ITEM && - (item->with_sum_func || - (item->used_tables() & PSEUDO_TABLE_BITS))) - item->split_sum_func(thd, ref_pointer_array, fields); - else if (item->type() == SUM_FUNC_ITEM || - (item->used_tables() && item->type() != REF_ITEM)) - { - uint el= fields.elements; - ref_pointer_array[el]= item; - Item *new_item= new Item_ref(ref_pointer_array + el, 0, item->name); - fields.push_front(item); - thd->change_item_tree(&item, new_item); - } + item->split_sum_func2(thd, ref_pointer_array, fields, &item); Item_str_func::split_sum_func(thd, ref_pointer_array, fields); } diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 8d392232f02..fe849bd213a 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -889,8 +889,10 @@ Item_in_subselect::single_value_transformer(JOIN *join, ref_pointer_array, (char *)"<ref>", this->full_name())); +#ifdef CORRECT_BUT_TOO_SLOW_TO_BE_USABLE if (!abort_on_null && left_expr->maybe_null) item= new Item_cond_or(new Item_func_isnull(left_expr), item); +#endif /* AND and comparison functions can't be changed during fix_fields() we can assign select_lex->having here, and pass 0 as last @@ -944,8 +946,10 @@ Item_in_subselect::single_value_transformer(JOIN *join, goto err; item= new Item_cond_or(item, new Item_func_isnull(orig_item)); +#ifdef CORRECT_BUT_TOO_SLOW_TO_BE_USABLE if (left_expr->maybe_null) item= new Item_cond_or(new Item_func_isnull(left_expr), item); +#endif } item->name= (char *)in_additional_cond; /* @@ -975,8 +979,10 @@ Item_in_subselect::single_value_transformer(JOIN *join, new Item_null_helper(this, item, (char *)"<no matter>", (char *)"<result>")); +#ifdef CORRECT_BUT_TOO_SLOW_TO_BE_USABLE if (!abort_on_null && left_expr->maybe_null) item= new Item_cond_or(new Item_func_isnull(left_expr), item); +#endif select_lex->having= join->having= item; select_lex->having_fix_field= 1; /* diff --git a/sql/sql_list.h b/sql/sql_list.h index 657943f1e69..6317d215399 100644 --- a/sql/sql_list.h +++ b/sql/sql_list.h @@ -140,6 +140,15 @@ public: delete *prev; *prev=node; } + inline void concat(base_list *list) + { + if (!list->is_empty()) + { + *last= list->first; + last= list->last; + elements+= list->elements; + } + } inline void *pop(void) { if (first == &end_of_list) return 0; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 6af257893d4..f49f980f364 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -8247,6 +8247,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, keyinfo->key_length=(uint16) reclength; keyinfo->name= (char*) "distinct_key"; keyinfo->algorithm= HA_KEY_ALG_UNDEF; + keyinfo->rec_per_key=0; if (null_pack_length) { key_part_info->null_bit=0; @@ -11831,6 +11832,7 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, res_selected_fields.empty(); res_all_fields.empty(); List_iterator_fast<Item> itr(res_all_fields); + List<Item> extra_funcs; uint i, border= all_fields.elements - elements; DBUG_ENTER("setup_copy_fields"); @@ -11892,7 +11894,12 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, */ if (!(pos=new Item_copy_string(pos))) goto err; - if (param->copy_funcs.push_back(pos)) + if (i < border) // HAVING, ORDER and GROUP BY + { + if (extra_funcs.push_back(pos)) + goto err; + } + else if (param->copy_funcs.push_back(pos)) goto err; } res_all_fields.push_back(pos); @@ -11904,6 +11911,12 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, for (i= 0; i < border; i++) itr++; itr.sublist(res_selected_fields, elements); + /* + Put elements from HAVING, ORDER BY and GROUP BY last to ensure that any + reference used in these will resolve to a item that is already calculated + */ + param->copy_funcs.concat(&extra_funcs); + DBUG_RETURN(0); err: |