~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_insert.cc

  • Committer: Stewart Smith
  • Date: 2009-06-16 00:47:17 UTC
  • mto: (1119.2.6 merge)
  • mto: This revision was merged to the branch mainline in revision 1124.
  • Revision ID: stewart@flamingspork.com-20090616004717-po86r1tt9ch8eg0d
make show_create_table_utf8 test not leave tables behind

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 
17
17
/* Insert of records */
18
18
 
19
 
#include "config.h"
 
19
#include <drizzled/server_includes.h>
20
20
#include <drizzled/sql_select.h>
21
21
#include <drizzled/show.h>
22
22
#include <drizzled/error.h>
26
26
#include <drizzled/sql_load.h>
27
27
#include <drizzled/field/timestamp.h>
28
28
#include <drizzled/lock.h>
29
 
#include "drizzled/sql_table.h"
30
 
#include "drizzled/pthread_globals.h"
31
 
#include "drizzled/transaction_services.h"
32
 
#include "drizzled/plugin/transactional_storage_engine.h"
33
 
 
34
 
namespace drizzled
35
 
{
36
 
 
37
 
extern plugin::StorageEngine *heap_engine;
38
 
extern plugin::StorageEngine *myisam_engine;
 
29
 
39
30
 
40
31
/*
41
32
  Check if insert fields are correct.
165
156
      Unmark the timestamp field so that we can check if this is modified
166
157
      by update_fields
167
158
    */
168
 
    timestamp_mark= table->write_set->testAndClear(table->timestamp_field->field_index);
 
159
    timestamp_mark= bitmap_test_and_clear(table->write_set,
 
160
                                          table->timestamp_field->field_index);
169
161
  }
170
162
 
171
163
  /* Check the fields we are going to modify */
248
240
                    values_list.elements > 1);
249
241
 
250
242
  if (session->openTablesLock(table_list))
251
 
  {
252
 
    DRIZZLE_INSERT_DONE(1, 0);
253
243
    return true;
254
 
  }
255
244
 
256
245
  lock_type= table_list->lock_type;
257
246
 
307
296
  ctx_state.restore_state(context, table_list);
308
297
 
309
298
  /*
310
 
    Fill in the given fields and dump it to the table cursor
 
299
    Fill in the given fields and dump it to the table file
311
300
  */
312
301
  memset(&info, 0, sizeof(info));
313
302
  info.ignore= ignore;
321
310
    to NULL.
322
311
  */
323
312
  session->count_cuted_fields= ((values_list.elements == 1 &&
324
 
                                 !ignore) ?
325
 
                                CHECK_FIELD_ERROR_FOR_NULL :
326
 
                                CHECK_FIELD_WARN);
 
313
                             !ignore) ?
 
314
                            CHECK_FIELD_ERROR_FOR_NULL :
 
315
                            CHECK_FIELD_WARN);
327
316
  session->cuted_fields = 0L;
328
317
  table->next_number_field=table->found_next_number_field;
329
318
 
330
319
  error=0;
331
320
  session->set_proc_info("update");
332
321
  if (duplic == DUP_REPLACE)
333
 
    table->cursor->extra(HA_EXTRA_WRITE_CAN_REPLACE);
 
322
    table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE);
334
323
  if (duplic == DUP_UPDATE)
335
 
    table->cursor->extra(HA_EXTRA_INSERT_WITH_UPDATE);
 
324
    table->file->extra(HA_EXTRA_INSERT_WITH_UPDATE);
336
325
  {
337
326
    if (duplic != DUP_ERROR || ignore)
338
 
      table->cursor->extra(HA_EXTRA_IGNORE_DUP_KEY);
339
 
    table->cursor->ha_start_bulk_insert(values_list.elements);
 
327
      table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
 
328
    table->file->ha_start_bulk_insert(values_list.elements);
340
329
  }
341
330
 
342
331
 
349
338
    if (fields.elements || !value_count)
350
339
    {
351
340
      table->restoreRecordAsDefault();  // Get empty record
352
 
      if (fill_record(session, fields, *values))
 
341
      if (fill_record(session, fields, *values, 0))
353
342
      {
354
343
        if (values_list.elements != 1 && ! session->is_error())
355
344
        {
367
356
    }
368
357
    else
369
358
    {
370
 
      table->restoreRecordAsDefault();  // Get empty record
371
 
 
372
 
      if (fill_record(session, table->field, *values))
 
359
      if (session->used_tables)                 // Column used in values()
 
360
        table->restoreRecordAsDefault();        // Get empty record
 
361
      else
 
362
      {
 
363
        /*
 
364
          Fix delete marker. No need to restore rest of record since it will
 
365
          be overwritten by fill_record() anyway (and fill_record() does not
 
366
          use default values in this case).
 
367
        */
 
368
        table->record[0][0]= table->s->default_values[0];
 
369
      }
 
370
      if (fill_record(session, table->field, *values, 0))
373
371
      {
374
372
        if (values_list.elements != 1 && ! session->is_error())
375
373
        {
382
380
    }
383
381
 
384
382
    // Release latches in case bulk insert takes a long time
385
 
    plugin::TransactionalStorageEngine::releaseTemporaryLatches(session);
 
383
    ha_release_temporary_latches(session);
386
384
 
387
385
    error=write_record(session, table ,&info);
388
386
    if (error)
402
400
      Do not do this release if this is a delayed insert, it would steal
403
401
      auto_inc values from the delayed_insert thread as they share Table.
404
402
    */
405
 
    table->cursor->ha_release_auto_increment();
406
 
    if (table->cursor->ha_end_bulk_insert() && !error)
 
403
    table->file->ha_release_auto_increment();
 
404
    if (table->file->ha_end_bulk_insert() && !error)
407
405
    {
408
 
      table->print_error(errno,MYF(0));
 
406
      table->file->print_error(my_errno,MYF(0));
409
407
      error=1;
410
408
    }
411
409
    if (duplic != DUP_ERROR || ignore)
412
 
      table->cursor->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
 
410
      table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
413
411
 
414
 
    transactional_table= table->cursor->has_transactions();
 
412
    transactional_table= table->file->has_transactions();
415
413
 
416
414
    changed= (info.copied || info.deleted || info.updated);
417
 
    if ((changed && error <= 0) || session->transaction.stmt.hasModifiedNonTransData())
 
415
    if ((changed && error <= 0) || session->transaction.stmt.modified_non_trans_table)
418
416
    {
419
 
      if (session->transaction.stmt.hasModifiedNonTransData())
420
 
        session->transaction.all.markModifiedNonTransData();
 
417
      if (session->transaction.stmt.modified_non_trans_table)
 
418
        session->transaction.all.modified_non_trans_table= true;
421
419
    }
422
 
    assert(transactional_table || !changed || session->transaction.stmt.hasModifiedNonTransData());
 
420
    assert(transactional_table || !changed || session->transaction.stmt.modified_non_trans_table);
423
421
 
424
422
  }
425
423
  session->set_proc_info("end");
443
441
  session->count_cuted_fields= CHECK_FIELD_IGNORE;
444
442
  table->auto_increment_field_not_null= false;
445
443
  if (duplic == DUP_REPLACE)
446
 
    table->cursor->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
 
444
    table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
447
445
 
448
446
  if (error)
449
447
    goto abort;
458
456
  {
459
457
    char buff[160];
460
458
    if (ignore)
461
 
      snprintf(buff, sizeof(buff), ER(ER_INSERT_INFO), (ulong) info.records,
 
459
      sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records,
462
460
              (ulong) (info.records - info.copied), (ulong) session->cuted_fields);
463
461
    else
464
 
      snprintf(buff, sizeof(buff), ER(ER_INSERT_INFO), (ulong) info.records,
 
462
      sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records,
465
463
              (ulong) (info.deleted + info.updated), (ulong) session->cuted_fields);
466
464
    session->row_count_func= info.copied + info.deleted + info.updated;
467
465
    session->my_ok((ulong) session->row_count_func,
468
466
                   info.copied + info.deleted + info.touched, id, buff);
469
467
  }
470
468
  session->abort_on_warning= 0;
471
 
  DRIZZLE_INSERT_DONE(0, session->row_count_func);
472
 
  return false;
 
469
  DRIZZLE_INSERT_END();
 
470
  return(false);
473
471
 
474
472
abort:
475
473
  if (table != NULL)
476
 
    table->cursor->ha_release_auto_increment();
 
474
    table->file->ha_release_auto_increment();
477
475
  if (!joins_freed)
478
476
    free_underlaid_joins(session, &session->lex->select_lex);
479
477
  session->abort_on_warning= 0;
480
 
  DRIZZLE_INSERT_DONE(1, 0);
481
 
  return true;
 
478
  DRIZZLE_INSERT_END();
 
479
  return(true);
482
480
}
483
481
 
484
482
 
654
652
  if (!select_insert)
655
653
  {
656
654
    TableList *duplicate;
657
 
    if ((duplicate= unique_table(table_list, table_list->next_global, true)))
 
655
    if ((duplicate= unique_table(session, table_list, table_list->next_global, 1)))
658
656
    {
659
657
      my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->alias);
660
658
 
697
695
    then both on update triggers will work instead. Similarly both on
698
696
    delete triggers will be invoked if we will delete conflicting records.
699
697
 
700
 
    Sets session->transaction.stmt.modified_non_trans_data to true if table which is updated didn't have
 
698
    Sets session->transaction.stmt.modified_non_trans_table to true if table which is updated didn't have
701
699
    transactions.
702
700
 
703
701
  RETURN VALUE
710
708
{
711
709
  int error;
712
710
  char *key=0;
713
 
  MyBitmap *save_read_set, *save_write_set;
714
 
  uint64_t prev_insert_id= table->cursor->next_insert_id;
 
711
  MY_BITMAP *save_read_set, *save_write_set;
 
712
  uint64_t prev_insert_id= table->file->next_insert_id;
715
713
  uint64_t insert_id_for_cur_row= 0;
716
714
 
717
715
 
721
719
 
722
720
  if (info->handle_duplicates == DUP_REPLACE || info->handle_duplicates == DUP_UPDATE)
723
721
  {
724
 
    while ((error=table->cursor->ha_write_row(table->record[0])))
 
722
    while ((error=table->file->ha_write_row(table->record[0])))
725
723
    {
726
724
      uint32_t key_nr;
727
725
      /*
731
729
        the autogenerated value to avoid session->insert_id_for_cur_row to become
732
730
        0.
733
731
      */
734
 
      if (table->cursor->insert_id_for_cur_row > 0)
735
 
        insert_id_for_cur_row= table->cursor->insert_id_for_cur_row;
 
732
      if (table->file->insert_id_for_cur_row > 0)
 
733
        insert_id_for_cur_row= table->file->insert_id_for_cur_row;
736
734
      else
737
 
        table->cursor->insert_id_for_cur_row= insert_id_for_cur_row;
 
735
        table->file->insert_id_for_cur_row= insert_id_for_cur_row;
738
736
      bool is_duplicate_key_error;
739
 
      if (table->cursor->is_fatal_error(error, HA_CHECK_DUP))
 
737
      if (table->file->is_fatal_error(error, HA_CHECK_DUP))
740
738
        goto err;
741
 
      is_duplicate_key_error= table->cursor->is_fatal_error(error, 0);
 
739
      is_duplicate_key_error= table->file->is_fatal_error(error, 0);
742
740
      if (!is_duplicate_key_error)
743
741
      {
744
742
        /*
750
748
          goto gok_or_after_err; /* Ignoring a not fatal error, return 0 */
751
749
        goto err;
752
750
      }
753
 
      if ((int) (key_nr = table->get_dup_key(error)) < 0)
 
751
      if ((int) (key_nr = table->file->get_dup_key(error)) < 0)
754
752
      {
755
753
        error= HA_ERR_FOUND_DUPP_KEY;         /* Database can't find key */
756
754
        goto err;
767
765
          key_nr == table->s->next_number_index &&
768
766
          (insert_id_for_cur_row > 0))
769
767
        goto err;
770
 
      if (table->cursor->getEngine()->check_flag(HTON_BIT_DUPLICATE_POS))
 
768
      if (table->file->ha_table_flags() & HA_DUPLICATE_POS)
771
769
      {
772
 
        if (table->cursor->rnd_pos(table->record[1],table->cursor->dup_ref))
 
770
        if (table->file->rnd_pos(table->record[1],table->file->dup_ref))
773
771
          goto err;
774
772
      }
775
773
      else
776
774
      {
777
 
        if (table->cursor->extra(HA_EXTRA_FLUSH_CACHE)) /* Not needed with NISAM */
 
775
        if (table->file->extra(HA_EXTRA_FLUSH_CACHE)) /* Not needed with NISAM */
778
776
        {
779
 
          error=errno;
 
777
          error=my_errno;
780
778
          goto err;
781
779
        }
782
780
 
789
787
          }
790
788
        }
791
789
        key_copy((unsigned char*) key,table->record[0],table->key_info+key_nr,0);
792
 
        if ((error=(table->cursor->index_read_idx_map(table->record[1],key_nr,
 
790
        if ((error=(table->file->index_read_idx_map(table->record[1],key_nr,
793
791
                                                    (unsigned char*) key, HA_WHOLE_KEY,
794
792
                                                    HA_READ_KEY_EXACT))))
795
793
          goto err;
811
809
                                                 info->ignore))
812
810
          goto before_err;
813
811
 
814
 
        table->cursor->restore_auto_increment(prev_insert_id);
 
812
        table->file->restore_auto_increment(prev_insert_id);
815
813
        if (table->next_number_field)
816
 
          table->cursor->adjust_next_insert_id_after_explicit_value(
 
814
          table->file->adjust_next_insert_id_after_explicit_value(
817
815
            table->next_number_field->val_int());
818
816
        info->touched++;
819
 
        if ((table->cursor->getEngine()->check_flag(HTON_BIT_PARTIAL_COLUMN_READ) &&
 
817
        if ((table->file->ha_table_flags() & HA_PARTIAL_COLUMN_READ &&
820
818
             !bitmap_is_subset(table->write_set, table->read_set)) ||
821
819
            table->compare_record())
822
820
        {
823
 
          if ((error=table->cursor->ha_update_row(table->record[1],
 
821
          if ((error=table->file->ha_update_row(table->record[1],
824
822
                                                table->record[0])) &&
825
823
              error != HA_ERR_RECORD_IS_THE_SAME)
826
824
          {
827
825
            if (info->ignore &&
828
 
                !table->cursor->is_fatal_error(error, HA_CHECK_DUP_KEY))
 
826
                !table->file->is_fatal_error(error, HA_CHECK_DUP_KEY))
829
827
            {
830
828
              goto gok_or_after_err;
831
829
            }
843
841
            Except if LAST_INSERT_ID(#) was in the INSERT query, which is
844
842
            handled separately by Session::arg_of_last_insert_id_function.
845
843
          */
846
 
          insert_id_for_cur_row= table->cursor->insert_id_for_cur_row= 0;
 
844
          insert_id_for_cur_row= table->file->insert_id_for_cur_row= 0;
847
845
          info->copied++;
848
846
        }
849
847
 
850
848
        if (table->next_number_field)
851
 
          table->cursor->adjust_next_insert_id_after_explicit_value(
 
849
          table->file->adjust_next_insert_id_after_explicit_value(
852
850
            table->next_number_field->val_int());
853
851
        info->touched++;
854
852
 
871
869
          ON UPDATE triggers.
872
870
        */
873
871
        if (last_uniq_key(table,key_nr) &&
874
 
            !table->cursor->referenced_by_foreign_key() &&
 
872
            !table->file->referenced_by_foreign_key() &&
875
873
            (table->timestamp_field_type == TIMESTAMP_NO_AUTO_SET ||
876
874
             table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_BOTH))
877
875
        {
878
 
          if ((error=table->cursor->ha_update_row(table->record[1],
 
876
          if ((error=table->file->ha_update_row(table->record[1],
879
877
                                                table->record[0])) &&
880
878
              error != HA_ERR_RECORD_IS_THE_SAME)
881
879
            goto err;
883
881
            info->deleted++;
884
882
          else
885
883
            error= 0;
886
 
          session->record_first_successful_insert_id_in_cur_stmt(table->cursor->insert_id_for_cur_row);
 
884
          session->record_first_successful_insert_id_in_cur_stmt(table->file->insert_id_for_cur_row);
887
885
          /*
888
886
            Since we pretend that we have done insert we should call
889
887
            its after triggers.
892
890
        }
893
891
        else
894
892
        {
895
 
          if ((error=table->cursor->ha_delete_row(table->record[1])))
 
893
          if ((error=table->file->ha_delete_row(table->record[1])))
896
894
            goto err;
897
895
          info->deleted++;
898
 
          if (!table->cursor->has_transactions())
899
 
            session->transaction.stmt.markModifiedNonTransData();
 
896
          if (!table->file->has_transactions())
 
897
            session->transaction.stmt.modified_non_trans_table= true;
900
898
          /* Let us attempt do write_row() once more */
901
899
        }
902
900
      }
903
901
    }
904
 
    session->record_first_successful_insert_id_in_cur_stmt(table->cursor->insert_id_for_cur_row);
 
902
    session->record_first_successful_insert_id_in_cur_stmt(table->file->insert_id_for_cur_row);
905
903
    /*
906
904
      Restore column maps if they where replaced during an duplicate key
907
905
      problem.
910
908
        table->write_set != save_write_set)
911
909
      table->column_bitmaps_set(save_read_set, save_write_set);
912
910
  }
913
 
  else if ((error=table->cursor->ha_write_row(table->record[0])))
 
911
  else if ((error=table->file->ha_write_row(table->record[0])))
914
912
  {
915
913
    if (!info->ignore ||
916
 
        table->cursor->is_fatal_error(error, HA_CHECK_DUP))
 
914
        table->file->is_fatal_error(error, HA_CHECK_DUP))
917
915
      goto err;
918
 
    table->cursor->restore_auto_increment(prev_insert_id);
 
916
    table->file->restore_auto_increment(prev_insert_id);
919
917
    goto gok_or_after_err;
920
918
  }
921
919
 
922
920
after_n_copied_inc:
923
921
  info->copied++;
924
 
  session->record_first_successful_insert_id_in_cur_stmt(table->cursor->insert_id_for_cur_row);
 
922
  session->record_first_successful_insert_id_in_cur_stmt(table->file->insert_id_for_cur_row);
925
923
 
926
924
gok_or_after_err:
927
925
  if (key)
928
926
    free(key);
929
 
  if (!table->cursor->has_transactions())
930
 
    session->transaction.stmt.markModifiedNonTransData();
 
927
  if (!table->file->has_transactions())
 
928
    session->transaction.stmt.modified_non_trans_table= true;
931
929
  return(0);
932
930
 
933
931
err:
935
933
  /* current_select is NULL if this is a delayed insert */
936
934
  if (session->lex->current_select)
937
935
    session->lex->current_select->no_error= 0;        // Give error
938
 
  table->print_error(error,MYF(0));
 
936
  table->file->print_error(error,MYF(0));
939
937
 
940
938
before_err:
941
 
  table->cursor->restore_auto_increment(prev_insert_id);
 
939
  table->file->restore_auto_increment(prev_insert_id);
942
940
  if (key)
943
941
    free(key);
944
942
  table->column_bitmaps_set(save_read_set, save_write_set);
1153
1151
    Is table which we are changing used somewhere in other parts of
1154
1152
    query
1155
1153
  */
1156
 
  if (unique_table(table_list, table_list->next_global))
 
1154
  if (unique_table(session, table_list, table_list->next_global, 0))
1157
1155
  {
1158
1156
    /* Using same table for INSERT and SELECT */
1159
1157
    lex->current_select->options|= OPTION_BUFFER_RESULT;
1170
1168
      We won't start bulk inserts at all if this statement uses functions or
1171
1169
      should invoke triggers since they may access to the same table too.
1172
1170
    */
1173
 
    table->cursor->ha_start_bulk_insert((ha_rows) 0);
 
1171
    table->file->ha_start_bulk_insert((ha_rows) 0);
1174
1172
  }
1175
1173
  table->restoreRecordAsDefault();              // Get empty record
1176
1174
  table->next_number_field=table->found_next_number_field;
1177
1175
 
1178
1176
  session->cuted_fields=0;
1179
1177
  if (info.ignore || info.handle_duplicates != DUP_ERROR)
1180
 
    table->cursor->extra(HA_EXTRA_IGNORE_DUP_KEY);
 
1178
    table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
1181
1179
  if (info.handle_duplicates == DUP_REPLACE)
1182
 
    table->cursor->extra(HA_EXTRA_WRITE_CAN_REPLACE);
 
1180
    table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE);
1183
1181
  if (info.handle_duplicates == DUP_UPDATE)
1184
 
    table->cursor->extra(HA_EXTRA_INSERT_WITH_UPDATE);
 
1182
    table->file->extra(HA_EXTRA_INSERT_WITH_UPDATE);
1185
1183
  session->abort_on_warning= !info.ignore;
1186
1184
  table->mark_columns_needed_for_insert();
1187
1185
 
1210
1208
{
1211
1209
 
1212
1210
  if (session->lex->current_select->options & OPTION_BUFFER_RESULT)
1213
 
    table->cursor->ha_start_bulk_insert((ha_rows) 0);
 
1211
    table->file->ha_start_bulk_insert((ha_rows) 0);
1214
1212
  return(0);
1215
1213
}
1216
1214
 
1228
1226
  {
1229
1227
    table->next_number_field=0;
1230
1228
    table->auto_increment_field_not_null= false;
1231
 
    table->cursor->ha_reset();
 
1229
    table->file->ha_reset();
1232
1230
  }
1233
1231
  session->count_cuted_fields= CHECK_FIELD_IGNORE;
1234
1232
  session->abort_on_warning= 0;
1254
1252
    return(1);
1255
1253
 
1256
1254
  // Release latches in case bulk insert takes a long time
1257
 
  plugin::TransactionalStorageEngine::releaseTemporaryLatches(session);
 
1255
  ha_release_temporary_latches(session);
1258
1256
 
1259
1257
  error= write_record(session, table, &info);
1260
1258
 
1295
1293
void select_insert::store_values(List<Item> &values)
1296
1294
{
1297
1295
  if (fields->elements)
1298
 
    fill_record(session, *fields, values, true);
 
1296
    fill_record(session, *fields, values, 1);
1299
1297
  else
1300
 
    fill_record(session, table->field, values, true);
 
1298
    fill_record(session, table->field, values, 1);
1301
1299
}
1302
1300
 
1303
1301
void select_insert::send_error(uint32_t errcode,const char *err)
1313
1311
bool select_insert::send_eof()
1314
1312
{
1315
1313
  int error;
1316
 
  bool const trans_table= table->cursor->has_transactions();
 
1314
  bool const trans_table= table->file->has_transactions();
1317
1315
  uint64_t id;
1318
1316
  bool changed;
1319
1317
 
1320
 
  error= table->cursor->ha_end_bulk_insert();
1321
 
  table->cursor->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
1322
 
  table->cursor->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
 
1318
  error= table->file->ha_end_bulk_insert();
 
1319
  table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
 
1320
  table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
1323
1321
 
1324
1322
  if ((changed= (info.copied || info.deleted || info.updated)))
1325
1323
  {
1327
1325
      We must invalidate the table in the query cache before binlog writing
1328
1326
      and ha_autocommit_or_rollback.
1329
1327
    */
1330
 
    if (session->transaction.stmt.hasModifiedNonTransData())
1331
 
      session->transaction.all.markModifiedNonTransData();
 
1328
    if (session->transaction.stmt.modified_non_trans_table)
 
1329
      session->transaction.all.modified_non_trans_table= true;
1332
1330
  }
1333
1331
  assert(trans_table || !changed ||
1334
 
              session->transaction.stmt.hasModifiedNonTransData());
 
1332
              session->transaction.stmt.modified_non_trans_table);
1335
1333
 
1336
 
  table->cursor->ha_release_auto_increment();
 
1334
  table->file->ha_release_auto_increment();
1337
1335
 
1338
1336
  if (error)
1339
1337
  {
1340
 
    table->print_error(error,MYF(0));
1341
 
    DRIZZLE_INSERT_SELECT_DONE(error, 0);
1342
 
    return 1;
 
1338
    table->file->print_error(error,MYF(0));
 
1339
    return(1);
1343
1340
  }
1344
1341
  char buff[160];
1345
1342
  if (info.ignore)
1346
 
    snprintf(buff, sizeof(buff), ER(ER_INSERT_INFO), (ulong) info.records,
 
1343
    sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records,
1347
1344
            (ulong) (info.records - info.copied), (ulong) session->cuted_fields);
1348
1345
  else
1349
 
    snprintf(buff, sizeof(buff), ER(ER_INSERT_INFO), (ulong) info.records,
 
1346
    sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records,
1350
1347
            (ulong) (info.deleted+info.updated), (ulong) session->cuted_fields);
1351
1348
  session->row_count_func= info.copied + info.deleted + info.updated;
1352
1349
 
1357
1354
     (info.copied ? autoinc_value_of_last_inserted_row : 0));
1358
1355
  session->my_ok((ulong) session->row_count_func,
1359
1356
                 info.copied + info.deleted + info.touched, id, buff);
1360
 
  DRIZZLE_INSERT_SELECT_DONE(0, session->row_count_func);
1361
 
  return 0;
 
1357
  return(0);
1362
1358
}
1363
1359
 
1364
1360
void select_insert::abort() {
1374
1370
  {
1375
1371
    bool changed, transactional_table;
1376
1372
 
1377
 
    table->cursor->ha_end_bulk_insert();
 
1373
    table->file->ha_end_bulk_insert();
1378
1374
 
1379
1375
    /*
1380
1376
      If at least one row has been inserted/modified and will stay in
1391
1387
      zero, so no check for that is made.
1392
1388
    */
1393
1389
    changed= (info.copied || info.deleted || info.updated);
1394
 
    transactional_table= table->cursor->has_transactions();
 
1390
    transactional_table= table->file->has_transactions();
1395
1391
    assert(transactional_table || !changed ||
1396
 
                session->transaction.stmt.hasModifiedNonTransData());
1397
 
    table->cursor->ha_release_auto_increment();
1398
 
  }
1399
 
 
1400
 
  if (DRIZZLE_INSERT_SELECT_DONE_ENABLED())
1401
 
  {
1402
 
    DRIZZLE_INSERT_SELECT_DONE(0, info.copied + info.deleted + info.updated);
 
1392
                session->transaction.stmt.modified_non_trans_table);
 
1393
    table->file->ha_release_auto_increment();
1403
1394
  }
1404
1395
 
1405
1396
  return;
1454
1445
 
1455
1446
static Table *create_table_from_items(Session *session, HA_CREATE_INFO *create_info,
1456
1447
                                      TableList *create_table,
1457
 
                                      message::Table &table_proto,
1458
 
                                      AlterInfo *alter_info,
 
1448
                                      drizzled::message::Table *table_proto,
 
1449
                                      Alter_info *alter_info,
1459
1450
                                      List<Item> *items,
1460
 
                                      bool is_if_not_exists,
1461
 
                                      DRIZZLE_LOCK **lock,
1462
 
                                      TableIdentifier &identifier)
 
1451
                                      DRIZZLE_LOCK **lock)
1463
1452
{
1464
1453
  Table tmp_table;              // Used during 'CreateField()'
1465
1454
  TableShare share;
1471
1460
  Field *tmp_field;
1472
1461
  bool not_used;
1473
1462
 
1474
 
  if (not (identifier.isTmp()) && create_table->table->db_stat)
 
1463
  if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
 
1464
      create_table->table->db_stat)
1475
1465
  {
1476
1466
    /* Table already exists and was open at openTablesLock() stage. */
1477
 
    if (is_if_not_exists)
 
1467
    if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
1478
1468
    {
1479
1469
      create_info->table_existed= 1;            // Mark that table existed
1480
1470
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1493
1483
 
1494
1484
  tmp_table.s->db_create_options=0;
1495
1485
  tmp_table.s->blob_ptr_size= portable_sizeof_char_ptr;
1496
 
 
1497
 
  if (not table_proto.engine().name().compare("MyISAM"))
1498
 
    tmp_table.s->db_low_byte_first= true;
1499
 
  else if (not table_proto.engine().name().compare("MEMORY"))
1500
 
    tmp_table.s->db_low_byte_first= true;
1501
 
 
 
1486
  tmp_table.s->db_low_byte_first=
 
1487
        test(create_info->db_type == myisam_engine ||
 
1488
             create_info->db_type == heap_engine);
1502
1489
  tmp_table.null_row= false;
1503
1490
  tmp_table.maybe_null= false;
1504
1491
 
1513
1500
        field= item->tmp_table_field_from_field_type(&tmp_table, 0);
1514
1501
    else
1515
1502
      field= create_tmp_field(session, &tmp_table, item, item->type(),
1516
 
                              (Item ***) 0, &tmp_field, &def_field, false,
1517
 
                              false, false, 0);
 
1503
                              (Item ***) 0, &tmp_field, &def_field, 0, 0, 0, 0,
 
1504
                              0);
1518
1505
    if (!field ||
1519
1506
        !(cr_field=new CreateField(field,(item->type() == Item::FIELD_ITEM ?
1520
1507
                                           ((Item_field *)item)->field :
1533
1520
    should not cause deadlocks or races.
1534
1521
  */
1535
1522
  {
1536
 
    if (not mysql_create_table_no_lock(session,
1537
 
                                       identifier,
1538
 
                                       create_info,
1539
 
                                       table_proto,
1540
 
                                       alter_info,
1541
 
                                       false,
1542
 
                                       select_field_count,
1543
 
                                       is_if_not_exists))
 
1523
    if (!mysql_create_table_no_lock(session, create_table->db,
 
1524
                                    create_table->table_name,
 
1525
                                    create_info,
 
1526
                                    table_proto,
 
1527
                                    alter_info, false,
 
1528
                                    select_field_count))
1544
1529
    {
1545
 
      if (create_info->table_existed && not identifier.isTmp())
 
1530
      if (create_info->table_existed &&
 
1531
          !(create_info->options & HA_LEX_CREATE_TMP_TABLE))
1546
1532
      {
1547
1533
        /*
1548
1534
          This means that someone created table underneath server
1553
1539
        return NULL;
1554
1540
      }
1555
1541
 
1556
 
      if (not identifier.isTmp())
 
1542
      if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
1557
1543
      {
1558
1544
        pthread_mutex_lock(&LOCK_open); /* CREATE TABLE... has found that the table already exists for insert and is adapting to use it */
1559
1545
        if (session->reopen_name_locked_table(create_table, false))
1560
1546
        {
1561
 
          quick_rm_table(*session, identifier);
 
1547
          quick_rm_table(create_info->db_type, create_table->db,
 
1548
                         create_table->table_name, false);
1562
1549
        }
1563
1550
        else
1564
1551
          table= create_table->table;
1566
1553
      }
1567
1554
      else
1568
1555
      {
1569
 
        if (not (table= session->openTable(create_table, (bool*) 0,
1570
 
                                           DRIZZLE_OPEN_TEMPORARY_ONLY)) &&
1571
 
            not create_info->table_existed)
 
1556
        if (!(table= session->openTable(create_table, (bool*) 0,
 
1557
                                         DRIZZLE_OPEN_TEMPORARY_ONLY)) &&
 
1558
            !create_info->table_existed)
1572
1559
        {
1573
1560
          /*
1574
1561
            This shouldn't happen as creation of temporary table should make
1593
1580
      *lock= 0;
1594
1581
    }
1595
1582
 
1596
 
    if (not create_info->table_existed)
1597
 
      session->drop_open_table(table, identifier);
 
1583
    if (!create_info->table_existed)
 
1584
      session->drop_open_table(table, create_table->db, create_table->table_name);
1598
1585
    return NULL;
1599
1586
  }
1600
1587
 
1607
1594
{
1608
1595
  DRIZZLE_LOCK *extra_lock= NULL;
1609
1596
  /*
1610
 
    For replication, the CREATE-SELECT statement is written
1611
 
    in two pieces: the first transaction messsage contains 
1612
 
    the CREATE TABLE statement as a CreateTableStatement message
1613
 
    necessary to create the table.
1614
 
    
1615
 
    The second transaction message contains all the InsertStatement
1616
 
    and associated InsertRecords that should go into the table.
 
1597
    For row-based replication, the CREATE-SELECT statement is written
 
1598
    in two pieces: the first one contain the CREATE TABLE statement
 
1599
    necessary to create the table and the second part contain the rows
 
1600
    that should go into the table.
 
1601
 
 
1602
    For non-temporary tables, the start of the CREATE-SELECT
 
1603
    implicitly commits the previous transaction, and all events
 
1604
    forming the statement will be stored the transaction cache. At end
 
1605
    of the statement, the entire statement is committed as a
 
1606
    transaction, and all events are written to the binary log.
 
1607
 
 
1608
    On the master, the table is locked for the duration of the
 
1609
    statement, but since the CREATE part is replicated as a simple
 
1610
    statement, there is no way to lock the table for accesses on the
 
1611
    slave.  Hence, we have to hold on to the CREATE part of the
 
1612
    statement until the statement has finished.
1617
1613
   */
1618
1614
 
1619
1615
  unit= u;
1620
1616
 
1621
 
  if (not (table= create_table_from_items(session, create_info, create_table,
1622
 
                                          table_proto,
1623
 
                                          alter_info, &values,
1624
 
                                          is_if_not_exists,
1625
 
                                          &extra_lock, identifier)))
 
1617
  /*
 
1618
    Start a statement transaction before the create if we are using
 
1619
    row-based replication for the statement.  If we are creating a
 
1620
    temporary table, we need to start a statement transaction.
 
1621
  */
 
1622
 
 
1623
  if (!(table= create_table_from_items(session, create_info, create_table,
 
1624
                                       table_proto,
 
1625
                                       alter_info, &values,
 
1626
                                       &extra_lock)))
1626
1627
    return(-1);                         // abort() deletes table
1627
1628
 
1628
1629
  if (extra_lock)
1629
1630
  {
1630
1631
    assert(m_plock == NULL);
1631
1632
 
1632
 
    if (identifier.isTmp())
 
1633
    if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
1633
1634
      m_plock= &m_lock;
1634
1635
    else
1635
1636
      m_plock= &session->extra_lock;
1657
1658
  table->restoreRecordAsDefault();      // Get empty record
1658
1659
  session->cuted_fields=0;
1659
1660
  if (info.ignore || info.handle_duplicates != DUP_ERROR)
1660
 
    table->cursor->extra(HA_EXTRA_IGNORE_DUP_KEY);
 
1661
    table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
1661
1662
  if (info.handle_duplicates == DUP_REPLACE)
1662
 
    table->cursor->extra(HA_EXTRA_WRITE_CAN_REPLACE);
 
1663
    table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE);
1663
1664
  if (info.handle_duplicates == DUP_UPDATE)
1664
 
    table->cursor->extra(HA_EXTRA_INSERT_WITH_UPDATE);
1665
 
  table->cursor->ha_start_bulk_insert((ha_rows) 0);
 
1665
    table->file->extra(HA_EXTRA_INSERT_WITH_UPDATE);
 
1666
  table->file->ha_start_bulk_insert((ha_rows) 0);
1666
1667
  session->abort_on_warning= !info.ignore;
1667
1668
  if (check_that_all_fields_are_given_values(session, table, table_list))
1668
1669
    return(1);
1669
1670
  table->mark_columns_needed_for_insert();
1670
 
  table->cursor->extra(HA_EXTRA_WRITE_CACHE);
 
1671
  table->file->extra(HA_EXTRA_WRITE_CACHE);
1671
1672
  return(0);
1672
1673
}
1673
1674
 
1674
1675
void select_create::store_values(List<Item> &values)
1675
1676
{
1676
 
  fill_record(session, field, values, true);
 
1677
  fill_record(session, field, values, 1);
1677
1678
}
1678
1679
 
1679
1680
 
1680
1681
void select_create::send_error(uint32_t errcode,const char *err)
1681
1682
{
 
1683
 
 
1684
 
1682
1685
  /*
1683
1686
    This will execute any rollbacks that are necessary before writing
1684
1687
    the transcation cache.
1710
1713
    */
1711
1714
    if (!table->s->tmp_table)
1712
1715
    {
1713
 
      TransactionServices &transaction_services= TransactionServices::singleton();
1714
 
      transaction_services.ha_autocommit_or_rollback(session, 0);
 
1716
      ha_autocommit_or_rollback(session, 0);
1715
1717
      (void) session->endActiveTransaction();
1716
1718
    }
1717
1719
 
1718
 
    table->cursor->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
1719
 
    table->cursor->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
 
1720
    table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
 
1721
    table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
1720
1722
    if (m_plock)
1721
1723
    {
1722
1724
      mysql_unlock_tables(session, *m_plock);
1730
1732
 
1731
1733
void select_create::abort()
1732
1734
{
 
1735
 
 
1736
 
1733
1737
  /*
1734
1738
    In select_insert::abort() we roll back the statement, including
1735
1739
    truncating the transaction cache of the binary log. To do this, we
1746
1750
    log state.
1747
1751
  */
1748
1752
  select_insert::abort();
 
1753
  session->transaction.stmt.modified_non_trans_table= false;
 
1754
 
1749
1755
 
1750
1756
  if (m_plock)
1751
1757
  {
1756
1762
 
1757
1763
  if (table)
1758
1764
  {
1759
 
    table->cursor->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
1760
 
    table->cursor->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
1761
 
    if (not create_info->table_existed)
1762
 
      session->drop_open_table(table, identifier);
 
1765
    table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
 
1766
    table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
 
1767
    if (!create_info->table_existed)
 
1768
      session->drop_open_table(table, create_table->db, create_table->table_name);
1763
1769
    table= NULL;                                    // Safety
1764
1770
  }
1765
1771
}
1766
1772
 
1767
 
} /* namespace drizzled */
 
1773
 
 
1774
/*****************************************************************************
 
1775
  Instansiate templates
 
1776
*****************************************************************************/
 
1777
 
 
1778
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
 
1779
template class List_iterator_fast<List_item>;
 
1780
#endif /* HAVE_EXPLICIT_TEMPLATE_INSTANTIATION */