Loading include/my_sys.h +3 −0 Original line number Diff line number Diff line Loading @@ -90,6 +90,9 @@ extern int NEAR my_errno; /* Last error in mysys */ #define ME_COLOUR1 ((1 << ME_HIGHBYTE)) /* Possibly error-colours */ #define ME_COLOUR2 ((2 << ME_HIGHBYTE)) #define ME_COLOUR3 ((3 << ME_HIGHBYTE)) #define ME_FATALERROR 1024 /* Fatal statement error */ #define ME_NO_WARNING_FOR_ERROR 2048 /* Don't push a warning for error */ #define ME_NO_SP_HANDLER 4096 /* Don't call stored routine error handlers */ /* Bits in last argument to fn_format */ #define MY_REPLACE_DIR 1 /* replace dir in name with 'dir' */ Loading sql/item.cc +8 −4 Original line number Diff line number Diff line Loading @@ -3165,15 +3165,19 @@ void Item_param::print(String *str, enum_query_type query_type) Preserve the original parameter types and values when re-preparing a prepared statement. Copy parameter type information and conversion function pointers from a parameter of the old statement to the corresponding parameter of the new one. @details Copy parameter type information and conversion function pointers from a parameter of the old statement to the corresponding parameter of the new one. Move parameter values from the old parameters to the new one. We simply "exchange" the values, which allows to save on allocation and character set conversion in case a parameter is a string or a blob/clob. The old parameter gets the value of this one, which ensures that all memory of this parameter is freed correctly. @param[in] src parameter item of the original prepared statement */ Loading @@ -3187,7 +3191,7 @@ Item_param::set_param_type_and_swap_value(Item_param *src) item_type= src->item_type; item_result_type= src->item_result_type; collation.set(src->collation.collation); collation.set(src->collation); maybe_null= src->maybe_null; null_value= src->null_value; max_length= src->max_length; Loading sql/mysqld.cc +3 −1 Original line number Diff line number Diff line Loading @@ -2843,6 +2843,7 @@ int my_message_sql(uint error, const char *str, myf MyFlags) by the stored procedures code. */ if (thd->spcont && ! (MyFlags & ME_NO_SP_HANDLER) && thd->spcont->handle_error(error, MYSQL_ERROR::WARN_LEVEL_ERROR, thd)) { /* Loading @@ -2852,7 +2853,8 @@ int my_message_sql(uint error, const char *str, myf MyFlags) DBUG_RETURN(0); } if (!thd->no_warnings_for_error) if (!thd->no_warnings_for_error && !(MyFlags & ME_NO_WARNING_FOR_ERROR)) { /* Suppress infinite recursion if there a memory allocation error Loading sql/sql_base.cc +14 −9 Original line number Diff line number Diff line Loading @@ -3722,9 +3722,8 @@ void assign_new_table_id(TABLE_SHARE *share) Compare metadata versions of an element obtained from the table definition cache and its corresponding node in the parse tree. If the new and the old values mismatch, invoke @details If the new and the old values mismatch, invoke Metadata_version_observer. At prepared statement prepare, all TABLE_LIST version values are NULL and we always have a mismatch. But there is no observer set in THD, and therefore no error is reported. Instead, we update Loading @@ -3738,8 +3737,8 @@ void assign_new_table_id(TABLE_SHARE *share) @sa Execute_observer @sa check_prepared_statement() to see cases when an observer is installed @sa TABLE_LIST::is_metadata_version_equal() @sa TABLE_SHARE::get_metadata_version() @sa TABLE_LIST::is_metadata_id_equal() @sa TABLE_SHARE::get_metadata_id() @param[in] thd used to report errors @param[in,out] tables TABLE_LIST instance created by the parser Loading @@ -3755,27 +3754,28 @@ bool check_and_update_table_version(THD *thd, TABLE_LIST *tables, TABLE_SHARE *table_share) { if (! tables->is_metadata_version_equal(table_share)) if (! tables->is_metadata_id_equal(table_share)) { if (thd->m_metadata_observer && thd->m_metadata_observer->check_metadata_change(thd)) thd->m_metadata_observer->report_error(thd)) { /* Version of the table share is different from the previous execution of the prepared statement, and it is unacceptable for this SQLCOM. Error has been reported. */ DBUG_ASSERT(thd->is_error()); return TRUE; } /* Always maintain the latest version */ tables->set_metadata_version(table_share); /* Always maintain the latest version and type */ tables->set_metadata_id(table_share); } #if 0 #ifndef DBUG_OFF /* Spuriously reprepare each statement. */ if (thd->m_metadata_observer && thd->stmt_arena->is_reprepared == FALSE) { thd->m_metadata_observer->check_metadata_change(thd); thd->m_metadata_observer->report_error(thd); return TRUE; } #endif Loading Loading @@ -3828,6 +3828,10 @@ static int open_unireg_entry(THD *thd, TABLE *entry, TABLE_LIST *table_list, if (share->is_view) { /* This table is a view. Validate its metadata version: in particular, that it was a view when the statement was prepared. */ if (check_and_update_table_version(thd, table_list, share)) goto err; if (table_list->i_s_requested_object & OPEN_TABLE_ONLY) Loading Loading @@ -4622,6 +4626,7 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags) } tables->table->grant= tables->grant; /* Check and update metadata version of a base table. */ if (check_and_update_table_version(thd, tables, tables->table->s)) { result= -1; Loading sql/sql_class.h +15 −3 Original line number Diff line number Diff line Loading @@ -57,16 +57,15 @@ class Metadata_version_observer { protected: virtual ~Metadata_version_observer(); public: virtual ~Metadata_version_observer(); /** Check if a change of metadata is OK. In future the signature of this method may be extended to accept the old and the new versions, but since currently the check is very simple, we only need the THD to report an error. */ virtual bool check_metadata_change(THD *thd)= 0; virtual bool report_error(THD *thd)= 0; }; Loading Loading @@ -2842,6 +2841,19 @@ class select_dumpvar :public select_result_interceptor { #define CF_STATUS_COMMAND 4 #define CF_SHOW_TABLE_COMMAND 8 #define CF_WRITE_LOGS_COMMAND 16 /** Must be set for SQL statements that may contain Item expressions and/or use joins and tables. Indicates that the parse tree of such statement may contain rule-based optimizations that depend on metadata (i.e. number of columns in a table), and consequently that the statement must be re-prepared whenever referenced metadata changes. Must not be set for statements that themselves change metadata, e.g. RENAME, ALTER and other DDL, since otherwise will trigger constant reprepare. Consequently, complex item expressions and joins are currently prohibited in these statements. */ #define CF_REEXECUTION_FRAGILE 32 /* Functions in sql_class.cc */ Loading Loading
include/my_sys.h +3 −0 Original line number Diff line number Diff line Loading @@ -90,6 +90,9 @@ extern int NEAR my_errno; /* Last error in mysys */ #define ME_COLOUR1 ((1 << ME_HIGHBYTE)) /* Possibly error-colours */ #define ME_COLOUR2 ((2 << ME_HIGHBYTE)) #define ME_COLOUR3 ((3 << ME_HIGHBYTE)) #define ME_FATALERROR 1024 /* Fatal statement error */ #define ME_NO_WARNING_FOR_ERROR 2048 /* Don't push a warning for error */ #define ME_NO_SP_HANDLER 4096 /* Don't call stored routine error handlers */ /* Bits in last argument to fn_format */ #define MY_REPLACE_DIR 1 /* replace dir in name with 'dir' */ Loading
sql/item.cc +8 −4 Original line number Diff line number Diff line Loading @@ -3165,15 +3165,19 @@ void Item_param::print(String *str, enum_query_type query_type) Preserve the original parameter types and values when re-preparing a prepared statement. Copy parameter type information and conversion function pointers from a parameter of the old statement to the corresponding parameter of the new one. @details Copy parameter type information and conversion function pointers from a parameter of the old statement to the corresponding parameter of the new one. Move parameter values from the old parameters to the new one. We simply "exchange" the values, which allows to save on allocation and character set conversion in case a parameter is a string or a blob/clob. The old parameter gets the value of this one, which ensures that all memory of this parameter is freed correctly. @param[in] src parameter item of the original prepared statement */ Loading @@ -3187,7 +3191,7 @@ Item_param::set_param_type_and_swap_value(Item_param *src) item_type= src->item_type; item_result_type= src->item_result_type; collation.set(src->collation.collation); collation.set(src->collation); maybe_null= src->maybe_null; null_value= src->null_value; max_length= src->max_length; Loading
sql/mysqld.cc +3 −1 Original line number Diff line number Diff line Loading @@ -2843,6 +2843,7 @@ int my_message_sql(uint error, const char *str, myf MyFlags) by the stored procedures code. */ if (thd->spcont && ! (MyFlags & ME_NO_SP_HANDLER) && thd->spcont->handle_error(error, MYSQL_ERROR::WARN_LEVEL_ERROR, thd)) { /* Loading @@ -2852,7 +2853,8 @@ int my_message_sql(uint error, const char *str, myf MyFlags) DBUG_RETURN(0); } if (!thd->no_warnings_for_error) if (!thd->no_warnings_for_error && !(MyFlags & ME_NO_WARNING_FOR_ERROR)) { /* Suppress infinite recursion if there a memory allocation error Loading
sql/sql_base.cc +14 −9 Original line number Diff line number Diff line Loading @@ -3722,9 +3722,8 @@ void assign_new_table_id(TABLE_SHARE *share) Compare metadata versions of an element obtained from the table definition cache and its corresponding node in the parse tree. If the new and the old values mismatch, invoke @details If the new and the old values mismatch, invoke Metadata_version_observer. At prepared statement prepare, all TABLE_LIST version values are NULL and we always have a mismatch. But there is no observer set in THD, and therefore no error is reported. Instead, we update Loading @@ -3738,8 +3737,8 @@ void assign_new_table_id(TABLE_SHARE *share) @sa Execute_observer @sa check_prepared_statement() to see cases when an observer is installed @sa TABLE_LIST::is_metadata_version_equal() @sa TABLE_SHARE::get_metadata_version() @sa TABLE_LIST::is_metadata_id_equal() @sa TABLE_SHARE::get_metadata_id() @param[in] thd used to report errors @param[in,out] tables TABLE_LIST instance created by the parser Loading @@ -3755,27 +3754,28 @@ bool check_and_update_table_version(THD *thd, TABLE_LIST *tables, TABLE_SHARE *table_share) { if (! tables->is_metadata_version_equal(table_share)) if (! tables->is_metadata_id_equal(table_share)) { if (thd->m_metadata_observer && thd->m_metadata_observer->check_metadata_change(thd)) thd->m_metadata_observer->report_error(thd)) { /* Version of the table share is different from the previous execution of the prepared statement, and it is unacceptable for this SQLCOM. Error has been reported. */ DBUG_ASSERT(thd->is_error()); return TRUE; } /* Always maintain the latest version */ tables->set_metadata_version(table_share); /* Always maintain the latest version and type */ tables->set_metadata_id(table_share); } #if 0 #ifndef DBUG_OFF /* Spuriously reprepare each statement. */ if (thd->m_metadata_observer && thd->stmt_arena->is_reprepared == FALSE) { thd->m_metadata_observer->check_metadata_change(thd); thd->m_metadata_observer->report_error(thd); return TRUE; } #endif Loading Loading @@ -3828,6 +3828,10 @@ static int open_unireg_entry(THD *thd, TABLE *entry, TABLE_LIST *table_list, if (share->is_view) { /* This table is a view. Validate its metadata version: in particular, that it was a view when the statement was prepared. */ if (check_and_update_table_version(thd, table_list, share)) goto err; if (table_list->i_s_requested_object & OPEN_TABLE_ONLY) Loading Loading @@ -4622,6 +4626,7 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags) } tables->table->grant= tables->grant; /* Check and update metadata version of a base table. */ if (check_and_update_table_version(thd, tables, tables->table->s)) { result= -1; Loading
sql/sql_class.h +15 −3 Original line number Diff line number Diff line Loading @@ -57,16 +57,15 @@ class Metadata_version_observer { protected: virtual ~Metadata_version_observer(); public: virtual ~Metadata_version_observer(); /** Check if a change of metadata is OK. In future the signature of this method may be extended to accept the old and the new versions, but since currently the check is very simple, we only need the THD to report an error. */ virtual bool check_metadata_change(THD *thd)= 0; virtual bool report_error(THD *thd)= 0; }; Loading Loading @@ -2842,6 +2841,19 @@ class select_dumpvar :public select_result_interceptor { #define CF_STATUS_COMMAND 4 #define CF_SHOW_TABLE_COMMAND 8 #define CF_WRITE_LOGS_COMMAND 16 /** Must be set for SQL statements that may contain Item expressions and/or use joins and tables. Indicates that the parse tree of such statement may contain rule-based optimizations that depend on metadata (i.e. number of columns in a table), and consequently that the statement must be re-prepared whenever referenced metadata changes. Must not be set for statements that themselves change metadata, e.g. RENAME, ALTER and other DDL, since otherwise will trigger constant reprepare. Consequently, complex item expressions and joins are currently prohibited in these statements. */ #define CF_REEXECUTION_FRAGILE 32 /* Functions in sql_class.cc */ Loading