~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/cursor.cc

  • Committer: Monty Taylor
  • Date: 2009-12-25 08:50:15 UTC
  • mto: This revision was merged to the branch mainline in revision 1255.
  • Revision ID: mordred@inaugust.com-20091225085015-83sux5qsvy312gew
MEM_ROOT == memory::Root

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
27
27
 
28
28
#include <fcntl.h>
29
29
 
 
30
#include "drizzled/my_hash.h"
30
31
#include "drizzled/error.h"
31
 
#include "drizzled/field/epoch.h"
32
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
33
#include "drizzled/probes.h"
 
34
#include "drizzled/sql_parse.h"
 
35
#include "drizzled/cost_vect.h"
44
36
#include "drizzled/session.h"
45
37
#include "drizzled/sql_base.h"
46
 
#include "drizzled/sql_parse.h"
47
 
#include "drizzled/transaction_services.h"
 
38
#include "drizzled/replication_services.h"
 
39
#include "drizzled/lock.h"
 
40
#include "drizzled/item/int.h"
 
41
#include "drizzled/item/empty_string.h"
 
42
#include "drizzled/unireg.h" // for mysql_frm_type
 
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"
48
47
 
49
48
using namespace std;
50
 
 
51
 
namespace drizzled
52
 
{
 
49
using namespace drizzled;
53
50
 
54
51
/****************************************************************************
55
52
** General Cursor functions
56
53
****************************************************************************/
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),
 
54
Cursor::Cursor(drizzled::plugin::StorageEngine &engine_arg,
 
55
               TableShare &share_arg)
 
56
  : table_share(&share_arg), table(0),
 
57
    estimation_rows_to_insert(0), engine(&engine_arg),
 
58
    ref(0), in_range_check_pushed_down(false),
63
59
    key_used_on_scan(MAX_KEY), active_index(MAX_KEY),
64
 
    ref_length(sizeof(internal::my_off_t)),
 
60
    ref_length(sizeof(my_off_t)),
65
61
    inited(NONE),
66
 
    locked(false),
 
62
    locked(false), implicit_emptied(0),
67
63
    next_insert_id(0), insert_id_for_cur_row(0)
68
64
{ }
69
65
 
74
70
}
75
71
 
76
72
 
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
73
Cursor *Cursor::clone(memory::Root *mem_root)
83
74
{
84
 
  Cursor *new_handler= getTable()->getMutableShare()->db_type()->getCursor(*getTable());
 
75
  Cursor *new_handler= table->s->db_type()->getCursor(*table->s, mem_root);
85
76
 
86
77
  /*
87
78
    Allocate Cursor->ref here because otherwise ha_open will allocate it
88
79
    on this->table->mem_root and we will not be able to reclaim that memory
89
80
    when the clone Cursor object is destroyed.
90
81
  */
91
 
  if (!(new_handler->ref= (unsigned char*) mem_root->alloc_root(ALIGN_SIZE(ref_length)*2)))
 
82
  if (!(new_handler->ref= (unsigned char*) alloc_root(mem_root, ALIGN_SIZE(ref_length)*2)))
92
83
    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(),
 
84
  if (new_handler && !new_handler->ha_open(table,
 
85
                                           table->s->normalized_path.str,
 
86
                                           table->getDBStat(),
100
87
                                           HA_OPEN_IGNORE_IF_LOCKED))
101
88
    return new_handler;
102
89
  return NULL;
103
90
}
104
91
 
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)
 
92
int Cursor::ha_index_init(uint32_t idx, bool sorted)
129
93
{
130
94
  int result;
131
95
  assert(inited == NONE);
132
 
  if (!(result= doStartIndexScan(idx, sorted)))
 
96
  if (!(result= index_init(idx, sorted)))
133
97
    inited=INDEX;
134
98
  end_range= NULL;
135
99
  return result;
136
100
}
137
101
 
138
 
int Cursor::endIndexScan()
 
102
int Cursor::ha_index_end()
139
103
{
140
104
  assert(inited==INDEX);
141
105
  inited=NONE;
142
106
  end_range= NULL;
143
 
  return(doEndIndexScan());
 
107
  return(index_end());
144
108
}
145
109
 
146
 
int Cursor::startTableScan(bool scan)
 
110
int Cursor::ha_rnd_init(bool scan)
147
111
{
148
112
  int result;
149
113
  assert(inited==NONE || (inited==RND && scan));
150
 
  inited= (result= doStartTableScan(scan)) ? NONE: RND;
 
114
  inited= (result= rnd_init(scan)) ? NONE: RND;
151
115
 
152
116
  return result;
153
117
}
154
118
 
155
 
int Cursor::endTableScan()
 
119
int Cursor::ha_rnd_end()
156
120
{
157
121
  assert(inited==RND);
158
122
  inited=NONE;
159
 
  return(doEndTableScan());
 
123
  return(rnd_end());
160
124
}
161
125
 
162
126
int Cursor::ha_index_or_rnd_end()
163
127
{
164
 
  return inited == INDEX ? endIndexScan() : inited == RND ? endTableScan() : 0;
 
128
  return inited == INDEX ? ha_index_end() : inited == RND ? ha_rnd_end() : 0;
165
129
}
166
130
 
167
131
void Cursor::ha_start_bulk_insert(ha_rows rows)
176
140
  return end_bulk_insert();
177
141
}
178
142
 
 
143
void Cursor::change_table_ptr(Table *table_arg, TableShare *share)
 
144
{
 
145
  table= table_arg;
 
146
  table_share= share;
 
147
}
 
148
 
179
149
const key_map *Cursor::keys_to_use_for_scanning()
180
150
{
181
151
  return &key_map_empty;
183
153
 
184
154
bool Cursor::has_transactions()
185
155
{
186
 
  return (getTable()->getShare()->db_type()->check_flag(HTON_BIT_DOES_TRANSACTIONS));
 
156
  return (table->s->db_type()->check_flag(HTON_BIT_DOES_TRANSACTIONS));
187
157
}
188
158
 
189
 
void Cursor::ha_statistic_increment(uint64_t system_status_var::*offset) const
 
159
void Cursor::ha_statistic_increment(ulong SSV::*offset) const
190
160
{
191
 
  (getTable()->in_use->status_var.*offset)++;
 
161
  status_var_increment(table->in_use->status_var.*offset);
192
162
}
193
163
 
194
164
void **Cursor::ha_data(Session *session) const
195
165
{
196
 
  return session->getEngineData(getEngine());
197
 
}
 
166
  return session->getEngineData(engine);
 
167
}
 
168
 
 
169
Session *Cursor::ha_session(void) const
 
170
{
 
171
  assert(!table || !table->in_use || table->in_use == current_session);
 
172
  return (table && table->in_use) ? table->in_use : current_session;
 
173
}
 
174
 
198
175
 
199
176
bool Cursor::is_fatal_error(int error, uint32_t flags)
200
177
{
208
185
 
209
186
 
210
187
ha_rows Cursor::records() { return stats.records; }
211
 
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
 
}
218
188
 
219
189
/**
220
190
  Open database-Cursor.
222
192
  Try O_RDONLY if cannot open as O_RDWR
223
193
  Don't wait for locks if not HA_OPEN_WAIT_IF_LOCKED is set
224
194
*/
225
 
int Cursor::ha_open(const identifier::Table &identifier,
226
 
                    int mode,
227
 
                    int test_if_locked)
 
195
int Cursor::ha_open(Table *table_arg, const char *name, int mode,
 
196
                     int test_if_locked)
228
197
{
229
198
  int error;
230
199
 
231
 
  if ((error= doOpen(identifier, mode, test_if_locked)))
 
200
  table= table_arg;
 
201
  assert(table->s == table_share);
 
202
  assert(alloc_root_inited(&table->mem_root));
 
203
 
 
204
  if ((error=open(name,mode,test_if_locked)))
232
205
  {
233
206
    if ((error == EACCES || error == EROFS) && mode == O_RDWR &&
234
 
        (getTable()->db_stat & HA_TRY_READ_ONLY))
 
207
        (table->db_stat & HA_TRY_READ_ONLY))
235
208
    {
236
 
      getTable()->db_stat|=HA_READ_ONLY;
237
 
      error= doOpen(identifier, O_RDONLY,test_if_locked);
 
209
      table->db_stat|=HA_READ_ONLY;
 
210
      error=open(name,O_RDONLY,test_if_locked);
238
211
    }
239
212
  }
240
213
  if (error)
243
216
  }
244
217
  else
245
218
  {
246
 
    if (getTable()->getShare()->db_options_in_use & HA_OPTION_READ_ONLY_DATA)
247
 
      getTable()->db_stat|=HA_READ_ONLY;
 
219
    if (table->s->db_options_in_use & HA_OPTION_READ_ONLY_DATA)
 
220
      table->db_stat|=HA_READ_ONLY;
248
221
    (void) extra(HA_EXTRA_NO_READCHECK);        // Not needed in SQL
249
222
 
250
223
    /* 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)))
 
224
    if (!ref && !(ref= (unsigned char*) alloc_root(&table->mem_root,
 
225
                                          ALIGN_SIZE(ref_length)*2)))
252
226
    {
253
227
      close();
254
228
      error=HA_ERR_OUT_OF_MEM;
260
234
}
261
235
 
262
236
/**
 
237
  one has to use this method when to find
 
238
  random position by record as the plain
 
239
  position() call doesn't work for some
 
240
  handlers for random position
 
241
*/
 
242
 
 
243
int Cursor::rnd_pos_by_record(unsigned char *record)
 
244
{
 
245
  register int error;
 
246
 
 
247
  position(record);
 
248
  if (inited && (error= ha_index_end()))
 
249
    return error;
 
250
  if ((error= ha_rnd_init(false)))
 
251
    return error;
 
252
 
 
253
  return rnd_pos(record, ref);
 
254
}
 
255
 
 
256
/**
263
257
  Read first row (only) from a table.
264
258
 
265
259
  This is never called for InnoDB tables, as these table types
269
263
{
270
264
  register int error;
271
265
 
272
 
  ha_statistic_increment(&system_status_var::ha_read_first_count);
 
266
  ha_statistic_increment(&SSV::ha_read_first_count);
273
267
 
274
268
  /*
275
269
    If there is very few deleted rows in the table, find the first row by
277
271
    TODO remove the test for HA_READ_ORDER
278
272
  */
279
273
  if (stats.deleted < 10 || primary_key >= MAX_KEY ||
280
 
      !(getTable()->index_flags(primary_key) & HA_READ_ORDER))
 
274
      !(table->index_flags(primary_key) & HA_READ_ORDER))
281
275
  {
282
 
    error= startTableScan(1);
283
 
    if (error == 0)
284
 
    {
285
 
      while ((error= rnd_next(buf)) == HA_ERR_RECORD_DELETED) ;
286
 
      (void) endTableScan();
287
 
    }
 
276
    (void) ha_rnd_init(1);
 
277
    while ((error= rnd_next(buf)) == HA_ERR_RECORD_DELETED) ;
 
278
    (void) ha_rnd_end();
288
279
  }
289
280
  else
290
281
  {
291
282
    /* 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
 
    }
 
283
    (void) ha_index_init(primary_key, 0);
 
284
    error=index_first(buf);
 
285
    (void) ha_index_end();
298
286
  }
299
287
  return error;
300
288
}
311
299
  @verbatim 1,5,15,25,35,... @endverbatim
312
300
*/
313
301
inline uint64_t
314
 
compute_next_insert_id(uint64_t nr, drizzle_system_variables *variables)
 
302
compute_next_insert_id(uint64_t nr,struct system_variables *variables)
315
303
{
316
304
  if (variables->auto_increment_increment == 1)
317
305
    return (nr+1); // optimization of the formula below
331
319
    Session::next_insert_id to be greater than the explicit value.
332
320
  */
333
321
  if ((next_insert_id > 0) && (nr >= next_insert_id))
334
 
    set_next_insert_id(compute_next_insert_id(nr, &getTable()->in_use->variables));
 
322
    set_next_insert_id(compute_next_insert_id(nr, &table->in_use->variables));
335
323
}
336
324
 
337
325
 
351
339
    The number X if it exists, "nr" otherwise.
352
340
*/
353
341
inline uint64_t
354
 
prev_insert_id(uint64_t nr, drizzle_system_variables *variables)
 
342
prev_insert_id(uint64_t nr, struct system_variables *variables)
355
343
{
356
344
  if (unlikely(nr < variables->auto_increment_offset))
357
345
  {
448
436
{
449
437
  uint64_t nr, nb_reserved_values;
450
438
  bool append= false;
451
 
  Session *session= getTable()->in_use;
452
 
  drizzle_system_variables *variables= &session->variables;
 
439
  Session *session= table->in_use;
 
440
  struct system_variables *variables= &session->variables;
453
441
 
454
442
  /*
455
443
    next_insert_id is a "cursor" into the reserved interval, it may go greater
461
449
     for an auto increment column, not a magic value like NULL is.
462
450
     same as sql_mode=NO_AUTO_VALUE_ON_ZERO */
463
451
 
464
 
  if ((nr= getTable()->next_number_field->val_int()) != 0
465
 
      || getTable()->auto_increment_field_not_null)
 
452
  if ((nr= table->next_number_field->val_int()) != 0
 
453
      || table->auto_increment_field_not_null)
466
454
  {
467
455
    /*
468
456
      Update next_insert_id if we had already generated a value in this
540
528
      nr= compute_next_insert_id(nr-1, variables);
541
529
    }
542
530
 
543
 
    if (getTable()->getShare()->next_number_keypart == 0)
 
531
    if (table->s->next_number_keypart == 0)
544
532
    {
545
533
      /* We must defer the appending until "nr" has been possibly truncated */
546
534
      append= true;
547
535
    }
548
536
  }
549
537
 
550
 
  if (unlikely(getTable()->next_number_field->store((int64_t) nr, true)))
 
538
  if (unlikely(table->next_number_field->store((int64_t) nr, true)))
551
539
  {
552
540
    /*
553
541
      first test if the query was aborted due to strict mode constraints
554
542
    */
555
 
    if (session->getKilled() == Session::KILL_BAD_DATA)
 
543
    if (session->killed == Session::KILL_BAD_DATA)
556
544
      return HA_ERR_AUTOINC_ERANGE;
557
545
 
558
546
    /*
563
551
      bother shifting the right bound (anyway any other value from this
564
552
      interval will cause a duplicate key).
565
553
    */
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();
 
554
    nr= prev_insert_id(table->next_number_field->val_int(), variables);
 
555
    if (unlikely(table->next_number_field->store((int64_t) nr, true)))
 
556
      nr= table->next_number_field->val_int();
569
557
  }
570
558
  if (append)
571
559
  {
606
594
  @param first_value         (OUT) the first value reserved by the Cursor
607
595
  @param nb_reserved_values  (OUT) how many values the Cursor reserved
608
596
*/
 
597
void Cursor::get_auto_increment(uint64_t ,
 
598
                                 uint64_t ,
 
599
                                 uint64_t ,
 
600
                                 uint64_t *first_value,
 
601
                                 uint64_t *nb_reserved_values)
 
602
{
 
603
  uint64_t nr;
 
604
  int error;
 
605
 
 
606
  (void) extra(HA_EXTRA_KEYREAD);
 
607
  table->mark_columns_used_by_index_no_reset(table->s->next_number_index);
 
608
  index_init(table->s->next_number_index, 1);
 
609
  if (table->s->next_number_keypart == 0)
 
610
  {                                             // Autoincrement at key-start
 
611
    error=index_last(table->record[1]);
 
612
    /*
 
613
      MySQL implicitely assumes such method does locking (as MySQL decides to
 
614
      use nr+increment without checking again with the Cursor, in
 
615
      Cursor::update_auto_increment()), so reserves to infinite.
 
616
    */
 
617
    *nb_reserved_values= UINT64_MAX;
 
618
  }
 
619
  else
 
620
  {
 
621
    unsigned char key[MAX_KEY_LENGTH];
 
622
    key_copy(key, table->record[0],
 
623
             table->key_info + table->s->next_number_index,
 
624
             table->s->next_number_key_offset);
 
625
    error= index_read_map(table->record[1], key,
 
626
                          make_prev_keypart_map(table->s->next_number_keypart),
 
627
                          HA_READ_PREFIX_LAST);
 
628
    /*
 
629
      MySQL needs to call us for next row: assume we are inserting ("a",null)
 
630
      here, we return 3, and next this statement will want to insert
 
631
      ("b",null): there is no reason why ("b",3+1) would be the good row to
 
632
      insert: maybe it already exists, maybe 3+1 is too large...
 
633
    */
 
634
    *nb_reserved_values= 1;
 
635
  }
 
636
 
 
637
  if (error)
 
638
    nr=1;
 
639
  else
 
640
    nr= ((uint64_t) table->next_number_field->
 
641
         val_int_offset(table->s->rec_buff_length)+1);
 
642
  index_end();
 
643
  (void) extra(HA_EXTRA_NO_KEYREAD);
 
644
  *first_value= nr;
 
645
}
 
646
 
609
647
 
610
648
void Cursor::ha_release_auto_increment()
611
649
{
619
657
      this statement used forced auto_increment values if there were some,
620
658
      wipe them away for other statements.
621
659
    */
622
 
    getTable()->in_use->auto_inc_intervals_forced.empty();
 
660
    table->in_use->auto_inc_intervals_forced.empty();
623
661
  }
624
662
}
625
663
 
656
694
 
657
695
inline
658
696
void
659
 
Cursor::setTransactionReadWrite()
 
697
Cursor::mark_trx_read_write()
660
698
{
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());
 
699
  Ha_trx_info *ha_info= ha_session()->getEngineInfo(engine);
672
700
  /*
673
701
    When a storage engine method is called, the transaction must
674
702
    have been started, unless it's a DDL call, for which the
677
705
    Unfortunately here we can't know know for sure if the engine
678
706
    has registered the transaction or not, so we must check.
679
707
  */
680
 
  if (resource_context->isStarted())
 
708
  if (ha_info->is_started())
681
709
  {
682
 
    resource_context->markModifiedData();
 
710
      ha_info->set_trx_read_write();
683
711
  }
684
712
}
685
713
 
697
725
int
698
726
Cursor::ha_delete_all_rows()
699
727
{
700
 
  setTransactionReadWrite();
 
728
  mark_trx_read_write();
701
729
 
702
730
  int result= delete_all_rows();
703
731
 
706
734
    /** 
707
735
     * Trigger post-truncate notification to plugins... 
708
736
     *
709
 
     * @todo Make TransactionServices generic to AfterTriggerServices
 
737
     * @todo Make ReplicationServices generic to AfterTriggerServices
710
738
     * or similar...
711
739
     */
712
 
    Session *const session= getTable()->in_use;
713
 
    TransactionServices &transaction_services= TransactionServices::singleton();
714
 
    transaction_services.truncateTable(*session, *getTable());
 
740
    Session *const session= table->in_use;
 
741
    ReplicationServices &replication_services= ReplicationServices::singleton();
 
742
    replication_services.truncateTable(session, table);
715
743
  }
716
744
 
717
745
  return result;
727
755
int
728
756
Cursor::ha_reset_auto_increment(uint64_t value)
729
757
{
730
 
  setTransactionReadWrite();
 
758
  mark_trx_read_write();
731
759
 
732
760
  return reset_auto_increment(value);
733
761
}
742
770
int
743
771
Cursor::ha_analyze(Session* session, HA_CHECK_OPT*)
744
772
{
745
 
  setTransactionReadWrite();
 
773
  mark_trx_read_write();
746
774
 
747
775
  return analyze(session);
748
776
}
756
784
int
757
785
Cursor::ha_disable_indexes(uint32_t mode)
758
786
{
759
 
  setTransactionReadWrite();
 
787
  mark_trx_read_write();
760
788
 
761
789
  return disable_indexes(mode);
762
790
}
771
799
int
772
800
Cursor::ha_enable_indexes(uint32_t mode)
773
801
{
774
 
  setTransactionReadWrite();
 
802
  mark_trx_read_write();
775
803
 
776
804
  return enable_indexes(mode);
777
805
}
786
814
int
787
815
Cursor::ha_discard_or_import_tablespace(bool discard)
788
816
{
789
 
  setTransactionReadWrite();
 
817
  mark_trx_read_write();
790
818
 
791
819
  return discard_or_import_tablespace(discard);
792
820
}
800
828
void
801
829
Cursor::closeMarkForDelete(const char *name)
802
830
{
803
 
  setTransactionReadWrite();
 
831
  mark_trx_read_write();
804
832
 
805
833
  return drop_table(name);
806
834
}
807
835
 
 
836
/**
 
837
  Tell the storage engine that it is allowed to "disable transaction" in the
 
838
  Cursor. It is a hint that ACID is not required - it is used in NDB for
 
839
  ALTER Table, for example, when data are copied to temporary table.
 
840
  A storage engine may treat this hint any way it likes. NDB for example
 
841
  starts to commit every now and then automatically.
 
842
  This hint can be safely ignored.
 
843
*/
 
844
int ha_enable_transaction(Session *session, bool on)
 
845
{
 
846
  int error= 0;
 
847
 
 
848
  if ((session->transaction.on= on))
 
849
  {
 
850
    /*
 
851
      Now all storage engines should have transaction handling enabled.
 
852
      But some may have it enabled all the time - "disabling" transactions
 
853
      is an optimization hint that storage engine is free to ignore.
 
854
      So, let's commit an open transaction (if any) now.
 
855
    */
 
856
    if (!(error= ha_commit_trans(session, 0)))
 
857
      if (! session->endTransaction(COMMIT))
 
858
        error= 1;
 
859
 
 
860
  }
 
861
  return error;
 
862
}
 
863
 
808
864
int Cursor::index_next_same(unsigned char *buf, const unsigned char *key, uint32_t keylen)
809
865
{
810
866
  int error;
811
867
  if (!(error=index_next(buf)))
812
868
  {
813
 
    ptrdiff_t ptrdiff= buf - getTable()->getInsertRecord();
 
869
    ptrdiff_t ptrdiff= buf - table->record[0];
814
870
    unsigned char *save_record_0= NULL;
815
 
    KeyInfo *key_info= NULL;
816
 
    KeyPartInfo *key_part;
817
 
    KeyPartInfo *key_part_end= NULL;
 
871
    KEY *key_info= NULL;
 
872
    KEY_PART_INFO *key_part;
 
873
    KEY_PART_INFO *key_part_end= NULL;
818
874
 
819
875
    /*
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
 
876
      key_cmp_if_same() compares table->record[0] against 'key'.
 
877
      In parts it uses table->record[0] directly, in parts it uses
 
878
      field objects with their local pointers into table->record[0].
 
879
      If 'buf' is distinct from table->record[0], we need to move
 
880
      all record references. This is table->record[0] itself and
825
881
      the field pointers of the fields used in this key.
826
882
    */
827
883
    if (ptrdiff)
828
884
    {
829
 
      save_record_0= getTable()->getInsertRecord();
830
 
      getTable()->record[0]= buf;
831
 
      key_info= getTable()->key_info + active_index;
 
885
      save_record_0= table->record[0];
 
886
      table->record[0]= buf;
 
887
      key_info= table->key_info + active_index;
832
888
      key_part= key_info->key_part;
833
889
      key_part_end= key_part + key_info->key_parts;
834
890
      for (; key_part < key_part_end; key_part++)
838
894
      }
839
895
    }
840
896
 
841
 
    if (key_cmp_if_same(getTable(), key, active_index, keylen))
 
897
    if (key_cmp_if_same(table, key, active_index, keylen))
842
898
    {
843
 
      getTable()->status=STATUS_NOT_FOUND;
 
899
      table->status=STATUS_NOT_FOUND;
844
900
      error=HA_ERR_END_OF_FILE;
845
901
    }
846
902
 
847
903
    /* Move back if necessary. */
848
904
    if (ptrdiff)
849
905
    {
850
 
      getTable()->record[0]= save_record_0;
 
906
      table->record[0]= save_record_0;
851
907
      for (key_part= key_info->key_part; key_part < key_part_end; key_part++)
852
908
        key_part->field->move_field_offset(-ptrdiff);
853
909
    }
884
940
double Cursor::index_only_read_time(uint32_t keynr, double key_records)
885
941
{
886
942
  uint32_t keys_per_block= (stats.block_size/2/
887
 
                        (getTable()->key_info[keynr].key_length + ref_length) + 1);
 
943
                        (table->key_info[keynr].key_length + ref_length) + 1);
888
944
  return ((double) (key_records + keys_per_block-1) /
889
945
          (double) keys_per_block);
890
946
}
913
969
 
914
970
  @note
915
971
    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
 
972
    session->killed and return HA_POS_ERROR if it is not zero. This is required
917
973
    for a user to be able to interrupt the calculation by killing the
918
974
    connection/query.
919
975
 
929
985
Cursor::multi_range_read_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
930
986
                                     void *seq_init_param,
931
987
                                     uint32_t ,
932
 
                                     uint32_t *bufsz, uint32_t *flags, optimizer::CostVector *cost)
 
988
                                     uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
933
989
{
934
990
  KEY_MULTI_RANGE range;
935
991
  range_seq_t seq_it;
936
992
  ha_rows rows, total_rows= 0;
937
993
  uint32_t n_ranges=0;
 
994
  Session *session= current_session;
938
995
 
939
996
  /* Default MRR implementation doesn't need buffer */
940
997
  *bufsz= 0;
942
999
  seq_it= seq->init(seq_init_param, n_ranges, *flags);
943
1000
  while (!seq->next(seq_it, &range))
944
1001
  {
 
1002
    if (unlikely(session->killed != 0))
 
1003
      return HA_POS_ERROR;
 
1004
 
945
1005
    n_ranges++;
946
1006
    key_range *min_endp, *max_endp;
947
1007
    {
968
1028
    /* The following calculation is the same as in multi_range_read_info(): */
969
1029
    *flags |= HA_MRR_USE_DEFAULT_IMPL;
970
1030
    cost->zero();
971
 
    cost->setAvgIOCost(1); /* assume random seeks */
 
1031
    cost->avg_io_cost= 1; /* assume random seeks */
972
1032
    if ((*flags & HA_MRR_INDEX_ONLY) && total_rows > 2)
973
 
      cost->setIOCount(index_only_read_time(keyno, (uint32_t)total_rows));
 
1033
      cost->io_count= index_only_read_time(keyno, (uint32_t)total_rows);
974
1034
    else
975
 
      cost->setIOCount(read_time(keyno, n_ranges, total_rows));
976
 
    cost->setCpuCost((double) total_rows / TIME_FOR_COMPARE + 0.01);
 
1035
      cost->io_count= read_time(keyno, n_ranges, total_rows);
 
1036
    cost->cpu_cost= (double) total_rows / TIME_FOR_COMPARE + 0.01;
977
1037
  }
978
1038
  return total_rows;
979
1039
}
1014
1074
*/
1015
1075
 
1016
1076
int Cursor::multi_range_read_info(uint32_t keyno, uint32_t n_ranges, uint32_t n_rows,
1017
 
                                   uint32_t *bufsz, uint32_t *flags, optimizer::CostVector *cost)
 
1077
                                   uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
1018
1078
{
1019
1079
  *bufsz= 0; /* Default implementation doesn't need a buffer */
1020
1080
 
1021
1081
  *flags |= HA_MRR_USE_DEFAULT_IMPL;
1022
1082
 
1023
1083
  cost->zero();
1024
 
  cost->setAvgIOCost(1); /* assume random seeks */
 
1084
  cost->avg_io_cost= 1; /* assume random seeks */
1025
1085
 
1026
1086
  /* Produce the same cost as non-MRR code does */
1027
1087
  if (*flags & HA_MRR_INDEX_ONLY)
1028
 
    cost->setIOCount(index_only_read_time(keyno, n_rows));
 
1088
    cost->io_count= index_only_read_time(keyno, n_rows);
1029
1089
  else
1030
 
    cost->setIOCount(read_time(keyno, n_ranges, n_rows));
 
1090
    cost->io_count= read_time(keyno, n_ranges, n_rows);
1031
1091
  return 0;
1032
1092
}
1033
1093
 
1051
1111
  @param buf             INOUT: memory buffer to be used
1052
1112
 
1053
1113
  @note
1054
 
    One must have called doStartIndexScan() before calling this function. Several
 
1114
    One must have called index_init() before calling this function. Several
1055
1115
    multi_range_read_init() calls may be made in course of one query.
1056
1116
 
1057
1117
    Until WL#2623 is done (see its text, section 3.2), the following will
1066
1126
    The callee consumes all or some fraction of the provided buffer space, and
1067
1127
    sets the HANDLER_BUFFER members accordingly.
1068
1128
    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
 
1129
    call is made, all records have been read, or until index_end() call is
1070
1130
    made, whichever comes first.
1071
1131
 
1072
1132
  @retval 0  OK
1075
1135
 
1076
1136
int
1077
1137
Cursor::multi_range_read_init(RANGE_SEQ_IF *seq_funcs, void *seq_init_param,
1078
 
                               uint32_t n_ranges, uint32_t mode)
 
1138
                               uint32_t n_ranges, uint32_t mode,
 
1139
                               HANDLER_BUFFER *)
1079
1140
{
1080
1141
  mrr_iter= seq_funcs->init(seq_init_param, n_ranges, mode);
1081
1142
  mrr_funcs= *seq_funcs;
1082
1143
  mrr_is_output_sorted= test(mode & HA_MRR_SORTED);
1083
1144
  mrr_have_range= false;
1084
 
 
1085
1145
  return 0;
1086
1146
}
1087
1147
 
1104
1164
  int result= 0;
1105
1165
  int range_res= 0;
1106
1166
 
1107
 
  if (not mrr_have_range)
 
1167
  if (!mrr_have_range)
1108
1168
  {
1109
1169
    mrr_have_range= true;
1110
1170
    goto start;
1166
1226
  @param sorted         Set to 1 if result should be sorted per key
1167
1227
 
1168
1228
  @note
1169
 
    Record is read into table->getInsertRecord()
 
1229
    Record is read into table->record[0]
1170
1230
 
1171
1231
  @retval
1172
1232
    0                   Found row
1191
1251
    key_compare_result_on_equal= ((end_key->flag == HA_READ_BEFORE_KEY) ? 1 :
1192
1252
                                  (end_key->flag == HA_READ_AFTER_KEY) ? -1 : 0);
1193
1253
  }
1194
 
  range_key_part= getTable()->key_info[active_index].key_part;
 
1254
  range_key_part= table->key_info[active_index].key_part;
1195
1255
 
1196
1256
  if (!start_key)                       // Read first record
1197
 
    result= index_first(getTable()->getInsertRecord());
 
1257
    result= index_first(table->record[0]);
1198
1258
  else
1199
 
    result= index_read_map(getTable()->getInsertRecord(),
 
1259
    result= index_read_map(table->record[0],
1200
1260
                           start_key->key,
1201
1261
                           start_key->keypart_map,
1202
1262
                           start_key->flag);
1213
1273
  Read next row between two endpoints.
1214
1274
 
1215
1275
  @note
1216
 
    Record is read into table->getInsertRecord()
 
1276
    Record is read into table->record[0]
1217
1277
 
1218
1278
  @retval
1219
1279
    0                   Found row
1229
1289
  if (eq_range)
1230
1290
  {
1231
1291
    /* We trust that index_next_same always gives a row in range */
1232
 
    return(index_next_same(getTable()->getInsertRecord(),
 
1292
    return(index_next_same(table->record[0],
1233
1293
                                end_range->key,
1234
1294
                                end_range->length));
1235
1295
  }
1236
 
  result= index_next(getTable()->getInsertRecord());
 
1296
  result= index_next(table->record[0]);
1237
1297
  if (result)
1238
1298
    return result;
1239
1299
  return(compare_key(end_range) <= 0 ? 0 : HA_ERR_END_OF_FILE);
1258
1318
int Cursor::compare_key(key_range *range)
1259
1319
{
1260
1320
  int cmp;
1261
 
  if (not range)
 
1321
  if (!range || in_range_check_pushed_down)
1262
1322
    return 0;                                   // No max range
1263
1323
  cmp= key_cmp(range_key_part, range->key, range->length);
1264
1324
  if (!cmp)
1266
1326
  return cmp;
1267
1327
}
1268
1328
 
 
1329
 
 
1330
/*
 
1331
  Same as compare_key() but doesn't check have in_range_check_pushed_down.
 
1332
  This is used by index condition pushdown implementation.
 
1333
*/
 
1334
 
 
1335
int Cursor::compare_key2(key_range *range)
 
1336
{
 
1337
  int cmp;
 
1338
  if (!range)
 
1339
    return 0;                                   // no max range
 
1340
  cmp= key_cmp(range_key_part, range->key, range->length);
 
1341
  if (!cmp)
 
1342
    cmp= key_compare_result_on_equal;
 
1343
  return cmp;
 
1344
}
 
1345
 
1269
1346
int Cursor::index_read_idx_map(unsigned char * buf, uint32_t index,
1270
1347
                                const unsigned char * key,
1271
1348
                                key_part_map keypart_map,
1272
1349
                                enum ha_rkey_function find_flag)
1273
1350
{
1274
1351
  int error, error1;
1275
 
  error= doStartIndexScan(index, 0);
 
1352
  error= index_init(index, 0);
1276
1353
  if (!error)
1277
1354
  {
1278
1355
    error= index_read_map(buf, key, keypart_map, find_flag);
1279
 
    error1= doEndIndexScan();
 
1356
    error1= index_end();
1280
1357
  }
1281
1358
  return error ?  error : error1;
1282
1359
}
1292
1369
                                    const unsigned char *before_record,
1293
1370
                                    const unsigned char *after_record)
1294
1371
{
1295
 
  TransactionServices &transaction_services= TransactionServices::singleton();
 
1372
  ReplicationServices &replication_services= ReplicationServices::singleton();
1296
1373
  Session *const session= table->in_use;
1297
1374
 
1298
 
  if (table->getShare()->getType() || not transaction_services.shouldConstructMessages())
 
1375
  if (table->s->tmp_table || ! replication_services.isActive())
1299
1376
    return false;
1300
1377
 
1301
1378
  bool result= false;
1302
1379
 
1303
1380
  switch (session->lex->sql_command)
1304
1381
  {
1305
 
  case SQLCOM_CREATE_TABLE:
1306
 
    /*
1307
 
     * We are in a CREATE TABLE ... SELECT statement
1308
 
     * and the kernel has already created the table
1309
 
     * and put a CreateTableStatement in the active
1310
 
     * Transaction message.  Here, we add a new InsertRecord
1311
 
     * to a new Transaction message (because the above
1312
 
     * CREATE TABLE will commit the transaction containing
1313
 
     * it).
1314
 
     */
1315
 
    result= transaction_services.insertRecord(*session, *table);
1316
 
    break;
1317
1382
  case SQLCOM_REPLACE:
1318
1383
  case SQLCOM_REPLACE_SELECT:
1319
1384
    /*
1320
1385
     * This is a total hack because of the code that is
1321
1386
     * 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()
 
1387
     * a REPLACE statement, a call to ha_write_row() is
 
1388
     * called.  If it fails, then a call to ha_delete_row()
1324
1389
     * 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
 
1390
     * call to ha_write_row().  So, log_row_for_replication
 
1391
     * could be called either once or twice for a REPLACE
1327
1392
     * statement.  The below looks at the values of before_record
1328
1393
     * and after_record to determine which call to this
1329
1394
     * function is for the delete or the insert, since NULL
1336
1401
     */
1337
1402
    if (after_record == NULL)
1338
1403
    {
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);
 
1404
      replication_services.deleteRecord(session, table);
1345
1405
      /* 
1346
1406
       * We set the "current" statement message to NULL.  This triggers
1347
1407
       * the replication services component to generate a new statement
1348
1408
       * message for the inserted record which will come next.
1349
1409
       */
1350
 
      transaction_services.finalizeStatementMessage(*session->getStatementMessage(), *session);
 
1410
      replication_services.finalizeStatement(*session->getStatementMessage(), session);
1351
1411
    }
1352
1412
    else
1353
1413
    {
1354
1414
      if (before_record == NULL)
1355
 
        result= transaction_services.insertRecord(*session, *table);
 
1415
        result= replication_services.insertRecord(session, table);
1356
1416
      else
1357
 
        transaction_services.updateRecord(*session, *table, before_record, after_record);
 
1417
        replication_services.updateRecord(session, table, before_record, after_record);
1358
1418
    }
1359
1419
    break;
1360
1420
  case SQLCOM_INSERT:
1361
1421
  case SQLCOM_INSERT_SELECT:
1362
 
  case SQLCOM_LOAD:
1363
1422
    /*
1364
1423
     * The else block below represents an 
1365
1424
     * INSERT ... ON DUPLICATE KEY UPDATE that
1367
1426
     * an update.
1368
1427
     */
1369
1428
    if (before_record == NULL)
1370
 
      result= transaction_services.insertRecord(*session, *table);
 
1429
      result= replication_services.insertRecord(session, table);
1371
1430
    else
1372
 
      transaction_services.updateRecord(*session, *table, before_record, after_record);
 
1431
      replication_services.updateRecord(session, table, before_record, after_record);
1373
1432
    break;
1374
1433
 
1375
1434
  case SQLCOM_UPDATE:
1376
 
    transaction_services.updateRecord(*session, *table, before_record, after_record);
 
1435
    replication_services.updateRecord(session, table, before_record, after_record);
1377
1436
    break;
1378
1437
 
1379
1438
  case SQLCOM_DELETE:
1380
 
    transaction_services.deleteRecord(*session, *table);
 
1439
    replication_services.deleteRecord(session, table);
1381
1440
    break;
1382
1441
  default:
1383
1442
    break;
1401
1460
  {
1402
1461
    if (lock_type == F_RDLCK)
1403
1462
    {
1404
 
      DRIZZLE_CURSOR_RDLOCK_START(getTable()->getShare()->getSchemaName(),
1405
 
                                  getTable()->getShare()->getTableName());
 
1463
      DRIZZLE_CURSOR_RDLOCK_START(table_share->db.str,
 
1464
                                  table_share->table_name.str);
1406
1465
    }
1407
1466
    else if (lock_type == F_WRLCK)
1408
1467
    {
1409
 
      DRIZZLE_CURSOR_WRLOCK_START(getTable()->getShare()->getSchemaName(),
1410
 
                                  getTable()->getShare()->getTableName());
 
1468
      DRIZZLE_CURSOR_WRLOCK_START(table_share->db.str,
 
1469
                                  table_share->table_name.str);
1411
1470
    }
1412
1471
    else if (lock_type == F_UNLCK)
1413
1472
    {
1414
 
      DRIZZLE_CURSOR_UNLOCK_START(getTable()->getShare()->getSchemaName(),
1415
 
                                  getTable()->getShare()->getTableName());
 
1473
      DRIZZLE_CURSOR_UNLOCK_START(table_share->db.str,
 
1474
                                  table_share->table_name.str);
1416
1475
    }
1417
1476
  }
1418
1477
 
1451
1510
int Cursor::ha_reset()
1452
1511
{
1453
1512
  /* 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 */
 
1513
  assert((unsigned char*) table->def_read_set.getBitmap() +
 
1514
              table->s->column_bitmap_size ==
 
1515
              (unsigned char*) table->def_write_set.getBitmap());
 
1516
  assert(table->s->all_set.isSetAll());
 
1517
  assert(table->key_read == 0);
 
1518
  /* ensure that ha_index_end / ha_rnd_end has been called */
1457
1519
  assert(inited == NONE);
1458
1520
  /* Free cache used by filesort */
1459
 
  getTable()->free_io_cache();
 
1521
  table->free_io_cache();
1460
1522
  /* reset the bitmaps to point to defaults */
1461
 
  getTable()->default_column_bitmaps();
 
1523
  table->default_column_bitmaps();
1462
1524
  return(reset());
1463
1525
}
1464
1526
 
1465
1527
 
1466
 
int Cursor::insertRecord(unsigned char *buf)
 
1528
int Cursor::ha_write_row(unsigned char *buf)
1467
1529
{
1468
1530
  int error;
1469
1531
 
1473
1535
   * @TODO Technically, the below two lines can be take even further out of the
1474
1536
   * Cursor interface and into the fill_record() method.
1475
1537
   */
1476
 
  if (getTable()->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
1477
 
  {
1478
 
    getTable()->timestamp_field->set_time();
1479
 
  }
1480
 
 
1481
 
  DRIZZLE_INSERT_ROW_START(getTable()->getShare()->getSchemaName(), getTable()->getShare()->getTableName());
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
 
 
 
1538
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
 
1539
    table->timestamp_field->set_time();
 
1540
 
 
1541
  DRIZZLE_INSERT_ROW_START(table_share->db.str, table_share->table_name.str);
 
1542
  mark_trx_read_write();
 
1543
  error= write_row(buf);
1499
1544
  DRIZZLE_INSERT_ROW_DONE(error);
1500
1545
 
1501
1546
  if (unlikely(error))
1503
1548
    return error;
1504
1549
  }
1505
1550
 
1506
 
  if (unlikely(log_row_for_replication(getTable(), NULL, buf)))
 
1551
  if (unlikely(log_row_for_replication(table, NULL, buf)))
1507
1552
    return HA_ERR_RBR_LOGGING_FAILED;
1508
1553
 
1509
1554
  return 0;
1510
1555
}
1511
1556
 
1512
1557
 
1513
 
int Cursor::updateRecord(const unsigned char *old_data, unsigned char *new_data)
 
1558
int Cursor::ha_update_row(const unsigned char *old_data, unsigned char *new_data)
1514
1559
{
1515
1560
  int error;
1516
1561
 
1517
1562
  /*
1518
 
    Some storage engines require that the new record is in getInsertRecord()
1519
 
    (and the old record is in getUpdateRecord()).
 
1563
    Some storage engines require that the new record is in record[0]
 
1564
    (and the old record is in record[1]).
1520
1565
   */
1521
 
  assert(new_data == getTable()->getInsertRecord());
1522
 
 
1523
 
  DRIZZLE_UPDATE_ROW_START(getTable()->getShare()->getSchemaName(), getTable()->getShare()->getTableName());
1524
 
  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
 
 
 
1566
  assert(new_data == table->record[0]);
 
1567
 
 
1568
  DRIZZLE_UPDATE_ROW_START(table_share->db.str, table_share->table_name.str);
 
1569
  mark_trx_read_write();
 
1570
  error= update_row(old_data, new_data);
1545
1571
  DRIZZLE_UPDATE_ROW_DONE(error);
1546
1572
 
1547
1573
  if (unlikely(error))
1549
1575
    return error;
1550
1576
  }
1551
1577
 
1552
 
  if (unlikely(log_row_for_replication(getTable(), old_data, new_data)))
 
1578
  if (unlikely(log_row_for_replication(table, old_data, new_data)))
1553
1579
    return HA_ERR_RBR_LOGGING_FAILED;
1554
1580
 
1555
1581
  return 0;
1556
1582
}
1557
 
TableShare *Cursor::getShare()
1558
 
{
1559
 
  return getTable()->getMutableShare();
1560
 
}
1561
1583
 
1562
 
int Cursor::deleteRecord(const unsigned char *buf)
 
1584
int Cursor::ha_delete_row(const unsigned char *buf)
1563
1585
{
1564
1586
  int error;
1565
1587
 
1566
 
  DRIZZLE_DELETE_ROW_START(getTable()->getShare()->getSchemaName(), getTable()->getShare()->getTableName());
1567
 
  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
 
 
 
1588
  DRIZZLE_DELETE_ROW_START(table_share->db.str, table_share->table_name.str);
 
1589
  mark_trx_read_write();
 
1590
  error= delete_row(buf);
1583
1591
  DRIZZLE_DELETE_ROW_DONE(error);
1584
1592
 
1585
1593
  if (unlikely(error))
1586
1594
    return error;
1587
1595
 
1588
 
  if (unlikely(log_row_for_replication(getTable(), buf, NULL)))
 
1596
  if (unlikely(log_row_for_replication(table, buf, NULL)))
1589
1597
    return HA_ERR_RBR_LOGGING_FAILED;
1590
1598
 
1591
1599
  return 0;
1592
1600
}
1593
 
 
1594
 
} /* namespace drizzled */