~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/cursor.cc

  • Committer: Brian Aker
  • Date: 2009-11-24 02:06:37 UTC
  • mfrom: (1223.1.7 push)
  • Revision ID: brian@gaz-20091124020637-9gb65vj98x1arydm
MergeĀ forĀ staging.

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"
27
 
 
28
 
#include <fcntl.h>
29
 
 
 
26
#include "drizzled/server_includes.h"
 
27
#include "mysys/hash.h"
30
28
#include "drizzled/error.h"
31
 
#include "drizzled/field/epoch.h"
32
29
#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
30
#include "drizzled/probes.h"
 
31
#include "drizzled/sql_parse.h"
 
32
#include "drizzled/cost_vect.h"
44
33
#include "drizzled/session.h"
45
34
#include "drizzled/sql_base.h"
46
 
#include "drizzled/sql_parse.h"
47
 
#include "drizzled/transaction_services.h"
 
35
#include "drizzled/replication_services.h"
 
36
#include "drizzled/lock.h"
 
37
#include "drizzled/item/int.h"
 
38
#include "drizzled/item/empty_string.h"
 
39
#include "drizzled/unireg.h" // for mysql_frm_type
 
40
#include "drizzled/field/timestamp.h"
 
41
#include "drizzled/message/table.pb.h"
 
42
#include "drizzled/plugin/client.h"
48
43
 
49
44
using namespace std;
50
 
 
51
 
namespace drizzled
52
 
{
 
45
using namespace drizzled;
53
46
 
54
47
/****************************************************************************
55
48
** General Cursor functions
56
49
****************************************************************************/
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),
63
 
    key_used_on_scan(MAX_KEY), active_index(MAX_KEY),
64
 
    ref_length(sizeof(internal::my_off_t)),
65
 
    inited(NONE),
66
 
    locked(false),
67
 
    next_insert_id(0), insert_id_for_cur_row(0)
68
 
{ }
69
 
 
70
50
Cursor::~Cursor(void)
71
51
{
72
52
  assert(locked == false);
74
54
}
75
55
 
76
56
 
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
 
Cursor *Cursor::clone(memory::Root *mem_root)
 
57
Cursor *Cursor::clone(MEM_ROOT *mem_root)
83
58
{
84
 
  Cursor *new_handler= getTable()->getMutableShare()->db_type()->getCursor(*getTable());
 
59
  Cursor *new_handler= table->s->db_type()->getCursor(*table->s, mem_root);
85
60
 
86
61
  /*
87
62
    Allocate Cursor->ref here because otherwise ha_open will allocate it
88
63
    on this->table->mem_root and we will not be able to reclaim that memory
89
64
    when the clone Cursor object is destroyed.
90
65
  */
91
 
  if (!(new_handler->ref= (unsigned char*) mem_root->alloc_root(ALIGN_SIZE(ref_length)*2)))
 
66
  if (!(new_handler->ref= (unsigned char*) alloc_root(mem_root, ALIGN_SIZE(ref_length)*2)))
92
67
    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(),
 
68
  if (new_handler && !new_handler->ha_open(table,
 
69
                                           table->s->normalized_path.str,
 
70
                                           table->getDBStat(),
100
71
                                           HA_OPEN_IGNORE_IF_LOCKED))
101
72
    return new_handler;
102
73
  return NULL;
103
74
}
104
75
 
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)
 
76
int Cursor::ha_index_init(uint32_t idx, bool sorted)
129
77
{
130
78
  int result;
131
79
  assert(inited == NONE);
132
 
  if (!(result= doStartIndexScan(idx, sorted)))
 
80
  if (!(result= index_init(idx, sorted)))
133
81
    inited=INDEX;
134
82
  end_range= NULL;
135
83
  return result;
136
84
}
137
85
 
138
 
int Cursor::endIndexScan()
 
86
int Cursor::ha_index_end()
139
87
{
140
88
  assert(inited==INDEX);
141
89
  inited=NONE;
142
90
  end_range= NULL;
143
 
  return(doEndIndexScan());
 
91
  return(index_end());
144
92
}
145
93
 
146
 
int Cursor::startTableScan(bool scan)
 
94
int Cursor::ha_rnd_init(bool scan)
147
95
{
148
96
  int result;
149
97
  assert(inited==NONE || (inited==RND && scan));
150
 
  inited= (result= doStartTableScan(scan)) ? NONE: RND;
 
98
  inited= (result= rnd_init(scan)) ? NONE: RND;
151
99
 
152
100
  return result;
153
101
}
154
102
 
155
 
int Cursor::endTableScan()
 
103
int Cursor::ha_rnd_end()
156
104
{
157
105
  assert(inited==RND);
158
106
  inited=NONE;
159
 
  return(doEndTableScan());
 
107
  return(rnd_end());
160
108
}
161
109
 
162
110
int Cursor::ha_index_or_rnd_end()
163
111
{
164
 
  return inited == INDEX ? endIndexScan() : inited == RND ? endTableScan() : 0;
 
112
  return inited == INDEX ? ha_index_end() : inited == RND ? ha_rnd_end() : 0;
 
113
}
 
114
 
 
115
plugin::StorageEngine::Table_flags Cursor::ha_table_flags() const
 
116
{
 
117
  return engine->table_flags();
165
118
}
166
119
 
167
120
void Cursor::ha_start_bulk_insert(ha_rows rows)
176
129
  return end_bulk_insert();
177
130
}
178
131
 
 
132
void Cursor::change_table_ptr(Table *table_arg, TableShare *share)
 
133
{
 
134
  table= table_arg;
 
135
  table_share= share;
 
136
}
 
137
 
179
138
const key_map *Cursor::keys_to_use_for_scanning()
180
139
{
181
140
  return &key_map_empty;
183
142
 
184
143
bool Cursor::has_transactions()
185
144
{
186
 
  return (getTable()->getShare()->db_type()->check_flag(HTON_BIT_DOES_TRANSACTIONS));
 
145
  return (ha_table_flags() & HA_NO_TRANSACTIONS) == 0;
187
146
}
188
147
 
189
 
void Cursor::ha_statistic_increment(uint64_t system_status_var::*offset) const
 
148
void Cursor::ha_statistic_increment(ulong SSV::*offset) const
190
149
{
191
 
  (getTable()->in_use->status_var.*offset)++;
 
150
  status_var_increment(table->in_use->status_var.*offset);
192
151
}
193
152
 
194
153
void **Cursor::ha_data(Session *session) const
195
154
{
196
 
  return session->getEngineData(getEngine());
197
 
}
 
155
  return session_ha_data(session, engine);
 
156
}
 
157
 
 
158
Session *Cursor::ha_session(void) const
 
159
{
 
160
  assert(!table || !table->in_use || table->in_use == current_session);
 
161
  return (table && table->in_use) ? table->in_use : current_session;
 
162
}
 
163
 
198
164
 
199
165
bool Cursor::is_fatal_error(int error, uint32_t flags)
200
166
{
208
174
 
209
175
 
210
176
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
177
 
219
178
/**
220
179
  Open database-Cursor.
222
181
  Try O_RDONLY if cannot open as O_RDWR
223
182
  Don't wait for locks if not HA_OPEN_WAIT_IF_LOCKED is set
224
183
*/
225
 
int Cursor::ha_open(const identifier::Table &identifier,
226
 
                    int mode,
227
 
                    int test_if_locked)
 
184
int Cursor::ha_open(Table *table_arg, const char *name, int mode,
 
185
                     int test_if_locked)
228
186
{
229
187
  int error;
230
188
 
231
 
  if ((error= doOpen(identifier, mode, test_if_locked)))
 
189
  table= table_arg;
 
190
  assert(table->s == table_share);
 
191
  assert(alloc_root_inited(&table->mem_root));
 
192
 
 
193
  if ((error=open(name,mode,test_if_locked)))
232
194
  {
233
195
    if ((error == EACCES || error == EROFS) && mode == O_RDWR &&
234
 
        (getTable()->db_stat & HA_TRY_READ_ONLY))
 
196
        (table->db_stat & HA_TRY_READ_ONLY))
235
197
    {
236
 
      getTable()->db_stat|=HA_READ_ONLY;
237
 
      error= doOpen(identifier, O_RDONLY,test_if_locked);
 
198
      table->db_stat|=HA_READ_ONLY;
 
199
      error=open(name,O_RDONLY,test_if_locked);
238
200
    }
239
201
  }
240
202
  if (error)
241
203
  {
242
 
    errno= error;                            /* Safeguard */
 
204
    my_errno= error;                            /* Safeguard */
243
205
  }
244
206
  else
245
207
  {
246
 
    if (getTable()->getShare()->db_options_in_use & HA_OPTION_READ_ONLY_DATA)
247
 
      getTable()->db_stat|=HA_READ_ONLY;
 
208
    if (table->s->db_options_in_use & HA_OPTION_READ_ONLY_DATA)
 
209
      table->db_stat|=HA_READ_ONLY;
248
210
    (void) extra(HA_EXTRA_NO_READCHECK);        // Not needed in SQL
249
211
 
250
212
    /* 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)))
 
213
    if (!ref && !(ref= (unsigned char*) alloc_root(&table->mem_root,
 
214
                                          ALIGN_SIZE(ref_length)*2)))
252
215
    {
253
216
      close();
254
217
      error=HA_ERR_OUT_OF_MEM;
260
223
}
261
224
 
262
225
/**
 
226
  one has to use this method when to find
 
227
  random position by record as the plain
 
228
  position() call doesn't work for some
 
229
  handlers for random position
 
230
*/
 
231
 
 
232
int Cursor::rnd_pos_by_record(unsigned char *record)
 
233
{
 
234
  register int error;
 
235
 
 
236
  position(record);
 
237
  if (inited && (error= ha_index_end()))
 
238
    return error;
 
239
  if ((error= ha_rnd_init(false)))
 
240
    return error;
 
241
 
 
242
  return rnd_pos(record, ref);
 
243
}
 
244
 
 
245
/**
263
246
  Read first row (only) from a table.
264
247
 
265
248
  This is never called for InnoDB tables, as these table types
269
252
{
270
253
  register int error;
271
254
 
272
 
  ha_statistic_increment(&system_status_var::ha_read_first_count);
 
255
  ha_statistic_increment(&SSV::ha_read_first_count);
273
256
 
274
257
  /*
275
258
    If there is very few deleted rows in the table, find the first row by
277
260
    TODO remove the test for HA_READ_ORDER
278
261
  */
279
262
  if (stats.deleted < 10 || primary_key >= MAX_KEY ||
280
 
      !(getTable()->index_flags(primary_key) & HA_READ_ORDER))
 
263
      !(index_flags(primary_key, 0, 0) & HA_READ_ORDER))
281
264
  {
282
 
    error= startTableScan(1);
283
 
    if (error == 0)
284
 
    {
285
 
      while ((error= rnd_next(buf)) == HA_ERR_RECORD_DELETED) ;
286
 
      (void) endTableScan();
287
 
    }
 
265
    (void) ha_rnd_init(1);
 
266
    while ((error= rnd_next(buf)) == HA_ERR_RECORD_DELETED) ;
 
267
    (void) ha_rnd_end();
288
268
  }
289
269
  else
290
270
  {
291
271
    /* 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
 
    }
 
272
    (void) ha_index_init(primary_key, 0);
 
273
    error=index_first(buf);
 
274
    (void) ha_index_end();
298
275
  }
299
276
  return error;
300
277
}
311
288
  @verbatim 1,5,15,25,35,... @endverbatim
312
289
*/
313
290
inline uint64_t
314
 
compute_next_insert_id(uint64_t nr, drizzle_system_variables *variables)
 
291
compute_next_insert_id(uint64_t nr,struct system_variables *variables)
315
292
{
316
293
  if (variables->auto_increment_increment == 1)
317
294
    return (nr+1); // optimization of the formula below
331
308
    Session::next_insert_id to be greater than the explicit value.
332
309
  */
333
310
  if ((next_insert_id > 0) && (nr >= next_insert_id))
334
 
    set_next_insert_id(compute_next_insert_id(nr, &getTable()->in_use->variables));
 
311
    set_next_insert_id(compute_next_insert_id(nr, &table->in_use->variables));
335
312
}
336
313
 
337
314
 
351
328
    The number X if it exists, "nr" otherwise.
352
329
*/
353
330
inline uint64_t
354
 
prev_insert_id(uint64_t nr, drizzle_system_variables *variables)
 
331
prev_insert_id(uint64_t nr, struct system_variables *variables)
355
332
{
356
333
  if (unlikely(nr < variables->auto_increment_offset))
357
334
  {
448
425
{
449
426
  uint64_t nr, nb_reserved_values;
450
427
  bool append= false;
451
 
  Session *session= getTable()->in_use;
452
 
  drizzle_system_variables *variables= &session->variables;
 
428
  Session *session= table->in_use;
 
429
  struct system_variables *variables= &session->variables;
453
430
 
454
431
  /*
455
432
    next_insert_id is a "cursor" into the reserved interval, it may go greater
461
438
     for an auto increment column, not a magic value like NULL is.
462
439
     same as sql_mode=NO_AUTO_VALUE_ON_ZERO */
463
440
 
464
 
  if ((nr= getTable()->next_number_field->val_int()) != 0
465
 
      || getTable()->auto_increment_field_not_null)
 
441
  if ((nr= table->next_number_field->val_int()) != 0
 
442
      || table->auto_increment_field_not_null)
466
443
  {
467
444
    /*
468
445
      Update next_insert_id if we had already generated a value in this
540
517
      nr= compute_next_insert_id(nr-1, variables);
541
518
    }
542
519
 
543
 
    if (getTable()->getShare()->next_number_keypart == 0)
 
520
    if (table->s->next_number_keypart == 0)
544
521
    {
545
522
      /* We must defer the appending until "nr" has been possibly truncated */
546
523
      append= true;
547
524
    }
548
525
  }
549
526
 
550
 
  if (unlikely(getTable()->next_number_field->store((int64_t) nr, true)))
 
527
  if (unlikely(table->next_number_field->store((int64_t) nr, true)))
551
528
  {
552
529
    /*
553
530
      first test if the query was aborted due to strict mode constraints
554
531
    */
555
 
    if (session->getKilled() == Session::KILL_BAD_DATA)
 
532
    if (session->killed == Session::KILL_BAD_DATA)
556
533
      return HA_ERR_AUTOINC_ERANGE;
557
534
 
558
535
    /*
563
540
      bother shifting the right bound (anyway any other value from this
564
541
      interval will cause a duplicate key).
565
542
    */
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();
 
543
    nr= prev_insert_id(table->next_number_field->val_int(), variables);
 
544
    if (unlikely(table->next_number_field->store((int64_t) nr, true)))
 
545
      nr= table->next_number_field->val_int();
569
546
  }
570
547
  if (append)
571
548
  {
606
583
  @param first_value         (OUT) the first value reserved by the Cursor
607
584
  @param nb_reserved_values  (OUT) how many values the Cursor reserved
608
585
*/
 
586
void Cursor::get_auto_increment(uint64_t ,
 
587
                                 uint64_t ,
 
588
                                 uint64_t ,
 
589
                                 uint64_t *first_value,
 
590
                                 uint64_t *nb_reserved_values)
 
591
{
 
592
  uint64_t nr;
 
593
  int error;
 
594
 
 
595
  (void) extra(HA_EXTRA_KEYREAD);
 
596
  table->mark_columns_used_by_index_no_reset(table->s->next_number_index);
 
597
  index_init(table->s->next_number_index, 1);
 
598
  if (table->s->next_number_keypart == 0)
 
599
  {                                             // Autoincrement at key-start
 
600
    error=index_last(table->record[1]);
 
601
    /*
 
602
      MySQL implicitely assumes such method does locking (as MySQL decides to
 
603
      use nr+increment without checking again with the Cursor, in
 
604
      Cursor::update_auto_increment()), so reserves to infinite.
 
605
    */
 
606
    *nb_reserved_values= UINT64_MAX;
 
607
  }
 
608
  else
 
609
  {
 
610
    unsigned char key[MAX_KEY_LENGTH];
 
611
    key_copy(key, table->record[0],
 
612
             table->key_info + table->s->next_number_index,
 
613
             table->s->next_number_key_offset);
 
614
    error= index_read_map(table->record[1], key,
 
615
                          make_prev_keypart_map(table->s->next_number_keypart),
 
616
                          HA_READ_PREFIX_LAST);
 
617
    /*
 
618
      MySQL needs to call us for next row: assume we are inserting ("a",null)
 
619
      here, we return 3, and next this statement will want to insert
 
620
      ("b",null): there is no reason why ("b",3+1) would be the good row to
 
621
      insert: maybe it already exists, maybe 3+1 is too large...
 
622
    */
 
623
    *nb_reserved_values= 1;
 
624
  }
 
625
 
 
626
  if (error)
 
627
    nr=1;
 
628
  else
 
629
    nr= ((uint64_t) table->next_number_field->
 
630
         val_int_offset(table->s->rec_buff_length)+1);
 
631
  index_end();
 
632
  (void) extra(HA_EXTRA_NO_KEYREAD);
 
633
  *first_value= nr;
 
634
}
 
635
 
609
636
 
610
637
void Cursor::ha_release_auto_increment()
611
638
{
619
646
      this statement used forced auto_increment values if there were some,
620
647
      wipe them away for other statements.
621
648
    */
622
 
    getTable()->in_use->auto_inc_intervals_forced.empty();
 
649
    table->in_use->auto_inc_intervals_forced.empty();
623
650
  }
624
651
}
625
652
 
656
683
 
657
684
inline
658
685
void
659
 
Cursor::setTransactionReadWrite()
 
686
Cursor::mark_trx_read_write()
660
687
{
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());
 
688
  Ha_trx_info *ha_info= &ha_session()->ha_data[engine->getSlot()].ha_info[0];
672
689
  /*
673
690
    When a storage engine method is called, the transaction must
674
691
    have been started, unless it's a DDL call, for which the
677
694
    Unfortunately here we can't know know for sure if the engine
678
695
    has registered the transaction or not, so we must check.
679
696
  */
680
 
  if (resource_context->isStarted())
 
697
  if (ha_info->is_started())
681
698
  {
682
 
    resource_context->markModifiedData();
 
699
      ha_info->set_trx_read_write();
683
700
  }
684
701
}
685
702
 
 
703
/**
 
704
  Bulk update row: public interface.
 
705
 
 
706
  @sa Cursor::bulk_update_row()
 
707
*/
 
708
 
 
709
int
 
710
Cursor::ha_bulk_update_row(const unsigned char *old_data, unsigned char *new_data,
 
711
                            uint32_t *dup_key_found)
 
712
{
 
713
  mark_trx_read_write();
 
714
 
 
715
  return bulk_update_row(old_data, new_data, dup_key_found);
 
716
}
 
717
 
686
718
 
687
719
/**
688
720
  Delete all rows: public interface.
689
721
 
690
722
  @sa Cursor::delete_all_rows()
691
 
 
692
 
  @note
693
 
 
694
 
  This is now equalivalent to TRUNCATE TABLE.
695
723
*/
696
724
 
697
725
int
698
726
Cursor::ha_delete_all_rows()
699
727
{
700
 
  setTransactionReadWrite();
701
 
 
702
 
  int result= delete_all_rows();
703
 
 
704
 
  if (result == 0)
705
 
  {
706
 
    /** 
707
 
     * Trigger post-truncate notification to plugins... 
708
 
     *
709
 
     * @todo Make TransactionServices generic to AfterTriggerServices
710
 
     * or similar...
711
 
     */
712
 
    Session *const session= getTable()->in_use;
713
 
    TransactionServices &transaction_services= TransactionServices::singleton();
714
 
    transaction_services.truncateTable(*session, *getTable());
715
 
  }
716
 
 
717
 
  return result;
 
728
  mark_trx_read_write();
 
729
 
 
730
  return delete_all_rows();
718
731
}
719
732
 
720
733
 
727
740
int
728
741
Cursor::ha_reset_auto_increment(uint64_t value)
729
742
{
730
 
  setTransactionReadWrite();
 
743
  mark_trx_read_write();
731
744
 
732
745
  return reset_auto_increment(value);
733
746
}
734
747
 
735
748
 
736
749
/**
 
750
  Optimize table: public interface.
 
751
 
 
752
  @sa Cursor::optimize()
 
753
*/
 
754
 
 
755
int
 
756
Cursor::ha_optimize(Session* session, HA_CHECK_OPT*)
 
757
{
 
758
  mark_trx_read_write();
 
759
 
 
760
  return optimize(session);
 
761
}
 
762
 
 
763
 
 
764
/**
737
765
  Analyze table: public interface.
738
766
 
739
767
  @sa Cursor::analyze()
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
 
  bool result= false;
1302
 
 
1303
1378
  switch (session->lex->sql_command)
1304
1379
  {
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
1380
  case SQLCOM_REPLACE:
1318
1381
  case SQLCOM_REPLACE_SELECT:
1319
1382
    /*
1320
1383
     * This is a total hack because of the code that is
1321
1384
     * 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()
 
1385
     * a REPLACE statement, a call to ha_write_row() is
 
1386
     * called.  If it fails, then a call to ha_delete_row()
1324
1387
     * 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
 
1388
     * call to ha_write_row().  So, log_row_for_replication
 
1389
     * could be called either once or twice for a REPLACE
1327
1390
     * statement.  The below looks at the values of before_record
1328
1391
     * and after_record to determine which call to this
1329
1392
     * function is for the delete or the insert, since NULL
1336
1399
     */
1337
1400
    if (after_record == NULL)
1338
1401
    {
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);
 
1402
      replication_services.deleteRecord(session, table);
1345
1403
      /* 
1346
1404
       * We set the "current" statement message to NULL.  This triggers
1347
1405
       * the replication services component to generate a new statement
1348
1406
       * message for the inserted record which will come next.
1349
1407
       */
1350
 
      transaction_services.finalizeStatementMessage(*session->getStatementMessage(), *session);
 
1408
      replication_services.finalizeStatement(*session->getStatementMessage(), session);
1351
1409
    }
1352
1410
    else
1353
1411
    {
1354
1412
      if (before_record == NULL)
1355
 
        result= transaction_services.insertRecord(*session, *table);
 
1413
        replication_services.insertRecord(session, table);
1356
1414
      else
1357
 
        transaction_services.updateRecord(*session, *table, before_record, after_record);
 
1415
        replication_services.updateRecord(session, table, before_record, after_record);
1358
1416
    }
1359
1417
    break;
1360
1418
  case SQLCOM_INSERT:
1361
1419
  case SQLCOM_INSERT_SELECT:
1362
 
  case SQLCOM_LOAD:
1363
1420
    /*
1364
1421
     * The else block below represents an 
1365
1422
     * INSERT ... ON DUPLICATE KEY UPDATE that
1367
1424
     * an update.
1368
1425
     */
1369
1426
    if (before_record == NULL)
1370
 
      result= transaction_services.insertRecord(*session, *table);
 
1427
      replication_services.insertRecord(session, table);
1371
1428
    else
1372
 
      transaction_services.updateRecord(*session, *table, before_record, after_record);
 
1429
      replication_services.updateRecord(session, table, before_record, after_record);
1373
1430
    break;
1374
1431
 
1375
1432
  case SQLCOM_UPDATE:
1376
 
    transaction_services.updateRecord(*session, *table, before_record, after_record);
 
1433
    replication_services.updateRecord(session, table, before_record, after_record);
1377
1434
    break;
1378
1435
 
1379
1436
  case SQLCOM_DELETE:
1380
 
    transaction_services.deleteRecord(*session, *table);
 
1437
    replication_services.deleteRecord(session, table);
1381
1438
    break;
1382
1439
  default:
1383
1440
    break;
1384
1441
  }
1385
1442
 
1386
 
  return result;
 
1443
  return false;
1387
1444
}
1388
1445
 
1389
1446
int Cursor::ha_external_lock(Session *session, int lock_type)
1395
1452
  */
1396
1453
  assert(next_insert_id == 0);
1397
1454
 
1398
 
  if (DRIZZLE_CURSOR_RDLOCK_START_ENABLED() ||
1399
 
      DRIZZLE_CURSOR_WRLOCK_START_ENABLED() ||
1400
 
      DRIZZLE_CURSOR_UNLOCK_START_ENABLED())
1401
 
  {
1402
 
    if (lock_type == F_RDLCK)
1403
 
    {
1404
 
      DRIZZLE_CURSOR_RDLOCK_START(getTable()->getShare()->getSchemaName(),
1405
 
                                  getTable()->getShare()->getTableName());
1406
 
    }
1407
 
    else if (lock_type == F_WRLCK)
1408
 
    {
1409
 
      DRIZZLE_CURSOR_WRLOCK_START(getTable()->getShare()->getSchemaName(),
1410
 
                                  getTable()->getShare()->getTableName());
1411
 
    }
1412
 
    else if (lock_type == F_UNLCK)
1413
 
    {
1414
 
      DRIZZLE_CURSOR_UNLOCK_START(getTable()->getShare()->getSchemaName(),
1415
 
                                  getTable()->getShare()->getTableName());
1416
 
    }
1417
 
  }
1418
 
 
1419
1455
  /*
1420
1456
    We cache the table flags if the locking succeeded. Otherwise, we
1421
1457
    keep them as they were when they were fetched in ha_open().
1423
1459
 
1424
1460
  int error= external_lock(session, lock_type);
1425
1461
 
1426
 
  if (DRIZZLE_CURSOR_RDLOCK_DONE_ENABLED() ||
1427
 
      DRIZZLE_CURSOR_WRLOCK_DONE_ENABLED() ||
1428
 
      DRIZZLE_CURSOR_UNLOCK_DONE_ENABLED())
1429
 
  {
1430
 
    if (lock_type == F_RDLCK)
1431
 
    {
1432
 
      DRIZZLE_CURSOR_RDLOCK_DONE(error);
1433
 
    }
1434
 
    else if (lock_type == F_WRLCK)
1435
 
    {
1436
 
      DRIZZLE_CURSOR_WRLOCK_DONE(error);
1437
 
    }
1438
 
    else if (lock_type == F_UNLCK)
1439
 
    {
1440
 
      DRIZZLE_CURSOR_UNLOCK_DONE(error);
1441
 
    }
1442
 
  }
1443
 
 
1444
1462
  return error;
1445
1463
}
1446
1464
 
1451
1469
int Cursor::ha_reset()
1452
1470
{
1453
1471
  /* 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 */
 
1472
  assert((unsigned char*) table->def_read_set.getBitmap() +
 
1473
              table->s->column_bitmap_size ==
 
1474
              (unsigned char*) table->def_write_set.getBitmap());
 
1475
  assert(table->s->all_set.isSetAll());
 
1476
  assert(table->key_read == 0);
 
1477
  /* ensure that ha_index_end / ha_rnd_end has been called */
1457
1478
  assert(inited == NONE);
1458
1479
  /* Free cache used by filesort */
1459
 
  getTable()->free_io_cache();
 
1480
  table->free_io_cache();
1460
1481
  /* reset the bitmaps to point to defaults */
1461
 
  getTable()->default_column_bitmaps();
 
1482
  table->default_column_bitmaps();
1462
1483
  return(reset());
1463
1484
}
1464
1485
 
1465
1486
 
1466
 
int Cursor::insertRecord(unsigned char *buf)
 
1487
int Cursor::ha_write_row(unsigned char *buf)
1467
1488
{
1468
1489
  int error;
1469
1490
 
1470
 
  /*
1471
 
   * If we have a timestamp column, update it to the current time
1472
 
   *
 
1491
  /* 
 
1492
   * If we have a timestamp column, update it to the current time 
 
1493
   * 
1473
1494
   * @TODO Technically, the below two lines can be take even further out of the
1474
1495
   * Cursor interface and into the fill_record() method.
1475
1496
   */
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
 
 
1499
 
  DRIZZLE_INSERT_ROW_DONE(error);
1500
 
 
1501
 
  if (unlikely(error))
 
1497
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
 
1498
    table->timestamp_field->set_time();
 
1499
 
 
1500
  mark_trx_read_write();
 
1501
 
 
1502
  if (unlikely(error= write_row(buf)))
1502
1503
  {
1503
1504
    return error;
1504
1505
  }
1505
1506
 
1506
 
  if (unlikely(log_row_for_replication(getTable(), NULL, buf)))
 
1507
  if (unlikely(log_row_for_replication(table, NULL, buf)))
1507
1508
    return HA_ERR_RBR_LOGGING_FAILED;
1508
1509
 
1509
1510
  return 0;
1510
1511
}
1511
1512
 
1512
1513
 
1513
 
int Cursor::updateRecord(const unsigned char *old_data, unsigned char *new_data)
 
1514
int Cursor::ha_update_row(const unsigned char *old_data, unsigned char *new_data)
1514
1515
{
1515
1516
  int error;
1516
1517
 
1517
1518
  /*
1518
 
    Some storage engines require that the new record is in getInsertRecord()
1519
 
    (and the old record is in getUpdateRecord()).
 
1519
    Some storage engines require that the new record is in record[0]
 
1520
    (and the old record is in record[1]).
1520
1521
   */
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
 
 
1545
 
  DRIZZLE_UPDATE_ROW_DONE(error);
1546
 
 
1547
 
  if (unlikely(error))
 
1522
  assert(new_data == table->record[0]);
 
1523
 
 
1524
  mark_trx_read_write();
 
1525
 
 
1526
  if (unlikely(error= update_row(old_data, new_data)))
1548
1527
  {
1549
1528
    return error;
1550
1529
  }
1551
1530
 
1552
 
  if (unlikely(log_row_for_replication(getTable(), old_data, new_data)))
 
1531
  if (unlikely(log_row_for_replication(table, old_data, new_data)))
1553
1532
    return HA_ERR_RBR_LOGGING_FAILED;
1554
1533
 
1555
1534
  return 0;
1556
1535
}
1557
 
TableShare *Cursor::getShare()
1558
 
{
1559
 
  return getTable()->getMutableShare();
1560
 
}
1561
1536
 
1562
 
int Cursor::deleteRecord(const unsigned char *buf)
 
1537
int Cursor::ha_delete_row(const unsigned char *buf)
1563
1538
{
1564
1539
  int error;
1565
1540
 
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
 
 
1583
 
  DRIZZLE_DELETE_ROW_DONE(error);
1584
 
 
1585
 
  if (unlikely(error))
 
1541
  mark_trx_read_write();
 
1542
 
 
1543
  if (unlikely(error= delete_row(buf)))
1586
1544
    return error;
1587
1545
 
1588
 
  if (unlikely(log_row_for_replication(getTable(), buf, NULL)))
 
1546
  if (unlikely(log_row_for_replication(table, buf, NULL)))
1589
1547
    return HA_ERR_RBR_LOGGING_FAILED;
1590
1548
 
1591
1549
  return 0;
1592
1550
}
1593
 
 
1594
 
} /* namespace drizzled */