~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_update.cc

  • Committer: Brian Aker
  • Date: 2008-09-04 19:31:00 UTC
  • Revision ID: brian@tangent.org-20080904193100-l849hgghfy4urj43
Changing default character set from this point on.

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/error.h>
24
 
#include <drizzled/probes.h>
 
23
#include <drizzled/drizzled_error_messages.h>
25
24
 
26
25
/*
27
26
  check that all fields are real fields
28
27
 
29
28
  SYNOPSIS
30
29
    check_fields()
31
 
    session             thread handler
 
30
    thd             thread handler
32
31
    items           Items for check
33
32
 
34
33
  RETURN
36
35
    false Items are OK
37
36
*/
38
37
 
39
 
static bool check_fields(Session *session, List<Item> &items)
 
38
static bool check_fields(THD *thd, List<Item> &items)
40
39
{
41
40
  List_iterator<Item> it(items);
42
41
  Item *item;
54
53
      we make temporary copy of Item_field, to avoid influence of changing
55
54
      result_field on Item_ref which refer on this field
56
55
    */
57
 
    session->change_item_tree(it.ref(), new Item_field(session, field));
 
56
    thd->change_item_tree(it.ref(), new Item_field(thd, field));
58
57
  }
59
58
  return false;
60
59
}
76
75
{
77
76
  Field **field_p;
78
77
  Field *field;
79
 
  uint32_t keynr;
 
78
  uint keynr;
80
79
  MY_BITMAP unique_map; /* Fields in offended unique. */
81
80
  my_bitmap_map unique_map_buf[bitmap_buffer_size(MAX_FIELDS)];
82
81
  
133
132
 
134
133
  SYNOPSIS
135
134
    mysql_update()
136
 
    session                     thread handler
 
135
    thd                 thread handler
137
136
    fields              fields for update
138
137
    values              values of fields for update
139
138
    conds               WHERE clause expression
149
148
    1  - error
150
149
*/
151
150
 
152
 
int mysql_update(Session *session, TableList *table_list,
153
 
                 List<Item> &fields, List<Item> &values, COND *conds,
154
 
                 uint32_t order_num, order_st *order,
155
 
                 ha_rows limit, enum enum_duplicates,
 
151
int mysql_update(THD *thd,
 
152
                 TableList *table_list,
 
153
                 List<Item> &fields,
 
154
                 List<Item> &values,
 
155
                 COND *conds,
 
156
                 uint order_num, order_st *order,
 
157
                 ha_rows limit,
 
158
                 enum enum_duplicates handle_duplicates __attribute__((unused)),
156
159
                 bool ignore)
157
160
{
158
161
  bool          using_limit= limit != HA_POS_ERROR;
159
 
  bool          safe_update= test(session->options & OPTION_SAFE_UPDATES);
 
162
  bool          safe_update= test(thd->options & OPTION_SAFE_UPDATES);
160
163
  bool          used_key_is_modified, transactional_table, will_batch;
161
164
  bool          can_compare_record;
162
165
  int           error, loc_error;
163
166
  uint          used_index= MAX_KEY, dup_key_found;
164
167
  bool          need_sort= true;
165
 
  uint32_t          table_count= 0;
 
168
  uint          table_count= 0;
166
169
  ha_rows       updated, found;
167
170
  key_map       old_covering_keys;
168
171
  Table         *table;
169
172
  SQL_SELECT    *select;
170
173
  READ_RECORD   info;
171
 
  SELECT_LEX    *select_lex= &session->lex->select_lex;
 
174
  SELECT_LEX    *select_lex= &thd->lex->select_lex;
172
175
  bool          need_reopen;
173
176
  uint64_t     id;
174
177
  List<Item> all_fields;
175
 
  Session::killed_state killed_status= Session::NOT_KILLED;
 
178
  THD::killed_state killed_status= THD::NOT_KILLED;
176
179
  
177
180
  for ( ; ; )
178
181
  {
179
 
    if (open_tables(session, &table_list, &table_count, 0))
 
182
    if (open_tables(thd, &table_list, &table_count, 0))
180
183
      return(1);
181
184
 
182
 
    if (!lock_tables(session, table_list, table_count, &need_reopen))
 
185
    if (!lock_tables(thd, table_list, table_count, &need_reopen))
183
186
      break;
184
187
    if (!need_reopen)
185
188
      return(1);
186
 
    close_tables_for_reopen(session, &table_list);
 
189
    close_tables_for_reopen(thd, &table_list);
187
190
  }
188
191
 
189
 
  if (mysql_handle_derived(session->lex, &mysql_derived_prepare) ||
190
 
      (session->fill_derived_tables() &&
191
 
       mysql_handle_derived(session->lex, &mysql_derived_filling)))
 
192
  if (mysql_handle_derived(thd->lex, &mysql_derived_prepare) ||
 
193
      (thd->fill_derived_tables() &&
 
194
       mysql_handle_derived(thd->lex, &mysql_derived_filling)))
192
195
    return(1);
193
196
 
194
197
  DRIZZLE_UPDATE_START();
195
 
  session->set_proc_info("init");
 
198
  thd_proc_info(thd, "init");
196
199
  table= table_list->table;
197
200
 
198
201
  /* Calculate "table->covering_keys" based on the WHERE */
199
202
  table->covering_keys= table->s->keys_in_use;
200
203
  table->quick_keys.clear_all();
201
204
 
202
 
  if (mysql_prepare_update(session, table_list, &conds, order_num, order))
 
205
  if (mysql_prepare_update(thd, table_list, &conds, order_num, order))
203
206
    goto abort;
204
207
 
205
208
  old_covering_keys= table->covering_keys;              // Keys used in WHERE
206
209
  /* Check the fields we are going to modify */
207
 
  if (setup_fields_with_no_wrap(session, 0, fields, MARK_COLUMNS_WRITE, 0, 0))
 
210
  if (setup_fields_with_no_wrap(thd, 0, fields, MARK_COLUMNS_WRITE, 0, 0))
208
211
    goto abort;                               /* purecov: inspected */
209
212
  if (table->timestamp_field)
210
213
  {
221
224
    }
222
225
  }
223
226
 
224
 
  if (setup_fields(session, 0, values, MARK_COLUMNS_READ, 0, 0))
 
227
  if (setup_fields(thd, 0, values, MARK_COLUMNS_READ, 0, 0))
225
228
  {
226
 
    free_underlaid_joins(session, select_lex);
 
229
    free_underlaid_joins(thd, select_lex);
227
230
    goto abort;                               /* purecov: inspected */
228
231
  }
229
232
 
230
233
  if (select_lex->inner_refs_list.elements &&
231
 
    fix_inner_refs(session, all_fields, select_lex, select_lex->ref_pointer_array))
 
234
    fix_inner_refs(thd, all_fields, select_lex, select_lex->ref_pointer_array))
232
235
  {
233
236
    DRIZZLE_UPDATE_END();
234
237
    return(-1);
237
240
  if (conds)
238
241
  {
239
242
    Item::cond_result cond_value;
240
 
    conds= remove_eq_conds(session, conds, &cond_value);
 
243
    conds= remove_eq_conds(thd, conds, &cond_value);
241
244
    if (cond_value == Item::COND_FALSE)
242
245
      limit= 0;                                   // Impossible WHERE
243
246
  }
260
263
 
261
264
  select= make_select(table, 0, 0, conds, 0, &error);
262
265
  if (error || !limit ||
263
 
      (select && select->check_quick(session, safe_update, limit)))
 
266
      (select && select->check_quick(thd, safe_update, limit)))
264
267
  {
265
268
    delete select;
266
 
    free_underlaid_joins(session, select_lex);
 
269
    free_underlaid_joins(thd, select_lex);
267
270
    if (error)
268
271
      goto abort;                               // Error in where
269
272
    DRIZZLE_UPDATE_END();
270
 
    my_ok(session);                             // No matching records
 
273
    my_ok(thd);                         // No matching records
271
274
    return(0);
272
275
  }
273
276
  if (!select && limit != HA_POS_ERROR)
278
281
  /* If running in safe sql mode, don't allow updates without keys */
279
282
  if (table->quick_keys.is_clear_all())
280
283
  {
281
 
    session->server_status|=SERVER_QUERY_NO_INDEX_USED;
 
284
    thd->server_status|=SERVER_QUERY_NO_INDEX_USED;
282
285
    if (safe_update && !using_limit)
283
286
    {
284
287
      my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,
331
334
        to update
332
335
        NOTE: filesort will call table->prepare_for_position()
333
336
      */
334
 
      uint32_t         length= 0;
 
337
      uint         length= 0;
335
338
      SORT_FIELD  *sortorder;
336
339
      ha_rows examined_rows;
337
340
 
338
341
      table->sort.io_cache = (IO_CACHE *) my_malloc(sizeof(IO_CACHE),
339
342
                                                    MYF(MY_FAE | MY_ZEROFILL));
340
343
      if (!(sortorder=make_unireg_sortorder(order, &length, NULL)) ||
341
 
          (table->sort.found_records= filesort(session, table, sortorder, length,
 
344
          (table->sort.found_records= filesort(thd, table, sortorder, length,
342
345
                                               select, limit, 1,
343
346
                                               &examined_rows))
344
347
          == HA_POS_ERROR)
382
385
      */
383
386
 
384
387
      if (used_index == MAX_KEY || (select && select->quick))
385
 
        init_read_record(&info,session,table,select,0,1);
 
388
        init_read_record(&info,thd,table,select,0,1);
386
389
      else
387
 
        init_read_record_idx(&info, session, table, 1, used_index);
 
390
        init_read_record_idx(&info, thd, table, 1, used_index);
388
391
 
389
 
      session->set_proc_info("Searching rows for update");
 
392
      thd_proc_info(thd, "Searching rows for update");
390
393
      ha_rows tmp_limit= limit;
391
394
 
392
 
      while (!(error=info.read_record(&info)) && !session->killed)
 
395
      while (!(error=info.read_record(&info)) && !thd->killed)
393
396
      {
394
397
        if (!(select && select->skip_record()))
395
398
        {
412
415
        else
413
416
          table->file->unlock_row();
414
417
      }
415
 
      if (session->killed && !error)
 
418
      if (thd->killed && !error)
416
419
        error= 1;                               // Aborted
417
420
      limit= tmp_limit;
418
421
      table->file->try_semi_consistent_read(0);
448
451
  if (select && select->quick && select->quick->reset())
449
452
    goto err;
450
453
  table->file->try_semi_consistent_read(1);
451
 
  init_read_record(&info,session,table,select,0,1);
 
454
  init_read_record(&info,thd,table,select,0,1);
452
455
 
453
456
  updated= found= 0;
454
457
  /* Generate an error when trying to set a NOT NULL field to NULL. */
455
 
  session->count_cuted_fields= ignore ? CHECK_FIELD_WARN
 
458
  thd->count_cuted_fields= ignore ? CHECK_FIELD_WARN
456
459
                                  : CHECK_FIELD_ERROR_FOR_NULL;
457
 
  session->cuted_fields=0L;
458
 
  session->set_proc_info("Updating");
 
460
  thd->cuted_fields=0L;
 
461
  thd_proc_info(thd, "Updating");
459
462
 
460
463
  transactional_table= table->file->has_transactions();
461
 
  session->abort_on_warning= test(!ignore);
 
464
  thd->abort_on_warning= test(!ignore);
462
465
  will_batch= !table->file->start_bulk_update();
463
466
 
464
467
  /*
477
480
                         HA_PARTIAL_COLUMN_READ) ||
478
481
                       bitmap_is_subset(table->write_set, table->read_set));
479
482
 
480
 
  while (!(error=info.read_record(&info)) && !session->killed)
 
483
  while (!(error=info.read_record(&info)) && !thd->killed)
481
484
  {
482
485
    if (!(select && select->skip_record()))
483
486
    {
485
488
        continue;  /* repeat the read of the same row if it still exists */
486
489
 
487
490
      store_record(table,record[1]);
488
 
      if (fill_record(session, fields, values, 0))
 
491
      if (fill_record(thd, fields, values, 0))
489
492
        break; /* purecov: inspected */
490
493
 
491
494
      found++;
603
606
    }
604
607
    else
605
608
      table->file->unlock_row();
606
 
    session->row_count++;
 
609
    thd->row_count++;
607
610
  }
608
611
  dup_key_found= 0;
609
612
  /*
614
617
    It's assumed that if an error was set in combination with an effective
615
618
    killed status then the error is due to killing.
616
619
  */
617
 
  killed_status= session->killed; // get the status of the volatile
 
620
  killed_status= thd->killed; // get the status of the volatile
618
621
  // simulated killing after the loop must be ineffective for binlogging
619
 
  error= (killed_status == Session::NOT_KILLED)?  error : 1;
 
622
  error= (killed_status == THD::NOT_KILLED)?  error : 1;
620
623
 
621
624
  if (error &&
622
625
      will_batch &&
643
646
  table->file->try_semi_consistent_read(0);
644
647
 
645
648
  if (!transactional_table && updated > 0)
646
 
    session->transaction.stmt.modified_non_trans_table= true;
 
649
    thd->transaction.stmt.modified_non_trans_table= true;
647
650
 
648
651
  end_read_record(&info);
649
652
  delete select;
650
 
  session->set_proc_info("end");
651
 
  table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
 
653
  thd_proc_info(thd, "end");
 
654
  VOID(table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY));
652
655
 
653
656
  /*
654
657
    error < 0 means really no error at all: we processed all rows until the
659
662
    Sometimes we want to binlog even if we updated no rows, in case user used
660
663
    it to be sure master and slave are in same state.
661
664
  */
662
 
  if ((error < 0) || session->transaction.stmt.modified_non_trans_table)
 
665
  if ((error < 0) || thd->transaction.stmt.modified_non_trans_table)
663
666
  {
664
667
    if (mysql_bin_log.is_open())
665
668
    {
666
669
      if (error < 0)
667
 
        session->clear_error();
668
 
      if (session->binlog_query(Session::ROW_QUERY_TYPE,
669
 
                            session->query, session->query_length,
 
670
        thd->clear_error();
 
671
      if (thd->binlog_query(THD::ROW_QUERY_TYPE,
 
672
                            thd->query, thd->query_length,
670
673
                            transactional_table, false, killed_status) &&
671
674
          transactional_table)
672
675
      {
673
676
        error=1;                                // Rollback update
674
677
      }
675
678
    }
676
 
    if (session->transaction.stmt.modified_non_trans_table)
677
 
      session->transaction.all.modified_non_trans_table= true;
 
679
    if (thd->transaction.stmt.modified_non_trans_table)
 
680
      thd->transaction.all.modified_non_trans_table= true;
678
681
  }
679
 
  assert(transactional_table || !updated || session->transaction.stmt.modified_non_trans_table);
680
 
  free_underlaid_joins(session, select_lex);
 
682
  assert(transactional_table || !updated || thd->transaction.stmt.modified_non_trans_table);
 
683
  free_underlaid_joins(thd, select_lex);
681
684
 
682
685
  /* If LAST_INSERT_ID(X) was used, report X */
683
 
  id= session->arg_of_last_insert_id_function ?
684
 
    session->first_successful_insert_id_in_prev_stmt : 0;
 
686
  id= thd->arg_of_last_insert_id_function ?
 
687
    thd->first_successful_insert_id_in_prev_stmt : 0;
685
688
 
686
689
  DRIZZLE_UPDATE_END();
687
690
  if (error < 0)
688
691
  {
689
692
    char buff[STRING_BUFFER_USUAL_SIZE];
690
693
    sprintf(buff, ER(ER_UPDATE_INFO), (ulong) found, (ulong) updated,
691
 
            (ulong) session->cuted_fields);
692
 
    session->row_count_func=
693
 
      (session->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated;
694
 
    my_ok(session, (ulong) session->row_count_func, id, buff);
 
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);
695
698
  }
696
 
  session->count_cuted_fields= CHECK_FIELD_IGNORE;              /* calc cuted fields */
697
 
  session->abort_on_warning= 0;
698
 
  return((error >= 0 || session->is_error()) ? 1 : 0);
 
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);
699
702
 
700
703
err:
701
704
  delete select;
702
 
  free_underlaid_joins(session, select_lex);
 
705
  free_underlaid_joins(thd, select_lex);
703
706
  if (table->key_read)
704
707
  {
705
708
    table->key_read=0;
706
709
    table->file->extra(HA_EXTRA_NO_KEYREAD);
707
710
  }
708
 
  session->abort_on_warning= 0;
 
711
  thd->abort_on_warning= 0;
709
712
 
710
713
abort:
711
714
  DRIZZLE_UPDATE_END();
717
720
 
718
721
  SYNOPSIS
719
722
    mysql_prepare_update()
720
 
    session                     - thread handler
 
723
    thd                 - thread handler
721
724
    table_list          - global/local table list
722
725
    conds               - conditions
723
726
    order_num           - number of order_st BY list entries
727
730
    false OK
728
731
    true  error
729
732
*/
730
 
bool mysql_prepare_update(Session *session, TableList *table_list,
731
 
                         Item **conds, uint32_t order_num, order_st *order)
 
733
bool mysql_prepare_update(THD *thd, TableList *table_list,
 
734
                         Item **conds, uint order_num, order_st *order)
732
735
{
733
736
  List<Item> all_fields;
734
 
  SELECT_LEX *select_lex= &session->lex->select_lex;
 
737
  SELECT_LEX *select_lex= &thd->lex->select_lex;
735
738
  
736
739
  /*
737
740
    Statement-based replication of UPDATE ... LIMIT is not safe as order of
741
744
    is present. However it may confuse users to see very similiar statements
742
745
    replicated differently.
743
746
  */
744
 
  if (session->lex->current_select->select_limit)
 
747
  if (thd->lex->current_select->select_limit)
745
748
  {
746
 
    session->lex->set_stmt_unsafe();
747
 
    session->set_current_stmt_binlog_row_based_if_mixed();
 
749
    thd->lex->set_stmt_unsafe();
 
750
    thd->set_current_stmt_binlog_row_based_if_mixed();
748
751
  }
749
752
 
750
 
  session->lex->allow_sum_func= 0;
 
753
  thd->lex->allow_sum_func= 0;
751
754
 
752
 
  if (setup_tables_and_check_access(session, &select_lex->context, 
 
755
  if (setup_tables_and_check_access(thd, &select_lex->context, 
753
756
                                    &select_lex->top_join_list,
754
757
                                    table_list,
755
758
                                    &select_lex->leaf_tables,
756
759
                                    false) ||
757
 
      setup_conds(session, table_list, select_lex->leaf_tables, conds) ||
758
 
      select_lex->setup_ref_array(session, order_num) ||
759
 
      setup_order(session, select_lex->ref_pointer_array,
 
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,
760
763
                  table_list, all_fields, all_fields, order))
761
764
    return(true);
762
765
 
763
766
  /* Check that we are not using table that we are updating in a sub select */
764
767
  {
765
768
    TableList *duplicate;
766
 
    if ((duplicate= unique_table(session, table_list, table_list->next_global, 0)))
 
769
    if ((duplicate= unique_table(thd, table_list, table_list->next_global, 0)))
767
770
    {
768
771
      update_non_unique_table_error(table_list, "UPDATE", duplicate);
769
772
      my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->table_name);
800
803
 
801
804
  SYNOPSIS
802
805
    mysql_multi_update_prepare()
803
 
    session         thread handler
 
806
    thd         thread handler
804
807
 
805
808
  RETURN
806
809
    false OK
807
810
    true  Error
808
811
*/
809
812
 
810
 
int mysql_multi_update_prepare(Session *session)
 
813
int mysql_multi_update_prepare(THD *thd)
811
814
{
812
 
  LEX *lex= session->lex;
 
815
  LEX *lex= thd->lex;
813
816
  TableList *table_list= lex->query_tables;
814
817
  TableList *tl, *leaves;
815
818
  List<Item> *fields= &lex->select_lex.item_list;
820
823
    counter else junk will be assigned here, but then replaced with real
821
824
    count in open_tables()
822
825
  */
823
 
  uint32_t  table_count= lex->table_count;
824
 
  const bool using_lock_tables= session->locked_tables != 0;
825
 
  bool original_multiupdate= (session->lex->sql_command == SQLCOM_UPDATE_MULTI);
 
826
  uint  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);
826
829
  bool need_reopen= false;
827
830
  
828
831
 
829
832
  /* following need for prepared statements, to run next time multi-update */
830
 
  session->lex->sql_command= SQLCOM_UPDATE_MULTI;
 
833
  thd->lex->sql_command= SQLCOM_UPDATE_MULTI;
831
834
 
832
835
reopen_tables:
833
836
 
834
837
  /* open tables and create derived ones, but do not lock and fill them */
835
838
  if (((original_multiupdate || need_reopen) &&
836
 
       open_tables(session, &table_list, &table_count, 0)) ||
 
839
       open_tables(thd, &table_list, &table_count, 0)) ||
837
840
      mysql_handle_derived(lex, &mysql_derived_prepare))
838
841
    return(true);
839
842
  /*
842
845
    call in setup_tables()).
843
846
  */
844
847
 
845
 
  if (setup_tables_and_check_access(session, &lex->select_lex.context,
 
848
  if (setup_tables_and_check_access(thd, &lex->select_lex.context,
846
849
                                    &lex->select_lex.top_join_list,
847
850
                                    table_list,
848
851
                                    &lex->select_lex.leaf_tables, false))
849
852
    return(true);
850
853
 
851
 
  if (setup_fields_with_no_wrap(session, 0, *fields, MARK_COLUMNS_WRITE, 0, 0))
 
854
  if (setup_fields_with_no_wrap(thd, 0, *fields, MARK_COLUMNS_WRITE, 0, 0))
852
855
    return(true);
853
856
 
854
 
  if (update_view && check_fields(session, *fields))
 
857
  if (update_view && check_fields(thd, *fields))
855
858
  {
856
859
    return(true);
857
860
  }
896
899
  }
897
900
 
898
901
  /* now lock and fill tables */
899
 
  if (lock_tables(session, table_list, table_count, &need_reopen))
 
902
  if (lock_tables(thd, table_list, table_count, &need_reopen))
900
903
  {
901
904
    if (!need_reopen)
902
905
      return(true);
916
919
    for (TableList *tbl= table_list; tbl; tbl= tbl->next_global)
917
920
      tbl->cleanup_items();
918
921
 
919
 
    close_tables_for_reopen(session, &table_list);
 
922
    close_tables_for_reopen(thd, &table_list);
920
923
    goto reopen_tables;
921
924
  }
922
925
 
932
935
        tl->lock_type != TL_READ_NO_INSERT)
933
936
    {
934
937
      TableList *duplicate;
935
 
      if ((duplicate= unique_table(session, tl, table_list, 0)))
 
938
      if ((duplicate= unique_table(thd, tl, table_list, 0)))
936
939
      {
937
940
        update_non_unique_table_error(table_list, "UPDATE", duplicate);
938
941
        return(true);
945
948
  */
946
949
  lex->select_lex.exclude_from_table_unique_test= false;
947
950
 
948
 
  if (session->fill_derived_tables() &&
 
951
  if (thd->fill_derived_tables() &&
949
952
      mysql_handle_derived(lex, &mysql_derived_filling))
950
953
    return(true);
951
954
 
957
960
  Setup multi-update handling and call SELECT to do the join
958
961
*/
959
962
 
960
 
bool mysql_multi_update(Session *session,
 
963
bool mysql_multi_update(THD *thd,
961
964
                        TableList *table_list,
962
965
                        List<Item> *fields,
963
966
                        List<Item> *values,
970
973
  bool res;
971
974
  
972
975
  if (!(result= new multi_update(table_list,
973
 
                                 session->lex->select_lex.leaf_tables,
 
976
                                 thd->lex->select_lex.leaf_tables,
974
977
                                 fields, values,
975
978
                                 handle_duplicates, ignore)))
976
979
    return(true);
977
980
 
978
 
  session->abort_on_warning= true;
 
981
  thd->abort_on_warning= true;
979
982
 
980
983
  List<Item> total_list;
981
 
  res= mysql_select(session, &select_lex->ref_pointer_array,
 
984
  res= mysql_select(thd, &select_lex->ref_pointer_array,
982
985
                      table_list, select_lex->with_wild,
983
986
                      total_list,
984
987
                      conds, 0, (order_st *) NULL, (order_st *)NULL, (Item *) NULL,
986
989
                      options | SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK |
987
990
                      OPTION_SETUP_TABLES_DONE,
988
991
                      result, unit, select_lex);
989
 
  res|= session->is_error();
 
992
  res|= thd->is_error();
990
993
  if (unlikely(res))
991
994
  {
992
995
    /* If we had a another error reported earlier then this will be ignored */
994
997
    result->abort();
995
998
  }
996
999
  delete result;
997
 
  session->abort_on_warning= 0;
 
1000
  thd->abort_on_warning= 0;
998
1001
  return(false);
999
1002
}
1000
1003
 
1016
1019
  Connect fields with tables and create list of tables that are updated
1017
1020
*/
1018
1021
 
1019
 
int multi_update::prepare(List<Item> &,
1020
 
                          SELECT_LEX_UNIT *)
 
1022
int multi_update::prepare(List<Item> &not_used_values __attribute__((unused)),
 
1023
                          SELECT_LEX_UNIT *lex_unit __attribute__((unused)))
1021
1024
{
1022
1025
  TableList *table_ref;
1023
1026
  SQL_LIST update;
1025
1028
  Item_field *item;
1026
1029
  List_iterator_fast<Item> field_it(*fields);
1027
1030
  List_iterator_fast<Item> value_it(*values);
1028
 
  uint32_t i, max_fields;
1029
 
  uint32_t leaf_table_count= 0;
 
1031
  uint i, max_fields;
 
1032
  uint leaf_table_count= 0;
1030
1033
  
1031
 
  session->count_cuted_fields= CHECK_FIELD_WARN;
1032
 
  session->cuted_fields=0L;
1033
 
  session->set_proc_info("updating main table");
 
1034
  thd->count_cuted_fields= CHECK_FIELD_WARN;
 
1035
  thd->cuted_fields=0L;
 
1036
  thd_proc_info(thd, "updating main table");
1034
1037
 
1035
1038
  tables_to_update= get_table_map(fields);
1036
1039
 
1045
1048
    reference tables
1046
1049
  */
1047
1050
 
1048
 
  if (setup_fields(session, 0, *values, MARK_COLUMNS_READ, 0, 0))
 
1051
  if (setup_fields(thd, 0, *values, MARK_COLUMNS_READ, 0, 0))
1049
1052
    return(1);
1050
1053
 
1051
1054
  /*
1062
1065
    leaf_table_count++;
1063
1066
    if (tables_to_update & table->map)
1064
1067
    {
1065
 
      TableList *tl= (TableList*) session->memdup((char*) table_ref,
 
1068
      TableList *tl= (TableList*) thd->memdup((char*) table_ref,
1066
1069
                                                sizeof(*tl));
1067
1070
      if (!tl)
1068
1071
        return(1);
1069
 
      update.link_in_list((unsigned char*) tl, (unsigned char**) &tl->next_local);
 
1072
      update.link_in_list((uchar*) tl, (uchar**) &tl->next_local);
1070
1073
      tl->shared= table_count++;
1071
1074
      table->no_keyread=1;
1072
1075
      table->covering_keys.clear_all();
1078
1081
  table_count=  update.elements;
1079
1082
  update_tables= (TableList*) update.first;
1080
1083
 
1081
 
  tmp_tables = (Table**) session->calloc(sizeof(Table *) * table_count);
1082
 
  tmp_table_param = (TMP_TABLE_PARAM*) session->calloc(sizeof(TMP_TABLE_PARAM) *
 
1084
  tmp_tables = (Table**) thd->calloc(sizeof(Table *) * table_count);
 
1085
  tmp_table_param = (TMP_TABLE_PARAM*) thd->calloc(sizeof(TMP_TABLE_PARAM) *
1083
1086
                                                   table_count);
1084
 
  fields_for_table= (List_item **) session->alloc(sizeof(List_item *) *
1085
 
                                              table_count);
1086
 
  values_for_table= (List_item **) session->alloc(sizeof(List_item *) *
1087
 
                                              table_count);
1088
 
  if (session->is_fatal_error)
 
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)
1089
1092
    return(1);
1090
1093
  for (i=0 ; i < table_count ; i++)
1091
1094
  {
1092
1095
    fields_for_table[i]= new List_item;
1093
1096
    values_for_table[i]= new List_item;
1094
1097
  }
1095
 
  if (session->is_fatal_error)
 
1098
  if (thd->is_fatal_error)
1096
1099
    return(1);
1097
1100
 
1098
1101
  /* Split fields into fields_for_table[] and values_by_table[] */
1100
1103
  while ((item= (Item_field *) field_it++))
1101
1104
  {
1102
1105
    Item *value= value_it++;
1103
 
    uint32_t offset= item->field->table->pos_in_table_list->shared;
 
1106
    uint offset= item->field->table->pos_in_table_list->shared;
1104
1107
    fields_for_table[offset]->push_back(item);
1105
1108
    values_for_table[offset]->push_back(value);
1106
1109
  }
1107
 
  if (session->is_fatal_error)
 
1110
  if (thd->is_fatal_error)
1108
1111
    return(1);
1109
1112
 
1110
1113
  /* Allocate copy fields */
1112
1115
  for (i=0 ; i < table_count ; i++)
1113
1116
    set_if_bigger(max_fields, fields_for_table[i]->elements + leaf_table_count);
1114
1117
  copy_field= new Copy_field[max_fields];
1115
 
  return(session->is_fatal_error != 0);
 
1118
  return(thd->is_fatal_error != 0);
1116
1119
}
1117
1120
 
1118
1121
 
1121
1124
 
1122
1125
  SYNOPSIS
1123
1126
    safe_update_on_fly()
1124
 
    session                 Thread handler
 
1127
    thd                 Thread handler
1125
1128
    join_tab            How table is used in join
1126
1129
    all_tables          List of tables
1127
1130
 
1149
1152
    1           Safe to update
1150
1153
*/
1151
1154
 
1152
 
static bool safe_update_on_fly(Session *session, JOIN_TAB *join_tab,
 
1155
static bool safe_update_on_fly(THD *thd, JOIN_TAB *join_tab,
1153
1156
                               TableList *table_ref, TableList *all_tables)
1154
1157
{
1155
1158
  Table *table= join_tab->table;
1156
 
  if (unique_table(session, table_ref, all_tables, 0))
 
1159
  if (unique_table(thd, table_ref, all_tables, 0))
1157
1160
    return 0;
1158
1161
  switch (join_tab->type) {
1159
1162
  case JT_SYSTEM:
1194
1197
{
1195
1198
  TableList *table_ref;
1196
1199
  
1197
 
  if ((session->options & OPTION_SAFE_UPDATES) && error_if_full_join(join))
 
1200
  if ((thd->options & OPTION_SAFE_UPDATES) && error_if_full_join(join))
1198
1201
    return(1);
1199
1202
  main_table=join->join_tab->table;
1200
1203
  table_to_update= 0;
1206
1209
  for (table_ref= update_tables; table_ref; table_ref= table_ref->next_local)
1207
1210
  {
1208
1211
    Table *table=table_ref->table;
1209
 
    uint32_t cnt= table_ref->shared;
 
1212
    uint cnt= table_ref->shared;
1210
1213
    List<Item> temp_fields;
1211
1214
    order_st     group;
1212
1215
    TMP_TABLE_PARAM *tmp_param;
1216
1219
      table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
1217
1220
    if (table == main_table)                    // First table in join
1218
1221
    {
1219
 
      if (safe_update_on_fly(session, join->join_tab, table_ref, all_tables))
 
1222
      if (safe_update_on_fly(thd, join->join_tab, table_ref, all_tables))
1220
1223
      {
1221
1224
        table_to_update= main_table;            // Update table on the fly
1222
1225
        continue;
1270
1273
    tmp_param->field_count=temp_fields.elements;
1271
1274
    tmp_param->group_parts=1;
1272
1275
    tmp_param->group_length= table->file->ref_length;
1273
 
    if (!(tmp_tables[cnt]=create_tmp_table(session,
 
1276
    if (!(tmp_tables[cnt]=create_tmp_table(thd,
1274
1277
                                           tmp_param,
1275
1278
                                           temp_fields,
1276
1279
                                           (order_st*) &group, 0, 0,
1296
1299
 
1297
1300
  if (tmp_tables)
1298
1301
  {
1299
 
    for (uint32_t cnt = 0; cnt < table_count; cnt++)
 
1302
    for (uint cnt = 0; cnt < table_count; cnt++)
1300
1303
    {
1301
1304
      if (tmp_tables[cnt])
1302
1305
      {
1303
 
        tmp_tables[cnt]->free_tmp_table(session);
 
1306
        tmp_tables[cnt]->free_tmp_table(thd);
1304
1307
        tmp_table_param[cnt].cleanup();
1305
1308
      }
1306
1309
    }
1307
1310
  }
1308
1311
  if (copy_field)
1309
1312
    delete [] copy_field;
1310
 
  session->count_cuted_fields= CHECK_FIELD_IGNORE;              // Restore this setting
 
1313
  thd->count_cuted_fields= CHECK_FIELD_IGNORE;          // Restore this setting
1311
1314
  assert(trans_safe || !updated ||
1312
 
              session->transaction.all.modified_non_trans_table);
 
1315
              thd->transaction.all.modified_non_trans_table);
1313
1316
}
1314
1317
 
1315
1318
 
1316
 
bool multi_update::send_data(List<Item> &)
 
1319
bool multi_update::send_data(List<Item> &not_used_values __attribute__((unused)))
1317
1320
{
1318
1321
  TableList *cur_table;
1319
 
 
 
1322
  
1320
1323
  for (cur_table= update_tables; cur_table; cur_table= cur_table->next_local)
1321
1324
  {
1322
1325
    Table *table= cur_table->table;
1323
 
    uint32_t offset= cur_table->shared;
 
1326
    uint offset= cur_table->shared;
1324
1327
    /*
1325
1328
      Check if we are using outer join and we didn't find the row
1326
1329
      or if we have already updated this row in the previous call to this
1350
1353
                                            table->read_set));
1351
1354
      table->status|= STATUS_UPDATED;
1352
1355
      store_record(table,record[1]);
1353
 
      if (fill_record(session, *fields_for_table[offset],
 
1356
      if (fill_record(thd, *fields_for_table[offset],
1354
1357
                      *values_for_table[offset], 0))
1355
1358
        return(1);
1356
1359
 
1403
1406
          else
1404
1407
          {
1405
1408
            trans_safe= 0;
1406
 
            session->transaction.stmt.modified_non_trans_table= true;
 
1409
            thd->transaction.stmt.modified_non_trans_table= true;
1407
1410
          }
1408
1411
        }
1409
1412
      }
1416
1419
       For updatable VIEW store rowid of the updated table and
1417
1420
       rowids of tables used in the CHECK OPTION condition.
1418
1421
      */
1419
 
      uint32_t field_num= 0;
 
1422
      uint field_num= 0;
1420
1423
      List_iterator_fast<Table> tbl_it(unupdated_check_opt_tables);
1421
1424
      Table *tbl= table;
1422
1425
      do
1428
1431
      } while ((tbl= tbl_it++));
1429
1432
 
1430
1433
      /* Store regular updated fields in the row. */
1431
 
      fill_record(session,
 
1434
      fill_record(thd,
1432
1435
                  tmp_table->field + 1 + unupdated_check_opt_tables.elements,
1433
1436
                  *values_for_table[offset], 1);
1434
1437
 
1437
1440
      if (error != HA_ERR_FOUND_DUPP_KEY && error != HA_ERR_FOUND_DUPP_UNIQUE)
1438
1441
      {
1439
1442
        if (error &&
1440
 
            create_myisam_from_heap(session, tmp_table,
 
1443
            create_myisam_from_heap(thd, tmp_table,
1441
1444
                                         tmp_table_param[offset].start_recinfo,
1442
1445
                                         &tmp_table_param[offset].recinfo,
1443
1446
                                         error, 1))
1453
1456
}
1454
1457
 
1455
1458
 
1456
 
void multi_update::send_error(uint32_t errcode,const char *err)
 
1459
void multi_update::send_error(uint errcode,const char *err)
1457
1460
{
1458
1461
  /* First send error what ever it is ... */
1459
1462
  my_error(errcode, MYF(0), err);
1464
1467
{
1465
1468
  /* the error was handled or nothing deleted and no side effects return */
1466
1469
  if (error_handled ||
1467
 
      (!session->transaction.stmt.modified_non_trans_table && !updated))
 
1470
      (!thd->transaction.stmt.modified_non_trans_table && !updated))
1468
1471
    return;
1469
1472
  /*
1470
1473
    If all tables that has been updated are trans safe then just do rollback.
1473
1476
 
1474
1477
  if (! trans_safe)
1475
1478
  {
1476
 
    assert(session->transaction.stmt.modified_non_trans_table);
 
1479
    assert(thd->transaction.stmt.modified_non_trans_table);
1477
1480
    if (do_update && table_count > 1)
1478
1481
    {
1479
1482
      /* Add warning here */
1481
1484
         todo/fixme: do_update() is never called with the arg 1.
1482
1485
         should it change the signature to become argless?
1483
1486
      */
1484
 
      do_updates();
 
1487
      VOID(do_updates());
1485
1488
    }
1486
1489
  }
1487
 
  if (session->transaction.stmt.modified_non_trans_table)
 
1490
  if (thd->transaction.stmt.modified_non_trans_table)
1488
1491
  {
1489
1492
    /*
1490
1493
      The query has to binlog because there's a modified non-transactional table
1493
1496
    if (mysql_bin_log.is_open())
1494
1497
    {
1495
1498
      /*
1496
 
        Session::killed status might not have been set ON at time of an error
 
1499
        THD::killed status might not have been set ON at time of an error
1497
1500
        got caught and if happens later the killed error is written
1498
1501
        into repl event.
1499
1502
      */
1500
 
      session->binlog_query(Session::ROW_QUERY_TYPE,
1501
 
                        session->query, session->query_length,
 
1503
      thd->binlog_query(THD::ROW_QUERY_TYPE,
 
1504
                        thd->query, thd->query_length,
1502
1505
                        transactional_tables, false);
1503
1506
    }
1504
 
    session->transaction.all.modified_non_trans_table= true;
 
1507
    thd->transaction.all.modified_non_trans_table= true;
1505
1508
  }
1506
 
  assert(trans_safe || !updated || session->transaction.stmt.modified_non_trans_table);
 
1509
  assert(trans_safe || !updated || thd->transaction.stmt.modified_non_trans_table);
1507
1510
}
1508
1511
 
1509
1512
 
1521
1524
  for (cur_table= update_tables; cur_table; cur_table= cur_table->next_local)
1522
1525
  {
1523
1526
    bool can_compare_record;
1524
 
    uint32_t offset= cur_table->shared;
 
1527
    uint offset= cur_table->shared;
1525
1528
 
1526
1529
    table = cur_table->table;
1527
1530
    if (table == table_to_update)
1564
1567
 
1565
1568
    for (;;)
1566
1569
    {
1567
 
      if (session->killed && trans_safe)
 
1570
      if (thd->killed && trans_safe)
1568
1571
        goto err;
1569
1572
      if ((local_error=tmp_table->file->rnd_next(tmp_table->record[0])))
1570
1573
      {
1578
1581
      /* call rnd_pos() using rowids from temporary table */
1579
1582
      check_opt_it.rewind();
1580
1583
      Table *tbl= table;
1581
 
      uint32_t field_num= 0;
 
1584
      uint field_num= 0;
1582
1585
      do
1583
1586
      {
1584
1587
        if((local_error=
1585
1588
              tbl->file->rnd_pos(tbl->record[0],
1586
 
                                (unsigned char *) tmp_table->field[field_num]->ptr)))
 
1589
                                (uchar *) tmp_table->field[field_num]->ptr)))
1587
1590
          goto err;
1588
1591
        field_num++;
1589
1592
      } while((tbl= check_opt_it++));
1621
1624
      else
1622
1625
      {
1623
1626
        trans_safe= 0;                          // Can't do safe rollback
1624
 
        session->transaction.stmt.modified_non_trans_table= true;
 
1627
        thd->transaction.stmt.modified_non_trans_table= true;
1625
1628
      }
1626
1629
    }
1627
1630
    (void) table->file->ha_rnd_end();
1652
1655
    else
1653
1656
    {
1654
1657
      trans_safe= 0;
1655
 
      session->transaction.stmt.modified_non_trans_table= true;
 
1658
      thd->transaction.stmt.modified_non_trans_table= true;
1656
1659
    }
1657
1660
  }
1658
1661
  return(1);
1665
1668
{
1666
1669
  char buff[STRING_BUFFER_USUAL_SIZE];
1667
1670
  uint64_t id;
1668
 
  Session::killed_state killed_status= Session::NOT_KILLED;
 
1671
  THD::killed_state killed_status= THD::NOT_KILLED;
1669
1672
  
1670
 
  session->set_proc_info("updating reference tables");
 
1673
  thd_proc_info(thd, "updating reference tables");
1671
1674
 
1672
1675
  /* 
1673
1676
     Does updates for the last n - 1 tables, returns 0 if ok;
1678
1681
    if local_error is not set ON until after do_updates() then
1679
1682
    later carried out killing should not affect binlogging.
1680
1683
  */
1681
 
  killed_status= (local_error == 0)? Session::NOT_KILLED : session->killed;
1682
 
  session->set_proc_info("end");
 
1684
  killed_status= (local_error == 0)? THD::NOT_KILLED : thd->killed;
 
1685
  thd_proc_info(thd, "end");
1683
1686
 
1684
1687
  /*
1685
1688
    Write the SQL statement to the binlog if we updated
1691
1694
  */
1692
1695
 
1693
1696
  assert(trans_safe || !updated || 
1694
 
              session->transaction.stmt.modified_non_trans_table);
1695
 
  if (local_error == 0 || session->transaction.stmt.modified_non_trans_table)
 
1697
              thd->transaction.stmt.modified_non_trans_table);
 
1698
  if (local_error == 0 || thd->transaction.stmt.modified_non_trans_table)
1696
1699
  {
1697
1700
    if (mysql_bin_log.is_open())
1698
1701
    {
1699
1702
      if (local_error == 0)
1700
 
        session->clear_error();
1701
 
      if (session->binlog_query(Session::ROW_QUERY_TYPE,
1702
 
                            session->query, session->query_length,
 
1703
        thd->clear_error();
 
1704
      if (thd->binlog_query(THD::ROW_QUERY_TYPE,
 
1705
                            thd->query, thd->query_length,
1703
1706
                            transactional_tables, false, killed_status) &&
1704
1707
          trans_safe)
1705
1708
      {
1706
1709
        local_error= 1;                         // Rollback update
1707
1710
      }
1708
1711
    }
1709
 
    if (session->transaction.stmt.modified_non_trans_table)
1710
 
      session->transaction.all.modified_non_trans_table= true;
 
1712
    if (thd->transaction.stmt.modified_non_trans_table)
 
1713
      thd->transaction.all.modified_non_trans_table= true;
1711
1714
  }
1712
1715
  if (local_error != 0)
1713
1716
    error_handled= true; // to force early leave from ::send_error()
1720
1723
    return(true);
1721
1724
  }
1722
1725
 
1723
 
  id= session->arg_of_last_insert_id_function ?
1724
 
    session->first_successful_insert_id_in_prev_stmt : 0;
 
1726
  id= thd->arg_of_last_insert_id_function ?
 
1727
    thd->first_successful_insert_id_in_prev_stmt : 0;
1725
1728
  sprintf(buff, ER(ER_UPDATE_INFO), (ulong) found, (ulong) updated,
1726
 
          (ulong) session->cuted_fields);
1727
 
  session->row_count_func=
1728
 
    (session->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated;
1729
 
  ::my_ok(session, (ulong) session->row_count_func, id, buff);
 
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);
1730
1733
  return(false);
1731
1734
}