summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/group_min_max.result38
-rw-r--r--mysql-test/r/sp-error.result28
-rw-r--r--mysql-test/t/group_min_max.test6
-rw-r--r--mysql-test/t/sp-error.test38
-rw-r--r--sql/opt_range.cc11
-rw-r--r--sql/share/errmsg.txt2
-rw-r--r--sql/sp_pcontext.cc24
-rw-r--r--sql/sp_pcontext.h6
-rw-r--r--sql/sql_repl.cc5
-rw-r--r--sql/sql_yacc.yy12
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';
}
;