12
12
You should have received a copy of the GNU General Public License
13
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
29
29
#include "drizzled/records.h"
30
30
#include "drizzled/internal/my_sys.h"
31
31
#include "drizzled/internal/iocache.h"
32
#include "drizzled/transaction_services.h"
33
#include "drizzled/filesort.h"
35
#include <boost/dynamic_bitset.hpp>
38
35
using namespace std;
46
43
If we got a duplicate key error, we want to write an error
47
44
message containing the value of the duplicate key. If we do not have
48
all fields of the key value in getInsertRecord(), we need to re-read the
45
all fields of the key value in record[0], we need to re-read the
49
46
record with a proper read_set.
51
48
@param[in] error error number
55
52
static void prepare_record_for_error_message(int error, Table *table)
57
Field **field_p= NULL;
57
MyBitmap unique_map; /* Fields in offended unique. */
58
my_bitmap_map unique_map_buf[bitmap_buffer_size(MAX_FIELDS)];
62
61
Only duplicate key errors print the key value.
63
62
If storage engine does always read all columns, we have the value alraedy.
65
64
if ((error != HA_ERR_FOUND_DUPP_KEY) ||
66
! (table->cursor->getEngine()->check_flag(HTON_BIT_PARTIAL_COLUMN_READ)))
65
!(table->cursor->getEngine()->check_flag(HTON_BIT_PARTIAL_COLUMN_READ)))
76
75
/* Create unique_map with all fields used by that index. */
77
boost::dynamic_bitset<> unique_map(table->getShare()->sizeFields()); /* Fields in offended unique. */
78
table->mark_columns_used_by_index_no_reset(keynr, unique_map);
76
unique_map.init(unique_map_buf, table->s->fields);
77
table->mark_columns_used_by_index_no_reset(keynr, &unique_map);
80
79
/* Subtract read_set and write_set. */
81
unique_map-= *table->read_set;
82
unique_map-= *table->write_set;
80
bitmap_subtract(&unique_map, table->read_set);
81
bitmap_subtract(&unique_map, table->write_set);
85
84
If the unique index uses columns that are neither in read_set
86
85
nor in write_set, we must re-read the record.
87
86
Otherwise no need to do anything.
89
if (unique_map.none())
88
if (unique_map.isClearAll())
92
91
/* Get identifier of last read record into table->cursor->ref. */
93
table->cursor->position(table->getInsertRecord());
92
table->cursor->position(table->record[0]);
94
93
/* Add all fields used by unique index to read_set. */
95
*table->read_set|= unique_map;
94
bitmap_union(table->read_set, &unique_map);
96
95
/* Read record that is identified by table->cursor->ref. */
97
(void) table->cursor->rnd_pos(table->getUpdateRecord(), table->cursor->ref);
96
(void) table->cursor->rnd_pos(table->record[1], table->cursor->ref);
98
97
/* Copy the newly read columns into the new record. */
99
for (field_p= table->getFields(); (field= *field_p); field_p++)
101
if (unique_map.test(field->field_index))
103
field->copy_from_tmp(table->getShare()->rec_buff_length);
98
for (field_p= table->field; (field= *field_p); field_p++)
99
if (unique_map.isBitSet(field->field_index))
100
field->copy_from_tmp(table->s->rec_buff_length);
130
125
int mysql_update(Session *session, TableList *table_list,
131
126
List<Item> &fields, List<Item> &values, COND *conds,
132
uint32_t order_num, Order *order,
127
uint32_t order_num, order_st *order,
133
128
ha_rows limit, enum enum_duplicates,
136
131
bool using_limit= limit != HA_POS_ERROR;
137
132
bool used_key_is_modified;
138
133
bool transactional_table;
134
bool can_compare_record;
140
136
uint used_index= MAX_KEY, dup_key_found;
141
137
bool need_sort= true;
143
139
key_map old_covering_keys;
145
141
optimizer::SqlSelect *select= NULL;
147
143
Select_Lex *select_lex= &session->lex->select_lex;
149
145
List<Item> all_fields;
150
Session::killed_state_t killed_status= Session::NOT_KILLED;
146
Session::killed_state killed_status= Session::NOT_KILLED;
152
DRIZZLE_UPDATE_START(session->getQueryString()->c_str());
148
DRIZZLE_UPDATE_START(session->query);
153
149
if (session->openTablesLock(table_list))
155
151
DRIZZLE_UPDATE_DONE(1, 0, 0);
160
156
table= table_list->table;
162
158
/* Calculate "table->covering_keys" based on the WHERE */
163
table->covering_keys= table->getShare()->keys_in_use;
159
table->covering_keys= table->s->keys_in_use;
164
160
table->quick_keys.reset();
166
162
if (mysql_prepare_update(session, table_list, &conds, order_num, order))
168
DRIZZLE_UPDATE_DONE(1, 0, 0);
172
165
old_covering_keys= table->covering_keys; // Keys used in WHERE
173
166
/* Check the fields we are going to modify */
174
167
if (setup_fields_with_no_wrap(session, 0, fields, MARK_COLUMNS_WRITE, 0, 0))
176
DRIZZLE_UPDATE_DONE(1, 0, 0);
180
169
if (table->timestamp_field)
182
171
// Don't set timestamp column if this is modified
183
172
if (table->timestamp_field->isWriteSet())
185
173
table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
189
176
if (table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_UPDATE ||
190
177
table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_BOTH)
192
178
table->setWriteSet(table->timestamp_field->field_index);
197
182
if (setup_fields(session, 0, values, MARK_COLUMNS_READ, 0, 0))
199
184
free_underlaid_joins(session, select_lex);
200
DRIZZLE_UPDATE_DONE(1, 0, 0);
205
188
if (select_lex->inner_refs_list.elements &&
226
209
table->timestamp_field &&
227
210
(table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_UPDATE ||
228
211
table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_BOTH))
230
*table->read_set|= *table->write_set;
212
bitmap_union(table->read_set, table->write_set);
232
213
// Don't count on usage of 'only index' when calculating which key to use
233
214
table->covering_keys.reset();
247
228
session->main_da.reset_diagnostics_area();
248
229
free_underlaid_joins(session, select_lex);
251
DRIZZLE_UPDATE_DONE(1, 0, 0);
231
goto abort; // Error in where
254
232
DRIZZLE_UPDATE_DONE(0, 0, 0);
255
233
session->my_ok(); // No matching records
282
260
if (used_index == MAX_KEY) // no index for sort order
283
261
used_index= table->cursor->key_used_on_scan;
284
262
if (used_index != MAX_KEY)
285
used_key_is_modified= is_key_used(table, used_index, *table->write_set);
263
used_key_is_modified= is_key_used(table, used_index, table->write_set);
311
289
NOTE: filesort will call table->prepare_for_position()
313
291
uint32_t length= 0;
314
SortField *sortorder;
292
SORT_FIELD *sortorder;
315
293
ha_rows examined_rows;
316
FileSort filesort(*session);
318
table->sort.io_cache= new internal::IO_CACHE;
295
table->sort.io_cache = new internal::IO_CACHE;
296
memset(table->sort.io_cache, 0, sizeof(internal::IO_CACHE));
320
298
if (!(sortorder=make_unireg_sortorder(order, &length, NULL)) ||
321
(table->sort.found_records= filesort.run(table, sortorder, length,
323
examined_rows)) == HA_POS_ERROR)
299
(table->sort.found_records= filesort(session, table, sortorder, length,
342
321
internal::IO_CACHE tempfile;
343
if (tempfile.open_cached_file(drizzle_tmpdir.c_str(),TEMP_PREFIX, DISK_BUFFER_SIZE, MYF(MY_WME)))
322
if (open_cached_file(&tempfile, drizzle_tmpdir,TEMP_PREFIX,
323
DISK_BUFFER_SIZE, MYF(MY_WME)))
348
326
/* If quick select is used, initialize it before retrieving rows. */
349
327
if (select && select->quick && select->quick->reset())
364
342
if (used_index == MAX_KEY || (select && select->quick))
366
info.init_read_record(session, table, select, 0, true);
343
init_read_record(&info,session,table,select,0,1);
370
info.init_read_record_idx(session, table, 1, used_index);
345
init_read_record_idx(&info, session, table, 1, used_index);
373
347
session->set_proc_info("Searching rows for update");
374
348
ha_rows tmp_limit= limit;
376
while (not(error= info.read_record(&info)) && not session->getKilled())
350
while (!(error=info.read_record(&info)) && !session->killed)
378
352
if (!(select && select->skip_record()))
380
354
if (table->cursor->was_semi_consistent_read())
381
355
continue; /* repeat the read of the same row if it still exists */
383
table->cursor->position(table->getInsertRecord());
357
table->cursor->position(table->record[0]);
384
358
if (my_b_write(&tempfile,table->cursor->ref,
385
359
table->cursor->ref_length))
397
371
table->cursor->unlock_row();
399
if (session->getKilled() && not error)
373
if (session->killed && !error)
400
374
error= 1; // Aborted
401
375
limit= tmp_limit;
402
376
table->cursor->try_semi_consistent_read(0);
403
info.end_read_record();
377
end_read_record(&info);
405
379
/* Change select to use tempfile */
416
390
select= new optimizer::SqlSelect;
417
391
select->head=table;
419
if (tempfile.reinit_io_cache(internal::READ_CACHE,0L,0,0))
393
if (reinit_io_cache(&tempfile,internal::READ_CACHE,0L,0,0))
421
395
// Read row ptrs from this cursor
422
396
memcpy(select->file, &tempfile, sizeof(tempfile));
433
407
if (select && select->quick && select->quick->reset())
435
409
table->cursor->try_semi_consistent_read(1);
436
info.init_read_record(session, table, select, 0, true);
410
init_read_record(&info,session,table,select,0,1);
438
412
updated= found= 0;
458
432
if (table->cursor->getEngine()->check_flag(HTON_BIT_PARTIAL_COLUMN_READ))
459
433
table->prepare_for_position();
461
while (not (error=info.read_record(&info)) && not session->getKilled())
436
We can use compare_record() to optimize away updates if
437
the table handler is returning all columns OR if
438
if all updated columns are read
440
can_compare_record= (!(table->cursor->getEngine()->check_flag(HTON_BIT_PARTIAL_COLUMN_READ)) ||
441
bitmap_is_subset(table->write_set, table->read_set));
443
while (!(error=info.read_record(&info)) && !session->killed)
463
if (not (select && select->skip_record()))
445
if (!(select && select->skip_record()))
465
447
if (table->cursor->was_semi_consistent_read())
466
448
continue; /* repeat the read of the same row if it still exists */
474
if (! table->records_are_comparable() || table->compare_records())
456
if (!can_compare_record || table->compare_record())
476
458
/* Non-batched update */
477
error= table->cursor->updateRecord(table->getUpdateRecord(),
478
table->getInsertRecord());
480
table->auto_increment_field_not_null= false;
459
error= table->cursor->ha_update_row(table->record[1],
482
461
if (!error || error == HA_ERR_RECORD_IS_THE_SAME)
484
463
if (error != HA_ERR_RECORD_IS_THE_SAME)
490
469
table->cursor->is_fatal_error(error, HA_CHECK_DUP_KEY))
493
472
If (ignore && error is ignorable) we don't have to
494
473
do anything; otherwise...
499
478
flags|= ME_FATALERROR; /* Other handler errors are fatal */
501
480
prepare_record_for_error_message(error, table);
502
table->print_error(error,MYF(flags));
481
table->print_error(error,MYF(flags));
508
487
if (!--limit && using_limit)
524
503
It's assumed that if an error was set in combination with an effective
525
504
killed status then the error is due to killing.
527
killed_status= session->getKilled(); // get the status of the volatile
506
killed_status= session->killed; // get the status of the volatile
528
507
// simulated killing after the loop must be ineffective for binlogging
529
508
error= (killed_status == Session::NOT_KILLED)? error : 1;
532
511
table->cursor->try_semi_consistent_read(0);
534
513
if (!transactional_table && updated > 0)
535
session->transaction.stmt.markModifiedNonTransData();
514
session->transaction.stmt.modified_non_trans_table= true;
537
info.end_read_record();
516
end_read_record(&info);
539
518
session->set_proc_info("end");
540
519
table->cursor->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
544
523
last one without error. error > 0 means an error (e.g. unique key
545
524
violation and no IGNORE or REPLACE). error == 0 is also an error (if
546
525
preparing the record or invoking before triggers fails). See
547
autocommitOrRollback(error>=0) and return(error>=0) below.
526
ha_autocommit_or_rollback(error>=0) and return(error>=0) below.
548
527
Sometimes we want to binlog even if we updated no rows, in case user used
549
528
it to be sure master and slave are in same state.
551
if ((error < 0) || session->transaction.stmt.hasModifiedNonTransData())
530
if ((error < 0) || session->transaction.stmt.modified_non_trans_table)
553
if (session->transaction.stmt.hasModifiedNonTransData())
554
session->transaction.all.markModifiedNonTransData();
532
if (session->transaction.stmt.modified_non_trans_table)
533
session->transaction.all.modified_non_trans_table= true;
556
assert(transactional_table || !updated || session->transaction.stmt.hasModifiedNonTransData());
535
assert(transactional_table || !updated || session->transaction.stmt.modified_non_trans_table);
557
536
free_underlaid_joins(session, select_lex);
559
538
/* If LAST_INSERT_ID(X) was used, report X */
565
544
char buff[STRING_BUFFER_USUAL_SIZE];
566
snprintf(buff, sizeof(buff), ER(ER_UPDATE_INFO), (ulong) found, (ulong) updated,
545
sprintf(buff, ER(ER_UPDATE_INFO), (ulong) found, (ulong) updated,
567
546
(ulong) session->cuted_fields);
568
547
session->row_count_func= updated;
573
552
session->main_da.reset_diagnostics_area();
574
553
session->my_ok((ulong) session->row_count_func, found, id, buff);
575
session->status_var.updated_row_count+= session->row_count_func;
577
session->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL; /* calc cuted fields */
555
session->count_cuted_fields= CHECK_FIELD_IGNORE; /* calc cuted fields */
578
556
session->abort_on_warning= 0;
579
557
DRIZZLE_UPDATE_DONE((error >= 0 || session->is_error()), found, updated);
580
558
return ((error >= 0 || session->is_error()) ? 1 : 0);
611
590
bool mysql_prepare_update(Session *session, TableList *table_list,
612
Item **conds, uint32_t order_num, Order *order)
591
Item **conds, uint32_t order_num, order_st *order)
614
593
List<Item> all_fields;
615
594
Select_Lex *select_lex= &session->lex->select_lex;
632
611
TableList *duplicate;
633
612
if ((duplicate= unique_table(table_list, table_list->next_global)))
635
my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->getTableName());
614
my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->table_name);