Commit 69ea046b authored by tomas@poseidon.ndb.mysql.com's avatar tomas@poseidon.ndb.mysql.com

Merge tulin@bk-internal.mysql.com:/home/bk/mysql-4.1

into poseidon.ndb.mysql.com:/home/tomas/mysql-4.1
parents 91a593ad 84513973
...@@ -1007,3 +1007,4 @@ tests/mysql_client_test ...@@ -1007,3 +1007,4 @@ tests/mysql_client_test
libmysqld/examples/mysql_client_test.c libmysqld/examples/mysql_client_test.c
libmysqld/examples/mysql_client_test_embedded libmysqld/examples/mysql_client_test_embedded
libmysqld/examples/mysqltest_embedded libmysqld/examples/mysqltest_embedded
support-files/ndb-config-2-node.ini
...@@ -109,6 +109,12 @@ sub add_copyright ...@@ -109,6 +109,12 @@ sub add_copyright
$line_copyright= "! "; $line_copyright= "! ";
$end_copyright= ""; $end_copyright= "";
} }
elsif ($ARGV =~ /\.sql$/)
{
$start_copyright="-- ";
$line_copyright= "-- ";
$end_copyright= "";
}
elsif ($ARGV =~ /\.asm$/) elsif ($ARGV =~ /\.asm$/)
{ {
$start_copyright="; "; $start_copyright="; ";
......
...@@ -47,7 +47,7 @@ dist-hook: ...@@ -47,7 +47,7 @@ dist-hook:
$(distdir)/std_data $(distdir)/std_data
$(INSTALL_DATA) $(srcdir)/t/*.test $(srcdir)/t/*.opt $(srcdir)/t/*.sh $(srcdir)/t/*.slave-mi $(distdir)/t $(INSTALL_DATA) $(srcdir)/t/*.test $(srcdir)/t/*.opt $(srcdir)/t/*.sh $(srcdir)/t/*.slave-mi $(distdir)/t
$(INSTALL_DATA) $(srcdir)/include/*.inc $(distdir)/include $(INSTALL_DATA) $(srcdir)/include/*.inc $(distdir)/include
$(INSTALL_DATA) $(srcdir)/r/*.result $(srcdir)/r/*.require $(distdir)/r $(INSTALL_DATA) $(srcdir)/r/*.result $(srcdir)/r/*.result.es $(srcdir)/r/*.require $(distdir)/r
$(INSTALL_DATA) $(srcdir)/std_data/Moscow_leap $(distdir)/std_data $(INSTALL_DATA) $(srcdir)/std_data/Moscow_leap $(distdir)/std_data
$(INSTALL_DATA) $(srcdir)/std_data/*.dat $(srcdir)/std_data/*.000001 $(distdir)/std_data $(INSTALL_DATA) $(srcdir)/std_data/*.dat $(srcdir)/std_data/*.000001 $(distdir)/std_data
$(INSTALL_DATA) $(srcdir)/std_data/des_key_file $(distdir)/std_data $(INSTALL_DATA) $(srcdir)/std_data/des_key_file $(distdir)/std_data
...@@ -65,7 +65,7 @@ install-data-local: ...@@ -65,7 +65,7 @@ install-data-local:
$(INSTALL_DATA) $(srcdir)/t/*.opt $(DESTDIR)$(testdir)/t $(INSTALL_DATA) $(srcdir)/t/*.opt $(DESTDIR)$(testdir)/t
$(INSTALL_DATA) $(srcdir)/t/*.sh $(DESTDIR)$(testdir)/t $(INSTALL_DATA) $(srcdir)/t/*.sh $(DESTDIR)$(testdir)/t
$(INSTALL_DATA) $(srcdir)/t/*.slave-mi $(DESTDIR)$(testdir)/t $(INSTALL_DATA) $(srcdir)/t/*.slave-mi $(DESTDIR)$(testdir)/t
$(INSTALL_DATA) $(srcdir)/r/*.result $(DESTDIR)$(testdir)/r $(INSTALL_DATA) $(srcdir)/r/*.result $(srcdir)/r/*.result.es $(DESTDIR)$(testdir)/r
$(INSTALL_DATA) $(srcdir)/r/*.require $(DESTDIR)$(testdir)/r $(INSTALL_DATA) $(srcdir)/r/*.require $(DESTDIR)$(testdir)/r
$(INSTALL_DATA) $(srcdir)/include/*.inc $(DESTDIR)$(testdir)/include $(INSTALL_DATA) $(srcdir)/include/*.inc $(DESTDIR)$(testdir)/include
$(INSTALL_DATA) $(srcdir)/std_data/*.dat $(DESTDIR)$(testdir)/std_data $(INSTALL_DATA) $(srcdir)/std_data/*.dat $(DESTDIR)$(testdir)/std_data
......
...@@ -194,8 +194,8 @@ MY_LOG_DIR="$MYSQL_TEST_DIR/var/log" ...@@ -194,8 +194,8 @@ MY_LOG_DIR="$MYSQL_TEST_DIR/var/log"
# #
# Set LD_LIBRARY_PATH if we are using shared libraries # Set LD_LIBRARY_PATH if we are using shared libraries
# #
LD_LIBRARY_PATH="$BASEDIR/lib:$BASEDIR/libmysql/.libs:$LD_LIBRARY_PATH" LD_LIBRARY_PATH="$BASEDIR/lib:$BASEDIR/libmysql/.libs:$BASEDIR/zlib/.libs:$LD_LIBRARY_PATH"
DYLD_LIBRARY_PATH="$BASEDIR/lib:$BASEDIR/libmysql/.libs:$DYLD_LIBRARY_PATH" DYLD_LIBRARY_PATH="$BASEDIR/lib:$BASEDIR/libmysql/.libs:$BASEDIR/zlib/.libs:$DYLD_LIBRARY_PATH"
export LD_LIBRARY_PATH DYLD_LIBRARY_PATH export LD_LIBRARY_PATH DYLD_LIBRARY_PATH
MASTER_RUNNING=0 MASTER_RUNNING=0
......
...@@ -655,9 +655,9 @@ insert into t1 (a,b) values (1,2),(1,3),(2,5); ...@@ -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; 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 a r2 r1
1 1.0 2 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 a r2 r1
1 1 2 1 2 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;
a sum(b) a sum(b)
1 5 1 5
......
...@@ -1425,7 +1425,7 @@ Note 1003 (select test.t1.s1 AS `s1` from test.t1) ...@@ -1425,7 +1425,7 @@ Note 1003 (select test.t1.s1 AS `s1` from test.t1)
s1 s1
tttt tttt
drop table t1; 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)); create table t2 (s1 char(5), index s1(s1));
insert into t1 values ('a1'),('a2'),('a3'); insert into t1 values ('a1'),('a2'),('a3');
insert into t2 values ('a1'),('a2'); insert into t2 values ('a1'),('a2');
...@@ -1451,25 +1451,25 @@ a2 1 ...@@ -1451,25 +1451,25 @@ a2 1
a3 1 a3 1
explain extended select s1, s1 NOT IN (SELECT s1 FROM t2) from t1; 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 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 2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 2 Using index
Warnings: 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 chicking NULL)))) AS `s1 NOT IN (SELECT s1 FROM t2)` from test.t1 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 chicking NULL)))) AS `s1 NOT IN (SELECT s1 FROM t2)` from test.t1
explain extended select s1, s1 = ANY (SELECT s1 FROM t2) from 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 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 2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 2 Using index
Warnings: 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 chicking NULL))) AS `s1 = ANY (SELECT s1 FROM t2)` from test.t1 Note 1003 select test.t1.s1 AS `s1`,<in_optimizer>(test.t1.s1,<exists>(<index_lookup>(<cache>(test.t1.s1) in t2 on s1 chicking NULL))) AS `s1 = ANY (SELECT s1 FROM t2)` from test.t1
explain extended select s1, s1 <> ALL (SELECT s1 FROM t2) from 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 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 2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 2 Using index
Warnings: 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 chicking NULL)))) AS `s1 <> ALL (SELECT s1 FROM t2)` from test.t1 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 chicking 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; 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 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 2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 1 Using index; Using where
Warnings: 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 chicking NULL where (test.t2.s1 < _latin1'a2'))))) AS `s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2')` from test.t1 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 chicking NULL where (test.t2.s1 < _latin1'a2'))))) AS `s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2')` from test.t1
...@@ -2125,34 +2125,6 @@ SELECT DISTINCT Continent AS c FROM t1 WHERE Code <> SOME ( SELECT Code FROM t1 ...@@ -2125,34 +2125,6 @@ SELECT DISTINCT Continent AS c FROM t1 WHERE Code <> SOME ( SELECT Code FROM t1
c c
Oceania Oceania
drop table t1; 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 t1 (a1 int);
create table t2 (b1 int); create table t2 (b1 int);
select * from t1 where a2 > any(select b1 from t2); select * from t1 where a2 > any(select b1 from t2);
......
...@@ -109,8 +109,8 @@ select @a:=0; ...@@ -109,8 +109,8 @@ select @a:=0;
select @a, @a:=@a+count(*), count(*), @a from t1 group by i; select @a, @a:=@a+count(*), count(*), @a from t1 group by i;
@a @a:=@a+count(*) count(*) @a @a @a:=@a+count(*) count(*) @a
0 1 1 0 0 1 1 0
0 3 2 0 0 2 2 0
0 6 3 0 0 3 3 0
select @a:=0; select @a:=0;
@a:=0 @a:=0
0 0
......
...@@ -480,7 +480,8 @@ drop table t1; ...@@ -480,7 +480,8 @@ drop table t1;
create table t1 (a integer, b integer, c integer); create table t1 (a integer, b integer, c integer);
insert into t1 (a,b) values (1,2),(1,3),(2,5); 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, 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 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; select sum(a)*sum(b) from t1 where a=1 group by c;
......
...@@ -889,7 +889,7 @@ drop table t1; ...@@ -889,7 +889,7 @@ drop table t1;
# #
# IN optimisation test results # 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)); create table t2 (s1 char(5), index s1(s1));
insert into t1 values ('a1'),('a2'),('a3'); insert into t1 values ('a1'),('a2'),('a3');
insert into t2 values ('a1'),('a2'); insert into t2 values ('a1'),('a2');
...@@ -1387,34 +1387,6 @@ INSERT INTO t1 VALUES ('UMI','United States Minor Outlying Islands','Oceania','M ...@@ -1387,34 +1387,6 @@ INSERT INTO t1 VALUES ('UMI','United States Minor Outlying Islands','Oceania','M
SELECT DISTINCT Continent AS c FROM t1 WHERE Code <> SOME ( SELECT Code FROM t1 WHERE Continent = c AND Population < 200); SELECT DISTINCT Continent AS c FROM t1 WHERE Code <> SOME ( SELECT Code FROM t1 WHERE Continent = c AND Population < 200);
drop table 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 # Test for BUG#7885: Server crash when 'any' subselect compared to
# non-existant field. # non-existant field.
......
...@@ -493,6 +493,24 @@ sub print_insert_header ...@@ -493,6 +493,24 @@ sub print_insert_header
} }
} }
print <<EOF;
-- Copyright (C) 2000-2005 MySQL AB
--
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
EOF
print "delete from help_topic;\n"; print "delete from help_topic;\n";
print "delete from help_category;\n"; print "delete from help_category;\n";
print "delete from help_keyword;\n"; print "delete from help_keyword;\n";
......
...@@ -295,6 +295,58 @@ CHARSET_INFO *Item::default_charset() ...@@ -295,6 +295,58 @@ CHARSET_INFO *Item::default_charset()
} }
/*
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 Aggregate two collations together taking
into account their coercibility (aka derivation): into account their coercibility (aka derivation):
......
...@@ -262,6 +262,9 @@ public: ...@@ -262,6 +262,9 @@ public:
virtual void update_used_tables() {} virtual void update_used_tables() {}
virtual void split_sum_func(THD *thd, Item **ref_pointer_array, virtual void split_sum_func(THD *thd, Item **ref_pointer_array,
List<Item> &fields) {} 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_date(TIME *ltime,uint fuzzydate);
virtual bool get_time(TIME *ltime); virtual bool get_time(TIME *ltime);
virtual bool get_date_result(TIME *ltime,uint fuzzydate) virtual bool get_date_result(TIME *ltime,uint fuzzydate)
......
...@@ -636,13 +636,12 @@ longlong Item_in_optimizer::val_int() ...@@ -636,13 +636,12 @@ longlong Item_in_optimizer::val_int()
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
cache->store(args[0]); cache->store(args[0]);
longlong tmp= args[1]->val_int_result();
if (cache->null_value) if (cache->null_value)
{ {
if (tmp) null_value= 1;
null_value= 1;
return 0; return 0;
} }
longlong tmp= args[1]->val_int_result();
null_value= args[1]->null_value; null_value= args[1]->null_value;
return tmp; return tmp;
} }
...@@ -1969,10 +1968,10 @@ bool Item_cond::walk(Item_processor processor, byte *arg) ...@@ -1969,10 +1968,10 @@ bool Item_cond::walk(Item_processor processor, byte *arg)
Move SUM items out from item tree and replace with reference Move SUM items out from item tree and replace with reference
SYNOPSIS SYNOPSIS
split_sum_func() split_sum_func()
thd Thread handler thd Thread handler
ref_pointer_array Pointer to array of reference fields ref_pointer_array Pointer to array of reference fields
fields All fields in select fields All fields in select
NOTES NOTES
This function is run on all expression (SELECT list, WHERE, HAVING etc) This function is run on all expression (SELECT list, WHERE, HAVING etc)
...@@ -1982,16 +1981,6 @@ bool Item_cond::walk(Item_processor processor, byte *arg) ...@@ -1982,16 +1981,6 @@ bool Item_cond::walk(Item_processor processor, byte *arg)
so that we can easily find and calculate them. so that we can easily find and calculate them.
(Calculation done by update_sum_func() and copy_sum_funcs() in (Calculation done by update_sum_func() and copy_sum_funcs() in
sql_select.cc) 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, void Item_cond::split_sum_func(THD *thd, Item **ref_pointer_array,
...@@ -1999,38 +1988,8 @@ void Item_cond::split_sum_func(THD *thd, Item **ref_pointer_array, ...@@ -1999,38 +1988,8 @@ void Item_cond::split_sum_func(THD *thd, Item **ref_pointer_array,
{ {
List_iterator<Item> li(list); List_iterator<Item> li(list);
Item *item; Item *item;
used_tables_cache=0; while ((item= li++))
const_item_cache=0; item->split_sum_func2(thd, ref_pointer_array, fields, li.ref());
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);
ref_pointer_array[el]= item;
thd->change_item_tree(ref, new_item);
}
item->update_used_tables();
used_tables_cache|=item->used_tables();
const_item_cache&=item->const_item();
}
} }
......
...@@ -352,28 +352,14 @@ bool Item_func::walk (Item_processor processor, byte *argument) ...@@ -352,28 +352,14 @@ bool Item_func::walk (Item_processor processor, byte *argument)
} }
/* See comments in Item_cmp_func::split_sum_func() */
void Item_func::split_sum_func(THD *thd, Item **ref_pointer_array, void Item_func::split_sum_func(THD *thd, Item **ref_pointer_array,
List<Item> &fields) List<Item> &fields)
{ {
Item **arg, **arg_end; Item **arg, **arg_end;
for (arg= args, arg_end= args+arg_count; arg != arg_end ; arg++) for (arg= args, arg_end= args+arg_count; arg != arg_end ; arg++)
{ (*arg)->split_sum_func2(thd, ref_pointer_array, fields, 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);
ref_pointer_array[el]= item;
thd->change_item_tree(arg, new_item);
}
}
} }
......
...@@ -90,25 +90,10 @@ void Item_row::split_sum_func(THD *thd, Item **ref_pointer_array, ...@@ -90,25 +90,10 @@ void Item_row::split_sum_func(THD *thd, Item **ref_pointer_array,
{ {
Item **arg, **arg_end; Item **arg, **arg_end;
for (arg= items, arg_end= items+arg_count; arg != arg_end ; arg++) for (arg= items, arg_end= items+arg_count; arg != arg_end ; arg++)
{ (*arg)->split_sum_func2(thd, ref_pointer_array, fields, 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);
ref_pointer_array[el]= *arg;
thd->change_item_tree(arg, new_item);
}
}
} }
void Item_row::update_used_tables() void Item_row::update_used_tables()
{ {
used_tables_cache= 0; used_tables_cache= 0;
......
...@@ -1758,20 +1758,7 @@ String *Item_func_elt::val_str(String *str) ...@@ -1758,20 +1758,7 @@ String *Item_func_elt::val_str(String *str)
void Item_func_make_set::split_sum_func(THD *thd, Item **ref_pointer_array, void Item_func_make_set::split_sum_func(THD *thd, Item **ref_pointer_array,
List<Item> &fields) List<Item> &fields)
{ {
if (item->type() != SUM_FUNC_ITEM && item->split_sum_func2(thd, ref_pointer_array, fields, &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);
ref_pointer_array[el]= item;
thd->change_item_tree(&item, new_item);
}
Item_str_func::split_sum_func(thd, ref_pointer_array, fields); Item_str_func::split_sum_func(thd, ref_pointer_array, fields);
} }
......
...@@ -825,8 +825,6 @@ Item_in_subselect::single_value_transformer(JOIN *join, ...@@ -825,8 +825,6 @@ Item_in_subselect::single_value_transformer(JOIN *join,
select_lex->ref_pointer_array, select_lex->ref_pointer_array,
(char *)"<ref>", (char *)"<ref>",
this->full_name())); this->full_name()));
if (!abort_on_null && left_expr->maybe_null)
item= new Item_cond_or(new Item_func_isnull(left_expr), item);
/* /*
AND and comparison functions can't be changed during fix_fields() AND and comparison functions can't be changed during fix_fields()
we can assign select_lex->having here, and pass 0 as last we can assign select_lex->having here, and pass 0 as last
...@@ -872,8 +870,6 @@ Item_in_subselect::single_value_transformer(JOIN *join, ...@@ -872,8 +870,6 @@ Item_in_subselect::single_value_transformer(JOIN *join,
select_lex->having_fix_field= 0; select_lex->having_fix_field= 0;
item= new Item_cond_or(item, item= new Item_cond_or(item,
new Item_func_isnull(orig_item)); new Item_func_isnull(orig_item));
if (left_expr->maybe_null)
item= new Item_cond_or(new Item_func_isnull(left_expr), item);
} }
item->name= (char *)in_additional_cond; item->name= (char *)in_additional_cond;
/* /*
...@@ -894,13 +890,12 @@ Item_in_subselect::single_value_transformer(JOIN *join, ...@@ -894,13 +890,12 @@ Item_in_subselect::single_value_transformer(JOIN *join,
we can assign select_lex->having here, and pass 0 as last we can assign select_lex->having here, and pass 0 as last
argument (reference) to fix_fields() argument (reference) to fix_fields()
*/ */
item= func->create(expr, select_lex->having=
new Item_null_helper(this, item, join->having=
func->create(expr,
new Item_null_helper(this, item,
(char *)"<no matter>", (char *)"<no matter>",
(char *)"<result>")); (char *)"<result>"));
if (!abort_on_null && left_expr->maybe_null)
item= new Item_cond_or(new Item_func_isnull(left_expr), item);
select_lex->having= join->having= item;
select_lex->having_fix_field= 1; select_lex->having_fix_field= 1;
if (join->having->fix_fields(thd, join->tables_list, if (join->having->fix_fields(thd, join->tables_list,
0)) 0))
......
...@@ -134,6 +134,15 @@ public: ...@@ -134,6 +134,15 @@ public:
if (!--elements) if (!--elements)
last= &first; last= &first;
} }
inline void concat(base_list *list)
{
if (!list->is_empty())
{
*last= list->first;
last= list->last;
elements+= list->elements;
}
}
inline void *pop(void) inline void *pop(void)
{ {
if (first == &end_of_list) return 0; if (first == &end_of_list) return 0;
......
...@@ -8503,6 +8503,7 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, ...@@ -8503,6 +8503,7 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
res_selected_fields.empty(); res_selected_fields.empty();
res_all_fields.empty(); res_all_fields.empty();
List_iterator_fast<Item> itr(res_all_fields); List_iterator_fast<Item> itr(res_all_fields);
List<Item> extra_funcs;
uint i, border= all_fields.elements - elements; uint i, border= all_fields.elements - elements;
DBUG_ENTER("setup_copy_fields"); DBUG_ENTER("setup_copy_fields");
...@@ -8564,7 +8565,12 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, ...@@ -8564,7 +8565,12 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
*/ */
if (!(pos=new Item_copy_string(pos))) if (!(pos=new Item_copy_string(pos)))
goto err; 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; goto err;
} }
res_all_fields.push_back(pos); res_all_fields.push_back(pos);
...@@ -8576,6 +8582,12 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, ...@@ -8576,6 +8582,12 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
for (i= 0; i < border; i++) for (i= 0; i < border; i++)
itr++; itr++;
itr.sublist(res_selected_fields, elements); 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); DBUG_RETURN(0);
err: err:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment