List:Commits« Previous MessageNext Message »
From:marc.alff Date:February 15 2007 4:42am
Subject:bk commit into 5.0 tree (malff:1.2395) BUG#26093
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of marcsql. When marcsql does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2007-02-14 20:42:33-07:00, malff@weblab.(none) +3 -0
  Bug#26093 (SELECT BENCHMARK() for SELECT statements does not produce valid
    results)
  
  Before this fix, the function BENCHMARK() would fail to evaluate expressions
  like "(select avg(a) from t1)" in debug builds (with an assert),
  or would report a time of zero in non debug builds.
  
  The root cause is that evaluation of DECIMAL_RESULT expressions was not
  supported in Item_func_benchmark::val_int().
  
  This is a bug, which has been fixed by this change.
  
  Independently of this fix, the behavior of BENCHMARK() needs to be better
  documented in the user manual to clarify expectations:
  
  "select BENCHMARK(N, expression)" is intended to measure the performance of
  the runtime evaluation of scalar expressions.
  This has major implications:
  
  a)
  Only scalar expressions can be used: a statement like "select * from t1",
  when returning multiple rows, or a more general statement like "create
  table" can not be benchmarked using this function.
  
  b)
    [1] select expression;
    [2] select expression;
    ...
    [N] select expression;
  and
    select BENCHMARK(N, expression)
  have a very different execution profile.
  
  With the former, the parser, the optimizer, table locking, and runtime
  evaluation are each invoked N times.
  With the later, the parser is invoked once, the optimizer is invoked once,
  tables are opened and locked once, and runtime evaluation is executed N
  times, while reusing memory structures already allocated.
  In addition, runtime optimizations, like local caching of results already
  evaluated for aggregate functions like avg(), can alter the results.
  
  There is no expectation that
    time("select BENCHMARK(N, expression)")
  is equivalent to
    N * time("select expression")
  since to the contrary, the purpose of BENCHMARK() is to remove the noise
  created by the network, the parser, the optimizer, etc,
  to measure the performance of the runtime component itself,
  by giving more weight (repeat the evaluation N times) to this part.

  mysql-test/r/func_misc.result@stripped, 2007-02-14 20:38:47-07:00, malff@weblab.(none) +42
-0
    Added support for DECIMAL_RESULT in Item_func_benchmark::val_int()

  mysql-test/t/func_misc.test@stripped, 2007-02-14 20:38:48-07:00, malff@weblab.(none) +54 -0
    Added support for DECIMAL_RESULT in Item_func_benchmark::val_int()

  sql/item_func.cc@stripped, 2007-02-14 20:38:48-07:00, malff@weblab.(none) +4 -0
    Added support for DECIMAL_RESULT in Item_func_benchmark::val_int()

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	malff
# Host:	weblab.(none)
# Root:	/home/marcsql/TREE/mysql-5.0-26093

--- 1.322/sql/item_func.cc	2007-02-14 20:42:38 -07:00
+++ 1.323/sql/item_func.cc	2007-02-14 20:42:38 -07:00
@@ -3456,6 +3456,7 @@ longlong Item_func_benchmark::val_int()
   DBUG_ASSERT(fixed == 1);
   char buff[MAX_FIELD_WIDTH];
   String tmp(buff,sizeof(buff), &my_charset_bin);
+  my_decimal tmp_decimal;
   THD *thd=current_thd;
 
   for (ulong loop=0 ; loop < loop_count && !thd->killed; loop++)
@@ -3469,6 +3470,9 @@ longlong Item_func_benchmark::val_int()
       break;
     case STRING_RESULT:
       (void) args[0]->val_str(&tmp);
+      break;
+    case DECIMAL_RESULT:
+      (void) args[0]->val_decimal(&tmp_decimal);
       break;
     case ROW_RESULT:
     default:

--- 1.26/mysql-test/r/func_misc.result	2007-02-14 20:42:38 -07:00
+++ 1.27/mysql-test/r/func_misc.result	2007-02-14 20:42:38 -07:00
@@ -141,4 +141,46 @@ t1	CREATE TABLE `t1` (
   `a` bigint(21) unsigned default NULL
 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
 drop table t1;
+drop table if exists table_26093;
+drop function if exists func_26093_a;
+drop function if exists func_26093_b;
+create table table_26093(a int);
+insert into table_26093 values
+(1), (2), (3), (4), (5),
+(6), (7), (8), (9), (10);
+create function func_26093_a(x int) returns int
+begin
+set @invoked := @invoked + 1;
+return x;
+end||
+create function func_26093_b(x int, y int) returns int
+begin
+set @invoked := @invoked + 1;
+return x;
+end||
+select avg(a) from table_26093;
+avg(a)
+5.5000
+select benchmark(100, (select avg(a) from table_26093));
+benchmark(100, (select avg(a) from table_26093))
+0
+set @invoked := 0;
+select benchmark(100, (select avg(func_26093_a(a)) from table_26093));
+benchmark(100, (select avg(func_26093_a(a)) from table_26093))
+0
+select @invoked;
+@invoked
+10
+set @invoked := 0;
+select benchmark(100, (select avg(func_26093_b(a, rand())) from table_26093));
+benchmark(100, (select avg(func_26093_b(a, rand())) from table_26093))
+0
+select @invoked;
+@invoked
+1000
+select benchmark(100, (select (a) from table_26093));
+ERROR 21000: Subquery returns more than 1 row
+drop table table_26093;
+drop function func_26093_a;
+drop function func_26093_b;
 End of 5.0 tests

--- 1.20/mysql-test/t/func_misc.test	2007-02-14 20:42:38 -07:00
+++ 1.21/mysql-test/t/func_misc.test	2007-02-14 20:42:38 -07:00
@@ -132,4 +132,58 @@ set global query_cache_size=default;
 create table t1 select INET_ATON('255.255.0.1') as `a`;
 show create table t1;
 drop table t1;
+
+#
+# Bug#26093 (SELECT BENCHMARK() for SELECT statements does not produce
+#   valid results)
+#
+
+--disable_warnings
+drop table if exists table_26093;
+drop function if exists func_26093_a;
+drop function if exists func_26093_b;
+--enable_warnings
+
+create table table_26093(a int);
+insert into table_26093 values
+(1), (2), (3), (4), (5),
+(6), (7), (8), (9), (10);
+
+delimiter ||;
+
+create function func_26093_a(x int) returns int
+begin
+  set @invoked := @invoked + 1;
+  return x;
+end||
+
+create function func_26093_b(x int, y int) returns int
+begin
+  set @invoked := @invoked + 1;
+  return x;
+end||
+
+delimiter ;||
+
+select avg(a) from table_26093;
+
+select benchmark(100, (select avg(a) from table_26093));
+
+set @invoked := 0;
+select benchmark(100, (select avg(func_26093_a(a)) from table_26093));
+# Returns only 10, since intermediate results are cached.
+select @invoked;
+
+set @invoked := 0;
+select benchmark(100, (select avg(func_26093_b(a, rand())) from table_26093));
+# Returns 1000, due to rand() preventing caching.
+select @invoked;
+
+--error ER_SUBQUERY_NO_1_ROW
+select benchmark(100, (select (a) from table_26093));
+
+drop table table_26093;
+drop function func_26093_a;
+drop function func_26093_b;
+
 --echo End of 5.0 tests
Thread
bk commit into 5.0 tree (malff:1.2395) BUG#26093marc.alff15 Feb