summaryrefslogtreecommitdiff
path: root/sql/sql_class.cc
diff options
context:
space:
mode:
authorSergey Petrunya <psergey@askmonty.org>2012-04-13 14:01:15 -0700
committerSergey Petrunya <psergey@askmonty.org>2012-04-13 14:01:15 -0700
commit8c4fc9ba75db308ba60a2efefa7cf5aa6b9b6447 (patch)
tree7236f5230d9245cc1295d5bc4ade92facfcceefa /sql/sql_class.cc
parentf081107fe01a1d9a6d7d88e3d9c7c5e99aec8144 (diff)
parentca020dfa9e8668ce52eaff92c157097bba671ec1 (diff)
downloadmariadb-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.cc131
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()
{
}