List:Internals« Previous MessageNext Message »
From:pem Date:September 26 2005 2:30pm
Subject:bk commit into 5.0 tree (pem:1.1995)
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of pem. When pem 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
  1.1995 05/09/26 15:55:37 pem@stripped +6 -0
  Merge mysql.com:/usr/local/bk/mysql-5.0
  into  mysql.com:/usr/home/pem/mysql-5.0

  sql/sp_rcontext.h
    1.25 05/09/26 15:55:28 pem@stripped +0 -0
    Auto merged

  sql/sp_rcontext.cc
    1.34 05/09/26 15:55:28 pem@stripped +0 -0
    Auto merged

  sql/sp_head.cc
    1.188 05/09/26 15:55:28 pem@stripped +0 -0
    Auto merged

  sql/item.cc
    1.180 05/09/26 15:55:27 pem@stripped +0 -0
    Auto merged

  mysql-test/t/sp.test
    1.153 05/09/26 15:55:27 pem@stripped +0 -0
    Auto merged

  mysql-test/r/sp.result
    1.157 05/09/26 15:55:27 pem@stripped +0 -0
    Auto merged

# 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:	pem
# Host:	mysql.comhem.se
# Root:	/usr/home/pem/mysql-5.0/RESYNC

--- 1.179/sql/item.cc	2005-09-15 21:29:00 +02:00
+++ 1.180/sql/item.cc	2005-09-26 15:55:27 +02:00
@@ -1845,7 +1845,7 @@
   decimals= (uint8) decimal_value.frac;
   fixed= 1;
   max_length= my_decimal_precision_to_length(decimal_value.intg + decimals,
-                                             decimals, !decimal_value.sign());
+                                             decimals, FALSE);
 }
 
 
@@ -1855,8 +1855,7 @@
                     &decimal_value, precision, scale);
   decimals= (uint8) decimal_value.frac;
   fixed= 1;
-  max_length= my_decimal_precision_to_length(precision, decimals,
-                                             !decimal_value.sign());
+  max_length= my_decimal_precision_to_length(precision, decimals, FALSE);
 }
 
 

--- 1.156/mysql-test/r/sp.result	2005-09-20 01:30:57 +02:00
+++ 1.157/mysql-test/r/sp.result	2005-09-26 15:55:27 +02:00
@@ -3360,4 +3360,79 @@
 internal_var
 NULL
 drop procedure bug12979_2|
+drop procedure if exists bug12589_1|
+drop procedure if exists bug12589_2|
+drop procedure if exists bug12589_3|
+create procedure bug12589_1()
+begin
+declare spv1 decimal(3,3);
+set spv1= 123.456;
+set spv1 = 'test';
+create temporary table tm1 as select spv1;
+show create table tm1;
+drop temporary table tm1;
+end|
+create procedure bug12589_2()
+begin
+declare spv1 decimal(6,3);
+set spv1= 123.456;
+create temporary table tm1 as select spv1;
+show create table tm1;
+drop temporary table tm1;
+end|
+create procedure bug12589_3()
+begin
+declare spv1 decimal(6,3);
+set spv1= -123.456;
+create temporary table tm1 as select spv1;
+show create table tm1;
+drop temporary table tm1;
+end|
+call bug12589_1()|
+Table	Create Table
+tm1	CREATE TEMPORARY TABLE `tm1` (
+  `spv1` decimal(1,0) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+Warnings:
+Warning	1292	Truncated incorrect DECIMAL value: 'test'
+call bug12589_2()|
+Table	Create Table
+tm1	CREATE TEMPORARY TABLE `tm1` (
+  `spv1` decimal(6,3) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+call bug12589_3()|
+Table	Create Table
+tm1	CREATE TEMPORARY TABLE `tm1` (
+  `spv1` decimal(6,3) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table if exists t3|
+drop procedure if exists bug6127|
+create table t3 (s1 int unique)|
+set @sm=@@sql_mode|
+set sql_mode='traditional'|
+create procedure bug6127()
+begin
+declare continue handler for sqlstate '23000'
+    begin
+declare continue handler for sqlstate '22003'
+        insert into t3 values (0);
+insert into t3 values (1000000000000000);
+end;
+insert into t3 values (1);
+insert into t3 values (1);
+end|
+call bug6127()|
+select * from t3|
+s1
+0
+1
+call bug6127()|
+ERROR 23000: Duplicate entry '0' for key 1
+select * from t3|
+s1
+0
+1
+set sql_mode=@sm|
+drop table t3|
+drop procedure bug6127|
 drop table t1,t2;

--- 1.152/mysql-test/t/sp.test	2005-09-20 01:30:57 +02:00
+++ 1.153/mysql-test/t/sp.test	2005-09-26 15:55:27 +02:00
@@ -4229,6 +4229,93 @@
 
 
 #
+# BUG#12589: Assert when creating temp. table from decimal stored procedure
+#            variable
+#
+--disable_warnings
+drop procedure if exists bug12589_1|
+drop procedure if exists bug12589_2|
+drop procedure if exists bug12589_3|
+--enable_warnings
+create procedure bug12589_1()
+begin
+  declare spv1 decimal(3,3);
+  set spv1= 123.456;
+
+  set spv1 = 'test';
+  create temporary table tm1 as select spv1;
+  show create table tm1;
+  drop temporary table tm1;
+end|
+
+create procedure bug12589_2()
+begin
+  declare spv1 decimal(6,3);
+  set spv1= 123.456;
+
+  create temporary table tm1 as select spv1;
+  show create table tm1;
+  drop temporary table tm1;
+end|
+
+create procedure bug12589_3()
+begin
+  declare spv1 decimal(6,3);
+  set spv1= -123.456;
+
+  create temporary table tm1 as select spv1;
+  show create table tm1;
+  drop temporary table tm1;
+end|
+
+# Note: The type of the field will match the value, not the declared
+#       type of the variable. (This is a type checking issue which
+#       might be changed later.)
+
+# Warning expected from "set spv1 = 'test'", the value is set to decimal "0".
+call bug12589_1()|
+# No warnings here
+call bug12589_2()|
+call bug12589_3()|
+
+
+#
+# BUG#6127: Stored procedure handlers within handlers don't work
+#
+--disable_warnings
+drop table if exists t3|
+drop procedure if exists bug6127|
+--enable_warnings
+create table t3 (s1 int unique)|
+
+set @sm=@@sql_mode|
+set sql_mode='traditional'|
+
+create procedure bug6127()
+begin
+  declare continue handler for sqlstate '23000'
+    begin
+      declare continue handler for sqlstate '22003'
+        insert into t3 values (0);
+
+      insert into t3 values (1000000000000000);
+    end;
+
+  insert into t3 values (1);
+  insert into t3 values (1);
+end|
+
+call bug6127()|
+select * from t3|
+--error ER_DUP_ENTRY
+call bug6127()|
+select * from t3|
+set sql_mode=@sm|
+drop table t3|
+drop procedure bug6127|
+
+
+#
 # BUG#NNNN: New bug synopsis
 #
 #--disable_warnings

--- 1.187/sql/sp_head.cc	2005-09-22 22:46:49 +02:00
+++ 1.188/sql/sp_head.cc	2005-09-26 15:55:28 +02:00
@@ -1015,7 +1015,7 @@
 	ip= hip;
 	ret= 0;
 	ctx->clear_handler();
-	ctx->in_handler= TRUE;
+	ctx->enter_handler(hip);
         thd->clear_error();
 	thd->killed= THD::NOT_KILLED;
 	continue;
@@ -2378,7 +2378,7 @@
     thd->spcont->restore_variables(m_frame);
     *nextp= thd->spcont->pop_hstack();
   }
-  thd->spcont->in_handler= FALSE;
+  thd->spcont->exit_handler();
   DBUG_RETURN(0);
 }
 

--- 1.33/sql/sp_rcontext.cc	2005-09-21 13:10:57 +02:00
+++ 1.34/sql/sp_rcontext.cc	2005-09-26 15:55:28 +02:00
@@ -25,6 +25,7 @@
 
 #include "mysql.h"
 #include "sp_head.h"
+#include "sql_cursor.h"
 #include "sp_rcontext.h"
 #include "sp_pcontext.h"
 
@@ -45,31 +46,18 @@
 sp_rcontext::set_item_eval(THD *thd, uint idx, Item **item_addr,
 			   enum_field_types type)
 {
-  extern Item *sp_eval_func_item(THD *thd, Item **it, enum_field_types type,
-				 Item *reuse, bool use_callers_arena);
   Item *it;
   Item *reuse_it;
-  Item *old_item_next;
   /* sp_eval_func_item will use callers_arena */
-  Item *old_free_list= thd->spcont->callers_arena->free_list;
   int res;
-  LINT_INIT(old_item_next);
 
-  if ((reuse_it= get_item(idx)))
-    old_item_next= reuse_it->next;
+  reuse_it= get_item(idx);
   it= sp_eval_func_item(thd, item_addr, type, reuse_it, TRUE);
   if (! it)
     res= -1;
   else
   {
     res= 0;
-    if (reuse_it && it == reuse_it)
-    {
-      // A reused item slot, where the constructor put it in the free_list,
-      // so we have to restore the list.
-      thd->spcont->callers_arena->free_list= old_free_list;
-      it->next= old_item_next;
-    }
     set_item(idx, it);
   }
 
@@ -175,7 +163,8 @@
  */
 
 sp_cursor::sp_cursor(sp_lex_keeper *lex_keeper, sp_instr_cpush *i)
-  :m_lex_keeper(lex_keeper), m_prot(NULL), m_isopen(0), m_current_row(NULL),
+  :m_lex_keeper(lex_keeper),
+   server_side_cursor(NULL),
    m_i(i)
 {
   /*
@@ -187,59 +176,37 @@
 
 
 /*
-  pre_open cursor
+  Open an SP cursor
 
   SYNOPSIS
-    pre_open()
-    THD		Thread handler
+    open()
+    THD		         Thread handler
 
-  NOTES
-    We have to open cursor in two steps to make it easy for sp_instr_copen
-    to reuse the sp_instr::exec_stmt() code.
-    If this function returns 0, post_open should not be called
 
   RETURN
-   0  ERROR
+   0 in case of success, -1 otherwise
 */
 
-sp_lex_keeper*
-sp_cursor::pre_open(THD *thd)
+int
+sp_cursor::open(THD *thd)
 {
-  if (m_isopen)
+  if (server_side_cursor)
   {
     my_message(ER_SP_CURSOR_ALREADY_OPEN, ER(ER_SP_CURSOR_ALREADY_OPEN),
                MYF(0));
-    return NULL;
+    return -1;
   }
-  init_alloc_root(&m_mem_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC);
-  if ((m_prot= new Protocol_cursor(thd, &m_mem_root)) == NULL)
-    return NULL;
-
-  /* Save for execution. Will be restored in post_open */
-  m_oprot= thd->protocol;
-  m_nseof= thd->net.no_send_eof;
-
-  /* Change protocol for execution */
-  thd->protocol= m_prot;
-  thd->net.no_send_eof= TRUE;
-  return m_lex_keeper;
-}
-
-
-void
-sp_cursor::post_open(THD *thd, my_bool was_opened)
-{
-  thd->net.no_send_eof= m_nseof; // Restore the originals
-  thd->protocol= m_oprot;
-  if ((m_isopen= was_opened))
-    m_current_row= m_prot->data;
+  if (mysql_open_cursor(thd, (uint) ALWAYS_MATERIALIZED_CURSOR, &result,
+                        &server_side_cursor))
+    return -1;
+  return 0;
 }
 
 
 int
 sp_cursor::close(THD *thd)
 {
-  if (! m_isopen)
+  if (! server_side_cursor)
   {
     my_message(ER_SP_CURSOR_NOT_OPEN, ER(ER_SP_CURSOR_NOT_OPEN), MYF(0));
     return -1;
@@ -252,106 +219,82 @@
 void
 sp_cursor::destroy()
 {
-  if (m_prot)
-  {
-    delete m_prot;
-    m_prot= NULL;
-    free_root(&m_mem_root, MYF(0));
-  }
-  m_isopen= FALSE;
+  delete server_side_cursor;
+  server_side_cursor= 0;
 }
 
+
 int
 sp_cursor::fetch(THD *thd, List<struct sp_pvar> *vars)
 {
-  List_iterator_fast<struct sp_pvar> li(*vars);
-  sp_pvar_t *pv;
-  MYSQL_ROW row;
-  uint fldcount;
-
-  if (! m_isopen)
+  if (! server_side_cursor)
   {
     my_message(ER_SP_CURSOR_NOT_OPEN, ER(ER_SP_CURSOR_NOT_OPEN), MYF(0));
     return -1;
   }
-  if (m_current_row == NULL)
+  if (vars->elements != result.get_field_count())
   {
-    my_message(ER_SP_FETCH_NO_DATA, ER(ER_SP_FETCH_NO_DATA), MYF(0));
+    my_message(ER_SP_WRONG_NO_OF_FETCH_ARGS,
+               ER(ER_SP_WRONG_NO_OF_FETCH_ARGS), MYF(0));
     return -1;
   }
 
-  row= m_current_row->data;
-  for (fldcount= 0 ; (pv= li++) ; fldcount++)
-  {
-    Item *it;
-    Item *reuse;
-    uint rsize;
-    Item *old_item_next;
-    Item *old_free_list= thd->free_list;
-    const char *s;
-    LINT_INIT(old_item_next);
-
-    if (fldcount >= m_prot->get_field_count())
-    {
-      my_message(ER_SP_WRONG_NO_OF_FETCH_ARGS,
-                 ER(ER_SP_WRONG_NO_OF_FETCH_ARGS), MYF(0));
-      return -1;
-    }
+  result.set_spvar_list(vars);
 
-    if ((reuse= thd->spcont->get_item(pv->offset)))
-      old_item_next= reuse->next;
+  /* Attempt to fetch one row */
+  if (server_side_cursor->is_open())
+    server_side_cursor->fetch(1);
 
-    s= row[fldcount];
-    if (!s)
-      it= new(reuse, &rsize) Item_null();
-    else
-    {
-      /*
-        Length of data can be calculated as:
-        pointer_to_next_not_null_object - s -1
-        where the last -1 is to remove the end \0
-      */
-      uint len;
-      MYSQL_ROW next= row+fldcount+1;
-      while (!*next)                             // Skip nulls
-        next++;
-      len= (*next -s)-1;
-      switch (sp_map_result_type(pv->type)) {
-      case INT_RESULT:
-	it= new(reuse, &rsize) Item_int(s);
-	break;
-      case REAL_RESULT:
-        it= new(reuse, &rsize) Item_float(s, len);
-	break;
-      case DECIMAL_RESULT:
-        it= new(reuse, &rsize) Item_decimal(s, len, thd->db_charset);
-        break;
-      case STRING_RESULT:
-        /* TODO: Document why we do an extra copy of the string 's' here */
-        it= new(reuse, &rsize) Item_string(thd->strmake(s, len), len,
-					   thd->db_charset);
-        break;
-      case ROW_RESULT:
-      default:
-        DBUG_ASSERT(0);
-      }
-    }
-    it->rsize= rsize;
-    if (reuse && it == reuse)
-    {
-      // A reused item slot, where the constructor put it in the free_list,
-      // so we have to restore the list.
-      thd->free_list= old_free_list;
-      it->next= old_item_next;
-    }
-    thd->spcont->set_item(pv->offset, it);
-  }
-  if (fldcount < m_prot->get_field_count())
+  /*
+    If the cursor was pointing after the last row, the fetch will
+    close it instead of sending any rows.
+  */
+  if (! server_side_cursor->is_open())
   {
-    my_message(ER_SP_WRONG_NO_OF_FETCH_ARGS,
-               ER(ER_SP_WRONG_NO_OF_FETCH_ARGS), MYF(0));
+    my_message(ER_SP_FETCH_NO_DATA, ER(ER_SP_FETCH_NO_DATA), MYF(0));
     return -1;
   }
-  m_current_row= m_current_row->next;
+
   return 0;
+}
+
+
+/***************************************************************************
+ Select_fetch_into_spvars
+****************************************************************************/
+
+int Select_fetch_into_spvars::prepare(List<Item> &fields, SELECT_LEX_UNIT *u)
+{
+  /*
+    Cache the number of columns in the result set in order to easily
+    return an error if column count does not match value count.
+  */
+  field_count= fields.elements;
+  return select_result_interceptor::prepare(fields, u);
+}
+
+
+bool Select_fetch_into_spvars::send_data(List<Item> &items)
+{
+  List_iterator_fast<struct sp_pvar> pv_iter(*spvar_list);
+  List_iterator_fast<Item> item_iter(items);
+  sp_pvar_t *pv;
+  Item *item;
+
+  /* Must be ensured by the caller */
+  DBUG_ASSERT(spvar_list->elements == items.elements);
+
+  /*
+    Assign the row fetched from a server side cursor to stored
+    procedure variables.
+  */
+  for (; pv= pv_iter++, item= item_iter++; )
+  {
+    Item *reuse= thd->spcont->get_item(pv->offset);
+    /* Evaluate a new item on the arena of the calling instruction */
+    Item *it= sp_eval_func_item(thd, &item, pv->type, reuse, TRUE);
+
+    thd->spcont->set_item(pv->offset, it);
+  }
+  return FALSE;
 }

--- 1.24/sql/sp_rcontext.h	2005-09-21 13:10:57 +02:00
+++ 1.25/sql/sp_rcontext.h	2005-09-26 15:55:28 +02:00
@@ -229,6 +229,27 @@
 }; // class sp_rcontext : public Sql_alloc
 
 
+/*
+  An interceptor of cursor result set used to implement
+  FETCH <cname> INTO <varlist>.
+*/
+
+class Select_fetch_into_spvars: public select_result_interceptor
+{
+  List<struct sp_pvar> *spvar_list;
+  uint field_count;
+public:
+  uint get_field_count() { return field_count; }
+  void set_spvar_list(List<struct sp_pvar> *vars) { spvar_list= vars; }
+
+  virtual bool send_eof() { return FALSE; }
+  virtual bool send_data(List<Item> &items);
+  virtual int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
+};
+
+
+/* A mediator between stored procedures and server side cursors */
+
 class sp_cursor : public Sql_alloc
 {
 public:
@@ -240,12 +261,11 @@
     destroy();
   }
 
-  // We have split this in two to make it easy for sp_instr_copen
-  // to reuse the sp_instr::exec_stmt() code.
   sp_lex_keeper *
-  pre_open(THD *thd);
-  void
-  post_open(THD *thd, my_bool was_opened);
+  get_lex_keeper() { return m_lex_keeper; }
+
+  int
+  open(THD *thd);
 
   int
   close(THD *thd);
@@ -253,7 +273,7 @@
   inline my_bool
   is_open()
   {
-    return m_isopen;
+    return test(server_side_cursor);
   }
 
   int
@@ -264,18 +284,13 @@
   {
     return m_i;
   }
-  
+
 private:
 
-  MEM_ROOT m_mem_root;		// My own mem_root
+  Select_fetch_into_spvars result;
   sp_lex_keeper *m_lex_keeper;
-  Protocol_cursor *m_prot;
-  my_bool m_isopen;
-  my_bool m_nseof;		// Original no_send_eof
-  Protocol *m_oprot;		// Original protcol
-  MYSQL_ROWS *m_current_row;
+  Server_side_cursor *server_side_cursor;
   sp_instr_cpush *m_i;		// My push instruction
-  
   void
   destroy();
 
Thread
bk commit into 5.0 tree (pem:1.1995)pem26 Sep