From 26211d5567d72e502f6edaaab7bdefbafd92cdd8 Mon Sep 17 00:00:00 2001 From: Jacob Mathew Date: Sat, 14 Oct 2017 15:24:24 -0700 Subject: Adding direct update/delete to the server and to the partition engine. 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. --- sql/ha_partition.cc | 656 ++++++++++++++++++++- sql/ha_partition.h | 21 +- sql/handler.cc | 91 ++- sql/handler.h | 160 +++-- sql/opt_sum.cc | 9 +- sql/sql_delete.cc | 72 ++- sql/sql_update.cc | 93 ++- sql/table.cc | 53 ++ sql/table.h | 2 + storage/spider/ha_spider.cc | 26 +- storage/spider/ha_spider.h | 62 +- .../mysql-test/spider/bg/r/direct_update.result | 8 + .../spider/bg/r/direct_update_part.result | 8 + .../mysql-test/spider/bg/r/spider_fixes.result | 1 + .../spider/handler/r/direct_update.result | 8 + .../spider/handler/r/direct_update_part.result | 8 + .../spider/handler/r/spider_fixes.result | 1 + .../mysql-test/spider/r/direct_update.result | 8 + .../mysql-test/spider/r/direct_update_part.result | 8 + .../spider/mysql-test/spider/r/spider_fixes.result | 1 + storage/spider/spd_db_conn.cc | 22 +- storage/spider/spd_db_conn.h | 10 +- storage/spider/spd_environ.h | 3 +- 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]); @@ -11223,6 +11224,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(¬_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(¬_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. 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_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 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 -- cgit v1.2.1