~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_update.cc

  • Committer: Joe Daly
  • Date: 2010-03-08 04:23:54 UTC
  • mto: This revision was merged to the branch mainline in revision 1380.
  • Revision ID: skinny.moey@gmail.com-20100308042354-7k0jibdqaxkhac7o
scoreboardĀ implementationĀ forĀ statistics

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
 
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 */
15
15
 
16
16
 
17
17
/*
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"
34
32
 
35
 
#include <boost/dynamic_bitset.hpp>
36
33
#include <list>
37
34
 
38
35
using namespace std;
45
42
 
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.
50
47
 
51
48
  @param[in] error   error number
54
51
 
55
52
static void prepare_record_for_error_message(int error, Table *table)
56
53
{
57
 
  Field **field_p= NULL;
58
 
  Field *field= NULL;
59
 
  uint32_t keynr= 0;
 
54
  Field **field_p;
 
55
  Field *field;
 
56
  uint32_t keynr;
 
57
  MyBitmap unique_map; /* Fields in offended unique. */
 
58
  my_bitmap_map unique_map_buf[bitmap_buffer_size(MAX_FIELDS)];
60
59
 
61
60
  /*
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.
64
63
  */
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)))
67
66
    return;
68
67
 
69
68
  /*
74
73
    return;
75
74
 
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);
79
78
 
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);
83
82
 
84
83
  /*
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.
88
87
  */
89
 
  if (unique_map.none())
 
88
  if (unique_map.isClearAll())
90
89
    return;
91
90
 
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++)
100
 
  {
101
 
    if (unique_map.test(field->field_index))
102
 
    {
103
 
      field->copy_from_tmp(table->getShare()->rec_buff_length);
104
 
    }
105
 
  }
 
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);
106
101
 
107
102
  return;
108
103
}
129
124
 
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,
134
129
                 bool ignore)
135
130
{
144
139
  key_map       old_covering_keys;
145
140
  Table         *table;
146
141
  optimizer::SqlSelect *select= NULL;
147
 
  ReadRecord    info;
 
142
  READ_RECORD   info;
148
143
  Select_Lex    *select_lex= &session->lex->select_lex;
149
144
  uint64_t     id;
150
145
  List<Item> all_fields;
151
 
  Session::killed_state_t killed_status= Session::NOT_KILLED;
 
146
  Session::killed_state killed_status= Session::NOT_KILLED;
152
147
 
153
 
  DRIZZLE_UPDATE_START(session->getQueryString()->c_str());
 
148
  DRIZZLE_UPDATE_START(session->query.c_str());
154
149
  if (session->openTablesLock(table_list))
155
150
  {
156
151
    DRIZZLE_UPDATE_DONE(1, 0, 0);
161
156
  table= table_list->table;
162
157
 
163
158
  /* Calculate "table->covering_keys" based on the WHERE */
164
 
  table->covering_keys= table->getShare()->keys_in_use;
 
159
  table->covering_keys= table->s->keys_in_use;
165
160
  table->quick_keys.reset();
166
161
 
167
162
  if (mysql_prepare_update(session, table_list, &conds, order_num, order))
168
 
  {
169
 
    DRIZZLE_UPDATE_DONE(1, 0, 0);
170
 
    return 1;
171
 
  }
 
163
    goto abort;
172
164
 
173
165
  old_covering_keys= table->covering_keys;              // Keys used in WHERE
174
166
  /* Check the fields we are going to modify */
175
167
  if (setup_fields_with_no_wrap(session, 0, fields, MARK_COLUMNS_WRITE, 0, 0))
176
 
  {
177
 
    DRIZZLE_UPDATE_DONE(1, 0, 0);
178
 
    return 1;
179
 
  }
180
 
 
 
168
    goto abort;
181
169
  if (table->timestamp_field)
182
170
  {
183
171
    // Don't set timestamp column if this is modified
184
172
    if (table->timestamp_field->isWriteSet())
185
 
    {
186
173
      table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
187
 
    }
188
174
    else
189
175
    {
190
176
      if (table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_UPDATE ||
191
177
          table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_BOTH)
192
 
      {
193
178
        table->setWriteSet(table->timestamp_field->field_index);
194
 
      }
195
179
    }
196
180
  }
197
181
 
198
182
  if (setup_fields(session, 0, values, MARK_COLUMNS_READ, 0, 0))
199
183
  {
200
184
    free_underlaid_joins(session, select_lex);
201
 
    DRIZZLE_UPDATE_DONE(1, 0, 0);
202
 
 
203
 
    return 1;
 
185
    goto abort;
204
186
  }
205
187
 
206
188
  if (select_lex->inner_refs_list.elements &&
227
209
      table->timestamp_field &&
228
210
      (table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_UPDATE ||
229
211
       table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_BOTH))
230
 
  {
231
 
    *table->read_set|= *table->write_set;
232
 
  }
 
212
    bitmap_union(table->read_set, table->write_set);
233
213
  // Don't count on usage of 'only index' when calculating which key to use
234
214
  table->covering_keys.reset();
235
215
 
248
228
    session->main_da.reset_diagnostics_area();
249
229
    free_underlaid_joins(session, select_lex);
250
230
    if (error)
251
 
    {
252
 
      DRIZZLE_UPDATE_DONE(1, 0, 0);
253
 
      return 1;
254
 
    }
 
231
      goto abort;                               // Error in where
255
232
    DRIZZLE_UPDATE_DONE(0, 0, 0);
256
233
    session->my_ok();                           // No matching records
257
234
    return 0;
275
252
  {
276
253
    used_index= select->quick->index;
277
254
    used_key_is_modified= (!select->quick->unique_key_range() &&
278
 
                          select->quick->is_keys_used(*table->write_set));
 
255
                          select->quick->is_keys_used(table->write_set));
279
256
  }
280
257
  else
281
258
  {
283
260
    if (used_index == MAX_KEY)                  // no index for sort order
284
261
      used_index= table->cursor->key_used_on_scan;
285
262
    if (used_index != MAX_KEY)
286
 
      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);
287
264
  }
288
265
 
289
266
 
312
289
        NOTE: filesort will call table->prepare_for_position()
313
290
      */
314
291
      uint32_t         length= 0;
315
 
      SortField  *sortorder;
 
292
      SORT_FIELD  *sortorder;
316
293
      ha_rows examined_rows;
317
 
      FileSort filesort(*session);
318
294
 
319
 
      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
297
 
321
298
      if (!(sortorder=make_unireg_sortorder(order, &length, NULL)) ||
322
 
          (table->sort.found_records= filesort.run(table, sortorder, length,
323
 
                                                   select, limit, 1,
324
 
                                                   examined_rows)) == HA_POS_ERROR)
 
299
          (table->sort.found_records= filesort(session, table, sortorder, length,
 
300
                                               select, limit, 1,
 
301
                                               &examined_rows))
 
302
          == HA_POS_ERROR)
325
303
      {
326
304
        goto err;
327
305
      }
341
319
      */
342
320
 
343
321
      internal::IO_CACHE tempfile;
344
 
      if (tempfile.open_cached_file(drizzle_tmpdir.c_str(),TEMP_PREFIX, DISK_BUFFER_SIZE, MYF(MY_WME)))
345
 
      {
 
322
      if (open_cached_file(&tempfile, drizzle_tmpdir,TEMP_PREFIX,
 
323
                           DISK_BUFFER_SIZE, MYF(MY_WME)))
346
324
        goto err;
347
 
      }
348
325
 
349
326
      /* If quick select is used, initialize it before retrieving rows. */
350
327
      if (select && select->quick && select->quick->reset())
363
340
      */
364
341
 
365
342
      if (used_index == MAX_KEY || (select && select->quick))
366
 
      {
367
 
        info.init_read_record(session, table, select, 0, true);
368
 
      }
 
343
        init_read_record(&info,session,table,select,0,1);
369
344
      else
370
 
      {
371
 
        info.init_read_record_idx(session, table, 1, used_index);
372
 
      }
 
345
        init_read_record_idx(&info, session, table, 1, used_index);
373
346
 
374
347
      session->set_proc_info("Searching rows for update");
375
348
      ha_rows tmp_limit= limit;
376
349
 
377
 
      while (not(error= info.read_record(&info)) && not session->getKilled())
 
350
      while (!(error=info.read_record(&info)) && !session->killed)
378
351
      {
379
352
        if (!(select && select->skip_record()))
380
353
        {
381
354
          if (table->cursor->was_semi_consistent_read())
382
355
            continue;  /* repeat the read of the same row if it still exists */
383
356
 
384
 
          table->cursor->position(table->getInsertRecord());
 
357
          table->cursor->position(table->record[0]);
385
358
          if (my_b_write(&tempfile,table->cursor->ref,
386
359
                         table->cursor->ref_length))
387
360
          {
397
370
        else
398
371
          table->cursor->unlock_row();
399
372
      }
400
 
      if (session->getKilled() && not error)
 
373
      if (session->killed && !error)
401
374
        error= 1;                               // Aborted
402
375
      limit= tmp_limit;
403
376
      table->cursor->try_semi_consistent_read(0);
404
 
      info.end_read_record();
 
377
      end_read_record(&info);
405
378
 
406
379
      /* Change select to use tempfile */
407
380
      if (select)
417
390
        select= new optimizer::SqlSelect;
418
391
        select->head=table;
419
392
      }
420
 
      if (tempfile.reinit_io_cache(internal::READ_CACHE,0L,0,0))
 
393
      if (reinit_io_cache(&tempfile,internal::READ_CACHE,0L,0,0))
421
394
        error=1;
422
395
      // Read row ptrs from this cursor
423
396
      memcpy(select->file, &tempfile, sizeof(tempfile));
434
407
  if (select && select->quick && select->quick->reset())
435
408
    goto err;
436
409
  table->cursor->try_semi_consistent_read(1);
437
 
  info.init_read_record(session, table, select, 0, true);
 
410
  init_read_record(&info,session,table,select,0,1);
438
411
 
439
412
  updated= found= 0;
440
413
  /*
464
437
    the table handler is returning all columns OR if
465
438
    if all updated columns are read
466
439
  */
467
 
  can_compare_record= (! (table->cursor->getEngine()->check_flag(HTON_BIT_PARTIAL_COLUMN_READ)) ||
468
 
                       table->write_set->is_subset_of(*table->read_set));
 
440
  can_compare_record= (!(table->cursor->getEngine()->check_flag(HTON_BIT_PARTIAL_COLUMN_READ)) ||
 
441
                       bitmap_is_subset(table->write_set, table->read_set));
469
442
 
470
 
  while (not (error=info.read_record(&info)) && not session->getKilled())
 
443
  while (!(error=info.read_record(&info)) && !session->killed)
471
444
  {
472
 
    if (not (select && select->skip_record()))
 
445
    if (!(select && select->skip_record()))
473
446
    {
474
447
      if (table->cursor->was_semi_consistent_read())
475
448
        continue;  /* repeat the read of the same row if it still exists */
476
449
 
477
450
      table->storeRecord();
478
451
      if (fill_record(session, fields, values))
479
 
      {
480
 
        /*
481
 
         * If we updated some rows before this one failed (updated > 0),
482
 
         * then we will need to undo adding those records to the
483
 
         * replication Statement message.
484
 
         */
485
 
        if (updated > 0)
486
 
        {
487
 
          TransactionServices &ts= TransactionServices::singleton();
488
 
          ts.removeStatementRecords(session, updated);
489
 
        }
490
 
 
491
452
        break;
492
 
      }
493
453
 
494
454
      found++;
495
455
 
496
456
      if (!can_compare_record || table->compare_record())
497
457
      {
498
458
        /* Non-batched update */
499
 
        error= table->cursor->updateRecord(table->getUpdateRecord(),
500
 
                                            table->getInsertRecord());
501
 
 
502
 
        table->auto_increment_field_not_null= false;
503
 
 
 
459
        error= table->cursor->ha_update_row(table->record[1],
 
460
                                            table->record[0]);
504
461
        if (!error || error == HA_ERR_RECORD_IS_THE_SAME)
505
 
        {
 
462
        {
506
463
          if (error != HA_ERR_RECORD_IS_THE_SAME)
507
464
            updated++;
508
465
          else
509
466
            error= 0;
510
 
        }
511
 
        else if (! ignore ||
 
467
        }
 
468
        else if (! ignore ||
512
469
                 table->cursor->is_fatal_error(error, HA_CHECK_DUP_KEY))
513
 
        {
 
470
        {
514
471
          /*
515
472
            If (ignore && error is ignorable) we don't have to
516
473
            do anything; otherwise...
521
478
            flags|= ME_FATALERROR; /* Other handler errors are fatal */
522
479
 
523
480
          prepare_record_for_error_message(error, table);
524
 
          table->print_error(error,MYF(flags));
525
 
          error= 1;
526
 
          break;
527
 
        }
 
481
          table->print_error(error,MYF(flags));
 
482
          error= 1;
 
483
          break;
 
484
        }
528
485
      }
529
486
 
530
487
      if (!--limit && using_limit)
546
503
    It's assumed that if an error was set in combination with an effective
547
504
    killed status then the error is due to killing.
548
505
  */
549
 
  killed_status= session->getKilled(); // get the status of the volatile
 
506
  killed_status= session->killed; // get the status of the volatile
550
507
  // simulated killing after the loop must be ineffective for binlogging
551
508
  error= (killed_status == Session::NOT_KILLED)?  error : 1;
552
509
 
556
513
  if (!transactional_table && updated > 0)
557
514
    session->transaction.stmt.markModifiedNonTransData();
558
515
 
559
 
  info.end_read_record();
 
516
  end_read_record(&info);
560
517
  delete select;
561
518
  session->set_proc_info("end");
562
519
  table->cursor->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
566
523
    last one without error. error > 0 means an error (e.g. unique key
567
524
    violation and no IGNORE or REPLACE). error == 0 is also an error (if
568
525
    preparing the record or invoking before triggers fails). See
569
 
    autocommitOrRollback(error>=0) and return(error>=0) below.
 
526
    ha_autocommit_or_rollback(error>=0) and return(error>=0) below.
570
527
    Sometimes we want to binlog even if we updated no rows, in case user used
571
528
    it to be sure master and slave are in same state.
572
529
  */
585
542
  if (error < 0)
586
543
  {
587
544
    char buff[STRING_BUFFER_USUAL_SIZE];
588
 
    snprintf(buff, sizeof(buff), ER(ER_UPDATE_INFO), (ulong) found, (ulong) updated,
 
545
    sprintf(buff, ER(ER_UPDATE_INFO), (ulong) found, (ulong) updated,
589
546
            (ulong) session->cuted_fields);
590
547
    session->row_count_func= updated;
591
548
    /**
594
551
     */
595
552
    session->main_da.reset_diagnostics_area();
596
553
    session->my_ok((ulong) session->row_count_func, found, id, buff);
597
 
    session->status_var.updated_row_count+= session->row_count_func;
598
554
  }
599
 
  session->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;              /* calc cuted fields */
 
555
  session->count_cuted_fields= CHECK_FIELD_IGNORE;              /* calc cuted fields */
600
556
  session->abort_on_warning= 0;
601
557
  DRIZZLE_UPDATE_DONE((error >= 0 || session->is_error()), found, updated);
602
558
  return ((error >= 0 || session->is_error()) ? 1 : 0);
611
567
  }
612
568
  session->abort_on_warning= 0;
613
569
 
 
570
abort:
614
571
  DRIZZLE_UPDATE_DONE(1, 0, 0);
615
572
  return 1;
616
573
}
631
588
    true  error
632
589
*/
633
590
bool mysql_prepare_update(Session *session, TableList *table_list,
634
 
                         Item **conds, uint32_t order_num, Order *order)
 
591
                         Item **conds, uint32_t order_num, order_st *order)
635
592
{
636
593
  List<Item> all_fields;
637
594
  Select_Lex *select_lex= &session->lex->select_lex;
654
611
    TableList *duplicate;
655
612
    if ((duplicate= unique_table(table_list, table_list->next_global)))
656
613
    {
657
 
      my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->getTableName());
 
614
      my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->table_name);
658
615
      return true;
659
616
    }
660
617
  }