diff options
-rw-r--r-- | mysql-test/r/group_min_max.result | 38 | ||||
-rw-r--r-- | mysql-test/r/sp-error.result | 28 | ||||
-rw-r--r-- | mysql-test/t/group_min_max.test | 6 | ||||
-rw-r--r-- | mysql-test/t/sp-error.test | 38 | ||||
-rw-r--r-- | sql/opt_range.cc | 11 | ||||
-rw-r--r-- | sql/share/errmsg.txt | 2 | ||||
-rw-r--r-- | sql/sp_pcontext.cc | 24 | ||||
-rw-r--r-- | sql/sp_pcontext.h | 6 | ||||
-rw-r--r-- | sql/sql_repl.cc | 5 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 12 |
10 files changed, 162 insertions, 8 deletions
diff --git a/mysql-test/r/group_min_max.result b/mysql-test/r/group_min_max.result index c7be93b0fd7..766e43b2299 100644 --- a/mysql-test/r/group_min_max.result +++ b/mysql-test/r/group_min_max.result @@ -1657,6 +1657,44 @@ a b c d +select distinct a1,a1 from t1; +a1 a1 +a a +b b +c c +d d +select distinct a2,a1,a2,a1 from t1; +a2 a1 a2 a1 +a a a a +b a b a +a b a b +b b b b +a c a c +b c b c +a d a d +b d b d +select distinct t1.a1,t2.a1 from t1,t2; +a1 a1 +a a +b a +c a +d a +a b +b b +c b +d b +a c +b c +c c +d c +a d +b d +c d +d d +a e +b e +c e +d e explain select distinct a1,a2,b from t1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range NULL idx_t1_1 147 NULL 17 Using index for group-by diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index 1c2f4662ef1..1182c3d3569 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -466,4 +466,32 @@ ERROR 70100: Query execution was interrupted call bug6807()| ERROR 70100: Query execution was interrupted drop procedure bug6807| +drop procedure if exists bug8776_1| +drop procedure if exists bug8776_2| +drop procedure if exists bug8776_3| +drop procedure if exists bug8776_4| +create procedure bug8776_1() +begin +declare continue handler for sqlstate '42S0200test' begin end; +begin end; +end| +ERROR 42000: Bad SQLSTATE: '42S0200test' +create procedure bug8776_2() +begin +declare continue handler for sqlstate '4200' begin end; +begin end; +end| +ERROR 42000: Bad SQLSTATE: '4200' +create procedure bug8776_3() +begin +declare continue handler for sqlstate '420000' begin end; +begin end; +end| +ERROR 42000: Bad SQLSTATE: '420000' +create procedure bug8776_4() +begin +declare continue handler for sqlstate '42x00' begin end; +begin end; +end| +ERROR 42000: Bad SQLSTATE: '42x00' drop table t1| diff --git a/mysql-test/t/group_min_max.test b/mysql-test/t/group_min_max.test index b42125566d5..d85b3395853 100644 --- a/mysql-test/t/group_min_max.test +++ b/mysql-test/t/group_min_max.test @@ -475,11 +475,15 @@ select distinct a1,a2,b,c from t2 where (a2 >= 'b') and (b = 'a') and (c = 'i121 select distinct a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c'); select distinct b from t2 where (a2 >= 'b') and (b = 'a'); --- BUG 6303 +-- BUG #6303 select distinct t_00.a1 from t1 t_00 where exists ( select * from t2 where a1 = t_00.a1 ); +-- BUG #8532 - SELECT DISTINCT a, a causes server to crash +select distinct a1,a1 from t1; +select distinct a2,a1,a2,a1 from t1; +select distinct t1.a1,t2.a1 from t1,t2; -- -- DISTINCT queries with GROUP-BY diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index 594daf66fcb..0f775958d7a 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -641,6 +641,44 @@ call bug6807()| drop procedure bug6807| +# +# BUG#876: Stored Procedures: Invalid SQLSTATE is allowed in +# a DECLARE ? HANDLER FOR stmt. +# +--disable_warnings +drop procedure if exists bug8776_1| +drop procedure if exists bug8776_2| +drop procedure if exists bug8776_3| +drop procedure if exists bug8776_4| +--enable_warnings +--error ER_SP_BAD_SQLSTATE +create procedure bug8776_1() +begin + declare continue handler for sqlstate '42S0200test' begin end; + begin end; +end| + +--error ER_SP_BAD_SQLSTATE +create procedure bug8776_2() +begin + declare continue handler for sqlstate '4200' begin end; + begin end; +end| + +--error ER_SP_BAD_SQLSTATE +create procedure bug8776_3() +begin + declare continue handler for sqlstate '420000' begin end; + begin end; +end| + +--error ER_SP_BAD_SQLSTATE +create procedure bug8776_4() +begin + declare continue handler for sqlstate '42x00' begin end; + begin end; +end| + drop table t1| diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 12e5c60312b..812d5a41cbc 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -6878,6 +6878,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree) SEL_ARG *cur_index_tree= NULL; ha_rows cur_quick_prefix_records= 0; uint cur_param_idx; + key_map cur_used_key_parts; for (uint cur_index= 0 ; cur_index_info != cur_index_info_end ; cur_index_info++, cur_index++) @@ -6925,17 +6926,25 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree) else if (join->select_distinct) { select_items_it.rewind(); + cur_used_key_parts.clear_all(); while ((item= select_items_it++)) { item_field= (Item_field*) item; /* (SA5) already checked above. */ /* Find the order of the key part in the index. */ key_part_nr= get_field_keypart(cur_index_info, item_field->field); + /* + Check if this attribute was already present in the select list. + If it was present, then its corresponding key part was alredy used. + */ + if (cur_used_key_parts.is_set(key_part_nr)) + continue; if (key_part_nr < 1 || key_part_nr > join->fields_list.elements) goto next_index; cur_part= cur_index_info->key_part + key_part_nr - 1; cur_group_prefix_len+= cur_part->store_length; + cur_used_key_parts.set_bit(key_part_nr); + ++cur_group_key_parts; } - cur_group_key_parts= join->fields_list.elements; } else DBUG_ASSERT(FALSE); diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 5757510bfb4..ba4ef70486b 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5326,3 +5326,5 @@ ER_PROC_AUTO_REVOKE_FAIL eng "Failed to revoke all privileges to dropped routine" ER_DATA_TOO_LONG 22001 eng "Data too long for column '%s' at row %ld" +ER_SP_BAD_SQLSTATE 42000 + eng "Bad SQLSTATE: '%s'" diff --git a/sql/sp_pcontext.cc b/sql/sp_pcontext.cc index 7176498f276..15d3f87ff29 100644 --- a/sql/sp_pcontext.cc +++ b/sql/sp_pcontext.cc @@ -26,6 +26,30 @@ #include "sp_pcontext.h" #include "sp_head.h" +/* + * Sanity check for SQLSTATEs. Will not check if it's really an existing + * state (there are just too many), but will check length and bad characters. + * Returns TRUE if it's ok, FALSE if it's bad. + */ +bool +sp_cond_check(LEX_STRING *sqlstate) +{ + int i; + const char *p; + + if (sqlstate->length != 5) + return FALSE; + for (p= sqlstate->str, i= 0 ; i < 5 ; i++) + { + char c = p[i]; + + if ((c < '0' || '9' < c) && + (c < 'A' || 'Z' < c)) + return FALSE; + } + return TRUE; +} + sp_pcontext::sp_pcontext(sp_pcontext *prev) : Sql_alloc(), m_psubsize(0), m_csubsize(0), m_hsubsize(0), m_handlers(0), m_parent(prev) diff --git a/sql/sp_pcontext.h b/sql/sp_pcontext.h index 66f631f4938..42d8140b78c 100644 --- a/sql/sp_pcontext.h +++ b/sql/sp_pcontext.h @@ -60,6 +60,12 @@ typedef struct sp_cond_type uint mysqlerr; } sp_cond_type_t; +/* Sanity check for SQLSTATEs. Will not check if it's really an existing + * state (there are just too many), but will check length bad characters. + */ +extern bool +sp_cond_check(LEX_STRING *sqlstate); + typedef struct sp_cond { LEX_STRING name; diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 8c486566fa6..95417c9face 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -1274,6 +1274,7 @@ bool mysql_show_binlog_events(THD* thd) DBUG_ENTER("show_binlog_events"); List<Item> field_list; const char *errmsg = 0; + bool ret = TRUE; IO_CACHE log; File file = -1; Format_description_log_event *description_event= new @@ -1376,6 +1377,8 @@ bool mysql_show_binlog_events(THD* thd) pthread_mutex_unlock(log_lock); } + ret= FALSE; + err: delete description_event; if (file >= 0) @@ -1395,7 +1398,7 @@ err: pthread_mutex_lock(&LOCK_thread_count); thd->current_linfo = 0; pthread_mutex_unlock(&LOCK_thread_count); - DBUG_RETURN(TRUE); + DBUG_RETURN(ret); } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 45c3e94f0ff..a69b6a96982 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1760,13 +1760,15 @@ sp_cond: } | SQLSTATE_SYM opt_value TEXT_STRING_literal { /* SQLSTATE */ - uint len= ($3.length < sizeof($$->sqlstate)-1 ? - $3.length : sizeof($$->sqlstate)-1); - + if (!sp_cond_check(&$3)) + { + my_error(ER_SP_BAD_SQLSTATE, MYF(0), $3.str); + YYABORT; + } $$= (sp_cond_type_t *)YYTHD->alloc(sizeof(sp_cond_type_t)); $$->type= sp_cond_type_t::state; - memcpy($$->sqlstate, $3.str, len); - $$->sqlstate[len]= '\0'; + memcpy($$->sqlstate, $3.str, 5); + $$->sqlstate[5]= '\0'; } ; |