summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/suite/compat/oracle/r/exception.result53
-rw-r--r--mysql-test/suite/compat/oracle/t/exception.test54
-rw-r--r--sql/sp_pcontext.cc30
-rw-r--r--sql/sp_pcontext.h25
-rw-r--r--sql/sql_yacc_ora.yy2
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));
}