~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_update.cc

  • Committer: Prafulla Tekawade
  • Date: 2010-08-06 11:21:12 UTC
  • mto: (1711.1.21 build) (1725.1.1 build)
  • mto: This revision was merged to the branch mainline in revision 1714.
  • Revision ID: prafulla_t@users.sourceforge.net-20100806112112-7w5u0s3nx9u67nzt
Fix for Bug 586051

1. test_if_ref method which checks whether predicate is already evaluated
   due to ref/eq_ref access or not was incorrectly removing a predicate 
   that was not implicitly evaluated due to ref access (due to presence of filesort ?)
   It was field=NULL predicate.
   Such predicate should be kept and execution engine will filter out rows
   correctly. Removal of such predicate led to returning of rows which had
   NULL for join/predicate columns.
2. field COMP_OP NULL will always false for all fields except when COMP_OP
   is NULL-safe equality operator. Modified range optimizer to return zero
   row count in such cases.
   Query now does not even run. It returns zero result. As such Fix(1) is not
   required but we might hit that case in some other query (I have not tried it
   yet)
3. Fixed Field::val_str to print "NULL" for literal NULL instead of "0". It
   added lot of confusion while debugging.

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;
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
92
  table->cursor->position(table->getInsertRecord());
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
96
  (void) table->cursor->rnd_pos(table->getUpdateRecord(), 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
        {
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
473
        error= table->cursor->updateRecord(table->getUpdateRecord(),
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
 
589
585
  }
590
586
  session->abort_on_warning= 0;
591
587
 
 
588
abort:
592
589
  DRIZZLE_UPDATE_DONE(1, 0, 0);
593
590
  return 1;
594
591
}
609
606
    true  error
610
607
*/
611
608
bool mysql_prepare_update(Session *session, TableList *table_list,
612
 
                         Item **conds, uint32_t order_num, Order *order)
 
609
                         Item **conds, uint32_t order_num, order_st *order)
613
610
{
614
611
  List<Item> all_fields;
615
612
  Select_Lex *select_lex= &session->lex->select_lex;
632
629
    TableList *duplicate;
633
630
    if ((duplicate= unique_table(table_list, table_list->next_global)))
634
631
    {
635
 
      my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->getTableName());
 
632
      my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->table_name);
636
633
      return true;
637
634
    }
638
635
  }