summaryrefslogtreecommitdiff
path: root/sql/sql_update.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_update.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_update.cc')
-rw-r--r--sql/sql_update.cc96
1 files changed, 87 insertions, 9 deletions
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index bd577426483..0b6564d8e49 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -255,11 +255,12 @@ int mysql_update(THD *thd,
{
bool using_limit= limit != HA_POS_ERROR;
bool safe_update= thd->variables.option_bits & OPTION_SAFE_UPDATES;
- bool used_key_is_modified= FALSE, transactional_table, will_batch;
+ bool used_key_is_modified= FALSE, transactional_table;
+ bool will_batch= FALSE;
bool can_compare_record;
int res;
int error, loc_error;
- uint dup_key_found;
+ ha_rows dup_key_found;
bool need_sort= TRUE;
bool reverse= FALSE;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
@@ -276,6 +277,7 @@ int mysql_update(THD *thd,
ulonglong id;
List<Item> all_fields;
killed_state killed_status= NOT_KILLED;
+ bool has_triggers, binlog_is_row, do_direct_update= FALSE;
Update_plan query_plan(thd->mem_root);
Explain_update *explain;
TABLE_LIST *update_source_table;
@@ -287,7 +289,7 @@ int mysql_update(THD *thd,
if (open_tables(thd, &table_list, &table_count, 0))
DBUG_RETURN(1);
- //Prepare views so they are handled correctly.
+ /* Prepare views so they are handled correctly */
if (mysql_handle_derived(thd->lex, DT_INIT))
DBUG_RETURN(1);
@@ -515,7 +517,6 @@ int mysql_update(THD *thd,
query_plan.using_io_buffer= true;
}
-
/*
Ok, we have generated a query plan for the UPDATE.
- if we're running EXPLAIN UPDATE, goto produce explain output
@@ -530,10 +531,68 @@ int mysql_update(THD *thd,
DBUG_EXECUTE_IF("show_explain_probe_update_exec_start",
dbug_serve_apcs(thd, 1););
-
+
+ has_triggers= (table->triggers &&
+ (table->triggers->has_triggers(TRG_EVENT_UPDATE,
+ TRG_ACTION_BEFORE) ||
+ table->triggers->has_triggers(TRG_EVENT_UPDATE,
+ TRG_ACTION_AFTER)));
+ DBUG_PRINT("info", ("has_triggers: %s", has_triggers ? "TRUE" : "FALSE"));
+ binlog_is_row= thd->is_current_stmt_binlog_format_row();
+ DBUG_PRINT("info", ("binlog_is_row: %s", binlog_is_row ? "TRUE" : "FALSE"));
+
if (!(select && select->quick))
status_var_increment(thd->status_var.update_scan_count);
+ /*
+ We can use direct update (update that is done silently in the handler)
+ if none of the following conditions are true:
+ - There are triggers
+ - There is binary logging
+ - using_io_buffer
+ - This means that the partition changed or the key we want
+ to use for scanning the table is changed
+ - ignore is set
+ - Direct updates don't return the number of ignored rows
+ - There is a virtual not stored column in the WHERE clause
+ - Changing a field used by a stored virtual column, which
+ would require the column to be recalculated.
+ - ORDER BY or LIMIT
+ - As this requires the rows to be updated 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_update_rows_init().
+
+ Direct update 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 &&
+ !query_plan.using_io_buffer && !ignore &&
+ !table->check_virtual_columns_marked_for_read() &&
+ !table->check_virtual_columns_marked_for_write())
+ {
+ DBUG_PRINT("info", ("Trying direct update"));
+ 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->info_push(INFO_KIND_UPDATE_FIELDS, &fields) &&
+ !table->file->info_push(INFO_KIND_UPDATE_VALUES, &values) &&
+ !table->file->direct_update_rows_init())
+ {
+ do_direct_update= TRUE;
+
+ /* Direct update is not using_filesort and is not using_io_buffer */
+ goto update_begin;
+ }
+ }
+
if (query_plan.using_filesort || query_plan.using_io_buffer)
{
/*
@@ -693,6 +752,7 @@ int mysql_update(THD *thd,
}
}
+update_begin:
if (ignore)
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
@@ -712,11 +772,20 @@ int mysql_update(THD *thd,
transactional_table= table->file->has_transactions();
thd->abort_on_warning= !ignore && thd->is_strict_mode();
- if (table->prepare_triggers_for_update_stmt_or_event())
+
+ if (do_direct_update)
{
- will_batch= FALSE;
+ /* Direct updating is supported */
+ DBUG_PRINT("info", ("Using direct update"));
+ table->reset_default_fields();
+ if (!(error= table->file->ha_direct_update_rows(&updated)))
+ error= -1;
+ found= updated;
+ goto update_end;
}
- else
+
+ if ((table->file->ha_table_flags() & HA_CAN_FORCE_BULK_UPDATE) &&
+ !table->prepare_triggers_for_update_stmt_or_event())
will_batch= !table->file->start_bulk_update();
/*
@@ -801,6 +870,7 @@ int mysql_update(THD *thd,
call then it should be included in the count of dup_key_found
and error should be set to 0 (only if these errors are ignored).
*/
+ DBUG_PRINT("info", ("Batched update"));
error= table->file->ha_bulk_update_row(table->record[1],
table->record[0],
&dup_key_found);
@@ -949,6 +1019,8 @@ int mysql_update(THD *thd,
updated-= dup_key_found;
if (will_batch)
table->file->end_bulk_update();
+
+update_end:
table->file->try_semi_consistent_read(0);
if (!transactional_table && updated > 0)
@@ -1004,6 +1076,11 @@ int mysql_update(THD *thd,
DBUG_ASSERT(transactional_table || !updated || thd->transaction.stmt.modified_non_trans_table);
free_underlaid_joins(thd, select_lex);
delete file_sort;
+ if (table->file->pushed_cond)
+ {
+ table->file->pushed_cond= 0;
+ table->file->cond_pop();
+ }
/* If LAST_INSERT_ID(X) was used, report X */
id= thd->arg_of_last_insert_id_function ?
@@ -1029,7 +1106,6 @@ int mysql_update(THD *thd,
*found_return= found;
*updated_return= updated;
-
if (thd->lex->analyze_stmt)
goto emit_explain_and_leave;
@@ -1040,6 +1116,8 @@ err:
delete file_sort;
free_underlaid_joins(thd, select_lex);
table->file->ha_end_keyread();
+ if (table->file->pushed_cond)
+ table->file->cond_pop();
thd->abort_on_warning= 0;
DBUG_RETURN(1);