~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_insert.cc

  • Committer: Monty Taylor
  • Date: 2010-12-03 19:56:07 UTC
  • mto: (1975.1.1 build)
  • mto: This revision was merged to the branch mainline in revision 1976.
  • Revision ID: mordred@inaugust.com-20101203195607-yw50aynlw04dt5k6
All protocol stuff except for the buffer_length. WTF?

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
#include <drizzled/probes.h>
26
26
#include <drizzled/sql_base.h>
27
27
#include <drizzled/sql_load.h>
28
 
#include <drizzled/field/epoch.h>
 
28
#include <drizzled/field/timestamp.h>
29
29
#include <drizzled/lock.h>
30
30
#include "drizzled/sql_table.h"
31
31
#include "drizzled/pthread_globals.h"
129
129
      }
130
130
      else
131
131
      {
132
 
        table->setWriteSet(table->timestamp_field->position());
 
132
        table->setWriteSet(table->timestamp_field->field_index);
133
133
      }
134
134
    }
135
135
  }
170
170
      Unmark the timestamp field so that we can check if this is modified
171
171
      by update_fields
172
172
    */
173
 
    timestamp_mark= table->write_set->test(table->timestamp_field->position());
174
 
    table->write_set->reset(table->timestamp_field->position());
 
173
    timestamp_mark= table->write_set->test(table->timestamp_field->field_index);
 
174
    table->write_set->reset(table->timestamp_field->field_index);
175
175
  }
176
176
 
177
177
  /* Check the fields we are going to modify */
189
189
 
190
190
    if (timestamp_mark)
191
191
    {
192
 
      table->setWriteSet(table->timestamp_field->position());
 
192
      table->setWriteSet(table->timestamp_field->field_index);
193
193
    }
194
194
  }
195
195
  return 0;
227
227
  end of dispatch_command().
228
228
*/
229
229
 
230
 
bool insert_query(Session *session,TableList *table_list,
 
230
bool mysql_insert(Session *session,TableList *table_list,
231
231
                  List<Item> &fields,
232
232
                  List<List_item> &values_list,
233
233
                  List<Item> &update_fields,
271
271
  values= its++;
272
272
  value_count= values->elements;
273
273
 
274
 
  if (prepare_insert(session, table_list, table, fields, values,
 
274
  if (mysql_prepare_insert(session, table_list, table, fields, values,
275
275
                           update_fields, update_values, duplic, &unused_conds,
276
276
                           false,
277
277
                           (fields.elements || !value_count ||
281
281
      table->cursor->ha_release_auto_increment();
282
282
    if (!joins_freed)
283
283
      free_underlaid_joins(session, &session->lex->select_lex);
284
 
    session->setAbortOnWarning(false);
 
284
    session->abort_on_warning= 0;
285
285
    DRIZZLE_INSERT_DONE(1, 0);
286
286
    return true;
287
287
  }
320
320
        table->cursor->ha_release_auto_increment();
321
321
      if (!joins_freed)
322
322
        free_underlaid_joins(session, &session->lex->select_lex);
323
 
      session->setAbortOnWarning(false);
 
323
      session->abort_on_warning= 0;
324
324
      DRIZZLE_INSERT_DONE(1, 0);
325
325
 
326
326
      return true;
331
331
        table->cursor->ha_release_auto_increment();
332
332
      if (!joins_freed)
333
333
        free_underlaid_joins(session, &session->lex->select_lex);
334
 
      session->setAbortOnWarning(false);
 
334
      session->abort_on_warning= 0;
335
335
      DRIZZLE_INSERT_DONE(1, 0);
336
336
      return true;
337
337
    }
372
372
  }
373
373
 
374
374
 
375
 
  session->setAbortOnWarning(not ignore);
 
375
  session->abort_on_warning= !ignore;
376
376
 
377
377
  table->mark_columns_needed_for_insert();
378
378
 
483
483
      table->cursor->ha_release_auto_increment();
484
484
    if (!joins_freed)
485
485
      free_underlaid_joins(session, &session->lex->select_lex);
486
 
    session->setAbortOnWarning(false);
 
486
    session->abort_on_warning= 0;
487
487
    DRIZZLE_INSERT_DONE(1, 0);
488
488
    return true;
489
489
  }
492
492
                                    !session->cuted_fields))
493
493
  {
494
494
    session->row_count_func= info.copied + info.deleted + info.updated;
495
 
    session->my_ok((ulong) session->rowCount(),
 
495
    session->my_ok((ulong) session->row_count_func,
496
496
                   info.copied + info.deleted + info.touched, id);
497
497
  }
498
498
  else
505
505
      snprintf(buff, sizeof(buff), ER(ER_INSERT_INFO), (ulong) info.records,
506
506
              (ulong) (info.deleted + info.updated), (ulong) session->cuted_fields);
507
507
    session->row_count_func= info.copied + info.deleted + info.updated;
508
 
    session->my_ok((ulong) session->rowCount(),
 
508
    session->my_ok((ulong) session->row_count_func,
509
509
                   info.copied + info.deleted + info.touched, id, buff);
510
510
  }
511
 
  session->status_var.inserted_row_count+= session->rowCount();
512
 
  session->setAbortOnWarning(false);
513
 
  DRIZZLE_INSERT_DONE(0, session->rowCount());
 
511
  session->status_var.inserted_row_count+= session->row_count_func;
 
512
  session->abort_on_warning= 0;
 
513
  DRIZZLE_INSERT_DONE(0, session->row_count_func);
514
514
 
515
515
  return false;
516
516
}
520
520
  Check if table can be updated
521
521
 
522
522
  SYNOPSIS
523
 
     prepare_insert_check_table()
 
523
     mysql_prepare_insert_check_table()
524
524
     session            Thread handle
525
525
     table_list         Table list
526
526
     fields             List of fields to be updated
532
532
     true  ERROR
533
533
*/
534
534
 
535
 
static bool prepare_insert_check_table(Session *session, TableList *table_list,
 
535
static bool mysql_prepare_insert_check_table(Session *session, TableList *table_list,
536
536
                                             List<Item> &,
537
537
                                             bool select_insert)
538
538
{
560
560
  Prepare items in INSERT statement
561
561
 
562
562
  SYNOPSIS
563
 
    prepare_insert()
 
563
    mysql_prepare_insert()
564
564
    session                     Thread handler
565
565
    table_list          Global/local table list
566
566
    table               Table to insert into (can be NULL if table should
587
587
    true  error
588
588
*/
589
589
 
590
 
bool prepare_insert(Session *session, TableList *table_list,
 
590
bool mysql_prepare_insert(Session *session, TableList *table_list,
591
591
                          Table *table, List<Item> &fields, List_item *values,
592
592
                          List<Item> &update_fields, List<Item> &update_values,
593
593
                          enum_duplicates duplic,
610
610
    inserting (for INSERT ... SELECT this is done by changing table_list,
611
611
    because INSERT ... SELECT share Select_Lex it with SELECT.
612
612
  */
613
 
  if (not select_insert)
 
613
  if (!select_insert)
614
614
  {
615
615
    for (Select_Lex_Unit *un= select_lex->first_inner_unit();
616
616
         un;
632
632
      return(true);
633
633
  }
634
634
 
635
 
  if (prepare_insert_check_table(session, table_list, fields, select_insert))
 
635
  if (mysql_prepare_insert_check_table(session, table_list, fields, select_insert))
636
636
    return(true);
637
637
 
638
638
 
658
658
 
659
659
    if (!res && check_fields)
660
660
    {
661
 
      bool saved_abort_on_warning= session->abortOnWarning();
662
 
 
663
 
      session->setAbortOnWarning(abort_on_warning);
 
661
      bool saved_abort_on_warning= session->abort_on_warning;
 
662
      session->abort_on_warning= abort_on_warning;
664
663
      res= check_that_all_fields_are_given_values(session,
665
664
                                                  table ? table :
666
665
                                                  context->table_list->table,
667
666
                                                  context->table_list);
668
 
      session->setAbortOnWarning(saved_abort_on_warning);
 
667
      session->abort_on_warning= saved_abort_on_warning;
669
668
    }
670
669
 
671
670
    if (!res && duplic == DUP_UPDATE)
676
675
    /* Restore the current context. */
677
676
    ctx_state.restore_state(context, table_list);
678
677
 
679
 
    if (not res)
 
678
    if (!res)
680
679
      res= setup_fields(session, 0, update_values, MARK_COLUMNS_READ, 0, 0);
681
680
  }
682
681
 
683
682
  if (res)
684
683
    return(res);
685
684
 
686
 
  if (not table)
 
685
  if (!table)
687
686
    table= table_list->table;
688
687
 
689
 
  if (not select_insert)
 
688
  if (!select_insert)
690
689
  {
691
690
    TableList *duplicate;
692
691
    if ((duplicate= unique_table(table_list, table_list->next_global, true)))
696
695
      return true;
697
696
    }
698
697
  }
699
 
 
700
698
  if (duplic == DUP_UPDATE || duplic == DUP_REPLACE)
701
699
    table->prepare_for_position();
702
700
 
848
846
          table->cursor->adjust_next_insert_id_after_explicit_value(
849
847
            table->next_number_field->val_int());
850
848
        info->touched++;
851
 
 
852
 
        if (! table->records_are_comparable() || table->compare_records())
 
849
        if ((table->cursor->getEngine()->check_flag(HTON_BIT_PARTIAL_COLUMN_READ) &&
 
850
            ! table->write_set->is_subset_of(*table->read_set)) ||
 
851
            table->compare_record())
853
852
        {
854
853
          if ((error=table->cursor->updateRecord(table->getUpdateRecord(),
855
854
                                                table->getInsertRecord())) &&
870
869
          /*
871
870
            If ON DUP KEY UPDATE updates a row instead of inserting one, it's
872
871
            like a regular UPDATE statement: it should not affect the value of a
873
 
            next SELECT LAST_INSERT_ID() or insert_id().
 
872
            next SELECT LAST_INSERT_ID() or mysql_insert_id().
874
873
            Except if LAST_INSERT_ID(#) was in the INSERT query, which is
875
874
            handled separately by Session::arg_of_last_insert_id_function.
876
875
          */
1016
1015
      }
1017
1016
    }
1018
1017
  }
1019
 
  return session->abortOnWarning() ? err : 0;
 
1018
  return session->abort_on_warning ? err : 0;
1020
1019
}
1021
1020
 
1022
1021
/***************************************************************************
1028
1027
  make insert specific preparation and checks after opening tables
1029
1028
 
1030
1029
  SYNOPSIS
1031
 
    insert_select_prepare()
 
1030
    mysql_insert_select_prepare()
1032
1031
    session         thread handler
1033
1032
 
1034
1033
  RETURN
1036
1035
    true  Error
1037
1036
*/
1038
1037
 
1039
 
bool insert_select_prepare(Session *session)
 
1038
bool mysql_insert_select_prepare(Session *session)
1040
1039
{
1041
1040
  LEX *lex= session->lex;
1042
1041
  Select_Lex *select_lex= &lex->select_lex;
1046
1045
    clause if table is VIEW
1047
1046
  */
1048
1047
 
1049
 
  if (prepare_insert(session, lex->query_tables,
 
1048
  if (mysql_prepare_insert(session, lex->query_tables,
1050
1049
                           lex->query_tables->table, lex->field_list, 0,
1051
1050
                           lex->update_list, lex->value_list,
1052
1051
                           lex->duplicates,
1105
1104
 
1106
1105
  if (!res && fields->elements)
1107
1106
  {
1108
 
    bool saved_abort_on_warning= session->abortOnWarning();
1109
 
    session->setAbortOnWarning(not info.ignore);
 
1107
    bool saved_abort_on_warning= session->abort_on_warning;
 
1108
    session->abort_on_warning= !info.ignore;
1110
1109
    res= check_that_all_fields_are_given_values(session, table_list->table,
1111
1110
                                                table_list);
1112
 
    session->setAbortOnWarning(saved_abort_on_warning);
 
1111
    session->abort_on_warning= saved_abort_on_warning;
1113
1112
  }
1114
1113
 
1115
1114
  if (info.handle_duplicates == DUP_UPDATE && !res)
1202
1201
  table->next_number_field=table->found_next_number_field;
1203
1202
 
1204
1203
  session->cuted_fields=0;
1205
 
 
1206
1204
  if (info.ignore || info.handle_duplicates != DUP_ERROR)
1207
1205
    table->cursor->extra(HA_EXTRA_IGNORE_DUP_KEY);
1208
 
 
1209
1206
  if (info.handle_duplicates == DUP_REPLACE)
1210
1207
    table->cursor->extra(HA_EXTRA_WRITE_CAN_REPLACE);
1211
 
 
1212
1208
  if (info.handle_duplicates == DUP_UPDATE)
1213
1209
    table->cursor->extra(HA_EXTRA_INSERT_WITH_UPDATE);
1214
 
 
1215
 
  session->setAbortOnWarning(not info.ignore);
 
1210
  session->abort_on_warning= !info.ignore;
1216
1211
  table->mark_columns_needed_for_insert();
1217
1212
 
1218
1213
 
1261
1256
    table->cursor->ha_reset();
1262
1257
  }
1263
1258
  session->count_cuted_fields= CHECK_FIELD_IGNORE;
1264
 
  session->setAbortOnWarning(false);
 
1259
  session->abort_on_warning= 0;
1265
1260
  return;
1266
1261
}
1267
1262
 
1274
1269
  if (unit->offset_limit_cnt)
1275
1270
  {                                             // using limit offset,count
1276
1271
    unit->offset_limit_cnt--;
1277
 
    return false;
 
1272
    return(0);
1278
1273
  }
1279
1274
 
1280
1275
  session->count_cuted_fields= CHECK_FIELD_WARN;        // Calculate cuted fields
1281
1276
  store_values(values);
1282
1277
  session->count_cuted_fields= CHECK_FIELD_IGNORE;
1283
1278
  if (session->is_error())
1284
 
    return true;
 
1279
  {
 
1280
    /*
 
1281
     * If we fail mid-way through INSERT..SELECT, we need to remove any
 
1282
     * records that we added to the current Statement message. We can
 
1283
     * use session->row_count to know how many records we have already added.
 
1284
     */
 
1285
    TransactionServices &ts= TransactionServices::singleton();
 
1286
    ts.removeStatementRecords(session, (session->row_count - 1));
 
1287
    return(1);
 
1288
  }
1285
1289
 
1286
1290
  // Release latches in case bulk insert takes a long time
1287
1291
  plugin::TransactionalStorageEngine::releaseTemporaryLatches(session);
1331
1335
    fill_record(session, table->getFields(), values, true);
1332
1336
}
1333
1337
 
1334
 
void select_insert::send_error(drizzled::error_t errcode,const char *err)
 
1338
void select_insert::send_error(uint32_t errcode,const char *err)
1335
1339
{
 
1340
 
 
1341
 
1336
1342
  my_message(errcode, err, MYF(0));
 
1343
 
 
1344
  return;
1337
1345
}
1338
1346
 
1339
1347
 
1382
1390
    (session->arg_of_last_insert_id_function ?
1383
1391
     session->first_successful_insert_id_in_prev_stmt :
1384
1392
     (info.copied ? autoinc_value_of_last_inserted_row : 0));
1385
 
  session->my_ok((ulong) session->rowCount(),
 
1393
  session->my_ok((ulong) session->row_count_func,
1386
1394
                 info.copied + info.deleted + info.touched, id, buff);
1387
 
  session->status_var.inserted_row_count+= session->rowCount(); 
1388
 
  DRIZZLE_INSERT_SELECT_DONE(0, session->rowCount());
 
1395
  session->status_var.inserted_row_count+= session->row_count_func; 
 
1396
  DRIZZLE_INSERT_SELECT_DONE(0, session->row_count_func);
1389
1397
  return 0;
1390
1398
}
1391
1399
 
1487
1495
                                      List<Item> *items,
1488
1496
                                      bool is_if_not_exists,
1489
1497
                                      DrizzleLock **lock,
1490
 
                                      identifier::Table::const_reference identifier)
 
1498
                                      TableIdentifier &identifier)
1491
1499
{
1492
1500
  TableShare share(message::Table::INTERNAL);
1493
1501
  uint32_t select_field_count= items->elements;
1495
1503
  List_iterator_fast<Item> it(*items);
1496
1504
  Item *item;
1497
1505
  Field *tmp_field;
 
1506
  bool not_used;
1498
1507
 
1499
1508
  if (not (identifier.isTmp()) && create_table->table->db_stat)
1500
1509
  {
1514
1523
 
1515
1524
  {
1516
1525
    table::Shell tmp_table(share);              // Used during 'CreateField()'
 
1526
    tmp_table.timestamp_field= 0;
 
1527
 
 
1528
    tmp_table.getMutableShare()->db_create_options= 0;
 
1529
    tmp_table.getMutableShare()->blob_ptr_size= portable_sizeof_char_ptr;
1517
1530
 
1518
1531
    if (not table_proto.engine().name().compare("MyISAM"))
1519
1532
      tmp_table.getMutableShare()->db_low_byte_first= true;
1520
1533
    else if (not table_proto.engine().name().compare("MEMORY"))
1521
1534
      tmp_table.getMutableShare()->db_low_byte_first= true;
1522
1535
 
 
1536
    tmp_table.null_row= false;
 
1537
    tmp_table.maybe_null= false;
 
1538
 
1523
1539
    tmp_table.in_use= session;
1524
1540
 
1525
1541
    while ((item=it++))
1570
1586
  */
1571
1587
  Table *table= 0;
1572
1588
  {
1573
 
    if (not create_table_no_lock(session,
1574
 
                                 identifier,
1575
 
                                 create_info,
1576
 
                                 table_proto,
1577
 
                                 alter_info,
1578
 
                                 false,
1579
 
                                 select_field_count,
1580
 
                                 is_if_not_exists))
 
1589
    if (not mysql_create_table_no_lock(session,
 
1590
                                       identifier,
 
1591
                                       create_info,
 
1592
                                       table_proto,
 
1593
                                       alter_info,
 
1594
                                       false,
 
1595
                                       select_field_count,
 
1596
                                       is_if_not_exists))
1581
1597
    {
1582
1598
      if (create_info->table_existed && not identifier.isTmp())
1583
1599
      {
1601
1617
 
1602
1618
          if (concurrent_table->reopen_name_locked_table(create_table, session))
1603
1619
          {
1604
 
            (void)plugin::StorageEngine::dropTable(*session, identifier);
 
1620
            plugin::StorageEngine::dropTable(*session, identifier);
1605
1621
          }
1606
1622
          else
1607
1623
          {
1610
1626
        }
1611
1627
        else
1612
1628
        {
1613
 
          (void)plugin::StorageEngine::dropTable(*session, identifier);
 
1629
          plugin::StorageEngine::dropTable(*session, identifier);
1614
1630
        }
1615
1631
      }
1616
1632
      else
1633
1649
  }
1634
1650
 
1635
1651
  table->reginfo.lock_type=TL_WRITE;
1636
 
  if (not ((*lock)= session->lockTables(&table, 1, DRIZZLE_LOCK_IGNORE_FLUSH)))
 
1652
  if (! ((*lock)= session->lockTables(&table, 1, DRIZZLE_LOCK_IGNORE_FLUSH, &not_used)))
1637
1653
  {
1638
1654
    if (*lock)
1639
1655
    {
1698
1714
 
1699
1715
  /* Mark all fields that are given values */
1700
1716
  for (Field **f= field ; *f ; f++)
1701
 
  {
1702
 
    table->setWriteSet((*f)->position());
1703
 
  }
 
1717
    table->setWriteSet((*f)->field_index);
1704
1718
 
1705
1719
  /* Don't set timestamp if used */
1706
1720
  table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
1710
1724
  session->cuted_fields=0;
1711
1725
  if (info.ignore || info.handle_duplicates != DUP_ERROR)
1712
1726
    table->cursor->extra(HA_EXTRA_IGNORE_DUP_KEY);
1713
 
 
1714
1727
  if (info.handle_duplicates == DUP_REPLACE)
1715
1728
    table->cursor->extra(HA_EXTRA_WRITE_CAN_REPLACE);
1716
 
 
1717
1729
  if (info.handle_duplicates == DUP_UPDATE)
1718
1730
    table->cursor->extra(HA_EXTRA_INSERT_WITH_UPDATE);
1719
 
 
1720
1731
  table->cursor->ha_start_bulk_insert((ha_rows) 0);
1721
 
  session->setAbortOnWarning(not info.ignore);
 
1732
  session->abort_on_warning= !info.ignore;
1722
1733
  if (check_that_all_fields_are_given_values(session, table, table_list))
1723
1734
    return(1);
1724
 
 
1725
1735
  table->mark_columns_needed_for_insert();
1726
1736
  table->cursor->extra(HA_EXTRA_WRITE_CACHE);
1727
1737
  return(0);
1733
1743
}
1734
1744
 
1735
1745
 
1736
 
void select_create::send_error(drizzled::error_t errcode,const char *err)
 
1746
void select_create::send_error(uint32_t errcode,const char *err)
1737
1747
{
1738
1748
  /*
1739
1749
    This will execute any rollbacks that are necessary before writing
1747
1757
 
1748
1758
  */
1749
1759
  select_insert::send_error(errcode, err);
 
1760
 
 
1761
  return;
1750
1762
}
1751
1763
 
1752
1764
 
1765
1777
    if (!table->getShare()->getType())
1766
1778
    {
1767
1779
      TransactionServices &transaction_services= TransactionServices::singleton();
1768
 
      transaction_services.autocommitOrRollback(*session, 0);
 
1780
      transaction_services.autocommitOrRollback(session, 0);
1769
1781
      (void) session->endActiveTransaction();
1770
1782
    }
1771
1783