mirror of
https://github.com/MariaDB/server.git
synced 2025-12-24 11:21:21 +03:00
Merge bk-internal.mysql.com:/home/bk/mysql-5.1-new
into mysql.com:/home/my/mysql-5.1 BitKeeper/etc/ignore: auto-union include/heap.h: Auto merged include/my_base.h: Auto merged include/mysql_com.h: Auto merged mysql-test/mysql-test-run.pl: Auto merged mysql-test/mysql-test-run.sh: Auto merged mysql-test/extra/binlog_tests/mix_innodb_myisam_binlog.test: Auto merged mysql-test/r/binlog_stm_mix_innodb_myisam.result: Auto merged mysql-test/r/func_time.result: Auto merged mysql-test/r/ndb_index_unique.result: Auto merged mysql-test/t/func_time.test: Auto merged mysql-test/t/view_grant.test: Auto merged sql/field.cc: Auto merged sql/field.h: Auto merged sql/ha_berkeley.cc: Auto merged sql/ha_berkeley.h: Auto merged mysql-test/r/view_grant.result: Auto merged sql/ha_federated.cc: Auto merged sql/ha_federated.h: Auto merged sql/ha_heap.h: Auto merged sql/ha_innodb.cc: Auto merged sql/ha_innodb.h: Auto merged sql/ha_myisam.h: Auto merged sql/ha_myisammrg.cc: Auto merged sql/ha_ndbcluster.h: Auto merged sql/ha_partition.h: Auto merged sql/item.cc: Auto merged sql/item_cmpfunc.h: Auto merged sql/item_func.cc: Auto merged sql/item_func.h: Auto merged sql/item_strfunc.h: Auto merged sql/item_subselect.cc: Auto merged sql/item_subselect.h: Auto merged sql/log.cc: Auto merged sql/mysqld.cc: Auto merged sql/set_var.cc: Auto merged sql/sp.cc: Auto merged sql/sp_head.cc: Auto merged sql/spatial.cc: Auto merged sql/sql_acl.cc: Auto merged sql/sql_base.cc: Auto merged sql/sql_class.cc: Auto merged sql/sql_class.h: Auto merged sql/sql_bitmap.h: Auto merged sql/sql_parse.cc: Auto merged sql/sql_partition.cc: Auto merged sql/sql_plugin.cc: Auto merged sql/sql_prepare.cc: Auto merged sql/share/errmsg.txt: Auto merged sql/sql_handler.cc: Auto merged sql/sql_view.cc: Auto merged sql/table.h: Auto merged storage/archive/ha_archive.cc: Auto merged storage/archive/ha_archive.h: Auto merged storage/example/ha_example.cc: Auto merged storage/myisam/ft_boolean_search.c: Auto merged unittest/mysys/base64-t.c: Auto merged mysql-test/r/innodb_mysql.result: manual merge mysql-test/t/innodb_mysql.test: manual merge mysql-test/valgrind.supp: manual merge sql/event.cc: manual merge sql/ha_heap.cc: manual merge sql/ha_myisam.cc: manual merge sql/ha_ndbcluster.cc: manual merge sql/ha_ndbcluster_binlog.cc: manual merge sql/ha_partition.cc: manual merge sql/handler.cc: manual merge renamed print_key_dupp_error to print_key_dup_error sql/handler.h: manual merge renamed print_key_dupp_error to print_key_dup_error sql/item.h: automatic merge sql/item_cmpfunc.cc: automatic merge sql/log_event.cc: manual merge Trivial cleanup sql/mysql_priv.h: manual merge renamed print_key_dupp_error to print_key_dup_error sql/opt_range.cc: manual merge renamed print_key_dupp_error to print_key_dup_error sql/sql_delete.cc: manual merge renamed print_key_dupp_error to print_key_dup_error sql/sql_insert.cc: manual merge renamed print_key_dupp_error to print_key_dup_error sql/sql_load.cc: manual merge renamed print_key_dupp_error to print_key_dup_error sql/sql_select.cc: manual merge renamed print_key_dupp_error to print_key_dup_error sql/sql_show.cc: manual merge renamed print_key_dupp_error to print_key_dup_error sql/sql_table.cc: manual merge renamed print_key_dupp_error to print_key_dup_error sql/sql_update.cc: manual merge renamed print_key_dupp_error to print_key_dup_error sql/table.cc: manual merge renamed print_key_dupp_error to print_key_dup_error storage/blackhole/ha_blackhole.cc: manual merge renamed print_key_dupp_error to print_key_dup_error storage/csv/ha_tina.cc: manual merge renamed print_key_dupp_error to print_key_dup_error mysql-test/valgrind.supp.orig: Manual merge
This commit is contained in:
@@ -29,7 +29,7 @@ static bool safe_update_on_fly(JOIN_TAB *join_tab, List<Item> *fields);
|
||||
|
||||
/* Return 0 if row hasn't changed */
|
||||
|
||||
static bool compare_record(TABLE *table, query_id_t query_id)
|
||||
static bool compare_record(TABLE *table)
|
||||
{
|
||||
if (table->s->blob_fields + table->s->varchar_fields == 0)
|
||||
return cmp_record(table,record[1]);
|
||||
@@ -39,9 +39,9 @@ static bool compare_record(TABLE *table, query_id_t query_id)
|
||||
table->s->null_bytes))
|
||||
return TRUE; // Diff in NULL value
|
||||
/* Compare updated fields */
|
||||
for (Field **ptr=table->field ; *ptr ; ptr++)
|
||||
for (Field **ptr= table->field ; *ptr ; ptr++)
|
||||
{
|
||||
if ((*ptr)->query_id == query_id &&
|
||||
if (bitmap_is_set(table->write_set, (*ptr)->field_index) &&
|
||||
(*ptr)->cmp_binary_offset(table->s->rec_buff_length))
|
||||
return TRUE;
|
||||
}
|
||||
@@ -120,6 +120,7 @@ int mysql_update(THD *thd,
|
||||
bool using_limit= limit != HA_POS_ERROR;
|
||||
bool safe_update= thd->options & OPTION_SAFE_UPDATES;
|
||||
bool used_key_is_modified, transactional_table, will_batch;
|
||||
bool can_compare_record;
|
||||
int res;
|
||||
int error, loc_error;
|
||||
uint used_index= MAX_KEY, dup_key_found;
|
||||
@@ -128,7 +129,6 @@ int mysql_update(THD *thd,
|
||||
uint want_privilege;
|
||||
#endif
|
||||
uint table_count= 0;
|
||||
query_id_t query_id=thd->query_id, timestamp_query_id;
|
||||
ha_rows updated, found;
|
||||
key_map old_used_keys;
|
||||
TABLE *table;
|
||||
@@ -138,8 +138,6 @@ int mysql_update(THD *thd,
|
||||
bool need_reopen;
|
||||
DBUG_ENTER("mysql_update");
|
||||
|
||||
LINT_INIT(timestamp_query_id);
|
||||
|
||||
for ( ; ; )
|
||||
{
|
||||
if (open_tables(thd, &table_list, &table_count, 0))
|
||||
@@ -181,26 +179,12 @@ int mysql_update(THD *thd,
|
||||
DBUG_RETURN(1);
|
||||
|
||||
old_used_keys= table->used_keys; // Keys used in WHERE
|
||||
/*
|
||||
Change the query_id for the timestamp column so that we can
|
||||
check if this is modified directly
|
||||
*/
|
||||
if (table->timestamp_field)
|
||||
{
|
||||
timestamp_query_id=table->timestamp_field->query_id;
|
||||
table->timestamp_field->query_id=thd->query_id-1;
|
||||
}
|
||||
|
||||
/* Check the fields we are going to modify */
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
table_list->grant.want_privilege= table->grant.want_privilege= want_privilege;
|
||||
table_list->register_want_access(want_privilege);
|
||||
#endif
|
||||
/*
|
||||
Indicate that the set of fields is to be updated by passing 2 for
|
||||
set_query_id.
|
||||
*/
|
||||
if (setup_fields_with_no_wrap(thd, 0, fields, 2, 0, 0))
|
||||
if (setup_fields_with_no_wrap(thd, 0, fields, MARK_COLUMNS_WRITE, 0, 0))
|
||||
DBUG_RETURN(1); /* purecov: inspected */
|
||||
if (table_list->view && check_fields(thd, fields))
|
||||
{
|
||||
@@ -214,12 +198,13 @@ int mysql_update(THD *thd,
|
||||
if (table->timestamp_field)
|
||||
{
|
||||
// Don't set timestamp column if this is modified
|
||||
if (table->timestamp_field->query_id == thd->query_id)
|
||||
if (bitmap_is_set(table->write_set,
|
||||
table->timestamp_field->field_index))
|
||||
table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
|
||||
else
|
||||
{
|
||||
table->timestamp_field->query_id=timestamp_query_id;
|
||||
table->file->ha_set_bit_in_write_set(table->timestamp_field->fieldnr);
|
||||
bitmap_set_bit(table->write_set,
|
||||
table->timestamp_field->field_index);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,7 +213,7 @@ int mysql_update(THD *thd,
|
||||
table_list->grant.want_privilege= table->grant.want_privilege=
|
||||
(SELECT_ACL & ~table->grant.privilege);
|
||||
#endif
|
||||
if (setup_fields(thd, 0, values, 1, 0, 0))
|
||||
if (setup_fields(thd, 0, values, MARK_COLUMNS_READ, 0, 0))
|
||||
{
|
||||
free_underlaid_joins(thd, select_lex);
|
||||
DBUG_RETURN(1); /* purecov: inspected */
|
||||
@@ -252,7 +237,7 @@ int mysql_update(THD *thd,
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
#endif
|
||||
/* Update the table->file->records number */
|
||||
/* Update the table->file->stats.records number */
|
||||
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
|
||||
|
||||
select= make_select(table, 0, 0, conds, 0, &error);
|
||||
@@ -313,19 +298,23 @@ int mysql_update(THD *thd,
|
||||
We can't update table directly; We must first search after all
|
||||
matching rows before updating the table!
|
||||
*/
|
||||
table->file->ha_retrieve_all_cols();
|
||||
if (used_index < MAX_KEY && old_used_keys.is_set(used_index))
|
||||
{
|
||||
table->key_read=1;
|
||||
table->file->extra(HA_EXTRA_KEYREAD);
|
||||
table->mark_columns_used_by_index(used_index);
|
||||
}
|
||||
else
|
||||
{
|
||||
table->use_all_columns();
|
||||
}
|
||||
|
||||
/* note: can actually avoid sorting below.. */
|
||||
/* note: We avoid sorting avoid if we sort on the used index */
|
||||
if (order && (need_sort || used_key_is_modified))
|
||||
{
|
||||
/*
|
||||
Doing an ORDER BY; Let filesort find and sort the rows we are going
|
||||
to update
|
||||
NOTE: filesort will call table->prepare_for_position()
|
||||
*/
|
||||
uint length;
|
||||
SORT_FIELD *sortorder;
|
||||
@@ -334,12 +323,11 @@ int mysql_update(THD *thd,
|
||||
table->sort.io_cache = (IO_CACHE *) my_malloc(sizeof(IO_CACHE),
|
||||
MYF(MY_FAE | MY_ZEROFILL));
|
||||
if (!(sortorder=make_unireg_sortorder(order, &length)) ||
|
||||
(table->sort.found_records = filesort(thd, table, sortorder, length,
|
||||
select, limit,
|
||||
&examined_rows))
|
||||
(table->sort.found_records= filesort(thd, table, sortorder, length,
|
||||
select, limit, 1,
|
||||
&examined_rows))
|
||||
== HA_POS_ERROR)
|
||||
{
|
||||
free_io_cache(table);
|
||||
goto err;
|
||||
}
|
||||
/*
|
||||
@@ -365,6 +353,7 @@ int mysql_update(THD *thd,
|
||||
/* If quick select is used, initialize it before retrieving rows. */
|
||||
if (select && select->quick && select->quick->reset())
|
||||
goto err;
|
||||
table->file->try_semi_consistent_read(1);
|
||||
|
||||
/*
|
||||
When we get here, we have one of the following options:
|
||||
@@ -376,11 +365,6 @@ int mysql_update(THD *thd,
|
||||
B.2 quick select is not used, this is full index scan (with LIMIT)
|
||||
Full index scan must be started with init_read_record_idx
|
||||
*/
|
||||
/* If quick select is used, initialize it before retrieving rows. */
|
||||
if (select && select->quick && select->quick->reset())
|
||||
goto err;
|
||||
|
||||
table->file->try_semi_consistent_read(1);
|
||||
|
||||
if (used_index == MAX_KEY || (select && select->quick))
|
||||
init_read_record(&info,thd,table,select,0,1);
|
||||
@@ -440,17 +424,14 @@ int mysql_update(THD *thd,
|
||||
goto err;
|
||||
}
|
||||
if (table->key_read)
|
||||
{
|
||||
table->key_read=0;
|
||||
table->file->extra(HA_EXTRA_NO_KEYREAD);
|
||||
}
|
||||
table->restore_column_maps_after_mark_index();
|
||||
}
|
||||
|
||||
if (ignore)
|
||||
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
|
||||
|
||||
if (select && select->quick && select->quick->reset())
|
||||
goto err;
|
||||
goto err;
|
||||
table->file->try_semi_consistent_read(1);
|
||||
init_read_record(&info,thd,table,select,0,1);
|
||||
|
||||
@@ -458,7 +439,6 @@ int mysql_update(THD *thd,
|
||||
thd->count_cuted_fields= CHECK_FIELD_WARN; /* calc cuted fields */
|
||||
thd->cuted_fields=0L;
|
||||
thd->proc_info="Updating";
|
||||
query_id=thd->query_id;
|
||||
|
||||
transactional_table= table->file->has_transactions();
|
||||
thd->no_trans_update= 0;
|
||||
@@ -468,12 +448,23 @@ int mysql_update(THD *thd,
|
||||
MODE_STRICT_ALL_TABLES)));
|
||||
will_batch= !table->file->start_bulk_update();
|
||||
|
||||
table->mark_columns_needed_for_update();
|
||||
|
||||
/*
|
||||
We can use compare_record() to optimize away updates if
|
||||
the table handler is returning all columns OR if
|
||||
if all updated columns are read
|
||||
*/
|
||||
can_compare_record= (!(table->file->ha_table_flags() &
|
||||
HA_PARTIAL_COLUMN_READ) ||
|
||||
bitmap_is_subset(table->write_set, table->read_set));
|
||||
|
||||
while (!(error=info.read_record(&info)) && !thd->killed)
|
||||
{
|
||||
if (!(select && select->skip_record()))
|
||||
{
|
||||
if (table->file->was_semi_consistent_read())
|
||||
continue; /* repeat the read of the same row if it still exists */
|
||||
continue; /* repeat the read of the same row if it still exists */
|
||||
|
||||
store_record(table,record[1]);
|
||||
if (fill_record_n_invoke_before_triggers(thd, fields, values, 0,
|
||||
@@ -483,7 +474,7 @@ int mysql_update(THD *thd,
|
||||
|
||||
found++;
|
||||
|
||||
if (compare_record(table, query_id))
|
||||
if (!can_compare_record || compare_record(table))
|
||||
{
|
||||
if ((res= table_list->view_check_option(thd, ignore)) !=
|
||||
VIEW_CHECK_OK)
|
||||
@@ -632,7 +623,6 @@ int mysql_update(THD *thd,
|
||||
table->file->end_bulk_update();
|
||||
table->file->try_semi_consistent_read(0);
|
||||
end_read_record(&info);
|
||||
free_io_cache(table); // If ORDER BY
|
||||
delete select;
|
||||
thd->proc_info= "end";
|
||||
VOID(table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY));
|
||||
@@ -698,7 +688,6 @@ int mysql_update(THD *thd,
|
||||
}
|
||||
thd->count_cuted_fields= CHECK_FIELD_IGNORE; /* calc cuted fields */
|
||||
thd->abort_on_warning= 0;
|
||||
free_io_cache(table);
|
||||
DBUG_RETURN((error >= 0 || thd->net.report_error) ? 1 : 0);
|
||||
|
||||
err:
|
||||
@@ -750,7 +739,7 @@ bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
|
||||
|
||||
if (setup_tables_and_check_access(thd, &select_lex->context,
|
||||
&select_lex->top_join_list,
|
||||
table_list, conds,
|
||||
table_list,
|
||||
&select_lex->leaf_tables,
|
||||
FALSE, UPDATE_ACL) ||
|
||||
setup_conds(thd, table_list, select_lex->leaf_tables, conds) ||
|
||||
@@ -845,12 +834,12 @@ reopen_tables:
|
||||
|
||||
if (setup_tables_and_check_access(thd, &lex->select_lex.context,
|
||||
&lex->select_lex.top_join_list,
|
||||
table_list, &lex->select_lex.where,
|
||||
table_list,
|
||||
&lex->select_lex.leaf_tables, FALSE,
|
||||
UPDATE_ACL))
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
if (setup_fields_with_no_wrap(thd, 0, *fields, 2, 0, 0))
|
||||
if (setup_fields_with_no_wrap(thd, 0, *fields, MARK_COLUMNS_WRITE, 0, 0))
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
for (tl= table_list; tl ; tl= tl->next_local)
|
||||
@@ -878,7 +867,8 @@ reopen_tables:
|
||||
TABLE *table= tl->table;
|
||||
/* Only set timestamp column if this is not modified */
|
||||
if (table->timestamp_field &&
|
||||
table->timestamp_field->query_id == thd->query_id)
|
||||
bitmap_is_set(table->write_set,
|
||||
table->timestamp_field->field_index))
|
||||
table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
|
||||
|
||||
/* if table will be updated then check that it is unique */
|
||||
@@ -890,6 +880,7 @@ reopen_tables:
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
|
||||
table->mark_columns_needed_for_update();
|
||||
DBUG_PRINT("info",("setting table `%s` for update", tl->alias));
|
||||
/*
|
||||
If table will be updated we should not downgrade lock for it and
|
||||
@@ -1091,7 +1082,7 @@ int multi_update::prepare(List<Item> ¬_used_values,
|
||||
reference tables
|
||||
*/
|
||||
|
||||
if (setup_fields(thd, 0, *values, 1, 0, 0))
|
||||
if (setup_fields(thd, 0, *values, MARK_COLUMNS_READ, 0, 0))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
/*
|
||||
@@ -1210,7 +1201,9 @@ multi_update::initialize_tables(JOIN *join)
|
||||
Item_field *ifield;
|
||||
List<Item> temp_fields= *fields_for_table[cnt];
|
||||
ORDER group;
|
||||
TMP_TABLE_PARAM *tmp_param;
|
||||
|
||||
table->mark_columns_needed_for_update();
|
||||
if (table == main_table) // First table in join
|
||||
{
|
||||
if (safe_update_on_fly(join->join_tab, &temp_fields))
|
||||
@@ -1219,9 +1212,9 @@ multi_update::initialize_tables(JOIN *join)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
table->prepare_for_position();
|
||||
|
||||
TMP_TABLE_PARAM *tmp_param= tmp_table_param+cnt;
|
||||
|
||||
tmp_param= tmp_table_param+cnt;
|
||||
/*
|
||||
Create a temporary table to store all fields that are changed for this
|
||||
table. The first field in the temporary table is a pointer to the
|
||||
@@ -1316,7 +1309,7 @@ static bool safe_update_on_fly(JOIN_TAB *join_tab, List<Item> *fields)
|
||||
!(table->triggers &&
|
||||
table->triggers->has_before_update_triggers());
|
||||
/* If scanning in clustered key */
|
||||
if ((table->file->table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX) &&
|
||||
if ((table->file->ha_table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX) &&
|
||||
table->s->primary_key < MAX_KEY)
|
||||
return !check_if_key_used(table, table->s->primary_key, *fields) &&
|
||||
!(table->triggers &&
|
||||
@@ -1362,6 +1355,7 @@ bool multi_update::send_data(List<Item> ¬_used_values)
|
||||
for (cur_table= update_tables; cur_table; cur_table= cur_table->next_local)
|
||||
{
|
||||
TABLE *table= cur_table->table;
|
||||
uint offset= cur_table->shared;
|
||||
/*
|
||||
Check if we are using outer join and we didn't find the row
|
||||
or if we have already updated this row in the previous call to this
|
||||
@@ -1377,10 +1371,18 @@ bool multi_update::send_data(List<Item> ¬_used_values)
|
||||
if (table->status & (STATUS_NULL_ROW | STATUS_UPDATED))
|
||||
continue;
|
||||
|
||||
uint offset= cur_table->shared;
|
||||
table->file->position(table->record[0]);
|
||||
/*
|
||||
We can use compare_record() to optimize away updates if
|
||||
the table handler is returning all columns OR if
|
||||
if all updated columns are read
|
||||
*/
|
||||
if (table == table_to_update)
|
||||
{
|
||||
bool can_compare_record;
|
||||
can_compare_record= (!(table->file->ha_table_flags() &
|
||||
HA_PARTIAL_COLUMN_READ) ||
|
||||
bitmap_is_subset(table->write_set,
|
||||
table->read_set));
|
||||
table->status|= STATUS_UPDATED;
|
||||
store_record(table,record[1]);
|
||||
if (fill_record_n_invoke_before_triggers(thd, *fields_for_table[offset],
|
||||
@@ -1390,7 +1392,7 @@ bool multi_update::send_data(List<Item> ¬_used_values)
|
||||
DBUG_RETURN(1);
|
||||
|
||||
found++;
|
||||
if (compare_record(table, thd->query_id))
|
||||
if (!can_compare_record || compare_record(table))
|
||||
{
|
||||
int error;
|
||||
if ((error= cur_table->view_check_option(thd, ignore)) !=
|
||||
@@ -1442,6 +1444,7 @@ bool multi_update::send_data(List<Item> ¬_used_values)
|
||||
{
|
||||
int error;
|
||||
TABLE *tmp_table= tmp_tables[offset];
|
||||
table->file->position(table->record[0]);
|
||||
fill_record(thd, tmp_table->field+1, *values_for_table[offset], 1);
|
||||
/* Store pointer to row */
|
||||
memcpy((char*) tmp_table->field[0]->ptr,
|
||||
@@ -1507,6 +1510,7 @@ int multi_update::do_updates(bool from_send_error)
|
||||
for (cur_table= update_tables; cur_table; cur_table= cur_table->next_local)
|
||||
{
|
||||
byte *ref_pos;
|
||||
bool can_compare_record;
|
||||
|
||||
table = cur_table->table;
|
||||
if (table == table_to_update)
|
||||
@@ -1533,6 +1537,11 @@ int multi_update::do_updates(bool from_send_error)
|
||||
if ((local_error = tmp_table->file->ha_rnd_init(1)))
|
||||
goto err;
|
||||
|
||||
can_compare_record= (!(table->file->ha_table_flags() &
|
||||
HA_PARTIAL_COLUMN_READ) ||
|
||||
bitmap_is_subset(table->write_set,
|
||||
table->read_set));
|
||||
|
||||
ref_pos= (byte*) tmp_table->field[0]->ptr;
|
||||
for (;;)
|
||||
{
|
||||
@@ -1562,7 +1571,7 @@ int multi_update::do_updates(bool from_send_error)
|
||||
TRG_ACTION_BEFORE, TRUE))
|
||||
goto err2;
|
||||
|
||||
if (compare_record(table, thd->query_id))
|
||||
if (!can_compare_record || compare_record(table))
|
||||
{
|
||||
if ((local_error=table->file->ha_update_row(table->record[1],
|
||||
table->record[0])))
|
||||
|
||||
Reference in New Issue
Block a user