mirror of
https://github.com/MariaDB/server.git
synced 2025-05-25 13:42:52 +03:00
Base code and idea from a patch from by plinux at Taobao. The idea is that we mark all memory that are thread specific with MY_THREAD_SPECIFIC. Memory counting is done per thread in the my_malloc_size_cb_func callback function from my_malloc(). There are plenty of new asserts to ensure that for a debug server the counting is correct. Information_schema.processlist gets two new columns: MEMORY_USED and EXAMINED_ROWS. - The later is there mainly to show how query is progressing. The following changes in interfaces was needed to get this to work: - init_alloc_root() amd init_sql_alloc() has extra option so that one can mark memory with MY_THREAD_SPECIFIC - One now have to use alloc_root_set_min_malloc() to set min memory to be allocated by alloc_root() - my_init_dynamic_array() has extra option so that one can mark memory with MY_THREAD_SPECIFIC - my_net_init() has extra option so that one can mark memory with MY_THREAD_SPECIFIC - Added flag for hash_init() so that one can mark hash table to be thread specific. - Added flags to init_tree() so that one can mark tree to be thread specific. - Removed with_delete option to init_tree(). Now one should instead use MY_TREE_WITH_DELETE_FLAG. - Added flag to Warning_info::Warning_info() if the structure should be fully initialized. - String elements can now be marked as thread specific. - Internal HEAP tables are now marking it's memory as MY_THREAD_SPECIFIC. - Changed type of myf from int to ulong, as this is always a set of bit flags. Other things: - Removed calls to net_end() and thd->cleanup() as these are now done in ~THD() - We now also show EXAMINED_ROWS in SHOW PROCESSLIST - Added new variable 'memory_used' - Fixed bug where kill_threads_for_user() was using the wrong mem_root to allocate memory. - Removed calls to the obsoleted function init_dynamic_array() - Use set_current_thd() instead of my_pthread_setspecific_ptr(THR_THD,...) client/completion_hash.cc: Updated call to init_alloc_root() client/mysql.cc: Updated call to init_alloc_root() client/mysqlbinlog.cc: init_dynamic_array() -> my_init_dynamic_array() Updated call to init_alloc_root() client/mysqlcheck.c: Updated call to my_init_dynamic_array() client/mysqldump.c: Updated call to init_alloc_root() client/mysqltest.cc: Updated call to init_alloc_root() Updated call to my_init_dynamic_array() Fixed compiler warnings extra/comp_err.c: Updated call to my_init_dynamic_array() extra/resolve_stack_dump.c: Updated call to my_init_dynamic_array() include/hash.h: Added HASH_THREAD_SPECIFIC include/heap.h: Added flag is internal temporary table. include/my_dir.h: Safety fix: Ensure that MY_DONT_SORT and MY_WANT_STAT don't interfer with other mysys flags include/my_global.h: Changed type of myf from int to ulong, as this is always a set of bit flags. include/my_sys.h: Added MY_THREAD_SPECIFIC and MY_THREAD_MOVE Added malloc_flags to DYNAMIC_ARRAY Added extra mysys flag argument to my_init_dynamic_array() Removed deprecated functions init_dynamic_array() and my_init_dynamic_array.._ci Updated paramaters for init_alloc_root() include/my_tree.h: Added my_flags to allow one to use MY_THREAD_SPECIFIC with hash tables. Removed with_delete. One should now instead use MY_TREE_WITH_DELETE_FLAG Updated parameters to init_tree() include/myisamchk.h: Added malloc_flags to allow one to use MY_THREAD_SPECIFIC for checks. include/mysql.h: Added MYSQL_THREAD_SPECIFIC_MALLOC Used 'unused1' to mark memory as thread specific. include/mysql.h.pp: Updated file include/mysql_com.h: Used 'unused1' to mark memory as thread specific. Updated parameters for my_net_init() libmysql/libmysql.c: Updated call to init_alloc_root() to mark memory thread specific. libmysqld/emb_qcache.cc: Updated call to init_alloc_root() libmysqld/lib_sql.cc: Updated call to init_alloc_root() mysql-test/r/create.result: Updated results mysql-test/r/user_var.result: Updated results mysql-test/suite/funcs_1/datadict/processlist_priv.inc: Update to handle new format of SHOW PROCESSLIST mysql-test/suite/funcs_1/datadict/processlist_val.inc: Update to handle new format of SHOW PROCESSLIST mysql-test/suite/funcs_1/r/is_columns_is.result: Update to handle new format of SHOW PROCESSLIST mysql-test/suite/funcs_1/r/processlist_priv_no_prot.result: Updated results mysql-test/suite/funcs_1/r/processlist_val_no_prot.result: Updated results mysql-test/t/show_explain.test: Fixed usage of debug variable so that one can run test with --debug mysql-test/t/user_var.test: Added test of memory_usage variable. mysys/array.c: Added extra my_flags option to init_dynamic_array() and init_dynamic_array2() so that one can mark memory with MY_THREAD_SPECIFIC All allocated memory is marked with the given my_flags. Removed obsolete function init_dynamic_array() mysys/default.c: Updated call to init_alloc_root() Updated call to my_init_dynamic_array() mysys/hash.c: Updated call to my_init_dynamic_array_ci(). Allocated memory is marked with MY_THREAD_SPECIFIC if HASH_THREAD_SPECIFIC is used. mysys/ma_dyncol.c: init_dynamic_array() -> my_init_dynamic_array() Added #if to get rid of compiler warnings mysys/mf_tempdir.c: Updated call to my_init_dynamic_array() mysys/my_alloc.c: Added extra parameter to init_alloc_root() so that one can mark memory with MY_THREAD_SPECIFIC Extend MEM_ROOT with a flag if memory is thread specific. This is stored in block_size, to keep the size of the MEM_ROOT object identical as before. Allocated memory is marked with MY_THREAD_SPECIFIC if used with init_alloc_root() mysys/my_chmod.c: Updated DBUG_PRINT because of change of myf type mysys/my_chsize.c: Updated DBUG_PRINT because of change of myf type mysys/my_copy.c: Updated DBUG_PRINT because of change of myf type mysys/my_create.c: Updated DBUG_PRINT because of change of myf type mysys/my_delete.c: Updated DBUG_PRINT because of change of myf type mysys/my_error.c: Updated DBUG_PRINT because of change of myf type mysys/my_fopen.c: Updated DBUG_PRINT because of change of myf type mysys/my_fstream.c: Updated DBUG_PRINT because of change of myf type mysys/my_getwd.c: Updated DBUG_PRINT because of change of myf type mysys/my_lib.c: Updated call to init_alloc_root() Updated call to my_init_dynamic_array() Updated DBUG_PRINT because of change of myf type mysys/my_lock.c: Updated DBUG_PRINT because of change of myf type mysys/my_malloc.c: Store at start of each allocated memory block the size of the block and if the block is thread specific. Call malloc_size_cb_func, if set, with the memory allocated/freed. Updated DBUG_PRINT because of change of myf type mysys/my_open.c: Updated DBUG_PRINT because of change of myf type mysys/my_pread.c: Updated DBUG_PRINT because of change of myf type mysys/my_read.c: Updated DBUG_PRINT because of change of myf type mysys/my_redel.c: Updated DBUG_PRINT because of change of myf type mysys/my_rename.c: Updated DBUG_PRINT because of change of myf type mysys/my_seek.c: Updated DBUG_PRINT because of change of myf type mysys/my_sync.c: Updated DBUG_PRINT because of change of myf type mysys/my_thr_init.c: Ensure that one can call my_thread_dbug_id() even if thread is not properly initialized. mysys/my_write.c: Updated DBUG_PRINT because of change of myf type mysys/mysys_priv.h: Updated parameters to sf_malloc and sf_realloc() mysys/safemalloc.c: Added checking that for memory marked with MY_THREAD_SPECIFIC that it's the same thread that is allocation and freeing the memory. Added sf_malloc_dbug_id() to allow MariaDB to specify which THD is handling the memory. Added my_flags arguments to sf_malloc() and sf_realloc() to be able to mark memory with MY_THREAD_SPECIFIC. Added sf_report_leaked_memory() to get list of memory not freed by a thread. mysys/tree.c: Added flags to init_tree() so that one can mark tree to be thread specific. Removed with_delete option to init_tree(). Now one should instead use MY_TREE_WITH_DELETE_FLAG. Updated call to init_alloc_root() All allocated memory is marked with the given malloc flags mysys/waiting_threads.c: Updated call to my_init_dynamic_array() sql-common/client.c: Updated call to init_alloc_root() and my_net_init() to mark memory thread specific. Updated call to my_init_dynamic_array(). Added MYSQL_THREAD_SPECIFIC_MALLOC so that client can mark memory as MY_THREAD_SPECIFIC. sql-common/client_plugin.c: Updated call to init_alloc_root() sql/debug_sync.cc: Added MY_THREAD_SPECIFIC to allocated memory. sql/event_scheduler.cc: Removed calls to net_end() as this is now done in ~THD() Call set_current_thd() to ensure that memory is assigned to right thread. sql/events.cc: my_pthread_setspecific_ptr(THR_THD,...) -> set_current_thd() sql/filesort.cc: Added MY_THREAD_SPECIFIC to allocated memory. sql/filesort_utils.cc: Added MY_THREAD_SPECIFIC to allocated memory. sql/ha_ndbcluster.cc: Updated call to init_alloc_root() Updated call to my_net_init() Removed calls to net_end() and thd->cleanup() as these are now done in ~THD() sql/ha_ndbcluster_binlog.cc: Updated call to my_net_init() Updated call to init_sql_alloc() Removed calls to net_end() and thd->cleanup() as these are now done in ~THD() sql/ha_partition.cc: Updated call to init_alloc_root() sql/handler.cc: Added MY_THREAD_SPECIFIC to allocated memory. Added missing call to my_dir_end() sql/item_func.cc: Added MY_THREAD_SPECIFIC to allocated memory. sql/item_subselect.cc: Added MY_THREAD_SPECIFIC to allocated memory. sql/item_sum.cc: Added MY_THREAD_SPECIFIC to allocated memory. sql/log.cc: More DBUG Updated call to init_alloc_root() sql/mdl.cc: Added MY_THREAD_SPECIFIC to allocated memory. sql/mysqld.cc: Added total_memory_used Updated call to init_alloc_root() Move mysql_cond_broadcast() before my_thread_end() Added mariadb_dbug_id() to count memory per THD instead of per thread. Added my_malloc_size_cb_func() callback function for my_malloc() to count memory. Move initialization of mysqld_server_started and mysqld_server_initialized earlier. Updated call to my_init_dynamic_array(). Updated call to my_net_init(). Call my_pthread_setspecific_ptr(THR_THD,...) to ensure that memory is assigned to right thread. Added status variable 'memory_used'. Updated call to init_alloc_root() my_pthread_setspecific_ptr(THR_THD,...) -> set_current_thd() sql/mysqld.h: Added set_current_thd() sql/net_serv.cc: Added new parameter to my_net_init() so that one can mark memory with MY_THREAD_SPECIFIC. Store in net->thread_specific_malloc if memory is thread specific. Mark memory to be thread specific if requested. sql/opt_range.cc: Updated call to my_init_dynamic_array() Updated call to init_sql_alloc() Added MY_THREAD_SPECIFIC to allocated memory. sql/opt_subselect.cc: Updated call to init_sql_alloc() to mark memory thread specific. sql/protocol.cc: Fixed compiler warning sql/records.cc: Added MY_THREAD_SPECIFIC to allocated memory. sql/rpl_filter.cc: Updated call to my_init_dynamic_array() sql/rpl_handler.cc: Updated call to my_init_dynamic_array2() sql/rpl_handler.h: Updated call to init_sql_alloc() sql/rpl_mi.cc: Updated call to my_init_dynamic_array() sql/rpl_tblmap.cc: Updated call to init_alloc_root() sql/rpl_utility.cc: Updated call to my_init_dynamic_array() sql/slave.cc: Initialize things properly before calling functions that allocate memory. Removed calls to net_end() as this is now done in ~THD() sql/sp_head.cc: Updated call to init_sql_alloc() Updated call to my_init_dynamic_array() Added parameter to warning_info() that it should be fully initialized. sql/sp_pcontext.cc: Updated call to my_init_dynamic_array() sql/sql_acl.cc: Updated call to init_sql_alloc() Updated call to my_init_dynamic_array() my_pthread_setspecific_ptr(THR_THD,...) -> set_current_thd() sql/sql_admin.cc: Added parameter to warning_info() that it should be fully initialized. sql/sql_analyse.h: Updated call to init_tree() to mark memory thread specific. sql/sql_array.h: Updated call to my_init_dynamic_array() to mark memory thread specific. sql/sql_audit.cc: Updated call to my_init_dynamic_array() sql/sql_base.cc: Updated call to init_sql_alloc() my_pthread_setspecific_ptr(THR_THD,...) -> set_current_thd() sql/sql_cache.cc: Updated comment sql/sql_class.cc: Added parameter to warning_info() that not initialize it until THD is fully created. Updated call to init_sql_alloc() Mark THD::user_vars has to be thread specific. Updated call to my_init_dynamic_array() Ensure that memory allocated by THD is assigned to the THD. More DBUG Always acll net_end() in ~THD() Assert that all memory signed to this THD is really deleted at ~THD. Fixed set_status_var_init() to not reset memory_used. my_pthread_setspecific_ptr(THR_THD,...) -> set_current_thd() sql/sql_class.h: Added MY_THREAD_SPECIFIC to allocated memory. Added malloc_size to THD to record allocated memory per THD. sql/sql_delete.cc: Added MY_THREAD_SPECIFIC to allocated memory. sql/sql_error.cc: Added 'initialize' parameter to Warning_info() to say if should allocate memory for it's structures. This is used by THD::THD() to not allocate memory until THD is ready. Added Warning_info::free_memory() sql/sql_error.h: Updated Warning_info() class. sql/sql_handler.cc: Updated call to init_alloc_root() to mark memory thread specific. sql/sql_insert.cc: More DBUG sql/sql_join_cache.cc: Added MY_THREAD_SPECIFIC to allocated memory. sql/sql_lex.cc: Updated call to my_init_dynamic_array() sql/sql_lex.h: Updated call to my_init_dynamic_array() sql/sql_load.cc: Added MY_THREAD_SPECIFIC to allocated memory. sql/sql_parse.cc: Removed calls to net_end() and thd->cleanup() as these are now done in ~THD() Ensure that examined_row_count() is reset before query. Fixed bug where kill_threads_for_user() was using the wrong mem_root to allocate memory. my_pthread_setspecific_ptr(THR_THD,...) -> set_current_thd() Don't restore thd->status_var.memory_used when restoring thd->status_var sql/sql_plugin.cc: Updated call to init_alloc_root() Updated call to my_init_dynamic_array() Don't allocate THD on the stack, as this causes problems with valgrind when doing thd memory counting. my_pthread_setspecific_ptr(THR_THD,...) -> set_current_thd() sql/sql_prepare.cc: Added parameter to warning_info() that it should be fully initialized. Updated call to init_sql_alloc() to mark memory thread specific. sql/sql_reload.cc: my_pthread_setspecific_ptr(THR_THD,...) -> set_current_thd() sql/sql_select.cc: Updated call to my_init_dynamic_array() and init_sql_alloc() to mark memory thread specific. Added MY_THREAD_SPECIFIC to allocated memory. More DBUG sql/sql_servers.cc: Updated call to init_sql_alloc() to mark memory some memory thread specific. my_pthread_setspecific_ptr(THR_THD,...) -> set_current_thd() sql/sql_show.cc: Updated call to my_init_dynamic_array() Mark my_dir() memory thread specific. Use my_pthread_setspecific_ptr(THR_THD,...) to mark that allocated memory should be allocated to calling thread. More DBUG. Added malloc_size and examined_row_count to SHOW PROCESSLIST. Added MY_THREAD_SPECIFIC to allocated memory. Updated call to init_sql_alloc() Added parameter to warning_info() that it should be fully initialized. sql/sql_statistics.cc: Fixed compiler warning sql/sql_string.cc: String elements can now be marked as thread specific. sql/sql_string.h: String elements can now be marked as thread specific. sql/sql_table.cc: Updated call to init_sql_alloc() and my_malloc() to mark memory thread specific my_pthread_setspecific_ptr(THR_THD,...) -> set_current_thd() Fixed compiler warning sql/sql_test.cc: Updated call to my_init_dynamic_array() to mark memory thread specific. sql/sql_trigger.cc: Updated call to init_sql_alloc() sql/sql_udf.cc: Updated call to init_sql_alloc() my_pthread_setspecific_ptr(THR_THD,...) -> set_current_thd() sql/sql_update.cc: Added MY_THREAD_SPECIFIC to allocated memory. sql/table.cc: Updated call to init_sql_alloc(). Mark memory used by temporary tables, that are not for slave threads, as MY_THREAD_SPECIFIC Updated call to init_sql_alloc() sql/thr_malloc.cc: Added my_flags argument to init_sql_alloc() to be able to mark memory as MY_THREAD_SPECIFIC. sql/thr_malloc.h: Updated prototype for init_sql_alloc() sql/tztime.cc: Updated call to init_sql_alloc() Updated call to init_alloc_root() to mark memory thread specific. my_pthread_setspecific_ptr(THR_THD,...) -> set_current_thd() sql/uniques.cc: Updated calls to init_tree(), my_init_dynamic_array() and my_malloc() to mark memory thread specific. sql/unireg.cc: Added MY_THREAD_SPECIFIC to allocated memory. storage/csv/ha_tina.cc: Updated call to init_alloc_root() storage/federated/ha_federated.cc: Updated call to init_alloc_root() Updated call to my_init_dynamic_array() Ensure that memory allocated by fedarated is registered for the system, not for the thread. storage/federatedx/federatedx_io_mysql.cc: Updated call to my_init_dynamic_array() storage/federatedx/ha_federatedx.cc: Updated call to init_alloc_root() Updated call to my_init_dynamic_array() storage/heap/ha_heap.cc: Added MY_THREAD_SPECIFIC to allocated memory. storage/heap/heapdef.h: Added parameter to hp_get_new_block() to be able to do thread specific memory tagging. storage/heap/hp_block.c: Added parameter to hp_get_new_block() to be able to do thread specific memory tagging. storage/heap/hp_create.c: - Internal HEAP tables are now marking it's memory as MY_THREAD_SPECIFIC. - Use MY_TREE_WITH_DELETE instead of removed option 'with_delete'. storage/heap/hp_open.c: Internal HEAP tables are now marking it's memory as MY_THREAD_SPECIFIC. storage/heap/hp_write.c: Added new parameter to hp_get_new_block() storage/maria/ma_bitmap.c: Updated call to my_init_dynamic_array() storage/maria/ma_blockrec.c: Updated call to my_init_dynamic_array() storage/maria/ma_check.c: Updated call to init_alloc_root() storage/maria/ma_ft_boolean_search.c: Updated calls to init_tree() and init_alloc_root() storage/maria/ma_ft_nlq_search.c: Updated call to init_tree() storage/maria/ma_ft_parser.c: Updated call to init_tree() Updated call to init_alloc_root() storage/maria/ma_loghandler.c: Updated call to my_init_dynamic_array() storage/maria/ma_open.c: Updated call to my_init_dynamic_array() storage/maria/ma_sort.c: Updated call to my_init_dynamic_array() storage/maria/ma_write.c: Updated calls to my_init_dynamic_array() and init_tree() storage/maria/maria_pack.c: Updated call to init_tree() storage/maria/unittest/sequence_storage.c: Updated call to my_init_dynamic_array() storage/myisam/ft_boolean_search.c: Updated call to init_tree() Updated call to init_alloc_root() storage/myisam/ft_nlq_search.c: Updated call to init_tree() storage/myisam/ft_parser.c: Updated call to init_tree() Updated call to init_alloc_root() storage/myisam/ft_stopwords.c: Updated call to init_tree() storage/myisam/mi_check.c: Updated call to init_alloc_root() storage/myisam/mi_write.c: Updated call to my_init_dynamic_array() Updated call to init_tree() storage/myisam/myisamlog.c: Updated call to init_tree() storage/myisam/myisampack.c: Updated call to init_tree() storage/myisam/sort.c: Updated call to my_init_dynamic_array() storage/myisammrg/ha_myisammrg.cc: Updated call to init_sql_alloc() storage/perfschema/pfs_check.cc: Rest current_thd storage/perfschema/pfs_instr.cc: Removed DBUG_ENTER/DBUG_VOID_RETURN as at this point my_thread_var is not allocated anymore, which can cause problems. support-files/compiler_warnings.supp: Disable compiler warning from offsetof macro.
595 lines
18 KiB
C++
595 lines
18 KiB
C++
/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; version 2 of the License.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
|
|
|
#ifndef SQL_ERROR_H
|
|
#define SQL_ERROR_H
|
|
|
|
#include "sql_list.h" /* Sql_alloc, MEM_ROOT */
|
|
#include "m_string.h" /* LEX_STRING */
|
|
#include "sql_string.h" /* String */
|
|
#include "mysql_com.h" /* MYSQL_ERRMSG_SIZE */
|
|
|
|
class THD;
|
|
|
|
/**
|
|
Stores status of the currently executed statement.
|
|
Cleared at the beginning of the statement, and then
|
|
can hold either OK, ERROR, or EOF status.
|
|
Can not be assigned twice per statement.
|
|
*/
|
|
|
|
class Diagnostics_area
|
|
{
|
|
public:
|
|
enum enum_diagnostics_status
|
|
{
|
|
/** The area is cleared at start of a statement. */
|
|
DA_EMPTY= 0,
|
|
/** Set whenever one calls my_ok(). */
|
|
DA_OK,
|
|
/** Set whenever one calls my_eof(). */
|
|
DA_EOF,
|
|
/** Set whenever one calls my_error() or my_message(). */
|
|
DA_ERROR,
|
|
/** Set in case of a custom response, such as one from COM_STMT_PREPARE. */
|
|
DA_DISABLED
|
|
};
|
|
/** True if status information is sent to the client. */
|
|
bool is_sent;
|
|
/** Set to make set_error_status after set_{ok,eof}_status possible. */
|
|
bool can_overwrite_status;
|
|
|
|
void set_ok_status(THD *thd, ulonglong affected_rows_arg,
|
|
ulonglong last_insert_id_arg,
|
|
const char *message);
|
|
void set_eof_status(THD *thd);
|
|
void set_error_status(THD *thd, uint sql_errno_arg, const char *message_arg,
|
|
const char *sqlstate);
|
|
|
|
void disable_status();
|
|
|
|
void reset_diagnostics_area();
|
|
|
|
bool is_set() const { return m_status != DA_EMPTY; }
|
|
bool is_error() const { return m_status == DA_ERROR; }
|
|
bool is_eof() const { return m_status == DA_EOF; }
|
|
bool is_ok() const { return m_status == DA_OK; }
|
|
bool is_disabled() const { return m_status == DA_DISABLED; }
|
|
enum_diagnostics_status status() const { return m_status; }
|
|
|
|
const char *message() const
|
|
{ DBUG_ASSERT(m_status == DA_ERROR || m_status == DA_OK); return m_message; }
|
|
|
|
uint sql_errno() const
|
|
{ DBUG_ASSERT(m_status == DA_ERROR); return m_sql_errno; }
|
|
|
|
const char* get_sqlstate() const
|
|
{ DBUG_ASSERT(m_status == DA_ERROR); return m_sqlstate; }
|
|
|
|
ulonglong affected_rows() const
|
|
{ DBUG_ASSERT(m_status == DA_OK); return m_affected_rows; }
|
|
|
|
ulonglong last_insert_id() const
|
|
{ DBUG_ASSERT(m_status == DA_OK); return m_last_insert_id; }
|
|
|
|
uint statement_warn_count() const
|
|
{
|
|
DBUG_ASSERT(m_status == DA_OK || m_status == DA_EOF);
|
|
return m_statement_warn_count;
|
|
}
|
|
|
|
/* Used to count any warnings pushed after calling set_ok_status(). */
|
|
void increment_warning()
|
|
{
|
|
if (m_status != DA_EMPTY)
|
|
m_statement_warn_count++;
|
|
}
|
|
|
|
Diagnostics_area() { reset_diagnostics_area(); }
|
|
|
|
private:
|
|
/** Message buffer. Can be used by OK or ERROR status. */
|
|
char m_message[MYSQL_ERRMSG_SIZE];
|
|
/**
|
|
SQL error number. One of ER_ codes from share/errmsg.txt.
|
|
Set by set_error_status.
|
|
*/
|
|
uint m_sql_errno;
|
|
|
|
char m_sqlstate[SQLSTATE_LENGTH+1];
|
|
|
|
/**
|
|
The number of rows affected by the last statement. This is
|
|
semantically close to thd->row_count_func, but has a different
|
|
life cycle. thd->row_count_func stores the value returned by
|
|
function ROW_COUNT() and is cleared only by statements that
|
|
update its value, such as INSERT, UPDATE, DELETE and few others.
|
|
This member is cleared at the beginning of the next statement.
|
|
|
|
We could possibly merge the two, but life cycle of thd->row_count_func
|
|
can not be changed.
|
|
*/
|
|
ulonglong m_affected_rows;
|
|
/**
|
|
Similarly to the previous member, this is a replacement of
|
|
thd->first_successful_insert_id_in_prev_stmt, which is used
|
|
to implement LAST_INSERT_ID().
|
|
*/
|
|
ulonglong m_last_insert_id;
|
|
/**
|
|
Number of warnings of this last statement. May differ from
|
|
the number of warnings returned by SHOW WARNINGS e.g. in case
|
|
the statement doesn't clear the warnings, and doesn't generate
|
|
them.
|
|
*/
|
|
uint m_statement_warn_count;
|
|
enum_diagnostics_status m_status;
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
/**
|
|
Representation of a SQL condition.
|
|
A SQL condition can be a completion condition (note, warning),
|
|
or an exception condition (error, not found).
|
|
@note This class is named MYSQL_ERROR instead of SQL_condition for
|
|
historical reasons, to facilitate merging code with previous releases.
|
|
*/
|
|
class MYSQL_ERROR : public Sql_alloc
|
|
{
|
|
public:
|
|
/*
|
|
Enumeration value describing the severity of the error.
|
|
|
|
Note that these enumeration values must correspond to the indices
|
|
of the sql_print_message_handlers array.
|
|
*/
|
|
enum enum_warning_level
|
|
{ WARN_LEVEL_NOTE, WARN_LEVEL_WARN, WARN_LEVEL_ERROR, WARN_LEVEL_END};
|
|
/**
|
|
Get the MESSAGE_TEXT of this condition.
|
|
@return the message text.
|
|
*/
|
|
const char* get_message_text() const;
|
|
|
|
/**
|
|
Get the MESSAGE_OCTET_LENGTH of this condition.
|
|
@return the length in bytes of the message text.
|
|
*/
|
|
int get_message_octet_length() const;
|
|
|
|
/**
|
|
Get the SQLSTATE of this condition.
|
|
@return the sql state.
|
|
*/
|
|
const char* get_sqlstate() const
|
|
{ return m_returned_sqlstate; }
|
|
|
|
/**
|
|
Get the SQL_ERRNO of this condition.
|
|
@return the sql error number condition item.
|
|
*/
|
|
uint get_sql_errno() const
|
|
{ return m_sql_errno; }
|
|
|
|
/**
|
|
Get the error level of this condition.
|
|
@return the error level condition item.
|
|
*/
|
|
MYSQL_ERROR::enum_warning_level get_level() const
|
|
{ return m_level; }
|
|
|
|
private:
|
|
/*
|
|
The interface of MYSQL_ERROR is mostly private, by design,
|
|
so that only the following code:
|
|
- various raise_error() or raise_warning() methods in class THD,
|
|
- the implementation of SIGNAL / RESIGNAL
|
|
- catch / re-throw of SQL conditions in stored procedures (sp_rcontext)
|
|
is allowed to create / modify a SQL condition.
|
|
Enforcing this policy prevents confusion, since the only public
|
|
interface available to the rest of the server implementation
|
|
is the interface offered by the THD methods (THD::raise_error()),
|
|
which should be used.
|
|
*/
|
|
friend class THD;
|
|
friend class Warning_info;
|
|
friend class Signal_common;
|
|
friend class Signal_statement;
|
|
friend class Resignal_statement;
|
|
friend class sp_rcontext;
|
|
|
|
/**
|
|
Default constructor.
|
|
This constructor is usefull when allocating arrays.
|
|
Note that the init() method should be called to complete the MYSQL_ERROR.
|
|
*/
|
|
MYSQL_ERROR();
|
|
|
|
/**
|
|
Complete the MYSQL_ERROR initialisation.
|
|
@param mem_root The memory root to use for the condition items
|
|
of this condition
|
|
*/
|
|
void init(MEM_ROOT *mem_root);
|
|
|
|
/**
|
|
Constructor.
|
|
@param mem_root The memory root to use for the condition items
|
|
of this condition
|
|
*/
|
|
MYSQL_ERROR(MEM_ROOT *mem_root);
|
|
|
|
/** Destructor. */
|
|
~MYSQL_ERROR()
|
|
{}
|
|
|
|
/**
|
|
Copy optional condition items attributes.
|
|
@param cond the condition to copy.
|
|
*/
|
|
void copy_opt_attributes(const MYSQL_ERROR *cond);
|
|
|
|
/**
|
|
Set this condition area with a fixed message text.
|
|
@param thd the current thread.
|
|
@param code the error number for this condition.
|
|
@param str the message text for this condition.
|
|
@param level the error level for this condition.
|
|
@param MyFlags additional flags.
|
|
*/
|
|
void set(uint sql_errno, const char* sqlstate,
|
|
MYSQL_ERROR::enum_warning_level level,
|
|
const char* msg);
|
|
|
|
/**
|
|
Set the condition message test.
|
|
@param str Message text, expressed in the character set derived from
|
|
the server --language option
|
|
*/
|
|
void set_builtin_message_text(const char* str);
|
|
|
|
/** Set the SQLSTATE of this condition. */
|
|
void set_sqlstate(const char* sqlstate);
|
|
|
|
/**
|
|
Clear this SQL condition.
|
|
*/
|
|
void clear();
|
|
|
|
private:
|
|
/** SQL CLASS_ORIGIN condition item. */
|
|
String m_class_origin;
|
|
|
|
/** SQL SUBCLASS_ORIGIN condition item. */
|
|
String m_subclass_origin;
|
|
|
|
/** SQL CONSTRAINT_CATALOG condition item. */
|
|
String m_constraint_catalog;
|
|
|
|
/** SQL CONSTRAINT_SCHEMA condition item. */
|
|
String m_constraint_schema;
|
|
|
|
/** SQL CONSTRAINT_NAME condition item. */
|
|
String m_constraint_name;
|
|
|
|
/** SQL CATALOG_NAME condition item. */
|
|
String m_catalog_name;
|
|
|
|
/** SQL SCHEMA_NAME condition item. */
|
|
String m_schema_name;
|
|
|
|
/** SQL TABLE_NAME condition item. */
|
|
String m_table_name;
|
|
|
|
/** SQL COLUMN_NAME condition item. */
|
|
String m_column_name;
|
|
|
|
/** SQL CURSOR_NAME condition item. */
|
|
String m_cursor_name;
|
|
|
|
/** Message text, expressed in the character set implied by --language. */
|
|
String m_message_text;
|
|
|
|
/** MySQL extension, MYSQL_ERRNO condition item. */
|
|
uint m_sql_errno;
|
|
|
|
/**
|
|
SQL RETURNED_SQLSTATE condition item.
|
|
This member is always NUL terminated.
|
|
*/
|
|
char m_returned_sqlstate[SQLSTATE_LENGTH+1];
|
|
|
|
/** Severity (error, warning, note) of this condition. */
|
|
MYSQL_ERROR::enum_warning_level m_level;
|
|
|
|
/** Memory root to use to hold condition item values. */
|
|
MEM_ROOT *m_mem_root;
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
/**
|
|
Information about warnings of the current connection.
|
|
*/
|
|
|
|
class Warning_info
|
|
{
|
|
/** A memory root to allocate warnings and errors */
|
|
MEM_ROOT m_warn_root;
|
|
|
|
/** List of warnings of all severities (levels). */
|
|
List <MYSQL_ERROR> m_warn_list;
|
|
|
|
/** A break down of the number of warnings per severity (level). */
|
|
uint m_warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_END];
|
|
|
|
/**
|
|
The number of warnings of the current statement. Warning_info
|
|
life cycle differs from statement life cycle -- it may span
|
|
multiple statements. In that case we get
|
|
m_statement_warn_count 0, whereas m_warn_list is not empty.
|
|
*/
|
|
uint m_statement_warn_count;
|
|
|
|
/*
|
|
Row counter, to print in errors and warnings. Not increased in
|
|
create_sort_index(); may differ from examined_row_count.
|
|
*/
|
|
ulong m_current_row_for_warning;
|
|
|
|
/** Used to optionally clear warnings only once per statement. */
|
|
ulonglong m_warn_id;
|
|
|
|
/** Indicates if push_warning() allows unlimited number of warnings. */
|
|
bool m_allow_unlimited_warnings;
|
|
bool initialized; /* Set to 1 if init() has been called */
|
|
|
|
private:
|
|
Warning_info(const Warning_info &rhs); /* Not implemented */
|
|
Warning_info& operator=(const Warning_info &rhs); /* Not implemented */
|
|
public:
|
|
|
|
Warning_info(ulonglong warn_id_arg, bool allow_unlimited_warnings,
|
|
bool initialize);
|
|
~Warning_info();
|
|
|
|
/* Allocate memory for structures */
|
|
void init();
|
|
void free_memory();
|
|
|
|
/**
|
|
Reset the warning information. Clear all warnings,
|
|
the number of warnings, reset current row counter
|
|
to point to the first row.
|
|
*/
|
|
void clear_warning_info(ulonglong warn_id_arg);
|
|
/**
|
|
Only clear warning info if haven't yet done that already
|
|
for the current query. Allows to be issued at any time
|
|
during the query, without risk of clearing some warnings
|
|
that have been generated by the current statement.
|
|
|
|
@todo: This is a sign of sloppy coding. Instead we need to
|
|
designate one place in a statement life cycle where we call
|
|
clear_warning_info().
|
|
*/
|
|
void opt_clear_warning_info(ulonglong query_id)
|
|
{
|
|
if (query_id != m_warn_id)
|
|
clear_warning_info(query_id);
|
|
}
|
|
|
|
void append_warning_info(THD *thd, Warning_info *source)
|
|
{
|
|
append_warnings(thd, & source->warn_list());
|
|
}
|
|
|
|
/**
|
|
Concatenate the list of warnings.
|
|
It's considered tolerable to lose a warning.
|
|
*/
|
|
void append_warnings(THD *thd, List<MYSQL_ERROR> *src)
|
|
{
|
|
MYSQL_ERROR *err;
|
|
List_iterator_fast<MYSQL_ERROR> it(*src);
|
|
/*
|
|
Don't use ::push_warning() to avoid invocation of condition
|
|
handlers or escalation of warnings to errors.
|
|
*/
|
|
while ((err= it++))
|
|
Warning_info::push_warning(thd, err);
|
|
}
|
|
|
|
/**
|
|
Conditional merge of related warning information areas.
|
|
*/
|
|
void merge_with_routine_info(THD *thd, Warning_info *source);
|
|
|
|
/**
|
|
Reset between two COM_ commands. Warnings are preserved
|
|
between commands, but statement_warn_count indicates
|
|
the number of warnings of this particular statement only.
|
|
*/
|
|
void reset_for_next_command() { m_statement_warn_count= 0; }
|
|
|
|
/**
|
|
Used for @@warning_count system variable, which prints
|
|
the number of rows returned by SHOW WARNINGS.
|
|
*/
|
|
ulong warn_count() const
|
|
{
|
|
/*
|
|
This may be higher than warn_list.elements if we have
|
|
had more warnings than thd->variables.max_error_count.
|
|
*/
|
|
return (m_warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_NOTE] +
|
|
m_warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_ERROR] +
|
|
m_warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_WARN]);
|
|
}
|
|
|
|
/**
|
|
This is for iteration purposes. We return a non-constant reference
|
|
since List doesn't have constant iterators.
|
|
*/
|
|
List<MYSQL_ERROR> &warn_list() { return m_warn_list; }
|
|
|
|
/**
|
|
The number of errors, or number of rows returned by SHOW ERRORS,
|
|
also the value of session variable @@error_count.
|
|
*/
|
|
ulong error_count() const
|
|
{
|
|
return m_warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_ERROR];
|
|
}
|
|
|
|
/** Id of the warning information area. */
|
|
ulonglong warn_id() const { return m_warn_id; }
|
|
|
|
/** Do we have any errors and warnings that we can *show*? */
|
|
bool is_empty() const { return m_warn_list.elements == 0; }
|
|
|
|
/** Increment the current row counter to point at the next row. */
|
|
void inc_current_row_for_warning() { m_current_row_for_warning++; }
|
|
/** Reset the current row counter. Start counting from the first row. */
|
|
void reset_current_row_for_warning() { m_current_row_for_warning= 1; }
|
|
/** Return the current counter value. */
|
|
ulong current_row_for_warning() const { return m_current_row_for_warning; }
|
|
|
|
ulong statement_warn_count() const { return m_statement_warn_count; }
|
|
|
|
/** Add a new condition to the current list. */
|
|
MYSQL_ERROR *push_warning(THD *thd,
|
|
uint sql_errno, const char* sqlstate,
|
|
MYSQL_ERROR::enum_warning_level level,
|
|
const char* msg);
|
|
|
|
/** Add a new condition to the current list. */
|
|
MYSQL_ERROR *push_warning(THD *thd, const MYSQL_ERROR *sql_condition);
|
|
|
|
/**
|
|
Set the read only status for this statement area.
|
|
This is a privileged operation, reserved for the implementation of
|
|
diagnostics related statements, to enforce that the statement area is
|
|
left untouched during execution.
|
|
The diagnostics statements are:
|
|
- SHOW WARNINGS
|
|
- SHOW ERRORS
|
|
- GET DIAGNOSTICS
|
|
@param read_only the read only property to set
|
|
*/
|
|
void set_read_only(bool read_only)
|
|
{ m_read_only= read_only; }
|
|
|
|
/**
|
|
Read only status.
|
|
@return the read only property
|
|
*/
|
|
bool is_read_only() const
|
|
{ return m_read_only; }
|
|
|
|
private:
|
|
/** Read only status. */
|
|
bool m_read_only;
|
|
|
|
friend class Resignal_statement;
|
|
};
|
|
|
|
extern char *err_conv(char *buff, uint to_length, const char *from,
|
|
uint from_length, CHARSET_INFO *from_cs);
|
|
|
|
class ErrConv
|
|
{
|
|
protected:
|
|
mutable char err_buffer[MYSQL_ERRMSG_SIZE];
|
|
public:
|
|
ErrConv() {}
|
|
virtual ~ErrConv() {}
|
|
virtual const char *ptr() const = 0;
|
|
};
|
|
|
|
class ErrConvString : public ErrConv
|
|
{
|
|
const char *str;
|
|
size_t len;
|
|
CHARSET_INFO *cs;
|
|
public:
|
|
ErrConvString(const char *str_arg, size_t len_arg, CHARSET_INFO *cs_arg)
|
|
: ErrConv(), str(str_arg), len(len_arg), cs(cs_arg) {}
|
|
ErrConvString(String *s)
|
|
: ErrConv(), str(s->ptr()), len(s->length()), cs(s->charset()) {}
|
|
const char *ptr() const
|
|
{ return err_conv(err_buffer, sizeof(err_buffer), str, len, cs); }
|
|
};
|
|
|
|
class ErrConvInteger : public ErrConv
|
|
{
|
|
longlong num;
|
|
public:
|
|
ErrConvInteger(longlong num_arg) : ErrConv(), num(num_arg) {}
|
|
const char *ptr() const
|
|
{ return llstr(num, err_buffer); }
|
|
};
|
|
|
|
class ErrConvDouble: public ErrConv
|
|
{
|
|
double num;
|
|
public:
|
|
ErrConvDouble(double num_arg) : ErrConv(), num(num_arg) {}
|
|
const char *ptr() const
|
|
{
|
|
my_gcvt(num, MY_GCVT_ARG_DOUBLE, sizeof(err_buffer), err_buffer, 0);
|
|
return err_buffer;
|
|
}
|
|
};
|
|
|
|
class ErrConvTime : public ErrConv
|
|
{
|
|
const MYSQL_TIME *ltime;
|
|
public:
|
|
ErrConvTime(const MYSQL_TIME *ltime_arg) : ErrConv(), ltime(ltime_arg) {}
|
|
const char *ptr() const
|
|
{
|
|
my_TIME_to_str(ltime, err_buffer, AUTO_SEC_PART_DIGITS);
|
|
return err_buffer;
|
|
}
|
|
};
|
|
|
|
class ErrConvDecimal : public ErrConv
|
|
{
|
|
const decimal_t *d;
|
|
public:
|
|
ErrConvDecimal(const decimal_t *d_arg) : ErrConv(), d(d_arg) {}
|
|
const char *ptr() const
|
|
{
|
|
int len= sizeof(err_buffer);
|
|
decimal2string(d, err_buffer, &len, 0, 0, ' ');
|
|
return err_buffer;
|
|
}
|
|
};
|
|
|
|
void push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level,
|
|
uint code, const char *msg);
|
|
void push_warning_printf(THD *thd, MYSQL_ERROR::enum_warning_level level,
|
|
uint code, const char *format, ...);
|
|
bool mysqld_show_warnings(THD *thd, ulong levels_to_show);
|
|
uint32 convert_error_message(char *to, uint32 to_length, CHARSET_INFO *to_cs,
|
|
const char *from, uint32 from_length,
|
|
CHARSET_INFO *from_cs, uint *errors);
|
|
|
|
extern const LEX_STRING warning_level_names[];
|
|
|
|
#endif // SQL_ERROR_H
|