~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_update.cc

  • Committer: Brian Aker
  • Date: 2010-10-28 01:45:34 UTC
  • mfrom: (1878.5.8 catalogs)
  • Revision ID: brian@tangent.org-20101028014534-b6qp4wp6crj60h7k
Merge in catalog tree.

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 
17
17
/*
18
18
  Single table and multi table updates of tables.
 
19
  Multi-table updates were introduced by Sinisa & Monty
19
20
*/
20
 
 
21
 
#include <config.h>
22
 
 
23
 
#include <drizzled/sql_select.h>
24
 
#include <drizzled/error.h>
25
 
#include <drizzled/probes.h>
26
 
#include <drizzled/sql_base.h>
27
 
#include <drizzled/field/epoch.h>
28
 
#include <drizzled/sql_parse.h>
29
 
#include <drizzled/optimizer/range.h>
30
 
#include <drizzled/records.h>
31
 
#include <drizzled/internal/my_sys.h>
32
 
#include <drizzled/internal/iocache.h>
33
 
#include <drizzled/transaction_services.h>
34
 
#include <drizzled/filesort.h>
35
 
#include <drizzled/plugin/storage_engine.h>
 
21
#include "config.h"
 
22
#include "drizzled/sql_select.h"
 
23
#include "drizzled/error.h"
 
24
#include "drizzled/probes.h"
 
25
#include "drizzled/sql_base.h"
 
26
#include "drizzled/field/timestamp.h"
 
27
#include "drizzled/sql_parse.h"
 
28
#include "drizzled/optimizer/range.h"
 
29
#include "drizzled/records.h"
 
30
#include "drizzled/internal/my_sys.h"
 
31
#include "drizzled/internal/iocache.h"
 
32
#include "drizzled/transaction_services.h"
36
33
 
37
34
#include <boost/dynamic_bitset.hpp>
38
35
#include <list>
100
97
  /* Copy the newly read columns into the new record. */
101
98
  for (field_p= table->getFields(); (field= *field_p); field_p++)
102
99
  {
103
 
    if (unique_map.test(field->position()))
 
100
    if (unique_map.test(field->field_index))
104
101
    {
105
102
      field->copy_from_tmp(table->getShare()->rec_buff_length);
106
103
    }
114
111
  Process usual UPDATE
115
112
 
116
113
  SYNOPSIS
117
 
    update_query()
 
114
    mysql_update()
118
115
    session                     thread handler
119
116
    fields              fields for update
120
117
    values              values of fields for update
129
126
    1  - error
130
127
*/
131
128
 
132
 
int update_query(Session *session, TableList *table_list,
 
129
int mysql_update(Session *session, TableList *table_list,
133
130
                 List<Item> &fields, List<Item> &values, COND *conds,
134
 
                 uint32_t order_num, Order *order,
 
131
                 uint32_t order_num, order_st *order,
135
132
                 ha_rows limit, enum enum_duplicates,
136
133
                 bool ignore)
137
134
{
138
135
  bool          using_limit= limit != HA_POS_ERROR;
139
136
  bool          used_key_is_modified;
140
137
  bool          transactional_table;
141
 
  int           error= 0;
 
138
  bool          can_compare_record;
 
139
  int           error;
142
140
  uint          used_index= MAX_KEY, dup_key_found;
143
141
  bool          need_sort= true;
144
142
  ha_rows       updated, found;
146
144
  Table         *table;
147
145
  optimizer::SqlSelect *select= NULL;
148
146
  ReadRecord    info;
149
 
  Select_Lex    *select_lex= &session->getLex()->select_lex;
 
147
  Select_Lex    *select_lex= &session->lex->select_lex;
150
148
  uint64_t     id;
151
149
  List<Item> all_fields;
152
 
  Session::killed_state_t killed_status= Session::NOT_KILLED;
 
150
  Session::killed_state killed_status= Session::NOT_KILLED;
153
151
 
154
 
  DRIZZLE_UPDATE_START(session->getQueryString()->c_str());
 
152
  DRIZZLE_UPDATE_START(session->query.c_str());
155
153
  if (session->openTablesLock(table_list))
156
154
  {
157
155
    DRIZZLE_UPDATE_DONE(1, 0, 0);
165
163
  table->covering_keys= table->getShare()->keys_in_use;
166
164
  table->quick_keys.reset();
167
165
 
168
 
  if (prepare_update(session, table_list, &conds, order_num, order))
 
166
  if (mysql_prepare_update(session, table_list, &conds, order_num, order))
169
167
  {
170
168
    DRIZZLE_UPDATE_DONE(1, 0, 0);
171
169
    return 1;
191
189
      if (table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_UPDATE ||
192
190
          table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_BOTH)
193
191
      {
194
 
        table->setWriteSet(table->timestamp_field->position());
 
192
        table->setWriteSet(table->timestamp_field->field_index);
195
193
      }
196
194
    }
197
195
  }
208
206
    fix_inner_refs(session, all_fields, select_lex, select_lex->ref_pointer_array))
209
207
  {
210
208
    DRIZZLE_UPDATE_DONE(1, 0, 0);
211
 
    return 1;
 
209
    return -1;
212
210
  }
213
211
 
214
212
  if (conds)
248
246
     */
249
247
    session->main_da.reset_diagnostics_area();
250
248
    free_underlaid_joins(session, select_lex);
251
 
    if (error || session->is_error())
 
249
    if (error)
252
250
    {
253
251
      DRIZZLE_UPDATE_DONE(1, 0, 0);
254
252
      return 1;
315
313
      uint32_t         length= 0;
316
314
      SortField  *sortorder;
317
315
      ha_rows examined_rows;
318
 
      FileSort filesort(*session);
319
316
 
320
 
      table->sort.io_cache= new internal::IO_CACHE;
 
317
      table->sort.io_cache = new internal::IO_CACHE;
321
318
 
322
319
      if (!(sortorder=make_unireg_sortorder(order, &length, NULL)) ||
323
 
          (table->sort.found_records= filesort.run(table, sortorder, length,
324
 
                                                   select, limit, 1,
325
 
                                                   examined_rows)) == HA_POS_ERROR)
 
320
          (table->sort.found_records= filesort(session, table, sortorder, length,
 
321
                                               select, limit, 1,
 
322
                                               &examined_rows))
 
323
          == HA_POS_ERROR)
326
324
      {
327
325
        goto err;
328
326
      }
330
328
        Filesort has already found and selected the rows we want to update,
331
329
        so we don't need the where clause
332
330
      */
333
 
      safe_delete(select);
 
331
      delete select;
 
332
      select= 0;
334
333
    }
335
334
    else
336
335
    {
341
340
      */
342
341
 
343
342
      internal::IO_CACHE tempfile;
344
 
      if (tempfile.open_cached_file(drizzle_tmpdir.c_str(),TEMP_PREFIX, DISK_BUFFER_SIZE, MYF(MY_WME)))
345
 
      {
 
343
      if (open_cached_file(&tempfile, drizzle_tmpdir.c_str(),TEMP_PREFIX,
 
344
                           DISK_BUFFER_SIZE, MYF(MY_WME)))
346
345
        goto err;
347
 
      }
348
346
 
349
347
      /* If quick select is used, initialize it before retrieving rows. */
350
348
      if (select && select->quick && select->quick->reset())
364
362
 
365
363
      if (used_index == MAX_KEY || (select && select->quick))
366
364
      {
367
 
        if ((error= info.init_read_record(session, table, select, 0, true)))
368
 
          goto err;
 
365
        info.init_read_record(session, table, select, 0, true);
369
366
      }
370
367
      else
371
368
      {
372
 
        if ((error= info.init_read_record_idx(session, table, 1, used_index)))
373
 
          goto err;
 
369
        info.init_read_record_idx(session, table, 1, used_index);
374
370
      }
375
371
 
376
372
      session->set_proc_info("Searching rows for update");
377
373
      ha_rows tmp_limit= limit;
378
374
 
379
 
      while (not(error= info.read_record(&info)) && not session->getKilled())
 
375
      while (!(error=info.read_record(&info)) && !session->killed)
380
376
      {
381
377
        if (!(select && select->skip_record()))
382
378
        {
399
395
        else
400
396
          table->cursor->unlock_row();
401
397
      }
402
 
      if (session->getKilled() && not error)
 
398
      if (session->killed && !error)
403
399
        error= 1;                               // Aborted
404
400
      limit= tmp_limit;
405
401
      table->cursor->try_semi_consistent_read(0);
408
404
      /* Change select to use tempfile */
409
405
      if (select)
410
406
      {
411
 
        safe_delete(select->quick);
 
407
        delete select->quick;
412
408
        if (select->free_cond)
413
409
          delete select->cond;
 
410
        select->quick=0;
414
411
        select->cond=0;
415
412
      }
416
413
      else
417
414
      {
418
 
        select= new optimizer::SqlSelect();
 
415
        select= new optimizer::SqlSelect;
419
416
        select->head=table;
420
417
      }
421
 
      if (tempfile.reinit_io_cache(internal::READ_CACHE,0L,0,0))
 
418
      if (reinit_io_cache(&tempfile,internal::READ_CACHE,0L,0,0))
422
419
        error=1;
423
420
      // Read row ptrs from this cursor
424
421
      memcpy(select->file, &tempfile, sizeof(tempfile));
435
432
  if (select && select->quick && select->quick->reset())
436
433
    goto err;
437
434
  table->cursor->try_semi_consistent_read(1);
438
 
  if ((error= info.init_read_record(session, table, select, 0, true)))
439
 
  {
440
 
    goto err;
441
 
  }
 
435
  info.init_read_record(session, table, select, 0, true);
442
436
 
443
437
  updated= found= 0;
444
438
  /*
454
448
  session->set_proc_info("Updating");
455
449
 
456
450
  transactional_table= table->cursor->has_transactions();
457
 
  session->setAbortOnWarning(test(!ignore));
 
451
  session->abort_on_warning= test(!ignore);
458
452
 
459
453
  /*
460
454
    Assure that we can use position()
463
457
  if (table->cursor->getEngine()->check_flag(HTON_BIT_PARTIAL_COLUMN_READ))
464
458
    table->prepare_for_position();
465
459
 
466
 
  while (not (error=info.read_record(&info)) && not session->getKilled())
 
460
  /*
 
461
    We can use compare_record() to optimize away updates if
 
462
    the table handler is returning all columns OR if
 
463
    if all updated columns are read
 
464
  */
 
465
  can_compare_record= (! (table->cursor->getEngine()->check_flag(HTON_BIT_PARTIAL_COLUMN_READ)) ||
 
466
                       table->write_set->is_subset_of(*table->read_set));
 
467
 
 
468
  while (! (error=info.read_record(&info)) && !session->killed)
467
469
  {
468
 
    if (not (select && select->skip_record()))
 
470
    if (! (select && select->skip_record()))
469
471
    {
470
472
      if (table->cursor->was_semi_consistent_read())
471
473
        continue;  /* repeat the read of the same row if it still exists */
472
474
 
473
475
      table->storeRecord();
474
476
      if (fill_record(session, fields, values))
 
477
      {
 
478
        /*
 
479
         * If we updated some rows before this one failed (updated > 0),
 
480
         * then we will need to undo adding those records to the
 
481
         * replication Statement message.
 
482
         */
 
483
        if (updated > 0)
 
484
        {
 
485
          TransactionServices &ts= TransactionServices::singleton();
 
486
          ts.removeStatementRecords(session, updated);
 
487
        }
 
488
 
475
489
        break;
 
490
      }
476
491
 
477
492
      found++;
478
493
 
479
 
      if (! table->records_are_comparable() || table->compare_records())
 
494
      if (!can_compare_record || table->compare_record())
480
495
      {
481
496
        /* Non-batched update */
482
497
        error= table->cursor->updateRecord(table->getUpdateRecord(),
529
544
    It's assumed that if an error was set in combination with an effective
530
545
    killed status then the error is due to killing.
531
546
  */
532
 
  killed_status= session->getKilled(); // get the status of the volatile
 
547
  killed_status= session->killed; // get the status of the volatile
533
548
  // simulated killing after the loop must be ineffective for binlogging
534
549
  error= (killed_status == Session::NOT_KILLED)?  error : 1;
535
550
 
576
591
     * lp bug# 439719
577
592
     */
578
593
    session->main_da.reset_diagnostics_area();
579
 
    session->my_ok((ulong) session->rowCount(), found, id, buff);
580
 
    session->status_var.updated_row_count+= session->rowCount();
 
594
    session->my_ok((ulong) session->row_count_func, found, id, buff);
 
595
    session->status_var.updated_row_count+= session->row_count_func;
581
596
  }
582
597
  session->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;              /* calc cuted fields */
583
 
  session->setAbortOnWarning(false);
 
598
  session->abort_on_warning= 0;
584
599
  DRIZZLE_UPDATE_DONE((error >= 0 || session->is_error()), found, updated);
585
600
  return ((error >= 0 || session->is_error()) ? 1 : 0);
586
601
 
587
602
err:
588
 
  if (error != 0)
589
 
    table->print_error(error,MYF(0));
590
 
 
591
603
  delete select;
592
604
  free_underlaid_joins(session, select_lex);
593
605
  if (table->key_read)
595
607
    table->key_read=0;
596
608
    table->cursor->extra(HA_EXTRA_NO_KEYREAD);
597
609
  }
598
 
  session->setAbortOnWarning(false);
 
610
  session->abort_on_warning= 0;
599
611
 
600
612
  DRIZZLE_UPDATE_DONE(1, 0, 0);
601
613
  return 1;
605
617
  Prepare items in UPDATE statement
606
618
 
607
619
  SYNOPSIS
608
 
    prepare_update()
 
620
    mysql_prepare_update()
609
621
    session                     - thread handler
610
622
    table_list          - global/local table list
611
623
    conds               - conditions
616
628
    false OK
617
629
    true  error
618
630
*/
619
 
bool prepare_update(Session *session, TableList *table_list,
620
 
                         Item **conds, uint32_t order_num, Order *order)
 
631
bool mysql_prepare_update(Session *session, TableList *table_list,
 
632
                         Item **conds, uint32_t order_num, order_st *order)
621
633
{
622
634
  List<Item> all_fields;
623
 
  Select_Lex *select_lex= &session->getLex()->select_lex;
 
635
  Select_Lex *select_lex= &session->lex->select_lex;
624
636
 
625
 
  session->getLex()->allow_sum_func= 0;
 
637
  session->lex->allow_sum_func= 0;
626
638
 
627
639
  if (setup_tables_and_check_access(session, &select_lex->context,
628
640
                                    &select_lex->top_join_list,