From fb36d923cea32705dff7d5221234ce948b13c17a Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 10 Mar 2006 14:04:56 +0100 Subject: [PATCH 1/2] Fixed BUG#16474: SP crashed MySQL fix_fields() was not called for "order by" variables if the type was a "constant integer", and thus interpreted as a column index. However, a local variable is an expression and should not be interpreted as a column index. Instead it behaves just like when using a user variable for instance (i.e. it will not affect the ordering). mysql-test/r/sp.result: Updated results for new test case (BUG#16474). mysql-test/t/sp.test: New test case for BUG#16474. sql/sql_select.cc: When processing order list, --- mysql-test/r/sp.result | 29 +++++++++++++++++++++++++++++ mysql-test/t/sp.test | 31 +++++++++++++++++++++++++++++++ sql/sql_select.cc | 6 +++++- 3 files changed, 65 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index b03c49b72e7..f19dbbd2689 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -4857,4 +4857,33 @@ i 0 drop table t3| drop procedure bug16887| +drop procedure if exists bug16474_1| +drop procedure if exists bug16474_2| +delete from t1| +insert into t1 values ('c', 2), ('b', 3), ('a', 1)| +create procedure bug16474_1() +begin +declare x int; +select id from t1 order by x; +end| +create procedure bug16474_2(x int) +select id from t1 order by x| +call bug16474_1()| +id +c +b +a +call bug16474_2(1)| +id +c +b +a +call bug16474_2(2)| +id +c +b +a +drop procedure bug16474_1| +drop procedure bug16474_2| +delete from t1| drop table t1,t2; diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index e6823693b3d..af7ce57b252 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -5717,6 +5717,37 @@ drop table t3| drop procedure bug16887| +# +# BUG#16474: SP crashed MySQL +# (when using "order by localvar", where 'localvar' is just that. +# +--disable_warnings +drop procedure if exists bug16474_1| +drop procedure if exists bug16474_2| +--enable_warnings + +delete from t1| +insert into t1 values ('c', 2), ('b', 3), ('a', 1)| + +create procedure bug16474_1() +begin + declare x int; + + select id from t1 order by x; +end| + +# This does NOT order by column index; variable is an expression. +create procedure bug16474_2(x int) + select id from t1 order by x| + +call bug16474_1()| +call bug16474_2(1)| +call bug16474_2(2)| +drop procedure bug16474_1| +drop procedure bug16474_2| +delete from t1| + + # # BUG#NNNN: New bug synopsis # diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 768ae7bf71f..eb92bd1177b 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -12325,7 +12325,11 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, Item **select_item; /* The corresponding item from the SELECT clause. */ Field *from_field; /* The corresponding field from the FROM clause. */ - if (order_item->type() == Item::INT_ITEM) + /* + Local SP variables may be int but are expressions, not positions. + (And they must be fixed.) + */ + if (order_item->type() == Item::INT_ITEM && !order_item->is_splocal()) { /* Order by position */ uint count= (uint) order_item->val_int(); if (!count || count > fields.elements) From 537ec1e6df2d308b1765329570bc83ebffc42b68 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 28 Mar 2006 14:16:21 +0200 Subject: [PATCH 2/2] Post review fixes for BUG#16474: SP crashed MySQL. mysql-test/r/ps.result: Added test coverage for "order by" in prepared statements (related to BUG#16474). mysql-test/r/sp.result: Added reference to test case for BUG#16474. mysql-test/t/ps.test: Added test coverage for "order by" in prepared statements (related to BUG#16474). mysql-test/t/sp.test: Added reference to test case for BUG#16474. sql/sql_select.cc: Fixed comment and test for basic_const_item() instead of is_splocal(). --- mysql-test/r/ps.result | 46 ++++++++++++++++++++++++++++++++++++++++++ mysql-test/r/sp.result | 6 ++++++ mysql-test/t/ps.test | 34 +++++++++++++++++++++++++++++++ mysql-test/t/sp.test | 5 +++++ sql/sql_select.cc | 5 +++-- 5 files changed, 94 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 4d108e06356..9afbca9dcb1 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -880,3 +880,49 @@ select row_count(); row_count() 1 drop table t1; +create table t1 (a int, b int); +insert into t1 (a,b) values (2,8),(1,9),(3,7); +prepare stmt from "select * from t1 order by ?"; +execute stmt using @a; +a b +2 8 +1 9 +3 7 +set @a=1; +execute stmt using @a; +a b +1 9 +2 8 +3 7 +set @a=2; +execute stmt using @a; +a b +3 7 +2 8 +1 9 +deallocate prepare stmt; +select * from t1 order by 1; +a b +1 9 +2 8 +3 7 +prepare stmt from "select * from t1 order by ?+1"; +set @a=0; +execute stmt using @a; +a b +2 8 +1 9 +3 7 +set @a=1; +execute stmt using @a; +a b +2 8 +1 9 +3 7 +deallocate prepare stmt; +select * from t1 order by 1+1; +a b +2 8 +1 9 +3 7 +drop table t1; diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index f19dbbd2689..0c9b64f37fa 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -4885,5 +4885,11 @@ b a drop procedure bug16474_1| drop procedure bug16474_2| +set @x = 2| +select * from t1 order by @x| +id data +c 2 +b 3 +a 1 delete from t1| drop table t1,t2; diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index d6b239c31bf..285b5fb0aa3 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -933,4 +933,38 @@ execute ins_call; select row_count(); drop table t1; +# +# BUG#16474: SP crashed MySQL +# (when using "order by localvar", where 'localvar' is just that. +# The actual bug test is in sp.test, this is just testing that we get the +# expected result for prepared statements too, i.e. place holders work as +# textual substitution. If it's a single integer, it works as the (deprecated) +# "order by column#", otherwise it's an expression. +# +create table t1 (a int, b int); +insert into t1 (a,b) values (2,8),(1,9),(3,7); + +# Will order by index +prepare stmt from "select * from t1 order by ?"; +execute stmt using @a; +set @a=1; +execute stmt using @a; +set @a=2; +execute stmt using @a; +deallocate prepare stmt; +# For reference: +select * from t1 order by 1; + +# Will not order by index. +prepare stmt from "select * from t1 order by ?+1"; +set @a=0; +execute stmt using @a; +set @a=1; +execute stmt using @a; +deallocate prepare stmt; +# For reference: +select * from t1 order by 1+1; + +drop table t1; + # End of 5.0 tests diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index af7ce57b252..1d1272b0b2a 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -5745,6 +5745,11 @@ call bug16474_2(1)| call bug16474_2(2)| drop procedure bug16474_1| drop procedure bug16474_2| + +# For reference: user variables are expressions too and do not affect ordering. +set @x = 2| +select * from t1 order by @x| + delete from t1| diff --git a/sql/sql_select.cc b/sql/sql_select.cc index eb92bd1177b..e31a2068dee 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -12327,9 +12327,10 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, /* Local SP variables may be int but are expressions, not positions. - (And they must be fixed.) + (And they can't be used before fix_fields is called for them). */ - if (order_item->type() == Item::INT_ITEM && !order_item->is_splocal()) + // if (order_item->type() == Item::INT_ITEM && !order_item->is_splocal()) + if (order_item->type() == Item::INT_ITEM && order_item->basic_const_item()) { /* Order by position */ uint count= (uint) order_item->val_int(); if (!count || count > fields.elements)