~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/cursor.cc

  • Committer: Stewart Smith
  • Date: 2010-04-07 02:08:20 UTC
  • mto: (1283.38.1)
  • mto: This revision was merged to the branch mainline in revision 1536.
  • Revision ID: stewart@flamingspork.com-20100407020820-4elzp2uuorw5vv89
add basic_create_select test that currently causes a crash due to https://bugs.launchpad.net/drizzle/+bug/556978

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
3
 *
4
 
 *  Copyright (C) 2008 Sun Microsystems, Inc.
 
4
 *  Copyright (C) 2008 Sun Microsystems
5
5
 *
6
6
 *  This program is free software; you can redistribute it and/or modify
7
7
 *  it under the terms of the GNU General Public License as published by
23
23
  Handler-calling-functions
24
24
*/
25
25
 
26
 
#include <config.h>
 
26
#include "config.h"
27
27
 
28
28
#include <fcntl.h>
29
29
 
30
 
#include <drizzled/error.h>
31
 
#include <drizzled/field/epoch.h>
32
 
#include <drizzled/gettext.h>
33
 
#include <drizzled/internal/my_sys.h>
34
 
#include <drizzled/item/empty_string.h>
35
 
#include <drizzled/item/int.h>
36
 
#include <drizzled/lock.h>
37
 
#include <drizzled/message/table.h>
38
 
#include <drizzled/my_hash.h>
39
 
#include <drizzled/optimizer/cost_vector.h>
40
 
#include <drizzled/plugin/client.h>
41
 
#include <drizzled/plugin/event_observer.h>
42
 
#include <drizzled/plugin/storage_engine.h>
43
 
#include <drizzled/probes.h>
44
 
#include <drizzled/session.h>
45
 
#include <drizzled/sql_base.h>
46
 
#include <drizzled/sql_parse.h>
47
 
#include <drizzled/transaction_services.h>
 
30
#include "drizzled/my_hash.h"
 
31
#include "drizzled/error.h"
 
32
#include "drizzled/gettext.h"
 
33
#include "drizzled/probes.h"
 
34
#include "drizzled/sql_parse.h"
 
35
#include "drizzled/optimizer/cost_vector.h"
 
36
#include "drizzled/session.h"
 
37
#include "drizzled/sql_base.h"
 
38
#include "drizzled/transaction_services.h"
 
39
#include "drizzled/replication_services.h"
 
40
#include "drizzled/lock.h"
 
41
#include "drizzled/item/int.h"
 
42
#include "drizzled/item/empty_string.h"
 
43
#include "drizzled/field/timestamp.h"
 
44
#include "drizzled/message/table.pb.h"
 
45
#include "drizzled/plugin/client.h"
 
46
#include "drizzled/internal/my_sys.h"
 
47
#include "drizzled/transaction_services.h"
48
48
 
49
49
using namespace std;
50
50
 
55
55
** General Cursor functions
56
56
****************************************************************************/
57
57
Cursor::Cursor(plugin::StorageEngine &engine_arg,
58
 
               Table &arg)
59
 
  : table(arg),
60
 
    engine(engine_arg),
61
 
    estimation_rows_to_insert(0),
62
 
    ref(0),
 
58
               TableShare &share_arg)
 
59
  : table_share(&share_arg), table(0),
 
60
    estimation_rows_to_insert(0), engine(&engine_arg),
 
61
    ref(0), in_range_check_pushed_down(false),
63
62
    key_used_on_scan(MAX_KEY), active_index(MAX_KEY),
64
63
    ref_length(sizeof(internal::my_off_t)),
65
64
    inited(NONE),
66
 
    locked(false),
 
65
    locked(false), implicit_emptied(0),
67
66
    next_insert_id(0), insert_id_for_cur_row(0)
68
67
{ }
69
68
 
74
73
}
75
74
 
76
75
 
77
 
/*
78
 
 * @note this only used in
79
 
 * optimizer::QuickRangeSelect::init_ror_merged_scan(bool reuse_handler) as
80
 
 * of the writing of this comment. -Brian
81
 
 */
82
76
Cursor *Cursor::clone(memory::Root *mem_root)
83
77
{
84
 
  Cursor *new_handler= getTable()->getMutableShare()->db_type()->getCursor(*getTable());
 
78
  Cursor *new_handler= table->s->db_type()->getCursor(*table->s, mem_root);
85
79
 
86
80
  /*
87
81
    Allocate Cursor->ref here because otherwise ha_open will allocate it
88
82
    on this->table->mem_root and we will not be able to reclaim that memory
89
83
    when the clone Cursor object is destroyed.
90
84
  */
91
 
  if (!(new_handler->ref= (unsigned char*) mem_root->alloc_root(ALIGN_SIZE(ref_length)*2)))
 
85
  if (!(new_handler->ref= (unsigned char*) alloc_root(mem_root, ALIGN_SIZE(ref_length)*2)))
92
86
    return NULL;
93
 
 
94
 
  identifier::Table identifier(getTable()->getShare()->getSchemaName(),
95
 
                             getTable()->getShare()->getTableName(),
96
 
                             getTable()->getShare()->getType());
97
 
 
98
 
  if (new_handler && !new_handler->ha_open(identifier,
99
 
                                           getTable()->getDBStat(),
 
87
  if (new_handler && !new_handler->ha_open(table,
 
88
                                           table->s->normalized_path.str,
 
89
                                           table->getDBStat(),
100
90
                                           HA_OPEN_IGNORE_IF_LOCKED))
101
91
    return new_handler;
102
92
  return NULL;
103
93
}
104
94
 
105
 
/*
106
 
  DESCRIPTION
107
 
    given a buffer with a key value, and a map of keyparts
108
 
    that are present in this value, returns the length of the value
109
 
*/
110
 
uint32_t Cursor::calculate_key_len(uint32_t key_position, key_part_map keypart_map_arg)
111
 
{
112
 
  /* works only with key prefixes */
113
 
  assert(((keypart_map_arg + 1) & keypart_map_arg) == 0);
114
 
 
115
 
  const KeyPartInfo *key_part_found= getTable()->getShare()->getKeyInfo(key_position).key_part;
116
 
  const KeyPartInfo *end_key_part_found= key_part_found + getTable()->getShare()->getKeyInfo(key_position).key_parts;
117
 
  uint32_t length= 0;
118
 
 
119
 
  while (key_part_found < end_key_part_found && keypart_map_arg)
120
 
  {
121
 
    length+= key_part_found->store_length;
122
 
    keypart_map_arg >>= 1;
123
 
    key_part_found++;
124
 
  }
125
 
  return length;
126
 
}
127
 
 
128
 
int Cursor::startIndexScan(uint32_t idx, bool sorted)
 
95
int Cursor::ha_index_init(uint32_t idx, bool sorted)
129
96
{
130
97
  int result;
131
98
  assert(inited == NONE);
132
 
  if (!(result= doStartIndexScan(idx, sorted)))
 
99
  if (!(result= index_init(idx, sorted)))
133
100
    inited=INDEX;
134
101
  end_range= NULL;
135
102
  return result;
136
103
}
137
104
 
138
 
int Cursor::endIndexScan()
 
105
int Cursor::ha_index_end()
139
106
{
140
107
  assert(inited==INDEX);
141
108
  inited=NONE;
142
109
  end_range= NULL;
143
 
  return(doEndIndexScan());
 
110
  return(index_end());
144
111
}
145
112
 
146
 
int Cursor::startTableScan(bool scan)
 
113
int Cursor::ha_rnd_init(bool scan)
147
114
{
148
115
  int result;
149
116
  assert(inited==NONE || (inited==RND && scan));
150
 
  inited= (result= doStartTableScan(scan)) ? NONE: RND;
 
117
  inited= (result= rnd_init(scan)) ? NONE: RND;
151
118
 
152
119
  return result;
153
120
}
154
121
 
155
 
int Cursor::endTableScan()
 
122
int Cursor::ha_rnd_end()
156
123
{
157
124
  assert(inited==RND);
158
125
  inited=NONE;
159
 
  return(doEndTableScan());
 
126
  return(rnd_end());
160
127
}
161
128
 
162
129
int Cursor::ha_index_or_rnd_end()
163
130
{
164
 
  return inited == INDEX ? endIndexScan() : inited == RND ? endTableScan() : 0;
 
131
  return inited == INDEX ? ha_index_end() : inited == RND ? ha_rnd_end() : 0;
165
132
}
166
133
 
167
134
void Cursor::ha_start_bulk_insert(ha_rows rows)
176
143
  return end_bulk_insert();
177
144
}
178
145
 
 
146
void Cursor::change_table_ptr(Table *table_arg, TableShare *share)
 
147
{
 
148
  table= table_arg;
 
149
  table_share= share;
 
150
}
 
151
 
179
152
const key_map *Cursor::keys_to_use_for_scanning()
180
153
{
181
154
  return &key_map_empty;
183
156
 
184
157
bool Cursor::has_transactions()
185
158
{
186
 
  return (getTable()->getShare()->db_type()->check_flag(HTON_BIT_DOES_TRANSACTIONS));
 
159
  return (table->s->db_type()->check_flag(HTON_BIT_DOES_TRANSACTIONS));
187
160
}
188
161
 
189
 
void Cursor::ha_statistic_increment(uint64_t system_status_var::*offset) const
 
162
void Cursor::ha_statistic_increment(ulong system_status_var::*offset) const
190
163
{
191
 
  (getTable()->in_use->status_var.*offset)++;
 
164
  status_var_increment(table->in_use->status_var.*offset);
192
165
}
193
166
 
194
167
void **Cursor::ha_data(Session *session) const
195
168
{
196
 
  return session->getEngineData(getEngine());
197
 
}
 
169
  return session->getEngineData(engine);
 
170
}
 
171
 
 
172
Session *Cursor::ha_session(void) const
 
173
{
 
174
  assert(!table || !table->in_use || table->in_use == current_session);
 
175
  return (table && table->in_use) ? table->in_use : current_session;
 
176
}
 
177
 
198
178
 
199
179
bool Cursor::is_fatal_error(int error, uint32_t flags)
200
180
{
209
189
 
210
190
ha_rows Cursor::records() { return stats.records; }
211
191
uint64_t Cursor::tableSize() { return stats.index_file_length + stats.data_file_length; }
212
 
uint64_t Cursor::rowSize() { return getTable()->getRecordLength() + getTable()->sizeFields(); }
213
 
 
214
 
int Cursor::doOpen(const identifier::Table &identifier, int mode, uint32_t test_if_locked)
215
 
{
216
 
  return open(identifier.getPath().c_str(), mode, test_if_locked);
217
 
}
 
192
uint64_t Cursor::rowSize() { return table->getRecordLength() + table->sizeFields(); }
218
193
 
219
194
/**
220
195
  Open database-Cursor.
222
197
  Try O_RDONLY if cannot open as O_RDWR
223
198
  Don't wait for locks if not HA_OPEN_WAIT_IF_LOCKED is set
224
199
*/
225
 
int Cursor::ha_open(const identifier::Table &identifier,
226
 
                    int mode,
227
 
                    int test_if_locked)
 
200
int Cursor::ha_open(Table *table_arg, const char *name, int mode,
 
201
                     int test_if_locked)
228
202
{
229
203
  int error;
230
204
 
231
 
  if ((error= doOpen(identifier, mode, test_if_locked)))
 
205
  table= table_arg;
 
206
  assert(table->s == table_share);
 
207
  assert(alloc_root_inited(&table->mem_root));
 
208
 
 
209
  if ((error=open(name, mode, test_if_locked)))
232
210
  {
233
211
    if ((error == EACCES || error == EROFS) && mode == O_RDWR &&
234
 
        (getTable()->db_stat & HA_TRY_READ_ONLY))
 
212
        (table->db_stat & HA_TRY_READ_ONLY))
235
213
    {
236
 
      getTable()->db_stat|=HA_READ_ONLY;
237
 
      error= doOpen(identifier, O_RDONLY,test_if_locked);
 
214
      table->db_stat|=HA_READ_ONLY;
 
215
      error=open(name,O_RDONLY,test_if_locked);
238
216
    }
239
217
  }
240
218
  if (error)
243
221
  }
244
222
  else
245
223
  {
246
 
    if (getTable()->getShare()->db_options_in_use & HA_OPTION_READ_ONLY_DATA)
247
 
      getTable()->db_stat|=HA_READ_ONLY;
 
224
    if (table->s->db_options_in_use & HA_OPTION_READ_ONLY_DATA)
 
225
      table->db_stat|=HA_READ_ONLY;
248
226
    (void) extra(HA_EXTRA_NO_READCHECK);        // Not needed in SQL
249
227
 
250
228
    /* ref is already allocated for us if we're called from Cursor::clone() */
251
 
    if (!ref && !(ref= (unsigned char*) getTable()->alloc_root(ALIGN_SIZE(ref_length)*2)))
 
229
    if (!ref && !(ref= (unsigned char*) alloc_root(&table->mem_root,
 
230
                                          ALIGN_SIZE(ref_length)*2)))
252
231
    {
253
232
      close();
254
233
      error=HA_ERR_OUT_OF_MEM;
260
239
}
261
240
 
262
241
/**
 
242
  one has to use this method when to find
 
243
  random position by record as the plain
 
244
  position() call doesn't work for some
 
245
  handlers for random position
 
246
*/
 
247
 
 
248
int Cursor::rnd_pos_by_record(unsigned char *record)
 
249
{
 
250
  register int error;
 
251
 
 
252
  position(record);
 
253
  if (inited && (error= ha_index_end()))
 
254
    return error;
 
255
  if ((error= ha_rnd_init(false)))
 
256
    return error;
 
257
 
 
258
  return rnd_pos(record, ref);
 
259
}
 
260
 
 
261
/**
263
262
  Read first row (only) from a table.
264
263
 
265
264
  This is never called for InnoDB tables, as these table types
267
266
*/
268
267
int Cursor::read_first_row(unsigned char * buf, uint32_t primary_key)
269
268
{
270
 
  int error;
 
269
  register int error;
271
270
 
272
271
  ha_statistic_increment(&system_status_var::ha_read_first_count);
273
272
 
274
273
  /*
275
274
    If there is very few deleted rows in the table, find the first row by
276
275
    scanning the table.
277
 
    @todo remove the test for HA_READ_ORDER
 
276
    TODO remove the test for HA_READ_ORDER
278
277
  */
279
278
  if (stats.deleted < 10 || primary_key >= MAX_KEY ||
280
 
      !(getTable()->index_flags(primary_key) & HA_READ_ORDER))
 
279
      !(table->index_flags(primary_key) & HA_READ_ORDER))
281
280
  {
282
 
    error= startTableScan(1);
283
 
    if (error == 0)
284
 
    {
285
 
      while ((error= rnd_next(buf)) == HA_ERR_RECORD_DELETED) ;
286
 
      (void) endTableScan();
287
 
    }
 
281
    (void) ha_rnd_init(1);
 
282
    while ((error= rnd_next(buf)) == HA_ERR_RECORD_DELETED) ;
 
283
    (void) ha_rnd_end();
288
284
  }
289
285
  else
290
286
  {
291
287
    /* Find the first row through the primary key */
292
 
    error= startIndexScan(primary_key, 0);
293
 
    if (error == 0)
294
 
    {
295
 
      error=index_first(buf);
296
 
      (void) endIndexScan();
297
 
    }
 
288
    (void) ha_index_init(primary_key, 0);
 
289
    error=index_first(buf);
 
290
    (void) ha_index_end();
298
291
  }
299
292
  return error;
300
293
}
311
304
  @verbatim 1,5,15,25,35,... @endverbatim
312
305
*/
313
306
inline uint64_t
314
 
compute_next_insert_id(uint64_t nr, drizzle_system_variables *variables)
 
307
compute_next_insert_id(uint64_t nr,struct system_variables *variables)
315
308
{
316
309
  if (variables->auto_increment_increment == 1)
317
310
    return (nr+1); // optimization of the formula below
331
324
    Session::next_insert_id to be greater than the explicit value.
332
325
  */
333
326
  if ((next_insert_id > 0) && (nr >= next_insert_id))
334
 
    set_next_insert_id(compute_next_insert_id(nr, &getTable()->in_use->variables));
 
327
    set_next_insert_id(compute_next_insert_id(nr, &table->in_use->variables));
335
328
}
336
329
 
337
330
 
351
344
    The number X if it exists, "nr" otherwise.
352
345
*/
353
346
inline uint64_t
354
 
prev_insert_id(uint64_t nr, drizzle_system_variables *variables)
 
347
prev_insert_id(uint64_t nr, struct system_variables *variables)
355
348
{
356
349
  if (unlikely(nr < variables->auto_increment_offset))
357
350
  {
448
441
{
449
442
  uint64_t nr, nb_reserved_values;
450
443
  bool append= false;
451
 
  Session *session= getTable()->in_use;
452
 
  drizzle_system_variables *variables= &session->variables;
 
444
  Session *session= table->in_use;
 
445
  struct system_variables *variables= &session->variables;
453
446
 
454
447
  /*
455
448
    next_insert_id is a "cursor" into the reserved interval, it may go greater
461
454
     for an auto increment column, not a magic value like NULL is.
462
455
     same as sql_mode=NO_AUTO_VALUE_ON_ZERO */
463
456
 
464
 
  if ((nr= getTable()->next_number_field->val_int()) != 0
465
 
      || getTable()->auto_increment_field_not_null)
 
457
  if ((nr= table->next_number_field->val_int()) != 0
 
458
      || table->auto_increment_field_not_null)
466
459
  {
467
460
    /*
468
461
      Update next_insert_id if we had already generated a value in this
540
533
      nr= compute_next_insert_id(nr-1, variables);
541
534
    }
542
535
 
543
 
    if (getTable()->getShare()->next_number_keypart == 0)
 
536
    if (table->s->next_number_keypart == 0)
544
537
    {
545
538
      /* We must defer the appending until "nr" has been possibly truncated */
546
539
      append= true;
547
540
    }
548
541
  }
549
542
 
550
 
  if (unlikely(getTable()->next_number_field->store((int64_t) nr, true)))
 
543
  if (unlikely(table->next_number_field->store((int64_t) nr, true)))
551
544
  {
552
545
    /*
553
546
      first test if the query was aborted due to strict mode constraints
554
547
    */
555
 
    if (session->getKilled() == Session::KILL_BAD_DATA)
 
548
    if (session->killed == Session::KILL_BAD_DATA)
556
549
      return HA_ERR_AUTOINC_ERANGE;
557
550
 
558
551
    /*
563
556
      bother shifting the right bound (anyway any other value from this
564
557
      interval will cause a duplicate key).
565
558
    */
566
 
    nr= prev_insert_id(getTable()->next_number_field->val_int(), variables);
567
 
    if (unlikely(getTable()->next_number_field->store((int64_t) nr, true)))
568
 
      nr= getTable()->next_number_field->val_int();
 
559
    nr= prev_insert_id(table->next_number_field->val_int(), variables);
 
560
    if (unlikely(table->next_number_field->store((int64_t) nr, true)))
 
561
      nr= table->next_number_field->val_int();
569
562
  }
570
563
  if (append)
571
564
  {
619
612
      this statement used forced auto_increment values if there were some,
620
613
      wipe them away for other statements.
621
614
    */
622
 
    getTable()->in_use->auto_inc_intervals_forced.empty();
 
615
    table->in_use->auto_inc_intervals_forced.empty();
623
616
  }
624
617
}
625
618
 
658
651
void
659
652
Cursor::setTransactionReadWrite()
660
653
{
661
 
  ResourceContext *resource_context;
662
 
 
663
 
  /*
664
 
   * If the cursor has not context for execution then there should be no
665
 
   * possible resource to gain (and if there is... then there is a bug such
666
 
   * that in_use should have been set.
667
 
 */
668
 
  if (not getTable()->in_use)
669
 
    return;
670
 
 
671
 
  resource_context= getTable()->in_use->getResourceContext(getEngine());
 
654
  ResourceContext *resource_context= ha_session()->getResourceContext(engine);
672
655
  /*
673
656
    When a storage engine method is called, the transaction must
674
657
    have been started, unless it's a DDL call, for which the
709
692
     * @todo Make TransactionServices generic to AfterTriggerServices
710
693
     * or similar...
711
694
     */
712
 
    Session *const session= getTable()->in_use;
 
695
    Session *const session= table->in_use;
713
696
    TransactionServices &transaction_services= TransactionServices::singleton();
714
 
    transaction_services.truncateTable(*session, *getTable());
 
697
    transaction_services.truncateTable(session, table);
715
698
  }
716
699
 
717
700
  return result;
810
793
  int error;
811
794
  if (!(error=index_next(buf)))
812
795
  {
813
 
    ptrdiff_t ptrdiff= buf - getTable()->getInsertRecord();
 
796
    ptrdiff_t ptrdiff= buf - table->record[0];
814
797
    unsigned char *save_record_0= NULL;
815
 
    KeyInfo *key_info= NULL;
816
 
    KeyPartInfo *key_part;
817
 
    KeyPartInfo *key_part_end= NULL;
 
798
    KEY *key_info= NULL;
 
799
    KEY_PART_INFO *key_part;
 
800
    KEY_PART_INFO *key_part_end= NULL;
818
801
 
819
802
    /*
820
 
      key_cmp_if_same() compares table->getInsertRecord() against 'key'.
821
 
      In parts it uses table->getInsertRecord() directly, in parts it uses
822
 
      field objects with their local pointers into table->getInsertRecord().
823
 
      If 'buf' is distinct from table->getInsertRecord(), we need to move
824
 
      all record references. This is table->getInsertRecord() itself and
 
803
      key_cmp_if_same() compares table->record[0] against 'key'.
 
804
      In parts it uses table->record[0] directly, in parts it uses
 
805
      field objects with their local pointers into table->record[0].
 
806
      If 'buf' is distinct from table->record[0], we need to move
 
807
      all record references. This is table->record[0] itself and
825
808
      the field pointers of the fields used in this key.
826
809
    */
827
810
    if (ptrdiff)
828
811
    {
829
 
      save_record_0= getTable()->getInsertRecord();
830
 
      getTable()->record[0]= buf;
831
 
      key_info= getTable()->key_info + active_index;
 
812
      save_record_0= table->record[0];
 
813
      table->record[0]= buf;
 
814
      key_info= table->key_info + active_index;
832
815
      key_part= key_info->key_part;
833
816
      key_part_end= key_part + key_info->key_parts;
834
817
      for (; key_part < key_part_end; key_part++)
838
821
      }
839
822
    }
840
823
 
841
 
    if (key_cmp_if_same(getTable(), key, active_index, keylen))
 
824
    if (key_cmp_if_same(table, key, active_index, keylen))
842
825
    {
843
 
      getTable()->status=STATUS_NOT_FOUND;
 
826
      table->status=STATUS_NOT_FOUND;
844
827
      error=HA_ERR_END_OF_FILE;
845
828
    }
846
829
 
847
830
    /* Move back if necessary. */
848
831
    if (ptrdiff)
849
832
    {
850
 
      getTable()->record[0]= save_record_0;
 
833
      table->record[0]= save_record_0;
851
834
      for (key_part= key_info->key_part; key_part < key_part_end; key_part++)
852
835
        key_part->field->move_field_offset(-ptrdiff);
853
836
    }
884
867
double Cursor::index_only_read_time(uint32_t keynr, double key_records)
885
868
{
886
869
  uint32_t keys_per_block= (stats.block_size/2/
887
 
                        (getTable()->key_info[keynr].key_length + ref_length) + 1);
 
870
                        (table->key_info[keynr].key_length + ref_length) + 1);
888
871
  return ((double) (key_records + keys_per_block-1) /
889
872
          (double) keys_per_block);
890
873
}
913
896
 
914
897
  @note
915
898
    This method (or an overriding one in a derived class) must check for
916
 
    session->getKilled() and return HA_POS_ERROR if it is not zero. This is required
 
899
    session->killed and return HA_POS_ERROR if it is not zero. This is required
917
900
    for a user to be able to interrupt the calculation by killing the
918
901
    connection/query.
919
902
 
935
918
  range_seq_t seq_it;
936
919
  ha_rows rows, total_rows= 0;
937
920
  uint32_t n_ranges=0;
 
921
  Session *session= current_session;
938
922
 
939
923
  /* Default MRR implementation doesn't need buffer */
940
924
  *bufsz= 0;
942
926
  seq_it= seq->init(seq_init_param, n_ranges, *flags);
943
927
  while (!seq->next(seq_it, &range))
944
928
  {
 
929
    if (unlikely(session->killed != 0))
 
930
      return HA_POS_ERROR;
 
931
 
945
932
    n_ranges++;
946
933
    key_range *min_endp, *max_endp;
947
934
    {
1051
1038
  @param buf             INOUT: memory buffer to be used
1052
1039
 
1053
1040
  @note
1054
 
    One must have called doStartIndexScan() before calling this function. Several
 
1041
    One must have called index_init() before calling this function. Several
1055
1042
    multi_range_read_init() calls may be made in course of one query.
1056
1043
 
1057
1044
    Until WL#2623 is done (see its text, section 3.2), the following will
1066
1053
    The callee consumes all or some fraction of the provided buffer space, and
1067
1054
    sets the HANDLER_BUFFER members accordingly.
1068
1055
    The callee may use the buffer memory until the next multi_range_read_init()
1069
 
    call is made, all records have been read, or until doEndIndexScan() call is
 
1056
    call is made, all records have been read, or until index_end() call is
1070
1057
    made, whichever comes first.
1071
1058
 
1072
1059
  @retval 0  OK
1075
1062
 
1076
1063
int
1077
1064
Cursor::multi_range_read_init(RANGE_SEQ_IF *seq_funcs, void *seq_init_param,
1078
 
                               uint32_t n_ranges, uint32_t mode)
 
1065
                               uint32_t n_ranges, uint32_t mode,
 
1066
                               HANDLER_BUFFER *)
1079
1067
{
1080
1068
  mrr_iter= seq_funcs->init(seq_init_param, n_ranges, mode);
1081
1069
  mrr_funcs= *seq_funcs;
1082
1070
  mrr_is_output_sorted= test(mode & HA_MRR_SORTED);
1083
1071
  mrr_have_range= false;
1084
 
 
1085
1072
  return 0;
1086
1073
}
1087
1074
 
1104
1091
  int result= 0;
1105
1092
  int range_res= 0;
1106
1093
 
1107
 
  if (not mrr_have_range)
 
1094
  if (!mrr_have_range)
1108
1095
  {
1109
1096
    mrr_have_range= true;
1110
1097
    goto start;
1166
1153
  @param sorted         Set to 1 if result should be sorted per key
1167
1154
 
1168
1155
  @note
1169
 
    Record is read into table->getInsertRecord()
 
1156
    Record is read into table->record[0]
1170
1157
 
1171
1158
  @retval
1172
1159
    0                   Found row
1191
1178
    key_compare_result_on_equal= ((end_key->flag == HA_READ_BEFORE_KEY) ? 1 :
1192
1179
                                  (end_key->flag == HA_READ_AFTER_KEY) ? -1 : 0);
1193
1180
  }
1194
 
  range_key_part= getTable()->key_info[active_index].key_part;
 
1181
  range_key_part= table->key_info[active_index].key_part;
1195
1182
 
1196
1183
  if (!start_key)                       // Read first record
1197
 
    result= index_first(getTable()->getInsertRecord());
 
1184
    result= index_first(table->record[0]);
1198
1185
  else
1199
 
    result= index_read_map(getTable()->getInsertRecord(),
 
1186
    result= index_read_map(table->record[0],
1200
1187
                           start_key->key,
1201
1188
                           start_key->keypart_map,
1202
1189
                           start_key->flag);
1213
1200
  Read next row between two endpoints.
1214
1201
 
1215
1202
  @note
1216
 
    Record is read into table->getInsertRecord()
 
1203
    Record is read into table->record[0]
1217
1204
 
1218
1205
  @retval
1219
1206
    0                   Found row
1229
1216
  if (eq_range)
1230
1217
  {
1231
1218
    /* We trust that index_next_same always gives a row in range */
1232
 
    return(index_next_same(getTable()->getInsertRecord(),
 
1219
    return(index_next_same(table->record[0],
1233
1220
                                end_range->key,
1234
1221
                                end_range->length));
1235
1222
  }
1236
 
  result= index_next(getTable()->getInsertRecord());
 
1223
  result= index_next(table->record[0]);
1237
1224
  if (result)
1238
1225
    return result;
1239
1226
  return(compare_key(end_range) <= 0 ? 0 : HA_ERR_END_OF_FILE);
1258
1245
int Cursor::compare_key(key_range *range)
1259
1246
{
1260
1247
  int cmp;
1261
 
  if (not range)
 
1248
  if (!range || in_range_check_pushed_down)
1262
1249
    return 0;                                   // No max range
1263
1250
  cmp= key_cmp(range_key_part, range->key, range->length);
1264
1251
  if (!cmp)
1266
1253
  return cmp;
1267
1254
}
1268
1255
 
 
1256
 
 
1257
/*
 
1258
  Same as compare_key() but doesn't check have in_range_check_pushed_down.
 
1259
  This is used by index condition pushdown implementation.
 
1260
*/
 
1261
 
 
1262
int Cursor::compare_key2(key_range *range)
 
1263
{
 
1264
  int cmp;
 
1265
  if (!range)
 
1266
    return 0;                                   // no max range
 
1267
  cmp= key_cmp(range_key_part, range->key, range->length);
 
1268
  if (!cmp)
 
1269
    cmp= key_compare_result_on_equal;
 
1270
  return cmp;
 
1271
}
 
1272
 
1269
1273
int Cursor::index_read_idx_map(unsigned char * buf, uint32_t index,
1270
1274
                                const unsigned char * key,
1271
1275
                                key_part_map keypart_map,
1272
1276
                                enum ha_rkey_function find_flag)
1273
1277
{
1274
1278
  int error, error1;
1275
 
  error= doStartIndexScan(index, 0);
 
1279
  error= index_init(index, 0);
1276
1280
  if (!error)
1277
1281
  {
1278
1282
    error= index_read_map(buf, key, keypart_map, find_flag);
1279
 
    error1= doEndIndexScan();
 
1283
    error1= index_end();
1280
1284
  }
1281
1285
  return error ?  error : error1;
1282
1286
}
1293
1297
                                    const unsigned char *after_record)
1294
1298
{
1295
1299
  TransactionServices &transaction_services= TransactionServices::singleton();
 
1300
  ReplicationServices &replication_services= ReplicationServices::singleton();
1296
1301
  Session *const session= table->in_use;
1297
1302
 
1298
 
  if (table->getShare()->getType() || not transaction_services.shouldConstructMessages())
 
1303
  if (table->s->tmp_table || not replication_services.isActive())
1299
1304
    return false;
1300
1305
 
1301
1306
  bool result= false;
1302
1307
 
1303
 
  switch (session->getLex()->sql_command)
 
1308
  switch (session->lex->sql_command)
1304
1309
  {
1305
1310
  case SQLCOM_CREATE_TABLE:
1306
1311
    /*
1312
1317
     * CREATE TABLE will commit the transaction containing
1313
1318
     * it).
1314
1319
     */
1315
 
    result= transaction_services.insertRecord(*session, *table);
 
1320
    result= transaction_services.insertRecord(session, table);
1316
1321
    break;
1317
1322
  case SQLCOM_REPLACE:
1318
1323
  case SQLCOM_REPLACE_SELECT:
1319
1324
    /*
1320
1325
     * This is a total hack because of the code that is
1321
1326
     * in write_record() in sql_insert.cc. During
1322
 
     * a REPLACE statement, a call to insertRecord() is
1323
 
     * called.  If it fails, then a call to deleteRecord()
 
1327
     * a REPLACE statement, a call to ha_write_row() is
 
1328
     * called.  If it fails, then a call to ha_delete_row()
1324
1329
     * is called, followed by a repeat of the original
1325
 
     * call to insertRecord().  So, log_row_for_replication
1326
 
     * could be called multiple times for a REPLACE
 
1330
     * call to ha_write_row().  So, log_row_for_replication
 
1331
     * could be called either once or twice for a REPLACE
1327
1332
     * statement.  The below looks at the values of before_record
1328
1333
     * and after_record to determine which call to this
1329
1334
     * function is for the delete or the insert, since NULL
1336
1341
     */
1337
1342
    if (after_record == NULL)
1338
1343
    {
1339
 
      /*
1340
 
       * The storage engine is passed the record in table->record[1]
1341
 
       * as the row to delete (this is the conflicting row), so
1342
 
       * we need to notify TransactionService to use that row.
1343
 
       */
1344
 
      transaction_services.deleteRecord(*session, *table, true);
 
1344
      transaction_services.deleteRecord(session, table);
1345
1345
      /* 
1346
1346
       * We set the "current" statement message to NULL.  This triggers
1347
1347
       * the replication services component to generate a new statement
1348
1348
       * message for the inserted record which will come next.
1349
1349
       */
1350
 
      transaction_services.finalizeStatementMessage(*session->getStatementMessage(), *session);
 
1350
      transaction_services.finalizeStatementMessage(*session->getStatementMessage(), session);
1351
1351
    }
1352
1352
    else
1353
1353
    {
1354
1354
      if (before_record == NULL)
1355
 
        result= transaction_services.insertRecord(*session, *table);
 
1355
        result= transaction_services.insertRecord(session, table);
1356
1356
      else
1357
 
        transaction_services.updateRecord(*session, *table, before_record, after_record);
 
1357
        transaction_services.updateRecord(session, table, before_record, after_record);
1358
1358
    }
1359
1359
    break;
1360
1360
  case SQLCOM_INSERT:
1361
1361
  case SQLCOM_INSERT_SELECT:
1362
 
  case SQLCOM_LOAD:
1363
1362
    /*
1364
1363
     * The else block below represents an 
1365
1364
     * INSERT ... ON DUPLICATE KEY UPDATE that
1367
1366
     * an update.
1368
1367
     */
1369
1368
    if (before_record == NULL)
1370
 
      result= transaction_services.insertRecord(*session, *table);
 
1369
      result= transaction_services.insertRecord(session, table);
1371
1370
    else
1372
 
      transaction_services.updateRecord(*session, *table, before_record, after_record);
 
1371
      transaction_services.updateRecord(session, table, before_record, after_record);
1373
1372
    break;
1374
1373
 
1375
1374
  case SQLCOM_UPDATE:
1376
 
    transaction_services.updateRecord(*session, *table, before_record, after_record);
 
1375
    transaction_services.updateRecord(session, table, before_record, after_record);
1377
1376
    break;
1378
1377
 
1379
1378
  case SQLCOM_DELETE:
1380
 
    transaction_services.deleteRecord(*session, *table);
 
1379
    transaction_services.deleteRecord(session, table);
1381
1380
    break;
1382
1381
  default:
1383
1382
    break;
1401
1400
  {
1402
1401
    if (lock_type == F_RDLCK)
1403
1402
    {
1404
 
      DRIZZLE_CURSOR_RDLOCK_START(getTable()->getShare()->getSchemaName(),
1405
 
                                  getTable()->getShare()->getTableName());
 
1403
      DRIZZLE_CURSOR_RDLOCK_START(table_share->getSchemaName(),
 
1404
                                  table_share->getTableName());
1406
1405
    }
1407
1406
    else if (lock_type == F_WRLCK)
1408
1407
    {
1409
 
      DRIZZLE_CURSOR_WRLOCK_START(getTable()->getShare()->getSchemaName(),
1410
 
                                  getTable()->getShare()->getTableName());
 
1408
      DRIZZLE_CURSOR_WRLOCK_START(table_share->getSchemaName(),
 
1409
                                  table_share->getTableName());
1411
1410
    }
1412
1411
    else if (lock_type == F_UNLCK)
1413
1412
    {
1414
 
      DRIZZLE_CURSOR_UNLOCK_START(getTable()->getShare()->getSchemaName(),
1415
 
                                  getTable()->getShare()->getTableName());
 
1413
      DRIZZLE_CURSOR_UNLOCK_START(table_share->getSchemaName(),
 
1414
                                  table_share->getTableName());
1416
1415
    }
1417
1416
  }
1418
1417
 
1451
1450
int Cursor::ha_reset()
1452
1451
{
1453
1452
  /* Check that we have called all proper deallocation functions */
1454
 
  assert(! getTable()->getShare()->all_set.none());
1455
 
  assert(getTable()->key_read == 0);
1456
 
  /* ensure that ha_index_end / endTableScan has been called */
 
1453
  assert((unsigned char*) table->def_read_set.getBitmap() +
 
1454
              table->s->column_bitmap_size ==
 
1455
              (unsigned char*) table->def_write_set.getBitmap());
 
1456
  assert(table->s->all_set.isSetAll());
 
1457
  assert(table->key_read == 0);
 
1458
  /* ensure that ha_index_end / ha_rnd_end has been called */
1457
1459
  assert(inited == NONE);
1458
1460
  /* Free cache used by filesort */
1459
 
  getTable()->free_io_cache();
 
1461
  table->free_io_cache();
1460
1462
  /* reset the bitmaps to point to defaults */
1461
 
  getTable()->default_column_bitmaps();
 
1463
  table->default_column_bitmaps();
1462
1464
  return(reset());
1463
1465
}
1464
1466
 
1465
1467
 
1466
 
int Cursor::insertRecord(unsigned char *buf)
 
1468
int Cursor::ha_write_row(unsigned char *buf)
1467
1469
{
1468
1470
  int error;
1469
1471
 
1473
1475
   * @TODO Technically, the below two lines can be take even further out of the
1474
1476
   * Cursor interface and into the fill_record() method.
1475
1477
   */
1476
 
  if (getTable()->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
1477
 
  {
1478
 
    getTable()->timestamp_field->set_time();
1479
 
  }
 
1478
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
 
1479
    table->timestamp_field->set_time();
1480
1480
 
1481
 
  DRIZZLE_INSERT_ROW_START(getTable()->getShare()->getSchemaName(), getTable()->getShare()->getTableName());
 
1481
  DRIZZLE_INSERT_ROW_START(table_share->getSchemaName(), table_share->getTableName());
1482
1482
  setTransactionReadWrite();
1483
 
  
1484
 
  if (unlikely(plugin::EventObserver::beforeInsertRecord(*getTable(), buf)))
1485
 
  {
1486
 
    error= ER_EVENT_OBSERVER_PLUGIN;
1487
 
  }
1488
 
  else
1489
 
  {
1490
 
    error= doInsertRecord(buf);
1491
 
    if (unlikely(plugin::EventObserver::afterInsertRecord(*getTable(), buf, error))) 
1492
 
    {
1493
 
      error= ER_EVENT_OBSERVER_PLUGIN;
1494
 
    }
1495
 
  }
1496
 
 
1497
 
  ha_statistic_increment(&system_status_var::ha_write_count);
1498
 
 
 
1483
  error= write_row(buf);
1499
1484
  DRIZZLE_INSERT_ROW_DONE(error);
1500
1485
 
1501
1486
  if (unlikely(error))
1503
1488
    return error;
1504
1489
  }
1505
1490
 
1506
 
  if (unlikely(log_row_for_replication(getTable(), NULL, buf)))
 
1491
  if (unlikely(log_row_for_replication(table, NULL, buf)))
1507
1492
    return HA_ERR_RBR_LOGGING_FAILED;
1508
1493
 
1509
1494
  return 0;
1510
1495
}
1511
1496
 
1512
1497
 
1513
 
int Cursor::updateRecord(const unsigned char *old_data, unsigned char *new_data)
 
1498
int Cursor::ha_update_row(const unsigned char *old_data, unsigned char *new_data)
1514
1499
{
1515
1500
  int error;
1516
1501
 
1517
1502
  /*
1518
 
    Some storage engines require that the new record is in getInsertRecord()
1519
 
    (and the old record is in getUpdateRecord()).
 
1503
    Some storage engines require that the new record is in record[0]
 
1504
    (and the old record is in record[1]).
1520
1505
   */
1521
 
  assert(new_data == getTable()->getInsertRecord());
 
1506
  assert(new_data == table->record[0]);
1522
1507
 
1523
 
  DRIZZLE_UPDATE_ROW_START(getTable()->getShare()->getSchemaName(), getTable()->getShare()->getTableName());
 
1508
  DRIZZLE_UPDATE_ROW_START(table_share->getSchemaName(), table_share->getTableName());
1524
1509
  setTransactionReadWrite();
1525
 
  if (unlikely(plugin::EventObserver::beforeUpdateRecord(*getTable(), old_data, new_data)))
1526
 
  {
1527
 
    error= ER_EVENT_OBSERVER_PLUGIN;
1528
 
  }
1529
 
  else
1530
 
  {
1531
 
    if (getTable()->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
1532
 
    {
1533
 
      getTable()->timestamp_field->set_time();
1534
 
    }
1535
 
 
1536
 
    error= doUpdateRecord(old_data, new_data);
1537
 
    if (unlikely(plugin::EventObserver::afterUpdateRecord(*getTable(), old_data, new_data, error)))
1538
 
    {
1539
 
      error= ER_EVENT_OBSERVER_PLUGIN;
1540
 
    }
1541
 
  }
1542
 
 
1543
 
  ha_statistic_increment(&system_status_var::ha_update_count);
1544
 
 
 
1510
  error= update_row(old_data, new_data);
1545
1511
  DRIZZLE_UPDATE_ROW_DONE(error);
1546
1512
 
1547
1513
  if (unlikely(error))
1549
1515
    return error;
1550
1516
  }
1551
1517
 
1552
 
  if (unlikely(log_row_for_replication(getTable(), old_data, new_data)))
 
1518
  if (unlikely(log_row_for_replication(table, old_data, new_data)))
1553
1519
    return HA_ERR_RBR_LOGGING_FAILED;
1554
1520
 
1555
1521
  return 0;
1556
1522
}
1557
 
TableShare *Cursor::getShare()
1558
 
{
1559
 
  return getTable()->getMutableShare();
1560
 
}
1561
1523
 
1562
 
int Cursor::deleteRecord(const unsigned char *buf)
 
1524
int Cursor::ha_delete_row(const unsigned char *buf)
1563
1525
{
1564
1526
  int error;
1565
1527
 
1566
 
  DRIZZLE_DELETE_ROW_START(getTable()->getShare()->getSchemaName(), getTable()->getShare()->getTableName());
 
1528
  DRIZZLE_DELETE_ROW_START(table_share->getSchemaName(), table_share->getTableName());
1567
1529
  setTransactionReadWrite();
1568
 
  if (unlikely(plugin::EventObserver::beforeDeleteRecord(*getTable(), buf)))
1569
 
  {
1570
 
    error= ER_EVENT_OBSERVER_PLUGIN;
1571
 
  }
1572
 
  else
1573
 
  {
1574
 
    error= doDeleteRecord(buf);
1575
 
    if (unlikely(plugin::EventObserver::afterDeleteRecord(*getTable(), buf, error)))
1576
 
    {
1577
 
      error= ER_EVENT_OBSERVER_PLUGIN;
1578
 
    }
1579
 
  }
1580
 
 
1581
 
  ha_statistic_increment(&system_status_var::ha_delete_count);
1582
 
 
 
1530
  error= delete_row(buf);
1583
1531
  DRIZZLE_DELETE_ROW_DONE(error);
1584
1532
 
1585
1533
  if (unlikely(error))
1586
1534
    return error;
1587
1535
 
1588
 
  if (unlikely(log_row_for_replication(getTable(), buf, NULL)))
 
1536
  if (unlikely(log_row_for_replication(table, buf, NULL)))
1589
1537
    return HA_ERR_RBR_LOGGING_FAILED;
1590
1538
 
1591
1539
  return 0;