~ubuntu-branches/ubuntu/trusty/drizzle/trusty

« back to all changes in this revision

Viewing changes to drizzled/cursor.cc

  • Committer: Bazaar Package Importer
  • Author(s): Monty Taylor
  • Date: 2010-11-12 12:26:01 UTC
  • mfrom: (1.1.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20101112122601-myppfj3tfmlkccuq
Tags: upstream-2010.11.03
ImportĀ upstreamĀ versionĀ 2010.11.03

Show diffs side-by-side

added added

removed removed

Lines of Context:
32
32
#include "drizzled/gettext.h"
33
33
#include "drizzled/probes.h"
34
34
#include "drizzled/sql_parse.h"
35
 
#include "drizzled/cost_vect.h"
 
35
#include "drizzled/optimizer/cost_vector.h"
36
36
#include "drizzled/session.h"
37
37
#include "drizzled/sql_base.h"
38
 
#include "drizzled/replication_services.h"
 
38
#include "drizzled/transaction_services.h"
39
39
#include "drizzled/lock.h"
40
40
#include "drizzled/item/int.h"
41
41
#include "drizzled/item/empty_string.h"
43
43
#include "drizzled/message/table.pb.h"
44
44
#include "drizzled/plugin/client.h"
45
45
#include "drizzled/internal/my_sys.h"
46
 
#include "drizzled/transaction_services.h"
 
46
#include "drizzled/plugin/event_observer.h"
47
47
 
48
48
using namespace std;
49
49
 
54
54
** General Cursor functions
55
55
****************************************************************************/
56
56
Cursor::Cursor(plugin::StorageEngine &engine_arg,
57
 
               TableShare &share_arg)
58
 
  : table_share(&share_arg), table(0),
59
 
    estimation_rows_to_insert(0), engine(&engine_arg),
60
 
    ref(0), in_range_check_pushed_down(false),
 
57
               Table &arg)
 
58
  : table(arg),
 
59
    engine(engine_arg),
 
60
    estimation_rows_to_insert(0),
 
61
    ref(0),
61
62
    key_used_on_scan(MAX_KEY), active_index(MAX_KEY),
62
63
    ref_length(sizeof(internal::my_off_t)),
63
64
    inited(NONE),
64
 
    locked(false), implicit_emptied(0),
 
65
    locked(false),
65
66
    next_insert_id(0), insert_id_for_cur_row(0)
66
67
{ }
67
68
 
72
73
}
73
74
 
74
75
 
 
76
/*
 
77
 * @note this only used in
 
78
 * optimizer::QuickRangeSelect::init_ror_merged_scan(bool reuse_handler) as
 
79
 * of the writing of this comment. -Brian
 
80
 */
75
81
Cursor *Cursor::clone(memory::Root *mem_root)
76
82
{
77
 
  Cursor *new_handler= table->s->db_type()->getCursor(*table->s, mem_root);
 
83
  Cursor *new_handler= getTable()->getMutableShare()->db_type()->getCursor(*getTable());
78
84
 
79
85
  /*
80
86
    Allocate Cursor->ref here because otherwise ha_open will allocate it
81
87
    on this->table->mem_root and we will not be able to reclaim that memory
82
88
    when the clone Cursor object is destroyed.
83
89
  */
84
 
  if (!(new_handler->ref= (unsigned char*) alloc_root(mem_root, ALIGN_SIZE(ref_length)*2)))
 
90
  if (!(new_handler->ref= (unsigned char*) mem_root->alloc_root(ALIGN_SIZE(ref_length)*2)))
85
91
    return NULL;
86
 
  if (new_handler && !new_handler->ha_open(table,
87
 
                                           table->s->normalized_path.str,
88
 
                                           table->getDBStat(),
 
92
 
 
93
  TableIdentifier identifier(getTable()->getShare()->getSchemaName(),
 
94
                             getTable()->getShare()->getTableName(),
 
95
                             getTable()->getShare()->getType());
 
96
 
 
97
  if (new_handler && !new_handler->ha_open(identifier,
 
98
                                           getTable()->getDBStat(),
89
99
                                           HA_OPEN_IGNORE_IF_LOCKED))
90
100
    return new_handler;
91
101
  return NULL;
92
102
}
93
103
 
94
 
int Cursor::ha_index_init(uint32_t idx, bool sorted)
 
104
/*
 
105
  DESCRIPTION
 
106
    given a buffer with a key value, and a map of keyparts
 
107
    that are present in this value, returns the length of the value
 
108
*/
 
109
uint32_t Cursor::calculate_key_len(uint32_t key_position, key_part_map keypart_map_arg)
 
110
{
 
111
  /* works only with key prefixes */
 
112
  assert(((keypart_map_arg + 1) & keypart_map_arg) == 0);
 
113
 
 
114
  const KeyPartInfo *key_part_found= getTable()->getShare()->getKeyInfo(key_position).key_part;
 
115
  const KeyPartInfo *end_key_part_found= key_part_found + getTable()->getShare()->getKeyInfo(key_position).key_parts;
 
116
  uint32_t length= 0;
 
117
 
 
118
  while (key_part_found < end_key_part_found && keypart_map_arg)
 
119
  {
 
120
    length+= key_part_found->store_length;
 
121
    keypart_map_arg >>= 1;
 
122
    key_part_found++;
 
123
  }
 
124
  return length;
 
125
}
 
126
 
 
127
int Cursor::startIndexScan(uint32_t idx, bool sorted)
95
128
{
96
129
  int result;
97
130
  assert(inited == NONE);
98
 
  if (!(result= index_init(idx, sorted)))
 
131
  if (!(result= doStartIndexScan(idx, sorted)))
99
132
    inited=INDEX;
100
133
  end_range= NULL;
101
134
  return result;
102
135
}
103
136
 
104
 
int Cursor::ha_index_end()
 
137
int Cursor::endIndexScan()
105
138
{
106
139
  assert(inited==INDEX);
107
140
  inited=NONE;
108
141
  end_range= NULL;
109
 
  return(index_end());
 
142
  return(doEndIndexScan());
110
143
}
111
144
 
112
 
int Cursor::ha_rnd_init(bool scan)
 
145
int Cursor::startTableScan(bool scan)
113
146
{
114
147
  int result;
115
148
  assert(inited==NONE || (inited==RND && scan));
116
 
  inited= (result= rnd_init(scan)) ? NONE: RND;
 
149
  inited= (result= doStartTableScan(scan)) ? NONE: RND;
117
150
 
118
151
  return result;
119
152
}
120
153
 
121
 
int Cursor::ha_rnd_end()
 
154
int Cursor::endTableScan()
122
155
{
123
156
  assert(inited==RND);
124
157
  inited=NONE;
125
 
  return(rnd_end());
 
158
  return(doEndTableScan());
126
159
}
127
160
 
128
161
int Cursor::ha_index_or_rnd_end()
129
162
{
130
 
  return inited == INDEX ? ha_index_end() : inited == RND ? ha_rnd_end() : 0;
 
163
  return inited == INDEX ? endIndexScan() : inited == RND ? endTableScan() : 0;
131
164
}
132
165
 
133
166
void Cursor::ha_start_bulk_insert(ha_rows rows)
142
175
  return end_bulk_insert();
143
176
}
144
177
 
145
 
void Cursor::change_table_ptr(Table *table_arg, TableShare *share)
146
 
{
147
 
  table= table_arg;
148
 
  table_share= share;
149
 
}
150
 
 
151
178
const key_map *Cursor::keys_to_use_for_scanning()
152
179
{
153
180
  return &key_map_empty;
155
182
 
156
183
bool Cursor::has_transactions()
157
184
{
158
 
  return (table->s->db_type()->check_flag(HTON_BIT_DOES_TRANSACTIONS));
 
185
  return (getTable()->getShare()->db_type()->check_flag(HTON_BIT_DOES_TRANSACTIONS));
159
186
}
160
187
 
161
 
void Cursor::ha_statistic_increment(ulong system_status_var::*offset) const
 
188
void Cursor::ha_statistic_increment(uint64_t system_status_var::*offset) const
162
189
{
163
 
  status_var_increment(table->in_use->status_var.*offset);
 
190
  (getTable()->in_use->status_var.*offset)++;
164
191
}
165
192
 
166
193
void **Cursor::ha_data(Session *session) const
167
194
{
168
 
  return session->getEngineData(engine);
169
 
}
170
 
 
171
 
Session *Cursor::ha_session(void) const
172
 
{
173
 
  assert(!table || !table->in_use || table->in_use == current_session);
174
 
  return (table && table->in_use) ? table->in_use : current_session;
175
 
}
176
 
 
 
195
  return session->getEngineData(getEngine());
 
196
}
177
197
 
178
198
bool Cursor::is_fatal_error(int error, uint32_t flags)
179
199
{
188
208
 
189
209
ha_rows Cursor::records() { return stats.records; }
190
210
uint64_t Cursor::tableSize() { return stats.index_file_length + stats.data_file_length; }
191
 
uint64_t Cursor::rowSize() { return table->getRecordLength() + table->sizeFields(); }
 
211
uint64_t Cursor::rowSize() { return getTable()->getRecordLength() + getTable()->sizeFields(); }
 
212
 
 
213
int Cursor::doOpen(const TableIdentifier &identifier, int mode, uint32_t test_if_locked)
 
214
{
 
215
  return open(identifier.getPath().c_str(), mode, test_if_locked);
 
216
}
192
217
 
193
218
/**
194
219
  Open database-Cursor.
196
221
  Try O_RDONLY if cannot open as O_RDWR
197
222
  Don't wait for locks if not HA_OPEN_WAIT_IF_LOCKED is set
198
223
*/
199
 
int Cursor::ha_open(Table *table_arg, const char *name, int mode,
200
 
                     int test_if_locked)
 
224
int Cursor::ha_open(const TableIdentifier &identifier,
 
225
                    int mode,
 
226
                    int test_if_locked)
201
227
{
202
228
  int error;
203
229
 
204
 
  table= table_arg;
205
 
  assert(table->s == table_share);
206
 
  assert(alloc_root_inited(&table->mem_root));
207
 
 
208
 
  if ((error=open(name,mode,test_if_locked)))
 
230
  if ((error= doOpen(identifier, mode, test_if_locked)))
209
231
  {
210
232
    if ((error == EACCES || error == EROFS) && mode == O_RDWR &&
211
 
        (table->db_stat & HA_TRY_READ_ONLY))
 
233
        (getTable()->db_stat & HA_TRY_READ_ONLY))
212
234
    {
213
 
      table->db_stat|=HA_READ_ONLY;
214
 
      error=open(name,O_RDONLY,test_if_locked);
 
235
      getTable()->db_stat|=HA_READ_ONLY;
 
236
      error= doOpen(identifier, O_RDONLY,test_if_locked);
215
237
    }
216
238
  }
217
239
  if (error)
220
242
  }
221
243
  else
222
244
  {
223
 
    if (table->s->db_options_in_use & HA_OPTION_READ_ONLY_DATA)
224
 
      table->db_stat|=HA_READ_ONLY;
 
245
    if (getTable()->getShare()->db_options_in_use & HA_OPTION_READ_ONLY_DATA)
 
246
      getTable()->db_stat|=HA_READ_ONLY;
225
247
    (void) extra(HA_EXTRA_NO_READCHECK);        // Not needed in SQL
226
248
 
227
249
    /* ref is already allocated for us if we're called from Cursor::clone() */
228
 
    if (!ref && !(ref= (unsigned char*) alloc_root(&table->mem_root,
229
 
                                          ALIGN_SIZE(ref_length)*2)))
 
250
    if (!ref && !(ref= (unsigned char*) getTable()->alloc_root(ALIGN_SIZE(ref_length)*2)))
230
251
    {
231
252
      close();
232
253
      error=HA_ERR_OUT_OF_MEM;
238
259
}
239
260
 
240
261
/**
241
 
  one has to use this method when to find
242
 
  random position by record as the plain
243
 
  position() call doesn't work for some
244
 
  handlers for random position
245
 
*/
246
 
 
247
 
int Cursor::rnd_pos_by_record(unsigned char *record)
248
 
{
249
 
  register int error;
250
 
 
251
 
  position(record);
252
 
  if (inited && (error= ha_index_end()))
253
 
    return error;
254
 
  if ((error= ha_rnd_init(false)))
255
 
    return error;
256
 
 
257
 
  return rnd_pos(record, ref);
258
 
}
259
 
 
260
 
/**
261
262
  Read first row (only) from a table.
262
263
 
263
264
  This is never called for InnoDB tables, as these table types
275
276
    TODO remove the test for HA_READ_ORDER
276
277
  */
277
278
  if (stats.deleted < 10 || primary_key >= MAX_KEY ||
278
 
      !(table->index_flags(primary_key) & HA_READ_ORDER))
 
279
      !(getTable()->index_flags(primary_key) & HA_READ_ORDER))
279
280
  {
280
 
    (void) ha_rnd_init(1);
 
281
    (void) startTableScan(1);
281
282
    while ((error= rnd_next(buf)) == HA_ERR_RECORD_DELETED) ;
282
 
    (void) ha_rnd_end();
 
283
    (void) endTableScan();
283
284
  }
284
285
  else
285
286
  {
286
287
    /* Find the first row through the primary key */
287
 
    (void) ha_index_init(primary_key, 0);
 
288
    (void) startIndexScan(primary_key, 0);
288
289
    error=index_first(buf);
289
 
    (void) ha_index_end();
 
290
    (void) endIndexScan();
290
291
  }
291
292
  return error;
292
293
}
303
304
  @verbatim 1,5,15,25,35,... @endverbatim
304
305
*/
305
306
inline uint64_t
306
 
compute_next_insert_id(uint64_t nr,struct system_variables *variables)
 
307
compute_next_insert_id(uint64_t nr, drizzle_system_variables *variables)
307
308
{
308
309
  if (variables->auto_increment_increment == 1)
309
310
    return (nr+1); // optimization of the formula below
323
324
    Session::next_insert_id to be greater than the explicit value.
324
325
  */
325
326
  if ((next_insert_id > 0) && (nr >= next_insert_id))
326
 
    set_next_insert_id(compute_next_insert_id(nr, &table->in_use->variables));
 
327
    set_next_insert_id(compute_next_insert_id(nr, &getTable()->in_use->variables));
327
328
}
328
329
 
329
330
 
343
344
    The number X if it exists, "nr" otherwise.
344
345
*/
345
346
inline uint64_t
346
 
prev_insert_id(uint64_t nr, struct system_variables *variables)
 
347
prev_insert_id(uint64_t nr, drizzle_system_variables *variables)
347
348
{
348
349
  if (unlikely(nr < variables->auto_increment_offset))
349
350
  {
440
441
{
441
442
  uint64_t nr, nb_reserved_values;
442
443
  bool append= false;
443
 
  Session *session= table->in_use;
444
 
  struct system_variables *variables= &session->variables;
 
444
  Session *session= getTable()->in_use;
 
445
  drizzle_system_variables *variables= &session->variables;
445
446
 
446
447
  /*
447
448
    next_insert_id is a "cursor" into the reserved interval, it may go greater
453
454
     for an auto increment column, not a magic value like NULL is.
454
455
     same as sql_mode=NO_AUTO_VALUE_ON_ZERO */
455
456
 
456
 
  if ((nr= table->next_number_field->val_int()) != 0
457
 
      || table->auto_increment_field_not_null)
 
457
  if ((nr= getTable()->next_number_field->val_int()) != 0
 
458
      || getTable()->auto_increment_field_not_null)
458
459
  {
459
460
    /*
460
461
      Update next_insert_id if we had already generated a value in this
532
533
      nr= compute_next_insert_id(nr-1, variables);
533
534
    }
534
535
 
535
 
    if (table->s->next_number_keypart == 0)
 
536
    if (getTable()->getShare()->next_number_keypart == 0)
536
537
    {
537
538
      /* We must defer the appending until "nr" has been possibly truncated */
538
539
      append= true;
539
540
    }
540
541
  }
541
542
 
542
 
  if (unlikely(table->next_number_field->store((int64_t) nr, true)))
 
543
  if (unlikely(getTable()->next_number_field->store((int64_t) nr, true)))
543
544
  {
544
545
    /*
545
546
      first test if the query was aborted due to strict mode constraints
546
547
    */
547
 
    if (session->killed == Session::KILL_BAD_DATA)
 
548
    if (session->getKilled() == Session::KILL_BAD_DATA)
548
549
      return HA_ERR_AUTOINC_ERANGE;
549
550
 
550
551
    /*
555
556
      bother shifting the right bound (anyway any other value from this
556
557
      interval will cause a duplicate key).
557
558
    */
558
 
    nr= prev_insert_id(table->next_number_field->val_int(), variables);
559
 
    if (unlikely(table->next_number_field->store((int64_t) nr, true)))
560
 
      nr= table->next_number_field->val_int();
 
559
    nr= prev_insert_id(getTable()->next_number_field->val_int(), variables);
 
560
    if (unlikely(getTable()->next_number_field->store((int64_t) nr, true)))
 
561
      nr= getTable()->next_number_field->val_int();
561
562
  }
562
563
  if (append)
563
564
  {
598
599
  @param first_value         (OUT) the first value reserved by the Cursor
599
600
  @param nb_reserved_values  (OUT) how many values the Cursor reserved
600
601
*/
601
 
void Cursor::get_auto_increment(uint64_t ,
602
 
                                 uint64_t ,
603
 
                                 uint64_t ,
604
 
                                 uint64_t *first_value,
605
 
                                 uint64_t *nb_reserved_values)
606
 
{
607
 
  uint64_t nr;
608
 
  int error;
609
 
 
610
 
  (void) extra(HA_EXTRA_KEYREAD);
611
 
  table->mark_columns_used_by_index_no_reset(table->s->next_number_index);
612
 
  index_init(table->s->next_number_index, 1);
613
 
  if (table->s->next_number_keypart == 0)
614
 
  {                                             // Autoincrement at key-start
615
 
    error=index_last(table->record[1]);
616
 
    /*
617
 
      MySQL implicitely assumes such method does locking (as MySQL decides to
618
 
      use nr+increment without checking again with the Cursor, in
619
 
      Cursor::update_auto_increment()), so reserves to infinite.
620
 
    */
621
 
    *nb_reserved_values= UINT64_MAX;
622
 
  }
623
 
  else
624
 
  {
625
 
    unsigned char key[MAX_KEY_LENGTH];
626
 
    key_copy(key, table->record[0],
627
 
             table->key_info + table->s->next_number_index,
628
 
             table->s->next_number_key_offset);
629
 
    error= index_read_map(table->record[1], key,
630
 
                          make_prev_keypart_map(table->s->next_number_keypart),
631
 
                          HA_READ_PREFIX_LAST);
632
 
    /*
633
 
      MySQL needs to call us for next row: assume we are inserting ("a",null)
634
 
      here, we return 3, and next this statement will want to insert
635
 
      ("b",null): there is no reason why ("b",3+1) would be the good row to
636
 
      insert: maybe it already exists, maybe 3+1 is too large...
637
 
    */
638
 
    *nb_reserved_values= 1;
639
 
  }
640
 
 
641
 
  if (error)
642
 
    nr=1;
643
 
  else
644
 
    nr= ((uint64_t) table->next_number_field->
645
 
         val_int_offset(table->s->rec_buff_length)+1);
646
 
  index_end();
647
 
  (void) extra(HA_EXTRA_NO_KEYREAD);
648
 
  *first_value= nr;
649
 
}
650
 
 
651
602
 
652
603
void Cursor::ha_release_auto_increment()
653
604
{
661
612
      this statement used forced auto_increment values if there were some,
662
613
      wipe them away for other statements.
663
614
    */
664
 
    table->in_use->auto_inc_intervals_forced.empty();
 
615
    getTable()->in_use->auto_inc_intervals_forced.empty();
665
616
  }
666
617
}
667
618
 
700
651
void
701
652
Cursor::setTransactionReadWrite()
702
653
{
703
 
  ResourceContext *resource_context= ha_session()->getResourceContext(engine);
 
654
  ResourceContext *resource_context;
 
655
 
 
656
  /*
 
657
   * If the cursor has not context for execution then there should be no
 
658
   * possible resource to gain (and if there is... then there is a bug such
 
659
   * that in_use should have been set.
 
660
 */
 
661
  if (not getTable()->in_use)
 
662
    return;
 
663
 
 
664
  resource_context= getTable()->in_use->getResourceContext(getEngine());
704
665
  /*
705
666
    When a storage engine method is called, the transaction must
706
667
    have been started, unless it's a DDL call, for which the
738
699
    /** 
739
700
     * Trigger post-truncate notification to plugins... 
740
701
     *
741
 
     * @todo Make ReplicationServices generic to AfterTriggerServices
 
702
     * @todo Make TransactionServices generic to AfterTriggerServices
742
703
     * or similar...
743
704
     */
744
 
    Session *const session= table->in_use;
745
 
    ReplicationServices &replication_services= ReplicationServices::singleton();
746
 
    replication_services.truncateTable(session, table);
 
705
    Session *const session= getTable()->in_use;
 
706
    TransactionServices &transaction_services= TransactionServices::singleton();
 
707
    transaction_services.truncateTable(session, getTable());
747
708
  }
748
709
 
749
710
  return result;
842
803
  int error;
843
804
  if (!(error=index_next(buf)))
844
805
  {
845
 
    ptrdiff_t ptrdiff= buf - table->record[0];
 
806
    ptrdiff_t ptrdiff= buf - getTable()->getInsertRecord();
846
807
    unsigned char *save_record_0= NULL;
847
 
    KEY *key_info= NULL;
848
 
    KEY_PART_INFO *key_part;
849
 
    KEY_PART_INFO *key_part_end= NULL;
 
808
    KeyInfo *key_info= NULL;
 
809
    KeyPartInfo *key_part;
 
810
    KeyPartInfo *key_part_end= NULL;
850
811
 
851
812
    /*
852
 
      key_cmp_if_same() compares table->record[0] against 'key'.
853
 
      In parts it uses table->record[0] directly, in parts it uses
854
 
      field objects with their local pointers into table->record[0].
855
 
      If 'buf' is distinct from table->record[0], we need to move
856
 
      all record references. This is table->record[0] itself and
 
813
      key_cmp_if_same() compares table->getInsertRecord() against 'key'.
 
814
      In parts it uses table->getInsertRecord() directly, in parts it uses
 
815
      field objects with their local pointers into table->getInsertRecord().
 
816
      If 'buf' is distinct from table->getInsertRecord(), we need to move
 
817
      all record references. This is table->getInsertRecord() itself and
857
818
      the field pointers of the fields used in this key.
858
819
    */
859
820
    if (ptrdiff)
860
821
    {
861
 
      save_record_0= table->record[0];
862
 
      table->record[0]= buf;
863
 
      key_info= table->key_info + active_index;
 
822
      save_record_0= getTable()->getInsertRecord();
 
823
      getTable()->record[0]= buf;
 
824
      key_info= getTable()->key_info + active_index;
864
825
      key_part= key_info->key_part;
865
826
      key_part_end= key_part + key_info->key_parts;
866
827
      for (; key_part < key_part_end; key_part++)
870
831
      }
871
832
    }
872
833
 
873
 
    if (key_cmp_if_same(table, key, active_index, keylen))
 
834
    if (key_cmp_if_same(getTable(), key, active_index, keylen))
874
835
    {
875
 
      table->status=STATUS_NOT_FOUND;
 
836
      getTable()->status=STATUS_NOT_FOUND;
876
837
      error=HA_ERR_END_OF_FILE;
877
838
    }
878
839
 
879
840
    /* Move back if necessary. */
880
841
    if (ptrdiff)
881
842
    {
882
 
      table->record[0]= save_record_0;
 
843
      getTable()->record[0]= save_record_0;
883
844
      for (key_part= key_info->key_part; key_part < key_part_end; key_part++)
884
845
        key_part->field->move_field_offset(-ptrdiff);
885
846
    }
916
877
double Cursor::index_only_read_time(uint32_t keynr, double key_records)
917
878
{
918
879
  uint32_t keys_per_block= (stats.block_size/2/
919
 
                        (table->key_info[keynr].key_length + ref_length) + 1);
 
880
                        (getTable()->key_info[keynr].key_length + ref_length) + 1);
920
881
  return ((double) (key_records + keys_per_block-1) /
921
882
          (double) keys_per_block);
922
883
}
945
906
 
946
907
  @note
947
908
    This method (or an overriding one in a derived class) must check for
948
 
    session->killed and return HA_POS_ERROR if it is not zero. This is required
 
909
    session->getKilled() and return HA_POS_ERROR if it is not zero. This is required
949
910
    for a user to be able to interrupt the calculation by killing the
950
911
    connection/query.
951
912
 
961
922
Cursor::multi_range_read_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
962
923
                                     void *seq_init_param,
963
924
                                     uint32_t ,
964
 
                                     uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
 
925
                                     uint32_t *bufsz, uint32_t *flags, optimizer::CostVector *cost)
965
926
{
966
927
  KEY_MULTI_RANGE range;
967
928
  range_seq_t seq_it;
968
929
  ha_rows rows, total_rows= 0;
969
930
  uint32_t n_ranges=0;
970
 
  Session *session= current_session;
971
931
 
972
932
  /* Default MRR implementation doesn't need buffer */
973
933
  *bufsz= 0;
975
935
  seq_it= seq->init(seq_init_param, n_ranges, *flags);
976
936
  while (!seq->next(seq_it, &range))
977
937
  {
978
 
    if (unlikely(session->killed != 0))
979
 
      return HA_POS_ERROR;
980
 
 
981
938
    n_ranges++;
982
939
    key_range *min_endp, *max_endp;
983
940
    {
1004
961
    /* The following calculation is the same as in multi_range_read_info(): */
1005
962
    *flags |= HA_MRR_USE_DEFAULT_IMPL;
1006
963
    cost->zero();
1007
 
    cost->avg_io_cost= 1; /* assume random seeks */
 
964
    cost->setAvgIOCost(1); /* assume random seeks */
1008
965
    if ((*flags & HA_MRR_INDEX_ONLY) && total_rows > 2)
1009
 
      cost->io_count= index_only_read_time(keyno, (uint32_t)total_rows);
 
966
      cost->setIOCount(index_only_read_time(keyno, (uint32_t)total_rows));
1010
967
    else
1011
 
      cost->io_count= read_time(keyno, n_ranges, total_rows);
1012
 
    cost->cpu_cost= (double) total_rows / TIME_FOR_COMPARE + 0.01;
 
968
      cost->setIOCount(read_time(keyno, n_ranges, total_rows));
 
969
    cost->setCpuCost((double) total_rows / TIME_FOR_COMPARE + 0.01);
1013
970
  }
1014
971
  return total_rows;
1015
972
}
1050
1007
*/
1051
1008
 
1052
1009
int Cursor::multi_range_read_info(uint32_t keyno, uint32_t n_ranges, uint32_t n_rows,
1053
 
                                   uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
 
1010
                                   uint32_t *bufsz, uint32_t *flags, optimizer::CostVector *cost)
1054
1011
{
1055
1012
  *bufsz= 0; /* Default implementation doesn't need a buffer */
1056
1013
 
1057
1014
  *flags |= HA_MRR_USE_DEFAULT_IMPL;
1058
1015
 
1059
1016
  cost->zero();
1060
 
  cost->avg_io_cost= 1; /* assume random seeks */
 
1017
  cost->setAvgIOCost(1); /* assume random seeks */
1061
1018
 
1062
1019
  /* Produce the same cost as non-MRR code does */
1063
1020
  if (*flags & HA_MRR_INDEX_ONLY)
1064
 
    cost->io_count= index_only_read_time(keyno, n_rows);
 
1021
    cost->setIOCount(index_only_read_time(keyno, n_rows));
1065
1022
  else
1066
 
    cost->io_count= read_time(keyno, n_ranges, n_rows);
 
1023
    cost->setIOCount(read_time(keyno, n_ranges, n_rows));
1067
1024
  return 0;
1068
1025
}
1069
1026
 
1087
1044
  @param buf             INOUT: memory buffer to be used
1088
1045
 
1089
1046
  @note
1090
 
    One must have called index_init() before calling this function. Several
 
1047
    One must have called doStartIndexScan() before calling this function. Several
1091
1048
    multi_range_read_init() calls may be made in course of one query.
1092
1049
 
1093
1050
    Until WL#2623 is done (see its text, section 3.2), the following will
1102
1059
    The callee consumes all or some fraction of the provided buffer space, and
1103
1060
    sets the HANDLER_BUFFER members accordingly.
1104
1061
    The callee may use the buffer memory until the next multi_range_read_init()
1105
 
    call is made, all records have been read, or until index_end() call is
 
1062
    call is made, all records have been read, or until doEndIndexScan() call is
1106
1063
    made, whichever comes first.
1107
1064
 
1108
1065
  @retval 0  OK
1111
1068
 
1112
1069
int
1113
1070
Cursor::multi_range_read_init(RANGE_SEQ_IF *seq_funcs, void *seq_init_param,
1114
 
                               uint32_t n_ranges, uint32_t mode,
1115
 
                               HANDLER_BUFFER *)
 
1071
                               uint32_t n_ranges, uint32_t mode)
1116
1072
{
1117
1073
  mrr_iter= seq_funcs->init(seq_init_param, n_ranges, mode);
1118
1074
  mrr_funcs= *seq_funcs;
1119
1075
  mrr_is_output_sorted= test(mode & HA_MRR_SORTED);
1120
1076
  mrr_have_range= false;
 
1077
 
1121
1078
  return 0;
1122
1079
}
1123
1080
 
1140
1097
  int result= 0;
1141
1098
  int range_res= 0;
1142
1099
 
1143
 
  if (!mrr_have_range)
 
1100
  if (not mrr_have_range)
1144
1101
  {
1145
1102
    mrr_have_range= true;
1146
1103
    goto start;
1202
1159
  @param sorted         Set to 1 if result should be sorted per key
1203
1160
 
1204
1161
  @note
1205
 
    Record is read into table->record[0]
 
1162
    Record is read into table->getInsertRecord()
1206
1163
 
1207
1164
  @retval
1208
1165
    0                   Found row
1227
1184
    key_compare_result_on_equal= ((end_key->flag == HA_READ_BEFORE_KEY) ? 1 :
1228
1185
                                  (end_key->flag == HA_READ_AFTER_KEY) ? -1 : 0);
1229
1186
  }
1230
 
  range_key_part= table->key_info[active_index].key_part;
 
1187
  range_key_part= getTable()->key_info[active_index].key_part;
1231
1188
 
1232
1189
  if (!start_key)                       // Read first record
1233
 
    result= index_first(table->record[0]);
 
1190
    result= index_first(getTable()->getInsertRecord());
1234
1191
  else
1235
 
    result= index_read_map(table->record[0],
 
1192
    result= index_read_map(getTable()->getInsertRecord(),
1236
1193
                           start_key->key,
1237
1194
                           start_key->keypart_map,
1238
1195
                           start_key->flag);
1249
1206
  Read next row between two endpoints.
1250
1207
 
1251
1208
  @note
1252
 
    Record is read into table->record[0]
 
1209
    Record is read into table->getInsertRecord()
1253
1210
 
1254
1211
  @retval
1255
1212
    0                   Found row
1265
1222
  if (eq_range)
1266
1223
  {
1267
1224
    /* We trust that index_next_same always gives a row in range */
1268
 
    return(index_next_same(table->record[0],
 
1225
    return(index_next_same(getTable()->getInsertRecord(),
1269
1226
                                end_range->key,
1270
1227
                                end_range->length));
1271
1228
  }
1272
 
  result= index_next(table->record[0]);
 
1229
  result= index_next(getTable()->getInsertRecord());
1273
1230
  if (result)
1274
1231
    return result;
1275
1232
  return(compare_key(end_range) <= 0 ? 0 : HA_ERR_END_OF_FILE);
1294
1251
int Cursor::compare_key(key_range *range)
1295
1252
{
1296
1253
  int cmp;
1297
 
  if (!range || in_range_check_pushed_down)
 
1254
  if (not range)
1298
1255
    return 0;                                   // No max range
1299
1256
  cmp= key_cmp(range_key_part, range->key, range->length);
1300
1257
  if (!cmp)
1302
1259
  return cmp;
1303
1260
}
1304
1261
 
1305
 
 
1306
 
/*
1307
 
  Same as compare_key() but doesn't check have in_range_check_pushed_down.
1308
 
  This is used by index condition pushdown implementation.
1309
 
*/
1310
 
 
1311
 
int Cursor::compare_key2(key_range *range)
1312
 
{
1313
 
  int cmp;
1314
 
  if (!range)
1315
 
    return 0;                                   // no max range
1316
 
  cmp= key_cmp(range_key_part, range->key, range->length);
1317
 
  if (!cmp)
1318
 
    cmp= key_compare_result_on_equal;
1319
 
  return cmp;
1320
 
}
1321
 
 
1322
1262
int Cursor::index_read_idx_map(unsigned char * buf, uint32_t index,
1323
1263
                                const unsigned char * key,
1324
1264
                                key_part_map keypart_map,
1325
1265
                                enum ha_rkey_function find_flag)
1326
1266
{
1327
1267
  int error, error1;
1328
 
  error= index_init(index, 0);
 
1268
  error= doStartIndexScan(index, 0);
1329
1269
  if (!error)
1330
1270
  {
1331
1271
    error= index_read_map(buf, key, keypart_map, find_flag);
1332
 
    error1= index_end();
 
1272
    error1= doEndIndexScan();
1333
1273
  }
1334
1274
  return error ?  error : error1;
1335
1275
}
1345
1285
                                    const unsigned char *before_record,
1346
1286
                                    const unsigned char *after_record)
1347
1287
{
1348
 
  ReplicationServices &replication_services= ReplicationServices::singleton();
 
1288
  TransactionServices &transaction_services= TransactionServices::singleton();
1349
1289
  Session *const session= table->in_use;
1350
1290
 
1351
 
  if (table->s->tmp_table || ! replication_services.isActive())
 
1291
  if (table->getShare()->getType() || not transaction_services.shouldConstructMessages())
1352
1292
    return false;
1353
1293
 
1354
1294
  bool result= false;
1365
1305
     * CREATE TABLE will commit the transaction containing
1366
1306
     * it).
1367
1307
     */
1368
 
    result= replication_services.insertRecord(session, table);
 
1308
    result= transaction_services.insertRecord(session, table);
1369
1309
    break;
1370
1310
  case SQLCOM_REPLACE:
1371
1311
  case SQLCOM_REPLACE_SELECT:
1372
1312
    /*
1373
1313
     * This is a total hack because of the code that is
1374
1314
     * in write_record() in sql_insert.cc. During
1375
 
     * a REPLACE statement, a call to ha_write_row() is
1376
 
     * called.  If it fails, then a call to ha_delete_row()
 
1315
     * a REPLACE statement, a call to insertRecord() is
 
1316
     * called.  If it fails, then a call to deleteRecord()
1377
1317
     * is called, followed by a repeat of the original
1378
 
     * call to ha_write_row().  So, log_row_for_replication
1379
 
     * could be called either once or twice for a REPLACE
 
1318
     * call to insertRecord().  So, log_row_for_replication
 
1319
     * could be called multiple times for a REPLACE
1380
1320
     * statement.  The below looks at the values of before_record
1381
1321
     * and after_record to determine which call to this
1382
1322
     * function is for the delete or the insert, since NULL
1389
1329
     */
1390
1330
    if (after_record == NULL)
1391
1331
    {
1392
 
      replication_services.deleteRecord(session, table);
 
1332
      /*
 
1333
       * The storage engine is passed the record in table->record[1]
 
1334
       * as the row to delete (this is the conflicting row), so
 
1335
       * we need to notify TransactionService to use that row.
 
1336
       */
 
1337
      transaction_services.deleteRecord(session, table, true);
1393
1338
      /* 
1394
1339
       * We set the "current" statement message to NULL.  This triggers
1395
1340
       * the replication services component to generate a new statement
1396
1341
       * message for the inserted record which will come next.
1397
1342
       */
1398
 
      replication_services.finalizeStatement(*session->getStatementMessage(), session);
 
1343
      transaction_services.finalizeStatementMessage(*session->getStatementMessage(), session);
1399
1344
    }
1400
1345
    else
1401
1346
    {
1402
1347
      if (before_record == NULL)
1403
 
        result= replication_services.insertRecord(session, table);
 
1348
        result= transaction_services.insertRecord(session, table);
1404
1349
      else
1405
 
        replication_services.updateRecord(session, table, before_record, after_record);
 
1350
        transaction_services.updateRecord(session, table, before_record, after_record);
1406
1351
    }
1407
1352
    break;
1408
1353
  case SQLCOM_INSERT:
1409
1354
  case SQLCOM_INSERT_SELECT:
 
1355
  case SQLCOM_LOAD:
1410
1356
    /*
1411
1357
     * The else block below represents an 
1412
1358
     * INSERT ... ON DUPLICATE KEY UPDATE that
1414
1360
     * an update.
1415
1361
     */
1416
1362
    if (before_record == NULL)
1417
 
      result= replication_services.insertRecord(session, table);
 
1363
      result= transaction_services.insertRecord(session, table);
1418
1364
    else
1419
 
      replication_services.updateRecord(session, table, before_record, after_record);
 
1365
      transaction_services.updateRecord(session, table, before_record, after_record);
1420
1366
    break;
1421
1367
 
1422
1368
  case SQLCOM_UPDATE:
1423
 
    replication_services.updateRecord(session, table, before_record, after_record);
 
1369
    transaction_services.updateRecord(session, table, before_record, after_record);
1424
1370
    break;
1425
1371
 
1426
1372
  case SQLCOM_DELETE:
1427
 
    replication_services.deleteRecord(session, table);
 
1373
    transaction_services.deleteRecord(session, table);
1428
1374
    break;
1429
1375
  default:
1430
1376
    break;
1448
1394
  {
1449
1395
    if (lock_type == F_RDLCK)
1450
1396
    {
1451
 
      DRIZZLE_CURSOR_RDLOCK_START(table_share->db.str,
1452
 
                                  table_share->table_name.str);
 
1397
      DRIZZLE_CURSOR_RDLOCK_START(getTable()->getShare()->getSchemaName(),
 
1398
                                  getTable()->getShare()->getTableName());
1453
1399
    }
1454
1400
    else if (lock_type == F_WRLCK)
1455
1401
    {
1456
 
      DRIZZLE_CURSOR_WRLOCK_START(table_share->db.str,
1457
 
                                  table_share->table_name.str);
 
1402
      DRIZZLE_CURSOR_WRLOCK_START(getTable()->getShare()->getSchemaName(),
 
1403
                                  getTable()->getShare()->getTableName());
1458
1404
    }
1459
1405
    else if (lock_type == F_UNLCK)
1460
1406
    {
1461
 
      DRIZZLE_CURSOR_UNLOCK_START(table_share->db.str,
1462
 
                                  table_share->table_name.str);
 
1407
      DRIZZLE_CURSOR_UNLOCK_START(getTable()->getShare()->getSchemaName(),
 
1408
                                  getTable()->getShare()->getTableName());
1463
1409
    }
1464
1410
  }
1465
1411
 
1498
1444
int Cursor::ha_reset()
1499
1445
{
1500
1446
  /* Check that we have called all proper deallocation functions */
1501
 
  assert((unsigned char*) table->def_read_set.getBitmap() +
1502
 
              table->s->column_bitmap_size ==
1503
 
              (unsigned char*) table->def_write_set.getBitmap());
1504
 
  assert(table->s->all_set.isSetAll());
1505
 
  assert(table->key_read == 0);
1506
 
  /* ensure that ha_index_end / ha_rnd_end has been called */
 
1447
  assert(! getTable()->getShare()->all_set.none());
 
1448
  assert(getTable()->key_read == 0);
 
1449
  /* ensure that ha_index_end / endTableScan has been called */
1507
1450
  assert(inited == NONE);
1508
1451
  /* Free cache used by filesort */
1509
 
  table->free_io_cache();
 
1452
  getTable()->free_io_cache();
1510
1453
  /* reset the bitmaps to point to defaults */
1511
 
  table->default_column_bitmaps();
 
1454
  getTable()->default_column_bitmaps();
1512
1455
  return(reset());
1513
1456
}
1514
1457
 
1515
1458
 
1516
 
int Cursor::ha_write_row(unsigned char *buf)
 
1459
int Cursor::insertRecord(unsigned char *buf)
1517
1460
{
1518
1461
  int error;
1519
1462
 
1523
1466
   * @TODO Technically, the below two lines can be take even further out of the
1524
1467
   * Cursor interface and into the fill_record() method.
1525
1468
   */
1526
 
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
1527
 
    table->timestamp_field->set_time();
 
1469
  if (getTable()->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
 
1470
  {
 
1471
    getTable()->timestamp_field->set_time();
 
1472
  }
1528
1473
 
1529
 
  DRIZZLE_INSERT_ROW_START(table_share->db.str, table_share->table_name.str);
 
1474
  DRIZZLE_INSERT_ROW_START(getTable()->getShare()->getSchemaName(), getTable()->getShare()->getTableName());
1530
1475
  setTransactionReadWrite();
1531
 
  error= write_row(buf);
 
1476
  
 
1477
  if (unlikely(plugin::EventObserver::beforeInsertRecord(*getTable(), buf)))
 
1478
  {
 
1479
    error= ER_EVENT_OBSERVER_PLUGIN;
 
1480
  }
 
1481
  else
 
1482
  {
 
1483
    error= doInsertRecord(buf);
 
1484
    if (unlikely(plugin::EventObserver::afterInsertRecord(*getTable(), buf, error))) 
 
1485
    {
 
1486
      error= ER_EVENT_OBSERVER_PLUGIN;
 
1487
    }
 
1488
  }
 
1489
 
 
1490
  ha_statistic_increment(&system_status_var::ha_write_count);
 
1491
 
1532
1492
  DRIZZLE_INSERT_ROW_DONE(error);
1533
1493
 
1534
1494
  if (unlikely(error))
1536
1496
    return error;
1537
1497
  }
1538
1498
 
1539
 
  if (unlikely(log_row_for_replication(table, NULL, buf)))
 
1499
  if (unlikely(log_row_for_replication(getTable(), NULL, buf)))
1540
1500
    return HA_ERR_RBR_LOGGING_FAILED;
1541
1501
 
1542
1502
  return 0;
1543
1503
}
1544
1504
 
1545
1505
 
1546
 
int Cursor::ha_update_row(const unsigned char *old_data, unsigned char *new_data)
 
1506
int Cursor::updateRecord(const unsigned char *old_data, unsigned char *new_data)
1547
1507
{
1548
1508
  int error;
1549
1509
 
1550
1510
  /*
1551
 
    Some storage engines require that the new record is in record[0]
1552
 
    (and the old record is in record[1]).
 
1511
    Some storage engines require that the new record is in getInsertRecord()
 
1512
    (and the old record is in getUpdateRecord()).
1553
1513
   */
1554
 
  assert(new_data == table->record[0]);
 
1514
  assert(new_data == getTable()->getInsertRecord());
1555
1515
 
1556
 
  DRIZZLE_UPDATE_ROW_START(table_share->db.str, table_share->table_name.str);
 
1516
  DRIZZLE_UPDATE_ROW_START(getTable()->getShare()->getSchemaName(), getTable()->getShare()->getTableName());
1557
1517
  setTransactionReadWrite();
1558
 
  error= update_row(old_data, new_data);
 
1518
  if (unlikely(plugin::EventObserver::beforeUpdateRecord(*getTable(), old_data, new_data)))
 
1519
  {
 
1520
    error= ER_EVENT_OBSERVER_PLUGIN;
 
1521
  }
 
1522
  else
 
1523
  {
 
1524
    if (getTable()->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
 
1525
    {
 
1526
      getTable()->timestamp_field->set_time();
 
1527
    }
 
1528
 
 
1529
    error= doUpdateRecord(old_data, new_data);
 
1530
    if (unlikely(plugin::EventObserver::afterUpdateRecord(*getTable(), old_data, new_data, error)))
 
1531
    {
 
1532
      error= ER_EVENT_OBSERVER_PLUGIN;
 
1533
    }
 
1534
  }
 
1535
 
 
1536
  ha_statistic_increment(&system_status_var::ha_update_count);
 
1537
 
1559
1538
  DRIZZLE_UPDATE_ROW_DONE(error);
1560
1539
 
1561
1540
  if (unlikely(error))
1563
1542
    return error;
1564
1543
  }
1565
1544
 
1566
 
  if (unlikely(log_row_for_replication(table, old_data, new_data)))
 
1545
  if (unlikely(log_row_for_replication(getTable(), old_data, new_data)))
1567
1546
    return HA_ERR_RBR_LOGGING_FAILED;
1568
1547
 
1569
1548
  return 0;
1570
1549
}
 
1550
TableShare *Cursor::getShare()
 
1551
{
 
1552
  return getTable()->getMutableShare();
 
1553
}
1571
1554
 
1572
 
int Cursor::ha_delete_row(const unsigned char *buf)
 
1555
int Cursor::deleteRecord(const unsigned char *buf)
1573
1556
{
1574
1557
  int error;
1575
1558
 
1576
 
  DRIZZLE_DELETE_ROW_START(table_share->db.str, table_share->table_name.str);
 
1559
  DRIZZLE_DELETE_ROW_START(getTable()->getShare()->getSchemaName(), getTable()->getShare()->getTableName());
1577
1560
  setTransactionReadWrite();
1578
 
  error= delete_row(buf);
 
1561
  if (unlikely(plugin::EventObserver::beforeDeleteRecord(*getTable(), buf)))
 
1562
  {
 
1563
    error= ER_EVENT_OBSERVER_PLUGIN;
 
1564
  }
 
1565
  else
 
1566
  {
 
1567
    error= doDeleteRecord(buf);
 
1568
    if (unlikely(plugin::EventObserver::afterDeleteRecord(*getTable(), buf, error)))
 
1569
    {
 
1570
      error= ER_EVENT_OBSERVER_PLUGIN;
 
1571
    }
 
1572
  }
 
1573
 
 
1574
  ha_statistic_increment(&system_status_var::ha_delete_count);
 
1575
 
1579
1576
  DRIZZLE_DELETE_ROW_DONE(error);
1580
1577
 
1581
1578
  if (unlikely(error))
1582
1579
    return error;
1583
1580
 
1584
 
  if (unlikely(log_row_for_replication(table, buf, NULL)))
 
1581
  if (unlikely(log_row_for_replication(getTable(), buf, NULL)))
1585
1582
    return HA_ERR_RBR_LOGGING_FAILED;
1586
1583
 
1587
1584
  return 0;