summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacob Mathew <jacob.mathew@mariadb.com>2017-10-14 15:24:24 -0700
committerJacob Mathew <jacob.mathew@mariadb.com>2017-11-10 13:38:09 -0800
commit26211d5567d72e502f6edaaab7bdefbafd92cdd8 (patch)
tree045dfe3b51d5b1a02c24b0ae1bd2accc8a6c1800
parent6e2e040432b7ade5c42f3feb0902d0286a2d3466 (diff)
downloadmariadb-git-bb-10.2-spider-extra-jacob.tar.gz
Adding direct update/delete to the server and to the partition engine.bb-10.2-spider-extra-jacob
Contains Spiral patches: - Spiral Patch 006: 006_mariadb-10.2.0.direct_update_rows.diff MDEV-7704 - Spiral Patch 008: 008_mariadb-10.2.0.partition_direct_update.diff MDEV-7706 - Spiral Patch 010: 010_mariadb-10.2.0.direct_update_rows2.diff MDEV-7708 - Spiral Patch 011: 011_mariadb-10.2.0.aggregate.diff MDEV-7709 - Spiral Patch 027: 027_mariadb-10.2.0.force_bulk_update.diff MDEV-7724 - Spiral Patch 061: 061_mariadb-10.2.0.mariadb-10.1.8.diff MDEV-12870 - Add support for direct update and direct delete requests. A direct update/delete request handles all qualified rows in a single operation, rather than one row at a time. - This commit has the following 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.
-rw-r--r--sql/ha_partition.cc656
-rw-r--r--sql/ha_partition.h21
-rw-r--r--sql/handler.cc91
-rw-r--r--sql/handler.h160
-rw-r--r--sql/opt_sum.cc9
-rw-r--r--sql/sql_delete.cc72
-rw-r--r--sql/sql_update.cc93
-rw-r--r--sql/table.cc53
-rw-r--r--sql/table.h2
-rw-r--r--storage/spider/ha_spider.cc26
-rw-r--r--storage/spider/ha_spider.h62
-rw-r--r--storage/spider/mysql-test/spider/bg/r/direct_update.result8
-rw-r--r--storage/spider/mysql-test/spider/bg/r/direct_update_part.result8
-rw-r--r--storage/spider/mysql-test/spider/bg/r/spider_fixes.result1
-rw-r--r--storage/spider/mysql-test/spider/handler/r/direct_update.result8
-rw-r--r--storage/spider/mysql-test/spider/handler/r/direct_update_part.result8
-rw-r--r--storage/spider/mysql-test/spider/handler/r/spider_fixes.result1
-rw-r--r--storage/spider/mysql-test/spider/r/direct_update.result8
-rw-r--r--storage/spider/mysql-test/spider/r/direct_update_part.result8
-rw-r--r--storage/spider/mysql-test/spider/r/spider_fixes.result1
-rw-r--r--storage/spider/spd_db_conn.cc22
-rw-r--r--storage/spider/spd_db_conn.h10
-rw-r--r--storage/spider/spd_environ.h3
23 files changed, 1221 insertions, 110 deletions
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index 16dca66dd06..ab825504121 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -7231,6 +7231,7 @@ FT_INFO *ha_partition::ft_init_ext(uint flags, uint inx, String *key)
DBUG_RETURN((FT_INFO*)ft_target);
}
+
/**
Return the next record from the FT result set during an ordered index
pre-scan
@@ -7245,7 +7246,7 @@ int ha_partition::pre_ft_read(bool use_parallel)
{
int error;
DBUG_ENTER("ha_partition::pre_ft_read");
- DBUG_PRINT("info", ("partition this=%p", this));
+ DBUG_PRINT("info", ("partition this: %p", this));
m_pre_calling= TRUE;
m_pre_call_use_parallel= use_parallel;
error= ft_read(table->record[0]);
@@ -11224,6 +11225,659 @@ void ha_partition::cond_pop()
/**
+ Perform bulk update preparation on each partition.
+
+ SYNOPSIS
+ start_bulk_update()
+
+ RETURN VALUE
+ TRUE Error
+ FALSE Success
+*/
+
+bool ha_partition::start_bulk_update()
+{
+ handler **file= m_file;
+ DBUG_ENTER("ha_partition::start_bulk_update");
+
+ if (bitmap_is_overlapping(&m_part_info->full_part_field_set,
+ table->write_set))
+ DBUG_RETURN(TRUE);
+
+ do
+ {
+ if ((*file)->start_bulk_update())
+ DBUG_RETURN(TRUE);
+ } while (*(++file));
+ DBUG_RETURN(FALSE);
+}
+
+
+/**
+ Perform bulk update execution on each partition. A bulk update allows
+ a handler to batch the updated rows instead of performing the updates
+ one row at a time.
+
+ SYNOPSIS
+ exec_bulk_update()
+
+ RETURN VALUE
+ TRUE Error
+ FALSE Success
+*/
+
+int ha_partition::exec_bulk_update(ha_rows *dup_key_found)
+{
+ int error;
+ handler **file= m_file;
+ DBUG_ENTER("ha_partition::exec_bulk_update");
+
+ do
+ {
+ if ((error= (*file)->exec_bulk_update(dup_key_found)))
+ DBUG_RETURN(error);
+ } while (*(++file));
+ DBUG_RETURN(0);
+}
+
+
+/**
+ Perform bulk update cleanup on each partition.
+
+ SYNOPSIS
+ end_bulk_update()
+
+ RETURN VALUE
+ NONE
+*/
+
+int ha_partition::end_bulk_update()
+{
+ int error= 0;
+ handler **file= m_file;
+ DBUG_ENTER("ha_partition::end_bulk_update");
+
+ do
+ {
+ int tmp;
+ if ((tmp= (*file)->end_bulk_update()))
+ error= tmp;
+ } while (*(++file));
+ DBUG_RETURN(error);
+}
+
+
+/**
+ Add the row to the bulk update on the partition on which the row is stored.
+ A bulk update allows a handler to batch the updated rows instead of
+ performing the updates one row at a time.
+
+ SYNOPSIS
+ bulk_update_row()
+ old_data Old record
+ new_data New record
+ dup_key_found Number of duplicate keys found
+
+ RETURN VALUE
+ >1 Error
+ 1 Bulk update not used, normal operation used
+ 0 Bulk update used by handler
+*/
+
+int ha_partition::bulk_update_row(const uchar *old_data, uchar *new_data,
+ ha_rows *dup_key_found)
+{
+ int error= 0;
+ uint32 part_id;
+ longlong func_value;
+ my_bitmap_map *old_map;
+ DBUG_ENTER("ha_partition::bulk_update_row");
+
+ old_map= dbug_tmp_use_all_columns(table, table->read_set);
+ error= m_part_info->get_partition_id(m_part_info, &part_id,
+ &func_value);
+ dbug_tmp_restore_column_map(table->read_set, old_map);
+ if (unlikely(error))
+ {
+ m_part_info->err_value= func_value;
+ goto end;
+ }
+
+ error= m_file[part_id]->ha_bulk_update_row(old_data, new_data,
+ dup_key_found);
+
+end:
+ DBUG_RETURN(error);
+}
+
+
+/**
+ Perform bulk delete preparation on each partition.
+
+ SYNOPSIS
+ start_bulk_delete()
+
+ RETURN VALUE
+ TRUE Error
+ FALSE Success
+*/
+
+bool ha_partition::start_bulk_delete()
+{
+ handler **file= m_file;
+ DBUG_ENTER("ha_partition::start_bulk_delete");
+
+ do
+ {
+ if ((*file)->start_bulk_delete())
+ DBUG_RETURN(TRUE);
+ } while (*(++file));
+ DBUG_RETURN(FALSE);
+}
+
+
+/**
+ Perform bulk delete cleanup on each partition.
+
+ SYNOPSIS
+ end_bulk_delete()
+
+ RETURN VALUE
+ >0 Error
+ 0 Success
+*/
+
+int ha_partition::end_bulk_delete()
+{
+ int error= 0;
+ handler **file= m_file;
+ DBUG_ENTER("ha_partition::end_bulk_delete");
+
+ do
+ {
+ int tmp;
+ if ((tmp= (*file)->end_bulk_delete()))
+ error= tmp;
+ } while (*(++file));
+ DBUG_RETURN(error);
+}
+
+
+/**
+ Perform initialization for a direct update request.
+
+ SYNOPSIS
+ direct_update_rows_init()
+
+ RETURN VALUE
+ >0 Error
+ 0 Success
+*/
+
+int ha_partition::direct_update_rows_init()
+{
+ int error;
+ uint i, j;
+ handler *file;
+ DBUG_ENTER("ha_partition::direct_update_rows_init");
+
+ if (bitmap_is_overlapping(&m_part_info->full_part_field_set,
+ table->write_set)
+#if defined(HS_HAS_SQLCOM)
+ && (thd_sql_command(ha_thd()) != SQLCOM_HS_UPDATE ||
+ check_hs_update_overlapping(&ranges->start_key))
+#endif
+ )
+ {
+ DBUG_PRINT("info", ("partition FALSE by updating part_key"));
+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
+ }
+
+ m_part_spec.start_part= 0;
+ m_part_spec.end_part= m_tot_parts - 1;
+ m_direct_update_part_spec= m_part_spec;
+
+ j= 0;
+ for (i= m_part_spec.start_part; i <= m_part_spec.end_part; i++)
+ {
+ if (bitmap_is_set(&(m_part_info->read_partitions), i) &&
+ bitmap_is_set(&(m_part_info->lock_partitions), i))
+ {
+ file= m_file[i];
+ if ((error= (m_pre_calling ?
+ file->pre_direct_update_rows_init() :
+ file->direct_update_rows_init())))
+ {
+ DBUG_PRINT("info", ("partition FALSE by storage engine"));
+ DBUG_RETURN(error);
+ }
+ j++;
+ }
+ }
+
+ TABLE_LIST *table_list= table->pos_in_table_list;
+ if (j != 1 && table_list)
+ {
+ while (table_list->parent_l)
+ table_list= table_list->parent_l;
+ st_select_lex *select_lex= table_list->select_lex;
+ DBUG_PRINT("info", ("partition select_lex=%p", select_lex));
+ if (select_lex && select_lex->explicit_limit)
+ {
+ DBUG_PRINT("info", ("partition explicit_limit=TRUE"));
+ DBUG_PRINT("info", ("partition offset_limit=%p",
+ select_lex->offset_limit));
+ DBUG_PRINT("info", ("partition select_limit=%p",
+ select_lex->select_limit));
+ DBUG_PRINT("info", ("partition FALSE by select_lex"));
+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
+ }
+ }
+ DBUG_PRINT("info", ("partition OK"));
+ DBUG_RETURN(0);
+}
+
+
+/**
+ Do initialization for performing parallel direct update
+ for a handlersocket update request.
+
+ SYNOPSIS
+ pre_direct_update_rows_init()
+
+ RETURN VALUE
+ >0 Error
+ 0 Success
+*/
+
+int ha_partition::pre_direct_update_rows_init()
+{
+ int error;
+ DBUG_ENTER("ha_partition::pre_direct_update_rows_init");
+ m_pre_calling= TRUE;
+ error= direct_update_rows_init();
+ m_pre_calling= FALSE;
+ if (!error && bulk_access_started)
+ bulk_access_info_current->called= TRUE;
+ DBUG_RETURN(error);
+}
+
+
+/**
+ Execute a direct update request. A direct update request updates all
+ qualified rows in a single operation, rather than one row at a time.
+ The direct update operation is pushed down to each individual
+ partition.
+
+ SYNOPSIS
+ direct_update_rows()
+ update_rows Number of updated rows
+
+ RETURN VALUE
+ >0 Error
+ 0 Success
+*/
+
+int ha_partition::direct_update_rows(ha_rows *update_rows_result)
+{
+ int error;
+ bool rnd_seq= FALSE;
+ ha_rows update_rows= 0;
+ uint32 i;
+ handler *file;
+ DBUG_ENTER("ha_partition::direct_update_rows");
+
+ /* If first call to direct_update_rows with RND scan */
+ if ((m_pre_calling ? pre_inited : inited) == RND && m_scan_value == 1)
+ {
+ rnd_seq= TRUE;
+ m_scan_value= 2;
+ }
+
+ *update_rows_result= 0;
+ for (i= m_part_spec.start_part; i <= m_part_spec.end_part; i++)
+ {
+ file= m_file[i];
+ if (bitmap_is_set(&(m_part_info->read_partitions), i) &&
+ bitmap_is_set(&(m_part_info->lock_partitions), i))
+ {
+ if (rnd_seq && (m_pre_calling ? file->pre_inited : file->inited) == NONE)
+ {
+ if ((error= (m_pre_calling ?
+ file->ha_pre_rnd_init(TRUE) :
+ file->ha_rnd_init(TRUE))))
+ DBUG_RETURN(error);
+ }
+ if ((error= (m_pre_calling ?
+ (file)->ha_pre_direct_update_rows() :
+ (file)->ha_direct_update_rows(&update_rows))))
+ {
+ if (rnd_seq)
+ {
+ if (m_pre_calling)
+ file->ha_pre_rnd_end();
+ else
+ file->ha_rnd_end();
+ }
+ DBUG_RETURN(error);
+ }
+ *update_rows_result+= update_rows;
+ if (m_pre_calling)
+ bitmap_set_bit(&bulk_access_exec_bitmap, i);
+ }
+ if (rnd_seq)
+ {
+ if ((error= (m_pre_calling ?
+ file->ha_pre_index_or_rnd_end() :
+ file->ha_index_or_rnd_end())))
+ DBUG_RETURN(error);
+ }
+ }
+ DBUG_RETURN(0);
+}
+
+
+/**
+ Start parallel execution of a direct update for a handlersocket update
+ request. A direct update request updates all qualified rows in a single
+ operation, rather than one row at a time. The direct update operation
+ is pushed down to each individual partition.
+
+ SYNOPSIS
+ pre_direct_update_rows()
+
+ RETURN VALUE
+ >0 Error
+ 0 Success
+*/
+
+int ha_partition::pre_direct_update_rows()
+{
+ int error;
+ ha_rows not_used= 0;
+ DBUG_ENTER("ha_partition::pre_direct_update_rows");
+ m_pre_calling= TRUE;
+ error= direct_update_rows(&not_used);
+ m_pre_calling= FALSE;
+ DBUG_RETURN(error);
+}
+
+
+#if defined(HS_HAS_SQLCOM)
+/**
+ Determine whether a key value being updated includes partition columns
+ when using handlersocket
+
+ SYNOPSIS
+ check_hs_update_overlapping()
+ key Key value
+
+ RETURN VALUE
+ TRUE The key value being updated does not include
+ partition columns
+ FALSE The key value being updated does include
+ partition columns
+*/
+
+bool ha_partition::check_hs_update_overlapping(key_range *key)
+{
+ Field *field;
+ uint store_length, length, var_len, field_index;
+ const uchar *ptr;
+ bool key_eq;
+ KEY *key_info;
+ KEY_PART_INFO *key_part;
+ key_part_map tgt_key_part_map= key->keypart_map;
+ char buf[MAX_FIELD_WIDTH], buf2[MAX_FIELD_WIDTH];
+ String tmp_str(buf, MAX_FIELD_WIDTH, &my_charset_bin), *str,
+ tmp_str2(buf2, MAX_FIELD_WIDTH, &my_charset_bin), *str2;
+ DBUG_ENTER("ha_partition::check_hs_update_overlapping");
+
+ key_info= &table->key_info[active_index];
+ for (key_part= key_info->key_part,
+ store_length= key_part->store_length, length= 0;
+ tgt_key_part_map;
+ length += store_length, tgt_key_part_map >>= 1, key_part++,
+ store_length= key_part->store_length)
+ {
+ field= key_part->field;
+ field_index= field->field_index;
+ if (bitmap_is_set(&m_part_info->full_part_field_set, field_index) &&
+ bitmap_is_set(table->write_set, field_index))
+ {
+ ptr= key->key + length;
+ key_eq= (tgt_key_part_map > 1);
+ if (key_part->null_bit && *ptr++)
+ {
+ if (key->flag != HA_READ_KEY_EXACT || !field->is_null())
+ {
+ DBUG_PRINT("info", ("spider flag=%u is_null=%s",
+ key->flag,
+ field->is_null() ? "TRUE" : "FALSE"));
+ DBUG_RETURN(TRUE);
+ }
+ }
+ else
+ {
+ if (field->type() == MYSQL_TYPE_BLOB ||
+ field->real_type() == MYSQL_TYPE_VARCHAR ||
+ field->type() == MYSQL_TYPE_GEOMETRY)
+ {
+ var_len= uint2korr(ptr);
+ tmp_str.set_quick((char *)ptr + HA_KEY_BLOB_LENGTH, var_len,
+ &my_charset_bin);
+ str= &tmp_str;
+ }
+ else
+ str= field->val_str(&tmp_str, ptr);
+ str2= field->val_str(&tmp_str2);
+ if (str->length() != str2->length() ||
+ memcmp(str->ptr(), str2->ptr(), str->length()))
+ {
+ DBUG_PRINT("info", ("spider length=%u %u",
+ str->length(), str2->length()));
+ DBUG_PRINT("info", ("spider length=%s %s",
+ str->c_ptr_safe(), str2->c_ptr_safe()));
+ DBUG_RETURN(TRUE);
+ }
+ }
+ }
+ }
+
+ DBUG_PRINT("info", ("partition return FALSE"));
+ DBUG_RETURN(FALSE);
+}
+#endif
+
+
+/**
+ Perform initialization for a direct delete request.
+
+ SYNOPSIS
+ direct_delete_rows_init()
+
+ RETURN VALUE
+ >0 Error
+ 0 Success
+*/
+
+int ha_partition::direct_delete_rows_init()
+{
+ int error;
+ uint i, j;
+ handler *file;
+ DBUG_ENTER("ha_partition::direct_delete_rows_init");
+
+ m_part_spec.start_part= 0;
+ m_part_spec.end_part= m_tot_parts - 1;
+ m_direct_update_part_spec= m_part_spec;
+
+ j= 0;
+ for (i= m_part_spec.start_part; i <= m_part_spec.end_part; i++)
+ {
+ if (bitmap_is_set(&(m_part_info->read_partitions), i) &&
+ bitmap_is_set(&(m_part_info->lock_partitions), i))
+ {
+ file= m_file[i];
+ if ((error= (m_pre_calling ?
+ file->pre_direct_delete_rows_init() :
+ file->direct_delete_rows_init())))
+ {
+ DBUG_PRINT("info", ("partition FALSE by storage engine"));
+ DBUG_RETURN(error);
+ }
+ j++;
+ }
+ }
+
+ TABLE_LIST *table_list= table->pos_in_table_list;
+ if (j != 1 && table_list)
+ {
+ while (table_list->parent_l)
+ table_list= table_list->parent_l;
+ st_select_lex *select_lex= table_list->select_lex;
+ DBUG_PRINT("info", ("partition select_lex=%p", select_lex));
+ if (select_lex && select_lex->explicit_limit)
+ {
+ DBUG_PRINT("info", ("partition explicit_limit=TRUE"));
+ DBUG_PRINT("info", ("partition offset_limit=%p",
+ select_lex->offset_limit));
+ DBUG_PRINT("info", ("partition select_limit=%p",
+ select_lex->select_limit));
+ DBUG_PRINT("info", ("partition FALSE by select_lex"));
+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
+ }
+ }
+ DBUG_PRINT("info", ("partition OK"));
+ DBUG_RETURN(0);
+}
+
+
+/**
+ Do initialization for performing parallel direct delete
+ for a handlersocket delete request.
+
+ SYNOPSIS
+ pre_direct_delete_rows_init()
+
+ RETURN VALUE
+ >0 Error
+ 0 Success
+*/
+
+int ha_partition::pre_direct_delete_rows_init()
+{
+ int error;
+ DBUG_ENTER("ha_partition::pre_direct_delete_rows_init");
+ m_pre_calling= TRUE;
+ error= direct_delete_rows_init();
+ m_pre_calling= FALSE;
+ if (bulk_access_started)
+ bulk_access_info_current->called= TRUE;
+ DBUG_RETURN(error);
+}
+
+
+/**
+ Execute a direct delete request. A direct delete request deletes all
+ qualified rows in a single operation, rather than one row at a time.
+ The direct delete operation is pushed down to each individual
+ partition.
+
+ SYNOPSIS
+ direct_delete_rows()
+ delete_rows Number of deleted rows
+
+ RETURN VALUE
+ >0 Error
+ 0 Success
+*/
+
+int ha_partition::direct_delete_rows(ha_rows *delete_rows_result)
+{
+ int error;
+ bool rnd_seq= FALSE;
+ ha_rows delete_rows= 0;
+ uint32 i;
+ handler *file;
+ DBUG_ENTER("ha_partition::direct_delete_rows");
+
+ if ((m_pre_calling ? pre_inited : inited) == RND && m_scan_value == 1)
+ {
+ rnd_seq= TRUE;
+ m_scan_value= 2;
+ }
+
+ *delete_rows_result= 0;
+ m_part_spec= m_direct_update_part_spec;
+ for (i= m_part_spec.start_part; i <= m_part_spec.end_part; i++)
+ {
+ file= m_file[i];
+ if (bitmap_is_set(&(m_part_info->read_partitions), i) &&
+ bitmap_is_set(&(m_part_info->lock_partitions), i))
+ {
+ if (rnd_seq && (m_pre_calling ? file->pre_inited : file->inited) == NONE)
+ {
+ if ((error= (m_pre_calling ?
+ file->ha_pre_rnd_init(TRUE) :
+ file->ha_rnd_init(TRUE))))
+ DBUG_RETURN(error);
+ }
+ if ((error= (m_pre_calling ?
+ file->ha_pre_direct_delete_rows() :
+ file->ha_direct_delete_rows(&delete_rows))))
+ {
+ if (m_pre_calling)
+ file->ha_pre_rnd_end();
+ else
+ file->ha_rnd_end();
+ DBUG_RETURN(error);
+ }
+ delete_rows_result+= delete_rows;
+ if (m_pre_calling)
+ bitmap_set_bit(&bulk_access_exec_bitmap, i);
+ }
+ if (rnd_seq)
+ {
+ if ((error= (m_pre_calling ?
+ file->ha_pre_index_or_rnd_end() :
+ file->ha_index_or_rnd_end())))
+ DBUG_RETURN(error);
+ }
+ }
+ DBUG_RETURN(0);
+}
+
+
+/**
+ Start parallel execution of a direct delete for a handlersocket delete
+ request. A direct delete request deletes all qualified rows in a single
+ operation, rather than one row at a time. The direct delete operation
+ is pushed down to each individual partition.
+
+ SYNOPSIS
+ pre_direct_delete_rows()
+
+ RETURN VALUE
+ >0 Error
+ 0 Success
+*/
+
+int ha_partition::pre_direct_delete_rows()
+{
+ int error;
+ ha_rows not_used;
+ DBUG_ENTER("ha_partition::pre_direct_delete_rows");
+ m_pre_calling= TRUE;
+ error= direct_delete_rows(&not_used);
+ m_pre_calling= FALSE;
+ if (!error && bulk_access_started)
+ bulk_access_info_current->called= TRUE;
+ DBUG_RETURN(error);
+}
+
+
+/**
Push metadata for the current operation down to each partition.
SYNOPSIS
diff --git a/sql/ha_partition.h b/sql/ha_partition.h
index db268a89aea..7bce64cf3a2 100644
--- a/sql/ha_partition.h
+++ b/sql/ha_partition.h
@@ -308,9 +308,11 @@ private:
bool auto_increment_safe_stmt_log_lock;
/** For optimizing ha_start_bulk_insert calls */
MY_BITMAP m_bulk_insert_started;
+ MY_BITMAP bulk_access_exec_bitmap;
ha_rows m_bulk_inserted_rows;
/** used for prediction of start_bulk_insert rows */
enum_monotonicity_info m_part_func_monotonicity_info;
+ part_id_range m_direct_update_part_spec;
bool m_pre_calling;
bool m_pre_call_use_parallel;
/* Keep track of bulk access requests */
@@ -320,7 +322,6 @@ private:
PARTITION_BULK_ACCESS_INFO *bulk_access_info_first;
PARTITION_BULK_ACCESS_INFO *bulk_access_info_current;
PARTITION_BULK_ACCESS_INFO *bulk_access_info_exec_tgt;
- MY_BITMAP bulk_access_exec_bitmap;
/** keep track of locked partitions */
MY_BITMAP m_locked_partitions;
@@ -551,8 +552,26 @@ public:
*/
virtual int pre_write_row(uchar *buf);
virtual int write_row(uchar * buf);
+ virtual bool start_bulk_update();
+ virtual int exec_bulk_update(ha_rows *dup_key_found);
+ virtual int end_bulk_update();
+ virtual int bulk_update_row(const uchar *old_data, uchar *new_data,
+ ha_rows *dup_key_found);
virtual int update_row(const uchar * old_data, uchar * new_data);
+ virtual int direct_update_rows_init();
+ virtual int pre_direct_update_rows_init();
+ virtual int direct_update_rows(ha_rows *update_rows);
+ virtual int pre_direct_update_rows();
+#if defined(HS_HAS_SQLCOM)
+ virtual bool check_hs_update_overlapping(key_range *key);
+#endif
+ virtual bool start_bulk_delete();
+ virtual int end_bulk_delete();
virtual int delete_row(const uchar * buf);
+ virtual int direct_delete_rows_init();
+ virtual int pre_direct_delete_rows_init();
+ virtual int direct_delete_rows(ha_rows *delete_rows);
+ virtual int pre_direct_delete_rows();
virtual int delete_all_rows(void);
virtual int truncate();
virtual void start_bulk_insert(ha_rows rows, uint flags);
diff --git a/sql/handler.cc b/sql/handler.cc
index c4dce3caf78..977dff0b6f4 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -4035,7 +4035,7 @@ int handler::ha_repair(THD* thd, HA_CHECK_OPT* check_opt)
int
handler::ha_bulk_update_row(const uchar *old_data, uchar *new_data,
- uint *dup_key_found)
+ ha_rows *dup_key_found)
{
DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
m_lock_type == F_WRLCK);
@@ -6085,6 +6085,95 @@ int handler::ha_delete_row(const uchar *buf)
}
+/**
+ Execute a direct update request. A direct update request updates all
+ qualified rows in a single operation, rather than one row at a time.
+ In a Spider cluster the direct update operation is pushed down to the
+ child levels of the cluster.
+
+ @param update_rows Number of updated rows.
+
+ @retval 0 Success.
+ @retval != 0 Failure.
+*/
+
+int handler::ha_direct_update_rows(ha_rows *update_rows)
+{
+ int error;
+
+ MYSQL_UPDATE_ROW_START(table_share->db.str, table_share->table_name.str);
+ mark_trx_read_write();
+
+ error = direct_update_rows(update_rows);
+ MYSQL_UPDATE_ROW_DONE(error);
+ return error;
+}
+
+
+/**
+ Log to the binary log the changes for a single row
+ in a direct update request.
+
+ @retval 0 Success.
+ @retval != 0 Failure.
+*/
+
+int handler::ha_direct_update_row_binlog(const uchar *old_data,
+ uchar *new_data)
+{
+ Log_func *log_func= Update_rows_log_event::binlog_row_logging_function;
+
+ /*
+ Some storage engines require that the new record is in record[0]
+ (and the old record is in record[1]).
+ */
+ DBUG_ASSERT(new_data == table->record[0]);
+
+ return binlog_log_row(table, old_data, new_data, log_func);
+}
+
+
+/**
+ Execute a direct delete request. A direct delete request deletes all
+ qualified rows in a single operation, rather than one row at a time.
+ In a Spider cluster the direct delete operation is pushed down to the
+ child levels of the cluster.
+
+ @param delete_rows Number of deleted rows.
+
+ @retval 0 Success.
+ @retval != 0 Failure.
+*/
+
+int handler::ha_direct_delete_rows(ha_rows *delete_rows)
+{
+ int error;
+
+ MYSQL_DELETE_ROW_START(table_share->db.str, table_share->table_name.str);
+ mark_trx_read_write();
+
+ error = direct_delete_rows(delete_rows);
+ MYSQL_DELETE_ROW_DONE(error);
+ return error;
+}
+
+
+/**
+ Log to the binary log the deletion of a single row
+ in a direct delete request.
+
+ @retval 0 Success.
+ @retval != 0 Failure.
+*/
+
+int handler::ha_direct_delete_row_binlog(const uchar *buf)
+{
+ Log_func *log_func= Delete_rows_log_event::binlog_row_logging_function;
+
+ return binlog_log_row(table, buf, 0, log_func);
+}
+
+
/** @brief
use_hidden_primary_key() is called in case of an update/delete when
diff --git a/sql/handler.h b/sql/handler.h
index 2818431cb64..88ee9e20b4d 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -277,6 +277,10 @@ enum enum_alter_inplace_result {
/* The following is for bulk access by the partition handler */
#define HA_CAN_BULK_ACCESS (1ULL << 49)
+/* The following are used by Spider */
+#define HA_CAN_FORCE_BULK_UPDATE (1ULL << 50)
+#define HA_CAN_FORCE_BULK_DELETE (1ULL << 51)
+
/* bits in index_flags(index_number) for what you can do with index */
#define HA_READ_NEXT 1 /* TODO really use this flag */
#define HA_READ_PREV 2 /* supports ::index_prev */
@@ -426,6 +430,10 @@ static const uint MYSQL_START_TRANS_OPT_READ_WRITE = 4;
#define HA_CHECK_ALL (~0U)
/* Options for info_push() */
+#define INFO_KIND_UPDATE_FIELDS 101
+#define INFO_KIND_UPDATE_VALUES 102
+#define INFO_KIND_FORCE_LIMIT_BEGIN 103
+#define INFO_KIND_FORCE_LIMIT_END 104
#define INFO_KIND_BULK_ACCESS_BEGIN 105
#define INFO_KIND_BULK_ACCESS_CURRENT 106
#define INFO_KIND_BULK_ACCESS_END 107
@@ -1405,9 +1413,6 @@ handlerton *ha_default_tmp_handlerton(THD *thd);
#define HTON_TEMPORARY_NOT_SUPPORTED (1 << 6) //Having temporary tables not supported
#define HTON_SUPPORT_LOG_TABLES (1 << 7) //Engine supports log tables
#define HTON_NO_PARTITION (1 << 8) //Not partition of these tables
-#define HTON_CAN_MULTISTEP_MERGE (1 << 9) //You can merge mearged tables
-// Engine needs to access the main connect string in partitions
-#define HTON_CAN_READ_CONNECT_STRING_IN_PARTITION (1 << 10)
/*
This flag should be set when deciding that the engine does not allow
@@ -1428,6 +1433,10 @@ handlerton *ha_default_tmp_handlerton(THD *thd);
// MySQL compatibility. Unused.
#define HTON_SUPPORTS_FOREIGN_KEYS (1 << 0) //Foreign key constraint supported.
+#define HTON_CAN_MERGE (1 <<11) //Merge type table
+// Engine needs to access the main connect string in partitions
+#define HTON_CAN_READ_CONNECT_STRING_IN_PARTITION (1 <<12)
+
class Ha_trx_info;
struct THD_TRANS
@@ -2834,15 +2843,6 @@ public:
}
DBUG_RETURN(result);
}
- int ha_pre_index_init(uint idx, bool sorted)
- {
- int result;
- DBUG_ENTER("ha_pre_index_init");
- DBUG_ASSERT(pre_inited==NONE);
- if (!(result= pre_index_init(idx, sorted)))
- pre_inited=INDEX;
- DBUG_RETURN(result);
- }
int ha_index_end()
{
DBUG_ENTER("ha_index_end");
@@ -2852,13 +2852,6 @@ public:
end_range= NULL;
DBUG_RETURN(index_end());
}
- int ha_pre_index_end()
- {
- DBUG_ENTER("ha_pre_index_end");
- DBUG_ASSERT(pre_inited==INDEX);
- pre_inited=NONE;
- DBUG_RETURN(pre_index_end());
- }
/* This is called after index_init() if we need to do a index scan */
virtual int prepare_index_scan() { return 0; }
virtual int prepare_index_key_scan_map(const uchar * key, key_part_map keypart_map)
@@ -2881,14 +2874,6 @@ public:
end_range= NULL;
DBUG_RETURN(result);
}
- int ha_pre_rnd_init(bool scan)
- {
- int result;
- DBUG_ENTER("ha_pre_rnd_init");
- DBUG_ASSERT(pre_inited==NONE || (pre_inited==RND && scan));
- pre_inited= (result= pre_rnd_init(scan)) ? NONE: RND;
- DBUG_RETURN(result);
- }
int ha_rnd_end()
{
DBUG_ENTER("ha_rnd_end");
@@ -2897,13 +2882,6 @@ public:
end_range= NULL;
DBUG_RETURN(rnd_end());
}
- int ha_pre_rnd_end()
- {
- DBUG_ENTER("ha_pre_rnd_end");
- DBUG_ASSERT(pre_inited==RND);
- pre_inited=NONE;
- DBUG_RETURN(pre_rnd_end());
- }
int ha_rnd_init_with_error(bool scan) __attribute__ ((warn_unused_result));
int ha_reset();
/* this is necessary in many places, e.g. in HANDLER command */
@@ -2911,12 +2889,6 @@ public:
{
return inited == INDEX ? ha_index_end() : inited == RND ? ha_rnd_end() : 0;
}
- int ha_pre_index_or_rnd_end()
- {
- return pre_inited == INDEX ? ha_pre_index_end()
- : pre_inited == RND ?
- ha_pre_rnd_end() : 0;
- }
/**
The cached_table_flags is set at ha_open and ha_external_lock
*/
@@ -2969,7 +2941,7 @@ public:
DBUG_RETURN(ret);
}
int ha_bulk_update_row(const uchar *old_data, uchar *new_data,
- uint *dup_key_found);
+ ha_rows *dup_key_found);
int ha_delete_all_rows();
int ha_truncate();
int ha_reset_auto_increment(ulonglong value);
@@ -3151,7 +3123,7 @@ public:
@retval 0 Success
@retval >0 Error code
*/
- virtual int exec_bulk_update(uint *dup_key_found)
+ virtual int exec_bulk_update(ha_rows *dup_key_found)
{
DBUG_ASSERT(FALSE);
return HA_ERR_WRONG_COMMAND;
@@ -3160,7 +3132,7 @@ public:
Perform any needed clean-up, no outstanding updates are there at the
moment.
*/
- virtual void end_bulk_update() { return; }
+ virtual int end_bulk_update() { return 0; }
/**
Execute all outstanding deletes and close down the bulk delete.
@@ -3192,6 +3164,48 @@ public:
{ return 0; }
virtual int pre_rnd_next(bool use_parallel)
{ return 0; }
+ int ha_pre_rnd_init(bool scan)
+ {
+ int result;
+ DBUG_ENTER("ha_pre_rnd_init");
+ DBUG_ASSERT(pre_inited==NONE || (pre_inited==RND && scan));
+ pre_inited= (result= pre_rnd_init(scan)) ? NONE: RND;
+ DBUG_RETURN(result);
+ }
+ int ha_pre_rnd_end()
+ {
+ DBUG_ENTER("ha_pre_rnd_end");
+ DBUG_ASSERT(pre_inited==RND);
+ pre_inited=NONE;
+ DBUG_RETURN(pre_rnd_end());
+ }
+ virtual int pre_rnd_init(bool scan) { return 0; }
+ virtual int pre_rnd_end() { return 0; }
+ virtual int pre_index_init(uint idx, bool sorted) { return 0; }
+ virtual int pre_index_end() { return 0; }
+ int ha_pre_index_init(uint idx, bool sorted)
+ {
+ int result;
+ DBUG_ENTER("ha_pre_index_init");
+ DBUG_ASSERT(pre_inited==NONE);
+ if (!(result= pre_index_init(idx, sorted)))
+ pre_inited=INDEX;
+ DBUG_RETURN(result);
+ }
+ int ha_pre_index_end()
+ {
+ DBUG_ENTER("ha_pre_index_end");
+ DBUG_ASSERT(pre_inited==INDEX);
+ pre_inited=NONE;
+ DBUG_RETURN(pre_index_end());
+ }
+ int ha_pre_index_or_rnd_end()
+ {
+ return (pre_inited == INDEX ?
+ ha_pre_index_end() :
+ pre_inited == RND ? ha_pre_rnd_end() : 0 );
+ }
+
/**
@brief
Positions an index cursor to the index specified in the
@@ -4112,9 +4126,7 @@ private:
virtual int open(const char *name, int mode, uint test_if_locked)=0;
/* Note: ha_index_read_idx_map() may bypass index_init() */
virtual int index_init(uint idx, bool sorted) { return 0; }
- virtual int pre_index_init(uint idx, bool sorted) { return 0; }
virtual int index_end() { return 0; }
- virtual int pre_index_end() { return 0; }
/**
rnd_init() can be called two times without rnd_end() in between
(it only makes sense if scan=1).
@@ -4123,9 +4135,7 @@ private:
to the start of the table, no need to deallocate and allocate it again
*/
virtual int rnd_init(bool scan)= 0;
- virtual int pre_rnd_init(bool scan) { return 0; }
virtual int rnd_end() { return 0; }
- virtual int pre_rnd_end() { return 0; }
virtual int write_row(uchar *buf __attribute__((unused)))
{
return HA_ERR_WRONG_COMMAND;
@@ -4153,6 +4163,60 @@ private:
{
return HA_ERR_WRONG_COMMAND;
}
+
+ /* Perform initialization for a direct update request */
+public:
+ int ha_direct_update_rows(ha_rows *update_rows);
+ int ha_pre_direct_update_rows()
+ {
+ return pre_direct_update_rows();
+ }
+ int ha_direct_update_row_binlog(const uchar *old_data,
+ uchar *new_data);
+ virtual int direct_update_rows_init()
+ {
+ return HA_ERR_WRONG_COMMAND;
+ }
+private:
+ virtual int pre_direct_update_rows_init()
+ {
+ return HA_ERR_WRONG_COMMAND;
+ }
+ virtual int direct_update_rows(ha_rows *update_rows __attribute__((unused)))
+ {
+ return HA_ERR_WRONG_COMMAND;
+ }
+ virtual int pre_direct_update_rows()
+ {
+ return HA_ERR_WRONG_COMMAND;
+ }
+
+ /* Perform initialization for a direct delete request */
+public:
+ int ha_direct_delete_rows(ha_rows *delete_rows);
+ int ha_pre_direct_delete_rows()
+ {
+ return pre_direct_delete_rows();
+ }
+ int ha_direct_delete_row_binlog(const uchar *buf);
+ virtual int direct_delete_rows_init()
+ {
+ return HA_ERR_WRONG_COMMAND;
+ }
+private:
+ virtual int pre_direct_delete_rows_init()
+ {
+ return HA_ERR_WRONG_COMMAND;
+ }
+ virtual int direct_delete_rows(ha_rows *delete_rows __attribute__((unused)))
+ {
+ return HA_ERR_WRONG_COMMAND;
+ }
+ virtual int pre_direct_delete_rows()
+ {
+ return HA_ERR_WRONG_COMMAND;
+ }
+
/**
Reset state of file to after 'open'.
This function is called after every statement for all tables used
@@ -4226,7 +4290,7 @@ public:
@retval 1 Bulk delete not used, normal operation used
*/
virtual int bulk_update_row(const uchar *old_data, uchar *new_data,
- uint *dup_key_found)
+ ha_rows *dup_key_found)
{
DBUG_ASSERT(FALSE);
return HA_ERR_WRONG_COMMAND;
diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc
index ab587b8b279..3c5a4da874b 100644
--- a/sql/opt_sum.cc
+++ b/sql/opt_sum.cc
@@ -398,6 +398,8 @@ int opt_sum_query(THD *thd,
const_result= 0;
break;
}
+ longlong info_limit = 1;
+ table->file->info_push(INFO_KIND_FORCE_LIMIT_BEGIN, &info_limit);
if (!(error= table->file->ha_index_init((uint) ref.key, 1)))
error= (is_max ?
get_index_max_value(table, &ref, range_fl) :
@@ -408,9 +410,10 @@ int opt_sum_query(THD *thd,
if (!error && reckey_in_range(is_max, &ref, item_field->field,
conds, range_fl, prefix_len))
error= HA_ERR_KEY_NOT_FOUND;
- table->file->ha_end_keyread();
- table->file->ha_index_end();
- if (error)
+ table->file->ha_end_keyread();
+ table->file->ha_index_end();
+ table->file->info_push(INFO_KIND_FORCE_LIMIT_END, NULL);
+ if (error)
{
if (error == HA_ERR_KEY_NOT_FOUND || error == HA_ERR_END_OF_FILE)
DBUG_RETURN(HA_ERR_KEY_NOT_FOUND); // No rows matching WHERE
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index eb5f0d7a477..c051ffcc13a 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -224,7 +224,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;
@@ -236,11 +236,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= FALSE;
bool with_select= !select_lex->item_list.is_empty();
Explain_delete *explain;
Delete_plan query_plan(thd->mem_root);
@@ -341,9 +343,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);
@@ -490,14 +495,58 @@ 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)
+ table->mark_columns_needed_for_delete();
+
+ binlog_is_row= (mysql_bin_log.is_open() &&
+ 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 binlog row 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 (!has_triggers && !binlog_is_row && !with_select &&
+ !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 delete_end;
+ }
+ }
+
+ 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)))
@@ -536,15 +585,10 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
init_ftfuncs(thd, select_lex, 1);
THD_STAGE_INFO(thd, stage_updating);
- if (table->prepare_triggers_for_delete_stmt_or_event())
- {
- will_batch= FALSE;
- }
- else
+ 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();
- table->mark_columns_needed_for_delete();
-
if (with_select)
{
if (result->send_result_set_metadata(select_lex->item_list,
@@ -616,6 +660,8 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
else
break;
}
+
+delete_end:
killed_status= thd->killed;
if (killed_status != NOT_KILLED || thd->is_error())
error= 1; // Aborted
@@ -699,6 +745,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 */
@@ -719,6 +767,8 @@ send_nothing_and_leave:
delete select;
delete file_sort;
free_underlaid_joins(thd, select_lex);
+ if (table->file->pushed_cond)
+ table->file->cond_pop();
//table->set_keyread(false);
DBUG_ASSERT(!return_error || thd->is_error() || thd->killed);
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 0d55003a50f..b8051e0e45d 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;
query_plan.index= MAX_KEY;
@@ -286,7 +288,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);
@@ -511,7 +513,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
@@ -525,10 +526,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 = (mysql_bin_log.is_open() &&
+ 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 binlog row 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 (!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)
{
/*
@@ -688,6 +747,7 @@ int mysql_update(THD *thd,
}
}
+update_begin:
if (ignore)
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
@@ -708,11 +768,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();
/*
@@ -796,6 +865,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);
@@ -944,6 +1014,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)
@@ -999,6 +1071,8 @@ 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->cond_pop();
/* If LAST_INSERT_ID(X) was used, report X */
id= thd->arg_of_last_insert_id_function ?
@@ -1024,7 +1098,6 @@ int mysql_update(THD *thd,
*found_return= found;
*updated_return= updated;
-
if (thd->lex->analyze_stmt)
goto emit_explain_and_leave;
@@ -1035,6 +1108,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);
diff --git a/sql/table.cc b/sql/table.cc
index 450e116080a..96fa09823a9 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -6628,6 +6628,58 @@ bool TABLE::mark_virtual_columns_for_write(bool insert_fl)
DBUG_RETURN(bitmap_updated);
}
+
+/**
+ Check if a virtual not stored column field is in read set
+
+ @retval FALSE No virtual not stored column is used
+ @retval TRUE At least one virtual not stored column is used
+*/
+
+bool TABLE::check_virtual_columns_marked_for_read()
+{
+ if (vfield)
+ {
+ Field **vfield_ptr;
+ for (vfield_ptr= vfield; *vfield_ptr; vfield_ptr++)
+ {
+ Field *tmp_vfield= *vfield_ptr;
+ if (bitmap_is_set(read_set, tmp_vfield->field_index) &&
+ !tmp_vfield->vcol_info->stored_in_db)
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+
+/**
+ Check if a stored virtual column field is marked for write
+
+ This can be used to check if any column that is part of a virtual
+ stored column is changed
+
+ @retval FALSE No stored virtual column is used
+ @retval TRUE At least one stored virtual column is used
+*/
+
+bool TABLE::check_virtual_columns_marked_for_write()
+{
+ if (vfield)
+ {
+ Field **vfield_ptr;
+ for (vfield_ptr= vfield; *vfield_ptr; vfield_ptr++)
+ {
+ Field *tmp_vfield= *vfield_ptr;
+ if (bitmap_is_set(write_set, tmp_vfield->field_index) &&
+ tmp_vfield->vcol_info->stored_in_db)
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+
/*
Mark fields used by check constraints.
This is done once for the TABLE_SHARE the first time the table is opened.
@@ -6685,6 +6737,7 @@ void TABLE::mark_default_fields_for_write(bool is_insert)
DBUG_VOID_RETURN;
}
+
void TABLE::move_fields(Field **ptr, const uchar *to, const uchar *from)
{
my_ptrdiff_t diff= to - from;
diff --git a/sql/table.h b/sql/table.h
index 22846e05bde..ba6e13dd4c5 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -1319,6 +1319,8 @@ public:
void mark_columns_per_binlog_row_image(void);
bool mark_virtual_col(Field *field);
bool mark_virtual_columns_for_write(bool insert_fl);
+ bool check_virtual_columns_marked_for_read();
+ bool check_virtual_columns_marked_for_write();
void mark_default_fields_for_write(bool insert_fl);
void mark_columns_used_by_check_constraints(void);
void mark_check_constraint_columns_for_read(void);
diff --git a/storage/spider/ha_spider.cc b/storage/spider/ha_spider.cc
index c2aafb68de8..1278148a789 100644
--- a/storage/spider/ha_spider.cc
+++ b/storage/spider/ha_spider.cc
@@ -9726,7 +9726,7 @@ bool ha_spider::start_bulk_update(
}
int ha_spider::exec_bulk_update(
- uint *dup_key_found
+ ha_rows *dup_key_found
) {
int error_num;
backup_error_status();
@@ -9738,7 +9738,7 @@ int ha_spider::exec_bulk_update(
DBUG_RETURN(0);
}
-void ha_spider::end_bulk_update(
+int ha_spider::end_bulk_update(
) {
int error_num;
backup_error_status();
@@ -9747,15 +9747,17 @@ void ha_spider::end_bulk_update(
if ((error_num = check_and_end_bulk_update(SPD_BU_START_BY_BULK_INIT)))
{
if (check_error_mode(error_num))
- my_errno = error_num;
+ my_errno= error_num;
+ else
+ error_num= 0;
}
- DBUG_VOID_RETURN;
+ DBUG_RETURN(error_num);
}
int ha_spider::bulk_update_row(
const uchar *old_data,
uchar *new_data,
- uint *dup_key_found
+ ha_rows *dup_key_found
) {
DBUG_ENTER("ha_spider::bulk_update_row");
DBUG_PRINT("info",("spider this=%p", this));
@@ -10005,7 +10007,7 @@ int ha_spider::pre_direct_update_rows_init(
if (bulk_access_started)
{
error_num = bulk_access_link_current->spider->
- ha_pre_direct_update_rows_init(
+ pre_direct_update_rows_init(
mode, ranges, range_count, sorted, new_data);
bulk_access_link_current->spider->bulk_access_pre_called = TRUE;
bulk_access_link_current->called = TRUE;
@@ -10022,7 +10024,7 @@ int ha_spider::direct_update_rows(
uint range_count,
bool sorted,
uchar *new_data,
- uint *update_rows
+ ha_rows *update_rows
) {
int error_num;
THD *thd = ha_thd();
@@ -10079,7 +10081,7 @@ int ha_spider::pre_direct_update_rows(
uint range_count,
bool sorted,
uchar *new_data,
- uint *update_rows
+ ha_rows *update_rows
) {
DBUG_ENTER("ha_spider::pre_direct_update_rows");
DBUG_PRINT("info",("spider this=%p", this));
@@ -10277,7 +10279,7 @@ int ha_spider::pre_direct_delete_rows_init(
if (bulk_access_started)
{
error_num = bulk_access_link_current->spider->
- ha_pre_direct_delete_rows_init(
+ pre_direct_delete_rows_init(
mode, ranges, range_count, sorted);
bulk_access_link_current->spider->bulk_access_pre_called = TRUE;
bulk_access_link_current->called = TRUE;
@@ -10293,7 +10295,7 @@ int ha_spider::direct_delete_rows(
KEY_MULTI_RANGE *ranges,
uint range_count,
bool sorted,
- uint *delete_rows
+ ha_rows *delete_rows
) {
int error_num;
THD *thd = ha_thd();
@@ -10349,7 +10351,7 @@ int ha_spider::pre_direct_delete_rows(
KEY_MULTI_RANGE *ranges,
uint range_count,
bool sorted,
- uint *delete_rows
+ ha_rows *delete_rows
) {
DBUG_ENTER("ha_spider::pre_direct_delete_rows");
DBUG_PRINT("info",("spider this=%p", this));
@@ -12027,7 +12029,7 @@ int ha_spider::check_and_end_bulk_update(
spider_bulk_upd_start bulk_upd_start
) {
int error_num = 0;
- uint dup_key_found = 0;
+ ha_rows dup_key_found = 0;
DBUG_ENTER("ha_spider::check_and_end_bulk_update");
DBUG_PRINT("info",("spider this=%p", this));
DBUG_PRINT("info",("spider bulk_update_start=%d",
diff --git a/storage/spider/ha_spider.h b/storage/spider/ha_spider.h
index d539946d89b..d40bc376a4c 100644
--- a/storage/spider/ha_spider.h
+++ b/storage/spider/ha_spider.h
@@ -562,19 +562,23 @@ public:
#endif
bool start_bulk_update();
int exec_bulk_update(
- uint *dup_key_found
+ ha_rows *dup_key_found
);
- void end_bulk_update();
+ int end_bulk_update();
int bulk_update_row(
const uchar *old_data,
uchar *new_data,
- uint *dup_key_found
+ ha_rows *dup_key_found
);
int update_row(
const uchar *old_data,
uchar *new_data
);
#ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS
+ inline int direct_update_rows_init()
+ {
+ return direct_update_rows_init(2, NULL, 0, FALSE, NULL);
+ }
int direct_update_rows_init(
uint mode,
KEY_MULTI_RANGE *ranges,
@@ -583,6 +587,10 @@ public:
uchar *new_data
);
#ifdef HA_CAN_BULK_ACCESS
+ inline int pre_direct_update_rows_init()
+ {
+ return pre_direct_update_rows_init(2, NULL, 0, FALSE, NULL);
+ }
int pre_direct_update_rows_init(
uint mode,
KEY_MULTI_RANGE *ranges,
@@ -591,20 +599,36 @@ public:
uchar *new_data
);
#endif
+ inline int ha_direct_update_rows(KEY_MULTI_RANGE *ranges,
+ uint range_count, bool sorted,
+ uchar *new_data, ha_rows *update_rows)
+ {
+ return handler::ha_direct_update_rows(update_rows);
+ }
+ inline int direct_update_rows(ha_rows *update_rows)
+ {
+ return direct_update_rows(NULL, 0, FALSE, NULL, update_rows);
+ }
int direct_update_rows(
KEY_MULTI_RANGE *ranges,
uint range_count,
bool sorted,
uchar *new_data,
- uint *update_rows
+ ha_rows *update_rows
);
#ifdef HA_CAN_BULK_ACCESS
+ inline int pre_direct_update_rows()
+ {
+ ha_rows update_rows;
+
+ return pre_direct_update_rows(NULL, 0, FALSE, NULL, &update_rows);
+ }
int pre_direct_update_rows(
KEY_MULTI_RANGE *ranges,
uint range_count,
bool sorted,
uchar *new_data,
- uint *update_rows
+ ha_rows *update_rows
);
#endif
#endif
@@ -614,6 +638,10 @@ public:
const uchar *buf
);
#ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS
+ inline int direct_delete_rows_init()
+ {
+ return direct_delete_rows_init(2, NULL, 0, FALSE);
+ }
int direct_delete_rows_init(
uint mode,
KEY_MULTI_RANGE *ranges,
@@ -621,6 +649,10 @@ public:
bool sorted
);
#ifdef HA_CAN_BULK_ACCESS
+ inline int pre_direct_delete_rows_init()
+ {
+ return pre_direct_delete_rows_init(2, NULL, 0, FALSE);
+ }
int pre_direct_delete_rows_init(
uint mode,
KEY_MULTI_RANGE *ranges,
@@ -628,18 +660,34 @@ public:
bool sorted
);
#endif
+ inline int ha_direct_delete_rows(KEY_MULTI_RANGE *ranges,
+ uint range_count, bool sorted,
+ ha_rows *delete_rows)
+ {
+ return handler::ha_direct_delete_rows(delete_rows);
+ }
+ inline int direct_delete_rows(ha_rows *delete_rows)
+ {
+ return direct_delete_rows(NULL, 0, FALSE, delete_rows);
+ }
int direct_delete_rows(
KEY_MULTI_RANGE *ranges,
uint range_count,
bool sorted,
- uint *delete_rows
+ ha_rows *delete_rows
);
#ifdef HA_CAN_BULK_ACCESS
+ inline int pre_direct_delete_rows()
+ {
+ ha_rows delete_rows;
+
+ return pre_direct_delete_rows(NULL, 0, FALSE, &delete_rows);
+ }
int pre_direct_delete_rows(
KEY_MULTI_RANGE *ranges,
uint range_count,
bool sorted,
- uint *delete_rows
+ ha_rows *delete_rows
);
#endif
#endif
diff --git a/storage/spider/mysql-test/spider/bg/r/direct_update.result b/storage/spider/mysql-test/spider/bg/r/direct_update.result
index 74dae7aec2e..0e536d48617 100644
--- a/storage/spider/mysql-test/spider/bg/r/direct_update.result
+++ b/storage/spider/mysql-test/spider/bg/r/direct_update.result
@@ -48,6 +48,7 @@ direct_updating test
connection master_1;
SHOW STATUS LIKE 'Spider_direct_update';
Variable_name Value
+Spider_direct_update 0
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l ORDER BY a;
a b date_format(c, '%Y-%m-%d %H:%i:%s')
1 a 2008-08-01 10:21:39
@@ -59,6 +60,7 @@ update all rows with function
UPDATE ta_l SET c = ADDDATE(c, 1);
SHOW STATUS LIKE 'Spider_direct_update';
Variable_name Value
+Spider_direct_update 1
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l ORDER BY a;
a b date_format(c, '%Y-%m-%d %H:%i:%s')
1 a 2008-08-02 10:21:39
@@ -70,6 +72,7 @@ update by primary key
UPDATE ta_l SET b = 'x' WHERE a = 3;
SHOW STATUS LIKE 'Spider_direct_update';
Variable_name Value
+Spider_direct_update 2
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l ORDER BY a;
a b date_format(c, '%Y-%m-%d %H:%i:%s')
1 a 2008-08-02 10:21:39
@@ -81,6 +84,7 @@ update by a column without index
UPDATE ta_l SET c = '2011-10-17' WHERE b = 'x';
SHOW STATUS LIKE 'Spider_direct_update';
Variable_name Value
+Spider_direct_update 3
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l ORDER BY a;
a b date_format(c, '%Y-%m-%d %H:%i:%s')
1 a 2008-08-02 10:21:39
@@ -92,6 +96,7 @@ update by primary key with order and limit
UPDATE ta_l SET c = ADDDATE(c, 1) WHERE a < 4 ORDER BY b DESC LIMIT 1;
SHOW STATUS LIKE 'Spider_direct_update';
Variable_name Value
+Spider_direct_update 4
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l ORDER BY a;
a b date_format(c, '%Y-%m-%d %H:%i:%s')
1 a 2008-08-02 10:21:39
@@ -103,6 +108,7 @@ delete by primary key with order and limit
DELETE FROM ta_l WHERE a < 4 ORDER BY c LIMIT 1;
SHOW STATUS LIKE 'Spider_direct_delete';
Variable_name Value
+Spider_direct_delete 1
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l ORDER BY a;
a b date_format(c, '%Y-%m-%d %H:%i:%s')
1 a 2008-08-02 10:21:39
@@ -113,6 +119,7 @@ delete by a column without index
DELETE FROM ta_l WHERE b = 'c';
SHOW STATUS LIKE 'Spider_direct_delete';
Variable_name Value
+Spider_direct_delete 2
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l ORDER BY a;
a b date_format(c, '%Y-%m-%d %H:%i:%s')
1 a 2008-08-02 10:21:39
@@ -122,6 +129,7 @@ delete by primary key
DELETE FROM ta_l WHERE a = 3;
SHOW STATUS LIKE 'Spider_direct_delete';
Variable_name Value
+Spider_direct_delete 3
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l ORDER BY a;
a b date_format(c, '%Y-%m-%d %H:%i:%s')
1 a 2008-08-02 10:21:39
diff --git a/storage/spider/mysql-test/spider/bg/r/direct_update_part.result b/storage/spider/mysql-test/spider/bg/r/direct_update_part.result
index 6db7c01f563..7069cd72fda 100644
--- a/storage/spider/mysql-test/spider/bg/r/direct_update_part.result
+++ b/storage/spider/mysql-test/spider/bg/r/direct_update_part.result
@@ -38,6 +38,7 @@ PRIMARY KEY(a)
) MASTER_1_ENGINE MASTER_1_COMMENT2_P_2_1
SHOW STATUS LIKE 'Spider_direct_update';
Variable_name Value
+Spider_direct_update 0
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l2 ORDER BY a;
a b date_format(c, '%Y-%m-%d %H:%i:%s')
1 a 2008-08-01 10:21:39
@@ -49,6 +50,7 @@ update all rows with function
UPDATE ta_l2 SET c = ADDDATE(c, 1);
SHOW STATUS LIKE 'Spider_direct_update';
Variable_name Value
+Spider_direct_update 2
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l2 ORDER BY a;
a b date_format(c, '%Y-%m-%d %H:%i:%s')
1 a 2008-08-02 10:21:39
@@ -60,6 +62,7 @@ update by primary key
UPDATE ta_l2 SET b = 'x' WHERE a = 3;
SHOW STATUS LIKE 'Spider_direct_update';
Variable_name Value
+Spider_direct_update 3
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l2 ORDER BY a;
a b date_format(c, '%Y-%m-%d %H:%i:%s')
1 a 2008-08-02 10:21:39
@@ -71,6 +74,7 @@ update by a column without index
UPDATE ta_l2 SET c = '2011-10-17' WHERE b = 'x';
SHOW STATUS LIKE 'Spider_direct_update';
Variable_name Value
+Spider_direct_update 5
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l2 ORDER BY a;
a b date_format(c, '%Y-%m-%d %H:%i:%s')
1 a 2008-08-02 10:21:39
@@ -82,6 +86,7 @@ update by primary key with order and limit
UPDATE ta_l2 SET c = ADDDATE(c, 1) WHERE a < 4 ORDER BY b DESC LIMIT 1;
SHOW STATUS LIKE 'Spider_direct_update';
Variable_name Value
+Spider_direct_update 6
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l2 ORDER BY a;
a b date_format(c, '%Y-%m-%d %H:%i:%s')
1 a 2008-08-02 10:21:39
@@ -93,6 +98,7 @@ delete by primary key with order and limit
DELETE FROM ta_l2 WHERE a < 4 ORDER BY c LIMIT 1;
SHOW STATUS LIKE 'Spider_direct_delete';
Variable_name Value
+Spider_direct_delete 1
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l2 ORDER BY a;
a b date_format(c, '%Y-%m-%d %H:%i:%s')
1 a 2008-08-02 10:21:39
@@ -103,6 +109,7 @@ delete by a column without index
DELETE FROM ta_l2 WHERE b = 'c';
SHOW STATUS LIKE 'Spider_direct_delete';
Variable_name Value
+Spider_direct_delete 3
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l2 ORDER BY a;
a b date_format(c, '%Y-%m-%d %H:%i:%s')
1 a 2008-08-02 10:21:39
@@ -112,6 +119,7 @@ delete by primary key
DELETE FROM ta_l2 WHERE a = 3;
SHOW STATUS LIKE 'Spider_direct_delete';
Variable_name Value
+Spider_direct_delete 4
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l2 ORDER BY a;
a b date_format(c, '%Y-%m-%d %H:%i:%s')
1 a 2008-08-02 10:21:39
diff --git a/storage/spider/mysql-test/spider/bg/r/spider_fixes.result b/storage/spider/mysql-test/spider/bg/r/spider_fixes.result
index f50c9822534..1db31ca9f95 100644
--- a/storage/spider/mysql-test/spider/bg/r/spider_fixes.result
+++ b/storage/spider/mysql-test/spider/bg/r/spider_fixes.result
@@ -461,6 +461,7 @@ Error 1146 Table 'auto_test_remote.ter1_1' doesn't exist
DELETE FROM t1;
Warnings:
Error 12702 Remote table 'auto_test_remote.ter1_1' is not found
+Error 12702 Remote table 'auto_test_remote.ter1_1' is not found
Error 1146 Table 'auto_test_remote.ter1_1' doesn't exist
TRUNCATE t1;
Warnings:
diff --git a/storage/spider/mysql-test/spider/handler/r/direct_update.result b/storage/spider/mysql-test/spider/handler/r/direct_update.result
index 74dae7aec2e..0e536d48617 100644
--- a/storage/spider/mysql-test/spider/handler/r/direct_update.result
+++ b/storage/spider/mysql-test/spider/handler/r/direct_update.result
@@ -48,6 +48,7 @@ direct_updating test
connection master_1;
SHOW STATUS LIKE 'Spider_direct_update';
Variable_name Value
+Spider_direct_update 0
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l ORDER BY a;
a b date_format(c, '%Y-%m-%d %H:%i:%s')
1 a 2008-08-01 10:21:39
@@ -59,6 +60,7 @@ update all rows with function
UPDATE ta_l SET c = ADDDATE(c, 1);
SHOW STATUS LIKE 'Spider_direct_update';
Variable_name Value
+Spider_direct_update 1
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l ORDER BY a;
a b date_format(c, '%Y-%m-%d %H:%i:%s')
1 a 2008-08-02 10:21:39
@@ -70,6 +72,7 @@ update by primary key
UPDATE ta_l SET b = 'x' WHERE a = 3;
SHOW STATUS LIKE 'Spider_direct_update';
Variable_name Value
+Spider_direct_update 2
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l ORDER BY a;
a b date_format(c, '%Y-%m-%d %H:%i:%s')
1 a 2008-08-02 10:21:39
@@ -81,6 +84,7 @@ update by a column without index
UPDATE ta_l SET c = '2011-10-17' WHERE b = 'x';
SHOW STATUS LIKE 'Spider_direct_update';
Variable_name Value
+Spider_direct_update 3
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l ORDER BY a;
a b date_format(c, '%Y-%m-%d %H:%i:%s')
1 a 2008-08-02 10:21:39
@@ -92,6 +96,7 @@ update by primary key with order and limit
UPDATE ta_l SET c = ADDDATE(c, 1) WHERE a < 4 ORDER BY b DESC LIMIT 1;
SHOW STATUS LIKE 'Spider_direct_update';
Variable_name Value
+Spider_direct_update 4
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l ORDER BY a;
a b date_format(c, '%Y-%m-%d %H:%i:%s')
1 a 2008-08-02 10:21:39
@@ -103,6 +108,7 @@ delete by primary key with order and limit
DELETE FROM ta_l WHERE a < 4 ORDER BY c LIMIT 1;
SHOW STATUS LIKE 'Spider_direct_delete';
Variable_name Value
+Spider_direct_delete 1
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l ORDER BY a;
a b date_format(c, '%Y-%m-%d %H:%i:%s')
1 a 2008-08-02 10:21:39
@@ -113,6 +119,7 @@ delete by a column without index
DELETE FROM ta_l WHERE b = 'c';
SHOW STATUS LIKE 'Spider_direct_delete';
Variable_name Value
+Spider_direct_delete 2
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l ORDER BY a;
a b date_format(c, '%Y-%m-%d %H:%i:%s')
1 a 2008-08-02 10:21:39
@@ -122,6 +129,7 @@ delete by primary key
DELETE FROM ta_l WHERE a = 3;
SHOW STATUS LIKE 'Spider_direct_delete';
Variable_name Value
+Spider_direct_delete 3
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l ORDER BY a;
a b date_format(c, '%Y-%m-%d %H:%i:%s')
1 a 2008-08-02 10:21:39
diff --git a/storage/spider/mysql-test/spider/handler/r/direct_update_part.result b/storage/spider/mysql-test/spider/handler/r/direct_update_part.result
index 6db7c01f563..7069cd72fda 100644
--- a/storage/spider/mysql-test/spider/handler/r/direct_update_part.result
+++ b/storage/spider/mysql-test/spider/handler/r/direct_update_part.result
@@ -38,6 +38,7 @@ PRIMARY KEY(a)
) MASTER_1_ENGINE MASTER_1_COMMENT2_P_2_1
SHOW STATUS LIKE 'Spider_direct_update';
Variable_name Value
+Spider_direct_update 0
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l2 ORDER BY a;
a b date_format(c, '%Y-%m-%d %H:%i:%s')
1 a 2008-08-01 10:21:39
@@ -49,6 +50,7 @@ update all rows with function
UPDATE ta_l2 SET c = ADDDATE(c, 1);
SHOW STATUS LIKE 'Spider_direct_update';
Variable_name Value
+Spider_direct_update 2
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l2 ORDER BY a;
a b date_format(c, '%Y-%m-%d %H:%i:%s')
1 a 2008-08-02 10:21:39
@@ -60,6 +62,7 @@ update by primary key
UPDATE ta_l2 SET b = 'x' WHERE a = 3;
SHOW STATUS LIKE 'Spider_direct_update';
Variable_name Value
+Spider_direct_update 3
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l2 ORDER BY a;
a b date_format(c, '%Y-%m-%d %H:%i:%s')
1 a 2008-08-02 10:21:39
@@ -71,6 +74,7 @@ update by a column without index
UPDATE ta_l2 SET c = '2011-10-17' WHERE b = 'x';
SHOW STATUS LIKE 'Spider_direct_update';
Variable_name Value
+Spider_direct_update 5
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l2 ORDER BY a;
a b date_format(c, '%Y-%m-%d %H:%i:%s')
1 a 2008-08-02 10:21:39
@@ -82,6 +86,7 @@ update by primary key with order and limit
UPDATE ta_l2 SET c = ADDDATE(c, 1) WHERE a < 4 ORDER BY b DESC LIMIT 1;
SHOW STATUS LIKE 'Spider_direct_update';
Variable_name Value
+Spider_direct_update 6
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l2 ORDER BY a;
a b date_format(c, '%Y-%m-%d %H:%i:%s')
1 a 2008-08-02 10:21:39
@@ -93,6 +98,7 @@ delete by primary key with order and limit
DELETE FROM ta_l2 WHERE a < 4 ORDER BY c LIMIT 1;
SHOW STATUS LIKE 'Spider_direct_delete';
Variable_name Value
+Spider_direct_delete 1
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l2 ORDER BY a;
a b date_format(c, '%Y-%m-%d %H:%i:%s')
1 a 2008-08-02 10:21:39
@@ -103,6 +109,7 @@ delete by a column without index
DELETE FROM ta_l2 WHERE b = 'c';
SHOW STATUS LIKE 'Spider_direct_delete';
Variable_name Value
+Spider_direct_delete 3
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l2 ORDER BY a;
a b date_format(c, '%Y-%m-%d %H:%i:%s')
1 a 2008-08-02 10:21:39
@@ -112,6 +119,7 @@ delete by primary key
DELETE FROM ta_l2 WHERE a = 3;
SHOW STATUS LIKE 'Spider_direct_delete';
Variable_name Value
+Spider_direct_delete 4
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l2 ORDER BY a;
a b date_format(c, '%Y-%m-%d %H:%i:%s')
1 a 2008-08-02 10:21:39
diff --git a/storage/spider/mysql-test/spider/handler/r/spider_fixes.result b/storage/spider/mysql-test/spider/handler/r/spider_fixes.result
index 9b14817eee4..c171167a1b7 100644
--- a/storage/spider/mysql-test/spider/handler/r/spider_fixes.result
+++ b/storage/spider/mysql-test/spider/handler/r/spider_fixes.result
@@ -465,6 +465,7 @@ Error 1146 Table 'auto_test_remote.ter1_1' doesn't exist
DELETE FROM t1;
Warnings:
Error 12702 Remote table 'auto_test_remote.ter1_1' is not found
+Error 12702 Remote table 'auto_test_remote.ter1_1' is not found
Error 1146 Table 'auto_test_remote.ter1_1' doesn't exist
TRUNCATE t1;
Warnings:
diff --git a/storage/spider/mysql-test/spider/r/direct_update.result b/storage/spider/mysql-test/spider/r/direct_update.result
index 74dae7aec2e..0e536d48617 100644
--- a/storage/spider/mysql-test/spider/r/direct_update.result
+++ b/storage/spider/mysql-test/spider/r/direct_update.result
@@ -48,6 +48,7 @@ direct_updating test
connection master_1;
SHOW STATUS LIKE 'Spider_direct_update';
Variable_name Value
+Spider_direct_update 0
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l ORDER BY a;
a b date_format(c, '%Y-%m-%d %H:%i:%s')
1 a 2008-08-01 10:21:39
@@ -59,6 +60,7 @@ update all rows with function
UPDATE ta_l SET c = ADDDATE(c, 1);
SHOW STATUS LIKE 'Spider_direct_update';
Variable_name Value
+Spider_direct_update 1
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l ORDER BY a;
a b date_format(c, '%Y-%m-%d %H:%i:%s')
1 a 2008-08-02 10:21:39
@@ -70,6 +72,7 @@ update by primary key
UPDATE ta_l SET b = 'x' WHERE a = 3;
SHOW STATUS LIKE 'Spider_direct_update';
Variable_name Value
+Spider_direct_update 2
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l ORDER BY a;
a b date_format(c, '%Y-%m-%d %H:%i:%s')
1 a 2008-08-02 10:21:39
@@ -81,6 +84,7 @@ update by a column without index
UPDATE ta_l SET c = '2011-10-17' WHERE b = 'x';
SHOW STATUS LIKE 'Spider_direct_update';
Variable_name Value
+Spider_direct_update 3
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l ORDER BY a;
a b date_format(c, '%Y-%m-%d %H:%i:%s')
1 a 2008-08-02 10:21:39
@@ -92,6 +96,7 @@ update by primary key with order and limit
UPDATE ta_l SET c = ADDDATE(c, 1) WHERE a < 4 ORDER BY b DESC LIMIT 1;
SHOW STATUS LIKE 'Spider_direct_update';
Variable_name Value
+Spider_direct_update 4
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l ORDER BY a;
a b date_format(c, '%Y-%m-%d %H:%i:%s')
1 a 2008-08-02 10:21:39
@@ -103,6 +108,7 @@ delete by primary key with order and limit
DELETE FROM ta_l WHERE a < 4 ORDER BY c LIMIT 1;
SHOW STATUS LIKE 'Spider_direct_delete';
Variable_name Value
+Spider_direct_delete 1
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l ORDER BY a;
a b date_format(c, '%Y-%m-%d %H:%i:%s')
1 a 2008-08-02 10:21:39
@@ -113,6 +119,7 @@ delete by a column without index
DELETE FROM ta_l WHERE b = 'c';
SHOW STATUS LIKE 'Spider_direct_delete';
Variable_name Value
+Spider_direct_delete 2
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l ORDER BY a;
a b date_format(c, '%Y-%m-%d %H:%i:%s')
1 a 2008-08-02 10:21:39
@@ -122,6 +129,7 @@ delete by primary key
DELETE FROM ta_l WHERE a = 3;
SHOW STATUS LIKE 'Spider_direct_delete';
Variable_name Value
+Spider_direct_delete 3
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l ORDER BY a;
a b date_format(c, '%Y-%m-%d %H:%i:%s')
1 a 2008-08-02 10:21:39
diff --git a/storage/spider/mysql-test/spider/r/direct_update_part.result b/storage/spider/mysql-test/spider/r/direct_update_part.result
index 6db7c01f563..7069cd72fda 100644
--- a/storage/spider/mysql-test/spider/r/direct_update_part.result
+++ b/storage/spider/mysql-test/spider/r/direct_update_part.result
@@ -38,6 +38,7 @@ PRIMARY KEY(a)
) MASTER_1_ENGINE MASTER_1_COMMENT2_P_2_1
SHOW STATUS LIKE 'Spider_direct_update';
Variable_name Value
+Spider_direct_update 0
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l2 ORDER BY a;
a b date_format(c, '%Y-%m-%d %H:%i:%s')
1 a 2008-08-01 10:21:39
@@ -49,6 +50,7 @@ update all rows with function
UPDATE ta_l2 SET c = ADDDATE(c, 1);
SHOW STATUS LIKE 'Spider_direct_update';
Variable_name Value
+Spider_direct_update 2
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l2 ORDER BY a;
a b date_format(c, '%Y-%m-%d %H:%i:%s')
1 a 2008-08-02 10:21:39
@@ -60,6 +62,7 @@ update by primary key
UPDATE ta_l2 SET b = 'x' WHERE a = 3;
SHOW STATUS LIKE 'Spider_direct_update';
Variable_name Value
+Spider_direct_update 3
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l2 ORDER BY a;
a b date_format(c, '%Y-%m-%d %H:%i:%s')
1 a 2008-08-02 10:21:39
@@ -71,6 +74,7 @@ update by a column without index
UPDATE ta_l2 SET c = '2011-10-17' WHERE b = 'x';
SHOW STATUS LIKE 'Spider_direct_update';
Variable_name Value
+Spider_direct_update 5
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l2 ORDER BY a;
a b date_format(c, '%Y-%m-%d %H:%i:%s')
1 a 2008-08-02 10:21:39
@@ -82,6 +86,7 @@ update by primary key with order and limit
UPDATE ta_l2 SET c = ADDDATE(c, 1) WHERE a < 4 ORDER BY b DESC LIMIT 1;
SHOW STATUS LIKE 'Spider_direct_update';
Variable_name Value
+Spider_direct_update 6
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l2 ORDER BY a;
a b date_format(c, '%Y-%m-%d %H:%i:%s')
1 a 2008-08-02 10:21:39
@@ -93,6 +98,7 @@ delete by primary key with order and limit
DELETE FROM ta_l2 WHERE a < 4 ORDER BY c LIMIT 1;
SHOW STATUS LIKE 'Spider_direct_delete';
Variable_name Value
+Spider_direct_delete 1
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l2 ORDER BY a;
a b date_format(c, '%Y-%m-%d %H:%i:%s')
1 a 2008-08-02 10:21:39
@@ -103,6 +109,7 @@ delete by a column without index
DELETE FROM ta_l2 WHERE b = 'c';
SHOW STATUS LIKE 'Spider_direct_delete';
Variable_name Value
+Spider_direct_delete 3
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l2 ORDER BY a;
a b date_format(c, '%Y-%m-%d %H:%i:%s')
1 a 2008-08-02 10:21:39
@@ -112,6 +119,7 @@ delete by primary key
DELETE FROM ta_l2 WHERE a = 3;
SHOW STATUS LIKE 'Spider_direct_delete';
Variable_name Value
+Spider_direct_delete 4
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l2 ORDER BY a;
a b date_format(c, '%Y-%m-%d %H:%i:%s')
1 a 2008-08-02 10:21:39
diff --git a/storage/spider/mysql-test/spider/r/spider_fixes.result b/storage/spider/mysql-test/spider/r/spider_fixes.result
index f50c9822534..1db31ca9f95 100644
--- a/storage/spider/mysql-test/spider/r/spider_fixes.result
+++ b/storage/spider/mysql-test/spider/r/spider_fixes.result
@@ -461,6 +461,7 @@ Error 1146 Table 'auto_test_remote.ter1_1' doesn't exist
DELETE FROM t1;
Warnings:
Error 12702 Remote table 'auto_test_remote.ter1_1' is not found
+Error 12702 Remote table 'auto_test_remote.ter1_1' is not found
Error 1146 Table 'auto_test_remote.ter1_1' doesn't exist
TRUNCATE t1;
Warnings:
diff --git a/storage/spider/spd_db_conn.cc b/storage/spider/spd_db_conn.cc
index c6bf4db3075..10332dc8709 100644
--- a/storage/spider/spd_db_conn.cc
+++ b/storage/spider/spd_db_conn.cc
@@ -1011,7 +1011,7 @@ int spider_db_query_for_bulk_update(
ha_spider *spider,
SPIDER_CONN *conn,
int link_idx,
- uint *dup_key_found
+ ha_rows *dup_key_found
) {
int error_num;
SPIDER_SHARE *share = spider->share;
@@ -6096,7 +6096,7 @@ int spider_db_bulk_update_size_limit(
SPIDER_SHARE *share = spider->share;
SPIDER_RESULT_LIST *result_list = &spider->result_list;
SPIDER_CONN *conn;
- uint dup_key_found = 0;
+ ha_rows dup_key_found = 0;
DBUG_ENTER("spider_db_bulk_update_size_limit");
if (result_list->bulk_update_mode == 1)
@@ -6159,7 +6159,7 @@ error_mk_table:
int spider_db_bulk_update_end(
ha_spider *spider,
- uint *dup_key_found
+ ha_rows *dup_key_found
) {
int error_num = 0, error_num2, roop_count;
THD *thd = spider->trx->thd;
@@ -6492,7 +6492,7 @@ int spider_db_direct_update(
TABLE *table,
KEY_MULTI_RANGE *ranges,
uint range_count,
- uint *update_rows
+ ha_rows *update_rows
) {
int error_num, roop_count;
SPIDER_SHARE *share = spider->share;
@@ -6762,7 +6762,7 @@ int spider_db_direct_update(
if (!counted)
{
*update_rows = spider->conns[roop_count]->db_conn->affected_rows();
- DBUG_PRINT("info", ("spider update_rows = %u", *update_rows));
+ DBUG_PRINT("info", ("spider update_rows = %llu", *update_rows));
counted = TRUE;
}
#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET)
@@ -6783,7 +6783,7 @@ int spider_db_direct_update(
if (!counted)
{
*update_rows = conn->db_conn->affected_rows();
- DBUG_PRINT("info", ("spider update_rows = %u", *update_rows));
+ DBUG_PRINT("info", ("spider update_rows = %llu", *update_rows));
counted = TRUE;
}
result->free_result();
@@ -6822,7 +6822,7 @@ int spider_db_direct_update(
#ifdef HA_CAN_BULK_ACCESS
int spider_db_bulk_direct_update(
ha_spider *spider,
- uint *update_rows
+ ha_rows *update_rows
) {
int error_num = 0, roop_count, tmp_error_num;
SPIDER_SHARE *share = spider->share;
@@ -6866,7 +6866,7 @@ int spider_db_bulk_direct_update(
if (!counted)
{
*update_rows = spider->conns[roop_count]->db_conn->affected_rows();
- DBUG_PRINT("info", ("spider update_rows = %u", *update_rows));
+ DBUG_PRINT("info", ("spider update_rows = %llu", *update_rows));
counted = TRUE;
}
#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET)
@@ -6887,7 +6887,7 @@ int spider_db_bulk_direct_update(
if (!counted)
{
*update_rows = conn->db_conn->affected_rows();
- DBUG_PRINT("info", ("spider update_rows = %u", *update_rows));
+ DBUG_PRINT("info", ("spider update_rows = %llu", *update_rows));
counted = TRUE;
}
result->free_result();
@@ -6996,7 +6996,7 @@ int spider_db_direct_delete(
TABLE *table,
KEY_MULTI_RANGE *ranges,
uint range_count,
- uint *delete_rows
+ ha_rows *delete_rows
) {
int error_num, roop_count;
SPIDER_SHARE *share = spider->share;
@@ -7186,7 +7186,7 @@ int spider_db_direct_delete(
if (!counted)
{
*delete_rows = spider->conns[roop_count]->db_conn->affected_rows();
- DBUG_PRINT("info", ("spider delete_rows = %u", *delete_rows));
+ DBUG_PRINT("info", ("spider delete_rows = %llu", *delete_rows));
counted = TRUE;
}
#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET)
diff --git a/storage/spider/spd_db_conn.h b/storage/spider/spd_db_conn.h
index 6d149f6d4a0..ab6826d0157 100644
--- a/storage/spider/spd_db_conn.h
+++ b/storage/spider/spd_db_conn.h
@@ -325,7 +325,7 @@ int spider_db_query_for_bulk_update(
ha_spider *spider,
SPIDER_CONN *conn,
int link_idx,
- uint *dup_key_found
+ ha_rows *dup_key_found
);
size_t spider_db_real_escape_string(
@@ -713,7 +713,7 @@ int spider_db_bulk_update_size_limit(
int spider_db_bulk_update_end(
ha_spider *spider,
- uint *dup_key_found
+ ha_rows *dup_key_found
);
int spider_db_bulk_update(
@@ -734,14 +734,14 @@ int spider_db_direct_update(
TABLE *table,
KEY_MULTI_RANGE *ranges,
uint range_count,
- uint *update_rows
+ ha_rows *update_rows
);
#endif
#ifdef HA_CAN_BULK_ACCESS
int spider_db_bulk_direct_update(
ha_spider *spider,
- uint *update_rows
+ ha_rows *update_rows
);
#endif
@@ -763,7 +763,7 @@ int spider_db_direct_delete(
TABLE *table,
KEY_MULTI_RANGE *ranges,
uint range_count,
- uint *delete_rows
+ ha_rows *delete_rows
);
#endif
diff --git a/storage/spider/spd_environ.h b/storage/spider/spd_environ.h
index 1ca40f3f8cd..fa462c75230 100644
--- a/storage/spider/spd_environ.h
+++ b/storage/spider/spd_environ.h
@@ -14,7 +14,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/*
- Define functinolity offered by MySQL or MariaDB
+ Define functionality offered by MySQL or MariaDB
*/
#ifndef SPD_ENVIRON_INCLUDED
@@ -25,6 +25,7 @@
#if MYSQL_VERSION_ID >= 100204
#define HANDLER_HAS_TOP_TABLE_FIELDS
+#define HANDLER_HAS_DIRECT_UPDATE_ROWS
#define HANDLER_HAS_DIRECT_AGGREGATE
#define PARTITION_HAS_EXTRA_ATTACH_CHILDREN
#define PARTITION_HAS_GET_CHILD_HANDLERS