1
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2008 Sun Microsystems, Inc.
4
* Copyright (C) 2008 Sun Microsystems
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
30
#include <drizzled/error.h>
31
#include <drizzled/field/epoch.h>
32
#include <drizzled/gettext.h>
33
#include <drizzled/internal/my_sys.h>
34
#include <drizzled/item/empty_string.h>
35
#include <drizzled/item/int.h>
36
#include <drizzled/lock.h>
37
#include <drizzled/message/table.h>
38
#include <drizzled/my_hash.h>
39
#include <drizzled/optimizer/cost_vector.h>
40
#include <drizzled/plugin/client.h>
41
#include <drizzled/plugin/event_observer.h>
42
#include <drizzled/plugin/storage_engine.h>
43
#include <drizzled/probes.h>
44
#include <drizzled/session.h>
45
#include <drizzled/sql_base.h>
46
#include <drizzled/sql_parse.h>
47
#include <drizzled/transaction_services.h>
30
#include "drizzled/my_hash.h"
31
#include "drizzled/error.h"
32
#include "drizzled/gettext.h"
33
#include "drizzled/probes.h"
34
#include "drizzled/sql_parse.h"
35
#include "drizzled/optimizer/cost_vector.h"
36
#include "drizzled/session.h"
37
#include "drizzled/sql_base.h"
38
#include "drizzled/transaction_services.h"
39
#include "drizzled/lock.h"
40
#include "drizzled/item/int.h"
41
#include "drizzled/item/empty_string.h"
42
#include "drizzled/field/timestamp.h"
43
#include "drizzled/message/table.pb.h"
44
#include "drizzled/plugin/client.h"
45
#include "drizzled/internal/my_sys.h"
46
#include "drizzled/plugin/event_observer.h"
49
48
using namespace std;
55
54
** General Cursor functions
56
55
****************************************************************************/
57
56
Cursor::Cursor(plugin::StorageEngine &engine_arg,
61
estimation_rows_to_insert(0),
57
TableShare &share_arg)
58
: table_share(&share_arg), table(0),
59
estimation_rows_to_insert(0), engine(&engine_arg),
63
61
key_used_on_scan(MAX_KEY), active_index(MAX_KEY),
64
62
ref_length(sizeof(internal::my_off_t)),
82
80
Cursor *Cursor::clone(memory::Root *mem_root)
84
Cursor *new_handler= getTable()->getMutableShare()->db_type()->getCursor(*getTable());
82
Cursor *new_handler= table->getMutableShare()->db_type()->getCursor(*table->getMutableShare());
87
85
Allocate Cursor->ref here because otherwise ha_open will allocate it
91
89
if (!(new_handler->ref= (unsigned char*) mem_root->alloc_root(ALIGN_SIZE(ref_length)*2)))
94
identifier::Table identifier(getTable()->getShare()->getSchemaName(),
95
getTable()->getShare()->getTableName(),
96
getTable()->getShare()->getType());
92
TableIdentifier identifier(table->getShare()->getSchemaName(),
93
table->getShare()->getTableName(),
94
table->getShare()->getType());
98
96
if (new_handler && !new_handler->ha_open(identifier,
99
getTable()->getDBStat(),
98
table->getMutableShare()->getNormalizedPath(),
100
100
HA_OPEN_IGNORE_IF_LOCKED))
101
101
return new_handler;
112
112
/* works only with key prefixes */
113
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;
115
const KeyPartInfo *key_part_found= table->getShare()->getKeyInfo(key_position).key_part;
116
const KeyPartInfo *end_key_part_found= key_part_found + table->getShare()->getKeyInfo(key_position).key_parts;
117
117
uint32_t length= 0;
119
119
while (key_part_found < end_key_part_found && keypart_map_arg)
184
190
bool Cursor::has_transactions()
186
return (getTable()->getShare()->db_type()->check_flag(HTON_BIT_DOES_TRANSACTIONS));
192
return (table->getShare()->db_type()->check_flag(HTON_BIT_DOES_TRANSACTIONS));
189
195
void Cursor::ha_statistic_increment(uint64_t system_status_var::*offset) const
191
(getTable()->in_use->status_var.*offset)++;
197
status_var_increment(table->in_use->status_var.*offset);
194
200
void **Cursor::ha_data(Session *session) const
196
return session->getEngineData(getEngine());
202
return session->getEngineData(engine);
199
205
bool Cursor::is_fatal_error(int error, uint32_t flags)
210
216
ha_rows Cursor::records() { return stats.records; }
211
217
uint64_t Cursor::tableSize() { return stats.index_file_length + stats.data_file_length; }
212
uint64_t Cursor::rowSize() { return getTable()->getRecordLength() + getTable()->sizeFields(); }
218
uint64_t Cursor::rowSize() { return table->getRecordLength() + table->sizeFields(); }
214
int Cursor::doOpen(const identifier::Table &identifier, int mode, uint32_t test_if_locked)
220
int Cursor::doOpen(const TableIdentifier &identifier, int mode, uint32_t test_if_locked)
216
222
return open(identifier.getPath().c_str(), mode, test_if_locked);
222
228
Try O_RDONLY if cannot open as O_RDWR
223
229
Don't wait for locks if not HA_OPEN_WAIT_IF_LOCKED is set
225
int Cursor::ha_open(const identifier::Table &identifier,
231
int Cursor::ha_open(const TableIdentifier &identifier,
232
Table *table_arg, const char *name, int mode,
227
233
int test_if_locked)
238
assert(table->getShare() == table_share);
240
assert(identifier.getPath().compare(name) == 0);
231
241
if ((error= doOpen(identifier, mode, test_if_locked)))
233
243
if ((error == EACCES || error == EROFS) && mode == O_RDWR &&
234
(getTable()->db_stat & HA_TRY_READ_ONLY))
244
(table->db_stat & HA_TRY_READ_ONLY))
236
getTable()->db_stat|=HA_READ_ONLY;
246
table->db_stat|=HA_READ_ONLY;
237
247
error= doOpen(identifier, 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;
256
if (table->getShare()->db_options_in_use & HA_OPTION_READ_ONLY_DATA)
257
table->db_stat|=HA_READ_ONLY;
248
258
(void) extra(HA_EXTRA_NO_READCHECK); // Not needed in SQL
250
260
/* 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)))
261
if (!ref && !(ref= (unsigned char*) table->alloc_root(ALIGN_SIZE(ref_length)*2)))
254
264
error=HA_ERR_OUT_OF_MEM;
268
278
int Cursor::read_first_row(unsigned char * buf, uint32_t primary_key)
272
282
ha_statistic_increment(&system_status_var::ha_read_first_count);
275
285
If there is very few deleted rows in the table, find the first row by
276
286
scanning the table.
277
@todo remove the test for HA_READ_ORDER
287
TODO remove the test for HA_READ_ORDER
279
289
if (stats.deleted < 10 || primary_key >= MAX_KEY ||
280
!(getTable()->index_flags(primary_key) & HA_READ_ORDER))
290
!(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();
292
(void) startTableScan(1);
293
while ((error= rnd_next(buf)) == HA_ERR_RECORD_DELETED) ;
294
(void) endTableScan();
291
298
/* Find the first row through the primary key */
292
error= startIndexScan(primary_key, 0);
295
error=index_first(buf);
296
(void) endIndexScan();
299
(void) startIndexScan(primary_key, 0);
300
error=index_first(buf);
301
(void) endIndexScan();
311
315
@verbatim 1,5,15,25,35,... @endverbatim
314
compute_next_insert_id(uint64_t nr, drizzle_system_variables *variables)
318
compute_next_insert_id(uint64_t nr,struct system_variables *variables)
316
320
if (variables->auto_increment_increment == 1)
317
321
return (nr+1); // optimization of the formula below
331
335
Session::next_insert_id to be greater than the explicit value.
333
337
if ((next_insert_id > 0) && (nr >= next_insert_id))
334
set_next_insert_id(compute_next_insert_id(nr, &getTable()->in_use->variables));
338
set_next_insert_id(compute_next_insert_id(nr, &table->in_use->variables));
351
355
The number X if it exists, "nr" otherwise.
354
prev_insert_id(uint64_t nr, drizzle_system_variables *variables)
358
prev_insert_id(uint64_t nr, struct system_variables *variables)
356
360
if (unlikely(nr < variables->auto_increment_offset))
449
453
uint64_t nr, nb_reserved_values;
450
454
bool append= false;
451
Session *session= getTable()->in_use;
452
drizzle_system_variables *variables= &session->variables;
455
Session *session= table->in_use;
456
struct system_variables *variables= &session->variables;
455
459
next_insert_id is a "cursor" into the reserved interval, it may go greater
461
465
for an auto increment column, not a magic value like NULL is.
462
466
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)
468
if ((nr= table->next_number_field->val_int()) != 0
469
|| table->auto_increment_field_not_null)
468
472
Update next_insert_id if we had already generated a value in this
540
544
nr= compute_next_insert_id(nr-1, variables);
543
if (getTable()->getShare()->next_number_keypart == 0)
547
if (table->getShare()->next_number_keypart == 0)
545
549
/* We must defer the appending until "nr" has been possibly truncated */
550
if (unlikely(getTable()->next_number_field->store((int64_t) nr, true)))
554
if (unlikely(table->next_number_field->store((int64_t) nr, true)))
553
557
first test if the query was aborted due to strict mode constraints
555
if (session->getKilled() == Session::KILL_BAD_DATA)
559
if (session->killed == Session::KILL_BAD_DATA)
556
560
return HA_ERR_AUTOINC_ERANGE;
563
567
bother shifting the right bound (anyway any other value from this
564
568
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();
570
nr= prev_insert_id(table->next_number_field->val_int(), variables);
571
if (unlikely(table->next_number_field->store((int64_t) nr, true)))
572
nr= table->next_number_field->val_int();
619
623
this statement used forced auto_increment values if there were some,
620
624
wipe them away for other statements.
622
getTable()->in_use->auto_inc_intervals_forced.empty();
626
table->in_use->auto_inc_intervals_forced.empty();
665
669
* possible resource to gain (and if there is... then there is a bug such
666
670
* that in_use should have been set.
668
if (not getTable()->in_use)
672
if (not table || not table->in_use)
671
resource_context= getTable()->in_use->getResourceContext(getEngine());
675
resource_context= table->in_use->getResourceContext(engine);
673
677
When a storage engine method is called, the transaction must
674
678
have been started, unless it's a DDL call, for which the
709
713
* @todo Make TransactionServices generic to AfterTriggerServices
712
Session *const session= getTable()->in_use;
716
Session *const session= table->in_use;
713
717
TransactionServices &transaction_services= TransactionServices::singleton();
714
transaction_services.truncateTable(*session, *getTable());
718
transaction_services.truncateTable(session, table);
829
save_record_0= getTable()->getInsertRecord();
830
getTable()->record[0]= buf;
831
key_info= getTable()->key_info + active_index;
833
save_record_0= table->getInsertRecord();
834
table->record[0]= buf;
835
key_info= table->key_info + active_index;
832
836
key_part= key_info->key_part;
833
837
key_part_end= key_part + key_info->key_parts;
834
838
for (; key_part < key_part_end; key_part++)
841
if (key_cmp_if_same(getTable(), key, active_index, keylen))
845
if (key_cmp_if_same(table, key, active_index, keylen))
843
getTable()->status=STATUS_NOT_FOUND;
847
table->status=STATUS_NOT_FOUND;
844
848
error=HA_ERR_END_OF_FILE;
847
851
/* Move back if necessary. */
850
getTable()->record[0]= save_record_0;
854
table->record[0]= save_record_0;
851
855
for (key_part= key_info->key_part; key_part < key_part_end; key_part++)
852
856
key_part->field->move_field_offset(-ptrdiff);
884
888
double Cursor::index_only_read_time(uint32_t keynr, double key_records)
886
890
uint32_t keys_per_block= (stats.block_size/2/
887
(getTable()->key_info[keynr].key_length + ref_length) + 1);
891
(table->key_info[keynr].key_length + ref_length) + 1);
888
892
return ((double) (key_records + keys_per_block-1) /
889
893
(double) keys_per_block);
915
919
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
920
session->killed and return HA_POS_ERROR if it is not zero. This is required
917
921
for a user to be able to interrupt the calculation by killing the
918
922
connection/query.
1191
1195
key_compare_result_on_equal= ((end_key->flag == HA_READ_BEFORE_KEY) ? 1 :
1192
1196
(end_key->flag == HA_READ_AFTER_KEY) ? -1 : 0);
1194
range_key_part= getTable()->key_info[active_index].key_part;
1198
range_key_part= table->key_info[active_index].key_part;
1196
1200
if (!start_key) // Read first record
1197
result= index_first(getTable()->getInsertRecord());
1201
result= index_first(table->getInsertRecord());
1199
result= index_read_map(getTable()->getInsertRecord(),
1203
result= index_read_map(table->getInsertRecord(),
1200
1204
start_key->key,
1201
1205
start_key->keypart_map,
1202
1206
start_key->flag);
1231
1235
/* We trust that index_next_same always gives a row in range */
1232
return(index_next_same(getTable()->getInsertRecord(),
1236
return(index_next_same(table->getInsertRecord(),
1233
1237
end_range->key,
1234
1238
end_range->length));
1236
result= index_next(getTable()->getInsertRecord());
1240
result= index_next(table->getInsertRecord());
1239
1243
return(compare_key(end_range) <= 0 ? 0 : HA_ERR_END_OF_FILE);
1312
1316
* CREATE TABLE will commit the transaction containing
1315
result= transaction_services.insertRecord(*session, *table);
1319
result= transaction_services.insertRecord(session, table);
1317
1321
case SQLCOM_REPLACE:
1318
1322
case SQLCOM_REPLACE_SELECT:
1323
1327
* called. If it fails, then a call to deleteRecord()
1324
1328
* is called, followed by a repeat of the original
1325
1329
* call to insertRecord(). So, log_row_for_replication
1326
* could be called multiple times for a REPLACE
1330
* could be called either once or twice for a REPLACE
1327
1331
* statement. The below looks at the values of before_record
1328
1332
* and after_record to determine which call to this
1329
1333
* function is for the delete or the insert, since NULL
1337
1341
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);
1343
transaction_services.deleteRecord(session, table);
1346
1345
* We set the "current" statement message to NULL. This triggers
1347
1346
* the replication services component to generate a new statement
1348
1347
* message for the inserted record which will come next.
1350
transaction_services.finalizeStatementMessage(*session->getStatementMessage(), *session);
1349
transaction_services.finalizeStatementMessage(*session->getStatementMessage(), session);
1354
1353
if (before_record == NULL)
1355
result= transaction_services.insertRecord(*session, *table);
1354
result= transaction_services.insertRecord(session, table);
1357
transaction_services.updateRecord(*session, *table, before_record, after_record);
1356
transaction_services.updateRecord(session, table, before_record, after_record);
1360
1359
case SQLCOM_INSERT:
1361
1360
case SQLCOM_INSERT_SELECT:
1364
1362
* The else block below represents an
1365
1363
* INSERT ... ON DUPLICATE KEY UPDATE that
1369
1367
if (before_record == NULL)
1370
result= transaction_services.insertRecord(*session, *table);
1368
result= transaction_services.insertRecord(session, table);
1372
transaction_services.updateRecord(*session, *table, before_record, after_record);
1370
transaction_services.updateRecord(session, table, before_record, after_record);
1375
1373
case SQLCOM_UPDATE:
1376
transaction_services.updateRecord(*session, *table, before_record, after_record);
1374
transaction_services.updateRecord(session, table, before_record, after_record);
1379
1377
case SQLCOM_DELETE:
1380
transaction_services.deleteRecord(*session, *table);
1378
transaction_services.deleteRecord(session, table);
1402
1400
if (lock_type == F_RDLCK)
1404
DRIZZLE_CURSOR_RDLOCK_START(getTable()->getShare()->getSchemaName(),
1405
getTable()->getShare()->getTableName());
1402
DRIZZLE_CURSOR_RDLOCK_START(table_share->getSchemaName(),
1403
table_share->getTableName());
1407
1405
else if (lock_type == F_WRLCK)
1409
DRIZZLE_CURSOR_WRLOCK_START(getTable()->getShare()->getSchemaName(),
1410
getTable()->getShare()->getTableName());
1407
DRIZZLE_CURSOR_WRLOCK_START(table_share->getSchemaName(),
1408
table_share->getTableName());
1412
1410
else if (lock_type == F_UNLCK)
1414
DRIZZLE_CURSOR_UNLOCK_START(getTable()->getShare()->getSchemaName(),
1415
getTable()->getShare()->getTableName());
1412
DRIZZLE_CURSOR_UNLOCK_START(table_share->getSchemaName(),
1413
table_share->getTableName());
1451
1449
int Cursor::ha_reset()
1453
1451
/* Check that we have called all proper deallocation functions */
1454
assert(! getTable()->getShare()->all_set.none());
1455
assert(getTable()->key_read == 0);
1452
assert((unsigned char*) table->def_read_set.getBitmap() +
1453
table->getShare()->column_bitmap_size ==
1454
(unsigned char*) table->def_write_set.getBitmap());
1455
assert(table->getShare()->all_set.isSetAll());
1456
assert(table->key_read == 0);
1456
1457
/* ensure that ha_index_end / endTableScan has been called */
1457
1458
assert(inited == NONE);
1458
1459
/* Free cache used by filesort */
1459
getTable()->free_io_cache();
1460
table->free_io_cache();
1460
1461
/* reset the bitmaps to point to defaults */
1461
getTable()->default_column_bitmaps();
1462
table->default_column_bitmaps();
1462
1463
return(reset());
1473
1474
* @TODO Technically, the below two lines can be take even further out of the
1474
1475
* Cursor interface and into the fill_record() method.
1476
if (getTable()->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
1477
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
1478
getTable()->timestamp_field->set_time();
1479
table->timestamp_field->set_time();
1481
DRIZZLE_INSERT_ROW_START(getTable()->getShare()->getSchemaName(), getTable()->getShare()->getTableName());
1482
DRIZZLE_INSERT_ROW_START(table_share->getSchemaName(), table_share->getTableName());
1482
1483
setTransactionReadWrite();
1484
if (unlikely(plugin::EventObserver::beforeInsertRecord(*getTable(), buf)))
1485
if (unlikely(plugin::EventObserver::beforeInsertRecord(*table, buf)))
1486
1487
error= ER_EVENT_OBSERVER_PLUGIN;
1490
1491
error= doInsertRecord(buf);
1491
if (unlikely(plugin::EventObserver::afterInsertRecord(*getTable(), buf, error)))
1492
if (unlikely(plugin::EventObserver::afterInsertRecord(*table, buf, error)))
1493
1494
error= ER_EVENT_OBSERVER_PLUGIN;
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;
1518
1519
Some storage engines require that the new record is in getInsertRecord()
1519
1520
(and the old record is in getUpdateRecord()).
1521
assert(new_data == getTable()->getInsertRecord());
1522
assert(new_data == table->getInsertRecord());
1523
DRIZZLE_UPDATE_ROW_START(getTable()->getShare()->getSchemaName(), getTable()->getShare()->getTableName());
1524
DRIZZLE_UPDATE_ROW_START(table_share->getSchemaName(), table_share->getTableName());
1524
1525
setTransactionReadWrite();
1525
if (unlikely(plugin::EventObserver::beforeUpdateRecord(*getTable(), old_data, new_data)))
1526
if (unlikely(plugin::EventObserver::beforeUpdateRecord(*table, old_data, new_data)))
1527
1528
error= ER_EVENT_OBSERVER_PLUGIN;
1531
if (getTable()->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
1532
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
1533
getTable()->timestamp_field->set_time();
1534
table->timestamp_field->set_time();
1536
1537
error= doUpdateRecord(old_data, new_data);
1537
if (unlikely(plugin::EventObserver::afterUpdateRecord(*getTable(), old_data, new_data, error)))
1538
if (unlikely(plugin::EventObserver::afterUpdateRecord(*table, old_data, new_data, error)))
1539
1540
error= ER_EVENT_OBSERVER_PLUGIN;
1552
if (unlikely(log_row_for_replication(getTable(), old_data, new_data)))
1553
if (unlikely(log_row_for_replication(table, old_data, new_data)))
1553
1554
return HA_ERR_RBR_LOGGING_FAILED;
1557
TableShare *Cursor::getShare()
1559
return getTable()->getMutableShare();
1562
1559
int Cursor::deleteRecord(const unsigned char *buf)
1566
DRIZZLE_DELETE_ROW_START(getTable()->getShare()->getSchemaName(), getTable()->getShare()->getTableName());
1563
DRIZZLE_DELETE_ROW_START(table_share->getSchemaName(), table_share->getTableName());
1567
1564
setTransactionReadWrite();
1568
if (unlikely(plugin::EventObserver::beforeDeleteRecord(*getTable(), buf)))
1565
if (unlikely(plugin::EventObserver::beforeDeleteRecord(*table, buf)))
1570
1567
error= ER_EVENT_OBSERVER_PLUGIN;
1574
1571
error= doDeleteRecord(buf);
1575
if (unlikely(plugin::EventObserver::afterDeleteRecord(*getTable(), buf, error)))
1572
if (unlikely(plugin::EventObserver::afterDeleteRecord(*table, buf, error)))
1577
1574
error= ER_EVENT_OBSERVER_PLUGIN;
1585
1582
if (unlikely(error))
1588
if (unlikely(log_row_for_replication(getTable(), buf, NULL)))
1585
if (unlikely(log_row_for_replication(table, buf, NULL)))
1589
1586
return HA_ERR_RBR_LOGGING_FAILED;