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
4
* Copyright (C) 2008 Sun Microsystems, Inc.
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/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"
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>
48
49
using namespace std;
54
55
** General Cursor functions
55
56
****************************************************************************/
56
57
Cursor::Cursor(plugin::StorageEngine &engine_arg,
57
TableShare &share_arg)
58
: table_share(&share_arg), table(0),
59
estimation_rows_to_insert(0), engine(&engine_arg),
61
estimation_rows_to_insert(0),
61
63
key_used_on_scan(MAX_KEY), active_index(MAX_KEY),
62
64
ref_length(sizeof(internal::my_off_t)),
80
82
Cursor *Cursor::clone(memory::Root *mem_root)
82
Cursor *new_handler= table->getMutableShare()->db_type()->getCursor(*table->getMutableShare());
84
Cursor *new_handler= getTable()->getMutableShare()->db_type()->getCursor(*getTable());
85
87
Allocate Cursor->ref here because otherwise ha_open will allocate it
89
91
if (!(new_handler->ref= (unsigned char*) mem_root->alloc_root(ALIGN_SIZE(ref_length)*2)))
92
TableIdentifier identifier(table->getShare()->getSchemaName(),
93
table->getShare()->getTableName(),
94
table->getShare()->getType());
94
identifier::Table identifier(getTable()->getShare()->getSchemaName(),
95
getTable()->getShare()->getTableName(),
96
getTable()->getShare()->getType());
96
98
if (new_handler && !new_handler->ha_open(identifier,
99
getTable()->getDBStat(),
99
100
HA_OPEN_IGNORE_IF_LOCKED))
100
101
return new_handler;
111
112
/* works only with key prefixes */
112
113
assert(((keypart_map_arg + 1) & keypart_map_arg) == 0);
114
const KeyPartInfo *key_part_found= table->getShare()->getKeyInfo(key_position).key_part;
115
const KeyPartInfo *end_key_part_found= key_part_found + table->getShare()->getKeyInfo(key_position).key_parts;
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;
116
117
uint32_t length= 0;
118
119
while (key_part_found < end_key_part_found && keypart_map_arg)
189
184
bool Cursor::has_transactions()
191
return (table->getShare()->db_type()->check_flag(HTON_BIT_DOES_TRANSACTIONS));
186
return (getTable()->getShare()->db_type()->check_flag(HTON_BIT_DOES_TRANSACTIONS));
194
189
void Cursor::ha_statistic_increment(uint64_t system_status_var::*offset) const
196
(table->in_use->status_var.*offset)++;
191
(getTable()->in_use->status_var.*offset)++;
199
194
void **Cursor::ha_data(Session *session) const
201
return session->getEngineData(engine);
196
return session->getEngineData(getEngine());
204
199
bool Cursor::is_fatal_error(int error, uint32_t flags)
215
210
ha_rows Cursor::records() { return stats.records; }
216
211
uint64_t Cursor::tableSize() { return stats.index_file_length + stats.data_file_length; }
217
uint64_t Cursor::rowSize() { return table->getRecordLength() + table->sizeFields(); }
212
uint64_t Cursor::rowSize() { return getTable()->getRecordLength() + getTable()->sizeFields(); }
219
int Cursor::doOpen(const TableIdentifier &identifier, int mode, uint32_t test_if_locked)
214
int Cursor::doOpen(const identifier::Table &identifier, int mode, uint32_t test_if_locked)
221
216
return open(identifier.getPath().c_str(), mode, test_if_locked);
227
222
Try O_RDONLY if cannot open as O_RDWR
228
223
Don't wait for locks if not HA_OPEN_WAIT_IF_LOCKED is set
230
int Cursor::ha_open(const TableIdentifier &identifier,
225
int Cursor::ha_open(const identifier::Table &identifier,
233
227
int test_if_locked)
238
assert(table->getShare() == table_share);
240
231
if ((error= doOpen(identifier, mode, test_if_locked)))
242
233
if ((error == EACCES || error == EROFS) && mode == O_RDWR &&
243
(table->db_stat & HA_TRY_READ_ONLY))
234
(getTable()->db_stat & HA_TRY_READ_ONLY))
245
table->db_stat|=HA_READ_ONLY;
236
getTable()->db_stat|=HA_READ_ONLY;
246
237
error= doOpen(identifier, O_RDONLY,test_if_locked);
255
if (table->getShare()->db_options_in_use & HA_OPTION_READ_ONLY_DATA)
256
table->db_stat|=HA_READ_ONLY;
246
if (getTable()->getShare()->db_options_in_use & HA_OPTION_READ_ONLY_DATA)
247
getTable()->db_stat|=HA_READ_ONLY;
257
248
(void) extra(HA_EXTRA_NO_READCHECK); // Not needed in SQL
259
250
/* ref is already allocated for us if we're called from Cursor::clone() */
260
if (!ref && !(ref= (unsigned char*) table->alloc_root(ALIGN_SIZE(ref_length)*2)))
251
if (!ref && !(ref= (unsigned char*) getTable()->alloc_root(ALIGN_SIZE(ref_length)*2)))
263
254
error=HA_ERR_OUT_OF_MEM;
277
268
int Cursor::read_first_row(unsigned char * buf, uint32_t primary_key)
281
272
ha_statistic_increment(&system_status_var::ha_read_first_count);
284
275
If there is very few deleted rows in the table, find the first row by
285
276
scanning the table.
286
TODO remove the test for HA_READ_ORDER
277
@todo remove the test for HA_READ_ORDER
288
279
if (stats.deleted < 10 || primary_key >= MAX_KEY ||
289
!(table->index_flags(primary_key) & HA_READ_ORDER))
280
!(getTable()->index_flags(primary_key) & HA_READ_ORDER))
291
(void) startTableScan(1);
292
while ((error= rnd_next(buf)) == HA_ERR_RECORD_DELETED) ;
293
(void) endTableScan();
282
error= startTableScan(1);
285
while ((error= rnd_next(buf)) == HA_ERR_RECORD_DELETED) ;
286
(void) endTableScan();
297
291
/* Find the first row through the primary key */
298
(void) startIndexScan(primary_key, 0);
299
error=index_first(buf);
300
(void) endIndexScan();
292
error= startIndexScan(primary_key, 0);
295
error=index_first(buf);
296
(void) endIndexScan();
314
311
@verbatim 1,5,15,25,35,... @endverbatim
317
compute_next_insert_id(uint64_t nr,struct system_variables *variables)
314
compute_next_insert_id(uint64_t nr, drizzle_system_variables *variables)
319
316
if (variables->auto_increment_increment == 1)
320
317
return (nr+1); // optimization of the formula below
334
331
Session::next_insert_id to be greater than the explicit value.
336
333
if ((next_insert_id > 0) && (nr >= next_insert_id))
337
set_next_insert_id(compute_next_insert_id(nr, &table->in_use->variables));
334
set_next_insert_id(compute_next_insert_id(nr, &getTable()->in_use->variables));
354
351
The number X if it exists, "nr" otherwise.
357
prev_insert_id(uint64_t nr, struct system_variables *variables)
354
prev_insert_id(uint64_t nr, drizzle_system_variables *variables)
359
356
if (unlikely(nr < variables->auto_increment_offset))
452
449
uint64_t nr, nb_reserved_values;
453
450
bool append= false;
454
Session *session= table->in_use;
455
struct system_variables *variables= &session->variables;
451
Session *session= getTable()->in_use;
452
drizzle_system_variables *variables= &session->variables;
458
455
next_insert_id is a "cursor" into the reserved interval, it may go greater
464
461
for an auto increment column, not a magic value like NULL is.
465
462
same as sql_mode=NO_AUTO_VALUE_ON_ZERO */
467
if ((nr= table->next_number_field->val_int()) != 0
468
|| table->auto_increment_field_not_null)
464
if ((nr= getTable()->next_number_field->val_int()) != 0
465
|| getTable()->auto_increment_field_not_null)
471
468
Update next_insert_id if we had already generated a value in this
543
540
nr= compute_next_insert_id(nr-1, variables);
546
if (table->getShare()->next_number_keypart == 0)
543
if (getTable()->getShare()->next_number_keypart == 0)
548
545
/* We must defer the appending until "nr" has been possibly truncated */
553
if (unlikely(table->next_number_field->store((int64_t) nr, true)))
550
if (unlikely(getTable()->next_number_field->store((int64_t) nr, true)))
556
553
first test if the query was aborted due to strict mode constraints
558
if (session->killed == Session::KILL_BAD_DATA)
555
if (session->getKilled() == Session::KILL_BAD_DATA)
559
556
return HA_ERR_AUTOINC_ERANGE;
566
563
bother shifting the right bound (anyway any other value from this
567
564
interval will cause a duplicate key).
569
nr= prev_insert_id(table->next_number_field->val_int(), variables);
570
if (unlikely(table->next_number_field->store((int64_t) nr, true)))
571
nr= table->next_number_field->val_int();
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();
622
619
this statement used forced auto_increment values if there were some,
623
620
wipe them away for other statements.
625
table->in_use->auto_inc_intervals_forced.empty();
622
getTable()->in_use->auto_inc_intervals_forced.empty();
668
665
* possible resource to gain (and if there is... then there is a bug such
669
666
* that in_use should have been set.
671
if (not table || not table->in_use)
668
if (not getTable()->in_use)
674
resource_context= table->in_use->getResourceContext(engine);
671
resource_context= getTable()->in_use->getResourceContext(getEngine());
676
673
When a storage engine method is called, the transaction must
677
674
have been started, unless it's a DDL call, for which the
712
709
* @todo Make TransactionServices generic to AfterTriggerServices
715
Session *const session= table->in_use;
712
Session *const session= getTable()->in_use;
716
713
TransactionServices &transaction_services= TransactionServices::singleton();
717
transaction_services.truncateTable(session, table);
714
transaction_services.truncateTable(*session, *getTable());
832
save_record_0= table->getInsertRecord();
833
table->record[0]= buf;
834
key_info= table->key_info + active_index;
829
save_record_0= getTable()->getInsertRecord();
830
getTable()->record[0]= buf;
831
key_info= getTable()->key_info + active_index;
835
832
key_part= key_info->key_part;
836
833
key_part_end= key_part + key_info->key_parts;
837
834
for (; key_part < key_part_end; key_part++)
844
if (key_cmp_if_same(table, key, active_index, keylen))
841
if (key_cmp_if_same(getTable(), key, active_index, keylen))
846
table->status=STATUS_NOT_FOUND;
843
getTable()->status=STATUS_NOT_FOUND;
847
844
error=HA_ERR_END_OF_FILE;
850
847
/* Move back if necessary. */
853
table->record[0]= save_record_0;
850
getTable()->record[0]= save_record_0;
854
851
for (key_part= key_info->key_part; key_part < key_part_end; key_part++)
855
852
key_part->field->move_field_offset(-ptrdiff);
887
884
double Cursor::index_only_read_time(uint32_t keynr, double key_records)
889
886
uint32_t keys_per_block= (stats.block_size/2/
890
(table->key_info[keynr].key_length + ref_length) + 1);
887
(getTable()->key_info[keynr].key_length + ref_length) + 1);
891
888
return ((double) (key_records + keys_per_block-1) /
892
889
(double) keys_per_block);
918
915
This method (or an overriding one in a derived class) must check for
919
session->killed and return HA_POS_ERROR if it is not zero. This is required
916
session->getKilled() and return HA_POS_ERROR if it is not zero. This is required
920
917
for a user to be able to interrupt the calculation by killing the
921
918
connection/query.
1194
1191
key_compare_result_on_equal= ((end_key->flag == HA_READ_BEFORE_KEY) ? 1 :
1195
1192
(end_key->flag == HA_READ_AFTER_KEY) ? -1 : 0);
1197
range_key_part= table->key_info[active_index].key_part;
1194
range_key_part= getTable()->key_info[active_index].key_part;
1199
1196
if (!start_key) // Read first record
1200
result= index_first(table->getInsertRecord());
1197
result= index_first(getTable()->getInsertRecord());
1202
result= index_read_map(table->getInsertRecord(),
1199
result= index_read_map(getTable()->getInsertRecord(),
1203
1200
start_key->key,
1204
1201
start_key->keypart_map,
1205
1202
start_key->flag);
1234
1231
/* We trust that index_next_same always gives a row in range */
1235
return(index_next_same(table->getInsertRecord(),
1232
return(index_next_same(getTable()->getInsertRecord(),
1236
1233
end_range->key,
1237
1234
end_range->length));
1239
result= index_next(table->getInsertRecord());
1236
result= index_next(getTable()->getInsertRecord());
1242
1239
return(compare_key(end_range) <= 0 ? 0 : HA_ERR_END_OF_FILE);
1315
1312
* CREATE TABLE will commit the transaction containing
1318
result= transaction_services.insertRecord(session, table);
1315
result= transaction_services.insertRecord(*session, *table);
1320
1317
case SQLCOM_REPLACE:
1321
1318
case SQLCOM_REPLACE_SELECT:
1344
1341
* as the row to delete (this is the conflicting row), so
1345
1342
* we need to notify TransactionService to use that row.
1347
transaction_services.deleteRecord(session, table, true);
1344
transaction_services.deleteRecord(*session, *table, true);
1349
1346
* We set the "current" statement message to NULL. This triggers
1350
1347
* the replication services component to generate a new statement
1351
1348
* message for the inserted record which will come next.
1353
transaction_services.finalizeStatementMessage(*session->getStatementMessage(), session);
1350
transaction_services.finalizeStatementMessage(*session->getStatementMessage(), *session);
1357
1354
if (before_record == NULL)
1358
result= transaction_services.insertRecord(session, table);
1355
result= transaction_services.insertRecord(*session, *table);
1360
transaction_services.updateRecord(session, table, before_record, after_record);
1357
transaction_services.updateRecord(*session, *table, before_record, after_record);
1363
1360
case SQLCOM_INSERT:
1372
1369
if (before_record == NULL)
1373
result= transaction_services.insertRecord(session, table);
1370
result= transaction_services.insertRecord(*session, *table);
1375
transaction_services.updateRecord(session, table, before_record, after_record);
1372
transaction_services.updateRecord(*session, *table, before_record, after_record);
1378
1375
case SQLCOM_UPDATE:
1379
transaction_services.updateRecord(session, table, before_record, after_record);
1376
transaction_services.updateRecord(*session, *table, before_record, after_record);
1382
1379
case SQLCOM_DELETE:
1383
transaction_services.deleteRecord(session, table);
1380
transaction_services.deleteRecord(*session, *table);
1405
1402
if (lock_type == F_RDLCK)
1407
DRIZZLE_CURSOR_RDLOCK_START(table_share->getSchemaName(),
1408
table_share->getTableName());
1404
DRIZZLE_CURSOR_RDLOCK_START(getTable()->getShare()->getSchemaName(),
1405
getTable()->getShare()->getTableName());
1410
1407
else if (lock_type == F_WRLCK)
1412
DRIZZLE_CURSOR_WRLOCK_START(table_share->getSchemaName(),
1413
table_share->getTableName());
1409
DRIZZLE_CURSOR_WRLOCK_START(getTable()->getShare()->getSchemaName(),
1410
getTable()->getShare()->getTableName());
1415
1412
else if (lock_type == F_UNLCK)
1417
DRIZZLE_CURSOR_UNLOCK_START(table_share->getSchemaName(),
1418
table_share->getTableName());
1414
DRIZZLE_CURSOR_UNLOCK_START(getTable()->getShare()->getSchemaName(),
1415
getTable()->getShare()->getTableName());
1454
1451
int Cursor::ha_reset()
1456
1453
/* Check that we have called all proper deallocation functions */
1457
assert(! table->getShare()->all_set.none());
1458
assert(table->key_read == 0);
1454
assert(! getTable()->getShare()->all_set.none());
1455
assert(getTable()->key_read == 0);
1459
1456
/* ensure that ha_index_end / endTableScan has been called */
1460
1457
assert(inited == NONE);
1461
1458
/* Free cache used by filesort */
1462
table->free_io_cache();
1459
getTable()->free_io_cache();
1463
1460
/* reset the bitmaps to point to defaults */
1464
table->default_column_bitmaps();
1461
getTable()->default_column_bitmaps();
1465
1462
return(reset());
1476
1473
* @TODO Technically, the below two lines can be take even further out of the
1477
1474
* Cursor interface and into the fill_record() method.
1479
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
1476
if (getTable()->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
1481
table->timestamp_field->set_time();
1478
getTable()->timestamp_field->set_time();
1484
DRIZZLE_INSERT_ROW_START(table_share->getSchemaName(), table_share->getTableName());
1481
DRIZZLE_INSERT_ROW_START(getTable()->getShare()->getSchemaName(), getTable()->getShare()->getTableName());
1485
1482
setTransactionReadWrite();
1487
if (unlikely(plugin::EventObserver::beforeInsertRecord(*table, buf)))
1484
if (unlikely(plugin::EventObserver::beforeInsertRecord(*getTable(), buf)))
1489
1486
error= ER_EVENT_OBSERVER_PLUGIN;
1493
1490
error= doInsertRecord(buf);
1494
if (unlikely(plugin::EventObserver::afterInsertRecord(*table, buf, error)))
1491
if (unlikely(plugin::EventObserver::afterInsertRecord(*getTable(), buf, error)))
1496
1493
error= ER_EVENT_OBSERVER_PLUGIN;
1509
if (unlikely(log_row_for_replication(table, NULL, buf)))
1506
if (unlikely(log_row_for_replication(getTable(), NULL, buf)))
1510
1507
return HA_ERR_RBR_LOGGING_FAILED;
1521
1518
Some storage engines require that the new record is in getInsertRecord()
1522
1519
(and the old record is in getUpdateRecord()).
1524
assert(new_data == table->getInsertRecord());
1521
assert(new_data == getTable()->getInsertRecord());
1526
DRIZZLE_UPDATE_ROW_START(table_share->getSchemaName(), table_share->getTableName());
1523
DRIZZLE_UPDATE_ROW_START(getTable()->getShare()->getSchemaName(), getTable()->getShare()->getTableName());
1527
1524
setTransactionReadWrite();
1528
if (unlikely(plugin::EventObserver::beforeUpdateRecord(*table, old_data, new_data)))
1525
if (unlikely(plugin::EventObserver::beforeUpdateRecord(*getTable(), old_data, new_data)))
1530
1527
error= ER_EVENT_OBSERVER_PLUGIN;
1534
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
1531
if (getTable()->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
1536
table->timestamp_field->set_time();
1533
getTable()->timestamp_field->set_time();
1539
1536
error= doUpdateRecord(old_data, new_data);
1540
if (unlikely(plugin::EventObserver::afterUpdateRecord(*table, old_data, new_data, error)))
1537
if (unlikely(plugin::EventObserver::afterUpdateRecord(*getTable(), old_data, new_data, error)))
1542
1539
error= ER_EVENT_OBSERVER_PLUGIN;
1555
if (unlikely(log_row_for_replication(table, old_data, new_data)))
1552
if (unlikely(log_row_for_replication(getTable(), old_data, new_data)))
1556
1553
return HA_ERR_RBR_LOGGING_FAILED;
1557
TableShare *Cursor::getShare()
1559
return getTable()->getMutableShare();
1561
1562
int Cursor::deleteRecord(const unsigned char *buf)
1565
DRIZZLE_DELETE_ROW_START(table_share->getSchemaName(), table_share->getTableName());
1566
DRIZZLE_DELETE_ROW_START(getTable()->getShare()->getSchemaName(), getTable()->getShare()->getTableName());
1566
1567
setTransactionReadWrite();
1567
if (unlikely(plugin::EventObserver::beforeDeleteRecord(*table, buf)))
1568
if (unlikely(plugin::EventObserver::beforeDeleteRecord(*getTable(), buf)))
1569
1570
error= ER_EVENT_OBSERVER_PLUGIN;
1573
1574
error= doDeleteRecord(buf);
1574
if (unlikely(plugin::EventObserver::afterDeleteRecord(*table, buf, error)))
1575
if (unlikely(plugin::EventObserver::afterDeleteRecord(*getTable(), buf, error)))
1576
1577
error= ER_EVENT_OBSERVER_PLUGIN;
1584
1585
if (unlikely(error))
1587
if (unlikely(log_row_for_replication(table, buf, NULL)))
1588
if (unlikely(log_row_for_replication(getTable(), buf, NULL)))
1588
1589
return HA_ERR_RBR_LOGGING_FAILED;