Hi Alexander,
On 3/22/11 11:36 AM, Alexander Nozdrin wrote:
> #At file:///home/alik/MySQL/bzr/00/bug55847/mysql-trunk-bug55847/ based on
> revid:vinay.fisrekar@stripped
>
> 3306 Alexander Nozdrin 2011-03-22
> A patch for Bug#11763166 (55847: SHOW WARNINGS returns empty
> result set when SQLEXCEPTION is active.
>
> The problem was in a hackish THD::no_warnings_for_error attribute.
> When it was set, an error was not written to Warning_info -- only
> Diagnostics_area state was changed. That means, Diagnostics_area
> might contain error state, which is not present in Warning_info.
>
> The user-visible problem was that in some cases SHOW WARNINGS
> returned empty result set (i.e. there were no warnings) while
> the previous SQL statement failed. According to the MySQL
> protocol errors must be presented in warning list.
>
> The fix is to remove THD::no_warnings_for_error.
>
Overall, it looks good. Only a single request below.
[...]
>
>
> +/**
> + Fill INFORMATION_SCHEMA-table, leave correct Diagnostics_area /
> + Warning_info state after itself.
> +
> + This function is a wrapper around ST_SCHEMA_TABLE::fill_table(), which
> + may "partially silence" some errors. The thing is that during
> + fill_table() many errors might be emitted. These errors stem from the
> + nature of fill_table().
> +
> + For example, SELECT ... FROM INFORMATION_SCHEMA.xxx WHERE TABLE_NAME = 'xxx'
> + results in a number of 'Table<db name>.xxx does not exist' errors,
> + because fill_table() tries to open the 'xxx' table in every possible
> + database.
> +
> + Those errors are cleared (the error status is cleared from
> + Diagnostics_area) inside fill_table(), but they remain in Warning_info
> + (Warning_info is not cleared because it may contain useful warnings).
> +
> + THD::no_warnings_for_error used to be set before calling fill_table(),
> + thus those errors didn't go to Warning_info. This is not the case now
> + (THD::no_warnings_for_error was eliminated as a hack), so we need to take
> + care of those warnings here.
> +
> + @param thd Thread context.
> + @param table_list I_S table.
> + @param join_table JOIN/SELECT table.
> +
> + @return Error status.
> + @retval TRUE Error.
> + @retval FALSE Success.
> +*/
> +static bool do_fill_table(THD *thd,
> + TABLE_LIST *table_list,
> + JOIN_TAB *join_table)
> +{
> + Warning_info wi(thd->query_id);
> + Warning_info *wi_saved= thd->warning_info;
> +
> + thd->warning_info=&wi;
> +
> + bool res= table_list->schema_table->fill_table(
> + thd, table_list, join_table->select_cond);
> +
> + thd->warning_info= wi_saved;
> +
> + // Pass an error if any.
> +
> + if (thd->stmt_da->is_error())
> + {
> + thd->warning_info->push_warning(thd,
> + thd->stmt_da->sql_errno(),
> + thd->stmt_da->get_sqlstate(),
> + MYSQL_ERROR::WARN_LEVEL_ERROR,
> + thd->stmt_da->message());
> + }
> +
> + // Pass warnings (if any).
> + //
> + // Filter out warnings with WARN_LEVEL_ERROR level, because they
> + // correspond to the errors which were filtered out in fill_table().
> +
Please investigate whether this logic can be implemented with a handler.
It seems all we have to allow is any condition which is not a error
(that is, a warning or note) and only allow a error condition only if
the diagnostics area state is not set yet.
Regards,
Davi