1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00

merge of Bug#33204 (backport)

This commit is contained in:
Martin Hansson
2009-11-20 13:29:43 +01:00
552 changed files with 20776 additions and 7322 deletions

View File

@ -25,54 +25,9 @@
#include "log.h"
#include "rpl_tblmap.h"
#include "replication.h"
/**
An interface that is used to take an action when
the locking module notices that a table version has changed
since the last execution. "Table" here may refer to any kind of
table -- a base table, a temporary table, a view or an
information schema table.
When we open and lock tables for execution of a prepared
statement, we must verify that they did not change
since statement prepare. If some table did change, the statement
parse tree *may* be no longer valid, e.g. in case it contains
optimizations that depend on table metadata.
This class provides an interface (a method) that is
invoked when such a situation takes place.
The implementation of the method simply reports an error, but
the exact details depend on the nature of the SQL statement.
At most 1 instance of this class is active at a time, in which
case THD::m_reprepare_observer is not NULL.
@sa check_and_update_table_version() for details of the
version tracking algorithm
@sa Open_tables_state::m_reprepare_observer for the life cycle
of metadata observers.
*/
class Reprepare_observer
{
public:
Reprepare_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.
*/
bool report_error(THD *thd);
bool is_invalidated() const { return m_invalidated; }
void reset_reprepare_observer() { m_invalidated= FALSE; }
private:
bool m_invalidated;
};
class Reprepare_observer;
class Relay_log_info;
class Query_log_event;
@ -99,6 +54,8 @@ extern char internal_table_name[2];
extern char empty_c_string[1];
extern MYSQL_PLUGIN_IMPORT const char **errmesg;
extern bool volatile shutdown_in_progress;
#define TC_LOG_PAGE_SIZE 8192
#define TC_LOG_MIN_SIZE (3*TC_LOG_PAGE_SIZE)
@ -150,9 +107,14 @@ typedef struct st_copy_info {
class Key_part_spec :public Sql_alloc {
public:
const char *field_name;
LEX_STRING field_name;
uint length;
Key_part_spec(const char *name,uint len=0) :field_name(name), length(len) {}
Key_part_spec(const LEX_STRING &name, uint len)
: field_name(name), length(len)
{}
Key_part_spec(const char *name, const size_t name_len, uint len)
: length(len)
{ field_name.str= (char *)name; field_name.length= name_len; }
bool operator==(const Key_part_spec& other) const;
/**
Construct a copy of this Key_part_spec. field_name is copied
@ -205,15 +167,24 @@ public:
enum Keytype type;
KEY_CREATE_INFO key_create_info;
List<Key_part_spec> columns;
const char *name;
LEX_STRING name;
bool generated;
Key(enum Keytype type_par, const char *name_arg,
Key(enum Keytype type_par, const LEX_STRING &name_arg,
KEY_CREATE_INFO *key_info_arg,
bool generated_arg, List<Key_part_spec> &cols)
:type(type_par), key_create_info(*key_info_arg), columns(cols),
name(name_arg), generated(generated_arg)
{}
Key(enum Keytype type_par, const char *name_arg, size_t name_len_arg,
KEY_CREATE_INFO *key_info_arg, bool generated_arg,
List<Key_part_spec> &cols)
:type(type_par), key_create_info(*key_info_arg), columns(cols),
generated(generated_arg)
{
name.str= (char *)name_arg;
name.length= name_len_arg;
}
Key(const Key &rhs, MEM_ROOT *mem_root);
virtual ~Key() {}
/* Equality comparison of keys (ignoring name) */
@ -238,7 +209,7 @@ public:
Table_ident *ref_table;
List<Key_part_spec> ref_columns;
uint delete_opt, update_opt, match_opt;
Foreign_key(const char *name_arg, List<Key_part_spec> &cols,
Foreign_key(const LEX_STRING &name_arg, List<Key_part_spec> &cols,
Table_ident *table, List<Key_part_spec> &ref_cols,
uint delete_opt_arg, uint update_opt_arg, uint match_opt_arg)
:Key(FOREIGN_KEY, name_arg, &default_key_create_info, 0, cols),
@ -271,6 +242,27 @@ public:
LEX_COLUMN (const String& x,const uint& y ): column (x),rights (y) {}
};
/**
Query_cache_tls -- query cache thread local data.
*/
struct Query_cache_block;
struct Query_cache_tls
{
/*
'first_query_block' should be accessed only via query cache
functions and methods to maintain proper locking.
*/
Query_cache_block *first_query_block;
void set_first_query_block(Query_cache_block *first_query_block_arg)
{
first_query_block= first_query_block_arg;
}
Query_cache_tls() :first_query_block(NULL) {}
};
/* SIGNAL / RESIGNAL / GET DIAGNOSTICS */
/**
@ -685,10 +677,13 @@ public:
This printing is needed at least in SHOW PROCESSLIST and SHOW
ENGINE INNODB STATUS.
*/
char *query;
uint32 query_length; // current query length
LEX_STRING query_string;
Server_side_cursor *cursor;
inline char *query() { return query_string.str; }
inline uint32 query_length() { return query_string.length; }
void set_query_inner(char *query_arg, uint32 query_length_arg);
/**
Name of the current (default) database.
@ -744,8 +739,8 @@ public:
Statement *find_by_name(LEX_STRING *name)
{
Statement *stmt;
stmt= (Statement*)hash_search(&names_hash, (uchar*)name->str,
name->length);
stmt= (Statement*)my_hash_search(&names_hash, (uchar*)name->str,
name->length);
return stmt;
}
@ -754,7 +749,7 @@ public:
if (last_found_statement == 0 || id != last_found_statement->id)
{
Statement *stmt;
stmt= (Statement *) hash_search(&st_hash, (uchar *) &id, sizeof(id));
stmt= (Statement *) my_hash_search(&st_hash, (uchar *) &id, sizeof(id));
if (stmt && stmt->name.str)
return NULL;
last_found_statement= stmt;
@ -1232,6 +1227,9 @@ public:
fields then.
*/
struct st_mysql_stmt *current_stmt;
#endif
#ifdef HAVE_QUERY_CACHE
Query_cache_tls query_cache_tls;
#endif
NET net; // client connection descriptor
Protocol *protocol; // Current protocol
@ -1651,7 +1649,7 @@ public:
CHARSET_INFO *db_charset;
Warning_info *warning_info;
Diagnostics_area *stmt_da;
#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
#if defined(ENABLED_PROFILING)
PROFILING profiling;
#endif
@ -1886,11 +1884,28 @@ public:
inline const char* enter_cond(pthread_cond_t *cond, pthread_mutex_t* mutex,
const char* msg)
{
return thd_enter_cond(this, cond, mutex, msg);
const char* old_msg = proc_info;
safe_mutex_assert_owner(mutex);
mysys_var->current_mutex = mutex;
mysys_var->current_cond = cond;
proc_info = msg;
return old_msg;
}
inline void exit_cond(const char* old_msg)
{
thd_exit_cond(this, old_msg);
/*
Putting the mutex unlock in thd->exit_cond() ensures that
mysys_var->current_mutex is always unlocked _before_ mysys_var->mutex is
locked (if that would not be the case, you'll get a deadlock if someone
does a THD::awake() on you).
*/
pthread_mutex_unlock(mysys_var->current_mutex);
pthread_mutex_lock(&mysys_var->mutex);
mysys_var->current_mutex = 0;
mysys_var->current_cond = 0;
proc_info = old_msg;
pthread_mutex_unlock(&mysys_var->mutex);
return;
}
inline time_t query_start() { query_start_used=1; return start_time; }
inline void set_time()
@ -2037,7 +2052,11 @@ public:
{
int err= killed_errno();
if (err)
{
if ((err == KILL_CONNECTION) && !shutdown_in_progress)
err = KILL_QUERY;
my_message(err, ER(err), MYF(0));
}
}
/* return TRUE if we will abort query if we make a warning now */
inline bool really_abort_on_warning()
@ -2397,7 +2416,7 @@ public:
*/
virtual uint field_count(List<Item> &fields) const
{ return fields.elements; }
virtual bool send_fields(List<Item> &list, uint flags)=0;
virtual bool send_result_set_metadata(List<Item> &list, uint flags)=0;
virtual bool send_data(List<Item> &items)=0;
virtual bool initialize_tables (JOIN *join=0) { return 0; }
virtual void send_error(uint errcode,const char *err);
@ -2436,7 +2455,7 @@ class select_result_interceptor: public select_result
public:
select_result_interceptor() {} /* Remove gcc warning */
uint field_count(List<Item> &fields) const { return 0; }
bool send_fields(List<Item> &fields, uint flag) { return FALSE; }
bool send_result_set_metadata(List<Item> &fields, uint flag) { return FALSE; }
};
@ -2449,7 +2468,7 @@ class select_send :public select_result {
bool is_result_set_started;
public:
select_send() :is_result_set_started(FALSE) {}
bool send_fields(List<Item> &list, uint flags);
bool send_result_set_metadata(List<Item> &list, uint flags);
bool send_data(List<Item> &items);
bool send_eof();
virtual bool check_simple_select() const { return FALSE; }