MDEV-36390: Minor refactoring of the method get_expr_query at the classes sp_instr_cpush/sp_instr_cursor_copy_struct

Duplicated code from methods
  sp_instr_cpush::get_expr_query
  sp_instr_cursor_copy_struct::get_expr_query
were extracted to the standalone function get_cursor_query

Additionally, added correct parsing of a cursor definition with
a new line or TAB instead of the space immediately after FOR/IS.
This commit is contained in:
Dmitry Shulga
2025-03-27 18:02:37 +07:00
parent cc831f16c8
commit 6e4fa7e5a1
3 changed files with 211 additions and 20 deletions

View File

@ -1993,4 +1993,96 @@ f1()
# Clean up
DROP FUNCTION f1;
DROP TABLE t1;
#
# MDEV-36390: Minor refactoring of the method get_expr_query at the classes sp_instr_cpush/sp_instr_cursor_copy_struct
#
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (1);
CREATE OR REPLACE PROCEDURE p1()
BEGIN
DECLARE va INT;
# Check that the TAB character after the clause FOR is skipped and
# the body of cursor is remembered correctly for subsequent re-parsing
DECLARE cur CURSOR FOR SELECT a FROM t1;
OPEN cur;
FETCH cur INTO va;
SELECT va;
CLOSE cur;
END;
$
CREATE OR REPLACE PROCEDURE p2()
BEGIN
DECLARE va INT;
# Check that the newline character after the clause FOR is skipped and
# the body of cursor is remembered correctly for subsequent re-parsing
DECLARE cur CURSOR FOR
SELECT a FROM t1;
OPEN cur;
FETCH cur INTO va;
SELECT va;
CLOSE cur;
END;
$
CREATE OR REPLACE PROCEDURE p3()
BEGIN
DECLARE va INT;
# Check that C-style comment and the newline character after
# the clause FOR is skipped and the body of cursor is remembered
# correctly for subsequent re-parsing
DECLARE cur CURSOR FOR /* Explicit comment */
SELECT a FROM t1;
OPEN cur;
FETCH cur INTO va;
SELECT va;
CLOSE cur;
END;
$
CREATE OR REPLACE PROCEDURE p4()
BEGIN
DECLARE va INT;
# Check that SQL-style comment and the newline character after
# the clause FOR is skipped and the body of cursor is remembered
# correctly for subsequent re-parsing
DECLARE cur CURSOR FOR -- Explicit comment
SELECT a FROM t1;
OPEN cur;
FETCH cur INTO va;
SELECT va;
CLOSE cur;
END;
$
CALL p1();
va
1
CALL p2();
va
1
CALL p3();
va
1
CALL p4();
va
1
ALTER TABLE t1 COMMENT 'The Comment 1';
# The following statements will run re-parsing of
# cursor declaration statements inside the stored
# procedures p1, p2, p3, p4.
CALL p1();
va
1
CALL p2();
va
1
CALL p3();
va
1
CALL p4();
va
1
# Clean up
DROP PROCEDURE p1;
DROP PROCEDURE p2;
DROP PROCEDURE p3;
DROP PROCEDURE p4;
DROP TABLE t1;
SET sql_mode = default;

View File

@ -2795,5 +2795,96 @@ SELECT f1();
DROP FUNCTION f1;
DROP TABLE t1;
--echo #
--echo # MDEV-36390: Minor refactoring of the method get_expr_query at the classes sp_instr_cpush/sp_instr_cursor_copy_struct
--echo #
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (1);
--delimiter $
CREATE OR REPLACE PROCEDURE p1()
BEGIN
DECLARE va INT;
# Check that the TAB character after the clause FOR is skipped and
# the body of cursor is remembered correctly for subsequent re-parsing
DECLARE cur CURSOR FOR SELECT a FROM t1;
OPEN cur;
FETCH cur INTO va;
SELECT va;
CLOSE cur;
END;
$
CREATE OR REPLACE PROCEDURE p2()
BEGIN
DECLARE va INT;
# Check that the newline character after the clause FOR is skipped and
# the body of cursor is remembered correctly for subsequent re-parsing
DECLARE cur CURSOR FOR
SELECT a FROM t1;
OPEN cur;
FETCH cur INTO va;
SELECT va;
CLOSE cur;
END;
$
CREATE OR REPLACE PROCEDURE p3()
BEGIN
DECLARE va INT;
# Check that C-style comment and the newline character after
# the clause FOR is skipped and the body of cursor is remembered
# correctly for subsequent re-parsing
DECLARE cur CURSOR FOR /* Explicit comment */
SELECT a FROM t1;
OPEN cur;
FETCH cur INTO va;
SELECT va;
CLOSE cur;
END;
$
CREATE OR REPLACE PROCEDURE p4()
BEGIN
DECLARE va INT;
# Check that SQL-style comment and the newline character after
# the clause FOR is skipped and the body of cursor is remembered
# correctly for subsequent re-parsing
DECLARE cur CURSOR FOR -- Explicit comment
SELECT a FROM t1;
OPEN cur;
FETCH cur INTO va;
SELECT va;
CLOSE cur;
END;
$
--delimiter ;
CALL p1();
CALL p2();
CALL p3();
CALL p4();
ALTER TABLE t1 COMMENT 'The Comment 1';
--echo # The following statements will run re-parsing of
--echo # cursor declaration statements inside the stored
--echo # procedures p1, p2, p3, p4.
CALL p1();
CALL p2();
CALL p3();
CALL p4();
--echo # Clean up
DROP PROCEDURE p1;
DROP PROCEDURE p2;
DROP PROCEDURE p3;
DROP PROCEDURE p4;
DROP TABLE t1;
SET sql_mode = default;
--enable_ps2_protocol

View File

@ -1251,6 +1251,32 @@ public:
}; // class sp_instr_hreturn : public sp_instr_jump
/**
Get a query text associated with the cursor.
*/
static inline LEX_CSTRING get_cursor_query(const LEX_CSTRING &cursor_stmt)
{
/*
Lexer on processing the clause CURSOR FOR / CURSOR IS doesn't
move a pointer on cpp_buf after the token FOR/IS so skip it explicitly
in order to get correct value of cursor's query string.
*/
if (strncasecmp(cursor_stmt.str, "FOR", 3) == 0 &&
my_isspace(current_thd->variables.character_set_client,
cursor_stmt.str[3]))
return LEX_CSTRING{cursor_stmt.str + 4, cursor_stmt.length - 4};
if (strncasecmp(cursor_stmt.str, "IS", 2) == 0 &&
my_isspace(current_thd->variables.character_set_client,
cursor_stmt.str[2]))
return LEX_CSTRING{cursor_stmt.str + 3, cursor_stmt.length - 3};
return cursor_stmt;
}
/**
This is DECLARE CURSOR
*/
@ -1311,16 +1337,7 @@ public:
protected:
LEX_CSTRING get_expr_query() const override
{
/*
Lexer on processing the clause CURSOR FOR / CURSOR IS doesn't
move a pointer on cpp_buf after the token FOR/IS so skip it explicitly
in order to get correct value of cursor's query string.
*/
if (strncasecmp(m_cursor_stmt.str, "FOR ", 4) == 0)
return LEX_CSTRING{m_cursor_stmt.str + 4, m_cursor_stmt.length - 4};
if (strncasecmp(m_cursor_stmt.str, "IS ", 3) == 0)
return LEX_CSTRING{m_cursor_stmt.str + 3, m_cursor_stmt.length - 3};
return m_cursor_stmt;
return get_cursor_query(m_cursor_stmt);
}
bool on_after_expr_parsing(THD *) override
@ -1452,16 +1469,7 @@ public:
protected:
LEX_CSTRING get_expr_query() const override
{
/*
Lexer on processing the clause CURSOR FOR / CURSOR IS doesn't
move a pointer on cpp_buf after the token FOR/IS so skip it explicitly
in order to get correct value of cursor's query string.
*/
if (strncasecmp(m_cursor_stmt.str, "FOR ", 4) == 0)
return LEX_CSTRING{m_cursor_stmt.str + 4, m_cursor_stmt.length - 4};
if (strncasecmp(m_cursor_stmt.str, "IS ", 3) == 0)
return LEX_CSTRING{m_cursor_stmt.str + 3, m_cursor_stmt.length - 3};
return m_cursor_stmt;
return get_cursor_query(m_cursor_stmt);
}
bool on_after_expr_parsing(THD *) override