~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_update.cc

  • Committer: Toru Maesaka
  • Date: 2008-12-17 07:16:37 UTC
  • mto: (685.1.40 devel) (713.1.5 devel)
  • mto: This revision was merged to the branch mainline in revision 713.
  • Revision ID: dev@torum.net-20081217071637-7j9040w7lpms77r2
Removed my_time() and added error checking

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
*/
21
21
#include <drizzled/server_includes.h>
22
22
#include <drizzled/sql_select.h>
23
 
#include <drizzled/drizzled_error_messages.h>
 
23
#include <drizzled/error.h>
 
24
#include <drizzled/probes.h>
 
25
#include <drizzled/sql_base.h>
 
26
#include <drizzled/field/timestamp.h>
24
27
 
25
28
/*
26
29
  check that all fields are real fields
27
30
 
28
31
  SYNOPSIS
29
32
    check_fields()
30
 
    thd             thread handler
 
33
    session             thread handler
31
34
    items           Items for check
32
35
 
33
36
  RETURN
35
38
    false Items are OK
36
39
*/
37
40
 
38
 
static bool check_fields(THD *thd, List<Item> &items)
 
41
static bool check_fields(Session *session, List<Item> &items)
39
42
{
40
43
  List_iterator<Item> it(items);
41
44
  Item *item;
53
56
      we make temporary copy of Item_field, to avoid influence of changing
54
57
      result_field on Item_ref which refer on this field
55
58
    */
56
 
    thd->change_item_tree(it.ref(), new Item_field(thd, field));
 
59
    session->change_item_tree(it.ref(), new Item_field(session, field));
57
60
  }
58
61
  return false;
59
62
}
78
81
  uint32_t keynr;
79
82
  MY_BITMAP unique_map; /* Fields in offended unique. */
80
83
  my_bitmap_map unique_map_buf[bitmap_buffer_size(MAX_FIELDS)];
81
 
  
 
84
 
82
85
  /*
83
86
    Only duplicate key errors print the key value.
84
87
    If storage engine does always read all columns, we have the value alraedy.
132
135
 
133
136
  SYNOPSIS
134
137
    mysql_update()
135
 
    thd                 thread handler
 
138
    session                     thread handler
136
139
    fields              fields for update
137
140
    values              values of fields for update
138
141
    conds               WHERE clause expression
148
151
    1  - error
149
152
*/
150
153
 
151
 
int mysql_update(THD *thd,
152
 
                 TableList *table_list,
153
 
                 List<Item> &fields,
154
 
                 List<Item> &values,
155
 
                 COND *conds,
 
154
int mysql_update(Session *session, TableList *table_list,
 
155
                 List<Item> &fields, List<Item> &values, COND *conds,
156
156
                 uint32_t order_num, order_st *order,
157
 
                 ha_rows limit,
158
 
                 enum enum_duplicates handle_duplicates __attribute__((unused)),
 
157
                 ha_rows limit, enum enum_duplicates,
159
158
                 bool ignore)
160
159
{
161
160
  bool          using_limit= limit != HA_POS_ERROR;
162
 
  bool          safe_update= test(thd->options & OPTION_SAFE_UPDATES);
 
161
  bool          safe_update= test(session->options & OPTION_SAFE_UPDATES);
163
162
  bool          used_key_is_modified, transactional_table, will_batch;
164
163
  bool          can_compare_record;
165
164
  int           error, loc_error;
171
170
  Table         *table;
172
171
  SQL_SELECT    *select;
173
172
  READ_RECORD   info;
174
 
  SELECT_LEX    *select_lex= &thd->lex->select_lex;
 
173
  SELECT_LEX    *select_lex= &session->lex->select_lex;
175
174
  bool          need_reopen;
176
175
  uint64_t     id;
177
176
  List<Item> all_fields;
178
 
  THD::killed_state killed_status= THD::NOT_KILLED;
179
 
  
 
177
  Session::killed_state killed_status= Session::NOT_KILLED;
 
178
 
180
179
  for ( ; ; )
181
180
  {
182
 
    if (open_tables(thd, &table_list, &table_count, 0))
 
181
    if (open_tables(session, &table_list, &table_count, 0))
183
182
      return(1);
184
183
 
185
 
    if (!lock_tables(thd, table_list, table_count, &need_reopen))
 
184
    if (!lock_tables(session, table_list, table_count, &need_reopen))
186
185
      break;
187
186
    if (!need_reopen)
188
187
      return(1);
189
 
    close_tables_for_reopen(thd, &table_list);
 
188
    close_tables_for_reopen(session, &table_list);
190
189
  }
191
190
 
192
 
  if (mysql_handle_derived(thd->lex, &mysql_derived_prepare) ||
193
 
      (thd->fill_derived_tables() &&
194
 
       mysql_handle_derived(thd->lex, &mysql_derived_filling)))
 
191
  if (mysql_handle_derived(session->lex, &mysql_derived_prepare) ||
 
192
      (session->fill_derived_tables() &&
 
193
       mysql_handle_derived(session->lex, &mysql_derived_filling)))
195
194
    return(1);
196
195
 
197
196
  DRIZZLE_UPDATE_START();
198
 
  thd_proc_info(thd, "init");
 
197
  session->set_proc_info("init");
199
198
  table= table_list->table;
200
199
 
201
200
  /* Calculate "table->covering_keys" based on the WHERE */
202
201
  table->covering_keys= table->s->keys_in_use;
203
202
  table->quick_keys.clear_all();
204
203
 
205
 
  if (mysql_prepare_update(thd, table_list, &conds, order_num, order))
 
204
  if (mysql_prepare_update(session, table_list, &conds, order_num, order))
206
205
    goto abort;
207
206
 
208
207
  old_covering_keys= table->covering_keys;              // Keys used in WHERE
209
208
  /* Check the fields we are going to modify */
210
 
  if (setup_fields_with_no_wrap(thd, 0, fields, MARK_COLUMNS_WRITE, 0, 0))
 
209
  if (setup_fields_with_no_wrap(session, 0, fields, MARK_COLUMNS_WRITE, 0, 0))
211
210
    goto abort;                               /* purecov: inspected */
212
211
  if (table->timestamp_field)
213
212
  {
224
223
    }
225
224
  }
226
225
 
227
 
  if (setup_fields(thd, 0, values, MARK_COLUMNS_READ, 0, 0))
 
226
  if (setup_fields(session, 0, values, MARK_COLUMNS_READ, 0, 0))
228
227
  {
229
 
    free_underlaid_joins(thd, select_lex);
 
228
    free_underlaid_joins(session, select_lex);
230
229
    goto abort;                               /* purecov: inspected */
231
230
  }
232
231
 
233
232
  if (select_lex->inner_refs_list.elements &&
234
 
    fix_inner_refs(thd, all_fields, select_lex, select_lex->ref_pointer_array))
 
233
    fix_inner_refs(session, all_fields, select_lex, select_lex->ref_pointer_array))
235
234
  {
236
235
    DRIZZLE_UPDATE_END();
237
236
    return(-1);
240
239
  if (conds)
241
240
  {
242
241
    Item::cond_result cond_value;
243
 
    conds= remove_eq_conds(thd, conds, &cond_value);
 
242
    conds= remove_eq_conds(session, conds, &cond_value);
244
243
    if (cond_value == Item::COND_FALSE)
245
244
      limit= 0;                                   // Impossible WHERE
246
245
  }
263
262
 
264
263
  select= make_select(table, 0, 0, conds, 0, &error);
265
264
  if (error || !limit ||
266
 
      (select && select->check_quick(thd, safe_update, limit)))
 
265
      (select && select->check_quick(session, safe_update, limit)))
267
266
  {
268
267
    delete select;
269
 
    free_underlaid_joins(thd, select_lex);
 
268
    free_underlaid_joins(session, select_lex);
270
269
    if (error)
271
270
      goto abort;                               // Error in where
272
271
    DRIZZLE_UPDATE_END();
273
 
    my_ok(thd);                         // No matching records
 
272
    my_ok(session);                             // No matching records
274
273
    return(0);
275
274
  }
276
275
  if (!select && limit != HA_POS_ERROR)
281
280
  /* If running in safe sql mode, don't allow updates without keys */
282
281
  if (table->quick_keys.is_clear_all())
283
282
  {
284
 
    thd->server_status|=SERVER_QUERY_NO_INDEX_USED;
 
283
    session->server_status|=SERVER_QUERY_NO_INDEX_USED;
285
284
    if (safe_update && !using_limit)
286
285
    {
287
286
      my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,
293
292
  table->mark_columns_needed_for_update();
294
293
 
295
294
  /* Check if we are modifying a key that we are used to search with */
296
 
  
 
295
 
297
296
  if (select && select->quick)
298
297
  {
299
298
    used_index= select->quick->index;
338
337
      SORT_FIELD  *sortorder;
339
338
      ha_rows examined_rows;
340
339
 
341
 
      table->sort.io_cache = (IO_CACHE *) my_malloc(sizeof(IO_CACHE),
342
 
                                                    MYF(MY_FAE | MY_ZEROFILL));
 
340
      table->sort.io_cache = new IO_CACHE;
 
341
      memset(table->sort.io_cache, 0, sizeof(IO_CACHE));
 
342
 
343
343
      if (!(sortorder=make_unireg_sortorder(order, &length, NULL)) ||
344
 
          (table->sort.found_records= filesort(thd, table, sortorder, length,
 
344
          (table->sort.found_records= filesort(session, table, sortorder, length,
345
345
                                               select, limit, 1,
346
346
                                               &examined_rows))
347
347
          == HA_POS_ERROR)
364
364
      */
365
365
 
366
366
      IO_CACHE tempfile;
367
 
      if (open_cached_file(&tempfile, mysql_tmpdir,TEMP_PREFIX,
 
367
      if (open_cached_file(&tempfile, drizzle_tmpdir,TEMP_PREFIX,
368
368
                           DISK_BUFFER_SIZE, MYF(MY_WME)))
369
369
        goto err;
370
370
 
385
385
      */
386
386
 
387
387
      if (used_index == MAX_KEY || (select && select->quick))
388
 
        init_read_record(&info,thd,table,select,0,1);
 
388
        init_read_record(&info,session,table,select,0,1);
389
389
      else
390
 
        init_read_record_idx(&info, thd, table, 1, used_index);
 
390
        init_read_record_idx(&info, session, table, 1, used_index);
391
391
 
392
 
      thd_proc_info(thd, "Searching rows for update");
 
392
      session->set_proc_info("Searching rows for update");
393
393
      ha_rows tmp_limit= limit;
394
394
 
395
 
      while (!(error=info.read_record(&info)) && !thd->killed)
 
395
      while (!(error=info.read_record(&info)) && !session->killed)
396
396
      {
397
397
        if (!(select && select->skip_record()))
398
398
        {
415
415
        else
416
416
          table->file->unlock_row();
417
417
      }
418
 
      if (thd->killed && !error)
 
418
      if (session->killed && !error)
419
419
        error= 1;                               // Aborted
420
420
      limit= tmp_limit;
421
421
      table->file->try_semi_consistent_read(0);
422
422
      end_read_record(&info);
423
 
     
 
423
 
424
424
      /* Change select to use tempfile */
425
425
      if (select)
426
426
      {
447
447
 
448
448
  if (ignore)
449
449
    table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
450
 
  
 
450
 
451
451
  if (select && select->quick && select->quick->reset())
452
452
    goto err;
453
453
  table->file->try_semi_consistent_read(1);
454
 
  init_read_record(&info,thd,table,select,0,1);
 
454
  init_read_record(&info,session,table,select,0,1);
455
455
 
456
456
  updated= found= 0;
457
457
  /* Generate an error when trying to set a NOT NULL field to NULL. */
458
 
  thd->count_cuted_fields= ignore ? CHECK_FIELD_WARN
 
458
  session->count_cuted_fields= ignore ? CHECK_FIELD_WARN
459
459
                                  : CHECK_FIELD_ERROR_FOR_NULL;
460
 
  thd->cuted_fields=0L;
461
 
  thd_proc_info(thd, "Updating");
 
460
  session->cuted_fields=0L;
 
461
  session->set_proc_info("Updating");
462
462
 
463
463
  transactional_table= table->file->has_transactions();
464
 
  thd->abort_on_warning= test(!ignore);
 
464
  session->abort_on_warning= test(!ignore);
465
465
  will_batch= !table->file->start_bulk_update();
466
466
 
467
467
  /*
480
480
                         HA_PARTIAL_COLUMN_READ) ||
481
481
                       bitmap_is_subset(table->write_set, table->read_set));
482
482
 
483
 
  while (!(error=info.read_record(&info)) && !thd->killed)
 
483
  while (!(error=info.read_record(&info)) && !session->killed)
484
484
  {
485
485
    if (!(select && select->skip_record()))
486
486
    {
488
488
        continue;  /* repeat the read of the same row if it still exists */
489
489
 
490
490
      store_record(table,record[1]);
491
 
      if (fill_record(thd, fields, values, 0))
 
491
      if (fill_record(session, fields, values, 0))
492
492
        break; /* purecov: inspected */
493
493
 
494
494
      found++;
506
506
 
507
507
            1) is covered by exec_bulk_update calls.
508
508
            2) and 3) is handled by the bulk_update_row method.
509
 
            
 
509
 
510
510
            bulk_update_row can execute the updates including the one
511
511
            defined in the bulk_update_row or not including the row
512
512
            in the call. This is up to the handler implementation and can
606
606
    }
607
607
    else
608
608
      table->file->unlock_row();
609
 
    thd->row_count++;
 
609
    session->row_count++;
610
610
  }
611
611
  dup_key_found= 0;
612
612
  /*
617
617
    It's assumed that if an error was set in combination with an effective
618
618
    killed status then the error is due to killing.
619
619
  */
620
 
  killed_status= thd->killed; // get the status of the volatile
 
620
  killed_status= session->killed; // get the status of the volatile
621
621
  // simulated killing after the loop must be ineffective for binlogging
622
 
  error= (killed_status == THD::NOT_KILLED)?  error : 1;
 
622
  error= (killed_status == Session::NOT_KILLED)?  error : 1;
623
623
 
624
624
  if (error &&
625
625
      will_batch &&
646
646
  table->file->try_semi_consistent_read(0);
647
647
 
648
648
  if (!transactional_table && updated > 0)
649
 
    thd->transaction.stmt.modified_non_trans_table= true;
 
649
    session->transaction.stmt.modified_non_trans_table= true;
650
650
 
651
651
  end_read_record(&info);
652
652
  delete select;
653
 
  thd_proc_info(thd, "end");
 
653
  session->set_proc_info("end");
654
654
  table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
655
655
 
656
656
  /*
662
662
    Sometimes we want to binlog even if we updated no rows, in case user used
663
663
    it to be sure master and slave are in same state.
664
664
  */
665
 
  if ((error < 0) || thd->transaction.stmt.modified_non_trans_table)
 
665
  if ((error < 0) || session->transaction.stmt.modified_non_trans_table)
666
666
  {
667
 
    if (mysql_bin_log.is_open())
668
 
    {
669
 
      if (error < 0)
670
 
        thd->clear_error();
671
 
      if (thd->binlog_query(THD::ROW_QUERY_TYPE,
672
 
                            thd->query, thd->query_length,
673
 
                            transactional_table, false, killed_status) &&
674
 
          transactional_table)
675
 
      {
676
 
        error=1;                                // Rollback update
677
 
      }
678
 
    }
679
 
    if (thd->transaction.stmt.modified_non_trans_table)
680
 
      thd->transaction.all.modified_non_trans_table= true;
 
667
    if (session->transaction.stmt.modified_non_trans_table)
 
668
      session->transaction.all.modified_non_trans_table= true;
681
669
  }
682
 
  assert(transactional_table || !updated || thd->transaction.stmt.modified_non_trans_table);
683
 
  free_underlaid_joins(thd, select_lex);
 
670
  assert(transactional_table || !updated || session->transaction.stmt.modified_non_trans_table);
 
671
  free_underlaid_joins(session, select_lex);
684
672
 
685
673
  /* If LAST_INSERT_ID(X) was used, report X */
686
 
  id= thd->arg_of_last_insert_id_function ?
687
 
    thd->first_successful_insert_id_in_prev_stmt : 0;
 
674
  id= session->arg_of_last_insert_id_function ?
 
675
    session->first_successful_insert_id_in_prev_stmt : 0;
688
676
 
689
677
  DRIZZLE_UPDATE_END();
690
678
  if (error < 0)
691
679
  {
692
680
    char buff[STRING_BUFFER_USUAL_SIZE];
693
681
    sprintf(buff, ER(ER_UPDATE_INFO), (ulong) found, (ulong) updated,
694
 
            (ulong) thd->cuted_fields);
695
 
    thd->row_count_func=
696
 
      (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated;
697
 
    my_ok(thd, (ulong) thd->row_count_func, id, buff);
 
682
            (ulong) session->cuted_fields);
 
683
    session->row_count_func=
 
684
      (session->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated;
 
685
    my_ok(session, (ulong) session->row_count_func, id, buff);
698
686
  }
699
 
  thd->count_cuted_fields= CHECK_FIELD_IGNORE;          /* calc cuted fields */
700
 
  thd->abort_on_warning= 0;
701
 
  return((error >= 0 || thd->is_error()) ? 1 : 0);
 
687
  session->count_cuted_fields= CHECK_FIELD_IGNORE;              /* calc cuted fields */
 
688
  session->abort_on_warning= 0;
 
689
  return((error >= 0 || session->is_error()) ? 1 : 0);
702
690
 
703
691
err:
704
692
  delete select;
705
 
  free_underlaid_joins(thd, select_lex);
 
693
  free_underlaid_joins(session, select_lex);
706
694
  if (table->key_read)
707
695
  {
708
696
    table->key_read=0;
709
697
    table->file->extra(HA_EXTRA_NO_KEYREAD);
710
698
  }
711
 
  thd->abort_on_warning= 0;
 
699
  session->abort_on_warning= 0;
712
700
 
713
701
abort:
714
702
  DRIZZLE_UPDATE_END();
720
708
 
721
709
  SYNOPSIS
722
710
    mysql_prepare_update()
723
 
    thd                 - thread handler
 
711
    session                     - thread handler
724
712
    table_list          - global/local table list
725
713
    conds               - conditions
726
714
    order_num           - number of order_st BY list entries
730
718
    false OK
731
719
    true  error
732
720
*/
733
 
bool mysql_prepare_update(THD *thd, TableList *table_list,
 
721
bool mysql_prepare_update(Session *session, TableList *table_list,
734
722
                         Item **conds, uint32_t order_num, order_st *order)
735
723
{
736
724
  List<Item> all_fields;
737
 
  SELECT_LEX *select_lex= &thd->lex->select_lex;
738
 
  
739
 
  /*
740
 
    Statement-based replication of UPDATE ... LIMIT is not safe as order of
741
 
    rows is not defined, so in mixed mode we go to row-based.
742
 
 
743
 
    Note that we may consider a statement as safe if order_st BY primary_key
744
 
    is present. However it may confuse users to see very similiar statements
745
 
    replicated differently.
746
 
  */
747
 
  if (thd->lex->current_select->select_limit)
748
 
  {
749
 
    thd->lex->set_stmt_unsafe();
750
 
    thd->set_current_stmt_binlog_row_based_if_mixed();
751
 
  }
752
 
 
753
 
  thd->lex->allow_sum_func= 0;
754
 
 
755
 
  if (setup_tables_and_check_access(thd, &select_lex->context, 
 
725
  SELECT_LEX *select_lex= &session->lex->select_lex;
 
726
 
 
727
  session->lex->allow_sum_func= 0;
 
728
 
 
729
  if (setup_tables_and_check_access(session, &select_lex->context,
756
730
                                    &select_lex->top_join_list,
757
731
                                    table_list,
758
732
                                    &select_lex->leaf_tables,
759
733
                                    false) ||
760
 
      setup_conds(thd, table_list, select_lex->leaf_tables, conds) ||
761
 
      select_lex->setup_ref_array(thd, order_num) ||
762
 
      setup_order(thd, select_lex->ref_pointer_array,
 
734
      setup_conds(session, table_list, select_lex->leaf_tables, conds) ||
 
735
      select_lex->setup_ref_array(session, order_num) ||
 
736
      setup_order(session, select_lex->ref_pointer_array,
763
737
                  table_list, all_fields, all_fields, order))
764
738
    return(true);
765
739
 
766
740
  /* Check that we are not using table that we are updating in a sub select */
767
741
  {
768
742
    TableList *duplicate;
769
 
    if ((duplicate= unique_table(thd, table_list, table_list->next_global, 0)))
 
743
    if ((duplicate= unique_table(session, table_list, table_list->next_global, 0)))
770
744
    {
771
745
      update_non_unique_table_error(table_list, "UPDATE", duplicate);
772
746
      my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->table_name);
779
753
 
780
754
 
781
755
/***************************************************************************
782
 
  Update multiple tables from join 
 
756
  Update multiple tables from join
783
757
***************************************************************************/
784
758
 
785
759
/*
792
766
  Item_field *item;
793
767
  table_map map= 0;
794
768
 
795
 
  while ((item= (Item_field *) item_it++)) 
 
769
  while ((item= (Item_field *) item_it++))
796
770
    map|= item->used_tables();
797
771
  return map;
798
772
}
803
777
 
804
778
  SYNOPSIS
805
779
    mysql_multi_update_prepare()
806
 
    thd         thread handler
 
780
    session         thread handler
807
781
 
808
782
  RETURN
809
783
    false OK
810
784
    true  Error
811
785
*/
812
786
 
813
 
int mysql_multi_update_prepare(THD *thd)
 
787
int mysql_multi_update_prepare(Session *session)
814
788
{
815
 
  LEX *lex= thd->lex;
 
789
  LEX *lex= session->lex;
816
790
  TableList *table_list= lex->query_tables;
817
791
  TableList *tl, *leaves;
818
792
  List<Item> *fields= &lex->select_lex.item_list;
824
798
    count in open_tables()
825
799
  */
826
800
  uint32_t  table_count= lex->table_count;
827
 
  const bool using_lock_tables= thd->locked_tables != 0;
828
 
  bool original_multiupdate= (thd->lex->sql_command == SQLCOM_UPDATE_MULTI);
 
801
  const bool using_lock_tables= session->locked_tables != 0;
 
802
  bool original_multiupdate= (session->lex->sql_command == SQLCOM_UPDATE_MULTI);
829
803
  bool need_reopen= false;
830
 
  
 
804
 
831
805
 
832
806
  /* following need for prepared statements, to run next time multi-update */
833
 
  thd->lex->sql_command= SQLCOM_UPDATE_MULTI;
 
807
  session->lex->sql_command= SQLCOM_UPDATE_MULTI;
834
808
 
835
809
reopen_tables:
836
810
 
837
811
  /* open tables and create derived ones, but do not lock and fill them */
838
812
  if (((original_multiupdate || need_reopen) &&
839
 
       open_tables(thd, &table_list, &table_count, 0)) ||
 
813
       open_tables(session, &table_list, &table_count, 0)) ||
840
814
      mysql_handle_derived(lex, &mysql_derived_prepare))
841
815
    return(true);
842
816
  /*
845
819
    call in setup_tables()).
846
820
  */
847
821
 
848
 
  if (setup_tables_and_check_access(thd, &lex->select_lex.context,
 
822
  if (setup_tables_and_check_access(session, &lex->select_lex.context,
849
823
                                    &lex->select_lex.top_join_list,
850
824
                                    table_list,
851
825
                                    &lex->select_lex.leaf_tables, false))
852
826
    return(true);
853
827
 
854
 
  if (setup_fields_with_no_wrap(thd, 0, *fields, MARK_COLUMNS_WRITE, 0, 0))
 
828
  if (setup_fields_with_no_wrap(session, 0, *fields, MARK_COLUMNS_WRITE, 0, 0))
855
829
    return(true);
856
830
 
857
 
  if (update_view && check_fields(thd, *fields))
 
831
  if (update_view && check_fields(session, *fields))
858
832
  {
859
833
    return(true);
860
834
  }
890
864
        correct order of statements. Otherwise, we use a TL_READ lock to
891
865
        improve performance.
892
866
      */
893
 
      tl->lock_type= using_update_log ? TL_READ_NO_INSERT : TL_READ;
 
867
      tl->lock_type= TL_READ;
894
868
      tl->updating= 0;
895
869
      /* Update Table::lock_type accordingly. */
896
870
      if (!tl->placeholder() && !using_lock_tables)
899
873
  }
900
874
 
901
875
  /* now lock and fill tables */
902
 
  if (lock_tables(thd, table_list, table_count, &need_reopen))
 
876
  if (lock_tables(session, table_list, table_count, &need_reopen))
903
877
  {
904
878
    if (!need_reopen)
905
879
      return(true);
919
893
    for (TableList *tbl= table_list; tbl; tbl= tbl->next_global)
920
894
      tbl->cleanup_items();
921
895
 
922
 
    close_tables_for_reopen(thd, &table_list);
 
896
    close_tables_for_reopen(session, &table_list);
923
897
    goto reopen_tables;
924
898
  }
925
899
 
935
909
        tl->lock_type != TL_READ_NO_INSERT)
936
910
    {
937
911
      TableList *duplicate;
938
 
      if ((duplicate= unique_table(thd, tl, table_list, 0)))
 
912
      if ((duplicate= unique_table(session, tl, table_list, 0)))
939
913
      {
940
914
        update_non_unique_table_error(table_list, "UPDATE", duplicate);
941
915
        return(true);
947
921
    further check in multi_update::prepare whether to use record cache.
948
922
  */
949
923
  lex->select_lex.exclude_from_table_unique_test= false;
950
 
 
951
 
  if (thd->fill_derived_tables() &&
 
924
 
 
925
  if (session->fill_derived_tables() &&
952
926
      mysql_handle_derived(lex, &mysql_derived_filling))
953
927
    return(true);
954
928
 
960
934
  Setup multi-update handling and call SELECT to do the join
961
935
*/
962
936
 
963
 
bool mysql_multi_update(THD *thd,
 
937
bool mysql_multi_update(Session *session,
964
938
                        TableList *table_list,
965
939
                        List<Item> *fields,
966
940
                        List<Item> *values,
971
945
{
972
946
  multi_update *result;
973
947
  bool res;
974
 
  
 
948
 
975
949
  if (!(result= new multi_update(table_list,
976
 
                                 thd->lex->select_lex.leaf_tables,
 
950
                                 session->lex->select_lex.leaf_tables,
977
951
                                 fields, values,
978
952
                                 handle_duplicates, ignore)))
979
953
    return(true);
980
954
 
981
 
  thd->abort_on_warning= true;
 
955
  session->abort_on_warning= true;
982
956
 
983
957
  List<Item> total_list;
984
 
  res= mysql_select(thd, &select_lex->ref_pointer_array,
 
958
  res= mysql_select(session, &select_lex->ref_pointer_array,
985
959
                      table_list, select_lex->with_wild,
986
960
                      total_list,
987
961
                      conds, 0, (order_st *) NULL, (order_st *)NULL, (Item *) NULL,
989
963
                      options | SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK |
990
964
                      OPTION_SETUP_TABLES_DONE,
991
965
                      result, unit, select_lex);
992
 
  res|= thd->is_error();
 
966
  res|= session->is_error();
993
967
  if (unlikely(res))
994
968
  {
995
969
    /* If we had a another error reported earlier then this will be ignored */
997
971
    result->abort();
998
972
  }
999
973
  delete result;
1000
 
  thd->abort_on_warning= 0;
 
974
  session->abort_on_warning= 0;
1001
975
  return(false);
1002
976
}
1003
977
 
1019
993
  Connect fields with tables and create list of tables that are updated
1020
994
*/
1021
995
 
1022
 
int multi_update::prepare(List<Item> &not_used_values __attribute__((unused)),
1023
 
                          SELECT_LEX_UNIT *lex_unit __attribute__((unused)))
 
996
int multi_update::prepare(List<Item> &,
 
997
                          SELECT_LEX_UNIT *)
1024
998
{
1025
999
  TableList *table_ref;
1026
1000
  SQL_LIST update;
1030
1004
  List_iterator_fast<Item> value_it(*values);
1031
1005
  uint32_t i, max_fields;
1032
1006
  uint32_t leaf_table_count= 0;
1033
 
  
1034
 
  thd->count_cuted_fields= CHECK_FIELD_WARN;
1035
 
  thd->cuted_fields=0L;
1036
 
  thd_proc_info(thd, "updating main table");
 
1007
 
 
1008
  session->count_cuted_fields= CHECK_FIELD_WARN;
 
1009
  session->cuted_fields=0L;
 
1010
  session->set_proc_info("updating main table");
1037
1011
 
1038
1012
  tables_to_update= get_table_map(fields);
1039
1013
 
1048
1022
    reference tables
1049
1023
  */
1050
1024
 
1051
 
  if (setup_fields(thd, 0, *values, MARK_COLUMNS_READ, 0, 0))
 
1025
  if (setup_fields(session, 0, *values, MARK_COLUMNS_READ, 0, 0))
1052
1026
    return(1);
1053
1027
 
1054
1028
  /*
1065
1039
    leaf_table_count++;
1066
1040
    if (tables_to_update & table->map)
1067
1041
    {
1068
 
      TableList *tl= (TableList*) thd->memdup((char*) table_ref,
 
1042
      TableList *tl= (TableList*) session->memdup((char*) table_ref,
1069
1043
                                                sizeof(*tl));
1070
1044
      if (!tl)
1071
1045
        return(1);
1081
1055
  table_count=  update.elements;
1082
1056
  update_tables= (TableList*) update.first;
1083
1057
 
1084
 
  tmp_tables = (Table**) thd->calloc(sizeof(Table *) * table_count);
1085
 
  tmp_table_param = (TMP_TABLE_PARAM*) thd->calloc(sizeof(TMP_TABLE_PARAM) *
 
1058
  tmp_tables = (Table**) session->calloc(sizeof(Table *) * table_count);
 
1059
  tmp_table_param = (TMP_TABLE_PARAM*) session->calloc(sizeof(TMP_TABLE_PARAM) *
1086
1060
                                                   table_count);
1087
 
  fields_for_table= (List_item **) thd->alloc(sizeof(List_item *) *
1088
 
                                              table_count);
1089
 
  values_for_table= (List_item **) thd->alloc(sizeof(List_item *) *
1090
 
                                              table_count);
1091
 
  if (thd->is_fatal_error)
 
1061
  fields_for_table= (List_item **) session->alloc(sizeof(List_item *) *
 
1062
                                              table_count);
 
1063
  values_for_table= (List_item **) session->alloc(sizeof(List_item *) *
 
1064
                                              table_count);
 
1065
  if (session->is_fatal_error)
1092
1066
    return(1);
1093
1067
  for (i=0 ; i < table_count ; i++)
1094
1068
  {
1095
1069
    fields_for_table[i]= new List_item;
1096
1070
    values_for_table[i]= new List_item;
1097
1071
  }
1098
 
  if (thd->is_fatal_error)
 
1072
  if (session->is_fatal_error)
1099
1073
    return(1);
1100
1074
 
1101
1075
  /* Split fields into fields_for_table[] and values_by_table[] */
1107
1081
    fields_for_table[offset]->push_back(item);
1108
1082
    values_for_table[offset]->push_back(value);
1109
1083
  }
1110
 
  if (thd->is_fatal_error)
 
1084
  if (session->is_fatal_error)
1111
1085
    return(1);
1112
1086
 
1113
1087
  /* Allocate copy fields */
1115
1089
  for (i=0 ; i < table_count ; i++)
1116
1090
    set_if_bigger(max_fields, fields_for_table[i]->elements + leaf_table_count);
1117
1091
  copy_field= new Copy_field[max_fields];
1118
 
  return(thd->is_fatal_error != 0);
 
1092
  return(session->is_fatal_error != 0);
1119
1093
}
1120
1094
 
1121
1095
 
1124
1098
 
1125
1099
  SYNOPSIS
1126
1100
    safe_update_on_fly()
1127
 
    thd                 Thread handler
 
1101
    session                 Thread handler
1128
1102
    join_tab            How table is used in join
1129
1103
    all_tables          List of tables
1130
1104
 
1152
1126
    1           Safe to update
1153
1127
*/
1154
1128
 
1155
 
static bool safe_update_on_fly(THD *thd, JOIN_TAB *join_tab,
 
1129
static bool safe_update_on_fly(Session *session, JOIN_TAB *join_tab,
1156
1130
                               TableList *table_ref, TableList *all_tables)
1157
1131
{
1158
1132
  Table *table= join_tab->table;
1159
 
  if (unique_table(thd, table_ref, all_tables, 0))
 
1133
  if (unique_table(session, table_ref, all_tables, 0))
1160
1134
    return 0;
1161
1135
  switch (join_tab->type) {
1162
1136
  case JT_SYSTEM:
1196
1170
multi_update::initialize_tables(JOIN *join)
1197
1171
{
1198
1172
  TableList *table_ref;
1199
 
  
1200
 
  if ((thd->options & OPTION_SAFE_UPDATES) && error_if_full_join(join))
 
1173
 
 
1174
  if ((session->options & OPTION_SAFE_UPDATES) && error_if_full_join(join))
1201
1175
    return(1);
1202
1176
  main_table=join->join_tab->table;
1203
1177
  table_to_update= 0;
1219
1193
      table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
1220
1194
    if (table == main_table)                    // First table in join
1221
1195
    {
1222
 
      if (safe_update_on_fly(thd, join->join_tab, table_ref, all_tables))
 
1196
      if (safe_update_on_fly(session, join->join_tab, table_ref, all_tables))
1223
1197
      {
1224
1198
        table_to_update= main_table;            // Update table on the fly
1225
1199
        continue;
1241
1215
    Table *tbl= table;
1242
1216
    do
1243
1217
    {
1244
 
      Field_string *field= new Field_string(tbl->file->ref_length, 0,
1245
 
                                            tbl->alias, &my_charset_bin);
1246
 
#ifdef OLD
1247
1218
      Field_varstring *field= new Field_varstring(tbl->file->ref_length, 0,
1248
1219
                                                  tbl->alias, tbl->s, &my_charset_bin);
1249
 
#endif
1250
1220
      if (!field)
1251
1221
        return(1);
1252
1222
      field->init(tbl);
1273
1243
    tmp_param->field_count=temp_fields.elements;
1274
1244
    tmp_param->group_parts=1;
1275
1245
    tmp_param->group_length= table->file->ref_length;
1276
 
    if (!(tmp_tables[cnt]=create_tmp_table(thd,
 
1246
    if (!(tmp_tables[cnt]=create_tmp_table(session,
1277
1247
                                           tmp_param,
1278
1248
                                           temp_fields,
1279
1249
                                           (order_st*) &group, 0, 0,
1303
1273
    {
1304
1274
      if (tmp_tables[cnt])
1305
1275
      {
1306
 
        tmp_tables[cnt]->free_tmp_table(thd);
 
1276
        tmp_tables[cnt]->free_tmp_table(session);
1307
1277
        tmp_table_param[cnt].cleanup();
1308
1278
      }
1309
1279
    }
1310
1280
  }
1311
1281
  if (copy_field)
1312
1282
    delete [] copy_field;
1313
 
  thd->count_cuted_fields= CHECK_FIELD_IGNORE;          // Restore this setting
 
1283
  session->count_cuted_fields= CHECK_FIELD_IGNORE;              // Restore this setting
1314
1284
  assert(trans_safe || !updated ||
1315
 
              thd->transaction.all.modified_non_trans_table);
 
1285
              session->transaction.all.modified_non_trans_table);
1316
1286
}
1317
1287
 
1318
1288
 
1319
 
bool multi_update::send_data(List<Item> &not_used_values __attribute__((unused)))
 
1289
bool multi_update::send_data(List<Item> &)
1320
1290
{
1321
1291
  TableList *cur_table;
1322
 
  
 
1292
 
1323
1293
  for (cur_table= update_tables; cur_table; cur_table= cur_table->next_local)
1324
1294
  {
1325
1295
    Table *table= cur_table->table;
1353
1323
                                            table->read_set));
1354
1324
      table->status|= STATUS_UPDATED;
1355
1325
      store_record(table,record[1]);
1356
 
      if (fill_record(thd, *fields_for_table[offset],
 
1326
      if (fill_record(session, *fields_for_table[offset],
1357
1327
                      *values_for_table[offset], 0))
1358
1328
        return(1);
1359
1329
 
1406
1376
          else
1407
1377
          {
1408
1378
            trans_safe= 0;
1409
 
            thd->transaction.stmt.modified_non_trans_table= true;
 
1379
            session->transaction.stmt.modified_non_trans_table= true;
1410
1380
          }
1411
1381
        }
1412
1382
      }
1425
1395
      do
1426
1396
      {
1427
1397
        tbl->file->position(tbl->record[0]);
1428
 
        memcpy(tmp_table->field[field_num]->ptr,
1429
 
               tbl->file->ref, tbl->file->ref_length);
 
1398
        Field_varstring *ref_field=
 
1399
          reinterpret_cast<Field_varstring *>(tmp_table->field[field_num]);
 
1400
        ref_field->store((char *)tbl->file->ref, tbl->file->ref_length,
 
1401
                         &my_charset_bin);
1430
1402
        field_num++;
1431
1403
      } while ((tbl= tbl_it++));
1432
1404
 
1433
1405
      /* Store regular updated fields in the row. */
1434
 
      fill_record(thd,
 
1406
      fill_record(session,
1435
1407
                  tmp_table->field + 1 + unupdated_check_opt_tables.elements,
1436
1408
                  *values_for_table[offset], 1);
1437
1409
 
1440
1412
      if (error != HA_ERR_FOUND_DUPP_KEY && error != HA_ERR_FOUND_DUPP_UNIQUE)
1441
1413
      {
1442
1414
        if (error &&
1443
 
            create_myisam_from_heap(thd, tmp_table,
 
1415
            create_myisam_from_heap(session, tmp_table,
1444
1416
                                         tmp_table_param[offset].start_recinfo,
1445
1417
                                         &tmp_table_param[offset].recinfo,
1446
1418
                                         error, 1))
1467
1439
{
1468
1440
  /* the error was handled or nothing deleted and no side effects return */
1469
1441
  if (error_handled ||
1470
 
      (!thd->transaction.stmt.modified_non_trans_table && !updated))
 
1442
      (!session->transaction.stmt.modified_non_trans_table && !updated))
1471
1443
    return;
1472
1444
  /*
1473
1445
    If all tables that has been updated are trans safe then just do rollback.
1476
1448
 
1477
1449
  if (! trans_safe)
1478
1450
  {
1479
 
    assert(thd->transaction.stmt.modified_non_trans_table);
 
1451
    assert(session->transaction.stmt.modified_non_trans_table);
1480
1452
    if (do_update && table_count > 1)
1481
1453
    {
1482
1454
      /* Add warning here */
1483
 
      /* 
 
1455
      /*
1484
1456
         todo/fixme: do_update() is never called with the arg 1.
1485
1457
         should it change the signature to become argless?
1486
1458
      */
1487
1459
      do_updates();
1488
1460
    }
1489
1461
  }
1490
 
  if (thd->transaction.stmt.modified_non_trans_table)
 
1462
  if (session->transaction.stmt.modified_non_trans_table)
1491
1463
  {
1492
 
    /*
1493
 
      The query has to binlog because there's a modified non-transactional table
1494
 
      either from the query's list or via a stored routine: bug#13270,23333
1495
 
    */
1496
 
    if (mysql_bin_log.is_open())
1497
 
    {
1498
 
      /*
1499
 
        THD::killed status might not have been set ON at time of an error
1500
 
        got caught and if happens later the killed error is written
1501
 
        into repl event.
1502
 
      */
1503
 
      thd->binlog_query(THD::ROW_QUERY_TYPE,
1504
 
                        thd->query, thd->query_length,
1505
 
                        transactional_tables, false);
1506
 
    }
1507
 
    thd->transaction.all.modified_non_trans_table= true;
 
1464
    session->transaction.all.modified_non_trans_table= true;
1508
1465
  }
1509
 
  assert(trans_safe || !updated || thd->transaction.stmt.modified_non_trans_table);
 
1466
  assert(trans_safe || !updated || session->transaction.stmt.modified_non_trans_table);
1510
1467
}
1511
1468
 
1512
1469
 
1517
1474
  ha_rows org_updated;
1518
1475
  Table *table, *tmp_table;
1519
1476
  List_iterator_fast<Table> check_opt_it(unupdated_check_opt_tables);
1520
 
  
 
1477
 
1521
1478
  do_update= 0;                                 // Don't retry this function
1522
1479
  if (!found)
1523
1480
    return(0);
1547
1504
      Setup copy functions to copy fields from temporary table
1548
1505
    */
1549
1506
    List_iterator_fast<Item> field_it(*fields_for_table[offset]);
1550
 
    Field **field= tmp_table->field + 
 
1507
    Field **field= tmp_table->field +
1551
1508
                   1 + unupdated_check_opt_tables.elements; // Skip row pointers
1552
1509
    Copy_field *copy_field_ptr= copy_field, *copy_field_end;
1553
1510
    for ( ; *field ; field++)
1567
1524
 
1568
1525
    for (;;)
1569
1526
    {
1570
 
      if (thd->killed && trans_safe)
 
1527
      if (session->killed && trans_safe)
1571
1528
        goto err;
1572
1529
      if ((local_error=tmp_table->file->rnd_next(tmp_table->record[0])))
1573
1530
      {
1584
1541
      uint32_t field_num= 0;
1585
1542
      do
1586
1543
      {
 
1544
        Field_varstring *ref_field=
 
1545
          reinterpret_cast<Field_varstring *>(tmp_table->field[field_num]);
1587
1546
        if((local_error=
1588
1547
              tbl->file->rnd_pos(tbl->record[0],
1589
 
                                (unsigned char *) tmp_table->field[field_num]->ptr)))
 
1548
                                (unsigned char *) ref_field->ptr
 
1549
                                 + ref_field->length_bytes)))
1590
1550
          goto err;
1591
1551
        field_num++;
1592
1552
      } while((tbl= check_opt_it++));
1624
1584
      else
1625
1585
      {
1626
1586
        trans_safe= 0;                          // Can't do safe rollback
1627
 
        thd->transaction.stmt.modified_non_trans_table= true;
 
1587
        session->transaction.stmt.modified_non_trans_table= true;
1628
1588
      }
1629
1589
    }
1630
1590
    (void) table->file->ha_rnd_end();
1655
1615
    else
1656
1616
    {
1657
1617
      trans_safe= 0;
1658
 
      thd->transaction.stmt.modified_non_trans_table= true;
 
1618
      session->transaction.stmt.modified_non_trans_table= true;
1659
1619
    }
1660
1620
  }
1661
1621
  return(1);
1668
1628
{
1669
1629
  char buff[STRING_BUFFER_USUAL_SIZE];
1670
1630
  uint64_t id;
1671
 
  THD::killed_state killed_status= THD::NOT_KILLED;
1672
 
  
1673
 
  thd_proc_info(thd, "updating reference tables");
1674
 
 
1675
 
  /* 
 
1631
  Session::killed_state killed_status= Session::NOT_KILLED;
 
1632
 
 
1633
  session->set_proc_info("updating reference tables");
 
1634
 
 
1635
  /*
1676
1636
     Does updates for the last n - 1 tables, returns 0 if ok;
1677
1637
     error takes into account killed status gained in do_updates()
1678
1638
  */
1681
1641
    if local_error is not set ON until after do_updates() then
1682
1642
    later carried out killing should not affect binlogging.
1683
1643
  */
1684
 
  killed_status= (local_error == 0)? THD::NOT_KILLED : thd->killed;
1685
 
  thd_proc_info(thd, "end");
 
1644
  killed_status= (local_error == 0)? Session::NOT_KILLED : session->killed;
 
1645
  session->set_proc_info("end");
1686
1646
 
1687
1647
  /*
1688
1648
    Write the SQL statement to the binlog if we updated
1689
1649
    rows and we succeeded or if we updated some non
1690
1650
    transactional tables.
1691
 
    
 
1651
 
1692
1652
    The query has to binlog because there's a modified non-transactional table
1693
1653
    either from the query's list or via a stored routine: bug#13270,23333
1694
1654
  */
1695
1655
 
1696
 
  assert(trans_safe || !updated || 
1697
 
              thd->transaction.stmt.modified_non_trans_table);
1698
 
  if (local_error == 0 || thd->transaction.stmt.modified_non_trans_table)
 
1656
  assert(trans_safe || !updated ||
 
1657
              session->transaction.stmt.modified_non_trans_table);
 
1658
  if (local_error == 0 || session->transaction.stmt.modified_non_trans_table)
1699
1659
  {
1700
 
    if (mysql_bin_log.is_open())
1701
 
    {
1702
 
      if (local_error == 0)
1703
 
        thd->clear_error();
1704
 
      if (thd->binlog_query(THD::ROW_QUERY_TYPE,
1705
 
                            thd->query, thd->query_length,
1706
 
                            transactional_tables, false, killed_status) &&
1707
 
          trans_safe)
1708
 
      {
1709
 
        local_error= 1;                         // Rollback update
1710
 
      }
1711
 
    }
1712
 
    if (thd->transaction.stmt.modified_non_trans_table)
1713
 
      thd->transaction.all.modified_non_trans_table= true;
 
1660
    if (session->transaction.stmt.modified_non_trans_table)
 
1661
      session->transaction.all.modified_non_trans_table= true;
1714
1662
  }
1715
1663
  if (local_error != 0)
1716
1664
    error_handled= true; // to force early leave from ::send_error()
1723
1671
    return(true);
1724
1672
  }
1725
1673
 
1726
 
  id= thd->arg_of_last_insert_id_function ?
1727
 
    thd->first_successful_insert_id_in_prev_stmt : 0;
 
1674
  id= session->arg_of_last_insert_id_function ?
 
1675
    session->first_successful_insert_id_in_prev_stmt : 0;
1728
1676
  sprintf(buff, ER(ER_UPDATE_INFO), (ulong) found, (ulong) updated,
1729
 
          (ulong) thd->cuted_fields);
1730
 
  thd->row_count_func=
1731
 
    (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated;
1732
 
  ::my_ok(thd, (ulong) thd->row_count_func, id, buff);
 
1677
          (ulong) session->cuted_fields);
 
1678
  session->row_count_func=
 
1679
    (session->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated;
 
1680
  ::my_ok(session, (ulong) session->row_count_func, id, buff);
1733
1681
  return(false);
1734
1682
}