Commit 82246120 authored by unknown's avatar unknown

Merge epotemkin@bk-internal.mysql.com:/home/bk/mysql-5.0-opt

into  moonbone.local:/work/19862-bug-5.0-opt-mysql


sql/item_func.h:
  Auto merged
sql/sql_select.cc:
  Auto merged
parents db7e5f0b 7af7bd48
...@@ -5057,4 +5057,23 @@ concat('data was: /', var1, '/') ...@@ -5057,4 +5057,23 @@ concat('data was: /', var1, '/')
data was: /1/ data was: /1/
drop table t3| drop table t3|
drop procedure bug15217| drop procedure bug15217|
drop procedure if exists bug19862|
CREATE TABLE t11 (a INT)|
CREATE TABLE t12 (a INT)|
CREATE FUNCTION bug19862(x INT) RETURNS INT
BEGIN
INSERT INTO t11 VALUES (x);
RETURN x+1;
END|
INSERT INTO t12 VALUES (1), (2)|
SELECT bug19862(a) FROM t12 ORDER BY 1|
bug19862(a)
2
3
SELECT * FROM t11|
a
1
2
DROP TABLE t11, t12|
DROP FUNCTION bug19862|
drop table t1,t2; drop table t1,t2;
...@@ -93,6 +93,12 @@ NULL ...@@ -93,6 +93,12 @@ NULL
0R 0R
FR FR
DROP TABLE bug19904; DROP TABLE bug19904;
create table t1(f1 int);
insert into t1 values(1),(2);
explain select myfunc_int(f1) from t1 order by 1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using temporary; Using filesort
drop table t1;
End of 5.0 tests. End of 5.0 tests.
DROP FUNCTION metaphon; DROP FUNCTION metaphon;
DROP FUNCTION myfunc_double; DROP FUNCTION myfunc_double;
......
...@@ -5962,6 +5962,24 @@ call bug15217()| ...@@ -5962,6 +5962,24 @@ call bug15217()|
drop table t3| drop table t3|
drop procedure bug15217| drop procedure bug15217|
#
# BUG#19862: Sort with filesort by function evaluates function twice
#
--disable_warnings
drop procedure if exists bug19862|
--enable_warnings
CREATE TABLE t11 (a INT)|
CREATE TABLE t12 (a INT)|
CREATE FUNCTION bug19862(x INT) RETURNS INT
BEGIN
INSERT INTO t11 VALUES (x);
RETURN x+1;
END|
INSERT INTO t12 VALUES (1), (2)|
SELECT bug19862(a) FROM t12 ORDER BY 1|
SELECT * FROM t11|
DROP TABLE t11, t12|
DROP FUNCTION bug19862|
# #
# BUG#NNNN: New bug synopsis # BUG#NNNN: New bug synopsis
# #
......
...@@ -109,6 +109,13 @@ SELECT myfunc_double(n) AS f FROM bug19904; ...@@ -109,6 +109,13 @@ SELECT myfunc_double(n) AS f FROM bug19904;
SELECT metaphon(v) AS f FROM bug19904; SELECT metaphon(v) AS f FROM bug19904;
DROP TABLE bug19904; DROP TABLE bug19904;
#
# Bug#19862: Sort with filesort by function evaluates function twice
#
create table t1(f1 int);
insert into t1 values(1),(2);
explain select myfunc_int(f1) from t1 order by 1;
drop table t1;
--echo End of 5.0 tests. --echo End of 5.0 tests.
# #
......
...@@ -752,6 +752,7 @@ class Item { ...@@ -752,6 +752,7 @@ class Item {
virtual bool find_item_in_field_list_processor(byte *arg) { return 0; } virtual bool find_item_in_field_list_processor(byte *arg) { return 0; }
virtual bool change_context_processor(byte *context) { return 0; } virtual bool change_context_processor(byte *context) { return 0; }
virtual bool reset_query_id_processor(byte *query_id) { return 0; } virtual bool reset_query_id_processor(byte *query_id) { return 0; }
virtual bool func_type_checker_processor(byte *arg) { return 0; }
virtual Item *equal_fields_propagator(byte * arg) { return this; } virtual Item *equal_fields_propagator(byte * arg) { return this; }
virtual Item *set_no_const_sub(byte *arg) { return this; } virtual Item *set_no_const_sub(byte *arg) { return this; }
......
...@@ -398,6 +398,13 @@ Field *Item_func::tmp_table_field(TABLE *t_arg) ...@@ -398,6 +398,13 @@ Field *Item_func::tmp_table_field(TABLE *t_arg)
return res; return res;
} }
bool Item_func::func_type_checker_processor(byte *arg)
{
return *((Functype*)arg) == functype();
}
my_decimal *Item_func::val_decimal(my_decimal *decimal_value) my_decimal *Item_func::val_decimal(my_decimal *decimal_value)
{ {
DBUG_ASSERT(fixed); DBUG_ASSERT(fixed);
......
...@@ -55,7 +55,7 @@ class Item_func :public Item_result_field ...@@ -55,7 +55,7 @@ class Item_func :public Item_result_field
NOT_FUNC, NOT_ALL_FUNC, NOT_FUNC, NOT_ALL_FUNC,
NOW_FUNC, TRIG_COND_FUNC, NOW_FUNC, TRIG_COND_FUNC,
GUSERVAR_FUNC, COLLATE_FUNC, GUSERVAR_FUNC, COLLATE_FUNC,
EXTRACT_FUNC, CHAR_TYPECAST_FUNC, FUNC_SP }; EXTRACT_FUNC, CHAR_TYPECAST_FUNC, FUNC_SP, UDF_FUNC };
enum optimize_type { OPTIMIZE_NONE,OPTIMIZE_KEY,OPTIMIZE_OP, OPTIMIZE_NULL, enum optimize_type { OPTIMIZE_NONE,OPTIMIZE_KEY,OPTIMIZE_OP, OPTIMIZE_NULL,
OPTIMIZE_EQUAL }; OPTIMIZE_EQUAL };
enum Type type() const { return FUNC_ITEM; } enum Type type() const { return FUNC_ITEM; }
...@@ -189,6 +189,7 @@ class Item_func :public Item_result_field ...@@ -189,6 +189,7 @@ class Item_func :public Item_result_field
Item *transform(Item_transformer transformer, byte *arg); Item *transform(Item_transformer transformer, byte *arg);
void traverse_cond(Cond_traverser traverser, void traverse_cond(Cond_traverser traverser,
void * arg, traverse_order order); void * arg, traverse_order order);
bool func_type_checker_processor(byte *arg);
}; };
...@@ -933,6 +934,7 @@ class Item_udf_func :public Item_func ...@@ -933,6 +934,7 @@ class Item_udf_func :public Item_func
Item_udf_func(udf_func *udf_arg, List<Item> &list) Item_udf_func(udf_func *udf_arg, List<Item> &list)
:Item_func(list), udf(udf_arg) {} :Item_func(list), udf(udf_arg) {}
const char *func_name() const { return udf.name(); } const char *func_name() const { return udf.name(); }
enum Functype functype() const { return UDF_FUNC; }
bool fix_fields(THD *thd, Item **ref) bool fix_fields(THD *thd, Item **ref)
{ {
DBUG_ASSERT(fixed == 0); DBUG_ASSERT(fixed == 0);
......
...@@ -1064,6 +1064,26 @@ JOIN::optimize() ...@@ -1064,6 +1064,26 @@ JOIN::optimize()
{ {
need_tmp=1; simple_order=simple_group=0; // Force tmp table without sort need_tmp=1; simple_order=simple_group=0; // Force tmp table without sort
} }
if (order)
{
/*
Force using of tmp table if sorting by a SP or UDF function due to
their expensive and probably non-deterministic nature.
*/
for (ORDER *tmp_order= order; tmp_order ; tmp_order=tmp_order->next)
{
Item *item= *tmp_order->item;
Item_func::Functype type=Item_func::FUNC_SP;
Item_func::Functype type1=Item_func::UDF_FUNC;
if (item->walk(&Item::func_type_checker_processor,(byte*)&type) ||
item->walk(&Item::func_type_checker_processor,(byte*)&type1))
{
/* Force tmp table without sort */
need_tmp=1; simple_order=simple_group=0;
break;
}
}
}
} }
tmp_having= having; tmp_having= having;
......
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