Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
MariaDB
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
4ed804aa
Commit
4ed804aa
authored
Oct 14, 2016
by
Alexander Barkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
MDEV-10587 sql_mode=ORACLE: User defined exceptions
parent
4d3818d3
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
655 additions
and
113 deletions
+655
-113
mysql-test/suite/compat/oracle/r/exception.result
mysql-test/suite/compat/oracle/r/exception.result
+161
-0
mysql-test/suite/compat/oracle/t/exception.test
mysql-test/suite/compat/oracle/t/exception.test
+167
-0
sql/sp_pcontext.cc
sql/sp_pcontext.cc
+86
-58
sql/sp_pcontext.h
sql/sp_pcontext.h
+38
-3
sql/sp_rcontext.cc
sql/sp_rcontext.cc
+4
-4
sql/sp_rcontext.h
sql/sp_rcontext.h
+3
-2
sql/sql_class.cc
sql/sql_class.cc
+6
-5
sql/sql_class.h
sql/sql_class.h
+34
-0
sql/sql_error.cc
sql/sql_error.cc
+9
-4
sql/sql_error.h
sql/sql_error.h
+133
-28
sql/sql_signal.cc
sql/sql_signal.cc
+4
-9
sql/sql_yacc_ora.yy
sql/sql_yacc_ora.yy
+10
-0
No files found.
mysql-test/suite/compat/oracle/r/exception.result
View file @
4ed804aa
...
...
@@ -220,3 +220,164 @@ DROP TABLE t1;
#
# End of MDEV-10840 sql_mode=ORACLE: RAISE statement for predefined exceptions
#
#
# MDEV-10587 sql_mode=ORACLE: User defined exceptions
#
#
# Checking that duplicate WHEN clause is not allowed
#
CREATE FUNCTION f1() RETURN VARCHAR
AS
e EXCEPTION;
BEGIN
RETURN 'Got no exceptions';
EXCEPTION
WHEN e THEN RETURN 'Got exception e';
WHEN e THEN RETURN 'Got exception e';
END;
$$
ERROR 42000: Duplicate handler declared in the same block
#
# Checking that raised user exceptions are further caught by name
#
CREATE FUNCTION f1(c VARCHAR) RETURN VARCHAR
AS
e EXCEPTION;
f EXCEPTION;
BEGIN
IF c = 'e' THEN RAISE e; END IF;
IF c = 'f' THEN RAISE f; END IF;
RETURN 'Got no exceptions';
EXCEPTION
WHEN e THEN RETURN 'Got exception e';
END;
$$
SELECT f1('');
f1('')
Got no exceptions
SELECT f1('e');
f1('e')
Got exception e
SELECT f1('f');
ERROR 45000: Unhandled user-defined exception condition
DROP FUNCTION f1;
#
# Checking that raised user exceptions are further caught by OTHERS
#
CREATE FUNCTION f1(c VARCHAR) RETURN VARCHAR
AS
e EXCEPTION;
f EXCEPTION;
BEGIN
IF c = 'e' THEN RAISE e; END IF;
IF c = 'f' THEN RAISE f; END IF;
RETURN 'Got no exceptions';
EXCEPTION
WHEN OTHERS THEN RETURN 'Got some exception';
END;
$$
SELECT f1('');
f1('')
Got no exceptions
SELECT f1('e');
f1('e')
Got some exception
SELECT f1('f');
f1('f')
Got some exception
DROP FUNCTION f1;
#
# Checking that 'WHEN e .. WHEN f' does not produce ER_SP_DUP_HANDLER
#
CREATE FUNCTION f1(c VARCHAR) RETURN VARCHAR
AS
e EXCEPTION;
f EXCEPTION;
a VARCHAR(64):='';
BEGIN
BEGIN
IF c = 'e' THEN RAISE e; END IF;
IF c = 'f' THEN RAISE f; END IF;
EXCEPTION
WHEN e THEN BEGIN a:='Got EXCEPTION1/e; '; RAISE e; END;
WHEN f THEN BEGIN a:='Got EXCEPTION1/f; '; RAISE f; END;
END;
RETURN 'Got no exceptions';
EXCEPTION
WHEN OTHERS THEN RETURN a || 'Got EXCEPTION2/OTHERS;';
END;
$$
SELECT f1('');
f1('')
Got no exceptions
SELECT f1('e');
f1('e')
Got EXCEPTION1/e; Got EXCEPTION2/OTHERS;
SELECT f1('f');
f1('f')
Got EXCEPTION1/f; Got EXCEPTION2/OTHERS;
DROP FUNCTION f1;
#
# Checking that resignaled user exceptions are further caught by name
#
CREATE FUNCTION f1(c VARCHAR) RETURN VARCHAR
AS
e EXCEPTION;
f EXCEPTION;
a VARCHAR(64):='';
BEGIN
BEGIN
IF c = 'e' THEN RAISE e; END IF;
IF c = 'f' THEN RAISE f; END IF;
EXCEPTION
WHEN e THEN BEGIN a:='Got EXCEPTION1/e; '; RAISE; END;
WHEN f THEN BEGIN a:='Got EXCEPTION1/f; '; RAISE; END;
END;
RETURN 'Got no exceptions';
EXCEPTION
WHEN e THEN RETURN a || 'Got EXCEPTION2/e;';
END;
$$
SELECT f1('');
f1('')
Got no exceptions
SELECT f1('e');
f1('e')
Got EXCEPTION1/e; Got EXCEPTION2/e;
SELECT f1('f');
ERROR 45000: Unhandled user-defined exception condition
DROP FUNCTION f1;
#
# Checking that resignaled user exceptions are further caught by OTHERS
#
CREATE FUNCTION f1(c VARCHAR) RETURN VARCHAR
AS
e EXCEPTION;
f EXCEPTION;
a VARCHAR(64):='';
BEGIN
BEGIN
IF c = 'e' THEN RAISE e; END IF;
IF c = 'f' THEN RAISE f; END IF;
EXCEPTION
WHEN e THEN BEGIN a:='Got EXCEPTION1/e; '; RAISE; END;
WHEN f THEN BEGIN a:='Got EXCEPTION1/f; '; RAISE; END;
END;
RETURN 'Got no exceptions';
EXCEPTION
WHEN OTHERS THEN RETURN a || 'Got EXCEPTION2/OTHERS;';
END;
$$
SELECT f1('');
f1('')
Got no exceptions
SELECT f1('e');
f1('e')
Got EXCEPTION1/e; Got EXCEPTION2/OTHERS;
SELECT f1('f');
f1('f')
Got EXCEPTION1/f; Got EXCEPTION2/OTHERS;
DROP FUNCTION f1;
#
# End of MDEV-10587 sql_mode=ORACLE: User defined exceptions
#
mysql-test/suite/compat/oracle/t/exception.test
View file @
4ed804aa
...
...
@@ -264,3 +264,170 @@ DROP TABLE t1;
--
echo
#
--
echo
# End of MDEV-10840 sql_mode=ORACLE: RAISE statement for predefined exceptions
--
echo
#
--
echo
#
--
echo
# MDEV-10587 sql_mode=ORACLE: User defined exceptions
--
echo
#
--
echo
#
--
echo
# Checking that duplicate WHEN clause is not allowed
--
echo
#
DELIMITER
$$
;
--
error
ER_SP_DUP_HANDLER
CREATE
FUNCTION
f1
()
RETURN
VARCHAR
AS
e
EXCEPTION
;
BEGIN
RETURN
'Got no exceptions'
;
EXCEPTION
WHEN
e
THEN
RETURN
'Got exception e'
;
WHEN
e
THEN
RETURN
'Got exception e'
;
END
;
$$
DELIMITER
;
$$
--
echo
#
--
echo
# Checking that raised user exceptions are further caught by name
--
echo
#
DELIMITER
$$
;
CREATE
FUNCTION
f1
(
c
VARCHAR
)
RETURN
VARCHAR
AS
e
EXCEPTION
;
f
EXCEPTION
;
BEGIN
IF
c
=
'e'
THEN
RAISE
e
;
END
IF
;
IF
c
=
'f'
THEN
RAISE
f
;
END
IF
;
RETURN
'Got no exceptions'
;
EXCEPTION
WHEN
e
THEN
RETURN
'Got exception e'
;
END
;
$$
DELIMITER
;
$$
SELECT
f1
(
''
);
SELECT
f1
(
'e'
);
--
error
ER_SIGNAL_EXCEPTION
SELECT
f1
(
'f'
);
DROP
FUNCTION
f1
;
--
echo
#
--
echo
# Checking that raised user exceptions are further caught by OTHERS
--
echo
#
DELIMITER
$$
;
CREATE
FUNCTION
f1
(
c
VARCHAR
)
RETURN
VARCHAR
AS
e
EXCEPTION
;
f
EXCEPTION
;
BEGIN
IF
c
=
'e'
THEN
RAISE
e
;
END
IF
;
IF
c
=
'f'
THEN
RAISE
f
;
END
IF
;
RETURN
'Got no exceptions'
;
EXCEPTION
WHEN
OTHERS
THEN
RETURN
'Got some exception'
;
END
;
$$
DELIMITER
;
$$
SELECT
f1
(
''
);
SELECT
f1
(
'e'
);
SELECT
f1
(
'f'
);
DROP
FUNCTION
f1
;
--
echo
#
--
echo
# Checking that 'WHEN e .. WHEN f' does not produce ER_SP_DUP_HANDLER
--
echo
#
DELIMITER
$$
;
CREATE
FUNCTION
f1
(
c
VARCHAR
)
RETURN
VARCHAR
AS
e
EXCEPTION
;
f
EXCEPTION
;
a
VARCHAR
(
64
)
:=
''
;
BEGIN
BEGIN
IF
c
=
'e'
THEN
RAISE
e
;
END
IF
;
IF
c
=
'f'
THEN
RAISE
f
;
END
IF
;
EXCEPTION
WHEN
e
THEN
BEGIN
a
:=
'Got EXCEPTION1/e; '
;
RAISE
e
;
END
;
WHEN
f
THEN
BEGIN
a
:=
'Got EXCEPTION1/f; '
;
RAISE
f
;
END
;
END
;
RETURN
'Got no exceptions'
;
EXCEPTION
WHEN
OTHERS
THEN
RETURN
a
||
'Got EXCEPTION2/OTHERS;'
;
END
;
$$
DELIMITER
;
$$
SELECT
f1
(
''
);
SELECT
f1
(
'e'
);
SELECT
f1
(
'f'
);
DROP
FUNCTION
f1
;
--
echo
#
--
echo
# Checking that resignaled user exceptions are further caught by name
--
echo
#
DELIMITER
$$
;
CREATE
FUNCTION
f1
(
c
VARCHAR
)
RETURN
VARCHAR
AS
e
EXCEPTION
;
f
EXCEPTION
;
a
VARCHAR
(
64
)
:=
''
;
BEGIN
BEGIN
IF
c
=
'e'
THEN
RAISE
e
;
END
IF
;
IF
c
=
'f'
THEN
RAISE
f
;
END
IF
;
EXCEPTION
WHEN
e
THEN
BEGIN
a
:=
'Got EXCEPTION1/e; '
;
RAISE
;
END
;
WHEN
f
THEN
BEGIN
a
:=
'Got EXCEPTION1/f; '
;
RAISE
;
END
;
END
;
RETURN
'Got no exceptions'
;
EXCEPTION
WHEN
e
THEN
RETURN
a
||
'Got EXCEPTION2/e;'
;
END
;
$$
DELIMITER
;
$$
SELECT
f1
(
''
);
SELECT
f1
(
'e'
);
--
error
ER_SIGNAL_EXCEPTION
SELECT
f1
(
'f'
);
DROP
FUNCTION
f1
;
--
echo
#
--
echo
# Checking that resignaled user exceptions are further caught by OTHERS
--
echo
#
DELIMITER
$$
;
CREATE
FUNCTION
f1
(
c
VARCHAR
)
RETURN
VARCHAR
AS
e
EXCEPTION
;
f
EXCEPTION
;
a
VARCHAR
(
64
)
:=
''
;
BEGIN
BEGIN
IF
c
=
'e'
THEN
RAISE
e
;
END
IF
;
IF
c
=
'f'
THEN
RAISE
f
;
END
IF
;
EXCEPTION
WHEN
e
THEN
BEGIN
a
:=
'Got EXCEPTION1/e; '
;
RAISE
;
END
;
WHEN
f
THEN
BEGIN
a
:=
'Got EXCEPTION1/f; '
;
RAISE
;
END
;
END
;
RETURN
'Got no exceptions'
;
EXCEPTION
WHEN
OTHERS
THEN
RETURN
a
||
'Got EXCEPTION2/OTHERS;'
;
END
;
$$
DELIMITER
;
$$
SELECT
f1
(
''
);
SELECT
f1
(
'e'
);
SELECT
f1
(
'f'
);
DROP
FUNCTION
f1
;
--
echo
#
--
echo
# End of MDEV-10587 sql_mode=ORACLE: User defined exceptions
--
echo
#
sql/sp_pcontext.cc
View file @
4ed804aa
...
...
@@ -27,10 +27,41 @@ bool sp_condition_value::equals(const sp_condition_value *cv) const
{
DBUG_ASSERT
(
cv
);
/*
The following test disallows duplicate handlers,
including user defined exceptions with the same WHEN clause:
DECLARE
a EXCEPTION;
b EXCEPTION;
BEGIN
RAUSE a;
EXCEPTION
WHEN a THEN RETURN 'a0';
WHEN a THEN RETURN 'a1';
END
*/
if
(
this
==
cv
)
return
true
;
if
(
type
!=
cv
->
type
)
/*
The test below considers two conditions of the same type as equal
(except for the user defined exceptions) to avoid declaring duplicate
handlers.
All user defined conditions have type==SQLSTATE
with the same SQL state and error code.
It's OK to have multiple user defined conditions:
DECLARE
a EXCEPTION;
b EXCEPTION;
BEGIN
RAISE a;
EXCEPTION
WHEN a THEN RETURN 'a';
WHEN b THEN RETURN 'b';
END;
*/
if
(
type
!=
cv
->
type
||
m_is_user_defined
||
cv
->
m_is_user_defined
)
return
false
;
switch
(
type
)
...
...
@@ -353,9 +384,57 @@ bool sp_pcontext::check_duplicate_handler(
}
bool
sp_condition_value
::
matches
(
const
Sql_condition_identity
&
value
,
const
sp_condition_value
*
found_cv
)
const
{
bool
user_value_matched
=
!
value
.
get_user_condition_value
()
||
this
==
value
.
get_user_condition_value
();
switch
(
type
)
{
case
sp_condition_value
:
:
ERROR_CODE
:
return
user_value_matched
&&
value
.
get_sql_errno
()
==
get_sql_errno
()
&&
(
!
found_cv
||
found_cv
->
type
>
sp_condition_value
::
ERROR_CODE
);
case
sp_condition_value
:
:
SQLSTATE
:
return
user_value_matched
&&
Sql_state
::
eq
(
&
value
)
&&
(
!
found_cv
||
found_cv
->
type
>
sp_condition_value
::
SQLSTATE
);
case
sp_condition_value
:
:
WARNING
:
return
user_value_matched
&&
(
value
.
Sql_state
::
is_warning
()
||
value
.
get_level
()
==
Sql_condition
::
WARN_LEVEL_WARN
)
&&
!
found_cv
;
case
sp_condition_value
:
:
NOT_FOUND
:
return
user_value_matched
&&
value
.
Sql_state
::
is_not_found
()
&&
!
found_cv
;
case
sp_condition_value
:
:
EXCEPTION
:
/*
In sql_mode=ORACLE this construct should catch both errors and warnings:
EXCEPTION
WHEN OTHERS THEN ...;
E.g. NO_DATA_FOUND is more like a warning than an error,
and it should be caught.
We don't check user_value_matched here.
"WHEN OTHERS" catches all user defined exception.
*/
return
(((
current_thd
->
variables
.
sql_mode
&
MODE_ORACLE
)
||
(
value
.
Sql_state
::
is_exception
()
&&
value
.
get_level
()
==
Sql_condition
::
WARN_LEVEL_ERROR
))
&&
!
found_cv
);
}
return
false
;
}
sp_handler
*
sp_pcontext
::
find_handler
(
const
Sql_state_errno
*
value
,
Sql_condition
::
enum_warning_level
level
)
const
sp_pcontext
::
find_handler
(
const
Sql_condition_identity
&
value
)
const
{
sp_handler
*
found_handler
=
NULL
;
sp_condition_value
*
found_cv
=
NULL
;
...
...
@@ -369,61 +448,10 @@ sp_pcontext::find_handler(const Sql_state_errno *value,
while
((
cv
=
li
++
))
{
switch
(
cv
->
type
)
if
(
cv
->
matches
(
value
,
found_cv
)
)
{
case
sp_condition_value
:
:
ERROR_CODE
:
if
(
value
->
get_sql_errno
()
==
cv
->
get_sql_errno
()
&&
(
!
found_cv
||
found_cv
->
type
>
sp_condition_value
::
ERROR_CODE
))
{
found_cv
=
cv
;
found_handler
=
h
;
}
break
;
case
sp_condition_value
:
:
SQLSTATE
:
if
(
cv
->
Sql_state
::
eq
(
value
)
&&
(
!
found_cv
||
found_cv
->
type
>
sp_condition_value
::
SQLSTATE
))
{
found_cv
=
cv
;
found_handler
=
h
;
}
break
;
case
sp_condition_value
:
:
WARNING
:
if
((
value
->
Sql_state
::
is_warning
()
||
level
==
Sql_condition
::
WARN_LEVEL_WARN
)
&&
!
found_cv
)
{
found_cv
=
cv
;
found_handler
=
h
;
}
break
;
case
sp_condition_value
:
:
NOT_FOUND
:
if
(
value
->
Sql_state
::
is_not_found
()
&&
!
found_cv
)
{
found_cv
=
cv
;
found_handler
=
h
;
}
break
;
case
sp_condition_value
:
:
EXCEPTION
:
/*
In sql_mode=ORACLE this construct should catch errors and warnings:
EXCEPTION
WHEN OTHERS THEN ...;
E.g. NO_DATA_FOUND is more like a warning than an error,
and it should be caught.
*/
if
(((
current_thd
->
variables
.
sql_mode
&
MODE_ORACLE
)
||
(
value
->
Sql_state
::
is_exception
()
&&
level
==
Sql_condition
::
WARN_LEVEL_ERROR
))
&&
!
found_cv
)
{
found_cv
=
cv
;
found_handler
=
h
;
}
break
;
found_cv
=
cv
;
found_handler
=
h
;
}
}
}
...
...
@@ -466,7 +494,7 @@ sp_pcontext::find_handler(const Sql_state_errno *value,
if
(
!
p
||
!
p
->
m_parent
)
return
NULL
;
return
p
->
m_parent
->
find_handler
(
value
,
level
);
return
p
->
m_parent
->
find_handler
(
value
);
}
...
...
sql/sp_pcontext.h
View file @
4ed804aa
...
...
@@ -129,6 +129,7 @@ class sp_label : public Sql_alloc
class
sp_condition_value
:
public
Sql_alloc
,
public
Sql_state_errno
{
bool
m_is_user_defined
;
public:
enum
enum_type
{
...
...
@@ -146,23 +147,27 @@ class sp_condition_value : public Sql_alloc, public Sql_state_errno
sp_condition_value
(
uint
_mysqlerr
)
:
Sql_alloc
(),
Sql_state_errno
(
_mysqlerr
),
m_is_user_defined
(
false
),
type
(
ERROR_CODE
)
{
}
sp_condition_value
(
uint
_mysqlerr
,
const
char
*
_sql_state
)
:
Sql_alloc
(),
Sql_state_errno
(
_mysqlerr
,
_sql_state
),
m_is_user_defined
(
false
),
type
(
ERROR_CODE
)
{
}
sp_condition_value
(
const
char
*
_sql_state
)
sp_condition_value
(
const
char
*
_sql_state
,
bool
is_user_defined
=
false
)
:
Sql_alloc
(),
Sql_state_errno
(
0
,
_sql_state
),
m_is_user_defined
(
is_user_defined
),
type
(
SQLSTATE
)
{
}
sp_condition_value
(
enum_type
_type
)
:
Sql_alloc
(),
m_is_user_defined
(
false
),
type
(
_type
)
{
DBUG_ASSERT
(
type
!=
ERROR_CODE
&&
type
!=
SQLSTATE
);
...
...
@@ -174,8 +179,39 @@ class sp_condition_value : public Sql_alloc, public Sql_state_errno
///
/// @return true if the instances are equal, false otherwise.
bool
equals
(
const
sp_condition_value
*
cv
)
const
;
/**
Checks if this condition is OK for search.
See also sp_context::find_handler().
@param identity - The condition identity
@param found_cv - A previously found matching condition or NULL.
@return true - If the current value matches identity and
makes a stronger match than the previously
found condition found_cv.
@return false - If the current value does not match identity,
of the current value makes a weaker match than found_cv.
*/
bool
matches
(
const
Sql_condition_identity
&
identity
,
const
sp_condition_value
*
found_cv
)
const
;
Sql_user_condition_identity
get_user_condition_identity
()
const
{
return
Sql_user_condition_identity
(
m_is_user_defined
?
this
:
NULL
);
}
};
class
sp_condition_value_user_defined
:
public
sp_condition_value
{
public:
sp_condition_value_user_defined
()
:
sp_condition_value
(
"45000"
,
true
)
{
}
};
///////////////////////////////////////////////////////////////////////////
/// This class represents 'DECLARE CONDITION' statement.
...
...
@@ -516,8 +552,7 @@ class sp_pcontext : public Sql_alloc
/// @param level The SQL condition level
///
/// @return a pointer to the found SQL-handler or NULL.
sp_handler
*
find_handler
(
const
Sql_state_errno
*
value
,
Sql_condition
::
enum_warning_level
level
)
const
;
sp_handler
*
find_handler
(
const
Sql_condition_identity
&
identity
)
const
;
/////////////////////////////////////////////////////////////////////////
// Cursors.
...
...
sql/sp_rcontext.cc
View file @
4ed804aa
...
...
@@ -228,7 +228,7 @@ bool sp_rcontext::handle_sql_condition(THD *thd,
if
(
thd
->
is_error
())
{
found_handler
=
cur_spi
->
m_ctx
->
find_handler
(
da
,
Sql_condition
::
WARN_LEVEL_ERROR
);
cur_spi
->
m_ctx
->
find_handler
(
da
->
get_error_condition_identity
()
);
if
(
found_handler
)
found_condition
=
da
->
get_error_condition
();
...
...
@@ -244,7 +244,8 @@ bool sp_rcontext::handle_sql_condition(THD *thd,
{
found_condition
=
new
(
callers_arena
->
mem_root
)
Sql_condition
(
callers_arena
->
mem_root
,
da
,
da
->
message
());
da
->
get_error_condition_identity
(),
da
->
message
());
}
}
else
if
(
da
->
current_statement_warn_count
())
...
...
@@ -261,8 +262,7 @@ bool sp_rcontext::handle_sql_condition(THD *thd,
if
(
c
->
get_level
()
==
Sql_condition
::
WARN_LEVEL_WARN
||
c
->
get_level
()
==
Sql_condition
::
WARN_LEVEL_NOTE
)
{
const
sp_handler
*
handler
=
cur_spi
->
m_ctx
->
find_handler
(
c
,
c
->
get_level
());
const
sp_handler
*
handler
=
cur_spi
->
m_ctx
->
find_handler
(
*
c
);
if
(
handler
)
{
found_handler
=
handler
;
...
...
sql/sp_rcontext.h
View file @
4ed804aa
...
...
@@ -120,7 +120,8 @@ class sp_rcontext : public Sql_alloc
/// standard SQL-condition processing (Diagnostics_area should contain an
/// object for active SQL-condition, not just information stored in DA's
/// fields).
class
Sql_condition_info
:
public
Sql_alloc
,
public
Sql_state_errno_level
class
Sql_condition_info
:
public
Sql_alloc
,
public
Sql_condition_identity
{
public:
/// Text message.
...
...
@@ -132,7 +133,7 @@ class sp_rcontext : public Sql_alloc
/// @param arena Query arena for SP
Sql_condition_info
(
const
Sql_condition
*
_sql_condition
,
Query_arena
*
arena
)
:
Sql_
state_errno_level
(
*
_sql_condition
)
:
Sql_
condition_identity
(
*
_sql_condition
)
{
message
=
strdup_root
(
arena
->
mem_root
,
_sql_condition
->
get_message_text
());
}
...
...
sql/sql_class.cc
View file @
4ed804aa
...
...
@@ -1066,9 +1066,10 @@ void THD::raise_note_printf(uint sql_errno, ...)
}
Sql_condition
*
THD
::
raise_condition
(
uint
sql_errno
,
const
char
*
sqlstate
,
Sql_condition
::
enum_warning_level
level
,
const
char
*
msg
)
const
char
*
sqlstate
,
Sql_condition
::
enum_warning_level
level
,
const
Sql_user_condition_identity
&
ucid
,
const
char
*
msg
)
{
Diagnostics_area
*
da
=
get_stmt_da
();
Sql_condition
*
cond
=
NULL
;
...
...
@@ -1127,7 +1128,7 @@ Sql_condition* THD::raise_condition(uint sql_errno,
if
(
!
da
->
is_error
())
{
set_row_count_func
(
-
1
);
da
->
set_error_status
(
sql_errno
,
msg
,
sqlstate
,
cond
);
da
->
set_error_status
(
sql_errno
,
msg
,
sqlstate
,
ucid
,
cond
);
}
}
...
...
@@ -1141,7 +1142,7 @@ Sql_condition* THD::raise_condition(uint sql_errno,
if
(
!
(
is_fatal_error
&&
(
sql_errno
==
EE_OUTOFMEMORY
||
sql_errno
==
ER_OUTOFMEMORY
)))
{
cond
=
da
->
push_warning
(
this
,
sql_errno
,
sqlstate
,
level
,
msg
);
cond
=
da
->
push_warning
(
this
,
sql_errno
,
sqlstate
,
level
,
ucid
,
msg
);
}
DBUG_RETURN
(
cond
);
}
...
...
sql/sql_class.h
View file @
4ed804aa
...
...
@@ -3939,8 +3939,42 @@ class THD :public Statement,
raise_condition
(
uint
sql_errno
,
const
char
*
sqlstate
,
Sql_condition
::
enum_warning_level
level
,
const
char
*
msg
)
{
return
raise_condition
(
sql_errno
,
sqlstate
,
level
,
Sql_user_condition_identity
(),
msg
);
}
/**
Raise a generic or a user defined SQL condition.
@param ucid - the user condition identity
(or an empty identity if not a user condition)
@param sql_errno - the condition error number
@param sqlstate - the condition SQLSTATE
@param level - the condition level
@param msg - the condition message text
@return The condition raised, or NULL
*/
Sql_condition
*
raise_condition
(
uint
sql_errno
,
const
char
*
sqlstate
,
Sql_condition
::
enum_warning_level
level
,
const
Sql_user_condition_identity
&
ucid
,
const
char
*
msg
);
Sql_condition
*
raise_condition
(
const
Sql_condition
*
cond
)
{
Sql_condition
*
raised
=
raise_condition
(
cond
->
get_sql_errno
(),
cond
->
get_sqlstate
(),
cond
->
get_level
(),
*
cond
/*Sql_user_condition_identity*/
,
cond
->
get_message_text
());
if
(
raised
)
raised
->
copy_opt_attributes
(
cond
);
return
raised
;
}
public
:
/** Overloaded to guard query/query_length fields */
virtual
void
set_statement
(
Statement
*
stmt
);
...
...
sql/sql_error.cc
View file @
4ed804aa
...
...
@@ -307,7 +307,8 @@ Diagnostics_area::reset_diagnostics_area()
m_can_overwrite_status
=
FALSE
;
/** Don't take chances in production */
m_message
[
0
]
=
'\0'
;
m_sql_errno
=
0
;
Sql_state_errno
::
clear
();
Sql_user_condition_identity
::
clear
();
m_affected_rows
=
0
;
m_last_insert_id
=
0
;
m_statement_warn_count
=
0
;
...
...
@@ -406,6 +407,7 @@ Diagnostics_area::set_error_status(uint sql_errno)
set_error_status
(
sql_errno
,
ER
(
sql_errno
),
mysql_errno_to_sqlstate
(
sql_errno
),
Sql_user_condition_identity
(),
NULL
);
}
...
...
@@ -419,6 +421,7 @@ Diagnostics_area::set_error_status(uint sql_errno)
@param sql_errno SQL-condition error number
@param message SQL-condition message
@param sqlstate SQL-condition state
@param ucid User defined condition identity
@param error_condition SQL-condition object representing the error state
@note Note, that error_condition may be NULL. It happens if a) OOM error is
...
...
@@ -429,6 +432,7 @@ void
Diagnostics_area
::
set_error_status
(
uint
sql_errno
,
const
char
*
message
,
const
char
*
sqlstate
,
const
Sql_user_condition_identity
&
ucid
,
const
Sql_condition
*
error_condition
)
{
DBUG_ENTER
(
"set_error_status"
);
...
...
@@ -455,7 +459,8 @@ Diagnostics_area::set_error_status(uint sql_errno,
return
;
#endif
set_condition_value
(
sql_errno
,
sqlstate
);
Sql_state_errno
::
set
(
sql_errno
,
sqlstate
);
Sql_user_condition_identity
::
set
(
ucid
);
strmake_buf
(
m_message
,
message
);
get_warning_info
()
->
set_error_condition
(
error_condition
);
...
...
@@ -647,7 +652,7 @@ void Warning_info::reserve_space(THD *thd, uint count)
}
Sql_condition
*
Warning_info
::
push_warning
(
THD
*
thd
,
const
Sql_
state_errno_level
*
value
,
const
Sql_
condition_identity
*
value
,
const
char
*
msg
)
{
Sql_condition
*
cond
=
NULL
;
...
...
@@ -657,7 +662,7 @@ Sql_condition *Warning_info::push_warning(THD *thd,
if
(
m_allow_unlimited_warnings
||
m_warn_list
.
elements
()
<
thd
->
variables
.
max_error_count
)
{
cond
=
new
(
&
m_warn_root
)
Sql_condition
(
&
m_warn_root
,
value
,
msg
);
cond
=
new
(
&
m_warn_root
)
Sql_condition
(
&
m_warn_root
,
*
value
,
msg
);
if
(
cond
)
m_warn_list
.
push_back
(
cond
);
}
...
...
sql/sql_error.h
View file @
4ed804aa
...
...
@@ -27,6 +27,7 @@
class
THD
;
class
my_decimal
;
class
sp_condition_value
;
///////////////////////////////////////////////////////////////////////////
...
...
@@ -130,15 +131,11 @@ class Sql_state_errno: public Sql_state
uint
get_sql_errno
()
const
{
return
m_sql_errno
;
}
void
set
_condition_value
(
uint
sql_errno
,
const
char
*
sqlstate
)
void
set
(
uint
sql_errno
,
const
char
*
sqlstate
)
{
m_sql_errno
=
sql_errno
;
set_sqlstate
(
sqlstate
);
}
void
set_condition_value
(
const
Sql_state_errno
*
other
)
{
*
this
=
*
other
;
}
void
clear
()
{
m_sql_errno
=
0
;
...
...
@@ -194,6 +191,88 @@ class Sql_state_errno_level: public Sql_state_errno
};
/*
class Sql_user_condition_identity.
Instances of this class uniquely idetify user defined conditions (EXCEPTION).
SET sql_mode=ORACLE;
CREATE PROCEDURE p1
AS
a EXCEPTION;
BEGIN
RAISE a;
EXCEPTION
WHEN a THEN NULL;
END;
Currently a user defined condition is identified by a pointer to
its parse time sp_condition_value instance. This can change when
we add packages. See MDEV-10591.
*/
class
Sql_user_condition_identity
{
protected:
const
sp_condition_value
*
m_user_condition_value
;
public:
Sql_user_condition_identity
()
:
m_user_condition_value
(
NULL
)
{
}
Sql_user_condition_identity
(
const
sp_condition_value
*
value
)
:
m_user_condition_value
(
value
)
{
}
const
sp_condition_value
*
get_user_condition_value
()
const
{
return
m_user_condition_value
;
}
void
set
(
const
Sql_user_condition_identity
&
identity
)
{
*
this
=
identity
;
}
void
clear
()
{
m_user_condition_value
=
NULL
;
}
};
/**
class Sql_condition_identity.
Instances of this class uniquely identify conditions
(including user-defined exceptions for sql_mode=ORACLE)
and store everything that is needed for handler search
purposes in sp_pcontext::find_handler().
*/
class
Sql_condition_identity
:
public
Sql_state_errno_level
,
public
Sql_user_condition_identity
{
public:
Sql_condition_identity
()
{
}
Sql_condition_identity
(
const
Sql_state_errno_level
&
st
,
const
Sql_user_condition_identity
&
ucid
)
:
Sql_state_errno_level
(
st
),
Sql_user_condition_identity
(
ucid
)
{
}
Sql_condition_identity
(
const
Sql_state_errno
&
st
,
enum_warning_level
level
,
const
Sql_user_condition_identity
&
ucid
)
:
Sql_state_errno_level
(
st
,
level
),
Sql_user_condition_identity
(
ucid
)
{
}
Sql_condition_identity
(
uint
sqlerrno
,
const
char
*
sqlstate
,
enum_warning_level
level
,
const
Sql_user_condition_identity
&
ucid
)
:
Sql_state_errno_level
(
sqlerrno
,
sqlstate
,
level
),
Sql_user_condition_identity
(
ucid
)
{
}
void
clear
()
{
Sql_state_errno_level
::
clear
();
Sql_user_condition_identity
::
clear
();
}
};
class
Sql_condition_items
{
protected:
...
...
@@ -262,7 +341,7 @@ class Sql_condition_items
or an exception condition (error, not found).
*/
class
Sql_condition
:
public
Sql_alloc
,
public
Sql_
state_errno_level
,
public
Sql_
condition_identity
,
public
Sql_condition_items
{
public:
...
...
@@ -342,6 +421,12 @@ class Sql_condition : public Sql_alloc,
DBUG_ASSERT
(
mem_root
!=
NULL
);
}
Sql_condition
(
MEM_ROOT
*
mem_root
,
const
Sql_user_condition_identity
&
ucid
)
:
Sql_condition_identity
(
Sql_state_errno_level
(),
ucid
),
m_mem_root
(
mem_root
)
{
DBUG_ASSERT
(
mem_root
!=
NULL
);
}
/**
Constructor for a fixed message text.
@param mem_root - memory root
...
...
@@ -350,25 +435,13 @@ class Sql_condition : public Sql_alloc,
@param msg - the message text for this condition
*/
Sql_condition
(
MEM_ROOT
*
mem_root
,
const
Sql_
state_errno_level
*
value
,
const
Sql_
condition_identity
&
value
,
const
char
*
msg
)
:
Sql_
state_errno_level
(
*
value
),
:
Sql_
condition_identity
(
value
),
m_mem_root
(
mem_root
)
{
DBUG_ASSERT
(
mem_root
!=
NULL
);
DBUG_ASSERT
(
value
->
get_sql_errno
()
!=
0
);
DBUG_ASSERT
(
msg
!=
NULL
);
set_builtin_message_text
(
msg
);
}
Sql_condition
(
MEM_ROOT
*
mem_root
,
const
Sql_state_errno
*
value
,
const
char
*
msg
)
:
Sql_state_errno_level
(
*
value
,
Sql_condition
::
WARN_LEVEL_ERROR
),
m_mem_root
(
mem_root
)
{
DBUG_ASSERT
(
mem_root
!=
NULL
);
DBUG_ASSERT
(
value
->
get_sql_errno
()
!=
0
);
DBUG_ASSERT
(
value
.
get_sql_errno
()
!=
0
);
DBUG_ASSERT
(
msg
!=
NULL
);
set_builtin_message_text
(
msg
);
}
...
...
@@ -409,7 +482,7 @@ class Sql_condition : public Sql_alloc,
*/
void
clear
()
{
Sql_
state_errno_level
::
clear
();
Sql_
condition_identity
::
clear
();
Sql_condition_items
::
clear
();
m_message_text
.
length
(
0
);
}
...
...
@@ -664,15 +737,13 @@ class Warning_info
counters.
@param thd Thread context.
@param sql_errno SQL-condition error number.
@param sqlstate SQL-condition state.
@param level SQL-condition level.
@param identity SQL-condition identity
@param msg SQL-condition message.
@return a pointer to the added SQL-condition.
*/
Sql_condition
*
push_warning
(
THD
*
thd
,
const
Sql_
state_errno_level
*
value
,
const
Sql_
condition_identity
*
identity
,
const
char
*
msg
);
/**
...
...
@@ -829,7 +900,8 @@ class ErrConvDecimal : public ErrConv
Can not be assigned twice per statement.
*/
class
Diagnostics_area
:
public
Sql_state_errno
class
Diagnostics_area
:
public
Sql_state_errno
,
public
Sql_user_condition_identity
{
private:
/** The type of the counted and doubly linked list of conditions. */
...
...
@@ -881,8 +953,19 @@ class Diagnostics_area: public Sql_state_errno
void
set_error_status
(
uint
sql_errno
,
const
char
*
message
,
const
char
*
sqlstate
,
const
Sql_user_condition_identity
&
ucid
,
const
Sql_condition
*
error_condition
);
void
set_error_status
(
uint
sql_errno
,
const
char
*
message
,
const
char
*
sqlstate
,
const
Sql_condition
*
error_condition
)
{
set_error_status
(
sql_errno
,
message
,
sqlstate
,
Sql_user_condition_identity
(),
error_condition
);
}
void
disable_status
();
void
reset_diagnostics_area
();
...
...
@@ -944,6 +1027,18 @@ class Diagnostics_area: public Sql_state_errno
return
m_statement_warn_count
;
}
/**
Get the current errno, state and id of the user defined condition
and return them as Sql_condition_identity.
*/
Sql_condition_identity
get_error_condition_identity
()
const
{
DBUG_ASSERT
(
m_status
==
DA_ERROR
);
return
Sql_condition_identity
(
*
this
/*Sql_state_errno*/
,
Sql_condition
::
WARN_LEVEL_ERROR
,
*
this
/*Sql_user_condition_identity*/
);
}
/* Used to count any warnings pushed after calling set_ok_status(). */
void
increment_warning
()
{
...
...
@@ -1040,12 +1135,22 @@ class Diagnostics_area: public Sql_state_errno
uint
sql_errno_arg
,
const
char
*
sqlstate
,
Sql_condition
::
enum_warning_level
level
,
const
Sql_user_condition_identity
&
ucid
,
const
char
*
msg
)
{
Sql_
state_errno_level
tmp
(
sql_errno_arg
,
sqlstate
,
level
);
Sql_
condition_identity
tmp
(
sql_errno_arg
,
sqlstate
,
level
,
ucid
);
return
get_warning_info
()
->
push_warning
(
thd
,
&
tmp
,
msg
);
}
Sql_condition
*
push_warning
(
THD
*
thd
,
uint
sqlerrno
,
const
char
*
sqlstate
,
Sql_condition
::
enum_warning_level
level
,
const
char
*
msg
)
{
return
push_warning
(
thd
,
sqlerrno
,
sqlstate
,
level
,
Sql_user_condition_identity
(),
msg
);
}
void
mark_sql_conditions_for_removal
()
{
get_warning_info
()
->
mark_sql_conditions_for_removal
();
}
...
...
sql/sql_signal.cc
View file @
4ed804aa
...
...
@@ -353,13 +353,7 @@ bool Sql_cmd_common_signal::raise_condition(THD *thd, Sql_condition *cond)
DBUG_ASSERT
((
cond
->
m_level
==
Sql_condition
::
WARN_LEVEL_WARN
)
||
(
cond
->
m_level
==
Sql_condition
::
WARN_LEVEL_ERROR
));
Sql_condition
*
raised
=
NULL
;
raised
=
thd
->
raise_condition
(
cond
->
get_sql_errno
(),
cond
->
get_sqlstate
(),
cond
->
get_level
(),
cond
->
get_message_text
());
if
(
raised
)
raised
->
copy_opt_attributes
(
cond
);
(
void
)
thd
->
raise_condition
(
cond
);
if
(
cond
->
m_level
==
Sql_condition
::
WARN_LEVEL_WARN
)
{
...
...
@@ -373,7 +367,8 @@ bool Sql_cmd_common_signal::raise_condition(THD *thd, Sql_condition *cond)
bool
Sql_cmd_signal
::
execute
(
THD
*
thd
)
{
bool
result
=
TRUE
;
Sql_condition
cond
(
thd
->
mem_root
);
DBUG_ASSERT
(
m_cond
);
Sql_condition
cond
(
thd
->
mem_root
,
m_cond
->
get_user_condition_identity
());
DBUG_ENTER
(
"Sql_cmd_signal::execute"
);
...
...
@@ -427,7 +422,7 @@ bool Sql_cmd_resignal::execute(THD *thd)
DBUG_RETURN
(
result
);
}
Sql_condition
signaled_err
(
thd
->
mem_root
,
signaled
,
signaled
->
message
);
Sql_condition
signaled_err
(
thd
->
mem_root
,
*
signaled
,
signaled
->
message
);
if
(
m_cond
)
{
...
...
sql/sql_yacc_ora.yy
View file @
4ed804aa
...
...
@@ -2416,6 +2416,16 @@ sp_decl_body:
$$.vars= $$.hndlrs= $$.curs= 0;
$$.conds= 1;
}
| ident_directly_assignable EXCEPTION_SYM
{
sp_condition_value *spcond= new (thd->mem_root)
sp_condition_value_user_defined();
if (!spcond ||
Lex->spcont->declare_condition(thd, $1, spcond))
MYSQL_YYABORT;
$$.vars= $$.hndlrs= $$.curs= 0;
$$.conds= 1;
}
| sp_handler_type HANDLER_SYM FOR_SYM
{
if (Lex->sp_handler_declaration_init(thd, $1))
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment