diff options
-rw-r--r-- | mysql-test/suite/compat/oracle/r/exception.result | 53 | ||||
-rw-r--r-- | mysql-test/suite/compat/oracle/t/exception.test | 54 | ||||
-rw-r--r-- | sql/sp_pcontext.cc | 30 | ||||
-rw-r--r-- | sql/sp_pcontext.h | 25 | ||||
-rw-r--r-- | sql/sql_yacc_ora.yy | 2 |
5 files changed, 160 insertions, 4 deletions
diff --git a/mysql-test/suite/compat/oracle/r/exception.result b/mysql-test/suite/compat/oracle/r/exception.result new file mode 100644 index 00000000000..f73efb0c08e --- /dev/null +++ b/mysql-test/suite/compat/oracle/r/exception.result @@ -0,0 +1,53 @@ +SET sql_mode=ORACLE; +# +# sql_mode=ORACLE: Predefined exceptions: TOO_MANY_ROWS, NO_DATA_FOUND, DUP_VAL_ON_INDEX +# +# +# Testing NO_DATA_FOUND and TOO_MANY_ROWS +# +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (10),(20); +CREATE PROCEDURE p1(lim INT, res OUT VARCHAR) +AS +a INT; +BEGIN +SELECT a INTO a FROM t1 LIMIT lim; +EXCEPTION +WHEN TOO_MANY_ROWS THEN res:='--- too_many_rows cought ---'; +WHEN NO_DATA_FOUND THEN res:='--- no_data_found cought ---'; +END; +$$ +SET @res=''; +CALL p1(0, @res); +SELECT @res; +@res +--- no_data_found cought --- +CALL p1(2, @res); +SELECT @res; +@res +--- too_many_rows cought --- +DROP PROCEDURE p1; +DROP TABLE t1; +# +# Testing DUP_VAL_ON_INDEX +# +CREATE TABLE t1 (a INT PRIMARY KEY); +CREATE PROCEDURE p1(res OUT VARCHAR) +AS +BEGIN +INSERT INTO t1 VALUES (10); +INSERT INTO t1 VALUES (10); +EXCEPTION +WHEN DUP_VAL_ON_INDEX THEN res:='--- dup_val_on_index cought ---'; +END; +$$ +SET @res=''; +CALL p1(@res); +SELECT @res; +@res +--- dup_val_on_index cought --- +SELECT * FROM t1; +a +10 +DROP PROCEDURE p1; +DROP TABLE t1; diff --git a/mysql-test/suite/compat/oracle/t/exception.test b/mysql-test/suite/compat/oracle/t/exception.test new file mode 100644 index 00000000000..f61b495ed86 --- /dev/null +++ b/mysql-test/suite/compat/oracle/t/exception.test @@ -0,0 +1,54 @@ +SET sql_mode=ORACLE; + +--echo # +--echo # sql_mode=ORACLE: Predefined exceptions: TOO_MANY_ROWS, NO_DATA_FOUND, DUP_VAL_ON_INDEX +--echo # + +--echo # +--echo # Testing NO_DATA_FOUND and TOO_MANY_ROWS +--echo # + +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (10),(20); +DELIMITER $$; +CREATE PROCEDURE p1(lim INT, res OUT VARCHAR) +AS + a INT; +BEGIN + SELECT a INTO a FROM t1 LIMIT lim; +EXCEPTION + WHEN TOO_MANY_ROWS THEN res:='--- too_many_rows cought ---'; + WHEN NO_DATA_FOUND THEN res:='--- no_data_found cought ---'; +END; +$$ +DELIMITER ;$$ +SET @res=''; +CALL p1(0, @res); +SELECT @res; +CALL p1(2, @res); +SELECT @res; +DROP PROCEDURE p1; +DROP TABLE t1; + +--echo # +--echo # Testing DUP_VAL_ON_INDEX +--echo # + +CREATE TABLE t1 (a INT PRIMARY KEY); +DELIMITER $$; +CREATE PROCEDURE p1(res OUT VARCHAR) +AS +BEGIN + INSERT INTO t1 VALUES (10); + INSERT INTO t1 VALUES (10); +EXCEPTION + WHEN DUP_VAL_ON_INDEX THEN res:='--- dup_val_on_index cought ---'; +END; +$$ +DELIMITER ;$$ +SET @res=''; +CALL p1(@res); +SELECT @res; +SELECT * FROM t1; +DROP PROCEDURE p1; +DROP TABLE t1; diff --git a/sql/sp_pcontext.cc b/sql/sp_pcontext.cc index db2d36978d4..6b796cb95e9 100644 --- a/sql/sp_pcontext.cc +++ b/sql/sp_pcontext.cc @@ -276,9 +276,7 @@ sp_condition_value *sp_pcontext::find_condition(const LEX_STRING name, { sp_condition *p= m_conditions.at(i); - if (my_strnncoll(system_charset_info, - (const uchar *) name.str, name.length, - (const uchar *) p->name.str, p->name.length) == 0) + if (p->eq_name(name)) { return p->value; } @@ -290,6 +288,32 @@ sp_condition_value *sp_pcontext::find_condition(const LEX_STRING name, } +static sp_condition_value + cond_no_data_found(ER_SP_FETCH_NO_DATA), + cond_dup_val_on_index(ER_DUP_ENTRY), + cond_too_many_rows(ER_TOO_MANY_ROWS); + + +static sp_condition sp_predefined_conditions[3]= +{ + sp_condition(C_STRING_WITH_LEN("NO_DATA_FOUND"), &cond_no_data_found), + sp_condition(C_STRING_WITH_LEN("DUP_VAL_ON_INDEX"), &cond_dup_val_on_index), + sp_condition(C_STRING_WITH_LEN("TOO_MANY_ROWS"), &cond_too_many_rows) +}; + + +sp_condition_value * +sp_pcontext::find_predefined_condition(const LEX_STRING name) const +{ + for (uint i= 0; i < array_elements(sp_predefined_conditions) ; i++) + { + if (sp_predefined_conditions[i].eq_name(name)) + return sp_predefined_conditions[i].value; + } + return NULL; +} + + sp_handler *sp_pcontext::add_handler(THD *thd, sp_handler::enum_type type) { diff --git a/sql/sp_pcontext.h b/sql/sp_pcontext.h index 877e43e96c0..808143d832c 100644 --- a/sql/sp_pcontext.h +++ b/sql/sp_pcontext.h @@ -198,6 +198,19 @@ public: name(_name), value(_value) { } + sp_condition(const char *name_arg, size_t name_length_arg, + sp_condition_value *value_arg) + :value(value_arg) + { + name.str= (char *) name_arg; + name.length= name_length_arg; + } + bool eq_name(const LEX_STRING str) const + { + return my_strnncoll(system_charset_info, + (const uchar *) name.str, name.length, + (const uchar *) str.str, str.length) == 0; + } }; /////////////////////////////////////////////////////////////////////////// @@ -454,6 +467,16 @@ public: /// See comment for find_variable() above. sp_condition_value *find_condition(const LEX_STRING name, bool current_scope_only) const; + + sp_condition_value * + find_declared_or_predefined_condition(const LEX_STRING name) const + { + sp_condition_value *p= find_condition(name, false); + if (p) + return p; + return find_predefined_condition(name); + } + bool declare_condition(THD *thd, const LEX_STRING name, sp_condition_value *val) { @@ -540,6 +563,8 @@ private: sp_pcontext(const sp_pcontext &); void operator=(sp_pcontext &); + sp_condition_value *find_predefined_condition(const LEX_STRING name) const; + private: /// m_max_var_index -- number of variables (including all types of arguments) /// in this context including all children contexts. diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy index 72e5a16cc7d..71c160f4eda 100644 --- a/sql/sql_yacc_ora.yy +++ b/sql/sql_yacc_ora.yy @@ -2515,7 +2515,7 @@ sp_hcond: } | ident /* CONDITION name */ { - $$= Lex->spcont->find_condition($1, false); + $$= Lex->spcont->find_declared_or_predefined_condition($1); if ($$ == NULL) my_yyabort_error((ER_SP_COND_MISMATCH, MYF(0), $1.str)); } |