summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <monty@mysql.com>2005-02-10 02:27:37 +0200
committerunknown <monty@mysql.com>2005-02-10 02:27:37 +0200
commit9f04f9d0352e404cf64e044d1c22873595f276d2 (patch)
tree5b603904b731e515c447d53d7843855bfbbe2f8c
parent70d3ac05d97f7721e564a718ba79afd5eb7eb2cb (diff)
parent0fe1b28b750c12dd500e507f1b688887c9aca227 (diff)
downloadmariadb-git-9f04f9d0352e404cf64e044d1c22873595f276d2.tar.gz
Merge with 4.1
BitKeeper/etc/ignore: auto-union client/mysqltest.c: Auto merged extra/my_print_defaults.c: Auto merged extra/perror.c: Auto merged extra/resolve_stack_dump.c: Auto merged include/help_end.h: Auto merged include/help_start.h: Auto merged myisam/myisamlog.c: Auto merged mysql-test/r/group_by.result: Auto merged mysql-test/r/heap_hash.result: Auto merged BitKeeper/deleted/.del-pack_isam.c~43801f0df7504834: Auto merged mysql-test/r/subselect.result: Auto merged mysql-test/r/user_var.result: Auto merged mysql-test/t/subselect.test: Auto merged ndb/src/kernel/vm/FastScheduler.cpp: Auto merged netware/mysql_test_run.c: Auto merged sql/item.cc: Auto merged sql/item.h: Auto merged sql/mysqld.cc: Auto merged sql/sql_list.h: Auto merged sql/sql_select.cc: Auto merged netware/BUILD/nwbootstrap: merge: keep local scripts/make_binary_distribution.sh: merge: keep local sql/ha_heap.cc: Trivial merge sql/ha_innodb.cc: Auto merge (Code already existed in 5.0) sql/item_cmpfunc.cc: Simple merge sql/item_func.cc: Simple merge sql/item_row.cc: Simple merge sql/item_strfunc.cc: Simple merge sql/item_subselect.cc: Merge with sanjas optimzation patch, but keep old code withing ifdef as a reference until this is fixed
-rw-r--r--client/mysqltest.c2
-rw-r--r--mysql-test/r/group_by.result4
-rw-r--r--mysql-test/r/heap_hash.result10
-rw-r--r--mysql-test/r/subselect.result38
-rw-r--r--mysql-test/r/user_var.result4
-rw-r--r--mysql-test/t/group_by.test3
-rw-r--r--mysql-test/t/heap_hash.test6
-rw-r--r--mysql-test/t/subselect.test30
-rw-r--r--mysys/my_rename.c2
-rw-r--r--ndb/src/kernel/vm/FastScheduler.cpp42
-rw-r--r--netware/mysql_test_run.c5
-rw-r--r--sql/ha_heap.cc13
-rw-r--r--sql/item.cc52
-rw-r--r--sql/item.h3
-rw-r--r--sql/item_cmpfunc.cc56
-rw-r--r--sql/item_func.cc19
-rw-r--r--sql/item_row.cc18
-rw-r--r--sql/item_strfunc.cc14
-rw-r--r--sql/item_subselect.cc6
-rw-r--r--sql/sql_list.h9
-rw-r--r--sql/sql_select.cc15
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: