From e6b8fa57072d29131071057fb827161346cd9df0 Mon Sep 17 00:00:00 2001
From: "Sinisa@sinisa.nasamreza.org" <>
Date: Sat, 18 Jan 2003 18:21:13 +0200
Subject: [PATCH] SELECT ... INTO local_vars ...;

For Stored Procedures
---
 mysql-test/r/sp.result | 17 ++++++++++++++
 mysql-test/t/sp.test   | 13 +++++++++++
 sql/sql_class.cc       | 51 +++++++++++++++++++++++++++++++++++-------
 sql/sql_class.h        | 13 +++++++++--
 sql/sql_yacc.yy        | 23 +++++++++++++++++--
 5 files changed, 105 insertions(+), 12 deletions(-)

diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result
index 0e2dfc52c5..59259c1225 100644
--- a/mysql-test/r/sp.result
+++ b/mysql-test/r/sp.result
@@ -124,6 +124,15 @@ insert into test.t1 values ("h1", x);
 else
 insert into test.t1 values ("h?", x);
 end case;
+create procedure sinisa()
+begin
+declare x char(16);
+declare y int;
+set x="aaaaa";
+set y=22;
+select id,data into x,y from test.t1 limit 2,1;
+insert into test.t1 values (x, y);
+end;
 call foo42();
 select * from t1;
 id	data
@@ -236,6 +245,13 @@ id	data
 h0	0
 h1	1
 h?	17
+call sinisa();
+select * from t1;
+id	data
+h0	0
+h1	1
+h?	17
+h?	17
 delete from t1;
 drop procedure foo42;
 drop procedure bar;
@@ -258,4 +274,5 @@ drop procedure e;
 drop procedure f;
 drop procedure g;
 drop procedure h;
+drop procedure sinisa;
 drop table t1;
diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test
index 6b90d700b5..d9b04afa33 100644
--- a/mysql-test/t/sp.test
+++ b/mysql-test/t/sp.test
@@ -187,6 +187,16 @@ else
   insert into test.t1 values ("h?", x);
 end case|
 
+create procedure sinisa()
+begin
+  declare x char(16);
+  declare y int;
+  set x="aaaaa";
+  set y=22;
+  select id,data into x,y from test.t1 limit 2,1;
+  insert into test.t1 values (x, y);
+end|
+
 delimiter ;|
 
 # Now, the CALL tests...
@@ -263,6 +273,8 @@ call h(0);
 call h(1);
 call h(17);
 select * from t1;
+call sinisa();
+select * from t1;
 delete from t1;
 
 drop procedure foo42;
@@ -286,5 +298,6 @@ drop procedure e;
 drop procedure f;
 drop procedure g;
 drop procedure h;
+drop procedure sinisa;
 
 drop table t1;
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index a5fb792224..8e66e1ca06 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -36,6 +36,7 @@
 #endif
 #include <mysys_err.h>
 #include <assert.h>
+#include <sp_rcontext.h>
 
 
 /*****************************************************************************
@@ -960,37 +961,71 @@ bool select_exists_subselect::send_data(List<Item> &items)
 int select_dumpvar::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
 {
   List_iterator_fast<Item> li(list);
-  List_iterator_fast<LEX_STRING> gl(var_list);
+  List_iterator_fast<my_var> gl(var_list);
   Item *item;
+  my_var *mv;
   LEX_STRING *ls;
   if (var_list.elements != list.elements)
   {
     my_error(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT, MYF(0));
     return 1;
   }
+  unit=u;
   while ((item=li++))
   {
-    ls= gl++;
-    Item_func_set_user_var *xx = new Item_func_set_user_var(*ls,item);
-    xx->fix_fields(current_thd,(TABLE_LIST*) current_thd->lex.select_lex.table_list.first,&item);
-    xx->fix_length_and_dec();
-    vars.push_back(xx);
+    mv=gl++;
+    ls= &mv->s;
+    if (mv->local)
+    {
+      (void)local_vars.push_back(new Item_splocal(mv->offset));
+    }
+    else
+    {
+      Item_func_set_user_var *xx = new Item_func_set_user_var(*ls,item);
+      xx->fix_fields(thd,(TABLE_LIST*) thd->lex.select_lex.table_list.first,&item);
+      xx->fix_length_and_dec();
+      vars.push_back(xx);
+    }
   }
   return 0;
 }
 bool select_dumpvar::send_data(List<Item> &items)
 {
   List_iterator_fast<Item_func_set_user_var> li(vars);
+  List_iterator_fast<Item_splocal> var_li(local_vars);
+  List_iterator_fast<my_var> my_li(var_list);
+  List_iterator_fast<Item> it(items);
   Item_func_set_user_var *xx;
+  Item_splocal *yy;
+  Item *item;
+  my_var *zz;
   DBUG_ENTER("send_data");
+  if (unit->offset_limit_cnt)
+  {						// using limit offset,count
+    unit->offset_limit_cnt--;
+    DBUG_RETURN(0);
+  }
 
   if (row_count++) 
   {
     my_error(ER_TOO_MANY_ROWS, MYF(0));
     DBUG_RETURN(1);
   }
-  while ((xx=li++))
-    xx->update();
+  while ((zz=my_li++) && (item=it++))
+  {
+    if (zz->local)
+    {
+      if ((yy=var_li++)) 
+      {
+	thd->spcont->set_item(yy->get_offset(), item);
+      }
+    }
+    else
+    {
+      if ((xx=li++))
+	xx->update();
+    }
+  }
   DBUG_RETURN(0);
 }
 
diff --git a/sql/sql_class.h b/sql/sql_class.h
index a078c4bd28..f367b089fd 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -987,13 +987,22 @@ public:
   bool send_eof();
 };
 
+class my_var : public Sql_alloc  {
+public:
+  LEX_STRING s;
+  bool local;
+  uint offset;
+  my_var (LEX_STRING& j, bool i, uint o) : s(j), local(i), offset(o) {}
+  ~my_var() {}
+};
 
 class select_dumpvar :public select_result {
   ha_rows row_count;
 public:
-  List<LEX_STRING> var_list;
+  List<my_var> var_list;
   List<Item_func_set_user_var> vars;
-  select_dumpvar(void)  { var_list.empty(); vars.empty(); row_count=0;}
+  List<Item_splocal> local_vars;
+  select_dumpvar(void)  { var_list.empty(); local_vars.empty(); vars.empty(); row_count=0;}
   ~select_dumpvar() {}
   int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
   bool send_fields(List<Item> &list, uint flag) {return 0;}
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 2cc2f674d4..33ec3788b2 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -3313,10 +3313,29 @@ select_var_list:
 	   | select_var_ident {}
            ;
 
-select_var_ident:  '@' ident_or_text
+select_var_ident:  
+	   '@' ident_or_text
            {
              LEX *lex=Lex;
-	     if (lex->result && ((select_dumpvar *)lex->result)->var_list.push_back((LEX_STRING*) sql_memdup(&$2,sizeof(LEX_STRING))))
+	     if (lex->result) 
+	       ((select_dumpvar *)lex->result)->var_list.push_back( new my_var($2,0,0));
+	     else
+	       YYABORT;
+	   }
+           | ident_or_text
+           {
+             LEX *lex=Lex;
+	     if (!lex->spcont)
+	       YYABORT;
+	     sp_pvar_t *t;
+	     if (!(t=lex->spcont->find_pvar(&$1)))
+	     {
+	       send_error(lex->thd, ER_SYNTAX_ERROR);
+	       YYABORT;
+	     }
+	     if (lex->result)
+	       ((select_dumpvar *)lex->result)->var_list.push_back( new my_var($1,1,t->offset));
+	     else
 	       YYABORT;
 	   }
            ;
-- 
2.30.9