1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

MDEV-36047 Package body variables are not allowed as FETCH targets

It was not possible to use a package body variable as a
fetch target:

CREATE PACKAGE BODY pkg AS
  vc INT := 0;
  FUNCTION f1 RETURN INT AS
    CURSOR cur IS SELECT 1 AS c FROM DUAL;
  BEGIN
    OPEN cur;
    FETCH cur INTO vc; -- this returned "Undeclared variable: vc" error.
    CLOSE cur;
    RETURN vc;
  END;
END;

FETCH assumed that all fetch targets reside of the same sp_rcontext
instance with the cursor. This patch fixes the problem.
Now a cursor and its fetch target can reside in different sp_rcontext
instances.

Details:

- Adding a helper class sp_rcontext_addr
  (a combination of Sp_rcontext_handler pointer and an offset in the rcontext)

- Adding a new class sp_fetch_target deriving from sp_rcontext_addr.
  Fetch targets in "FETCH cur INTO target1, target2 ..." are now collected
  into this structure instead of sp_variable.
  sp_variable cannot be used any more to store fetch targets,
  because it does not have a pointer to Sp_rcontext_handler
  (it only has the current rcontext offset).

- Removing members sp_instr_set members m_rcontext_handler and m_offset.
  Deriving sp_instr_set from sp_rcontext_addr instead.

- Renaming sp_instr_cfetch member  "List<sp_variable> m_varlist"
  to "List<sp_fetch_target> m_fetch_target_list".

- Fixing LEX::sp_add_cfetch() to return the pointer to the
  created sp_fetch_target instance (instead of returning bool).
  This helps to make the grammar in sql_yacc.c simpler

- Renaming LEX::sp_add_cfetch() to LEX::sp_add_instr_cfetch(),
  as `if(sp_add_cfetch())` changed its meaning to the opposite,
  to avoid automatic wrong merge from earlier versions.

- Chaning the "List<sp_variable> *vars" parameter to sp_cursor::fetch
  to have the data type "List<sp_fetch_target> *".

- Changing the data type of "List<sp_variable> &vars" in
  sp_cursor::Select_fetch_into_spvars::send_data_to_variable_list()
  to "List<sp_fetch_target> &".

- Adding THD helper methods get_rcontext() and get_variable().

- Moving the code from sql_yacc.yy into a new LEX method
  LEX::make_fetch_target().

- Simplifying the grammar in sql_yacc.yy using the new LEX method.
  Changing the data type of the bison rule sp_fetch_list from "void"
  to "List<sp_fetch_target> *".
This commit is contained in:
Alexander Barkov
2025-02-08 17:39:27 +04:00
parent 6be0940f10
commit b7d67ceb5f
25 changed files with 731 additions and 72 deletions

View File

@@ -591,7 +591,8 @@ public:
}; // class sp_instr_stmt : public sp_lex_instr
class sp_instr_set : public sp_lex_instr
class sp_instr_set : public sp_lex_instr,
public sp_rcontext_addr
{
sp_instr_set(const sp_instr_set &); /**< Prevent use of these */
void operator=(sp_instr_set &);
@@ -603,8 +604,7 @@ public:
LEX *lex, bool lex_resp,
const LEX_CSTRING &expr_str)
: sp_lex_instr(ip, ctx, lex, lex_resp),
m_rcontext_handler(rh),
m_offset(offset),
sp_rcontext_addr(rh, offset),
m_value(val),
m_expr_str(expr_str)
{}
@@ -651,8 +651,6 @@ protected:
}
sp_rcontext *get_rcontext(THD *thd) const;
const Sp_rcontext_handler *m_rcontext_handler;
uint m_offset; ///< Frame offset
Item *m_value;
private:
@@ -1490,7 +1488,7 @@ public:
m_cursor(c),
m_error_on_no_data(error_on_no_data)
{
m_varlist.empty();
m_fetch_target_list.empty();
}
virtual ~sp_instr_cfetch() = default;
@@ -1499,14 +1497,19 @@ public:
void print(String *str) override;
void add_to_varlist(sp_variable *var)
bool add_to_fetch_target_list(sp_fetch_target *target)
{
m_varlist.push_back(var);
return m_fetch_target_list.push_back(target);
}
void set_fetch_target_list(List<sp_fetch_target> *list)
{
m_fetch_target_list= *list;
}
private:
uint m_cursor;
List<sp_variable> m_varlist;
List<sp_fetch_target> m_fetch_target_list;
bool m_error_on_no_data;
public: