1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-29 05:21:33 +03:00

MDEV-20034 Add support for the pre-defined weak SYS_REFCURSOR

This patch adds support for SYS_REFCURSOR (a weakly typed cursor)
for both sql_mode=ORACLE and sql_mode=DEFAULT.

Works as a regular stored routine variable, parameter and return value:

- can be passed as an IN parameter to stored functions and procedures
- can be passed as an INOUT and OUT parameter to stored procedures
- can be returned from a stored function

Note, strongly typed REF CURSOR will be added separately.

Note, to maintain dependencies easier, some parts of sql_class.h
and item.h were moved to new header files:

- select_results.h:
  class select_result_sink
  class select_result
  class select_result_interceptor

- sp_cursor.h:
  class sp_cursor_statistics
  class sp_cursor

- sp_rcontext_handler.h
  class Sp_rcontext_handler and its descendants

The implementation consists of the following parts:
- A new class sp_cursor_array deriving from Dynamic_array

- A new class Statement_rcontext which contains data shared
  between sub-statements of a compound statement.
  It has a member m_statement_cursors of the sp_cursor_array data type,
  as well as open cursor counter. THD inherits from Statement_rcontext.

- A new data type handler Type_handler_sys_refcursor in plugins/type_cursor/
  It is designed to store uint16 references -
  positions of the cursor in THD::m_statement_cursors.

- Type_handler_sys_refcursor suppresses some derived numeric features.
  When a SYS_REFCURSOR variable is used as an integer an error is raised.

- A new abstract class sp_instr_fetch_cursor. It's needed to share
  the common code between "OPEN cur" (for static cursors) and
  "OPER cur FOR stmt" (for SYS_REFCURSORs).

- New sp_instr classes:
  * sp_instr_copen_by_ref      - OPEN sys_ref_curor FOR stmt;
  * sp_instr_cfetch_by_ref     - FETCH sys_ref_cursor INTO targets;
  * sp_instr_cclose_by_ref     - CLOSE sys_ref_cursor;
  * sp_instr_destruct_variable - to destruct SYS_REFCURSOR variables when
                                 the execution goes out of the BEGIN..END block
                                 where SYS_REFCURSOR variables are declared.
- New methods in LEX:
  * sp_open_cursor_for_stmt   - handles "OPEN sys_ref_cursor FOR stmt".
  * sp_add_instr_fetch_cursor - "FETCH cur INTO targets" for both
                                static cursors and SYS_REFCURSORs.
  * sp_close - handles "CLOSE cur" both for static cursors and SYS_REFCURSORs.

- Changes in cursor functions to handle both static cursors and SYS_REFCURSORs:
  * Item_func_cursor_isopen
  * Item_func_cursor_found
  * Item_func_cursor_notfound
  * Item_func_cursor_rowcount

- A new system variable @@max_open_cursors - to limit the number
  of cursors (static and SYS_REFCURSORs) opened at the same time.
  Its allowed range is [0-65536], with 50 by default.

- A new virtual method Type_handler::can_return_bool() telling
  if calling item->val_bool() is allowed for Items of this data type,
  or if otherwise the "Illegal parameter for operation" error should be raised
  at fix_fields() time.

- New methods in Sp_rcontext_handler:
  * get_cursor()
  * get_cursor_by_ref()

- A new class Sp_rcontext_handler_statement to handle top level statement
  wide cursors which are shared by all substatements.

- A new virtual method expr_event_handler() in classes Item and Field.
  It's needed to close (and make available for a new OPEN)
  unused THD::m_statement_cursors elements which do not have any references
  any more. It can happen in various moments in time, e.g.
  * after evaluation parameters of an SQL routine
  * after assigning a cursor expression into a SYS_REFCURSOR variable
  * when leaving a BEGIN..END block with SYS_REFCURSOR variables
  * after setting OUT/INOUT routine actual parameters from formal
    parameters.
This commit is contained in:
Alexander Barkov
2023-09-14 07:01:32 +04:00
parent 1e00b9ec2a
commit f11504af51
183 changed files with 16896 additions and 536 deletions

View File

@ -25,6 +25,7 @@
#include "sql_time.h"
#include "sql_type_string.h"
#include "sql_type_real.h"
#include "sql_type_ref.h"
#include "compat56.h"
#include "log_event_data_type.h"
@ -52,6 +53,8 @@ class Item_func_hex;
class Item_hybrid_func;
class Item_func_min_max;
class Item_func_hybrid_field_type;
class Item_func_last_value;
class Item_func_sp;
class Item_bool_func2;
class Item_bool_rowready_func2;
class Item_func_between;
@ -157,6 +160,57 @@ scalar_comparison_op_to_lex_cstring(scalar_comparison_op op)
}
enum class expr_event_t : uint32
{
NONE= 0,
/*
A result set row has been sent to the result sink, e.g. to the client.
All values in the row are not needed any more.
*/
DESTRUCT_RESULT_SET_ROW_FIELD= 1 << 0,
/*
An Item_func evaluated its result,
argument values are not needed any more.
*/
DESTRUCT_ROUTINE_ARG= 1 << 1,
/*
A value has been assigned to an SP variable.
*/
DESTRUCT_ASSIGNMENT_RIGHT_HAND= 1 << 2,
/*
Flow control has left a BEGIN..END block,
all variables declared in this block are not needed any more.
*/
DESTRUCT_OUT_OF_SCOPE= 1 << 3,
/*
A prepared statement has finished.
The values of Item_param instances are not needed any more.
*/
DESTRUCT_DYNAMIC_PARAM= 1 << 4,
/*
Any kind of destruction listed above.
*/
DESTRUCT_ANY= (uint32) (DESTRUCT_RESULT_SET_ROW_FIELD |
DESTRUCT_ROUTINE_ARG |
DESTRUCT_ASSIGNMENT_RIGHT_HAND |
DESTRUCT_OUT_OF_SCOPE |
DESTRUCT_DYNAMIC_PARAM)
};
static inline constexpr expr_event_t operator&(const expr_event_t a,
const expr_event_t b)
{
return (expr_event_t) (((uint32) a) & ((uint32) b));
}
class Hasher
{
ulong m_nr1;
@ -4065,6 +4119,18 @@ public:
{
return this;
}
/*
Returns true if this data type is complex (has some side effect),
so values of this type need additional handling, e.g. on destruction.
For example, SYS_REFCURSOR has a side effect:
it writes and reads THD::m_statement_cursors.
*/
virtual bool is_complex() const
{
return false;
}
virtual bool partition_field_check(const LEX_CSTRING &field_name, Item *)
const
{
@ -4083,6 +4149,15 @@ public:
type_handler_adjusted_to_max_octet_length(uint max_octet_length,
CHARSET_INFO *cs) const
{ return this; }
/*
Check if an Spvar_definition instance is of a complex data type,
or contains a complex data type in its components (e.g. a ROW member).
*/
virtual bool Spvar_definition_with_complex_data_types(Spvar_definition *def)
const
{
return false;
}
virtual bool adjust_spparam_type(Spvar_definition *def, Item *from) const
{
return false;
@ -4095,6 +4170,7 @@ public:
*/
bool is_traditional_scalar_type() const;
virtual bool is_scalar_type() const { return true; }
virtual bool can_return_bool() const { return can_return_int(); }
virtual bool can_return_int() const { return true; }
virtual bool can_return_decimal() const { return true; }
virtual bool can_return_real() const { return true; }
@ -4338,6 +4414,9 @@ public:
virtual void Item_param_setup_conversion(THD *thd, Item_param *) const {}
virtual void Item_param_set_param_func(Item_param *param,
uchar **pos, ulong len) const;
virtual void Item_param_expr_event_handler(THD *thd, Item_param *param,
expr_event_t event) const
{ }
virtual bool Item_param_set_from_value(THD *thd,
Item_param *param,
const Type_all_attributes *attr,
@ -4345,6 +4424,12 @@ public:
virtual bool Item_param_val_native(THD *thd,
Item_param *item,
Native *to) const;
virtual Type_ref_null Item_param_val_ref(THD *thd, const Item_param *item)
const
{
return Type_ref_null();
}
virtual bool Item_send(Item *item, Protocol *p, st_value *buf) const= 0;
virtual int Item_save_in_field(Item *item, Field *field,
bool no_conversions) const= 0;
@ -4581,6 +4666,10 @@ public:
MYSQL_TIME *,
date_mode_t) const;
virtual
Type_ref_null Item_func_hybrid_field_type_val_ref(THD *thd,
Item_func_hybrid_field_type *item)
const;
virtual
String *Item_func_min_max_val_str(Item_func_min_max *, String *) const= 0;
virtual
double Item_func_min_max_val_real(Item_func_min_max *) const= 0;
@ -4753,6 +4842,9 @@ public:
{
return false;
}
bool Spvar_definition_with_complex_data_types(Spvar_definition *def)
const override;
Field *make_table_field(MEM_ROOT *, const LEX_CSTRING *, const Record_addr &,
const Type_all_attributes &, TABLE_SHARE *)
const override
@ -7902,7 +7994,7 @@ extern MYSQL_PLUGIN_IMPORT Named_type_handler<Type_handler_long_ge0> type_han
extern MYSQL_PLUGIN_IMPORT Named_type_handler<Type_handler_longlong> type_handler_slonglong;
extern Named_type_handler<Type_handler_utiny> type_handler_utiny;
extern Named_type_handler<Type_handler_ushort> type_handler_ushort;
extern MYSQL_PLUGIN_IMPORT Named_type_handler<Type_handler_ushort> type_handler_ushort;
extern Named_type_handler<Type_handler_uint24> type_handler_uint24;
extern MYSQL_PLUGIN_IMPORT Named_type_handler<Type_handler_ulong> type_handler_ulong;
extern MYSQL_PLUGIN_IMPORT Named_type_handler<Type_handler_ulonglong> type_handler_ulonglong;