diff --git a/BitKeeper/etc/config b/BitKeeper/etc/config index c609fcdbd4920172b61d2dc34e84cfa45a6ac401..1ac24031dca7af1fcc6e064c2137d7e35dbe6c73 100644 --- a/BitKeeper/etc/config +++ b/BitKeeper/etc/config @@ -69,6 +69,7 @@ pager: hours: [serg:]checkout:get [arjen:]checkout:get +[kostja:]checkout:get [nick:]checkout:get checkout:edit eoln:unix diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index 311403f93e601f2233d5942d12a45b8d7a663ab7..3f0d0ce05fbcbc1c4ae920e74a8a9196de870ea8 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -126,6 +126,7 @@ kaa@polly.local kaj@work.mysql.com kent@mysql.com konstantin@mysql.com +kosipov@production.mysql.com kostja@oak.local lars@mysql.com lenz@kallisto.mysql.com diff --git a/libmysql/errmsg.c b/libmysql/errmsg.c index 48e44327d0f6193b05f215774bc83f215ce65cbf..5d183b478ef2bbe50536899295aed23a71250342 100644 --- a/libmysql/errmsg.c +++ b/libmysql/errmsg.c @@ -80,7 +80,7 @@ const char *client_errors[]= "Row retrieval was canceled by mysql_stmt_close() call", "Attempt to read column without prior row fetch", "Prepared statement contains no metadata", - "Attempt to read a row while there is no result set associated with the statement" + "Attempt to read a row while there is no result set associated with the statement", "" }; @@ -142,7 +142,7 @@ const char *client_errors[]= "Row retrieval was canceled by mysql_stmt_close() call", "Attempt to read column without prior row fetch", "Prepared statement contains no metadata", - "Attempt to read a row while there is no result set associated with the statement" + "Attempt to read a row while there is no result set associated with the statement", "" }; @@ -202,7 +202,7 @@ const char *client_errors[]= "Row retrieval was canceled by mysql_stmt_close() call", "Attempt to read column without prior row fetch", "Prepared statement contains no metadata", - "Attempt to read a row while there is no result set associated with the statement" + "Attempt to read a row while there is no result set associated with the statement", "" }; #endif diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 0cc164486253c46f4e99601d37fa0ac51b4c3c18..c1164380f09866329f773ab26812079531e8446e 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -3073,4 +3073,29 @@ update v1 set data = 10| call bug9841()| drop view v1| drop procedure bug9841| +drop procedure if exists bug5963| +create procedure bug5963_1 () begin declare v int; set v = (select s1 from t3); select v; end;| +create table t3 (s1 int)| +insert into t3 values (5)| +call bug5963_1()| +v +5 +call bug5963_1()| +v +5 +drop procedure bug5963_1| +drop table t3| +create procedure bug5963_2 (cfk_value int) +begin +if cfk_value in (select cpk from t3) then +set @x = 5; +end if; +end; +| +create table t3 (cpk int)| +insert into t3 values (1)| +call bug5963_2(1)| +call bug5963_2(1)| +drop procedure bug5963_2| +drop table t3| drop table t1,t2; diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result index 35bd8d7367598a3522f8bc3e79cc744900dc0c88..e775724ff543190b8d709f0afa683b3380fd94cb 100644 --- a/mysql-test/r/type_newdecimal.result +++ b/mysql-test/r/type_newdecimal.result @@ -876,3 +876,12 @@ SELECT * FROM t1; f1 f2 9999999999999999999999999999999999.00000000000000000000 0.00 DROP TABLE t1; +CREATE TABLE t1 (GRADE DECIMAL(4) NOT NULL, PRIMARY KEY (GRADE)) ENGINE=INNODB; +INSERT INTO t1 (GRADE) VALUES (151),(252),(343); +SELECT GRADE FROM t1 WHERE GRADE > 160 AND GRADE < 300; +GRADE +252 +SELECT GRADE FROM t1 WHERE GRADE= 151; +GRADE +151 +DROP TABLE t1; diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index b4066df16664f072b9519ae2e0967f6e697b1cdd..80acaacfdb3f56c994e978a59d16d9befac923ee 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -3772,6 +3772,35 @@ drop view v1| drop procedure bug9841| +# +# BUG#5963 subqueries in SET/IF +# +--disable_warnings +drop procedure if exists bug5963| +--enable_warnings + +create procedure bug5963_1 () begin declare v int; set v = (select s1 from t3); select v; end;| +create table t3 (s1 int)| +insert into t3 values (5)| +call bug5963_1()| +call bug5963_1()| +drop procedure bug5963_1| +drop table t3| + +create procedure bug5963_2 (cfk_value int) +begin + if cfk_value in (select cpk from t3) then + set @x = 5; + end if; + end; +| +create table t3 (cpk int)| +insert into t3 values (1)| +call bug5963_2(1)| +call bug5963_2(1)| +drop procedure bug5963_2| +drop table t3| + # # BUG#NNNN: New bug synopsis # diff --git a/mysql-test/t/type_newdecimal.test b/mysql-test/t/type_newdecimal.test index 45a2034e8ccb5baae0be07b4f6eb738908c25127..78ad5ed22868b4ec753b44207cca11ff43b724a6 100644 --- a/mysql-test/t/type_newdecimal.test +++ b/mysql-test/t/type_newdecimal.test @@ -906,3 +906,13 @@ CREATE TABLE t1 (f1 DECIMAL (64,20), f2 DECIMAL(2,2)); INSERT INTO t1 VALUES (9999999999999999999999999999999999, 0); SELECT * FROM t1; DROP TABLE t1; + +# +# Bug #10465 +# + +CREATE TABLE t1 (GRADE DECIMAL(4) NOT NULL, PRIMARY KEY (GRADE)) ENGINE=INNODB; +INSERT INTO t1 (GRADE) VALUES (151),(252),(343); +SELECT GRADE FROM t1 WHERE GRADE > 160 AND GRADE < 300; +SELECT GRADE FROM t1 WHERE GRADE= 151; +DROP TABLE t1; diff --git a/sql/field.cc b/sql/field.cc index 78266441bdae2412620dfa37614ae98397f46d32..34c5210b43c2052d3fed5960bbeb2e68dffdbcaa 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -8060,7 +8060,12 @@ void create_field::create_length_to_internal_length(void) } break; case MYSQL_TYPE_NEWDECIMAL: - key_length= pack_length= my_decimal_get_binary_size(length, decimals); + key_length= pack_length= + my_decimal_get_binary_size(my_decimal_length_to_precision(length, + decimals, + flags & + UNSIGNED_FLAG), + decimals); break; default: key_length= pack_length= calc_pack_length(sql_type, length); diff --git a/sql/item.cc b/sql/item.cc index 30c134ebdd5a9df48b6a9fc4ee4c50d0d01c2cfa..8100e78491b993b8b5537261d14648941a5ea662 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -740,6 +740,13 @@ Item_splocal::this_item() return thd->spcont->get_item(m_offset); } + +Item ** +Item_splocal::this_item_addr(THD *thd, Item **addr) +{ + return thd->spcont->get_item_addr(m_offset); +} + Item * Item_splocal::this_const_item() const { diff --git a/sql/item.h b/sql/item.h index 0e15e539067b5befc2990e8f4fe11bd739f23393..0166c5e87076ff392970b5b6492928928db09ce9 100644 --- a/sql/item.h +++ b/sql/item.h @@ -525,8 +525,17 @@ public: virtual Item *equal_fields_propagator(byte * arg) { return this; } virtual Item *set_no_const_sub(byte *arg) { return this; } virtual Item *replace_equal_field(byte * arg) { return this; } - - virtual Item *this_item() { return this; } /* For SPs mostly. */ + + /* + For SP local variable returns pointer to Item representing its + current value and pointer to current Item otherwise. + */ + virtual Item *this_item() { return this; } + /* + For SP local variable returns address of pointer to Item representing its + current value and pointer passed via parameter otherwise. + */ + virtual Item **this_item_addr(THD *thd, Item **addr) { return addr; } virtual Item *this_const_item() const { return const_cast<Item*>(this); } /* For SPs mostly. */ // Row emulation @@ -573,6 +582,7 @@ public: bool is_splocal() { return 1; } /* Needed for error checking */ Item *this_item(); + Item **this_item_addr(THD *thd, Item **); Item *this_const_item() const; bool fix_fields(THD *, struct st_table_list *, Item **); diff --git a/sql/item_func.cc b/sql/item_func.cc index 3c87b6ef920f349ba5b9cec9b0412d0c4a0866d2..db49b7b4ae96fcb760aa4404a847ecf6fde32601 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -1255,8 +1255,8 @@ void Item_func_div::result_precision() void Item_func_div::fix_length_and_dec() { DBUG_ENTER("Item_func_div::fix_length_and_dec"); - Item_num_op::fix_length_and_dec(); prec_increment= current_thd->variables.div_precincrement; + Item_num_op::fix_length_and_dec(); switch(hybrid_type) { case REAL_RESULT: { diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 0be93c3e41c8a8dbf076edd93c7085daa15267ea..2ffcd45b1a7c07be433a96ac1cb53249949849a9 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -97,19 +97,48 @@ sp_multi_results_command(enum enum_sql_command cmd) } } + +/* + Prepare Item for execution (call of fix_fields) + + SYNOPSIS + sp_prepare_func_item() + thd thread handler + it_addr pointer on item refernce + + RETURN + NULL error + prepared item +*/ + +static Item * +sp_prepare_func_item(THD* thd, Item **it_addr) +{ + Item *it= *it_addr; + DBUG_ENTER("sp_prepare_func_item"); + it_addr= it->this_item_addr(thd, it_addr); + + if (!it->fixed && (*it_addr)->fix_fields(thd, 0, it_addr)) + { + DBUG_PRINT("info", ("fix_fields() failed")); + DBUG_RETURN(NULL); + } + DBUG_RETURN(*it_addr); +} + + /* Evaluate a (presumed) func item. Always returns an item, the parameter ** if nothing else. */ Item * -sp_eval_func_item(THD *thd, Item *it, enum enum_field_types type) +sp_eval_func_item(THD *thd, Item **it_addr, enum enum_field_types type) { DBUG_ENTER("sp_eval_func_item"); - it= it->this_item(); + Item *it= sp_prepare_func_item(thd, it_addr); DBUG_PRINT("info", ("type: %d", type)); - if (!it->fixed && it->fix_fields(thd, 0, &it)) + if (!it) { - DBUG_PRINT("info", ("fix_fields() failed")); DBUG_RETURN(NULL); } @@ -679,7 +708,7 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp) for (i= 0 ; i < params && i < argcount ; i++) { sp_pvar_t *pvar = m_pcont->find_pvar(i); - Item *it= sp_eval_func_item(thd, *argp++, pvar->type); + Item *it= sp_eval_func_item(thd, argp++, pvar->type); if (it) nctx->push_item(it); @@ -761,7 +790,7 @@ sp_head::execute_procedure(THD *thd, List<Item> *args) { Item_null *nit= NULL; // Re-use this, and only create if needed uint i; - List_iterator_fast<Item> li(*args); + List_iterator<Item> li(*args); Item *it; nctx= new sp_rcontext(csize, hmax, cmax); @@ -794,7 +823,7 @@ sp_head::execute_procedure(THD *thd, List<Item> *args) } else { - Item *it2= sp_eval_func_item(thd, it, pvar->type); + Item *it2= sp_eval_func_item(thd, li.ref(), pvar->type); if (it2) nctx->push_item(it2); // IN or INOUT @@ -1439,7 +1468,7 @@ sp_instr_set::exec_core(THD *thd, uint *nextp) Item *it; int res; - it= sp_eval_func_item(thd, m_value, m_type); + it= sp_eval_func_item(thd, &m_value, m_type); if (! it) res= -1; else @@ -1569,13 +1598,13 @@ sp_instr_jump_if::exec_core(THD *thd, uint *nextp) Item *it; int res; - it= sp_eval_func_item(thd, m_expr, MYSQL_TYPE_TINY); + it= sp_prepare_func_item(thd, &m_expr); if (!it) res= -1; else { res= 0; - if (it->val_int()) + if (it->val_bool()) *nextp = m_dest; else *nextp = m_ip+1; @@ -1627,13 +1656,13 @@ sp_instr_jump_if_not::exec_core(THD *thd, uint *nextp) Item *it; int res; - it= sp_eval_func_item(thd, m_expr, MYSQL_TYPE_TINY); + it= sp_prepare_func_item(thd, &m_expr); if (! it) res= -1; else { res= 0; - if (! it->val_int()) + if (! it->val_bool()) *nextp = m_dest; else *nextp = m_ip+1; @@ -1685,7 +1714,7 @@ sp_instr_freturn::exec_core(THD *thd, uint *nextp) Item *it; int res; - it= sp_eval_func_item(thd, m_value, m_type); + it= sp_eval_func_item(thd, &m_value, m_type); if (! it) res= -1; else diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc index def38009eee6a574e634ca64e8026c7d329838a6..672491a97f29b86f40ef35dbdab3cf744d8d67f3 100644 --- a/sql/sp_rcontext.cc +++ b/sql/sp_rcontext.cc @@ -41,10 +41,10 @@ sp_rcontext::sp_rcontext(uint fsize, uint hmax, uint cmax) } int -sp_rcontext::set_item_eval(uint idx, Item *i, enum_field_types type) +sp_rcontext::set_item_eval(uint idx, Item **item_addr, enum_field_types type) { - extern Item *sp_eval_func_item(THD *thd, Item *it, enum_field_types type); - Item *it= sp_eval_func_item(current_thd, i, type); + extern Item *sp_eval_func_item(THD *thd, Item **it, enum_field_types type); + Item *it= sp_eval_func_item(current_thd, item_addr, type); if (! it) return -1; diff --git a/sql/sp_rcontext.h b/sql/sp_rcontext.h index afcd937a369b8c7a99f74fea8cdf032677ee3539..c132032e32c6735dfff8ac52771b53e5559a36c8 100644 --- a/sql/sp_rcontext.h +++ b/sql/sp_rcontext.h @@ -74,7 +74,7 @@ class sp_rcontext : public Sql_alloc /* Returns 0 on success, -1 on (eval) failure */ int - set_item_eval(uint idx, Item *i, enum_field_types type); + set_item_eval(uint idx, Item **i, enum_field_types type); inline Item * get_item(uint idx) @@ -82,6 +82,14 @@ class sp_rcontext : public Sql_alloc return m_frame[idx]; } + + inline Item ** + get_item_addr(uint idx) + { + return m_frame + idx; + } + + inline void set_result(Item *it) { diff --git a/sql/sql_class.cc b/sql/sql_class.cc index a6a1f4d60ef9e20cf9af8fed851aab1cfa4c3639..2d5c4722164ef94491b61c9abfb068be303dc74f 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1719,10 +1719,9 @@ 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); + List_iterator<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) @@ -1741,13 +1740,13 @@ bool select_dumpvar::send_data(List<Item> &items) my_message(ER_TOO_MANY_ROWS, ER(ER_TOO_MANY_ROWS), MYF(0)); DBUG_RETURN(1); } - while ((zz=my_li++) && (item=it++)) + while ((zz=my_li++) && (it++)) { if (zz->local) { if ((yy=var_li++)) { - if (thd->spcont->set_item_eval(yy->get_offset(), item, zz->type)) + if (thd->spcont->set_item_eval(yy->get_offset(), it.ref(), zz->type)) DBUG_RETURN(1); } } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 94f1a8e0df4020cdeaece85ee60ed55d2c9b272e..a33d60df0d463f30585dbf42455447b02f61d8d1 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -296,7 +296,7 @@ protected: *link_next, **link_prev; /* list of whole SELECT_LEX */ public: - ulong options; + ulonglong options; /* result of this query can't be cached, bit field, can be : UNCACHEABLE_DEPENDENT