summaryrefslogtreecommitdiff
path: root/sql/sql_delete.cc
diff options
context:
space:
mode:
authorKentoku SHIBA <kentokushiba@gmail.com>2017-11-16 11:11:52 +0200
committerMonty <monty@mariadb.org>2017-12-03 13:58:36 +0200
commite53ef202bd7706b88760472472af5ae878065f4f (patch)
treeb4835ec250e0e00d06097da05a28206ca75df75d /sql/sql_delete.cc
parentd1e4ecec07b0611d3d0cbbf53342246ca2c4f600 (diff)
downloadmariadb-git-e53ef202bd7706b88760472472af5ae878065f4f.tar.gz
Adding direct update/delete to the server and to the partition engine.
Add support for direct update and direct delete requests for spider. A direct update/delete request handles all qualified rows in a single operation rather than one row at a time. Contains Spiral patches: 006_mariadb-10.2.0.direct_update_rows.diff MDEV-7704 008_mariadb-10.2.0.partition_direct_update.diff MDEV-7706 010_mariadb-10.2.0.direct_update_rows2.diff MDEV-7708 011_mariadb-10.2.0.aggregate.diff MDEV-7709 027_mariadb-10.2.0.force_bulk_update.diff MDEV-7724 061_mariadb-10.2.0.mariadb-10.1.8.diff MDEV-12870 - The differences compared to the original patches: - Most of the parameters of the new functions are unnecessary. The unnecessary parameters have been removed. - Changed bit positions for new handler flags upon consideration of handler flags not needed by other Spiral patches and handler flags merged from MySQL. - Added info_push() (Was originally part of bulk access patch) - Didn't include code related to handler socket - Added HA_CAN_DIRECT_UPDATE_AND_DELETE Original author: Kentoku SHIBA First reviewer: Jacob Mathew Second reviewer: Michael Widenius
Diffstat (limited to 'sql/sql_delete.cc')
-rw-r--r--sql/sql_delete.cc75
1 files changed, 63 insertions, 12 deletions
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 0d4bed836b8..984a0799b54 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -250,7 +250,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
SQL_I_List<ORDER> *order_list, ha_rows limit,
ulonglong options, select_result *result)
{
- bool will_batch;
+ bool will_batch= FALSE;
int error, loc_error;
TABLE *table;
SQL_SELECT *select=0;
@@ -262,11 +262,13 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
bool return_error= 0;
ha_rows deleted= 0;
bool reverse= FALSE;
+ bool has_triggers;
ORDER *order= (ORDER *) ((order_list && order_list->elements) ?
order_list->first : NULL);
SELECT_LEX *select_lex= &thd->lex->select_lex;
killed_state killed_status= NOT_KILLED;
THD::enum_binlog_query_type query_type= THD::ROW_QUERY_TYPE;
+ bool binlog_is_row;
bool with_select= !select_lex->item_list.is_empty();
Explain_delete *explain;
Delete_plan query_plan(thd->mem_root);
@@ -371,9 +373,12 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
- We should not be binlogging this statement in row-based, and
- there should be no delete triggers associated with the table.
*/
+
+ has_triggers= (table->triggers &&
+ table->triggers->has_delete_triggers());
if (!with_select && !using_limit && const_cond_result &&
(!thd->is_current_stmt_binlog_format_row() &&
- !(table->triggers && table->triggers->has_delete_triggers())))
+ !has_triggers))
{
/* Update the table->file->stats.records number */
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
@@ -522,14 +527,59 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
if (!(select && select->quick))
status_var_increment(thd->status_var.delete_scan_count);
- if (query_plan.using_filesort)
+ binlog_is_row= thd->is_current_stmt_binlog_format_row();
+ DBUG_PRINT("info", ("binlog_is_row: %s", binlog_is_row ? "TRUE" : "FALSE"));
+
+ /*
+ We can use direct delete (delete that is done silently in the handler)
+ if none of the following conditions are true:
+ - There are triggers
+ - There is binary logging
+ - There is a virtual not stored column in the WHERE clause
+ - ORDER BY or LIMIT
+ - As this requires the rows to be deleted in a specific order
+ - Note that Spider can handle ORDER BY and LIMIT in a cluster with
+ one data node. These conditions are therefore checked in
+ direct_delete_rows_init().
+
+ Direct delete does not require a WHERE clause
+
+ Later we also ensure that we are only using one table (no sub queries)
+ */
+
+ if ((table->file->ha_table_flags() & HA_CAN_DIRECT_UPDATE_AND_DELETE) &&
+ !has_triggers && !binlog_is_row && !with_select)
{
+ table->mark_columns_needed_for_delete();
+ if (!table->check_virtual_columns_marked_for_read())
+ {
+ DBUG_PRINT("info", ("Trying direct delete"));
+ if (select && select->cond &&
+ (select->cond->used_tables() == table->map))
+ {
+ DBUG_ASSERT(!table->file->pushed_cond);
+ if (!table->file->cond_push(select->cond))
+ table->file->pushed_cond= select->cond;
+ }
+ if (!table->file->direct_delete_rows_init())
+ {
+ /* Direct deleting is supported */
+ DBUG_PRINT("info", ("Using direct delete"));
+ THD_STAGE_INFO(thd, stage_updating);
+ if (!(error= table->file->ha_direct_delete_rows(&deleted)))
+ error= -1;
+ goto terminate_delete;
+ }
+ }
+ }
+ if (query_plan.using_filesort)
+ {
{
Filesort fsort(order, HA_POS_ERROR, true, select);
DBUG_ASSERT(query_plan.index == MAX_KEY);
- Filesort_tracker *fs_tracker=
+ Filesort_tracker *fs_tracker=
thd->lex->explain->get_upd_del_plan()->filesort_tracker;
if (!(file_sort= filesort(thd, table, &fsort, fs_tracker)))
@@ -568,15 +618,12 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
if (init_ftfuncs(thd, select_lex, 1))
goto got_error;
- if (table->prepare_triggers_for_delete_stmt_or_event())
- {
- will_batch= FALSE;
- }
- else
- will_batch= !table->file->start_bulk_delete();
-
table->mark_columns_needed_for_delete();
+ if ((table->file->ha_table_flags() & HA_CAN_FORCE_BULK_DELETE) &&
+ !table->prepare_triggers_for_delete_stmt_or_event())
+ will_batch= !table->file->start_bulk_delete();
+
if (with_select)
{
if (result->send_result_set_metadata(select_lex->item_list,
@@ -683,6 +730,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
else
break;
}
+
terminate_delete:
killed_status= thd->killed;
if (killed_status != NOT_KILLED || thd->is_error())
@@ -769,6 +817,8 @@ cleanup:
}
delete file_sort;
free_underlaid_joins(thd, select_lex);
+ if (table->file->pushed_cond)
+ table->file->cond_pop();
DBUG_RETURN(error >= 0 || thd->is_error());
/* Special exits */
@@ -790,7 +840,8 @@ send_nothing_and_leave:
delete select;
delete file_sort;
free_underlaid_joins(thd, select_lex);
- //table->set_keyread(false);
+ if (table->file->pushed_cond)
+ table->file->cond_pop();
DBUG_ASSERT(!return_error || thd->is_error() || thd->killed);
DBUG_RETURN((return_error || thd->is_error() || thd->killed) ? 1 : 0);