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
76714a5c
Commit
76714a5c
authored
Sep 27, 2016
by
Alexander Barkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
MDEV-10582 sql_mode=ORACLE: explicit cursor attributes %ISOPEN, %ROWCOUNT, %FOUND, %NOTFOUND
parent
4bb87996
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
800 additions
and
10 deletions
+800
-10
mysql-test/r/keywords.result
mysql-test/r/keywords.result
+4
-0
mysql-test/suite/compat/oracle/r/sp-cursor.result
mysql-test/suite/compat/oracle/r/sp-cursor.result
+291
-0
mysql-test/suite/compat/oracle/t/sp-cursor.test
mysql-test/suite/compat/oracle/t/sp-cursor.test
+296
-0
mysql-test/t/keywords.test
mysql-test/t/keywords.test
+6
-0
sql/item_func.cc
sql/item_func.cc
+48
-0
sql/item_func.h
sql/item_func.h
+70
-0
sql/lex.h
sql/lex.h
+2
-0
sql/sp_pcontext.cc
sql/sp_pcontext.cc
+3
-1
sql/sp_rcontext.cc
sql/sp_rcontext.cc
+12
-1
sql/sp_rcontext.h
sql/sp_rcontext.h
+13
-1
sql/sql_yacc.yy
sql/sql_yacc.yy
+4
-0
sql/sql_yacc_ora.yy
sql/sql_yacc_ora.yy
+51
-7
No files found.
mysql-test/r/keywords.result
View file @
76714a5c
...
@@ -350,3 +350,7 @@ CREATE TABLE decode (decode int);
...
@@ -350,3 +350,7 @@ CREATE TABLE decode (decode int);
DROP TABLE decode;
DROP TABLE decode;
CREATE TABLE rowcount (rowcount int);
CREATE TABLE rowcount (rowcount int);
DROP TABLE rowcount;
DROP TABLE rowcount;
CREATE TABLE isopen (isopen int);
DROP TABLE isopen;
CREATE TABLE notfound (notfound int);
DROP TABLE notfound;
mysql-test/suite/compat/oracle/r/sp-cursor.result
0 → 100644
View file @
76714a5c
SET sql_mode=ORACLE;
#
# MDEV-10582 sql_mode=ORACLE: explicit cursor attributes %ISOPEN, %ROWCOUNT, %FOUND, %NOTFOUND
#
#
# Cursor attributes outside of an SP context
#
SELECT c%ISOPEN;
ERROR 42000: Undefined CURSOR: c
SELECT c%FOUND;
ERROR 42000: Undefined CURSOR: c
SELECT c%NOTFOUND;
ERROR 42000: Undefined CURSOR: c
SELECT c%ROWCOUNT;
ERROR 42000: Undefined CURSOR: c
#
# Undefinite cursor attributes
#
CREATE PROCEDURE p1
AS
BEGIN
SELECT c%ISOPEN;
END;
$$
ERROR 42000: Undefined CURSOR: c
CREATE PROCEDURE p1
AS
BEGIN
SELECT c%ROWCOUNT;
END;
$$
ERROR 42000: Undefined CURSOR: c
CREATE PROCEDURE p1
AS
BEGIN
SELECT c%FOUND;
END;
$$
ERROR 42000: Undefined CURSOR: c
CREATE PROCEDURE p1
AS
BEGIN
SELECT c%NOTFOUND;
END;
$$
ERROR 42000: Undefined CURSOR: c
#
# Not opened cursor attributes %FOUND, %NOTFOUND, %ROWCOUNT
#
CREATE PROCEDURE p1
AS
CURSOR c IS SELECT 1 AS c FROM DUAL;
BEGIN
SELECT c%ROWCOUNT;
END;
$$
CALL p1;
ERROR 24000: Cursor is not open
DROP PROCEDURE p1;
CREATE PROCEDURE p1
AS
CURSOR c IS SELECT 1 AS c FROM DUAL;
BEGIN
SELECT c%FOUND;
END;
$$
CALL p1;
ERROR 24000: Cursor is not open
DROP PROCEDURE p1;
CREATE PROCEDURE p1
AS
CURSOR c IS SELECT 1 AS c FROM DUAL;
BEGIN
SELECT c%NOTFOUND;
END;
$$
CALL p1;
ERROR 24000: Cursor is not open
DROP PROCEDURE p1;
#
# Not opened cursor attributes %FOUND, %NOTFOUND, %ROWCOUNT with INVALID_CURSOR exception
#
CREATE PROCEDURE p1
AS
CURSOR c IS SELECT 1 AS c FROM DUAL;
BEGIN
SELECT c%ROWCOUNT;
EXCEPTION
WHEN INVALID_CURSOR THEN SELECT 'INVALID_CURSOR caught' AS msg;
END;
$$
CALL p1;
c%ROWCOUNT
msg
INVALID_CURSOR caught
DROP PROCEDURE p1;
CREATE PROCEDURE p1
AS
CURSOR c IS SELECT 1 AS c FROM DUAL;
BEGIN
SELECT c%FOUND;
EXCEPTION
WHEN INVALID_CURSOR THEN SELECT 'INVALID_CURSOR caught' AS msg;
END;
$$
CALL p1;
c%FOUND
msg
INVALID_CURSOR caught
DROP PROCEDURE p1;
CREATE PROCEDURE p1
AS
CURSOR c IS SELECT 1 AS c FROM DUAL;
BEGIN
SELECT c%NOTFOUND;
EXCEPTION
WHEN INVALID_CURSOR THEN SELECT 'INVALID_CURSOR caught' AS msg;
END;
$$
CALL p1;
c%NOTFOUND
msg
INVALID_CURSOR caught
DROP PROCEDURE p1;
#
# print()
#
CREATE TABLE t1 (a INT);
CREATE PROCEDURE p1
AS
CURSOR c IS SELECT * FROM t1 ORDER BY a;
BEGIN
EXPLAIN EXTENDED SELECT c%ISOPEN, c%ROWCOUNT, c%FOUND, c%NOTFOUND;
END;
$$
CALL p1();
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 select "c"%ISOPEN AS "c%ISOPEN","c"%ROWCOUNT AS "c%ROWCOUNT","c"%FOUND AS "c%FOUND","c"%NOTFOUND AS "c%NOTFOUND"
DROP PROCEDURE p1;
DROP TABLE t1;
#
# Declared data type of the attributes
#
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (10);
CREATE PROCEDURE p1
AS
CURSOR c IS SELECT * FROM t1 ORDER BY a;
BEGIN
OPEN c;
CREATE TABLE t2 AS SELECT c%ISOPEN, c%ROWCOUNT, c%FOUND, c%NOTFOUND;
SHOW CREATE TABLE t2;
DROP TABLE t2;
CLOSE c;
END;
$$
CALL p1();
Table Create Table
t2 CREATE TABLE "t2" (
"c%ISOPEN" int(1) NOT NULL,
"c%ROWCOUNT" bigint(21) NOT NULL,
"c%FOUND" int(1) DEFAULT NULL,
"c%NOTFOUND" int(1) DEFAULT NULL
)
DROP PROCEDURE p1;
DROP TABLE t1;
#
# Core functionality
#
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (10);
INSERT INTO t1 VALUES (20);
INSERT INTO t1 VALUES (30);
CREATE PROCEDURE p1
AS
a INT:=0;
CURSOR c IS SELECT * FROM t1 ORDER BY a;
BEGIN
SELECT a, c%ISOPEN;
OPEN c;
/*
After OPEN and before FETCH:
- %ROWCOUNT returns 0
- %FOUND and %NOTFOUND return NULL
*/
SELECT a, c%ISOPEN, c%ROWCOUNT, c%FOUND, c%NOTFOUND;
FETCH c INTO a;
SELECT a, c%ISOPEN, c%ROWCOUNT, c%FOUND, c%NOTFOUND;
FETCH c INTO a;
SELECT a, c%ISOPEN, c%ROWCOUNT, c%FOUND, c%NOTFOUND;
FETCH c INTO a;
SELECT a, c%ISOPEN, c%ROWCOUNT, c%FOUND, c%NOTFOUND;
FETCH c INTO a;
SELECT a, c%ISOPEN, c%ROWCOUNT, c%FOUND, c%NOTFOUND;
CLOSE c;
SELECT a, c%ISOPEN;
/*
After reopen and before FETCH:
- %ROWCOUNT returns 0
- %FOUND and %NOTFOUND return NULL
*/
OPEN c;
SELECT a, c%ISOPEN, c%ROWCOUNT, c%FOUND, c%NOTFOUND;
FETCH c INTO a;
SELECT a, c%ISOPEN, c%ROWCOUNT, c%FOUND, c%NOTFOUND;
CLOSE c;
END;
$$
CALL p1();
a c%ISOPEN
0 0
a c%ISOPEN c%ROWCOUNT c%FOUND c%NOTFOUND
0 1 0 NULL NULL
a c%ISOPEN c%ROWCOUNT c%FOUND c%NOTFOUND
10 1 1 1 0
a c%ISOPEN c%ROWCOUNT c%FOUND c%NOTFOUND
20 1 2 1 0
a c%ISOPEN c%ROWCOUNT c%FOUND c%NOTFOUND
30 1 3 1 0
a c%ISOPEN c%ROWCOUNT c%FOUND c%NOTFOUND
30 1 3 0 1
a c%ISOPEN
30 0
a c%ISOPEN c%ROWCOUNT c%FOUND c%NOTFOUND
30 1 0 NULL NULL
a c%ISOPEN c%ROWCOUNT c%FOUND c%NOTFOUND
10 1 1 1 0
DROP PROCEDURE p1;
DROP TABLE t1;
#
# %NOTFOUND as a loop exit condition
#
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (10);
INSERT INTO t1 VALUES (20);
INSERT INTO t1 VALUES (30);
CREATE PROCEDURE p1
AS
a INT:=0;
CURSOR c IS SELECT * FROM t1 ORDER BY a;
BEGIN
OPEN c;
LOOP
FETCH c INTO a;
EXIT WHEN c%NOTFOUND;
SELECT a;
END LOOP;
CLOSE c;
END;
$$
CALL p1();
a
10
a
20
a
30
DROP PROCEDURE p1;
DROP TABLE t1;
#
# %FOUND as a loop exit condition
#
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (10);
INSERT INTO t1 VALUES (20);
INSERT INTO t1 VALUES (30);
CREATE PROCEDURE p1
AS
a INT:=0;
CURSOR c IS SELECT * FROM t1 ORDER BY a;
BEGIN
OPEN c;
LOOP
FETCH c INTO a;
EXIT WHEN NOT c%FOUND;
SELECT a;
END LOOP;
CLOSE c;
END;
$$
CALL p1();
a
10
a
20
a
30
DROP PROCEDURE p1;
DROP TABLE t1;
mysql-test/suite/compat/oracle/t/sp-cursor.test
0 → 100644
View file @
76714a5c
SET
sql_mode
=
ORACLE
;
--
echo
#
--
echo
# MDEV-10582 sql_mode=ORACLE: explicit cursor attributes %ISOPEN, %ROWCOUNT, %FOUND, %NOTFOUND
--
echo
#
--
echo
#
--
echo
# Cursor attributes outside of an SP context
--
echo
#
--
error
ER_SP_CURSOR_MISMATCH
SELECT
c
%
ISOPEN
;
--
error
ER_SP_CURSOR_MISMATCH
SELECT
c
%
FOUND
;
--
error
ER_SP_CURSOR_MISMATCH
SELECT
c
%
NOTFOUND
;
--
error
ER_SP_CURSOR_MISMATCH
SELECT
c
%
ROWCOUNT
;
--
echo
#
--
echo
# Undefinite cursor attributes
--
echo
#
DELIMITER
$$
;
--
error
ER_SP_CURSOR_MISMATCH
CREATE
PROCEDURE
p1
AS
BEGIN
SELECT
c
%
ISOPEN
;
END
;
$$
--
error
ER_SP_CURSOR_MISMATCH
CREATE
PROCEDURE
p1
AS
BEGIN
SELECT
c
%
ROWCOUNT
;
END
;
$$
--
error
ER_SP_CURSOR_MISMATCH
CREATE
PROCEDURE
p1
AS
BEGIN
SELECT
c
%
FOUND
;
END
;
$$
--
error
ER_SP_CURSOR_MISMATCH
CREATE
PROCEDURE
p1
AS
BEGIN
SELECT
c
%
NOTFOUND
;
END
;
$$
DELIMITER
;
$$
--
echo
#
--
echo
# Not opened cursor attributes %FOUND, %NOTFOUND, %ROWCOUNT
--
echo
#
DELIMITER
$$
;
CREATE
PROCEDURE
p1
AS
CURSOR
c
IS
SELECT
1
AS
c
FROM
DUAL
;
BEGIN
SELECT
c
%
ROWCOUNT
;
END
;
$$
DELIMITER
;
$$
--
error
ER_SP_CURSOR_NOT_OPEN
CALL
p1
;
DROP
PROCEDURE
p1
;
DELIMITER
$$
;
CREATE
PROCEDURE
p1
AS
CURSOR
c
IS
SELECT
1
AS
c
FROM
DUAL
;
BEGIN
SELECT
c
%
FOUND
;
END
;
$$
DELIMITER
;
$$
--
error
ER_SP_CURSOR_NOT_OPEN
CALL
p1
;
DROP
PROCEDURE
p1
;
DELIMITER
$$
;
CREATE
PROCEDURE
p1
AS
CURSOR
c
IS
SELECT
1
AS
c
FROM
DUAL
;
BEGIN
SELECT
c
%
NOTFOUND
;
END
;
$$
DELIMITER
;
$$
--
error
ER_SP_CURSOR_NOT_OPEN
CALL
p1
;
DROP
PROCEDURE
p1
;
--
echo
#
--
echo
# Not opened cursor attributes %FOUND, %NOTFOUND, %ROWCOUNT with INVALID_CURSOR exception
--
echo
#
DELIMITER
$$
;
CREATE
PROCEDURE
p1
AS
CURSOR
c
IS
SELECT
1
AS
c
FROM
DUAL
;
BEGIN
SELECT
c
%
ROWCOUNT
;
EXCEPTION
WHEN
INVALID_CURSOR
THEN
SELECT
'INVALID_CURSOR caught'
AS
msg
;
END
;
$$
DELIMITER
;
$$
CALL
p1
;
DROP
PROCEDURE
p1
;
DELIMITER
$$
;
CREATE
PROCEDURE
p1
AS
CURSOR
c
IS
SELECT
1
AS
c
FROM
DUAL
;
BEGIN
SELECT
c
%
FOUND
;
EXCEPTION
WHEN
INVALID_CURSOR
THEN
SELECT
'INVALID_CURSOR caught'
AS
msg
;
END
;
$$
DELIMITER
;
$$
CALL
p1
;
DROP
PROCEDURE
p1
;
DELIMITER
$$
;
CREATE
PROCEDURE
p1
AS
CURSOR
c
IS
SELECT
1
AS
c
FROM
DUAL
;
BEGIN
SELECT
c
%
NOTFOUND
;
EXCEPTION
WHEN
INVALID_CURSOR
THEN
SELECT
'INVALID_CURSOR caught'
AS
msg
;
END
;
$$
DELIMITER
;
$$
CALL
p1
;
DROP
PROCEDURE
p1
;
--
echo
#
--
echo
# print()
--
echo
#
CREATE
TABLE
t1
(
a
INT
);
DELIMITER
$$
;
CREATE
PROCEDURE
p1
AS
CURSOR
c
IS
SELECT
*
FROM
t1
ORDER
BY
a
;
BEGIN
EXPLAIN
EXTENDED
SELECT
c
%
ISOPEN
,
c
%
ROWCOUNT
,
c
%
FOUND
,
c
%
NOTFOUND
;
END
;
$$
DELIMITER
;
$$
CALL
p1
();
DROP
PROCEDURE
p1
;
DROP
TABLE
t1
;
--
echo
#
--
echo
# Declared data type of the attributes
--
echo
#
CREATE
TABLE
t1
(
a
INT
);
INSERT
INTO
t1
VALUES
(
10
);
DELIMITER
$$
;
CREATE
PROCEDURE
p1
AS
CURSOR
c
IS
SELECT
*
FROM
t1
ORDER
BY
a
;
BEGIN
OPEN
c
;
CREATE
TABLE
t2
AS
SELECT
c
%
ISOPEN
,
c
%
ROWCOUNT
,
c
%
FOUND
,
c
%
NOTFOUND
;
SHOW
CREATE
TABLE
t2
;
DROP
TABLE
t2
;
CLOSE
c
;
END
;
$$
DELIMITER
;
$$
CALL
p1
();
DROP
PROCEDURE
p1
;
DROP
TABLE
t1
;
--
echo
#
--
echo
# Core functionality
--
echo
#
CREATE
TABLE
t1
(
a
INT
);
INSERT
INTO
t1
VALUES
(
10
);
INSERT
INTO
t1
VALUES
(
20
);
INSERT
INTO
t1
VALUES
(
30
);
DELIMITER
$$
;
CREATE
PROCEDURE
p1
AS
a
INT
:=
0
;
CURSOR
c
IS
SELECT
*
FROM
t1
ORDER
BY
a
;
BEGIN
SELECT
a
,
c
%
ISOPEN
;
OPEN
c
;
/*
After OPEN and before FETCH:
- %ROWCOUNT returns 0
- %FOUND and %NOTFOUND return NULL
*/
SELECT
a
,
c
%
ISOPEN
,
c
%
ROWCOUNT
,
c
%
FOUND
,
c
%
NOTFOUND
;
FETCH
c
INTO
a
;
SELECT
a
,
c
%
ISOPEN
,
c
%
ROWCOUNT
,
c
%
FOUND
,
c
%
NOTFOUND
;
FETCH
c
INTO
a
;
SELECT
a
,
c
%
ISOPEN
,
c
%
ROWCOUNT
,
c
%
FOUND
,
c
%
NOTFOUND
;
FETCH
c
INTO
a
;
SELECT
a
,
c
%
ISOPEN
,
c
%
ROWCOUNT
,
c
%
FOUND
,
c
%
NOTFOUND
;
FETCH
c
INTO
a
;
SELECT
a
,
c
%
ISOPEN
,
c
%
ROWCOUNT
,
c
%
FOUND
,
c
%
NOTFOUND
;
CLOSE
c
;
SELECT
a
,
c
%
ISOPEN
;
/*
After reopen and before FETCH:
- %ROWCOUNT returns 0
- %FOUND and %NOTFOUND return NULL
*/
OPEN
c
;
SELECT
a
,
c
%
ISOPEN
,
c
%
ROWCOUNT
,
c
%
FOUND
,
c
%
NOTFOUND
;
FETCH
c
INTO
a
;
SELECT
a
,
c
%
ISOPEN
,
c
%
ROWCOUNT
,
c
%
FOUND
,
c
%
NOTFOUND
;
CLOSE
c
;
END
;
$$
DELIMITER
;
$$
CALL
p1
();
DROP
PROCEDURE
p1
;
DROP
TABLE
t1
;
--
echo
#
--
echo
# %NOTFOUND as a loop exit condition
--
echo
#
CREATE
TABLE
t1
(
a
INT
);
INSERT
INTO
t1
VALUES
(
10
);
INSERT
INTO
t1
VALUES
(
20
);
INSERT
INTO
t1
VALUES
(
30
);
DELIMITER
$$
;
CREATE
PROCEDURE
p1
AS
a
INT
:=
0
;
CURSOR
c
IS
SELECT
*
FROM
t1
ORDER
BY
a
;
BEGIN
OPEN
c
;
LOOP
FETCH
c
INTO
a
;
EXIT
WHEN
c
%
NOTFOUND
;
SELECT
a
;
END
LOOP
;
CLOSE
c
;
END
;
$$
DELIMITER
;
$$
CALL
p1
();
DROP
PROCEDURE
p1
;
DROP
TABLE
t1
;
--
echo
#
--
echo
# %FOUND as a loop exit condition
--
echo
#
CREATE
TABLE
t1
(
a
INT
);
INSERT
INTO
t1
VALUES
(
10
);
INSERT
INTO
t1
VALUES
(
20
);
INSERT
INTO
t1
VALUES
(
30
);
DELIMITER
$$
;
CREATE
PROCEDURE
p1
AS
a
INT
:=
0
;
CURSOR
c
IS
SELECT
*
FROM
t1
ORDER
BY
a
;
BEGIN
OPEN
c
;
LOOP
FETCH
c
INTO
a
;
EXIT
WHEN
NOT
c
%
FOUND
;
SELECT
a
;
END
LOOP
;
CLOSE
c
;
END
;
$$
DELIMITER
;
$$
CALL
p1
();
DROP
PROCEDURE
p1
;
DROP
TABLE
t1
;
mysql-test/t/keywords.test
View file @
76714a5c
...
@@ -247,3 +247,9 @@ DROP TABLE decode;
...
@@ -247,3 +247,9 @@ DROP TABLE decode;
CREATE
TABLE
rowcount
(
rowcount
int
);
CREATE
TABLE
rowcount
(
rowcount
int
);
DROP
TABLE
rowcount
;
DROP
TABLE
rowcount
;
CREATE
TABLE
isopen
(
isopen
int
);
DROP
TABLE
isopen
;
CREATE
TABLE
notfound
(
notfound
int
);
DROP
TABLE
notfound
;
sql/item_func.cc
View file @
76714a5c
...
@@ -6862,4 +6862,52 @@ void Item_func_last_value::fix_length_and_dec()
...
@@ -6862,4 +6862,52 @@ void Item_func_last_value::fix_length_and_dec()
}
}
void
Item_func_cursor_int_attr
::
print
(
String
*
str
,
enum_query_type
query_type
)
{
append_identifier
(
current_thd
,
str
,
m_cursor_name
.
str
,
m_cursor_name
.
length
);
str
->
append
(
func_name
());
}
sp_cursor
*
Item_func_cursor_int_attr
::
get_open_cursor_or_error
()
{
THD
*
thd
=
current_thd
;
sp_cursor
*
c
=
thd
->
spcont
->
get_cursor
(
m_cursor_offset
);
DBUG_ASSERT
(
c
);
if
(
!
c
/*safety*/
||
!
c
->
is_open
())
{
my_message
(
ER_SP_CURSOR_NOT_OPEN
,
ER_THD
(
thd
,
ER_SP_CURSOR_NOT_OPEN
),
MYF
(
0
));
return
NULL
;
}
return
c
;
}
longlong
Item_func_cursor_isopen
::
val_int
()
{
sp_cursor
*
c
=
current_thd
->
spcont
->
get_cursor
(
m_cursor_offset
);
DBUG_ASSERT
(
c
!=
NULL
);
return
c
?
c
->
is_open
()
:
0
;
}
longlong
Item_func_cursor_found
::
val_int
()
{
sp_cursor
*
c
=
get_open_cursor_or_error
();
return
!
(
null_value
=
(
!
c
||
c
->
fetch_count
()
==
0
))
&&
c
->
found
();
}
longlong
Item_func_cursor_notfound
::
val_int
()
{
sp_cursor
*
c
=
get_open_cursor_or_error
();
return
!
(
null_value
=
(
!
c
||
c
->
fetch_count
()
==
0
))
&&
!
c
->
found
();
}
longlong
Item_func_cursor_rowcount
::
val_int
()
{
sp_cursor
*
c
=
get_open_cursor_or_error
();
return
!
(
null_value
=
!
c
)
?
c
->
row_count
()
:
0
;
}
sql/item_func.h
View file @
76714a5c
...
@@ -725,6 +725,76 @@ class Item_int_func :public Item_func
...
@@ -725,6 +725,76 @@ class Item_int_func :public Item_func
};
};
class
Item_func_cursor_int_attr
:
public
Item_int_func
{
protected:
LEX_STRING
m_cursor_name
;
uint
m_cursor_offset
;
class
sp_cursor
*
get_open_cursor_or_error
();
public:
Item_func_cursor_int_attr
(
THD
*
thd
,
const
LEX_STRING
name
,
uint
offset
)
:
Item_int_func
(
thd
),
m_cursor_name
(
name
),
m_cursor_offset
(
offset
)
{
}
bool
check_vcol_func_processor
(
void
*
arg
)
{
return
mark_unsupported_function
(
func_name
(),
arg
,
VCOL_SESSION_FUNC
);
}
void
print
(
String
*
str
,
enum_query_type
query_type
);
};
class
Item_func_cursor_isopen
:
public
Item_func_cursor_int_attr
{
public:
Item_func_cursor_isopen
(
THD
*
thd
,
const
LEX_STRING
name
,
uint
offset
)
:
Item_func_cursor_int_attr
(
thd
,
name
,
offset
)
{
}
const
char
*
func_name
()
const
{
return
"%ISOPEN"
;
}
void
fix_length_and_dec
()
{
max_length
=
1
;
}
longlong
val_int
();
Item
*
get_copy
(
THD
*
thd
,
MEM_ROOT
*
mem_root
)
{
return
get_item_copy
<
Item_func_cursor_isopen
>
(
thd
,
mem_root
,
this
);
}
};
class
Item_func_cursor_found
:
public
Item_func_cursor_int_attr
{
public:
Item_func_cursor_found
(
THD
*
thd
,
const
LEX_STRING
name
,
uint
offset
)
:
Item_func_cursor_int_attr
(
thd
,
name
,
offset
)
{
}
const
char
*
func_name
()
const
{
return
"%FOUND"
;
}
void
fix_length_and_dec
()
{
max_length
=
1
;
maybe_null
=
true
;
}
longlong
val_int
();
Item
*
get_copy
(
THD
*
thd
,
MEM_ROOT
*
mem_root
)
{
return
get_item_copy
<
Item_func_cursor_found
>
(
thd
,
mem_root
,
this
);
}
};
class
Item_func_cursor_notfound
:
public
Item_func_cursor_int_attr
{
public:
Item_func_cursor_notfound
(
THD
*
thd
,
const
LEX_STRING
name
,
uint
offset
)
:
Item_func_cursor_int_attr
(
thd
,
name
,
offset
)
{
}
const
char
*
func_name
()
const
{
return
"%NOTFOUND"
;
}
void
fix_length_and_dec
()
{
max_length
=
1
;
maybe_null
=
true
;
}
longlong
val_int
();
Item
*
get_copy
(
THD
*
thd
,
MEM_ROOT
*
mem_root
)
{
return
get_item_copy
<
Item_func_cursor_notfound
>
(
thd
,
mem_root
,
this
);
}
};
class
Item_func_cursor_rowcount
:
public
Item_func_cursor_int_attr
{
public:
Item_func_cursor_rowcount
(
THD
*
thd
,
const
LEX_STRING
name
,
uint
offset
)
:
Item_func_cursor_int_attr
(
thd
,
name
,
offset
)
{
}
const
char
*
func_name
()
const
{
return
"%ROWCOUNT"
;
}
longlong
val_int
();
Item
*
get_copy
(
THD
*
thd
,
MEM_ROOT
*
mem_root
)
{
return
get_item_copy
<
Item_func_cursor_rowcount
>
(
thd
,
mem_root
,
this
);
}
};
class
Item_func_connection_id
:
public
Item_int_func
class
Item_func_connection_id
:
public
Item_int_func
{
{
longlong
value
;
longlong
value
;
...
...
sql/lex.h
View file @
76714a5c
...
@@ -310,6 +310,7 @@ static SYMBOL symbols[] = {
...
@@ -310,6 +310,7 @@ static SYMBOL symbols[] = {
{
"IPC"
,
SYM
(
IPC_SYM
)},
{
"IPC"
,
SYM
(
IPC_SYM
)},
{
"IS"
,
SYM
(
IS
)},
{
"IS"
,
SYM
(
IS
)},
{
"ISOLATION"
,
SYM
(
ISOLATION
)},
{
"ISOLATION"
,
SYM
(
ISOLATION
)},
{
"ISOPEN"
,
SYM
(
ISOPEN_SYM
)},
{
"ISSUER"
,
SYM
(
ISSUER_SYM
)},
{
"ISSUER"
,
SYM
(
ISSUER_SYM
)},
{
"ITERATE"
,
SYM
(
ITERATE_SYM
)},
{
"ITERATE"
,
SYM
(
ITERATE_SYM
)},
{
"INVOKER"
,
SYM
(
INVOKER_SYM
)},
{
"INVOKER"
,
SYM
(
INVOKER_SYM
)},
...
@@ -415,6 +416,7 @@ static SYMBOL symbols[] = {
...
@@ -415,6 +416,7 @@ static SYMBOL symbols[] = {
{
"NODEGROUP"
,
SYM
(
NODEGROUP_SYM
)},
{
"NODEGROUP"
,
SYM
(
NODEGROUP_SYM
)},
{
"NONE"
,
SYM
(
NONE_SYM
)},
{
"NONE"
,
SYM
(
NONE_SYM
)},
{
"NOT"
,
SYM
(
NOT_SYM
)},
{
"NOT"
,
SYM
(
NOT_SYM
)},
{
"NOTFOUND"
,
SYM
(
NOTFOUND_SYM
)},
{
"NO_WRITE_TO_BINLOG"
,
SYM
(
NO_WRITE_TO_BINLOG
)},
{
"NO_WRITE_TO_BINLOG"
,
SYM
(
NO_WRITE_TO_BINLOG
)},
{
"NULL"
,
SYM
(
NULL_SYM
)},
{
"NULL"
,
SYM
(
NULL_SYM
)},
{
"NUMBER"
,
SYM
(
NUMBER_SYM
)},
{
"NUMBER"
,
SYM
(
NUMBER_SYM
)},
...
...
sql/sp_pcontext.cc
View file @
76714a5c
...
@@ -289,13 +289,15 @@ sp_condition_value *sp_pcontext::find_condition(const LEX_STRING name,
...
@@ -289,13 +289,15 @@ sp_condition_value *sp_pcontext::find_condition(const LEX_STRING name,
static
sp_condition_value
static
sp_condition_value
cond_invalid_cursor
(
ER_SP_CURSOR_NOT_OPEN
),
cond_no_data_found
(
ER_SP_FETCH_NO_DATA
),
cond_no_data_found
(
ER_SP_FETCH_NO_DATA
),
cond_dup_val_on_index
(
ER_DUP_ENTRY
),
cond_dup_val_on_index
(
ER_DUP_ENTRY
),
cond_too_many_rows
(
ER_TOO_MANY_ROWS
);
cond_too_many_rows
(
ER_TOO_MANY_ROWS
);
static
sp_condition
sp_predefined_conditions
[
3
]
=
static
sp_condition
sp_predefined_conditions
[]
=
{
{
sp_condition
(
C_STRING_WITH_LEN
(
"INVALID_CURSOR"
),
&
cond_invalid_cursor
),
sp_condition
(
C_STRING_WITH_LEN
(
"NO_DATA_FOUND"
),
&
cond_no_data_found
),
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
(
"DUP_VAL_ON_INDEX"
),
&
cond_dup_val_on_index
),
sp_condition
(
C_STRING_WITH_LEN
(
"TOO_MANY_ROWS"
),
&
cond_too_many_rows
)
sp_condition
(
C_STRING_WITH_LEN
(
"TOO_MANY_ROWS"
),
&
cond_too_many_rows
)
...
...
sql/sp_rcontext.cc
View file @
76714a5c
...
@@ -425,7 +425,10 @@ sp_cursor::sp_cursor(THD *thd_arg, sp_lex_keeper *lex_keeper, sp_instr_cpush *i)
...
@@ -425,7 +425,10 @@ sp_cursor::sp_cursor(THD *thd_arg, sp_lex_keeper *lex_keeper, sp_instr_cpush *i)
result
(
thd_arg
),
result
(
thd_arg
),
m_lex_keeper
(
lex_keeper
),
m_lex_keeper
(
lex_keeper
),
server_side_cursor
(
NULL
),
server_side_cursor
(
NULL
),
m_i
(
i
)
m_i
(
i
),
m_fetch_count
(
0
),
m_row_count
(
0
),
m_found
(
false
)
{
{
/*
/*
currsor can't be stored in QC, so we should prevent opening QC for
currsor can't be stored in QC, so we should prevent opening QC for
...
@@ -470,6 +473,8 @@ int sp_cursor::close(THD *thd)
...
@@ -470,6 +473,8 @@ int sp_cursor::close(THD *thd)
MYF
(
0
));
MYF
(
0
));
return
-
1
;
return
-
1
;
}
}
m_row_count
=
m_fetch_count
=
0
;
m_found
=
false
;
destroy
();
destroy
();
return
0
;
return
0
;
}
}
...
@@ -497,6 +502,7 @@ int sp_cursor::fetch(THD *thd, List<sp_variable> *vars)
...
@@ -497,6 +502,7 @@ int sp_cursor::fetch(THD *thd, List<sp_variable> *vars)
return
-
1
;
return
-
1
;
}
}
m_fetch_count
++
;
DBUG_EXECUTE_IF
(
"bug23032_emit_warning"
,
DBUG_EXECUTE_IF
(
"bug23032_emit_warning"
,
push_warning
(
thd
,
Sql_condition
::
WARN_LEVEL_WARN
,
push_warning
(
thd
,
Sql_condition
::
WARN_LEVEL_WARN
,
ER_UNKNOWN_ERROR
,
ER_UNKNOWN_ERROR
,
...
@@ -514,10 +520,15 @@ int sp_cursor::fetch(THD *thd, List<sp_variable> *vars)
...
@@ -514,10 +520,15 @@ int sp_cursor::fetch(THD *thd, List<sp_variable> *vars)
*/
*/
if
(
!
server_side_cursor
->
is_open
())
if
(
!
server_side_cursor
->
is_open
())
{
{
m_found
=
false
;
if
(
thd
->
variables
.
sql_mode
&
MODE_ORACLE
)
return
0
;
my_message
(
ER_SP_FETCH_NO_DATA
,
ER_THD
(
thd
,
ER_SP_FETCH_NO_DATA
),
MYF
(
0
));
my_message
(
ER_SP_FETCH_NO_DATA
,
ER_THD
(
thd
,
ER_SP_FETCH_NO_DATA
),
MYF
(
0
));
return
-
1
;
return
-
1
;
}
}
m_found
=
true
;
m_row_count
++
;
return
0
;
return
0
;
}
}
...
...
sql/sp_rcontext.h
View file @
76714a5c
...
@@ -452,6 +452,15 @@ class sp_cursor : public Sql_alloc
...
@@ -452,6 +452,15 @@ class sp_cursor : public Sql_alloc
my_bool
is_open
()
my_bool
is_open
()
{
return
MY_TEST
(
server_side_cursor
);
}
{
return
MY_TEST
(
server_side_cursor
);
}
bool
found
()
const
{
return
m_found
;
}
ulonglong
row_count
()
const
{
return
m_row_count
;
}
ulonglong
fetch_count
()
const
{
return
m_fetch_count
;
}
int
fetch
(
THD
*
,
List
<
sp_variable
>
*
vars
);
int
fetch
(
THD
*
,
List
<
sp_variable
>
*
vars
);
sp_instr_cpush
*
get_instr
()
sp_instr_cpush
*
get_instr
()
...
@@ -461,7 +470,10 @@ class sp_cursor : public Sql_alloc
...
@@ -461,7 +470,10 @@ class sp_cursor : public Sql_alloc
Select_fetch_into_spvars
result
;
Select_fetch_into_spvars
result
;
sp_lex_keeper
*
m_lex_keeper
;
sp_lex_keeper
*
m_lex_keeper
;
Server_side_cursor
*
server_side_cursor
;
Server_side_cursor
*
server_side_cursor
;
sp_instr_cpush
*
m_i
;
// My push instruction
sp_instr_cpush
*
m_i
;
// My push instruction
ulonglong
m_fetch_count
;
// Number of FETCH commands since last OPEN
ulonglong
m_row_count
;
// Number of successful FETCH since last OPEN
bool
m_found
;
// If last FETCH fetched a row
void
destroy
();
void
destroy
();
};
// class sp_cursor : public Sql_alloc
};
// class sp_cursor : public Sql_alloc
...
...
sql/sql_yacc.yy
View file @
76714a5c
...
@@ -1181,6 +1181,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
...
@@ -1181,6 +1181,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token IPC_SYM
%token IPC_SYM
%token IS /* SQL-2003-R */
%token IS /* SQL-2003-R */
%token ISOLATION /* SQL-2003-R */
%token ISOLATION /* SQL-2003-R */
%token ISOPEN_SYM /* Oracle-N */
%token ISSUER_SYM
%token ISSUER_SYM
%token ITERATE_SYM
%token ITERATE_SYM
%token JOIN_SYM /* SQL-2003-R */
%token JOIN_SYM /* SQL-2003-R */
...
@@ -1290,6 +1291,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
...
@@ -1290,6 +1291,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token NONE_SYM /* SQL-2003-R */
%token NONE_SYM /* SQL-2003-R */
%token NOT2_SYM
%token NOT2_SYM
%token NOT_SYM /* SQL-2003-R */
%token NOT_SYM /* SQL-2003-R */
%token NOTFOUND_SYM /* Oracle-R */
%token NOW_SYM
%token NOW_SYM
%token NO_SYM /* SQL-2003-R */
%token NO_SYM /* SQL-2003-R */
%token NO_WAIT_SYM
%token NO_WAIT_SYM
...
@@ -14346,6 +14348,7 @@ keyword_sp:
...
@@ -14346,6 +14348,7 @@ keyword_sp:
| IO_SYM {}
| IO_SYM {}
| IPC_SYM {}
| IPC_SYM {}
| ISOLATION {}
| ISOLATION {}
| ISOPEN_SYM {}
| ISSUER_SYM {}
| ISSUER_SYM {}
| JSON_SYM {}
| JSON_SYM {}
| INSERT_METHOD {}
| INSERT_METHOD {}
...
@@ -14415,6 +14418,7 @@ keyword_sp:
...
@@ -14415,6 +14418,7 @@ keyword_sp:
| NO_WAIT_SYM {}
| NO_WAIT_SYM {}
| NODEGROUP_SYM {}
| NODEGROUP_SYM {}
| NONE_SYM {}
| NONE_SYM {}
| NOTFOUND_SYM {}
| NUMBER_SYM {}
| NUMBER_SYM {}
| NVARCHAR_SYM {}
| NVARCHAR_SYM {}
| OFFSET_SYM {}
| OFFSET_SYM {}
...
...
sql/sql_yacc_ora.yy
View file @
76714a5c
...
@@ -178,6 +178,11 @@ void ORAerror(THD *thd, const char *s)
...
@@ -178,6 +178,11 @@ void ORAerror(THD *thd, const char *s)
Lex_field_type_st Lex_field_type;
Lex_field_type_st Lex_field_type;
Lex_dyncol_type_st Lex_dyncol_type;
Lex_dyncol_type_st Lex_dyncol_type;
Lex_for_loop_st for_loop;
Lex_for_loop_st for_loop;
struct
{
LEX_STRING name;
uint offset;
} sp_cursor_name_and_offset;
/* pointers */
/* pointers */
Create_field *create_field;
Create_field *create_field;
...
@@ -555,6 +560,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
...
@@ -555,6 +560,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token IPC_SYM
%token IPC_SYM
%token IS /* SQL-2003-R */
%token IS /* SQL-2003-R */
%token ISOLATION /* SQL-2003-R */
%token ISOLATION /* SQL-2003-R */
%token ISOPEN_SYM /* Oracle-N */
%token ISSUER_SYM
%token ISSUER_SYM
%token ITERATE_SYM
%token ITERATE_SYM
%token JOIN_SYM /* SQL-2003-R */
%token JOIN_SYM /* SQL-2003-R */
...
@@ -664,6 +670,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
...
@@ -664,6 +670,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token NONE_SYM /* SQL-2003-R */
%token NONE_SYM /* SQL-2003-R */
%token NOT2_SYM
%token NOT2_SYM
%token NOT_SYM /* SQL-2003-R */
%token NOT_SYM /* SQL-2003-R */
%token NOTFOUND_SYM /* Oracle-R */
%token NOW_SYM
%token NOW_SYM
%token NO_SYM /* SQL-2003-R */
%token NO_SYM /* SQL-2003-R */
%token NO_WAIT_SYM
%token NO_WAIT_SYM
...
@@ -975,7 +982,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
...
@@ -975,7 +982,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%left '&'
%left '&'
%left SHIFT_LEFT SHIFT_RIGHT
%left SHIFT_LEFT SHIFT_RIGHT
%left '-' '+'
%left '-' '+'
%left '*' '/'
'%'
DIV_SYM MOD_SYM
%left '*' '/' DIV_SYM MOD_SYM
%left '^'
%left '^'
%left NEG '~'
%left NEG '~'
%right NOT_SYM NOT2_SYM
%right NOT_SYM NOT2_SYM
...
@@ -1103,6 +1110,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
...
@@ -1103,6 +1110,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
window_func_expr
window_func_expr
window_func
window_func
simple_window_func
simple_window_func
explicit_cursor_attr
function_call_keyword
function_call_keyword
function_call_nonkeyword
function_call_nonkeyword
function_call_generic
function_call_generic
...
@@ -1291,6 +1299,7 @@ END_OF_INPUT
...
@@ -1291,6 +1299,7 @@ END_OF_INPUT
%type <spblock> sp_decl_body sp_decl_body_list opt_sp_decl_body_list
%type <spblock> sp_decl_body sp_decl_body_list opt_sp_decl_body_list
%type <spblock_handlers> sp_block_statements_and_exceptions
%type <spblock_handlers> sp_block_statements_and_exceptions
%type <sp_instr_addr> sp_instr_addr
%type <sp_instr_addr> sp_instr_addr
%type <sp_cursor_name_and_offset> sp_cursor_name_and_offset
%type <num> opt_exception_clause exception_handlers
%type <num> opt_exception_clause exception_handlers
%type <lex> sp_cursor_stmt
%type <lex> sp_cursor_stmt
%type <spname> sp_name
%type <spname> sp_name
...
@@ -8598,12 +8607,6 @@ bit_expr:
...
@@ -8598,12 +8607,6 @@ bit_expr:
if ($$ == NULL)
if ($$ == NULL)
MYSQL_YYABORT;
MYSQL_YYABORT;
}
}
| bit_expr '%' bit_expr %prec '%'
{
$$= new (thd->mem_root) Item_func_mod(thd, $1, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bit_expr DIV_SYM bit_expr %prec DIV_SYM
| bit_expr DIV_SYM bit_expr %prec DIV_SYM
{
{
$$= new (thd->mem_root) Item_func_int_div(thd, $1, $3);
$$= new (thd->mem_root) Item_func_int_div(thd, $1, $3);
...
@@ -8740,6 +8743,44 @@ dyncall_create_list:
...
@@ -8740,6 +8743,44 @@ dyncall_create_list:
}
}
;
;
sp_cursor_name_and_offset:
ident
{
LEX *lex= Lex;
$$.name= $1;
if (!lex->spcont ||
!lex->spcont->find_cursor($1, &$$.offset, false))
my_yyabort_error((ER_SP_CURSOR_MISMATCH, MYF(0), $1.str));
}
;
explicit_cursor_attr:
sp_cursor_name_and_offset '%' ISOPEN_SYM
{
if (!($$= new (thd->mem_root)
Item_func_cursor_isopen(thd, $1.name, $1.offset)))
MYSQL_YYABORT;
}
| sp_cursor_name_and_offset '%' FOUND_SYM
{
if (!($$= new (thd->mem_root)
Item_func_cursor_found(thd, $1.name, $1.offset)))
MYSQL_YYABORT;
}
| sp_cursor_name_and_offset '%' NOTFOUND_SYM
{
if (!($$= new (thd->mem_root)
Item_func_cursor_notfound(thd, $1.name, $1.offset)))
MYSQL_YYABORT;
}
| sp_cursor_name_and_offset '%' ROWCOUNT_SYM
{
if (!($$= new (thd->mem_root)
Item_func_cursor_rowcount(thd, $1.name, $1.offset)))
MYSQL_YYABORT;
}
;
/*
/*
Expressions that the parser allows in a column DEFAULT clause
Expressions that the parser allows in a column DEFAULT clause
without parentheses. These expressions cannot end with a COLLATE clause.
without parentheses. These expressions cannot end with a COLLATE clause.
...
@@ -8904,6 +8945,7 @@ column_default_non_parenthesized_expr:
...
@@ -8904,6 +8945,7 @@ column_default_non_parenthesized_expr:
simple_expr:
simple_expr:
column_default_non_parenthesized_expr
column_default_non_parenthesized_expr
| explicit_cursor_attr
| simple_expr COLLATE_SYM ident_or_text %prec NEG
| simple_expr COLLATE_SYM ident_or_text %prec NEG
{
{
Item *i1= new (thd->mem_root) Item_string(thd, $3.str,
Item *i1= new (thd->mem_root) Item_string(thd, $3.str,
...
@@ -14306,6 +14348,7 @@ keyword_sp:
...
@@ -14306,6 +14348,7 @@ keyword_sp:
| IO_SYM {}
| IO_SYM {}
| IPC_SYM {}
| IPC_SYM {}
| ISOLATION {}
| ISOLATION {}
| ISOPEN_SYM {}
| ISSUER_SYM {}
| ISSUER_SYM {}
| JSON_SYM {}
| JSON_SYM {}
| INSERT_METHOD {}
| INSERT_METHOD {}
...
@@ -14375,6 +14418,7 @@ keyword_sp:
...
@@ -14375,6 +14418,7 @@ keyword_sp:
| NO_WAIT_SYM {}
| NO_WAIT_SYM {}
| NODEGROUP_SYM {}
| NODEGROUP_SYM {}
| NONE_SYM {}
| NONE_SYM {}
| NOTFOUND_SYM {}
| NUMBER_SYM {}
| NUMBER_SYM {}
| NVARCHAR_SYM {}
| NVARCHAR_SYM {}
| OFFSET_SYM {}
| OFFSET_SYM {}
...
...
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