23
23
Handler-calling-functions
30
#include "drizzled/my_hash.h"
26
#include "drizzled/server_includes.h"
27
#include "mysys/hash.h"
31
28
#include "drizzled/error.h"
32
29
#include "drizzled/gettext.h"
33
30
#include "drizzled/probes.h"
34
31
#include "drizzled/sql_parse.h"
35
#include "drizzled/optimizer/cost_vector.h"
32
#include "drizzled/cost_vect.h"
36
33
#include "drizzled/session.h"
37
34
#include "drizzled/sql_base.h"
38
#include "drizzled/transaction_services.h"
35
#include "drizzled/replication_services.h"
39
36
#include "drizzled/lock.h"
40
37
#include "drizzled/item/int.h"
41
38
#include "drizzled/item/empty_string.h"
39
#include "drizzled/unireg.h" // for mysql_frm_type
42
40
#include "drizzled/field/timestamp.h"
43
41
#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"
48
43
using namespace std;
44
using namespace drizzled;
46
KEY_CREATE_INFO default_key_create_info= { HA_KEY_ALG_UNDEF, 0, {NULL,0} };
48
/* number of entries in storage_engines[] */
50
/* number of storage engines (from storage_engines[]) that support 2pc */
51
uint32_t total_ha_2pc= 0;
52
/* size of savepoint storage area (see ha_init) */
53
uint32_t savepoint_alloc_size= 0;
55
const char *ha_row_type[] = {
56
"", "FIXED", "DYNAMIC", "COMPRESSED", "REDUNDANT", "COMPACT", "PAGE", "?","?","?"
59
const char *tx_isolation_names[] =
60
{ "READ-UNCOMMITTED", "READ-COMMITTED", "REPEATABLE-READ", "SERIALIZABLE",
63
TYPELIB tx_isolation_typelib= {array_elements(tx_isolation_names)-1,"",
64
tx_isolation_names, NULL};
68
Register handler error messages for use with my_error().
76
int ha_init_errors(void)
78
#define SETMSG(nr, msg) errmsgs[(nr) - HA_ERR_FIRST]= (msg)
81
/* Allocate a pointer array for the error message strings. */
82
/* Zerofill it to avoid uninitialized gaps. */
83
if (! (errmsgs= (const char**) malloc(HA_ERR_ERRORS * sizeof(char*))))
85
memset(errmsgs, 0, HA_ERR_ERRORS * sizeof(char *));
87
/* Set the dedicated error messages. */
88
SETMSG(HA_ERR_KEY_NOT_FOUND, ER(ER_KEY_NOT_FOUND));
89
SETMSG(HA_ERR_FOUND_DUPP_KEY, ER(ER_DUP_KEY));
90
SETMSG(HA_ERR_RECORD_CHANGED, "Update wich is recoverable");
91
SETMSG(HA_ERR_WRONG_INDEX, "Wrong index given to function");
92
SETMSG(HA_ERR_CRASHED, ER(ER_NOT_KEYFILE));
93
SETMSG(HA_ERR_WRONG_IN_RECORD, ER(ER_CRASHED_ON_USAGE));
94
SETMSG(HA_ERR_OUT_OF_MEM, "Table handler out of memory");
95
SETMSG(HA_ERR_NOT_A_TABLE, "Incorrect file format '%.64s'");
96
SETMSG(HA_ERR_WRONG_COMMAND, "Command not supported");
97
SETMSG(HA_ERR_OLD_FILE, ER(ER_OLD_KEYFILE));
98
SETMSG(HA_ERR_NO_ACTIVE_RECORD, "No record read in update");
99
SETMSG(HA_ERR_RECORD_DELETED, "Intern record deleted");
100
SETMSG(HA_ERR_RECORD_FILE_FULL, ER(ER_RECORD_FILE_FULL));
101
SETMSG(HA_ERR_INDEX_FILE_FULL, "No more room in index file '%.64s'");
102
SETMSG(HA_ERR_END_OF_FILE, "End in next/prev/first/last");
103
SETMSG(HA_ERR_UNSUPPORTED, ER(ER_ILLEGAL_HA));
104
SETMSG(HA_ERR_TO_BIG_ROW, "Too big row");
105
SETMSG(HA_WRONG_CREATE_OPTION, "Wrong create option");
106
SETMSG(HA_ERR_FOUND_DUPP_UNIQUE, ER(ER_DUP_UNIQUE));
107
SETMSG(HA_ERR_UNKNOWN_CHARSET, "Can't open charset");
108
SETMSG(HA_ERR_WRONG_MRG_TABLE_DEF, ER(ER_WRONG_MRG_TABLE));
109
SETMSG(HA_ERR_CRASHED_ON_REPAIR, ER(ER_CRASHED_ON_REPAIR));
110
SETMSG(HA_ERR_CRASHED_ON_USAGE, ER(ER_CRASHED_ON_USAGE));
111
SETMSG(HA_ERR_LOCK_WAIT_TIMEOUT, ER(ER_LOCK_WAIT_TIMEOUT));
112
SETMSG(HA_ERR_LOCK_TABLE_FULL, ER(ER_LOCK_TABLE_FULL));
113
SETMSG(HA_ERR_READ_ONLY_TRANSACTION, ER(ER_READ_ONLY_TRANSACTION));
114
SETMSG(HA_ERR_LOCK_DEADLOCK, ER(ER_LOCK_DEADLOCK));
115
SETMSG(HA_ERR_CANNOT_ADD_FOREIGN, ER(ER_CANNOT_ADD_FOREIGN));
116
SETMSG(HA_ERR_NO_REFERENCED_ROW, ER(ER_NO_REFERENCED_ROW_2));
117
SETMSG(HA_ERR_ROW_IS_REFERENCED, ER(ER_ROW_IS_REFERENCED_2));
118
SETMSG(HA_ERR_NO_SAVEPOINT, "No savepoint with that name");
119
SETMSG(HA_ERR_NON_UNIQUE_BLOCK_SIZE, "Non unique key block size");
120
SETMSG(HA_ERR_NO_SUCH_TABLE, "No such table: '%.64s'");
121
SETMSG(HA_ERR_TABLE_EXIST, ER(ER_TABLE_EXISTS_ERROR));
122
SETMSG(HA_ERR_NO_CONNECTION, "Could not connect to storage engine");
123
SETMSG(HA_ERR_TABLE_DEF_CHANGED, ER(ER_TABLE_DEF_CHANGED));
124
SETMSG(HA_ERR_FOREIGN_DUPLICATE_KEY, "FK constraint would lead to duplicate key");
125
SETMSG(HA_ERR_TABLE_NEEDS_UPGRADE, ER(ER_TABLE_NEEDS_UPGRADE));
126
SETMSG(HA_ERR_TABLE_READONLY, ER(ER_OPEN_AS_READONLY));
127
SETMSG(HA_ERR_AUTOINC_READ_FAILED, ER(ER_AUTOINC_READ_FAILED));
128
SETMSG(HA_ERR_AUTOINC_ERANGE, ER(ER_WARN_DATA_OUT_OF_RANGE));
130
/* Register the error messages for use with my_error(). */
131
return my_error_register(errmsgs, HA_ERR_FIRST, HA_ERR_LAST);
136
Unregister handler error messages.
143
static int ha_finish_errors(void)
145
const char **errmsgs;
147
/* Allocate a pointer array for the error message strings. */
148
if (! (errmsgs= my_error_unregister(HA_ERR_FIRST, HA_ERR_LAST)))
150
free((unsigned char*) errmsgs);
158
assert(total_ha < MAX_HA);
160
Check if there is a transaction-capable storage engine besides the
161
binary log (which is considered a transaction-capable storage engine in
164
savepoint_alloc_size+= sizeof(SAVEPOINT);
173
This should be eventualy based on the graceful shutdown flag.
174
So if flag is equal to HA_PANIC_CLOSE, the deallocate
177
if (ha_finish_errors())
185
/* ========================================================================
186
======================= TRANSACTIONS ===================================*/
189
Transaction handling in the server
190
==================================
192
In each client connection, MySQL maintains two transactional
194
- a statement transaction,
195
- a standard, also called normal transaction.
199
"Statement transaction" is a non-standard term that comes
200
from the times when MySQL supported BerkeleyDB storage engine.
202
First of all, it should be said that in BerkeleyDB auto-commit
203
mode auto-commits operations that are atomic to the storage
204
engine itself, such as a write of a record, and are too
205
high-granular to be atomic from the application perspective
206
(MySQL). One SQL statement could involve many BerkeleyDB
207
auto-committed operations and thus BerkeleyDB auto-commit was of
210
Secondly, instead of SQL standard savepoints, BerkeleyDB
211
provided the concept of "nested transactions". In a nutshell,
212
transactions could be arbitrarily nested, but when the parent
213
transaction was committed or aborted, all its child (nested)
214
transactions were handled committed or aborted as well.
215
Commit of a nested transaction, in turn, made its changes
216
visible, but not durable: it destroyed the nested transaction,
217
all its changes would become available to the parent and
218
currently active nested transactions of this parent.
220
So the mechanism of nested transactions was employed to
221
provide "all or nothing" guarantee of SQL statements
222
required by the standard.
223
A nested transaction would be created at start of each SQL
224
statement, and destroyed (committed or aborted) at statement
225
end. Such nested transaction was internally referred to as
226
a "statement transaction" and gave birth to the term.
228
<Historical note ends>
230
Since then a statement transaction is started for each statement
231
that accesses transactional tables or uses the binary log. If
232
the statement succeeds, the statement transaction is committed.
233
If the statement fails, the transaction is rolled back. Commits
234
of statement transactions are not durable -- each such
235
transaction is nested in the normal transaction, and if the
236
normal transaction is rolled back, the effects of all enclosed
237
statement transactions are undone as well. Technically,
238
a statement transaction can be viewed as a savepoint which is
239
maintained automatically in order to make effects of one
242
The normal transaction is started by the user and is ended
243
usually upon a user request as well. The normal transaction
244
encloses transactions of all statements issued between
245
its beginning and its end.
246
In autocommit mode, the normal transaction is equivalent
247
to the statement transaction.
249
Since MySQL supports PSEA (pluggable storage engine
250
architecture), more than one transactional engine can be
251
active at a time. Hence transactions, from the server
252
point of view, are always distributed. In particular,
253
transactional state is maintained independently for each
254
engine. In order to commit a transaction the two phase
255
commit protocol is employed.
257
Not all statements are executed in context of a transaction.
258
Administrative and status information statements do not modify
259
engine data, and thus do not start a statement transaction and
260
also have no effect on the normal transaction. Examples of such
261
statements are SHOW STATUS and RESET SLAVE.
263
Similarly DDL statements are not transactional,
264
and therefore a transaction is [almost] never started for a DDL
265
statement. The difference between a DDL statement and a purely
266
administrative statement though is that a DDL statement always
267
commits the current transaction before proceeding, if there is
270
At last, SQL statements that work with non-transactional
271
engines also have no effect on the transaction state of the
272
connection. Even though they are written to the binary log,
273
and the binary log is, overall, transactional, the writes
274
are done in "write-through" mode, directly to the binlog
275
file, followed with a OS cache sync, in other words,
276
bypassing the binlog undo log (translog).
277
They do not commit the current normal transaction.
278
A failure of a statement that uses non-transactional tables
279
would cause a rollback of the statement transaction, but
280
in case there no non-transactional tables are used,
281
no statement transaction is started.
286
The server stores its transaction-related data in
287
session->transaction. This structure has two members of type
288
Session_TRANS. These members correspond to the statement and
289
normal transactions respectively:
291
- session->transaction.stmt contains a list of engines
292
that are participating in the given statement
293
- session->transaction.all contains a list of engines that
294
have participated in any of the statement transactions started
295
within the context of the normal transaction.
296
Each element of the list contains a pointer to the storage
297
engine, engine-specific transactional data, and engine-specific
300
In autocommit mode session->transaction.all is empty.
301
Instead, data of session->transaction.stmt is
302
used to commit/rollback the normal transaction.
304
The list of registered engines has a few important properties:
305
- no engine is registered in the list twice
306
- engines are present in the list a reverse temporal order --
307
new participants are always added to the beginning of the list.
309
Transaction life cycle
310
----------------------
312
When a new connection is established, session->transaction
313
members are initialized to an empty state.
314
If a statement uses any tables, all affected engines
315
are registered in the statement engine list. In
316
non-autocommit mode, the same engines are registered in
317
the normal transaction list.
318
At the end of the statement, the server issues a commit
319
or a roll back for all engines in the statement list.
320
At this point transaction flags of an engine, if any, are
321
propagated from the statement list to the list of the normal
323
When commit/rollback is finished, the statement list is
324
cleared. It will be filled in again by the next statement,
325
and emptied again at the next statement's end.
327
The normal transaction is committed in a similar way
328
(by going over all engines in session->transaction.all list)
329
but at different times:
330
- upon COMMIT SQL statement is issued by the user
331
- implicitly, by the server, at the beginning of a DDL statement
332
or SET AUTOCOMMIT={0|1} statement.
334
The normal transaction can be rolled back as well:
335
- if the user has requested so, by issuing ROLLBACK SQL
337
- if one of the storage engines requested a rollback
338
by setting session->transaction_rollback_request. This may
339
happen in case, e.g., when the transaction in the engine was
340
chosen a victim of the internal deadlock resolution algorithm
341
and rolled back internally. When such a situation happens, there
342
is little the server can do and the only option is to rollback
343
transactions in all other participating engines. In this case
344
the rollback is accompanied by an error sent to the user.
346
As follows from the use cases above, the normal transaction
347
is never committed when there is an outstanding statement
348
transaction. In most cases there is no conflict, since
349
commits of the normal transaction are issued by a stand-alone
350
administrative or DDL statement, thus no outstanding statement
351
transaction of the previous statement exists. Besides,
352
all statements that manipulate with the normal transaction
353
are prohibited in stored functions and triggers, therefore
354
no conflicting situation can occur in a sub-statement either.
355
The remaining rare cases when the server explicitly has
356
to commit the statement transaction prior to committing the normal
357
one cover error-handling scenarios (see for example
360
When committing a statement or a normal transaction, the server
361
either uses the two-phase commit protocol, or issues a commit
362
in each engine independently. The two-phase commit protocol
364
- all participating engines support two-phase commit (provide
365
StorageEngine::prepare PSEA API call) and
366
- transactions in at least two engines modify data (i.e. are
369
Note that the two phase commit is used for
370
statement transactions, even though they are not durable anyway.
371
This is done to ensure logical consistency of data in a multiple-
373
For example, imagine that some day MySQL supports unique
374
constraint checks deferred till the end of statement. In such
375
case a commit in one of the engines may yield ER_DUP_KEY,
376
and MySQL should be able to gracefully abort statement
377
transactions of other participants.
379
After the normal transaction has been committed,
380
session->transaction.all list is cleared.
382
When a connection is closed, the current normal transaction, if
385
Roles and responsibilities
386
--------------------------
388
The server has no way to know that an engine participates in
389
the statement and a transaction has been started
390
in it unless the engine says so. Thus, in order to be
391
a part of a transaction, the engine must "register" itself.
392
This is done by invoking trans_register_ha() server call.
393
Normally the engine registers itself whenever handler::external_lock()
394
is called. trans_register_ha() can be invoked many times: if
395
an engine is already registered, the call does nothing.
396
In case autocommit is not set, the engine must register itself
397
twice -- both in the statement list and in the normal transaction
399
In which list to register is a parameter of trans_register_ha().
401
Note, that although the registration interface in itself is
402
fairly clear, the current usage practice often leads to undesired
403
effects. E.g. since a call to trans_register_ha() in most engines
404
is embedded into implementation of handler::external_lock(), some
405
DDL statements start a transaction (at least from the server
406
point of view) even though they are not expected to. E.g.
407
CREATE TABLE does not start a transaction, since
408
handler::external_lock() is never called during CREATE TABLE. But
409
CREATE TABLE ... SELECT does, since handler::external_lock() is
410
called for the table that is being selected from. This has no
411
practical effects currently, but must be kept in mind
414
Once an engine is registered, the server will do the rest
417
During statement execution, whenever any of data-modifying
418
PSEA API methods is used, e.g. handler::write_row() or
419
handler::update_row(), the read-write flag is raised in the
420
statement transaction for the involved engine.
421
Currently All PSEA calls are "traced", and the data can not be
422
changed in a way other than issuing a PSEA call. Important:
423
unless this invariant is preserved the server will not know that
424
a transaction in a given engine is read-write and will not
425
involve the two-phase commit protocol!
427
At the end of a statement, server call
428
ha_autocommit_or_rollback() is invoked. This call in turn
429
invokes StorageEngine::prepare() for every involved engine.
430
Prepare is followed by a call to StorageEngine::commit_one_phase()
431
If a one-phase commit will suffice, StorageEngine::prepare() is not
432
invoked and the server only calls StorageEngine::commit_one_phase().
433
At statement commit, the statement-related read-write engine
434
flag is propagated to the corresponding flag in the normal
435
transaction. When the commit is complete, the list of registered
438
Rollback is handled in a similar fashion.
440
Additional notes on DDL and the normal transaction.
441
---------------------------------------------------
443
DDLs and operations with non-transactional engines
444
do not "register" in session->transaction lists, and thus do not
445
modify the transaction state. Besides, each DDL in
446
MySQL is prefixed with an implicit normal transaction commit
447
(a call to Session::endActiveTransaction()), and thus leaves nothing
449
However, as it has been pointed out with CREATE TABLE .. SELECT,
450
some DDL statements can start a *new* transaction.
452
Behaviour of the server in this case is currently badly
454
DDL statements use a form of "semantic" logging
455
to maintain atomicity: if CREATE TABLE .. SELECT failed,
456
the newly created table is deleted.
457
In addition, some DDL statements issue interim transaction
458
commits: e.g. ALTER Table issues a commit after data is copied
459
from the original table to the internal temporary table. Other
460
statements, e.g. CREATE TABLE ... SELECT do not always commit
462
And finally there is a group of DDL statements such as
463
RENAME/DROP Table that doesn't start a new transaction
466
This diversity makes it hard to say what will happen if
467
by chance a stored function is invoked during a DDL --
468
whether any modifications it makes will be committed or not
469
is not clear. Fortunately, SQL grammar of few DDLs allows
470
invocation of a stored function.
472
A consistent behaviour is perhaps to always commit the normal
473
transaction after all DDLs, just like the statement transaction
474
is always committed at the end of all statements.
478
Register a storage engine for a transaction.
480
Every storage engine MUST call this function when it starts
481
a transaction or a statement (that is it must be called both for the
482
"beginning of transaction" and "beginning of statement").
483
Only storage engines registered for the transaction/statement
484
will know when to commit/rollback it.
487
trans_register_ha is idempotent - storage engine may register many
488
times per transaction.
491
void trans_register_ha(Session *session, bool all, StorageEngine *engine)
493
Session_TRANS *trans;
494
Ha_trx_info *ha_info;
498
trans= &session->transaction.all;
499
session->server_status|= SERVER_STATUS_IN_TRANS;
502
trans= &session->transaction.stmt;
504
ha_info= session->ha_data[engine->getSlot()].ha_info + static_cast<unsigned>(all);
506
if (ha_info->is_started())
507
return; /* already registered, return */
509
ha_info->register_ha(trans, engine);
511
trans->no_2pc|= not engine->has_2pc();
512
if (session->transaction.xid_state.xid.is_null())
513
session->transaction.xid_state.xid.set(session->query_id);
517
Check if we can skip the two-phase commit.
519
A helper function to evaluate if two-phase commit is mandatory.
520
As a side effect, propagates the read-only/read-write flags
521
of the statement transaction to its enclosing normal transaction.
523
@retval true we must run a two-phase commit. Returned
524
if we have at least two engines with read-write changes.
525
@retval false Don't need two-phase commit. Even if we have two
526
transactional engines, we can run two independent
527
commits if changes in one of the engines are read-only.
532
ha_check_and_coalesce_trx_read_only(Session *session, Ha_trx_info *ha_list,
535
/* The number of storage engines that have actual changes. */
536
unsigned rw_ha_count= 0;
537
Ha_trx_info *ha_info;
539
for (ha_info= ha_list; ha_info; ha_info= ha_info->next())
541
if (ha_info->is_trx_read_write())
546
Ha_trx_info *ha_info_all= &session->ha_data[ha_info->engine()->getSlot()].ha_info[1];
547
assert(ha_info != ha_info_all);
549
Merge read-only/read-write information about statement
550
transaction to its enclosing normal transaction. Do this
551
only if in a real transaction -- that is, if we know
552
that ha_info_all is registered in session->transaction.all.
553
Since otherwise we only clutter the normal transaction flags.
555
if (ha_info_all->is_started()) /* false if autocommit. */
556
ha_info_all->coalesce_trx_with(ha_info);
558
else if (rw_ha_count > 1)
561
It is a normal transaction, so we don't need to merge read/write
562
information up, and the need for two-phase commit has been
563
already established. Break the loop prematurely.
568
return rw_ha_count > 1;
576
1 transaction was rolled back
578
2 error during commit, data may be inconsistent
581
Since we don't support nested statement transactions in 5.0,
582
we can't commit or rollback stmt transactions while we are inside
583
stored functions or triggers. So we simply do nothing now.
584
TODO: This should be fixed in later ( >= 5.1) releases.
586
int ha_commit_trans(Session *session, bool all)
588
int error= 0, cookie= 0;
590
'all' means that this is either an explicit commit issued by
591
user, or an implicit commit issued by a DDL.
593
Session_TRANS *trans= all ? &session->transaction.all : &session->transaction.stmt;
594
bool is_real_trans= all || session->transaction.all.ha_list == 0;
595
Ha_trx_info *ha_info= trans->ha_list;
598
We must not commit the normal transaction if a statement
599
transaction is pending. Otherwise statement transaction
600
flags will not get propagated to its normal transaction's
603
assert(session->transaction.stmt.ha_list == NULL ||
604
trans == &session->transaction.stmt);
610
if (is_real_trans && wait_if_global_read_lock(session, 0, 0))
612
ha_rollback_trans(session, all);
616
must_2pc= ha_check_and_coalesce_trx_read_only(session, ha_info, all);
618
if (!trans->no_2pc && must_2pc)
620
for (; ha_info && !error; ha_info= ha_info->next())
623
StorageEngine *engine= ha_info->engine();
625
Do not call two-phase commit if this particular
626
transaction is read-only. This allows for simpler
627
implementation in engines that are always read-only.
629
if (! ha_info->is_trx_read_write())
632
Sic: we know that prepare() is not NULL since otherwise
633
trans->no_2pc would have been set.
635
if ((err= engine->prepare(session, all)))
637
my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
640
status_var_increment(session->status_var.ha_prepare_count);
644
ha_rollback_trans(session, all);
649
error=ha_commit_one_phase(session, all) ? (cookie ? 2 : 1) : 0;
652
start_waiting_global_read_lock(session);
659
This function does not care about global read lock. A caller should.
661
int ha_commit_one_phase(Session *session, bool all)
664
Session_TRANS *trans=all ? &session->transaction.all : &session->transaction.stmt;
665
bool is_real_trans=all || session->transaction.all.ha_list == 0;
666
Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
669
for (; ha_info; ha_info= ha_info_next)
672
StorageEngine *engine= ha_info->engine();
673
if ((err= engine->commit(session, all)))
675
my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
678
status_var_increment(session->status_var.ha_commit_count);
679
ha_info_next= ha_info->next();
680
ha_info->reset(); /* keep it conveniently zero-filled */
685
session->transaction.xid_state.xid.null();
688
session->variables.tx_isolation=session->session_tx_isolation;
689
session->transaction.cleanup();
696
int ha_rollback_trans(Session *session, bool all)
699
Session_TRANS *trans=all ? &session->transaction.all : &session->transaction.stmt;
700
Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
701
bool is_real_trans=all || session->transaction.all.ha_list == 0;
704
We must not rollback the normal transaction if a statement
705
transaction is pending.
707
assert(session->transaction.stmt.ha_list == NULL ||
708
trans == &session->transaction.stmt);
712
for (; ha_info; ha_info= ha_info_next)
715
StorageEngine *engine= ha_info->engine();
716
if ((err= engine->rollback(session, all)))
718
my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
721
status_var_increment(session->status_var.ha_rollback_count);
722
ha_info_next= ha_info->next();
723
ha_info->reset(); /* keep it conveniently zero-filled */
728
session->transaction.xid_state.xid.null();
731
session->variables.tx_isolation=session->session_tx_isolation;
732
session->transaction.cleanup();
736
session->transaction_rollback_request= false;
739
If a non-transactional table was updated, warn; don't warn if this is a
740
slave thread (because when a slave thread executes a ROLLBACK, it has
741
been read from the binary log, so it's 100% sure and normal to produce
742
error ER_WARNING_NOT_COMPLETE_ROLLBACK. If we sent the warning to the
743
slave SQL thread, it would not stop the thread but just be printed in
744
the error log; but we don't want users to wonder why they have this
745
message in the error log, so we don't send it.
747
if (is_real_trans && session->transaction.all.modified_non_trans_table && session->killed != Session::KILL_CONNECTION)
748
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
749
ER_WARNING_NOT_COMPLETE_ROLLBACK,
750
ER(ER_WARNING_NOT_COMPLETE_ROLLBACK));
755
This is used to commit or rollback a single statement depending on
759
Note that if the autocommit is on, then the following call inside
760
InnoDB will commit or rollback the whole transaction (= the statement). The
761
autocommit mechanism built into InnoDB is based on counting locks, but if
762
the user has used LOCK TABLES then that mechanism does not know to do the
765
int ha_autocommit_or_rollback(Session *session, int error)
767
if (session->transaction.stmt.ha_list)
771
if (ha_commit_trans(session, 0))
776
(void) ha_rollback_trans(session, 0);
777
if (session->transaction_rollback_request)
778
(void) ha_rollback(session);
781
session->variables.tx_isolation=session->session_tx_isolation;
788
return the list of XID's to a client, the same way SHOW commands do.
791
I didn't find in XA specs that an RM cannot return the same XID twice,
792
so mysql_xa_recover does not filter XID's to ensure uniqueness.
793
It can be easily fixed later, if necessary.
795
bool mysql_xa_recover(Session *session)
797
List<Item> field_list;
798
plugin::Protocol *protocol= session->protocol;
802
field_list.push_back(new Item_int("formatID", 0, MY_INT32_NUM_DECIMAL_DIGITS));
803
field_list.push_back(new Item_int("gtrid_length", 0, MY_INT32_NUM_DECIMAL_DIGITS));
804
field_list.push_back(new Item_int("bqual_length", 0, MY_INT32_NUM_DECIMAL_DIGITS));
805
field_list.push_back(new Item_empty_string("data",XIDDATASIZE));
807
if (protocol->sendFields(&field_list))
810
pthread_mutex_lock(&LOCK_xid_cache);
811
while ((xs= (XID_STATE*)hash_element(&xid_cache, i++)))
813
if (xs->xa_state==XA_PREPARED)
815
protocol->prepareForResend();
816
protocol->store((int64_t)xs->xid.formatID);
817
protocol->store((int64_t)xs->xid.gtrid_length);
818
protocol->store((int64_t)xs->xid.bqual_length);
819
protocol->store(xs->xid.data, xs->xid.gtrid_length+xs->xid.bqual_length);
820
if (protocol->write())
822
pthread_mutex_unlock(&LOCK_xid_cache);
828
pthread_mutex_unlock(&LOCK_xid_cache);
834
int ha_rollback_to_savepoint(Session *session, SAVEPOINT *sv)
837
Session_TRANS *trans= &session->transaction.all;
838
Ha_trx_info *ha_info, *ha_info_next;
842
rolling back to savepoint in all storage engines that were part of the
843
transaction when the savepoint was set
845
for (ha_info= sv->ha_list; ha_info; ha_info= ha_info->next())
848
StorageEngine *engine= ha_info->engine();
850
if ((err= engine->savepoint_rollback(session,
853
my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
856
status_var_increment(session->status_var.ha_savepoint_rollback_count);
857
trans->no_2pc|= not engine->has_2pc();
860
rolling back the transaction in all storage engines that were not part of
861
the transaction when the savepoint was set
863
for (ha_info= trans->ha_list; ha_info != sv->ha_list;
864
ha_info= ha_info_next)
867
StorageEngine *engine= ha_info->engine();
868
if ((err= engine->rollback(session, !(0))))
870
my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
873
status_var_increment(session->status_var.ha_rollback_count);
874
ha_info_next= ha_info->next();
875
ha_info->reset(); /* keep it conveniently zero-filled */
877
trans->ha_list= sv->ha_list;
883
according to the sql standard (ISO/IEC 9075-2:2003)
884
section "4.33.4 SQL-statements and transaction states",
885
SAVEPOINT is *not* transaction-initiating SQL-statement
887
int ha_savepoint(Session *session, SAVEPOINT *sv)
890
Session_TRANS *trans= &session->transaction.all;
891
Ha_trx_info *ha_info= trans->ha_list;
892
for (; ha_info; ha_info= ha_info->next())
895
StorageEngine *engine= ha_info->engine();
897
#ifdef NOT_IMPLEMENTED /*- TODO (examine this againt the original code base) */
898
if (! engine->savepoint_set)
900
my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "SAVEPOINT");
905
if ((err= engine->savepoint_set(session, (void *)(sv+1))))
907
my_error(ER_GET_ERRNO, MYF(0), err);
910
status_var_increment(session->status_var.ha_savepoint_count);
913
Remember the list of registered storage engines. All new
914
engines are prepended to the beginning of the list.
916
sv->ha_list= trans->ha_list;
920
int ha_release_savepoint(Session *session, SAVEPOINT *sv)
923
Ha_trx_info *ha_info= sv->ha_list;
925
for (; ha_info; ha_info= ha_info->next())
928
StorageEngine *engine= ha_info->engine();
929
/* Savepoint life time is enclosed into transaction life time. */
931
if ((err= engine->savepoint_release(session,
934
my_error(ER_GET_ERRNO, MYF(0), err);
53
945
/****************************************************************************
54
** General Cursor functions
946
** General handler functions
55
947
****************************************************************************/
56
Cursor::Cursor(plugin::StorageEngine &engine_arg,
60
estimation_rows_to_insert(0),
62
key_used_on_scan(MAX_KEY), active_index(MAX_KEY),
63
ref_length(sizeof(internal::my_off_t)),
66
next_insert_id(0), insert_id_for_cur_row(0)
948
handler::~handler(void)
71
950
assert(locked == false);
72
951
/* TODO: assert(inited == NONE); */
77
* @note this only used in
78
* optimizer::QuickRangeSelect::init_ror_merged_scan(bool reuse_handler) as
79
* of the writing of this comment. -Brian
81
Cursor *Cursor::clone(memory::Root *mem_root)
955
handler *handler::clone(MEM_ROOT *mem_root)
83
Cursor *new_handler= getTable()->getMutableShare()->db_type()->getCursor(*getTable());
957
handler *new_handler= get_new_handler(table->s, mem_root, table->s->db_type());
86
Allocate Cursor->ref here because otherwise ha_open will allocate it
959
Allocate handler->ref here because otherwise ha_open will allocate it
87
960
on this->table->mem_root and we will not be able to reclaim that memory
88
when the clone Cursor object is destroyed.
961
when the clone handler object is destroyed.
90
if (!(new_handler->ref= (unsigned char*) mem_root->alloc_root(ALIGN_SIZE(ref_length)*2)))
963
if (!(new_handler->ref= (unsigned char*) alloc_root(mem_root, ALIGN_SIZE(ref_length)*2)))
93
TableIdentifier identifier(getTable()->getShare()->getSchemaName(),
94
getTable()->getShare()->getTableName(),
95
getTable()->getShare()->getType());
97
if (new_handler && !new_handler->ha_open(identifier,
98
getTable()->getDBStat(),
965
if (new_handler && !new_handler->ha_open(table,
966
table->s->normalized_path.str,
99
968
HA_OPEN_IGNORE_IF_LOCKED))
100
969
return new_handler;
106
given a buffer with a key value, and a map of keyparts
107
that are present in this value, returns the length of the value
109
uint32_t Cursor::calculate_key_len(uint32_t key_position, key_part_map keypart_map_arg)
111
/* works only with key prefixes */
112
assert(((keypart_map_arg + 1) & keypart_map_arg) == 0);
114
const KeyPartInfo *key_part_found= getTable()->getShare()->getKeyInfo(key_position).key_part;
115
const KeyPartInfo *end_key_part_found= key_part_found + getTable()->getShare()->getKeyInfo(key_position).key_parts;
118
while (key_part_found < end_key_part_found && keypart_map_arg)
120
length+= key_part_found->store_length;
121
keypart_map_arg >>= 1;
127
int Cursor::startIndexScan(uint32_t idx, bool sorted)
973
int handler::ha_index_init(uint32_t idx, bool sorted)
130
976
assert(inited == NONE);
131
if (!(result= doStartIndexScan(idx, sorted)))
977
if (!(result= index_init(idx, sorted)))
137
int Cursor::endIndexScan()
983
int handler::ha_index_end()
139
985
assert(inited==INDEX);
142
return(doEndIndexScan());
145
int Cursor::startTableScan(bool scan)
991
int handler::ha_rnd_init(bool scan)
148
994
assert(inited==NONE || (inited==RND && scan));
149
inited= (result= doStartTableScan(scan)) ? NONE: RND;
995
inited= (result= rnd_init(scan)) ? NONE: RND;
154
int Cursor::endTableScan()
1000
int handler::ha_rnd_end()
156
1002
assert(inited==RND);
158
return(doEndTableScan());
161
int Cursor::ha_index_or_rnd_end()
163
return inited == INDEX ? endIndexScan() : inited == RND ? endTableScan() : 0;
166
void Cursor::ha_start_bulk_insert(ha_rows rows)
1007
int handler::ha_index_or_rnd_end()
1009
return inited == INDEX ? ha_index_end() : inited == RND ? ha_rnd_end() : 0;
1012
handler::Table_flags handler::ha_table_flags() const
1014
return cached_table_flags;
1017
void handler::ha_start_bulk_insert(ha_rows rows)
168
1019
estimation_rows_to_insert= rows;
169
1020
start_bulk_insert(rows);
172
int Cursor::ha_end_bulk_insert()
1023
int handler::ha_end_bulk_insert()
174
1025
estimation_rows_to_insert= 0;
175
1026
return end_bulk_insert();
178
const key_map *Cursor::keys_to_use_for_scanning()
1029
void handler::change_table_ptr(Table *table_arg, TableShare *share)
1035
const key_map *handler::keys_to_use_for_scanning()
180
1037
return &key_map_empty;
183
bool Cursor::has_transactions()
185
return (getTable()->getShare()->db_type()->check_flag(HTON_BIT_DOES_TRANSACTIONS));
188
void Cursor::ha_statistic_increment(uint64_t system_status_var::*offset) const
190
(getTable()->in_use->status_var.*offset)++;
193
void **Cursor::ha_data(Session *session) const
195
return session->getEngineData(getEngine());
198
bool Cursor::is_fatal_error(int error, uint32_t flags)
1040
bool handler::has_transactions()
1042
return (ha_table_flags() & HA_NO_TRANSACTIONS) == 0;
1045
void handler::ha_statistic_increment(ulong SSV::*offset) const
1047
status_var_increment(table->in_use->status_var.*offset);
1050
void **handler::ha_data(Session *session) const
1052
return session_ha_data(session, engine);
1055
Session *handler::ha_session(void) const
1057
assert(!table || !table->in_use || table->in_use == current_session);
1058
return (table && table->in_use) ? table->in_use : current_session;
1062
bool handler::is_fatal_error(int error, uint32_t flags)
201
1065
((flags & HA_CHECK_DUP_KEY) &&