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

MWL#182: Explain running statements: merge with 5.3-main

This commit is contained in:
Sergey Petrunya
2012-04-13 14:01:15 -07:00
25 changed files with 1522 additions and 126 deletions

View File

@ -965,6 +965,7 @@ void THD::init(void)
/* Initialize the Debug Sync Facility. See debug_sync.cc. */
debug_sync_init_thread(this);
#endif /* defined(ENABLED_DEBUG_SYNC) */
apc_target.init();
}
@ -1128,7 +1129,8 @@ void THD::cleanup(void)
pthread_mutex_unlock(&LOCK_user_locks);
ull= NULL;
}
apc_target.destroy();
cleanup_done=1;
DBUG_VOID_RETURN;
}
@ -1732,6 +1734,19 @@ CHANGED_TABLE_LIST* THD::changed_table_dup(const char *key, long key_length)
int THD::send_explain_fields(select_result *result)
{
List<Item> field_list;
make_explain_field_list(field_list);
return (result->send_fields(field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF));
}
/*
Populate the provided field_list with EXPLAIN output columns.
this->lex->describe has the EXPLAIN flags
*/
void THD::make_explain_field_list(List<Item> &field_list)
{
Item *item;
CHARSET_INFO *cs= system_charset_info;
field_list.push_back(new Item_return_int("id",3, MYSQL_TYPE_LONGLONG));
@ -1769,10 +1784,9 @@ int THD::send_explain_fields(select_result *result)
}
item->maybe_null= 1;
field_list.push_back(new Item_empty_string("Extra", 255, cs));
return (result->send_fields(field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF));
}
#ifdef SIGNAL_WITH_VIO_CLOSE
void THD::close_active_vio()
{
@ -1876,6 +1890,21 @@ void THD::rollback_item_tree_changes()
}
/*
Check if the thread has been killed, and also process "APC requests"
@retval true The thread is killed, execution should be interrupted
@retval false Not killed, continue execution
*/
bool THD::check_killed()
{
if (killed)
return TRUE;
apc_target.process_apc_requests();
return FALSE;
}
/*****************************************************************************
** Functions to provide a interface to select results
*****************************************************************************/
@ -2016,6 +2045,68 @@ int select_send::send_data(List<Item> &items)
DBUG_RETURN(0);
}
//////////////////////////////////////////////////////////////////////////////
int select_result_explain_buffer::send_data(List<Item> &items)
{
List_iterator_fast<Item> li(items);
char buff[MAX_FIELD_WIDTH];
String buffer(buff, sizeof(buff), &my_charset_bin);
DBUG_ENTER("select_send::send_data");
protocol->prepare_for_resend();
Item *item;
while ((item=li++))
{
if (item->send(protocol, &buffer))
{
protocol->free(); // Free used buffer
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
break;
}
/*
Reset buffer to its original state, as it may have been altered in
Item::send().
*/
buffer.set(buff, sizeof(buff), &my_charset_bin);
}
//TODO: do we need the following:
if (thd->is_error())
{
protocol->remove_last_row();
DBUG_RETURN(1);
}
/* psergey-TODO: instead of protocol->write(), steal the packet here */
const char *packet_data;
size_t len;
protocol->get_packet(&packet_data, &len);
String *s= new (thd->mem_root) String;
s->append(packet_data, len);
data_rows.push_back(s);
protocol->remove_last_row(); // <-- this does nothing. Do we need it?
// prepare_for_resend() will wipe out the packet
DBUG_RETURN(0);
}
void select_result_explain_buffer::flush_data()
{
List_iterator<String> it(data_rows);
String *str;
while ((str= it++))
{
/* TODO: write out the lines. */
protocol->set_packet(str->ptr(), str->length());
protocol->write();
delete str;
}
data_rows.empty();
}
//////////////////////////////////////////////////////////////////////////////
bool select_send::send_eof()
{
/*
@ -2889,6 +2980,10 @@ void THD::end_statement()
}
/*
Start using arena specified by @set. Current arena data will be saved to
*backup.
*/
void THD::set_n_backup_active_arena(Query_arena *set, Query_arena *backup)
{
DBUG_ENTER("THD::set_n_backup_active_arena");
@ -2903,6 +2998,12 @@ void THD::set_n_backup_active_arena(Query_arena *set, Query_arena *backup)
}
/*
Stop using the temporary arena, and start again using the arena that is
specified in *backup.
The temporary arena is returned back into *set.
*/
void THD::restore_active_arena(Query_arena *set, Query_arena *backup)
{
DBUG_ENTER("THD::restore_active_arena");
@ -2915,6 +3016,30 @@ void THD::restore_active_arena(Query_arena *set, Query_arena *backup)
DBUG_VOID_RETURN;
}
/*
Produce EXPLAIN data.
This function is APC-scheduled to be run in the context of the thread that
we're producing EXPLAIN for.
*/
void Show_explain_request::get_explain_data(void *arg)
{
Show_explain_request *req= (Show_explain_request*)arg;
//TODO: change mem_root to point to request_thd->mem_root.
// Actually, change the ARENA, because we're going to allocate items!
Query_arena backup_arena;
req->target_thd->set_n_backup_active_arena((Query_arena*)req->request_thd,
&backup_arena);
req->target_thd->lex->unit.print_explain(req->explain_buf);
req->target_thd->restore_active_arena((Query_arena*)req->request_thd,
&backup_arena);
}
Statement::~Statement()
{
}