diff options
author | Sergey Petrunya <psergey@askmonty.org> | 2012-04-13 14:01:15 -0700 |
---|---|---|
committer | Sergey Petrunya <psergey@askmonty.org> | 2012-04-13 14:01:15 -0700 |
commit | 8c4fc9ba75db308ba60a2efefa7cf5aa6b9b6447 (patch) | |
tree | 7236f5230d9245cc1295d5bc4ade92facfcceefa /sql/sql_class.cc | |
parent | f081107fe01a1d9a6d7d88e3d9c7c5e99aec8144 (diff) | |
parent | ca020dfa9e8668ce52eaff92c157097bba671ec1 (diff) | |
download | mariadb-git-8c4fc9ba75db308ba60a2efefa7cf5aa6b9b6447.tar.gz |
MWL#182: Explain running statements: merge with 5.3-main
Diffstat (limited to 'sql/sql_class.cc')
-rw-r--r-- | sql/sql_class.cc | 131 |
1 files changed, 128 insertions, 3 deletions
diff --git a/sql/sql_class.cc b/sql/sql_class.cc index dd5e02a5d88..d6f976cb505 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -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() { } |