Skip to content

Commit

Permalink
MDEV-10839 sql_mode=ORACLE: Predefined exceptions: TOO_MANY_ROWS, NO_…
Browse files Browse the repository at this point in the history
…DATA_FOUND, DUP_VAL_ON_INDEX
  • Loading branch information
Alexander Barkov committed Apr 5, 2017
1 parent c2c45c5 commit ccb91eb
Show file tree
Hide file tree
Showing 5 changed files with 160 additions and 4 deletions.
53 changes: 53 additions & 0 deletions 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;
54 changes: 54 additions & 0 deletions 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;
30 changes: 27 additions & 3 deletions sql/sp_pcontext.cc
Expand Up @@ -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;
}
Expand All @@ -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)
{
Expand Down
25 changes: 25 additions & 0 deletions sql/sp_pcontext.h
Expand Up @@ -198,6 +198,19 @@ class sp_condition : public Sql_alloc
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;
}
};

///////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -454,6 +467,16 @@ class sp_pcontext : public Sql_alloc
/// 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)
{
Expand Down Expand Up @@ -540,6 +563,8 @@ class sp_pcontext : public Sql_alloc
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.
Expand Down
2 changes: 1 addition & 1 deletion sql/sql_yacc_ora.yy
Expand Up @@ -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));
}
Expand Down

0 comments on commit ccb91eb

Please sign in to comment.