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:
@ -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;
|
||||
|
Reference in New Issue
Block a user