~ubuntu-branches/ubuntu/saucy/drizzle/saucy-proposed

« back to all changes in this revision

Viewing changes to drizzled/cursor.cc

  • Committer: Package Import Robot
  • Author(s): Clint Byrum
  • Date: 2012-06-19 10:46:49 UTC
  • mfrom: (1.1.6)
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20120619104649-e2l0ggd4oz3um0f4
Tags: upstream-7.1.36-stable
ImportĀ upstreamĀ versionĀ 7.1.36-stable

Show diffs side-by-side

added added

removed removed

Lines of Context:
44
44
#include <drizzled/transaction_services.h>
45
45
#include <drizzled/key.h>
46
46
#include <drizzled/sql_lex.h>
 
47
#include <drizzled/resource_context.h>
 
48
#include <drizzled/statistics_variables.h>
 
49
#include <drizzled/system_variables.h>
47
50
 
48
51
using namespace std;
49
52
 
65
68
    next_insert_id(0), insert_id_for_cur_row(0)
66
69
{ }
67
70
 
68
 
Cursor::~Cursor(void)
 
71
Cursor::~Cursor()
69
72
{
70
 
  assert(locked == false);
 
73
  assert(not locked);
71
74
  /* TODO: assert(inited == NONE); */
72
75
}
73
76
 
80
83
Cursor *Cursor::clone(memory::Root *mem_root)
81
84
{
82
85
  Cursor *new_handler= getTable()->getMutableShare()->db_type()->getCursor(*getTable());
83
 
 
84
86
  /*
85
87
    Allocate Cursor->ref here because otherwise ha_open will allocate it
86
88
    on this->table->mem_root and we will not be able to reclaim that memory
87
89
    when the clone Cursor object is destroyed.
88
90
  */
89
 
  if (!(new_handler->ref= (unsigned char*) mem_root->alloc_root(ALIGN_SIZE(ref_length)*2)))
90
 
    return NULL;
91
 
 
92
 
  identifier::Table identifier(getTable()->getShare()->getSchemaName(),
93
 
                             getTable()->getShare()->getTableName(),
94
 
                             getTable()->getShare()->getType());
95
 
 
96
 
  if (new_handler && !new_handler->ha_open(identifier,
97
 
                                           getTable()->getDBStat(),
98
 
                                           HA_OPEN_IGNORE_IF_LOCKED))
99
 
    return new_handler;
100
 
  return NULL;
 
91
  new_handler->ref= mem_root->alloc(ALIGN_SIZE(ref_length)*2);
 
92
  identifier::Table identifier(getTable()->getShare()->getSchemaName(), getTable()->getShare()->getTableName(), getTable()->getShare()->getType());
 
93
  return new_handler->ha_open(identifier, getTable()->getDBStat(), HA_OPEN_IGNORE_IF_LOCKED) ? NULL : new_handler;
101
94
}
102
95
 
103
96
/*
246
239
    (void) extra(HA_EXTRA_NO_READCHECK);        // Not needed in SQL
247
240
 
248
241
    /* ref is already allocated for us if we're called from Cursor::clone() */
249
 
    if (!ref && !(ref= (unsigned char*) getTable()->alloc_root(ALIGN_SIZE(ref_length)*2)))
250
 
    {
251
 
      close();
252
 
      error=HA_ERR_OUT_OF_MEM;
253
 
    }
254
 
    else
255
 
      dup_ref=ref+ALIGN_SIZE(ref_length);
 
242
    if (!ref)
 
243
      ref= getTable()->alloc(ALIGN_SIZE(ref_length)*2);
 
244
    dup_ref=ref+ALIGN_SIZE(ref_length);
256
245
  }
257
246
  return error;
258
247
}
383
372
    values we have not used. If yes, we pick the smallest one and use it.
384
373
    Otherwise:
385
374
 
386
 
  - If a list of intervals has been provided to the statement via SET
387
 
    INSERT_ID or via an Intvar_log_event (in a replication slave), we pick the
388
 
    first unused interval from this list, consider it as reserved.
389
 
 
390
375
  - Otherwise we set the column for the first row to the value
391
376
    next_insert_id(get_auto_increment(column))) which is usually
392
377
    max-used-column-value+1.
400
385
    we either take the next provided interval or call get_auto_increment()
401
386
    again to reserve a new interval.
402
387
 
403
 
  - In both cases, the reserved intervals are remembered in
404
 
    session->auto_inc_intervals_in_cur_stmt_for_binlog if statement-based
405
 
    binlogging; the last reserved interval is remembered in
 
388
  - the last reserved interval is remembered in
406
389
    auto_inc_interval_for_cur_row.
407
390
 
408
391
    The idea is that generated auto_increment values are predictable and
418
401
    with a value, session->next_insert_id is filled with the value to use for the
419
402
    next row, if a value was autogenerated for the current row it is stored in
420
403
    session->insert_id_for_cur_row, if get_auto_increment() was called
421
 
    session->auto_inc_interval_for_cur_row is modified, if that interval is not
422
 
    present in session->auto_inc_intervals_in_cur_stmt_for_binlog it is added to
423
 
    this list.
 
404
    session->auto_inc_interval_for_cur_row is modified.
424
405
 
425
406
  @todo
426
407
    Replace all references to "next number" or NEXT_NUMBER to
476
457
 
477
458
  if ((nr= next_insert_id) >= auto_inc_interval_for_cur_row.maximum())
478
459
  {
479
 
    /* next_insert_id is beyond what is reserved, so we reserve more. */
480
 
    const Discrete_interval *forced=
481
 
      session->auto_inc_intervals_forced.get_next();
482
 
    if (forced != NULL)
483
 
    {
484
 
      nr= forced->minimum();
485
 
      nb_reserved_values= forced->values();
486
 
    }
487
 
    else
488
460
    {
489
461
      /*
490
462
        Cursor::estimation_rows_to_insert was set by
491
463
        Cursor::ha_start_bulk_insert(); if 0 it means "unknown".
492
464
      */
493
 
      uint32_t nb_already_reserved_intervals=
494
 
        session->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements();
 
465
      uint32_t nb_already_reserved_intervals= 0;
495
466
      uint64_t nb_desired_values;
496
467
      /*
497
468
        If an estimation was given to the engine:
566
537
      nr= getTable()->next_number_field->val_int();
567
538
  }
568
539
  if (append)
569
 
  {
570
 
    auto_inc_interval_for_cur_row.replace(nr, nb_reserved_values,
571
 
                                          variables->auto_increment_increment);
572
 
  }
 
540
    auto_inc_interval_for_cur_row.replace(nr, nb_reserved_values, variables->auto_increment_increment);
573
541
 
574
542
  /*
575
543
    Record this autogenerated value. If the caller then
610
578
  release_auto_increment();
611
579
  insert_id_for_cur_row= 0;
612
580
  auto_inc_interval_for_cur_row.replace(0, 0, 0);
613
 
  if (next_insert_id > 0)
614
 
  {
615
 
    next_insert_id= 0;
616
 
    /*
617
 
      this statement used forced auto_increment values if there were some,
618
 
      wipe them away for other statements.
619
 
    */
620
 
    getTable()->in_use->auto_inc_intervals_forced.empty();
621
 
  }
 
581
  next_insert_id= 0;
622
582
}
623
583
 
624
 
void Cursor::drop_table(const char *)
 
584
void Cursor::drop_table()
625
585
{
626
586
  close();
627
587
}
628
588
 
629
 
 
630
 
/**
631
 
  Performs checks upon the table.
632
 
 
633
 
  @param session                thread doing CHECK Table operation
634
 
  @param check_opt          options from the parser
635
 
 
636
 
  @retval
637
 
    HA_ADMIN_OK               Successful upgrade
638
 
  @retval
639
 
    HA_ADMIN_NEEDS_UPGRADE    Table has structures requiring upgrade
640
 
  @retval
641
 
    HA_ADMIN_NEEDS_ALTER      Table has structures requiring ALTER Table
642
 
  @retval
643
 
    HA_ADMIN_NOT_IMPLEMENTED
644
 
*/
645
 
int Cursor::ha_check(Session *, HA_CHECK_OPT *)
 
589
int Cursor::ha_check(Session*)
646
590
{
647
591
  return HA_ADMIN_OK;
648
592
}
656
600
void
657
601
Cursor::setTransactionReadWrite()
658
602
{
659
 
  ResourceContext *resource_context;
660
 
 
661
603
  /*
662
604
   * If the cursor has not context for execution then there should be no
663
605
   * possible resource to gain (and if there is... then there is a bug such
666
608
  if (not getTable()->in_use)
667
609
    return;
668
610
 
669
 
  resource_context= getTable()->in_use->getResourceContext(getEngine());
670
611
  /*
671
612
    When a storage engine method is called, the transaction must
672
613
    have been started, unless it's a DDL call, for which the
675
616
    Unfortunately here we can't know know for sure if the engine
676
617
    has registered the transaction or not, so we must check.
677
618
  */
678
 
  if (resource_context->isStarted())
679
 
  {
680
 
    resource_context->markModifiedData();
681
 
  }
 
619
  ResourceContext& resource_context= getTable()->in_use->getResourceContext(*getEngine());
 
620
  if (resource_context.isStarted())
 
621
    resource_context.markModifiedData();
682
622
}
683
623
 
684
624
 
707
647
     * @todo Make TransactionServices generic to AfterTriggerServices
708
648
     * or similar...
709
649
     */
710
 
    Session *const session= getTable()->in_use;
711
 
    TransactionServices &transaction_services= TransactionServices::singleton();
712
 
    transaction_services.truncateTable(*session, *getTable());
 
650
    Session& session= *getTable()->in_use;
 
651
    TransactionServices::truncateTable(session, *getTable());
713
652
  }
714
653
 
715
654
  return result;
738
677
*/
739
678
 
740
679
int
741
 
Cursor::ha_analyze(Session* session, HA_CHECK_OPT*)
 
680
Cursor::ha_analyze(Session* session)
742
681
{
743
682
  setTransactionReadWrite();
744
683
 
781
720
  @sa Cursor::discard_or_import_tablespace()
782
721
*/
783
722
 
784
 
int
785
 
Cursor::ha_discard_or_import_tablespace(bool discard)
 
723
int Cursor::ha_discard_or_import_tablespace(bool discard)
786
724
{
787
725
  setTransactionReadWrite();
788
 
 
789
726
  return discard_or_import_tablespace(discard);
790
727
}
791
728
 
795
732
  @sa Cursor::drop_table()
796
733
*/
797
734
 
798
 
void
799
 
Cursor::closeMarkForDelete(const char *name)
 
735
void Cursor::closeMarkForDelete()
800
736
{
801
737
  setTransactionReadWrite();
802
 
 
803
 
  return drop_table(name);
 
738
  return drop_table();
804
739
}
805
740
 
806
741
int Cursor::index_next_same(unsigned char *buf, const unsigned char *key, uint32_t keylen)
807
742
{
808
 
  int error;
809
 
  if (!(error=index_next(buf)))
810
 
  {
811
 
    ptrdiff_t ptrdiff= buf - getTable()->getInsertRecord();
812
 
    unsigned char *save_record_0= NULL;
813
 
    KeyInfo *key_info= NULL;
814
 
    KeyPartInfo *key_part;
815
 
    KeyPartInfo *key_part_end= NULL;
816
 
 
817
 
    /*
818
 
      key_cmp_if_same() compares table->getInsertRecord() against 'key'.
819
 
      In parts it uses table->getInsertRecord() directly, in parts it uses
820
 
      field objects with their local pointers into table->getInsertRecord().
821
 
      If 'buf' is distinct from table->getInsertRecord(), we need to move
822
 
      all record references. This is table->getInsertRecord() itself and
823
 
      the field pointers of the fields used in this key.
824
 
    */
825
 
    if (ptrdiff)
826
 
    {
827
 
      save_record_0= getTable()->getInsertRecord();
828
 
      getTable()->record[0]= buf;
829
 
      key_info= getTable()->key_info + active_index;
830
 
      key_part= key_info->key_part;
831
 
      key_part_end= key_part + key_info->key_parts;
832
 
      for (; key_part < key_part_end; key_part++)
833
 
      {
834
 
        assert(key_part->field);
835
 
        key_part->field->move_field_offset(ptrdiff);
836
 
      }
837
 
    }
838
 
 
839
 
    if (key_cmp_if_same(getTable(), key, active_index, keylen))
840
 
    {
841
 
      getTable()->status=STATUS_NOT_FOUND;
842
 
      error=HA_ERR_END_OF_FILE;
843
 
    }
844
 
 
845
 
    /* Move back if necessary. */
846
 
    if (ptrdiff)
847
 
    {
848
 
      getTable()->record[0]= save_record_0;
849
 
      for (key_part= key_info->key_part; key_part < key_part_end; key_part++)
850
 
        key_part->field->move_field_offset(-ptrdiff);
851
 
    }
 
743
  int error= index_next(buf);
 
744
  if (error)
 
745
    return error;
 
746
 
 
747
  ptrdiff_t ptrdiff= buf - getTable()->getInsertRecord();
 
748
  unsigned char *save_record_0= NULL;
 
749
  KeyInfo *key_info= NULL;
 
750
  KeyPartInfo *key_part;
 
751
  KeyPartInfo *key_part_end= NULL;
 
752
 
 
753
  /*
 
754
  key_cmp_if_same() compares table->getInsertRecord() against 'key'.
 
755
  In parts it uses table->getInsertRecord() directly, in parts it uses
 
756
  field objects with their local pointers into table->getInsertRecord().
 
757
  If 'buf' is distinct from table->getInsertRecord(), we need to move
 
758
  all record references. This is table->getInsertRecord() itself and
 
759
  the field pointers of the fields used in this key.
 
760
  */
 
761
  if (ptrdiff)
 
762
  {
 
763
    save_record_0= getTable()->getInsertRecord();
 
764
    getTable()->record[0]= buf;
 
765
    key_info= getTable()->key_info + active_index;
 
766
    key_part= key_info->key_part;
 
767
    key_part_end= key_part + key_info->key_parts;
 
768
    for (; key_part < key_part_end; key_part++)
 
769
    {
 
770
      assert(key_part->field);
 
771
      key_part->field->move_field_offset(ptrdiff);
 
772
    }
 
773
  }
 
774
 
 
775
  if (key_cmp_if_same(getTable(), key, active_index, keylen))
 
776
  {
 
777
    getTable()->status=STATUS_NOT_FOUND;
 
778
    error= HA_ERR_END_OF_FILE;
 
779
  }
 
780
 
 
781
  /* Move back if necessary. */
 
782
  if (ptrdiff)
 
783
  {
 
784
    getTable()->record[0]= save_record_0;
 
785
    for (key_part= key_info->key_part; key_part < key_part_end; key_part++)
 
786
      key_part->field->move_field_offset(-ptrdiff);
852
787
  }
853
788
  return error;
854
789
}
1279
1214
  return error ?  error : error1;
1280
1215
}
1281
1216
 
1282
 
/**
1283
 
  Check if the conditions for row-based binlogging is correct for the table.
1284
 
 
1285
 
  A row in the given table should be replicated if:
1286
 
  - It is not a temporary table
1287
 
*/
1288
 
 
1289
1217
static bool log_row_for_replication(Table* table,
1290
1218
                                    const unsigned char *before_record,
1291
1219
                                    const unsigned char *after_record)
1292
1220
{
1293
 
  TransactionServices &transaction_services= TransactionServices::singleton();
1294
1221
  Session *const session= table->in_use;
1295
1222
 
1296
 
  if (table->getShare()->getType() || not transaction_services.shouldConstructMessages())
 
1223
  if (table->getShare()->getType() || not TransactionServices::shouldConstructMessages())
1297
1224
    return false;
1298
1225
 
1299
1226
  bool result= false;
1310
1237
     * CREATE TABLE will commit the transaction containing
1311
1238
     * it).
1312
1239
     */
1313
 
    result= transaction_services.insertRecord(*session, *table);
 
1240
    result= TransactionServices::insertRecord(*session, *table);
1314
1241
    break;
1315
1242
  case SQLCOM_REPLACE:
1316
1243
  case SQLCOM_REPLACE_SELECT:
1339
1266
       * as the row to delete (this is the conflicting row), so
1340
1267
       * we need to notify TransactionService to use that row.
1341
1268
       */
1342
 
      transaction_services.deleteRecord(*session, *table, true);
 
1269
      TransactionServices::deleteRecord(*session, *table, true);
1343
1270
      /* 
1344
1271
       * We set the "current" statement message to NULL.  This triggers
1345
1272
       * the replication services component to generate a new statement
1346
1273
       * message for the inserted record which will come next.
1347
1274
       */
1348
 
      transaction_services.finalizeStatementMessage(*session->getStatementMessage(), *session);
 
1275
      TransactionServices::finalizeStatementMessage(*session->getStatementMessage(), *session);
1349
1276
    }
1350
1277
    else
1351
1278
    {
1352
1279
      if (before_record == NULL)
1353
 
        result= transaction_services.insertRecord(*session, *table);
 
1280
        result= TransactionServices::insertRecord(*session, *table);
1354
1281
      else
1355
 
        transaction_services.updateRecord(*session, *table, before_record, after_record);
 
1282
        TransactionServices::updateRecord(*session, *table, before_record, after_record);
1356
1283
    }
1357
1284
    break;
1358
1285
  case SQLCOM_INSERT:
1365
1292
     * an update.
1366
1293
     */
1367
1294
    if (before_record == NULL)
1368
 
      result= transaction_services.insertRecord(*session, *table);
 
1295
      result= TransactionServices::insertRecord(*session, *table);
1369
1296
    else
1370
 
      transaction_services.updateRecord(*session, *table, before_record, after_record);
 
1297
      TransactionServices::updateRecord(*session, *table, before_record, after_record);
1371
1298
    break;
1372
1299
 
1373
1300
  case SQLCOM_UPDATE:
1374
 
    transaction_services.updateRecord(*session, *table, before_record, after_record);
 
1301
    TransactionServices::updateRecord(*session, *table, before_record, after_record);
1375
1302
    break;
1376
1303
 
1377
1304
  case SQLCOM_DELETE:
1378
 
    transaction_services.deleteRecord(*session, *table);
 
1305
    TransactionServices::deleteRecord(*session, *table);
1379
1306
    break;
1380
1307
  default:
1381
1308
    break;
1502
1429
  }
1503
1430
 
1504
1431
  if (unlikely(log_row_for_replication(getTable(), NULL, buf)))
1505
 
    return HA_ERR_RBR_LOGGING_FAILED;
 
1432
    return HA_ERR_LOG_ROW_FOR_REPLICATION_FAILED;
1506
1433
 
1507
1434
  return 0;
1508
1435
}
1548
1475
  }
1549
1476
 
1550
1477
  if (unlikely(log_row_for_replication(getTable(), old_data, new_data)))
1551
 
    return HA_ERR_RBR_LOGGING_FAILED;
 
1478
    return HA_ERR_LOG_ROW_FOR_REPLICATION_FAILED;
1552
1479
 
1553
1480
  return 0;
1554
1481
}
1584
1511
    return error;
1585
1512
 
1586
1513
  if (unlikely(log_row_for_replication(getTable(), buf, NULL)))
1587
 
    return HA_ERR_RBR_LOGGING_FAILED;
 
1514
    return HA_ERR_LOG_ROW_FOR_REPLICATION_FAILED;
1588
1515
 
1589
1516
  return 0;
1590
1517
}