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"
49
48
using namespace std;
49
using namespace drizzled;
54
51
/****************************************************************************
55
52
** General Cursor functions
56
53
****************************************************************************/
57
Cursor::Cursor(plugin::StorageEngine &engine_arg,
61
estimation_rows_to_insert(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)),
62
locked(false), implicit_emptied(0),
67
63
next_insert_id(0), insert_id_for_cur_row(0)
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
82
73
Cursor *Cursor::clone(memory::Root *mem_root)
84
Cursor *new_handler= getTable()->getMutableShare()->db_type()->getCursor(*getTable());
75
Cursor *new_handler= table->s->db_type()->getCursor(*table->s, mem_root);
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.
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)))
94
identifier::Table identifier(getTable()->getShare()->getSchemaName(),
95
getTable()->getShare()->getTableName(),
96
getTable()->getShare()->getType());
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,
100
87
HA_OPEN_IGNORE_IF_LOCKED))
101
88
return new_handler;
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
110
uint32_t Cursor::calculate_key_len(uint32_t key_position, key_part_map keypart_map_arg)
112
/* works only with key prefixes */
113
assert(((keypart_map_arg + 1) & keypart_map_arg) == 0);
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;
119
while (key_part_found < end_key_part_found && keypart_map_arg)
121
length+= key_part_found->store_length;
122
keypart_map_arg >>= 1;
128
int Cursor::startIndexScan(uint32_t idx, bool sorted)
92
int Cursor::ha_index_init(uint32_t idx, bool sorted)
131
95
assert(inited == NONE);
132
if (!(result= doStartIndexScan(idx, sorted)))
96
if (!(result= index_init(idx, sorted)))
138
int Cursor::endIndexScan()
102
int Cursor::ha_index_end()
140
104
assert(inited==INDEX);
143
return(doEndIndexScan());
146
int Cursor::startTableScan(bool scan)
110
int Cursor::ha_rnd_init(bool scan)
149
113
assert(inited==NONE || (inited==RND && scan));
150
inited= (result= doStartTableScan(scan)) ? NONE: RND;
114
inited= (result= rnd_init(scan)) ? NONE: RND;
155
int Cursor::endTableScan()
119
int Cursor::ha_rnd_end()
157
121
assert(inited==RND);
159
return(doEndTableScan());
162
126
int Cursor::ha_index_or_rnd_end()
164
return inited == INDEX ? endIndexScan() : inited == RND ? endTableScan() : 0;
128
return inited == INDEX ? ha_index_end() : inited == RND ? ha_rnd_end() : 0;
167
131
void Cursor::ha_start_bulk_insert(ha_rows rows)
184
154
bool Cursor::has_transactions()
186
return (getTable()->getShare()->db_type()->check_flag(HTON_BIT_DOES_TRANSACTIONS));
156
return (table->s->db_type()->check_flag(HTON_BIT_DOES_TRANSACTIONS));
189
void Cursor::ha_statistic_increment(uint64_t system_status_var::*offset) const
159
void Cursor::ha_statistic_increment(ulong SSV::*offset) const
191
(getTable()->in_use->status_var.*offset)++;
161
status_var_increment(table->in_use->status_var.*offset);
194
164
void **Cursor::ha_data(Session *session) const
196
return session->getEngineData(getEngine());
166
return session->getEngineData(engine);
169
Session *Cursor::ha_session(void) const
171
assert(!table || !table->in_use || table->in_use == current_session);
172
return (table && table->in_use) ? table->in_use : current_session;
199
176
bool Cursor::is_fatal_error(int error, uint32_t flags)
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(); }
214
int Cursor::doOpen(const identifier::Table &identifier, int mode, uint32_t test_if_locked)
216
return open(identifier.getPath().c_str(), mode, test_if_locked);
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
225
int Cursor::ha_open(const identifier::Table &identifier,
195
int Cursor::ha_open(Table *table_arg, const char *name, int mode,
231
if ((error= doOpen(identifier, mode, test_if_locked)))
201
assert(table->s == table_share);
202
assert(alloc_root_inited(&table->mem_root));
204
if ((error=open(name,mode,test_if_locked)))
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))
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);
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
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)))
254
228
error=HA_ERR_OUT_OF_MEM;
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
243
int Cursor::rnd_pos_by_record(unsigned char *record)
248
if (inited && (error= ha_index_end()))
250
if ((error= ha_rnd_init(false)))
253
return rnd_pos(record, ref);
263
257
Read first row (only) from a table.
265
259
This is never called for InnoDB tables, as these table types
277
271
TODO remove the test for HA_READ_ORDER
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))
282
error= startTableScan(1);
285
while ((error= rnd_next(buf)) == HA_ERR_RECORD_DELETED) ;
286
(void) endTableScan();
276
(void) ha_rnd_init(1);
277
while ((error= rnd_next(buf)) == HA_ERR_RECORD_DELETED) ;
291
282
/* Find the first row through the primary key */
292
error= startIndexScan(primary_key, 0);
295
error=index_first(buf);
296
(void) endIndexScan();
283
(void) ha_index_init(primary_key, 0);
284
error=index_first(buf);
285
(void) ha_index_end();
311
299
@verbatim 1,5,15,25,35,... @endverbatim
314
compute_next_insert_id(uint64_t nr, drizzle_system_variables *variables)
302
compute_next_insert_id(uint64_t nr,struct system_variables *variables)
316
304
if (variables->auto_increment_increment == 1)
317
305
return (nr+1); // optimization of the formula below
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 */
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)
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);
543
if (getTable()->getShare()->next_number_keypart == 0)
531
if (table->s->next_number_keypart == 0)
545
533
/* We must defer the appending until "nr" has been possibly truncated */
550
if (unlikely(getTable()->next_number_field->store((int64_t) nr, true)))
538
if (unlikely(table->next_number_field->store((int64_t) nr, true)))
553
541
first test if the query was aborted due to strict mode constraints
555
if (session->getKilled() == Session::KILL_BAD_DATA)
543
if (session->killed == Session::KILL_BAD_DATA)
556
544
return HA_ERR_AUTOINC_ERANGE;
563
551
bother shifting the right bound (anyway any other value from this
564
552
interval will cause a duplicate key).
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();
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
597
void Cursor::get_auto_increment(uint64_t ,
600
uint64_t *first_value,
601
uint64_t *nb_reserved_values)
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]);
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.
617
*nb_reserved_values= UINT64_MAX;
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);
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...
634
*nb_reserved_values= 1;
640
nr= ((uint64_t) table->next_number_field->
641
val_int_offset(table->s->rec_buff_length)+1);
643
(void) extra(HA_EXTRA_NO_KEYREAD);
610
648
void Cursor::ha_release_auto_increment()
659
Cursor::setTransactionReadWrite()
697
Cursor::mark_trx_read_write()
661
ResourceContext *resource_context;
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.
668
if (not getTable()->in_use)
671
resource_context= getTable()->in_use->getResourceContext(getEngine());
699
Ha_trx_info *ha_info= ha_session()->getEngineInfo(engine);
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
707
735
* Trigger post-truncate notification to plugins...
709
* @todo Make TransactionServices generic to AfterTriggerServices
737
* @todo Make ReplicationServices generic to AfterTriggerServices
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);
801
829
Cursor::closeMarkForDelete(const char *name)
803
setTransactionReadWrite();
831
mark_trx_read_write();
805
833
return drop_table(name);
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.
844
int ha_enable_transaction(Session *session, bool on)
848
if ((session->transaction.on= on))
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.
856
if (!(error= ha_commit_trans(session, 0)))
857
if (! session->endTransaction(COMMIT))
808
864
int Cursor::index_next_same(unsigned char *buf, const unsigned char *key, uint32_t keylen)
811
867
if (!(error=index_next(buf)))
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;
872
KEY_PART_INFO *key_part;
873
KEY_PART_INFO *key_part_end= NULL;
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.
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++)
841
if (key_cmp_if_same(getTable(), key, active_index, keylen))
897
if (key_cmp_if_same(table, key, active_index, keylen))
843
getTable()->status=STATUS_NOT_FOUND;
899
table->status=STATUS_NOT_FOUND;
844
900
error=HA_ERR_END_OF_FILE;
847
903
/* Move back if necessary. */
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);
929
985
Cursor::multi_range_read_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
930
986
void *seq_init_param,
932
uint32_t *bufsz, uint32_t *flags, optimizer::CostVector *cost)
988
uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
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;
939
996
/* Default MRR implementation doesn't need buffer */
968
1028
/* The following calculation is the same as in multi_range_read_info(): */
969
1029
*flags |= HA_MRR_USE_DEFAULT_IMPL;
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);
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;
978
1038
return total_rows;
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)
1019
1079
*bufsz= 0; /* Default implementation doesn't need a buffer */
1021
1081
*flags |= HA_MRR_USE_DEFAULT_IMPL;
1024
cost->setAvgIOCost(1); /* assume random seeks */
1084
cost->avg_io_cost= 1; /* assume random seeks */
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);
1030
cost->setIOCount(read_time(keyno, n_ranges, n_rows));
1090
cost->io_count= read_time(keyno, n_ranges, n_rows);
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.
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,
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;
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);
1194
range_key_part= getTable()->key_info[active_index].key_part;
1254
range_key_part= table->key_info[active_index].key_part;
1196
1256
if (!start_key) // Read first record
1197
result= index_first(getTable()->getInsertRecord());
1257
result= index_first(table->record[0]);
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);
1331
Same as compare_key() but doesn't check have in_range_check_pushed_down.
1332
This is used by index condition pushdown implementation.
1335
int Cursor::compare_key2(key_range *range)
1339
return 0; // no max range
1340
cmp= key_cmp(range_key_part, range->key, range->length);
1342
cmp= key_compare_result_on_equal;
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)
1274
1351
int error, error1;
1275
error= doStartIndexScan(index, 0);
1352
error= index_init(index, 0);
1278
1355
error= index_read_map(buf, key, keypart_map, find_flag);
1279
error1= doEndIndexScan();
1356
error1= index_end();
1281
1358
return error ? error : error1;
1292
1369
const unsigned char *before_record,
1293
1370
const unsigned char *after_record)
1295
TransactionServices &transaction_services= TransactionServices::singleton();
1372
ReplicationServices &replication_services= ReplicationServices::singleton();
1296
1373
Session *const session= table->in_use;
1298
if (table->getShare()->getType() || not transaction_services.shouldConstructMessages())
1375
if (table->s->tmp_table || ! replication_services.isActive())
1301
1378
bool result= false;
1303
1380
switch (session->lex->sql_command)
1305
case SQLCOM_CREATE_TABLE:
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
1315
result= transaction_services.insertRecord(*session, *table);
1317
1382
case SQLCOM_REPLACE:
1318
1383
case SQLCOM_REPLACE_SELECT:
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
1337
1402
if (after_record == NULL)
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.
1344
transaction_services.deleteRecord(*session, *table, true);
1404
replication_services.deleteRecord(session, table);
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.
1350
transaction_services.finalizeStatementMessage(*session->getStatementMessage(), *session);
1410
replication_services.finalizeStatement(*session->getStatementMessage(), session);
1354
1414
if (before_record == NULL)
1355
result= transaction_services.insertRecord(*session, *table);
1415
result= replication_services.insertRecord(session, table);
1357
transaction_services.updateRecord(*session, *table, before_record, after_record);
1417
replication_services.updateRecord(session, table, before_record, after_record);
1360
1420
case SQLCOM_INSERT:
1361
1421
case SQLCOM_INSERT_SELECT:
1364
1423
* The else block below represents an
1365
1424
* INSERT ... ON DUPLICATE KEY UPDATE that
1369
1428
if (before_record == NULL)
1370
result= transaction_services.insertRecord(*session, *table);
1429
result= replication_services.insertRecord(session, table);
1372
transaction_services.updateRecord(*session, *table, before_record, after_record);
1431
replication_services.updateRecord(session, table, before_record, after_record);
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);
1379
1438
case SQLCOM_DELETE:
1380
transaction_services.deleteRecord(*session, *table);
1439
replication_services.deleteRecord(session, table);
1402
1461
if (lock_type == F_RDLCK)
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);
1407
1466
else if (lock_type == F_WRLCK)
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);
1412
1471
else if (lock_type == F_UNLCK)
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);
1451
1510
int Cursor::ha_reset()
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());
1466
int Cursor::insertRecord(unsigned char *buf)
1528
int Cursor::ha_write_row(unsigned char *buf)
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.
1476
if (getTable()->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
1478
getTable()->timestamp_field->set_time();
1481
DRIZZLE_INSERT_ROW_START(getTable()->getShare()->getSchemaName(), getTable()->getShare()->getTableName());
1482
setTransactionReadWrite();
1484
if (unlikely(plugin::EventObserver::beforeInsertRecord(*getTable(), buf)))
1486
error= ER_EVENT_OBSERVER_PLUGIN;
1490
error= doInsertRecord(buf);
1491
if (unlikely(plugin::EventObserver::afterInsertRecord(*getTable(), buf, error)))
1493
error= ER_EVENT_OBSERVER_PLUGIN;
1497
ha_statistic_increment(&system_status_var::ha_write_count);
1538
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
1539
table->timestamp_field->set_time();
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);
1501
1546
if (unlikely(error))
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;
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)
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]).
1521
assert(new_data == getTable()->getInsertRecord());
1523
DRIZZLE_UPDATE_ROW_START(getTable()->getShare()->getSchemaName(), getTable()->getShare()->getTableName());
1524
setTransactionReadWrite();
1525
if (unlikely(plugin::EventObserver::beforeUpdateRecord(*getTable(), old_data, new_data)))
1527
error= ER_EVENT_OBSERVER_PLUGIN;
1531
if (getTable()->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
1533
getTable()->timestamp_field->set_time();
1536
error= doUpdateRecord(old_data, new_data);
1537
if (unlikely(plugin::EventObserver::afterUpdateRecord(*getTable(), old_data, new_data, error)))
1539
error= ER_EVENT_OBSERVER_PLUGIN;
1543
ha_statistic_increment(&system_status_var::ha_update_count);
1566
assert(new_data == table->record[0]);
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);
1547
1573
if (unlikely(error))
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;
1557
TableShare *Cursor::getShare()
1559
return getTable()->getMutableShare();
1562
int Cursor::deleteRecord(const unsigned char *buf)
1584
int Cursor::ha_delete_row(const unsigned char *buf)
1566
DRIZZLE_DELETE_ROW_START(getTable()->getShare()->getSchemaName(), getTable()->getShare()->getTableName());
1567
setTransactionReadWrite();
1568
if (unlikely(plugin::EventObserver::beforeDeleteRecord(*getTable(), buf)))
1570
error= ER_EVENT_OBSERVER_PLUGIN;
1574
error= doDeleteRecord(buf);
1575
if (unlikely(plugin::EventObserver::afterDeleteRecord(*getTable(), buf, error)))
1577
error= ER_EVENT_OBSERVER_PLUGIN;
1581
ha_statistic_increment(&system_status_var::ha_delete_count);
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);
1585
1593
if (unlikely(error))
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;
1594
} /* namespace drizzled */