Commit 52efe3e0 authored by Alexander Nozdrin's avatar Alexander Nozdrin

Preliminary patch for Bug#11848763 / 60025

(SUBSTRING inside a stored function works too slow).

Background:
  - THD classes derives from Query_arena, thus inherits the 'state'
    attribute and related operations (is_stmt_prepare() & co).

  - Although these operations are available in THD, they must not
    be used. THD has its own attribute to point to the active
    Query_arena -- stmt_arena.

  - So, instead of using thd->is_stmt_prepare(),
    thd->stmt_arena->is_stmt_prepare() must be used. This was the root
    cause of Bug 60025.

This patch enforces the proper way of calling those operations.
is_stmt_prepare() & co are declared as private operations
in THD (thus, they are hidden from being called on THD instance).

The patch tries to minimize changes in 5.5.
parent 167d2896
...@@ -581,7 +581,7 @@ void Item::rename(char *new_name) ...@@ -581,7 +581,7 @@ void Item::rename(char *new_name)
Item* Item::transform(Item_transformer transformer, uchar *arg) Item* Item::transform(Item_transformer transformer, uchar *arg)
{ {
DBUG_ASSERT(!current_thd->is_stmt_prepare()); DBUG_ASSERT(!current_thd->stmt_arena->is_stmt_prepare());
return (this->*transformer)(arg); return (this->*transformer)(arg);
} }
...@@ -1845,7 +1845,7 @@ bool agg_item_set_converter(DTCollation &coll, const char *fname, ...@@ -1845,7 +1845,7 @@ bool agg_item_set_converter(DTCollation &coll, const char *fname,
been created in prepare. In this case register the change for been created in prepare. In this case register the change for
rollback. rollback.
*/ */
if (thd->is_stmt_prepare()) if (thd->stmt_arena->is_stmt_prepare())
*arg= conv; *arg= conv;
else else
thd->change_item_tree(arg, conv); thd->change_item_tree(arg, conv);
...@@ -6965,7 +6965,7 @@ int Item_default_value::save_in_field(Field *field_arg, bool no_conversions) ...@@ -6965,7 +6965,7 @@ int Item_default_value::save_in_field(Field *field_arg, bool no_conversions)
Item *Item_default_value::transform(Item_transformer transformer, uchar *args) Item *Item_default_value::transform(Item_transformer transformer, uchar *args)
{ {
DBUG_ASSERT(!current_thd->is_stmt_prepare()); DBUG_ASSERT(!current_thd->stmt_arena->is_stmt_prepare());
/* /*
If the value of arg is NULL, then this object represents a constant, If the value of arg is NULL, then this object represents a constant,
......
...@@ -4345,7 +4345,7 @@ bool Item_cond::walk(Item_processor processor, bool walk_subquery, uchar *arg) ...@@ -4345,7 +4345,7 @@ bool Item_cond::walk(Item_processor processor, bool walk_subquery, uchar *arg)
Item *Item_cond::transform(Item_transformer transformer, uchar *arg) Item *Item_cond::transform(Item_transformer transformer, uchar *arg)
{ {
DBUG_ASSERT(!current_thd->is_stmt_prepare()); DBUG_ASSERT(!current_thd->stmt_arena->is_stmt_prepare());
List_iterator<Item> li(list); List_iterator<Item> li(list);
Item *item; Item *item;
...@@ -5718,7 +5718,7 @@ bool Item_equal::walk(Item_processor processor, bool walk_subquery, uchar *arg) ...@@ -5718,7 +5718,7 @@ bool Item_equal::walk(Item_processor processor, bool walk_subquery, uchar *arg)
Item *Item_equal::transform(Item_transformer transformer, uchar *arg) Item *Item_equal::transform(Item_transformer transformer, uchar *arg)
{ {
DBUG_ASSERT(!current_thd->is_stmt_prepare()); DBUG_ASSERT(!current_thd->stmt_arena->is_stmt_prepare());
List_iterator<Item_field> it(fields); List_iterator<Item_field> it(fields);
Item *item; Item *item;
......
...@@ -293,7 +293,7 @@ void Item_func::traverse_cond(Cond_traverser traverser, ...@@ -293,7 +293,7 @@ void Item_func::traverse_cond(Cond_traverser traverser,
Item *Item_func::transform(Item_transformer transformer, uchar *argument) Item *Item_func::transform(Item_transformer transformer, uchar *argument)
{ {
DBUG_ASSERT(!current_thd->is_stmt_prepare()); DBUG_ASSERT(!current_thd->stmt_arena->is_stmt_prepare());
if (arg_count) if (arg_count)
{ {
......
...@@ -170,7 +170,7 @@ bool Item_row::walk(Item_processor processor, bool walk_subquery, uchar *arg) ...@@ -170,7 +170,7 @@ bool Item_row::walk(Item_processor processor, bool walk_subquery, uchar *arg)
Item *Item_row::transform(Item_transformer transformer, uchar *arg) Item *Item_row::transform(Item_transformer transformer, uchar *arg)
{ {
DBUG_ASSERT(!current_thd->is_stmt_prepare()); DBUG_ASSERT(!current_thd->stmt_arena->is_stmt_prepare());
for (uint i= 0; i < arg_count; i++) for (uint i= 0; i < arg_count; i++)
{ {
......
...@@ -2536,7 +2536,7 @@ String *Item_func_make_set::val_str(String *str) ...@@ -2536,7 +2536,7 @@ String *Item_func_make_set::val_str(String *str)
Item *Item_func_make_set::transform(Item_transformer transformer, uchar *arg) Item *Item_func_make_set::transform(Item_transformer transformer, uchar *arg)
{ {
DBUG_ASSERT(!current_thd->is_stmt_prepare()); DBUG_ASSERT(!current_thd->stmt_arena->is_stmt_prepare());
Item *new_item= item->transform(transformer, arg); Item *new_item= item->transform(transformer, arg);
if (!new_item) if (!new_item)
......
...@@ -655,15 +655,10 @@ public: ...@@ -655,15 +655,10 @@ public:
virtual ~Query_arena() {}; virtual ~Query_arena() {};
inline bool is_stmt_prepare() const { return state == INITIALIZED; } inline bool is_stmt_prepare() const { return state == INITIALIZED; }
inline bool is_first_sp_execute() const
{ return state == INITIALIZED_FOR_SP; }
inline bool is_stmt_prepare_or_first_sp_execute() const inline bool is_stmt_prepare_or_first_sp_execute() const
{ return (int)state < (int)PREPARED; } { return (int)state < (int)PREPARED; }
inline bool is_stmt_prepare_or_first_stmt_execute() const inline bool is_stmt_prepare_or_first_stmt_execute() const
{ return (int)state <= (int)PREPARED; } { return (int)state <= (int)PREPARED; }
inline bool is_first_stmt_execute() const { return state == PREPARED; }
inline bool is_stmt_execute() const
{ return state == PREPARED || state == EXECUTED; }
inline bool is_conventional() const inline bool is_conventional() const
{ return state == CONVENTIONAL_EXECUTION; } { return state == CONVENTIONAL_EXECUTION; }
...@@ -1434,6 +1429,19 @@ extern "C" void my_message_sql(uint error, const char *str, myf MyFlags); ...@@ -1434,6 +1429,19 @@ extern "C" void my_message_sql(uint error, const char *str, myf MyFlags);
class THD :public Statement, class THD :public Statement,
public Open_tables_state public Open_tables_state
{ {
private:
inline bool is_stmt_prepare() const
{ DBUG_ASSERT(0); return Statement::is_stmt_prepare(); }
inline bool is_stmt_prepare_or_first_sp_execute() const
{ DBUG_ASSERT(0); return Statement::is_stmt_prepare_or_first_sp_execute(); }
inline bool is_stmt_prepare_or_first_stmt_execute() const
{ DBUG_ASSERT(0); return Statement::is_stmt_prepare_or_first_stmt_execute(); }
inline bool is_conventional() const
{ DBUG_ASSERT(0); return Statement::is_conventional(); }
public: public:
MDL_context mdl_context; MDL_context mdl_context;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment