~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_update.cc

  • Committer: Brian Aker
  • Date: 2010-06-21 22:16:28 UTC
  • mto: This revision was merged to the branch mainline in revision 1635.
  • Revision ID: brian@gaz-20100621221628-tnd8du7u2ubhheof
More current_session issues.

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->getMutableShare()->sizeFields());
 
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
98
  for (field_p= table->getFields(); (field= *field_p); field_p++)
100
99
  {
101
 
    if (unique_map.test(field->position()))
 
100
    if (unique_map.isBitSet(field->field_index))
102
101
    {
103
102
      field->copy_from_tmp(table->getShare()->rec_buff_length);
104
103
    }
105
104
  }
106
105
 
 
106
 
107
107
  return;
108
108
}
109
109
 
129
129
 
130
130
int mysql_update(Session *session, TableList *table_list,
131
131
                 List<Item> &fields, List<Item> &values, COND *conds,
132
 
                 uint32_t order_num, Order *order,
 
132
                 uint32_t order_num, order_st *order,
133
133
                 ha_rows limit, enum enum_duplicates,
134
134
                 bool ignore)
135
135
{
136
136
  bool          using_limit= limit != HA_POS_ERROR;
137
137
  bool          used_key_is_modified;
138
138
  bool          transactional_table;
 
139
  bool          can_compare_record;
139
140
  int           error;
140
141
  uint          used_index= MAX_KEY, dup_key_found;
141
142
  bool          need_sort= true;
147
148
  Select_Lex    *select_lex= &session->lex->select_lex;
148
149
  uint64_t     id;
149
150
  List<Item> all_fields;
150
 
  Session::killed_state_t killed_status= Session::NOT_KILLED;
 
151
  Session::killed_state killed_status= Session::NOT_KILLED;
151
152
 
152
 
  DRIZZLE_UPDATE_START(session->getQueryString()->c_str());
 
153
  DRIZZLE_UPDATE_START(session->query.c_str());
153
154
  if (session->openTablesLock(table_list))
154
155
  {
155
156
    DRIZZLE_UPDATE_DONE(1, 0, 0);
164
165
  table->quick_keys.reset();
165
166
 
166
167
  if (mysql_prepare_update(session, table_list, &conds, order_num, order))
167
 
  {
168
 
    DRIZZLE_UPDATE_DONE(1, 0, 0);
169
 
    return 1;
170
 
  }
 
168
    goto abort;
171
169
 
172
170
  old_covering_keys= table->covering_keys;              // Keys used in WHERE
173
171
  /* Check the fields we are going to modify */
174
172
  if (setup_fields_with_no_wrap(session, 0, fields, MARK_COLUMNS_WRITE, 0, 0))
175
 
  {
176
 
    DRIZZLE_UPDATE_DONE(1, 0, 0);
177
 
    return 1;
178
 
  }
179
 
 
 
173
    goto abort;
180
174
  if (table->timestamp_field)
181
175
  {
182
176
    // Don't set timestamp column if this is modified
189
183
      if (table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_UPDATE ||
190
184
          table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_BOTH)
191
185
      {
192
 
        table->setWriteSet(table->timestamp_field->position());
 
186
        table->setWriteSet(table->timestamp_field->field_index);
193
187
      }
194
188
    }
195
189
  }
197
191
  if (setup_fields(session, 0, values, MARK_COLUMNS_READ, 0, 0))
198
192
  {
199
193
    free_underlaid_joins(session, select_lex);
200
 
    DRIZZLE_UPDATE_DONE(1, 0, 0);
201
 
 
202
 
    return 1;
 
194
    goto abort;
203
195
  }
204
196
 
205
197
  if (select_lex->inner_refs_list.elements &&
227
219
      (table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_UPDATE ||
228
220
       table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_BOTH))
229
221
  {
230
 
    *table->read_set|= *table->write_set;
 
222
    bitmap_union(table->read_set, table->write_set);
231
223
  }
232
224
  // Don't count on usage of 'only index' when calculating which key to use
233
225
  table->covering_keys.reset();
247
239
    session->main_da.reset_diagnostics_area();
248
240
    free_underlaid_joins(session, select_lex);
249
241
    if (error)
250
 
    {
251
 
      DRIZZLE_UPDATE_DONE(1, 0, 0);
252
 
      return 1;
253
 
    }
 
242
      goto abort;                               // Error in where
254
243
    DRIZZLE_UPDATE_DONE(0, 0, 0);
255
244
    session->my_ok();                           // No matching records
256
245
    return 0;
274
263
  {
275
264
    used_index= select->quick->index;
276
265
    used_key_is_modified= (!select->quick->unique_key_range() &&
277
 
                          select->quick->is_keys_used(*table->write_set));
 
266
                          select->quick->is_keys_used(table->write_set));
278
267
  }
279
268
  else
280
269
  {
282
271
    if (used_index == MAX_KEY)                  // no index for sort order
283
272
      used_index= table->cursor->key_used_on_scan;
284
273
    if (used_index != MAX_KEY)
285
 
      used_key_is_modified= is_key_used(table, used_index, *table->write_set);
 
274
      used_key_is_modified= is_key_used(table, used_index, table->write_set);
286
275
  }
287
276
 
288
277
 
311
300
        NOTE: filesort will call table->prepare_for_position()
312
301
      */
313
302
      uint32_t         length= 0;
314
 
      SortField  *sortorder;
 
303
      SORT_FIELD  *sortorder;
315
304
      ha_rows examined_rows;
316
 
      FileSort filesort(*session);
317
305
 
318
 
      table->sort.io_cache= new internal::IO_CACHE;
 
306
      table->sort.io_cache = new internal::IO_CACHE;
319
307
 
320
308
      if (!(sortorder=make_unireg_sortorder(order, &length, NULL)) ||
321
 
          (table->sort.found_records= filesort.run(table, sortorder, length,
322
 
                                                   select, limit, 1,
323
 
                                                   examined_rows)) == HA_POS_ERROR)
 
309
          (table->sort.found_records= filesort(session, table, sortorder, length,
 
310
                                               select, limit, 1,
 
311
                                               &examined_rows))
 
312
          == HA_POS_ERROR)
324
313
      {
325
314
        goto err;
326
315
      }
340
329
      */
341
330
 
342
331
      internal::IO_CACHE tempfile;
343
 
      if (tempfile.open_cached_file(drizzle_tmpdir.c_str(),TEMP_PREFIX, DISK_BUFFER_SIZE, MYF(MY_WME)))
344
 
      {
 
332
      if (open_cached_file(&tempfile, drizzle_tmpdir.c_str(),TEMP_PREFIX,
 
333
                           DISK_BUFFER_SIZE, MYF(MY_WME)))
345
334
        goto err;
346
 
      }
347
335
 
348
336
      /* If quick select is used, initialize it before retrieving rows. */
349
337
      if (select && select->quick && select->quick->reset())
373
361
      session->set_proc_info("Searching rows for update");
374
362
      ha_rows tmp_limit= limit;
375
363
 
376
 
      while (not(error= info.read_record(&info)) && not session->getKilled())
 
364
      while (!(error=info.read_record(&info)) && !session->killed)
377
365
      {
378
366
        if (!(select && select->skip_record()))
379
367
        {
380
368
          if (table->cursor->was_semi_consistent_read())
381
369
            continue;  /* repeat the read of the same row if it still exists */
382
370
 
383
 
          table->cursor->position(table->getInsertRecord());
 
371
          table->cursor->position(table->record[0]);
384
372
          if (my_b_write(&tempfile,table->cursor->ref,
385
373
                         table->cursor->ref_length))
386
374
          {
396
384
        else
397
385
          table->cursor->unlock_row();
398
386
      }
399
 
      if (session->getKilled() && not error)
 
387
      if (session->killed && !error)
400
388
        error= 1;                               // Aborted
401
389
      limit= tmp_limit;
402
390
      table->cursor->try_semi_consistent_read(0);
416
404
        select= new optimizer::SqlSelect;
417
405
        select->head=table;
418
406
      }
419
 
      if (tempfile.reinit_io_cache(internal::READ_CACHE,0L,0,0))
 
407
      if (reinit_io_cache(&tempfile,internal::READ_CACHE,0L,0,0))
420
408
        error=1;
421
409
      // Read row ptrs from this cursor
422
410
      memcpy(select->file, &tempfile, sizeof(tempfile));
458
446
  if (table->cursor->getEngine()->check_flag(HTON_BIT_PARTIAL_COLUMN_READ))
459
447
    table->prepare_for_position();
460
448
 
461
 
  while (not (error=info.read_record(&info)) && not session->getKilled())
 
449
  /*
 
450
    We can use compare_record() to optimize away updates if
 
451
    the table handler is returning all columns OR if
 
452
    if all updated columns are read
 
453
  */
 
454
  can_compare_record= (!(table->cursor->getEngine()->check_flag(HTON_BIT_PARTIAL_COLUMN_READ)) ||
 
455
                       bitmap_is_subset(table->write_set, table->read_set));
 
456
 
 
457
  while (!(error=info.read_record(&info)) && !session->killed)
462
458
  {
463
 
    if (not (select && select->skip_record()))
 
459
    if (!(select && select->skip_record()))
464
460
    {
465
461
      if (table->cursor->was_semi_consistent_read())
466
462
        continue;  /* repeat the read of the same row if it still exists */
471
467
 
472
468
      found++;
473
469
 
474
 
      if (! table->records_are_comparable() || table->compare_records())
 
470
      if (!can_compare_record || table->compare_record())
475
471
      {
476
472
        /* Non-batched update */
477
 
        error= table->cursor->updateRecord(table->getUpdateRecord(),
478
 
                                            table->getInsertRecord());
 
473
        error= table->cursor->updateRecord(table->record[1],
 
474
                                            table->record[0]);
479
475
 
480
476
        table->auto_increment_field_not_null= false;
481
477
 
482
478
        if (!error || error == HA_ERR_RECORD_IS_THE_SAME)
483
 
        {
 
479
        {
484
480
          if (error != HA_ERR_RECORD_IS_THE_SAME)
485
481
            updated++;
486
482
          else
487
483
            error= 0;
488
 
        }
489
 
        else if (! ignore ||
 
484
        }
 
485
        else if (! ignore ||
490
486
                 table->cursor->is_fatal_error(error, HA_CHECK_DUP_KEY))
491
 
        {
 
487
        {
492
488
          /*
493
489
            If (ignore && error is ignorable) we don't have to
494
490
            do anything; otherwise...
499
495
            flags|= ME_FATALERROR; /* Other handler errors are fatal */
500
496
 
501
497
          prepare_record_for_error_message(error, table);
502
 
          table->print_error(error,MYF(flags));
503
 
          error= 1;
504
 
          break;
505
 
        }
 
498
          table->print_error(error,MYF(flags));
 
499
          error= 1;
 
500
          break;
 
501
        }
506
502
      }
507
503
 
508
504
      if (!--limit && using_limit)
524
520
    It's assumed that if an error was set in combination with an effective
525
521
    killed status then the error is due to killing.
526
522
  */
527
 
  killed_status= session->getKilled(); // get the status of the volatile
 
523
  killed_status= session->killed; // get the status of the volatile
528
524
  // simulated killing after the loop must be ineffective for binlogging
529
525
  error= (killed_status == Session::NOT_KILLED)?  error : 1;
530
526
 
572
568
     */
573
569
    session->main_da.reset_diagnostics_area();
574
570
    session->my_ok((ulong) session->row_count_func, found, id, buff);
575
 
    session->status_var.updated_row_count+= session->row_count_func;
576
571
  }
577
 
  session->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;              /* calc cuted fields */
 
572
  session->count_cuted_fields= CHECK_FIELD_IGNORE;              /* calc cuted fields */
578
573
  session->abort_on_warning= 0;
579
574
  DRIZZLE_UPDATE_DONE((error >= 0 || session->is_error()), found, updated);
580
575
  return ((error >= 0 || session->is_error()) ? 1 : 0);
589
584
  }
590
585
  session->abort_on_warning= 0;
591
586
 
 
587
abort:
592
588
  DRIZZLE_UPDATE_DONE(1, 0, 0);
593
589
  return 1;
594
590
}
609
605
    true  error
610
606
*/
611
607
bool mysql_prepare_update(Session *session, TableList *table_list,
612
 
                         Item **conds, uint32_t order_num, Order *order)
 
608
                         Item **conds, uint32_t order_num, order_st *order)
613
609
{
614
610
  List<Item> all_fields;
615
611
  Select_Lex *select_lex= &session->lex->select_lex;
632
628
    TableList *duplicate;
633
629
    if ((duplicate= unique_table(table_list, table_list->next_global)))
634
630
    {
635
 
      my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->getTableName());
 
631
      my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->table_name);
636
632
      return true;
637
633
    }
638
634
  }