Commit c57e1bf5 authored by Monty's avatar Monty

Added spider patches for adding HANDLER support for the partition engine

013_mariadb-10.0.15.vp_handler.diff
034_mariadb-10.0.15.vp_handler2.diff
005_mariadb-10.0.15.hs.diff
041_mariadb-10.0.15.vp_handler2.diff
+ Fixes from Kentoku
+ Added handler/suite.pm and handler/suite.opt to be able to run test cases
  in spider/handler
parent 66607085
...@@ -75,7 +75,6 @@ ...@@ -75,7 +75,6 @@
#define PARTITION_DISABLED_TABLE_FLAGS (HA_CAN_GEOMETRY | \ #define PARTITION_DISABLED_TABLE_FLAGS (HA_CAN_GEOMETRY | \
HA_CAN_FULLTEXT | \ HA_CAN_FULLTEXT | \
HA_DUPLICATE_POS | \ HA_DUPLICATE_POS | \
HA_CAN_SQL_HANDLER | \
HA_CAN_INSERT_DELAYED | \ HA_CAN_INSERT_DELAYED | \
HA_READ_BEFORE_WRITE_REMOVAL |\ HA_READ_BEFORE_WRITE_REMOVAL |\
HA_CAN_TABLES_WITHOUT_ROLLBACK) HA_CAN_TABLES_WITHOUT_ROLLBACK)
...@@ -5714,7 +5713,8 @@ int ha_partition::index_next(uchar * buf) ...@@ -5714,7 +5713,8 @@ int ha_partition::index_next(uchar * buf)
and if direction changes, we must step back those partitions in and if direction changes, we must step back those partitions in
the record queue so we don't return a value from the wrong direction. the record queue so we don't return a value from the wrong direction.
*/ */
DBUG_ASSERT(m_index_scan_type != partition_index_last); if (m_index_scan_type == partition_index_last)
DBUG_RETURN(HA_ERR_WRONG_COMMAND);
if (!m_ordered_scan_ongoing) if (!m_ordered_scan_ongoing)
{ {
DBUG_RETURN(handle_unordered_next(buf, FALSE)); DBUG_RETURN(handle_unordered_next(buf, FALSE));
...@@ -5747,7 +5747,8 @@ int ha_partition::index_next_same(uchar *buf, const uchar *key, uint keylen) ...@@ -5747,7 +5747,8 @@ int ha_partition::index_next_same(uchar *buf, const uchar *key, uint keylen)
decrement_statistics(&SSV::ha_read_next_count); decrement_statistics(&SSV::ha_read_next_count);
DBUG_ASSERT(keylen == m_start_key.length); DBUG_ASSERT(keylen == m_start_key.length);
DBUG_ASSERT(m_index_scan_type != partition_index_last); if (m_index_scan_type == partition_index_last)
DBUG_RETURN(HA_ERR_WRONG_COMMAND);
if (!m_ordered_scan_ongoing) if (!m_ordered_scan_ongoing)
DBUG_RETURN(handle_unordered_next(buf, TRUE)); DBUG_RETURN(handle_unordered_next(buf, TRUE));
DBUG_RETURN(handle_ordered_next(buf, TRUE)); DBUG_RETURN(handle_ordered_next(buf, TRUE));
...@@ -5775,7 +5776,8 @@ int ha_partition::index_prev(uchar * buf) ...@@ -5775,7 +5776,8 @@ int ha_partition::index_prev(uchar * buf)
decrement_statistics(&SSV::ha_read_prev_count); decrement_statistics(&SSV::ha_read_prev_count);
/* TODO: read comment in index_next */ /* TODO: read comment in index_next */
DBUG_ASSERT(m_index_scan_type != partition_index_first); if (m_index_scan_type == partition_index_first)
DBUG_RETURN(HA_ERR_WRONG_COMMAND);
DBUG_RETURN(handle_ordered_prev(buf)); DBUG_RETURN(handle_ordered_prev(buf));
} }
...@@ -6394,7 +6396,7 @@ int ha_partition::handle_ordered_next(uchar *buf, bool is_next_same) ...@@ -6394,7 +6396,7 @@ int ha_partition::handle_ordered_next(uchar *buf, bool is_next_same)
if (error) if (error)
{ {
if (error == HA_ERR_END_OF_FILE) if (error == HA_ERR_END_OF_FILE && m_queue.elements)
{ {
/* Return next buffered row */ /* Return next buffered row */
queue_remove_top(&m_queue); queue_remove_top(&m_queue);
...@@ -6446,7 +6448,7 @@ int ha_partition::handle_ordered_prev(uchar *buf) ...@@ -6446,7 +6448,7 @@ int ha_partition::handle_ordered_prev(uchar *buf)
if ((error= file->ha_index_prev(rec_buf))) if ((error= file->ha_index_prev(rec_buf)))
{ {
if (error == HA_ERR_END_OF_FILE) if (error == HA_ERR_END_OF_FILE && m_queue.elements)
{ {
queue_remove_top(&m_queue); queue_remove_top(&m_queue);
if (m_queue.elements) if (m_queue.elements)
...@@ -9126,6 +9128,20 @@ int ha_partition::check_for_upgrade(HA_CHECK_OPT *check_opt) ...@@ -9126,6 +9128,20 @@ int ha_partition::check_for_upgrade(HA_CHECK_OPT *check_opt)
} }
TABLE_LIST *ha_partition::get_next_global_for_child()
{
handler **file;
DBUG_ENTER("ha_partition::get_next_global_for_child");
for (file= m_file; *file; file++)
{
TABLE_LIST *table_list;
if ((table_list= (*file)->get_next_global_for_child()))
DBUG_RETURN(table_list);
}
DBUG_RETURN(0);
}
struct st_mysql_storage_engine partition_storage_engine= struct st_mysql_storage_engine partition_storage_engine=
{ MYSQL_HANDLERTON_INTERFACE_VERSION }; { MYSQL_HANDLERTON_INTERFACE_VERSION };
......
...@@ -916,7 +916,7 @@ class ha_partition :public handler ...@@ -916,7 +916,7 @@ class ha_partition :public handler
special file for handling names of partitions, engine types. special file for handling names of partitions, engine types.
HA_REC_NOT_IN_SEQ is always set for partition handler since we cannot HA_REC_NOT_IN_SEQ is always set for partition handler since we cannot
guarantee that the records will be returned in sequence. guarantee that the records will be returned in sequence.
HA_CAN_GEOMETRY, HA_CAN_FULLTEXT, HA_CAN_SQL_HANDLER, HA_DUPLICATE_POS, HA_CAN_GEOMETRY, HA_CAN_FULLTEXT, HA_DUPLICATE_POS,
HA_CAN_INSERT_DELAYED, HA_PRIMARY_KEY_REQUIRED_FOR_POSITION is disabled HA_CAN_INSERT_DELAYED, HA_PRIMARY_KEY_REQUIRED_FOR_POSITION is disabled
until further investigated. until further investigated.
*/ */
...@@ -1225,6 +1225,7 @@ class ha_partition :public handler ...@@ -1225,6 +1225,7 @@ class ha_partition :public handler
/* Enabled keycache for performance reasons, WL#4571 */ /* Enabled keycache for performance reasons, WL#4571 */
virtual int assign_to_keycache(THD* thd, HA_CHECK_OPT *check_opt); virtual int assign_to_keycache(THD* thd, HA_CHECK_OPT *check_opt);
virtual int preload_keys(THD* thd, HA_CHECK_OPT* check_opt); virtual int preload_keys(THD* thd, HA_CHECK_OPT* check_opt);
virtual TABLE_LIST *get_next_global_for_child();
/* /*
------------------------------------------------------------------------- -------------------------------------------------------------------------
......
...@@ -3690,6 +3690,10 @@ class handler :public Sql_alloc ...@@ -3690,6 +3690,10 @@ class handler :public Sql_alloc
pushed_idx_cond_keyno= MAX_KEY; pushed_idx_cond_keyno= MAX_KEY;
in_range_check_pushed_down= false; in_range_check_pushed_down= false;
} }
/* Needed for partition / spider */
virtual TABLE_LIST *get_next_global_for_child() { return NULL; }
/** /**
Part of old, deprecated in-place ALTER API. Part of old, deprecated in-place ALTER API.
*/ */
......
...@@ -139,6 +139,48 @@ static void mysql_ha_hash_free(SQL_HANDLER *table) ...@@ -139,6 +139,48 @@ static void mysql_ha_hash_free(SQL_HANDLER *table)
delete table; delete table;
} }
static void mysql_ha_close_childs(THD *thd, TABLE_LIST *current_table_list,
TABLE_LIST **next_global)
{
TABLE_LIST *table_list;
DBUG_ENTER("mysql_ha_close_childs");
DBUG_PRINT("info",("current_table_list: %p", current_table_list));
DBUG_PRINT("info",("next_global: %p", *next_global));
for (table_list = *next_global; table_list; table_list = *next_global)
{
*next_global = table_list->next_global;
DBUG_PRINT("info",("table_name: %s.%s", table_list->table->s->db.str,
table_list->table->s->table_name.str));
DBUG_PRINT("info",("parent_l: %p", table_list->parent_l));
if (table_list->parent_l == current_table_list)
{
DBUG_PRINT("info",("found child"));
TABLE *table = table_list->table;
if (table)
{
table->open_by_handler= 0;
if (!table->s->tmp_table)
{
(void) close_thread_table(thd, &table);
thd->mdl_context.release_lock(table_list->mdl_request.ticket);
}
else
{
thd->mark_tmp_table_as_free_for_reuse(table);
}
}
mysql_ha_close_childs(thd, table_list, next_global);
}
else
{
/* the end of child tables */
*next_global = table_list;
break;
}
}
DBUG_VOID_RETURN;
}
/** /**
Close a HANDLER table. Close a HANDLER table.
...@@ -155,11 +197,16 @@ static void mysql_ha_close_table(SQL_HANDLER *handler) ...@@ -155,11 +197,16 @@ static void mysql_ha_close_table(SQL_HANDLER *handler)
{ {
THD *thd= handler->thd; THD *thd= handler->thd;
TABLE *table= handler->table; TABLE *table= handler->table;
TABLE_LIST *current_table_list= NULL, *next_global;
/* check if table was already closed */ /* check if table was already closed */
if (!table) if (!table)
return; return;
if ((next_global= table->file->get_next_global_for_child()))
current_table_list= next_global->parent_l;
table->open_by_handler= 0;
if (!table->s->tmp_table) if (!table->s->tmp_table)
{ {
/* Non temporary table. */ /* Non temporary table. */
...@@ -170,15 +217,17 @@ static void mysql_ha_close_table(SQL_HANDLER *handler) ...@@ -170,15 +217,17 @@ static void mysql_ha_close_table(SQL_HANDLER *handler)
} }
table->file->ha_index_or_rnd_end(); table->file->ha_index_or_rnd_end();
table->open_by_handler= 0;
close_thread_table(thd, &table); close_thread_table(thd, &table);
if (current_table_list)
mysql_ha_close_childs(thd, current_table_list, &next_global);
thd->mdl_context.release_lock(handler->mdl_request.ticket); thd->mdl_context.release_lock(handler->mdl_request.ticket);
} }
else else
{ {
/* Must be a temporary table */ /* Must be a temporary table */
table->file->ha_index_or_rnd_end(); table->file->ha_index_or_rnd_end();
table->open_by_handler= 0; if (current_table_list)
mysql_ha_close_childs(thd, current_table_list, &next_global);
thd->mark_tmp_table_as_free_for_reuse(table); thd->mark_tmp_table_as_free_for_reuse(table);
} }
my_free(handler->lock); my_free(handler->lock);
...@@ -309,15 +358,24 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, SQL_HANDLER *reopen) ...@@ -309,15 +358,24 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, SQL_HANDLER *reopen)
goto err; goto err;
} }
if (tables->mdl_request.ticket && DBUG_PRINT("info",("clone_tickets start"));
thd->mdl_context.has_lock(mdl_savepoint, tables->mdl_request.ticket)) for (TABLE_LIST *table_list= tables; table_list;
table_list= table_list->next_global)
{
DBUG_PRINT("info",("table_list %s.%s", table_list->table->s->db.str,
table_list->table->s->table_name.str));
if (table_list->mdl_request.ticket &&
thd->mdl_context.has_lock(mdl_savepoint, table_list->mdl_request.ticket))
{ {
DBUG_PRINT("info",("clone_tickets"));
/* The ticket returned is within a savepoint. Make a copy. */ /* The ticket returned is within a savepoint. Make a copy. */
error= thd->mdl_context.clone_ticket(&tables->mdl_request); error= thd->mdl_context.clone_ticket(&table_list->mdl_request);
tables->table->mdl_ticket= tables->mdl_request.ticket; table_list->table->mdl_ticket= table_list->mdl_request.ticket;
if (error) if (error)
goto err; goto err;
} }
}
DBUG_PRINT("info",("clone_tickets end"));
if (! reopen) if (! reopen)
{ {
...@@ -378,26 +436,37 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, SQL_HANDLER *reopen) ...@@ -378,26 +436,37 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, SQL_HANDLER *reopen)
/* Restore the state. */ /* Restore the state. */
thd->set_open_tables(backup_open_tables); thd->set_open_tables(backup_open_tables);
DBUG_PRINT("info",("set_lock_duration start"));
if (sql_handler->mdl_request.ticket) if (sql_handler->mdl_request.ticket)
{ {
thd->mdl_context.set_lock_duration(sql_handler->mdl_request.ticket, thd->mdl_context.set_lock_duration(sql_handler->mdl_request.ticket,
MDL_EXPLICIT); MDL_EXPLICIT);
thd->mdl_context.set_needs_thr_lock_abort(TRUE); thd->mdl_context.set_needs_thr_lock_abort(TRUE);
} }
for (TABLE_LIST *table_list= tables->next_global; table_list;
table_list= table_list->next_global)
{
DBUG_PRINT("info",("table_list %s.%s", table_list->table->s->db.str,
table_list->table->s->table_name.str));
if (table_list->mdl_request.ticket)
{
thd->mdl_context.set_lock_duration(table_list->mdl_request.ticket,
MDL_EXPLICIT);
thd->mdl_context.set_needs_thr_lock_abort(TRUE);
}
}
DBUG_PRINT("info",("set_lock_duration end"));
/*
Assert that the above check prevents opening of views and merge tables.
For temporary tables, TABLE::next can be set even if only one table
was opened for HANDLER as it is used to link them together.
*/
DBUG_ASSERT(sql_handler->table->next == NULL ||
sql_handler->table->s->tmp_table);
/* /*
If it's a temp table, don't reset table->query_id as the table is If it's a temp table, don't reset table->query_id as the table is
being used by this handler. For non-temp tables we use this flag being used by this handler. For non-temp tables we use this flag
in asserts. in asserts.
*/ */
table->open_by_handler= 1; for (TABLE_LIST *table_list= tables; table_list;
table_list= table_list->next_global)
{
table_list->table->open_by_handler= 1;
}
/* Safety, cleanup the pointer to satisfy MDL assertions. */ /* Safety, cleanup the pointer to satisfy MDL assertions. */
tables->mdl_request.ticket= NULL; tables->mdl_request.ticket= NULL;
...@@ -707,8 +776,14 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables, ...@@ -707,8 +776,14 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
{ {
int lock_error; int lock_error;
if (handler->lock->lock_count > 0) THR_LOCK_DATA **pos,**end;
handler->lock->locks[0]->type= handler->lock->locks[0]->org_type; for (pos= handler->lock->locks,
end= handler->lock->locks + handler->lock->lock_count;
pos < end;
pos++)
{
pos[0]->type= pos[0]->org_type;
}
/* save open_tables state */ /* save open_tables state */
TABLE* backup_open_tables= thd->open_tables; TABLE* backup_open_tables= thd->open_tables;
......
...@@ -9,4 +9,3 @@ return "Test needs --big-test" unless $::opt_big_test; ...@@ -9,4 +9,3 @@ return "Test needs --big-test" unless $::opt_big_test;
sub is_default { 1 } sub is_default { 1 }
bless { }; bless { };
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment