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