~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/handler.cc

  • Committer: Monty Taylor
  • Date: 2009-09-22 23:50:12 UTC
  • mto: This revision was merged to the branch mainline in revision 1184.
  • Revision ID: mordred@inaugust.com-20090922235012-i0a3bs91f6krqduc
Fixed multi_malloc.h include guard.
Added include guard checking script.

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 */
19
19
 
20
20
/**
21
 
  @file Cursor.cc
 
21
  @file handler.cc
22
22
 
23
23
  Handler-calling-functions
24
24
*/
25
25
 
26
 
#include "config.h"
27
 
 
28
 
#include <fcntl.h>
29
 
 
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"
47
42
 
48
43
using namespace std;
49
 
 
50
 
namespace drizzled
51
 
{
 
44
using namespace drizzled;
 
45
 
 
46
KEY_CREATE_INFO default_key_create_info= { HA_KEY_ALG_UNDEF, 0, {NULL,0} };
 
47
 
 
48
/* number of entries in storage_engines[] */
 
49
uint32_t total_ha= 0;
 
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;
 
54
 
 
55
const char *ha_row_type[] = {
 
56
  "", "FIXED", "DYNAMIC", "COMPRESSED", "REDUNDANT", "COMPACT", "PAGE", "?","?","?"
 
57
};
 
58
 
 
59
const char *tx_isolation_names[] =
 
60
{ "READ-UNCOMMITTED", "READ-COMMITTED", "REPEATABLE-READ", "SERIALIZABLE",
 
61
  NULL};
 
62
 
 
63
TYPELIB tx_isolation_typelib= {array_elements(tx_isolation_names)-1,"",
 
64
                               tx_isolation_names, NULL};
 
65
 
 
66
 
 
67
/**
 
68
  Register handler error messages for use with my_error().
 
69
 
 
70
  @retval
 
71
    0           OK
 
72
  @retval
 
73
    !=0         Error
 
74
*/
 
75
 
 
76
int ha_init_errors(void)
 
77
{
 
78
#define SETMSG(nr, msg) errmsgs[(nr) - HA_ERR_FIRST]= (msg)
 
79
  const char    **errmsgs;
 
80
 
 
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*))))
 
84
    return 1;
 
85
  memset(errmsgs, 0, HA_ERR_ERRORS * sizeof(char *));
 
86
 
 
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));
 
129
 
 
130
  /* Register the error messages for use with my_error(). */
 
131
  return my_error_register(errmsgs, HA_ERR_FIRST, HA_ERR_LAST);
 
132
}
 
133
 
 
134
 
 
135
/**
 
136
  Unregister handler error messages.
 
137
 
 
138
  @retval
 
139
    0           OK
 
140
  @retval
 
141
    !=0         Error
 
142
*/
 
143
static int ha_finish_errors(void)
 
144
{
 
145
  const char    **errmsgs;
 
146
 
 
147
  /* Allocate a pointer array for the error message strings. */
 
148
  if (! (errmsgs= my_error_unregister(HA_ERR_FIRST, HA_ERR_LAST)))
 
149
    return 1;
 
150
  free((unsigned char*) errmsgs);
 
151
  return 0;
 
152
}
 
153
 
 
154
int ha_init()
 
155
{
 
156
  int error= 0;
 
157
 
 
158
  assert(total_ha < MAX_HA);
 
159
  /*
 
160
    Check if there is a transaction-capable storage engine besides the
 
161
    binary log (which is considered a transaction-capable storage engine in
 
162
    counting total_ha)
 
163
  */
 
164
  savepoint_alloc_size+= sizeof(SAVEPOINT);
 
165
  return error;
 
166
}
 
167
 
 
168
int ha_end()
 
169
{
 
170
  int error= 0;
 
171
 
 
172
  /*
 
173
    This should be eventualy based  on the graceful shutdown flag.
 
174
    So if flag is equal to HA_PANIC_CLOSE, the deallocate
 
175
    the errors.
 
176
  */
 
177
  if (ha_finish_errors())
 
178
    error= 1;
 
179
 
 
180
  return error;
 
181
}
 
182
 
 
183
 
 
184
 
 
185
/* ========================================================================
 
186
 ======================= TRANSACTIONS ===================================*/
 
187
 
 
188
/**
 
189
  Transaction handling in the server
 
190
  ==================================
 
191
 
 
192
  In each client connection, MySQL maintains two transactional
 
193
  states:
 
194
  - a statement transaction,
 
195
  - a standard, also called normal transaction.
 
196
 
 
197
  Historical note
 
198
  ---------------
 
199
  "Statement transaction" is a non-standard term that comes
 
200
  from the times when MySQL supported BerkeleyDB storage engine.
 
201
 
 
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
 
208
  little use to MySQL.
 
209
 
 
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.
 
219
 
 
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.
 
227
 
 
228
  <Historical note ends>
 
229
 
 
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
 
240
  statement atomic.
 
241
 
 
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.
 
248
 
 
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.
 
256
 
 
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.
 
262
 
 
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
 
268
  any.
 
269
 
 
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.
 
282
 
 
283
  Data layout
 
284
  -----------
 
285
 
 
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:
 
290
 
 
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
 
298
  transaction flags.
 
299
 
 
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.
 
303
 
 
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.
 
308
 
 
309
  Transaction life cycle
 
310
  ----------------------
 
311
 
 
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
 
322
  transaction.
 
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.
 
326
 
 
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.
 
333
 
 
334
  The normal transaction can be rolled back as well:
 
335
  - if the user has requested so, by issuing ROLLBACK SQL
 
336
  statement
 
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.
 
345
 
 
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
 
358
  ?).
 
359
 
 
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
 
363
  is used only if:
 
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
 
367
  not read-only).
 
368
 
 
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-
 
372
  engine transaction.
 
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.
 
378
 
 
379
  After the normal transaction has been committed,
 
380
  session->transaction.all list is cleared.
 
381
 
 
382
  When a connection is closed, the current normal transaction, if
 
383
  any, is rolled back.
 
384
 
 
385
  Roles and responsibilities
 
386
  --------------------------
 
387
 
 
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
 
398
  list.
 
399
  In which list to register is a parameter of trans_register_ha().
 
400
 
 
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
 
412
  nevertheless.
 
413
 
 
414
  Once an engine is registered, the server will do the rest
 
415
  of the work.
 
416
 
 
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!
 
426
 
 
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
 
436
  engines is cleared.
 
437
 
 
438
  Rollback is handled in a similar fashion.
 
439
 
 
440
  Additional notes on DDL and the normal transaction.
 
441
  ---------------------------------------------------
 
442
 
 
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
 
448
  to modify.
 
449
  However, as it has been pointed out with CREATE TABLE .. SELECT,
 
450
  some DDL statements can start a *new* transaction.
 
451
 
 
452
  Behaviour of the server in this case is currently badly
 
453
  defined.
 
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
 
461
  after itself.
 
462
  And finally there is a group of DDL statements such as
 
463
  RENAME/DROP Table that doesn't start a new transaction
 
464
  and doesn't commit.
 
465
 
 
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.
 
471
 
 
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.
 
475
*/
 
476
 
 
477
/**
 
478
  Register a storage engine for a transaction.
 
479
 
 
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.
 
485
 
 
486
  @note
 
487
    trans_register_ha is idempotent - storage engine may register many
 
488
    times per transaction.
 
489
 
 
490
*/
 
491
void trans_register_ha(Session *session, bool all, StorageEngine *engine)
 
492
{
 
493
  Session_TRANS *trans;
 
494
  Ha_trx_info *ha_info;
 
495
 
 
496
  if (all)
 
497
  {
 
498
    trans= &session->transaction.all;
 
499
    session->server_status|= SERVER_STATUS_IN_TRANS;
 
500
  }
 
501
  else
 
502
    trans= &session->transaction.stmt;
 
503
 
 
504
  ha_info= session->ha_data[engine->getSlot()].ha_info + static_cast<unsigned>(all);
 
505
 
 
506
  if (ha_info->is_started())
 
507
    return; /* already registered, return */
 
508
 
 
509
  ha_info->register_ha(trans, engine);
 
510
 
 
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);
 
514
}
 
515
 
 
516
/**
 
517
  Check if we can skip the two-phase commit.
 
518
 
 
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.
 
522
 
 
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.
 
528
*/
 
529
 
 
530
static
 
531
bool
 
532
ha_check_and_coalesce_trx_read_only(Session *session, Ha_trx_info *ha_list,
 
533
                                    bool all)
 
534
{
 
535
  /* The number of storage engines that have actual changes. */
 
536
  unsigned rw_ha_count= 0;
 
537
  Ha_trx_info *ha_info;
 
538
 
 
539
  for (ha_info= ha_list; ha_info; ha_info= ha_info->next())
 
540
  {
 
541
    if (ha_info->is_trx_read_write())
 
542
      ++rw_ha_count;
 
543
 
 
544
    if (! all)
 
545
    {
 
546
      Ha_trx_info *ha_info_all= &session->ha_data[ha_info->engine()->getSlot()].ha_info[1];
 
547
      assert(ha_info != ha_info_all);
 
548
      /*
 
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.
 
554
      */
 
555
      if (ha_info_all->is_started()) /* false if autocommit. */
 
556
        ha_info_all->coalesce_trx_with(ha_info);
 
557
    }
 
558
    else if (rw_ha_count > 1)
 
559
    {
 
560
      /*
 
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.
 
564
      */
 
565
      break;
 
566
    }
 
567
  }
 
568
  return rw_ha_count > 1;
 
569
}
 
570
 
 
571
 
 
572
/**
 
573
  @retval
 
574
    0   ok
 
575
  @retval
 
576
    1   transaction was rolled back
 
577
  @retval
 
578
    2   error during commit, data may be inconsistent
 
579
 
 
580
  @todo
 
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.
 
585
*/
 
586
int ha_commit_trans(Session *session, bool all)
 
587
{
 
588
  int error= 0, cookie= 0;
 
589
  /*
 
590
    'all' means that this is either an explicit commit issued by
 
591
    user, or an implicit commit issued by a DDL.
 
592
  */
 
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;
 
596
 
 
597
  /*
 
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
 
601
    counterpart.
 
602
  */
 
603
  assert(session->transaction.stmt.ha_list == NULL ||
 
604
              trans == &session->transaction.stmt);
 
605
 
 
606
  if (ha_info)
 
607
  {
 
608
    bool must_2pc;
 
609
 
 
610
    if (is_real_trans && wait_if_global_read_lock(session, 0, 0))
 
611
    {
 
612
      ha_rollback_trans(session, all);
 
613
      return 1;
 
614
    }
 
615
 
 
616
    must_2pc= ha_check_and_coalesce_trx_read_only(session, ha_info, all);
 
617
 
 
618
    if (!trans->no_2pc && must_2pc)
 
619
    {
 
620
      for (; ha_info && !error; ha_info= ha_info->next())
 
621
      {
 
622
        int err;
 
623
        StorageEngine *engine= ha_info->engine();
 
624
        /*
 
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.
 
628
        */
 
629
        if (! ha_info->is_trx_read_write())
 
630
          continue;
 
631
        /*
 
632
          Sic: we know that prepare() is not NULL since otherwise
 
633
          trans->no_2pc would have been set.
 
634
        */
 
635
        if ((err= engine->prepare(session, all)))
 
636
        {
 
637
          my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
 
638
          error= 1;
 
639
        }
 
640
        status_var_increment(session->status_var.ha_prepare_count);
 
641
      }
 
642
      if (error)
 
643
      {
 
644
        ha_rollback_trans(session, all);
 
645
        error= 1;
 
646
        goto end;
 
647
      }
 
648
    }
 
649
    error=ha_commit_one_phase(session, all) ? (cookie ? 2 : 1) : 0;
 
650
end:
 
651
    if (is_real_trans)
 
652
      start_waiting_global_read_lock(session);
 
653
  }
 
654
  return error;
 
655
}
 
656
 
 
657
/**
 
658
  @note
 
659
  This function does not care about global read lock. A caller should.
 
660
*/
 
661
int ha_commit_one_phase(Session *session, bool all)
 
662
{
 
663
  int error=0;
 
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;
 
667
  if (ha_info)
 
668
  {
 
669
    for (; ha_info; ha_info= ha_info_next)
 
670
    {
 
671
      int err;
 
672
      StorageEngine *engine= ha_info->engine();
 
673
      if ((err= engine->commit(session, all)))
 
674
      {
 
675
        my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
 
676
        error=1;
 
677
      }
 
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 */
 
681
    }
 
682
    trans->ha_list= 0;
 
683
    trans->no_2pc=0;
 
684
    if (is_real_trans)
 
685
      session->transaction.xid_state.xid.null();
 
686
    if (all)
 
687
    {
 
688
      session->variables.tx_isolation=session->session_tx_isolation;
 
689
      session->transaction.cleanup();
 
690
    }
 
691
  }
 
692
  return error;
 
693
}
 
694
 
 
695
 
 
696
int ha_rollback_trans(Session *session, bool all)
 
697
{
 
698
  int error=0;
 
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;
 
702
 
 
703
  /*
 
704
    We must not rollback the normal transaction if a statement
 
705
    transaction is pending.
 
706
  */
 
707
  assert(session->transaction.stmt.ha_list == NULL ||
 
708
              trans == &session->transaction.stmt);
 
709
 
 
710
  if (ha_info)
 
711
  {
 
712
    for (; ha_info; ha_info= ha_info_next)
 
713
    {
 
714
      int err;
 
715
      StorageEngine *engine= ha_info->engine();
 
716
      if ((err= engine->rollback(session, all)))
 
717
      { // cannot happen
 
718
        my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
 
719
        error=1;
 
720
      }
 
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 */
 
724
    }
 
725
    trans->ha_list= 0;
 
726
    trans->no_2pc=0;
 
727
    if (is_real_trans)
 
728
      session->transaction.xid_state.xid.null();
 
729
    if (all)
 
730
    {
 
731
      session->variables.tx_isolation=session->session_tx_isolation;
 
732
      session->transaction.cleanup();
 
733
    }
 
734
  }
 
735
  if (all)
 
736
    session->transaction_rollback_request= false;
 
737
 
 
738
  /*
 
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.
 
746
  */
 
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));
 
751
  return error;
 
752
}
 
753
 
 
754
/**
 
755
  This is used to commit or rollback a single statement depending on
 
756
  the value of error.
 
757
 
 
758
  @note
 
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
 
763
    commit.
 
764
*/
 
765
int ha_autocommit_or_rollback(Session *session, int error)
 
766
{
 
767
  if (session->transaction.stmt.ha_list)
 
768
  {
 
769
    if (!error)
 
770
    {
 
771
      if (ha_commit_trans(session, 0))
 
772
        error= 1;
 
773
    }
 
774
    else
 
775
    {
 
776
      (void) ha_rollback_trans(session, 0);
 
777
      if (session->transaction_rollback_request)
 
778
        (void) ha_rollback(session);
 
779
    }
 
780
 
 
781
    session->variables.tx_isolation=session->session_tx_isolation;
 
782
  }
 
783
 
 
784
  return error;
 
785
}
 
786
 
 
787
/**
 
788
  return the list of XID's to a client, the same way SHOW commands do.
 
789
 
 
790
  @note
 
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.
 
794
*/
 
795
bool mysql_xa_recover(Session *session)
 
796
{
 
797
  List<Item> field_list;
 
798
  plugin::Protocol *protocol= session->protocol;
 
799
  int i= 0;
 
800
  XID_STATE *xs;
 
801
 
 
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));
 
806
 
 
807
  if (protocol->sendFields(&field_list))
 
808
    return 1;
 
809
 
 
810
  pthread_mutex_lock(&LOCK_xid_cache);
 
811
  while ((xs= (XID_STATE*)hash_element(&xid_cache, i++)))
 
812
  {
 
813
    if (xs->xa_state==XA_PREPARED)
 
814
    {
 
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())
 
821
      {
 
822
        pthread_mutex_unlock(&LOCK_xid_cache);
 
823
        return 1;
 
824
      }
 
825
    }
 
826
  }
 
827
 
 
828
  pthread_mutex_unlock(&LOCK_xid_cache);
 
829
  session->my_eof();
 
830
  return 0;
 
831
}
 
832
 
 
833
 
 
834
int ha_rollback_to_savepoint(Session *session, SAVEPOINT *sv)
 
835
{
 
836
  int error= 0;
 
837
  Session_TRANS *trans= &session->transaction.all;
 
838
  Ha_trx_info *ha_info, *ha_info_next;
 
839
 
 
840
  trans->no_2pc=0;
 
841
  /*
 
842
    rolling back to savepoint in all storage engines that were part of the
 
843
    transaction when the savepoint was set
 
844
  */
 
845
  for (ha_info= sv->ha_list; ha_info; ha_info= ha_info->next())
 
846
  {
 
847
    int err;
 
848
    StorageEngine *engine= ha_info->engine();
 
849
    assert(engine);
 
850
    if ((err= engine->savepoint_rollback(session,
 
851
                                         (void *)(sv+1))))
 
852
    { // cannot happen
 
853
      my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
 
854
      error= 1;
 
855
    }
 
856
    status_var_increment(session->status_var.ha_savepoint_rollback_count);
 
857
    trans->no_2pc|= not engine->has_2pc();
 
858
  }
 
859
  /*
 
860
    rolling back the transaction in all storage engines that were not part of
 
861
    the transaction when the savepoint was set
 
862
  */
 
863
  for (ha_info= trans->ha_list; ha_info != sv->ha_list;
 
864
       ha_info= ha_info_next)
 
865
  {
 
866
    int err;
 
867
    StorageEngine *engine= ha_info->engine();
 
868
    if ((err= engine->rollback(session, !(0))))
 
869
    { // cannot happen
 
870
      my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
 
871
      error= 1;
 
872
    }
 
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 */
 
876
  }
 
877
  trans->ha_list= sv->ha_list;
 
878
  return error;
 
879
}
 
880
 
 
881
/**
 
882
  @note
 
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
 
886
*/
 
887
int ha_savepoint(Session *session, SAVEPOINT *sv)
 
888
{
 
889
  int error= 0;
 
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())
 
893
  {
 
894
    int err;
 
895
    StorageEngine *engine= ha_info->engine();
 
896
    assert(engine);
 
897
#ifdef NOT_IMPLEMENTED /*- TODO (examine this againt the original code base) */
 
898
    if (! engine->savepoint_set)
 
899
    {
 
900
      my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "SAVEPOINT");
 
901
      error= 1;
 
902
      break;
 
903
    } 
 
904
#endif
 
905
    if ((err= engine->savepoint_set(session, (void *)(sv+1))))
 
906
    { // cannot happen
 
907
      my_error(ER_GET_ERRNO, MYF(0), err);
 
908
      error= 1;
 
909
    }
 
910
    status_var_increment(session->status_var.ha_savepoint_count);
 
911
  }
 
912
  /*
 
913
    Remember the list of registered storage engines. All new
 
914
    engines are prepended to the beginning of the list.
 
915
  */
 
916
  sv->ha_list= trans->ha_list;
 
917
  return error;
 
918
}
 
919
 
 
920
int ha_release_savepoint(Session *session, SAVEPOINT *sv)
 
921
{
 
922
  int error= 0;
 
923
  Ha_trx_info *ha_info= sv->ha_list;
 
924
 
 
925
  for (; ha_info; ha_info= ha_info->next())
 
926
  {
 
927
    int err;
 
928
    StorageEngine *engine= ha_info->engine();
 
929
    /* Savepoint life time is enclosed into transaction life time. */
 
930
    assert(engine);
 
931
    if ((err= engine->savepoint_release(session,
 
932
                                        (void *)(sv+1))))
 
933
    { // cannot happen
 
934
      my_error(ER_GET_ERRNO, MYF(0), err);
 
935
      error= 1;
 
936
    }
 
937
  }
 
938
  return error;
 
939
}
 
940
 
 
941
 
 
942
 
 
943
 
52
944
 
53
945
/****************************************************************************
54
 
** General Cursor functions
 
946
** General handler functions
55
947
****************************************************************************/
56
 
Cursor::Cursor(plugin::StorageEngine &engine_arg,
57
 
               Table &arg)
58
 
  : table(arg),
59
 
    engine(engine_arg),
60
 
    estimation_rows_to_insert(0),
61
 
    ref(0),
62
 
    key_used_on_scan(MAX_KEY), active_index(MAX_KEY),
63
 
    ref_length(sizeof(internal::my_off_t)),
64
 
    inited(NONE),
65
 
    locked(false),
66
 
    next_insert_id(0), insert_id_for_cur_row(0)
67
 
{ }
68
 
 
69
 
Cursor::~Cursor(void)
 
948
handler::~handler(void)
70
949
{
71
950
  assert(locked == false);
72
951
  /* TODO: assert(inited == NONE); */
73
952
}
74
953
 
75
954
 
76
 
/*
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
80
 
 */
81
 
Cursor *Cursor::clone(memory::Root *mem_root)
 
955
handler *handler::clone(MEM_ROOT *mem_root)
82
956
{
83
 
  Cursor *new_handler= getTable()->getMutableShare()->db_type()->getCursor(*getTable());
84
 
 
 
957
  handler *new_handler= get_new_handler(table->s, mem_root, table->s->db_type());
85
958
  /*
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.
89
962
  */
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)))
91
964
    return NULL;
92
 
 
93
 
  TableIdentifier identifier(getTable()->getShare()->getSchemaName(),
94
 
                             getTable()->getShare()->getTableName(),
95
 
                             getTable()->getShare()->getType());
96
 
 
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,
 
967
                                           table->getDBStat(),
99
968
                                           HA_OPEN_IGNORE_IF_LOCKED))
100
969
    return new_handler;
101
970
  return NULL;
102
971
}
103
972
 
104
 
/*
105
 
  DESCRIPTION
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
108
 
*/
109
 
uint32_t Cursor::calculate_key_len(uint32_t key_position, key_part_map keypart_map_arg)
110
 
{
111
 
  /* works only with key prefixes */
112
 
  assert(((keypart_map_arg + 1) & keypart_map_arg) == 0);
113
 
 
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;
116
 
  uint32_t length= 0;
117
 
 
118
 
  while (key_part_found < end_key_part_found && keypart_map_arg)
119
 
  {
120
 
    length+= key_part_found->store_length;
121
 
    keypart_map_arg >>= 1;
122
 
    key_part_found++;
123
 
  }
124
 
  return length;
125
 
}
126
 
 
127
 
int Cursor::startIndexScan(uint32_t idx, bool sorted)
 
973
int handler::ha_index_init(uint32_t idx, bool sorted)
128
974
{
129
975
  int result;
130
976
  assert(inited == NONE);
131
 
  if (!(result= doStartIndexScan(idx, sorted)))
 
977
  if (!(result= index_init(idx, sorted)))
132
978
    inited=INDEX;
133
979
  end_range= NULL;
134
980
  return result;
135
981
}
136
982
 
137
 
int Cursor::endIndexScan()
 
983
int handler::ha_index_end()
138
984
{
139
985
  assert(inited==INDEX);
140
986
  inited=NONE;
141
987
  end_range= NULL;
142
 
  return(doEndIndexScan());
 
988
  return(index_end());
143
989
}
144
990
 
145
 
int Cursor::startTableScan(bool scan)
 
991
int handler::ha_rnd_init(bool scan)
146
992
{
147
993
  int result;
148
994
  assert(inited==NONE || (inited==RND && scan));
149
 
  inited= (result= doStartTableScan(scan)) ? NONE: RND;
 
995
  inited= (result= rnd_init(scan)) ? NONE: RND;
150
996
 
151
997
  return result;
152
998
}
153
999
 
154
 
int Cursor::endTableScan()
 
1000
int handler::ha_rnd_end()
155
1001
{
156
1002
  assert(inited==RND);
157
1003
  inited=NONE;
158
 
  return(doEndTableScan());
159
 
}
160
 
 
161
 
int Cursor::ha_index_or_rnd_end()
162
 
{
163
 
  return inited == INDEX ? endIndexScan() : inited == RND ? endTableScan() : 0;
164
 
}
165
 
 
166
 
void Cursor::ha_start_bulk_insert(ha_rows rows)
 
1004
  return(rnd_end());
 
1005
}
 
1006
 
 
1007
int handler::ha_index_or_rnd_end()
 
1008
{
 
1009
  return inited == INDEX ? ha_index_end() : inited == RND ? ha_rnd_end() : 0;
 
1010
}
 
1011
 
 
1012
handler::Table_flags handler::ha_table_flags() const
 
1013
{
 
1014
  return cached_table_flags;
 
1015
}
 
1016
 
 
1017
void handler::ha_start_bulk_insert(ha_rows rows)
167
1018
{
168
1019
  estimation_rows_to_insert= rows;
169
1020
  start_bulk_insert(rows);
170
1021
}
171
1022
 
172
 
int Cursor::ha_end_bulk_insert()
 
1023
int handler::ha_end_bulk_insert()
173
1024
{
174
1025
  estimation_rows_to_insert= 0;
175
1026
  return end_bulk_insert();
176
1027
}
177
1028
 
178
 
const key_map *Cursor::keys_to_use_for_scanning()
 
1029
void handler::change_table_ptr(Table *table_arg, TableShare *share)
 
1030
{
 
1031
  table= table_arg;
 
1032
  table_share= share;
 
1033
}
 
1034
 
 
1035
const key_map *handler::keys_to_use_for_scanning()
179
1036
{
180
1037
  return &key_map_empty;
181
1038
}
182
1039
 
183
 
bool Cursor::has_transactions()
184
 
{
185
 
  return (getTable()->getShare()->db_type()->check_flag(HTON_BIT_DOES_TRANSACTIONS));
186
 
}
187
 
 
188
 
void Cursor::ha_statistic_increment(uint64_t system_status_var::*offset) const
189
 
{
190
 
  (getTable()->in_use->status_var.*offset)++;
191
 
}
192
 
 
193
 
void **Cursor::ha_data(Session *session) const
194
 
{
195
 
  return session->getEngineData(getEngine());
196
 
}
197
 
 
198
 
bool Cursor::is_fatal_error(int error, uint32_t flags)
 
1040
bool handler::has_transactions()
 
1041
{
 
1042
  return (ha_table_flags() & HA_NO_TRANSACTIONS) == 0;
 
1043
}
 
1044
 
 
1045
void handler::ha_statistic_increment(ulong SSV::*offset) const
 
1046
{
 
1047
  status_var_increment(table->in_use->status_var.*offset);
 
1048
}
 
1049
 
 
1050
void **handler::ha_data(Session *session) const
 
1051
{
 
1052
  return session_ha_data(session, engine);
 
1053
}
 
1054
 
 
1055
Session *handler::ha_session(void) const
 
1056
{
 
1057
  assert(!table || !table->in_use || table->in_use == current_session);
 
1058
  return (table && table->in_use) ? table->in_use : current_session;
 
1059
}
 
1060
 
 
1061
 
 
1062
bool handler::is_fatal_error(int error, uint32_t flags)
199
1063
{
200
1064
  if (!error ||
201
1065
      ((flags & HA_CHECK_DUP_KEY) &&
206
1070
}
207
1071
 
208
1072
 
209
 
ha_rows Cursor::records() { return stats.records; }
210
 
uint64_t Cursor::tableSize() { return stats.index_file_length + stats.data_file_length; }
211
 
uint64_t Cursor::rowSize() { return getTable()->getRecordLength() + getTable()->sizeFields(); }
212
 
 
213
 
int Cursor::doOpen(const TableIdentifier &identifier, int mode, uint32_t test_if_locked)
214
 
{
215
 
  return open(identifier.getPath().c_str(), mode, test_if_locked);
216
 
}
 
1073
ha_rows handler::records() { return stats.records; }
217
1074
 
218
1075
/**
219
 
  Open database-Cursor.
 
1076
  Open database-handler.
220
1077
 
221
1078
  Try O_RDONLY if cannot open as O_RDWR
222
1079
  Don't wait for locks if not HA_OPEN_WAIT_IF_LOCKED is set
223
1080
*/
224
 
int Cursor::ha_open(const TableIdentifier &identifier,
225
 
                    int mode,
226
 
                    int test_if_locked)
 
1081
int handler::ha_open(Table *table_arg, const char *name, int mode,
 
1082
                     int test_if_locked)
227
1083
{
228
1084
  int error;
229
1085
 
230
 
  if ((error= doOpen(identifier, mode, test_if_locked)))
 
1086
  table= table_arg;
 
1087
  assert(table->s == table_share);
 
1088
  assert(alloc_root_inited(&table->mem_root));
 
1089
 
 
1090
  if ((error=open(name,mode,test_if_locked)))
231
1091
  {
232
1092
    if ((error == EACCES || error == EROFS) && mode == O_RDWR &&
233
 
        (getTable()->db_stat & HA_TRY_READ_ONLY))
 
1093
        (table->db_stat & HA_TRY_READ_ONLY))
234
1094
    {
235
 
      getTable()->db_stat|=HA_READ_ONLY;
236
 
      error= doOpen(identifier, O_RDONLY,test_if_locked);
 
1095
      table->db_stat|=HA_READ_ONLY;
 
1096
      error=open(name,O_RDONLY,test_if_locked);
237
1097
    }
238
1098
  }
239
1099
  if (error)
240
1100
  {
241
 
    errno= error;                            /* Safeguard */
 
1101
    my_errno= error;                            /* Safeguard */
242
1102
  }
243
1103
  else
244
1104
  {
245
 
    if (getTable()->getShare()->db_options_in_use & HA_OPTION_READ_ONLY_DATA)
246
 
      getTable()->db_stat|=HA_READ_ONLY;
 
1105
    if (table->s->db_options_in_use & HA_OPTION_READ_ONLY_DATA)
 
1106
      table->db_stat|=HA_READ_ONLY;
247
1107
    (void) extra(HA_EXTRA_NO_READCHECK);        // Not needed in SQL
248
1108
 
249
 
    /* ref is already allocated for us if we're called from Cursor::clone() */
250
 
    if (!ref && !(ref= (unsigned char*) getTable()->alloc_root(ALIGN_SIZE(ref_length)*2)))
 
1109
    /* ref is already allocated for us if we're called from handler::clone() */
 
1110
    if (!ref && !(ref= (unsigned char*) alloc_root(&table->mem_root,
 
1111
                                          ALIGN_SIZE(ref_length)*2)))
251
1112
    {
252
1113
      close();
253
1114
      error=HA_ERR_OUT_OF_MEM;
254
1115
    }
255
1116
    else
256
1117
      dup_ref=ref+ALIGN_SIZE(ref_length);
 
1118
    cached_table_flags= table_flags();
257
1119
  }
258
1120
  return error;
259
1121
}
260
1122
 
261
1123
/**
 
1124
  one has to use this method when to find
 
1125
  random position by record as the plain
 
1126
  position() call doesn't work for some
 
1127
  handlers for random position
 
1128
*/
 
1129
 
 
1130
int handler::rnd_pos_by_record(unsigned char *record)
 
1131
{
 
1132
  register int error;
 
1133
 
 
1134
  position(record);
 
1135
  if (inited && (error= ha_index_end()))
 
1136
    return error;
 
1137
  if ((error= ha_rnd_init(false)))
 
1138
    return error;
 
1139
 
 
1140
  return rnd_pos(record, ref);
 
1141
}
 
1142
 
 
1143
/**
262
1144
  Read first row (only) from a table.
263
1145
 
264
1146
  This is never called for InnoDB tables, as these table types
265
1147
  has the HA_STATS_RECORDS_IS_EXACT set.
266
1148
*/
267
 
int Cursor::read_first_row(unsigned char * buf, uint32_t primary_key)
 
1149
int handler::read_first_row(unsigned char * buf, uint32_t primary_key)
268
1150
{
269
1151
  register int error;
270
1152
 
271
 
  ha_statistic_increment(&system_status_var::ha_read_first_count);
 
1153
  ha_statistic_increment(&SSV::ha_read_first_count);
272
1154
 
273
1155
  /*
274
1156
    If there is very few deleted rows in the table, find the first row by
276
1158
    TODO remove the test for HA_READ_ORDER
277
1159
  */
278
1160
  if (stats.deleted < 10 || primary_key >= MAX_KEY ||
279
 
      !(getTable()->index_flags(primary_key) & HA_READ_ORDER))
 
1161
      !(index_flags(primary_key, 0, 0) & HA_READ_ORDER))
280
1162
  {
281
 
    (void) startTableScan(1);
 
1163
    (void) ha_rnd_init(1);
282
1164
    while ((error= rnd_next(buf)) == HA_ERR_RECORD_DELETED) ;
283
 
    (void) endTableScan();
 
1165
    (void) ha_rnd_end();
284
1166
  }
285
1167
  else
286
1168
  {
287
1169
    /* Find the first row through the primary key */
288
 
    (void) startIndexScan(primary_key, 0);
 
1170
    (void) ha_index_init(primary_key, 0);
289
1171
    error=index_first(buf);
290
 
    (void) endIndexScan();
 
1172
    (void) ha_index_end();
291
1173
  }
292
1174
  return error;
293
1175
}
304
1186
  @verbatim 1,5,15,25,35,... @endverbatim
305
1187
*/
306
1188
inline uint64_t
307
 
compute_next_insert_id(uint64_t nr, drizzle_system_variables *variables)
 
1189
compute_next_insert_id(uint64_t nr,struct system_variables *variables)
308
1190
{
309
1191
  if (variables->auto_increment_increment == 1)
310
1192
    return (nr+1); // optimization of the formula below
316
1198
}
317
1199
 
318
1200
 
319
 
void Cursor::adjust_next_insert_id_after_explicit_value(uint64_t nr)
 
1201
void handler::adjust_next_insert_id_after_explicit_value(uint64_t nr)
320
1202
{
321
1203
  /*
322
1204
    If we have set Session::next_insert_id previously and plan to insert an
324
1206
    Session::next_insert_id to be greater than the explicit value.
325
1207
  */
326
1208
  if ((next_insert_id > 0) && (nr >= next_insert_id))
327
 
    set_next_insert_id(compute_next_insert_id(nr, &getTable()->in_use->variables));
 
1209
    set_next_insert_id(compute_next_insert_id(nr, &table->in_use->variables));
328
1210
}
329
1211
 
330
1212
 
344
1226
    The number X if it exists, "nr" otherwise.
345
1227
*/
346
1228
inline uint64_t
347
 
prev_insert_id(uint64_t nr, drizzle_system_variables *variables)
 
1229
prev_insert_id(uint64_t nr, struct system_variables *variables)
348
1230
{
349
1231
  if (unlikely(nr < variables->auto_increment_offset))
350
1232
  {
390
1272
    reserved for us.
391
1273
 
392
1274
  - In both cases, for the following rows we use those reserved values without
393
 
    calling the Cursor again (we just progress in the interval, computing
 
1275
    calling the handler again (we just progress in the interval, computing
394
1276
    each new value from the previous one). Until we have exhausted them, then
395
1277
    we either take the next provided interval or call get_auto_increment()
396
1278
    again to reserve a new interval.
437
1319
#define AUTO_INC_DEFAULT_NB_MAX_BITS 16
438
1320
#define AUTO_INC_DEFAULT_NB_MAX ((1 << AUTO_INC_DEFAULT_NB_MAX_BITS) - 1)
439
1321
 
440
 
int Cursor::update_auto_increment()
 
1322
int handler::update_auto_increment()
441
1323
{
442
1324
  uint64_t nr, nb_reserved_values;
443
1325
  bool append= false;
444
 
  Session *session= getTable()->in_use;
445
 
  drizzle_system_variables *variables= &session->variables;
 
1326
  Session *session= table->in_use;
 
1327
  struct system_variables *variables= &session->variables;
446
1328
 
447
1329
  /*
448
1330
    next_insert_id is a "cursor" into the reserved interval, it may go greater
454
1336
     for an auto increment column, not a magic value like NULL is.
455
1337
     same as sql_mode=NO_AUTO_VALUE_ON_ZERO */
456
1338
 
457
 
  if ((nr= getTable()->next_number_field->val_int()) != 0
458
 
      || getTable()->auto_increment_field_not_null)
 
1339
  if ((nr= table->next_number_field->val_int()) != 0
 
1340
      || table->auto_increment_field_not_null)
459
1341
  {
460
1342
    /*
461
1343
      Update next_insert_id if we had already generated a value in this
482
1364
    else
483
1365
    {
484
1366
      /*
485
 
        Cursor::estimation_rows_to_insert was set by
486
 
        Cursor::ha_start_bulk_insert(); if 0 it means "unknown".
 
1367
        handler::estimation_rows_to_insert was set by
 
1368
        handler::ha_start_bulk_insert(); if 0 it means "unknown".
487
1369
      */
488
1370
      uint32_t nb_already_reserved_intervals=
489
1371
        session->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements();
533
1415
      nr= compute_next_insert_id(nr-1, variables);
534
1416
    }
535
1417
 
536
 
    if (getTable()->getShare()->next_number_keypart == 0)
 
1418
    if (table->s->next_number_keypart == 0)
537
1419
    {
538
1420
      /* We must defer the appending until "nr" has been possibly truncated */
539
1421
      append= true;
540
1422
    }
541
1423
  }
542
1424
 
543
 
  if (unlikely(getTable()->next_number_field->store((int64_t) nr, true)))
 
1425
  if (unlikely(table->next_number_field->store((int64_t) nr, true)))
544
1426
  {
545
1427
    /*
546
1428
      first test if the query was aborted due to strict mode constraints
547
1429
    */
548
 
    if (session->getKilled() == Session::KILL_BAD_DATA)
 
1430
    if (session->killed == Session::KILL_BAD_DATA)
549
1431
      return HA_ERR_AUTOINC_ERANGE;
550
1432
 
551
1433
    /*
556
1438
      bother shifting the right bound (anyway any other value from this
557
1439
      interval will cause a duplicate key).
558
1440
    */
559
 
    nr= prev_insert_id(getTable()->next_number_field->val_int(), variables);
560
 
    if (unlikely(getTable()->next_number_field->store((int64_t) nr, true)))
561
 
      nr= getTable()->next_number_field->val_int();
 
1441
    nr= prev_insert_id(table->next_number_field->val_int(), variables);
 
1442
    if (unlikely(table->next_number_field->store((int64_t) nr, true)))
 
1443
      nr= table->next_number_field->val_int();
562
1444
  }
563
1445
  if (append)
564
1446
  {
585
1467
 
586
1468
 
587
1469
/**
588
 
  Reserves an interval of auto_increment values from the Cursor.
 
1470
  Reserves an interval of auto_increment values from the handler.
589
1471
 
590
1472
  offset and increment means that we want values to be of the form
591
1473
  offset + N * increment, where N>=0 is integer.
596
1478
  @param offset
597
1479
  @param increment
598
1480
  @param nb_desired_values   how many values we want
599
 
  @param first_value         (OUT) the first value reserved by the Cursor
600
 
  @param nb_reserved_values  (OUT) how many values the Cursor reserved
 
1481
  @param first_value         (OUT) the first value reserved by the handler
 
1482
  @param nb_reserved_values  (OUT) how many values the handler reserved
601
1483
*/
602
 
 
603
 
void Cursor::ha_release_auto_increment()
 
1484
void handler::get_auto_increment(uint64_t ,
 
1485
                                 uint64_t ,
 
1486
                                 uint64_t ,
 
1487
                                 uint64_t *first_value,
 
1488
                                 uint64_t *nb_reserved_values)
 
1489
{
 
1490
  uint64_t nr;
 
1491
  int error;
 
1492
 
 
1493
  (void) extra(HA_EXTRA_KEYREAD);
 
1494
  table->mark_columns_used_by_index_no_reset(table->s->next_number_index);
 
1495
  index_init(table->s->next_number_index, 1);
 
1496
  if (table->s->next_number_keypart == 0)
 
1497
  {                                             // Autoincrement at key-start
 
1498
    error=index_last(table->record[1]);
 
1499
    /*
 
1500
      MySQL implicitely assumes such method does locking (as MySQL decides to
 
1501
      use nr+increment without checking again with the handler, in
 
1502
      handler::update_auto_increment()), so reserves to infinite.
 
1503
    */
 
1504
    *nb_reserved_values= UINT64_MAX;
 
1505
  }
 
1506
  else
 
1507
  {
 
1508
    unsigned char key[MAX_KEY_LENGTH];
 
1509
    key_copy(key, table->record[0],
 
1510
             table->key_info + table->s->next_number_index,
 
1511
             table->s->next_number_key_offset);
 
1512
    error= index_read_map(table->record[1], key,
 
1513
                          make_prev_keypart_map(table->s->next_number_keypart),
 
1514
                          HA_READ_PREFIX_LAST);
 
1515
    /*
 
1516
      MySQL needs to call us for next row: assume we are inserting ("a",null)
 
1517
      here, we return 3, and next this statement will want to insert
 
1518
      ("b",null): there is no reason why ("b",3+1) would be the good row to
 
1519
      insert: maybe it already exists, maybe 3+1 is too large...
 
1520
    */
 
1521
    *nb_reserved_values= 1;
 
1522
  }
 
1523
 
 
1524
  if (error)
 
1525
    nr=1;
 
1526
  else
 
1527
    nr= ((uint64_t) table->next_number_field->
 
1528
         val_int_offset(table->s->rec_buff_length)+1);
 
1529
  index_end();
 
1530
  (void) extra(HA_EXTRA_NO_KEYREAD);
 
1531
  *first_value= nr;
 
1532
}
 
1533
 
 
1534
 
 
1535
void handler::ha_release_auto_increment()
604
1536
{
605
1537
  release_auto_increment();
606
1538
  insert_id_for_cur_row= 0;
612
1544
      this statement used forced auto_increment values if there were some,
613
1545
      wipe them away for other statements.
614
1546
    */
615
 
    getTable()->in_use->auto_inc_intervals_forced.empty();
616
 
  }
617
 
}
618
 
 
619
 
void Cursor::drop_table(const char *)
 
1547
    table->in_use->auto_inc_intervals_forced.empty();
 
1548
  }
 
1549
}
 
1550
 
 
1551
 
 
1552
void handler::print_keydup_error(uint32_t key_nr, const char *msg)
 
1553
{
 
1554
  /* Write the duplicated key in the error message */
 
1555
  char key[MAX_KEY_LENGTH];
 
1556
  String str(key,sizeof(key),system_charset_info);
 
1557
 
 
1558
  if (key_nr == MAX_KEY)
 
1559
  {
 
1560
    /* Key is unknown */
 
1561
    str.copy("", 0, system_charset_info);
 
1562
    my_printf_error(ER_DUP_ENTRY, msg, MYF(0), str.c_ptr(), "*UNKNOWN*");
 
1563
  }
 
1564
  else
 
1565
  {
 
1566
    /* Table is opened and defined at this point */
 
1567
    key_unpack(&str,table,(uint32_t) key_nr);
 
1568
    uint32_t max_length=DRIZZLE_ERRMSG_SIZE-(uint32_t) strlen(msg);
 
1569
    if (str.length() >= max_length)
 
1570
    {
 
1571
      str.length(max_length-4);
 
1572
      str.append(STRING_WITH_LEN("..."));
 
1573
    }
 
1574
    my_printf_error(ER_DUP_ENTRY, msg,
 
1575
                    MYF(0), str.c_ptr(), table->key_info[key_nr].name);
 
1576
  }
 
1577
}
 
1578
 
 
1579
 
 
1580
/**
 
1581
  Print error that we got from handler function.
 
1582
 
 
1583
  @note
 
1584
    In case of delete table it's only safe to use the following parts of
 
1585
    the 'table' structure:
 
1586
    - table->s->path
 
1587
    - table->alias
 
1588
*/
 
1589
void handler::print_error(int error, myf errflag)
 
1590
{
 
1591
  int textno=ER_GET_ERRNO;
 
1592
  switch (error) {
 
1593
  case EACCES:
 
1594
    textno=ER_OPEN_AS_READONLY;
 
1595
    break;
 
1596
  case EAGAIN:
 
1597
    textno=ER_FILE_USED;
 
1598
    break;
 
1599
  case ENOENT:
 
1600
    textno=ER_FILE_NOT_FOUND;
 
1601
    break;
 
1602
  case HA_ERR_KEY_NOT_FOUND:
 
1603
  case HA_ERR_NO_ACTIVE_RECORD:
 
1604
  case HA_ERR_END_OF_FILE:
 
1605
    textno=ER_KEY_NOT_FOUND;
 
1606
    break;
 
1607
  case HA_ERR_WRONG_MRG_TABLE_DEF:
 
1608
    textno=ER_WRONG_MRG_TABLE;
 
1609
    break;
 
1610
  case HA_ERR_FOUND_DUPP_KEY:
 
1611
  {
 
1612
    uint32_t key_nr=get_dup_key(error);
 
1613
    if ((int) key_nr >= 0)
 
1614
    {
 
1615
      print_keydup_error(key_nr, ER(ER_DUP_ENTRY_WITH_KEY_NAME));
 
1616
      return;
 
1617
    }
 
1618
    textno=ER_DUP_KEY;
 
1619
    break;
 
1620
  }
 
1621
  case HA_ERR_FOREIGN_DUPLICATE_KEY:
 
1622
  {
 
1623
    uint32_t key_nr= get_dup_key(error);
 
1624
    if ((int) key_nr >= 0)
 
1625
    {
 
1626
      uint32_t max_length;
 
1627
      /* Write the key in the error message */
 
1628
      char key[MAX_KEY_LENGTH];
 
1629
      String str(key,sizeof(key),system_charset_info);
 
1630
      /* Table is opened and defined at this point */
 
1631
      key_unpack(&str,table,(uint32_t) key_nr);
 
1632
      max_length= (DRIZZLE_ERRMSG_SIZE-
 
1633
                   (uint32_t) strlen(ER(ER_FOREIGN_DUPLICATE_KEY)));
 
1634
      if (str.length() >= max_length)
 
1635
      {
 
1636
        str.length(max_length-4);
 
1637
        str.append(STRING_WITH_LEN("..."));
 
1638
      }
 
1639
      my_error(ER_FOREIGN_DUPLICATE_KEY, MYF(0), table_share->table_name.str,
 
1640
        str.c_ptr(), key_nr+1);
 
1641
      return;
 
1642
    }
 
1643
    textno= ER_DUP_KEY;
 
1644
    break;
 
1645
  }
 
1646
  case HA_ERR_FOUND_DUPP_UNIQUE:
 
1647
    textno=ER_DUP_UNIQUE;
 
1648
    break;
 
1649
  case HA_ERR_RECORD_CHANGED:
 
1650
    textno=ER_CHECKREAD;
 
1651
    break;
 
1652
  case HA_ERR_CRASHED:
 
1653
    textno=ER_NOT_KEYFILE;
 
1654
    break;
 
1655
  case HA_ERR_WRONG_IN_RECORD:
 
1656
    textno= ER_CRASHED_ON_USAGE;
 
1657
    break;
 
1658
  case HA_ERR_CRASHED_ON_USAGE:
 
1659
    textno=ER_CRASHED_ON_USAGE;
 
1660
    break;
 
1661
  case HA_ERR_NOT_A_TABLE:
 
1662
    textno= error;
 
1663
    break;
 
1664
  case HA_ERR_CRASHED_ON_REPAIR:
 
1665
    textno=ER_CRASHED_ON_REPAIR;
 
1666
    break;
 
1667
  case HA_ERR_OUT_OF_MEM:
 
1668
    textno=ER_OUT_OF_RESOURCES;
 
1669
    break;
 
1670
  case HA_ERR_WRONG_COMMAND:
 
1671
    textno=ER_ILLEGAL_HA;
 
1672
    break;
 
1673
  case HA_ERR_OLD_FILE:
 
1674
    textno=ER_OLD_KEYFILE;
 
1675
    break;
 
1676
  case HA_ERR_UNSUPPORTED:
 
1677
    textno=ER_UNSUPPORTED_EXTENSION;
 
1678
    break;
 
1679
  case HA_ERR_RECORD_FILE_FULL:
 
1680
  case HA_ERR_INDEX_FILE_FULL:
 
1681
    textno=ER_RECORD_FILE_FULL;
 
1682
    break;
 
1683
  case HA_ERR_LOCK_WAIT_TIMEOUT:
 
1684
    textno=ER_LOCK_WAIT_TIMEOUT;
 
1685
    break;
 
1686
  case HA_ERR_LOCK_TABLE_FULL:
 
1687
    textno=ER_LOCK_TABLE_FULL;
 
1688
    break;
 
1689
  case HA_ERR_LOCK_DEADLOCK:
 
1690
    textno=ER_LOCK_DEADLOCK;
 
1691
    break;
 
1692
  case HA_ERR_READ_ONLY_TRANSACTION:
 
1693
    textno=ER_READ_ONLY_TRANSACTION;
 
1694
    break;
 
1695
  case HA_ERR_CANNOT_ADD_FOREIGN:
 
1696
    textno=ER_CANNOT_ADD_FOREIGN;
 
1697
    break;
 
1698
  case HA_ERR_ROW_IS_REFERENCED:
 
1699
  {
 
1700
    String str;
 
1701
    get_error_message(error, &str);
 
1702
    my_error(ER_ROW_IS_REFERENCED_2, MYF(0), str.c_ptr_safe());
 
1703
    return;
 
1704
  }
 
1705
  case HA_ERR_NO_REFERENCED_ROW:
 
1706
  {
 
1707
    String str;
 
1708
    get_error_message(error, &str);
 
1709
    my_error(ER_NO_REFERENCED_ROW_2, MYF(0), str.c_ptr_safe());
 
1710
    return;
 
1711
  }
 
1712
  case HA_ERR_TABLE_DEF_CHANGED:
 
1713
    textno=ER_TABLE_DEF_CHANGED;
 
1714
    break;
 
1715
  case HA_ERR_NO_SUCH_TABLE:
 
1716
    my_error(ER_NO_SUCH_TABLE, MYF(0), table_share->db.str,
 
1717
             table_share->table_name.str);
 
1718
    return;
 
1719
  case HA_ERR_RBR_LOGGING_FAILED:
 
1720
    textno= ER_BINLOG_ROW_LOGGING_FAILED;
 
1721
    break;
 
1722
  case HA_ERR_DROP_INDEX_FK:
 
1723
  {
 
1724
    const char *ptr= "???";
 
1725
    uint32_t key_nr= get_dup_key(error);
 
1726
    if ((int) key_nr >= 0)
 
1727
      ptr= table->key_info[key_nr].name;
 
1728
    my_error(ER_DROP_INDEX_FK, MYF(0), ptr);
 
1729
    return;
 
1730
  }
 
1731
  case HA_ERR_TABLE_NEEDS_UPGRADE:
 
1732
    textno=ER_TABLE_NEEDS_UPGRADE;
 
1733
    break;
 
1734
  case HA_ERR_TABLE_READONLY:
 
1735
    textno= ER_OPEN_AS_READONLY;
 
1736
    break;
 
1737
  case HA_ERR_AUTOINC_READ_FAILED:
 
1738
    textno= ER_AUTOINC_READ_FAILED;
 
1739
    break;
 
1740
  case HA_ERR_AUTOINC_ERANGE:
 
1741
    textno= ER_WARN_DATA_OUT_OF_RANGE;
 
1742
    break;
 
1743
  case HA_ERR_LOCK_OR_ACTIVE_TRANSACTION:
 
1744
    my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
 
1745
               ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
 
1746
    return;
 
1747
  default:
 
1748
    {
 
1749
      /* The error was "unknown" to this function.
 
1750
         Ask handler if it has got a message for this error */
 
1751
      bool temporary= false;
 
1752
      String str;
 
1753
      temporary= get_error_message(error, &str);
 
1754
      if (!str.is_empty())
 
1755
      {
 
1756
        const char* engine_name= engine->getName().c_str();
 
1757
        if (temporary)
 
1758
          my_error(ER_GET_TEMPORARY_ERRMSG, MYF(0), error, str.ptr(),
 
1759
                   engine_name);
 
1760
        else
 
1761
          my_error(ER_GET_ERRMSG, MYF(0), error, str.ptr(), engine_name);
 
1762
      }
 
1763
      else
 
1764
      {
 
1765
              my_error(ER_GET_ERRNO,errflag,error);
 
1766
      }
 
1767
      return;
 
1768
    }
 
1769
  }
 
1770
  my_error(textno, errflag, table_share->table_name.str, error);
 
1771
}
 
1772
 
 
1773
 
 
1774
/**
 
1775
  Return an error message specific to this handler.
 
1776
 
 
1777
  @param error  error code previously returned by handler
 
1778
  @param buf    pointer to String where to add error message
 
1779
 
 
1780
  @return
 
1781
    Returns true if this is a temporary error
 
1782
*/
 
1783
bool handler::get_error_message(int , String* )
 
1784
{
 
1785
  return false;
 
1786
}
 
1787
 
 
1788
 
 
1789
/* Code left, but Drizzle has no legacy yet (while MySQL did) */
 
1790
int handler::check_old_types()
 
1791
{
 
1792
  return 0;
 
1793
}
 
1794
 
 
1795
/**
 
1796
  @return
 
1797
    key if error because of duplicated keys
 
1798
*/
 
1799
uint32_t handler::get_dup_key(int error)
 
1800
{
 
1801
  table->file->errkey  = (uint32_t) -1;
 
1802
  if (error == HA_ERR_FOUND_DUPP_KEY || error == HA_ERR_FOREIGN_DUPLICATE_KEY ||
 
1803
      error == HA_ERR_FOUND_DUPP_UNIQUE ||
 
1804
      error == HA_ERR_DROP_INDEX_FK)
 
1805
    info(HA_STATUS_ERRKEY | HA_STATUS_NO_LOCK);
 
1806
  return(table->file->errkey);
 
1807
}
 
1808
 
 
1809
void handler::drop_table(const char *name)
620
1810
{
621
1811
  close();
 
1812
  engine->deleteTable(ha_session(), name);
622
1813
}
623
1814
 
624
1815
 
637
1828
  @retval
638
1829
    HA_ADMIN_NOT_IMPLEMENTED
639
1830
*/
640
 
int Cursor::ha_check(Session *, HA_CHECK_OPT *)
 
1831
int handler::ha_check(Session *, HA_CHECK_OPT *)
641
1832
{
642
1833
  return HA_ADMIN_OK;
643
1834
}
649
1840
 
650
1841
inline
651
1842
void
652
 
Cursor::setTransactionReadWrite()
 
1843
handler::mark_trx_read_write()
653
1844
{
654
 
  ResourceContext *resource_context;
655
 
 
656
 
  /*
657
 
   * If the cursor has not context for execution then there should be no
658
 
   * possible resource to gain (and if there is... then there is a bug such
659
 
   * that in_use should have been set.
660
 
 */
661
 
  if (not getTable()->in_use)
662
 
    return;
663
 
 
664
 
  resource_context= getTable()->in_use->getResourceContext(getEngine());
 
1845
  Ha_trx_info *ha_info= &ha_session()->ha_data[engine->getSlot()].ha_info[0];
665
1846
  /*
666
1847
    When a storage engine method is called, the transaction must
667
1848
    have been started, unless it's a DDL call, for which the
670
1851
    Unfortunately here we can't know know for sure if the engine
671
1852
    has registered the transaction or not, so we must check.
672
1853
  */
673
 
  if (resource_context->isStarted())
 
1854
  if (ha_info->is_started())
674
1855
  {
675
 
    resource_context->markModifiedData();
 
1856
    /*
 
1857
      table_share can be NULL in ha_delete_table(). See implementation
 
1858
      of standalone function ha_delete_table() in sql_base.cc.
 
1859
    */
 
1860
//    if (table_share == NULL || table_share->tmp_table == NO_TMP_TABLE)
 
1861
      ha_info->set_trx_read_write();
676
1862
  }
677
1863
}
678
1864
 
 
1865
/**
 
1866
  Bulk update row: public interface.
 
1867
 
 
1868
  @sa handler::bulk_update_row()
 
1869
*/
 
1870
 
 
1871
int
 
1872
handler::ha_bulk_update_row(const unsigned char *old_data, unsigned char *new_data,
 
1873
                            uint32_t *dup_key_found)
 
1874
{
 
1875
  mark_trx_read_write();
 
1876
 
 
1877
  return bulk_update_row(old_data, new_data, dup_key_found);
 
1878
}
 
1879
 
679
1880
 
680
1881
/**
681
1882
  Delete all rows: public interface.
682
1883
 
683
 
  @sa Cursor::delete_all_rows()
684
 
 
685
 
  @note
686
 
 
687
 
  This is now equalivalent to TRUNCATE TABLE.
 
1884
  @sa handler::delete_all_rows()
688
1885
*/
689
1886
 
690
1887
int
691
 
Cursor::ha_delete_all_rows()
 
1888
handler::ha_delete_all_rows()
692
1889
{
693
 
  setTransactionReadWrite();
694
 
 
695
 
  int result= delete_all_rows();
696
 
 
697
 
  if (result == 0)
698
 
  {
699
 
    /** 
700
 
     * Trigger post-truncate notification to plugins... 
701
 
     *
702
 
     * @todo Make TransactionServices generic to AfterTriggerServices
703
 
     * or similar...
704
 
     */
705
 
    Session *const session= getTable()->in_use;
706
 
    TransactionServices &transaction_services= TransactionServices::singleton();
707
 
    transaction_services.truncateTable(session, getTable());
708
 
  }
709
 
 
710
 
  return result;
 
1890
  mark_trx_read_write();
 
1891
 
 
1892
  return delete_all_rows();
711
1893
}
712
1894
 
713
1895
 
714
1896
/**
715
1897
  Reset auto increment: public interface.
716
1898
 
717
 
  @sa Cursor::reset_auto_increment()
 
1899
  @sa handler::reset_auto_increment()
718
1900
*/
719
1901
 
720
1902
int
721
 
Cursor::ha_reset_auto_increment(uint64_t value)
 
1903
handler::ha_reset_auto_increment(uint64_t value)
722
1904
{
723
 
  setTransactionReadWrite();
 
1905
  mark_trx_read_write();
724
1906
 
725
1907
  return reset_auto_increment(value);
726
1908
}
727
1909
 
728
1910
 
729
1911
/**
 
1912
  Optimize table: public interface.
 
1913
 
 
1914
  @sa handler::optimize()
 
1915
*/
 
1916
 
 
1917
int
 
1918
handler::ha_optimize(Session* session, HA_CHECK_OPT* check_opt)
 
1919
{
 
1920
  mark_trx_read_write();
 
1921
 
 
1922
  return optimize(session, check_opt);
 
1923
}
 
1924
 
 
1925
 
 
1926
/**
730
1927
  Analyze table: public interface.
731
1928
 
732
 
  @sa Cursor::analyze()
 
1929
  @sa handler::analyze()
733
1930
*/
734
1931
 
735
1932
int
736
 
Cursor::ha_analyze(Session* session, HA_CHECK_OPT*)
 
1933
handler::ha_analyze(Session* session, HA_CHECK_OPT* check_opt)
737
1934
{
738
 
  setTransactionReadWrite();
 
1935
  mark_trx_read_write();
739
1936
 
740
 
  return analyze(session);
 
1937
  return analyze(session, check_opt);
741
1938
}
742
1939
 
743
1940
/**
744
1941
  Disable indexes: public interface.
745
1942
 
746
 
  @sa Cursor::disable_indexes()
 
1943
  @sa handler::disable_indexes()
747
1944
*/
748
1945
 
749
1946
int
750
 
Cursor::ha_disable_indexes(uint32_t mode)
 
1947
handler::ha_disable_indexes(uint32_t mode)
751
1948
{
752
 
  setTransactionReadWrite();
 
1949
  mark_trx_read_write();
753
1950
 
754
1951
  return disable_indexes(mode);
755
1952
}
758
1955
/**
759
1956
  Enable indexes: public interface.
760
1957
 
761
 
  @sa Cursor::enable_indexes()
 
1958
  @sa handler::enable_indexes()
762
1959
*/
763
1960
 
764
1961
int
765
 
Cursor::ha_enable_indexes(uint32_t mode)
 
1962
handler::ha_enable_indexes(uint32_t mode)
766
1963
{
767
 
  setTransactionReadWrite();
 
1964
  mark_trx_read_write();
768
1965
 
769
1966
  return enable_indexes(mode);
770
1967
}
773
1970
/**
774
1971
  Discard or import tablespace: public interface.
775
1972
 
776
 
  @sa Cursor::discard_or_import_tablespace()
 
1973
  @sa handler::discard_or_import_tablespace()
777
1974
*/
778
1975
 
779
1976
int
780
 
Cursor::ha_discard_or_import_tablespace(bool discard)
 
1977
handler::ha_discard_or_import_tablespace(bool discard)
781
1978
{
782
 
  setTransactionReadWrite();
 
1979
  mark_trx_read_write();
783
1980
 
784
1981
  return discard_or_import_tablespace(discard);
785
1982
}
787
1984
/**
788
1985
  Drop table in the engine: public interface.
789
1986
 
790
 
  @sa Cursor::drop_table()
 
1987
  @sa handler::drop_table()
791
1988
*/
792
1989
 
793
1990
void
794
 
Cursor::closeMarkForDelete(const char *name)
 
1991
handler::ha_drop_table(const char *name)
795
1992
{
796
 
  setTransactionReadWrite();
 
1993
  mark_trx_read_write();
797
1994
 
798
1995
  return drop_table(name);
799
1996
}
800
1997
 
801
 
int Cursor::index_next_same(unsigned char *buf, const unsigned char *key, uint32_t keylen)
 
1998
/**
 
1999
  Tell the storage engine that it is allowed to "disable transaction" in the
 
2000
  handler. It is a hint that ACID is not required - it is used in NDB for
 
2001
  ALTER Table, for example, when data are copied to temporary table.
 
2002
  A storage engine may treat this hint any way it likes. NDB for example
 
2003
  starts to commit every now and then automatically.
 
2004
  This hint can be safely ignored.
 
2005
*/
 
2006
int ha_enable_transaction(Session *session, bool on)
 
2007
{
 
2008
  int error= 0;
 
2009
 
 
2010
  if ((session->transaction.on= on))
 
2011
  {
 
2012
    /*
 
2013
      Now all storage engines should have transaction handling enabled.
 
2014
      But some may have it enabled all the time - "disabling" transactions
 
2015
      is an optimization hint that storage engine is free to ignore.
 
2016
      So, let's commit an open transaction (if any) now.
 
2017
    */
 
2018
    if (!(error= ha_commit_trans(session, 0)))
 
2019
      if (! session->endTransaction(COMMIT))
 
2020
        error= 1;
 
2021
 
 
2022
  }
 
2023
  return error;
 
2024
}
 
2025
 
 
2026
int handler::index_next_same(unsigned char *buf, const unsigned char *key, uint32_t keylen)
802
2027
{
803
2028
  int error;
804
2029
  if (!(error=index_next(buf)))
805
2030
  {
806
 
    ptrdiff_t ptrdiff= buf - getTable()->getInsertRecord();
 
2031
    ptrdiff_t ptrdiff= buf - table->record[0];
807
2032
    unsigned char *save_record_0= NULL;
808
 
    KeyInfo *key_info= NULL;
809
 
    KeyPartInfo *key_part;
810
 
    KeyPartInfo *key_part_end= NULL;
 
2033
    KEY *key_info= NULL;
 
2034
    KEY_PART_INFO *key_part;
 
2035
    KEY_PART_INFO *key_part_end= NULL;
811
2036
 
812
2037
    /*
813
 
      key_cmp_if_same() compares table->getInsertRecord() against 'key'.
814
 
      In parts it uses table->getInsertRecord() directly, in parts it uses
815
 
      field objects with their local pointers into table->getInsertRecord().
816
 
      If 'buf' is distinct from table->getInsertRecord(), we need to move
817
 
      all record references. This is table->getInsertRecord() itself and
 
2038
      key_cmp_if_same() compares table->record[0] against 'key'.
 
2039
      In parts it uses table->record[0] directly, in parts it uses
 
2040
      field objects with their local pointers into table->record[0].
 
2041
      If 'buf' is distinct from table->record[0], we need to move
 
2042
      all record references. This is table->record[0] itself and
818
2043
      the field pointers of the fields used in this key.
819
2044
    */
820
2045
    if (ptrdiff)
821
2046
    {
822
 
      save_record_0= getTable()->getInsertRecord();
823
 
      getTable()->record[0]= buf;
824
 
      key_info= getTable()->key_info + active_index;
 
2047
      save_record_0= table->record[0];
 
2048
      table->record[0]= buf;
 
2049
      key_info= table->key_info + active_index;
825
2050
      key_part= key_info->key_part;
826
2051
      key_part_end= key_part + key_info->key_parts;
827
2052
      for (; key_part < key_part_end; key_part++)
831
2056
      }
832
2057
    }
833
2058
 
834
 
    if (key_cmp_if_same(getTable(), key, active_index, keylen))
 
2059
    if (key_cmp_if_same(table, key, active_index, keylen))
835
2060
    {
836
 
      getTable()->status=STATUS_NOT_FOUND;
 
2061
      table->status=STATUS_NOT_FOUND;
837
2062
      error=HA_ERR_END_OF_FILE;
838
2063
    }
839
2064
 
840
2065
    /* Move back if necessary. */
841
2066
    if (ptrdiff)
842
2067
    {
843
 
      getTable()->record[0]= save_record_0;
 
2068
      table->record[0]= save_record_0;
844
2069
      for (key_part= key_info->key_part; key_part < key_part_end; key_part++)
845
2070
        key_part->field->move_field_offset(-ptrdiff);
846
2071
    }
850
2075
 
851
2076
 
852
2077
/****************************************************************************
853
 
** Some general functions that isn't in the Cursor class
 
2078
** Some general functions that isn't in the handler class
854
2079
****************************************************************************/
855
2080
 
 
2081
 
 
2082
void st_ha_check_opt::init()
 
2083
{
 
2084
  flags= 0; 
 
2085
  use_frm= false;
 
2086
}
 
2087
 
856
2088
/**
857
2089
  Calculate cost of 'index only' scan for given index and number of records
858
2090
 
862
2094
  @note
863
2095
    It is assumed that we will read trough the whole key range and that all
864
2096
    key blocks are half full (normally things are much better). It is also
865
 
    assumed that each time we read the next key from the index, the Cursor
 
2097
    assumed that each time we read the next key from the index, the handler
866
2098
    performs a random seek, thus the cost is proportional to the number of
867
2099
    blocks read.
868
2100
 
869
2101
  @todo
870
 
    Consider joining this function and Cursor::read_time() into one
871
 
    Cursor::read_time(keynr, records, ranges, bool index_only) function.
 
2102
    Consider joining this function and handler::read_time() into one
 
2103
    handler::read_time(keynr, records, ranges, bool index_only) function.
872
2104
 
873
2105
  @return
874
2106
    Estimated cost of 'index only' scan
875
2107
*/
876
2108
 
877
 
double Cursor::index_only_read_time(uint32_t keynr, double key_records)
 
2109
double handler::index_only_read_time(uint32_t keynr, double key_records)
878
2110
{
879
2111
  uint32_t keys_per_block= (stats.block_size/2/
880
 
                        (getTable()->key_info[keynr].key_length + ref_length) + 1);
 
2112
                        (table->key_info[keynr].key_length + ref_length) + 1);
881
2113
  return ((double) (key_records + keys_per_block-1) /
882
2114
          (double) keys_per_block);
883
2115
}
906
2138
 
907
2139
  @note
908
2140
    This method (or an overriding one in a derived class) must check for
909
 
    session->getKilled() and return HA_POS_ERROR if it is not zero. This is required
 
2141
    session->killed and return HA_POS_ERROR if it is not zero. This is required
910
2142
    for a user to be able to interrupt the calculation by killing the
911
2143
    connection/query.
912
2144
 
919
2151
*/
920
2152
 
921
2153
ha_rows
922
 
Cursor::multi_range_read_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
 
2154
handler::multi_range_read_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
923
2155
                                     void *seq_init_param,
924
2156
                                     uint32_t ,
925
 
                                     uint32_t *bufsz, uint32_t *flags, optimizer::CostVector *cost)
 
2157
                                     uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
926
2158
{
927
2159
  KEY_MULTI_RANGE range;
928
2160
  range_seq_t seq_it;
929
2161
  ha_rows rows, total_rows= 0;
930
2162
  uint32_t n_ranges=0;
 
2163
  Session *session= current_session;
931
2164
 
932
2165
  /* Default MRR implementation doesn't need buffer */
933
2166
  *bufsz= 0;
935
2168
  seq_it= seq->init(seq_init_param, n_ranges, *flags);
936
2169
  while (!seq->next(seq_it, &range))
937
2170
  {
 
2171
    if (unlikely(session->killed != 0))
 
2172
      return HA_POS_ERROR;
 
2173
 
938
2174
    n_ranges++;
939
2175
    key_range *min_endp, *max_endp;
940
2176
    {
961
2197
    /* The following calculation is the same as in multi_range_read_info(): */
962
2198
    *flags |= HA_MRR_USE_DEFAULT_IMPL;
963
2199
    cost->zero();
964
 
    cost->setAvgIOCost(1); /* assume random seeks */
 
2200
    cost->avg_io_cost= 1; /* assume random seeks */
965
2201
    if ((*flags & HA_MRR_INDEX_ONLY) && total_rows > 2)
966
 
      cost->setIOCount(index_only_read_time(keyno, (uint32_t)total_rows));
 
2202
      cost->io_count= index_only_read_time(keyno, (uint32_t)total_rows);
967
2203
    else
968
 
      cost->setIOCount(read_time(keyno, n_ranges, total_rows));
969
 
    cost->setCpuCost((double) total_rows / TIME_FOR_COMPARE + 0.01);
 
2204
      cost->io_count= read_time(keyno, n_ranges, total_rows);
 
2205
    cost->cpu_cost= (double) total_rows / TIME_FOR_COMPARE + 0.01;
970
2206
  }
971
2207
  return total_rows;
972
2208
}
1006
2242
    other Error or can't perform the requested scan
1007
2243
*/
1008
2244
 
1009
 
int Cursor::multi_range_read_info(uint32_t keyno, uint32_t n_ranges, uint32_t n_rows,
1010
 
                                   uint32_t *bufsz, uint32_t *flags, optimizer::CostVector *cost)
 
2245
int handler::multi_range_read_info(uint32_t keyno, uint32_t n_ranges, uint32_t n_rows,
 
2246
                                   uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
1011
2247
{
1012
2248
  *bufsz= 0; /* Default implementation doesn't need a buffer */
1013
2249
 
1014
2250
  *flags |= HA_MRR_USE_DEFAULT_IMPL;
1015
2251
 
1016
2252
  cost->zero();
1017
 
  cost->setAvgIOCost(1); /* assume random seeks */
 
2253
  cost->avg_io_cost= 1; /* assume random seeks */
1018
2254
 
1019
2255
  /* Produce the same cost as non-MRR code does */
1020
2256
  if (*flags & HA_MRR_INDEX_ONLY)
1021
 
    cost->setIOCount(index_only_read_time(keyno, n_rows));
 
2257
    cost->io_count= index_only_read_time(keyno, n_rows);
1022
2258
  else
1023
 
    cost->setIOCount(read_time(keyno, n_ranges, n_rows));
 
2259
    cost->io_count= read_time(keyno, n_ranges, n_rows);
1024
2260
  return 0;
1025
2261
}
1026
2262
 
1044
2280
  @param buf             INOUT: memory buffer to be used
1045
2281
 
1046
2282
  @note
1047
 
    One must have called doStartIndexScan() before calling this function. Several
 
2283
    One must have called index_init() before calling this function. Several
1048
2284
    multi_range_read_init() calls may be made in course of one query.
1049
2285
 
1050
2286
    Until WL#2623 is done (see its text, section 3.2), the following will
1051
2287
    also hold:
1052
2288
    The caller will guarantee that if "seq->init == mrr_ranges_array_init"
1053
2289
    then seq_init_param is an array of n_ranges KEY_MULTI_RANGE structures.
1054
 
    This property will only be used by NDB Cursor until WL#2623 is done.
 
2290
    This property will only be used by NDB handler until WL#2623 is done.
1055
2291
 
1056
2292
    Buffer memory management is done according to the following scenario:
1057
2293
    The caller allocates the buffer and provides it to the callee by filling
1059
2295
    The callee consumes all or some fraction of the provided buffer space, and
1060
2296
    sets the HANDLER_BUFFER members accordingly.
1061
2297
    The callee may use the buffer memory until the next multi_range_read_init()
1062
 
    call is made, all records have been read, or until doEndIndexScan() call is
 
2298
    call is made, all records have been read, or until index_end() call is
1063
2299
    made, whichever comes first.
1064
2300
 
1065
2301
  @retval 0  OK
1067
2303
*/
1068
2304
 
1069
2305
int
1070
 
Cursor::multi_range_read_init(RANGE_SEQ_IF *seq_funcs, void *seq_init_param,
1071
 
                               uint32_t n_ranges, uint32_t mode)
 
2306
handler::multi_range_read_init(RANGE_SEQ_IF *seq_funcs, void *seq_init_param,
 
2307
                               uint32_t n_ranges, uint32_t mode,
 
2308
                               HANDLER_BUFFER *)
1072
2309
{
1073
2310
  mrr_iter= seq_funcs->init(seq_init_param, n_ranges, mode);
1074
2311
  mrr_funcs= *seq_funcs;
1075
2312
  mrr_is_output_sorted= test(mode & HA_MRR_SORTED);
1076
2313
  mrr_have_range= false;
1077
 
 
1078
2314
  return 0;
1079
2315
}
1080
2316
 
1092
2328
  @retval other  Error code
1093
2329
*/
1094
2330
 
1095
 
int Cursor::multi_range_read_next(char **range_info)
 
2331
int handler::multi_range_read_next(char **range_info)
1096
2332
{
1097
2333
  int result= 0;
1098
2334
  int range_res= 0;
1099
2335
 
1100
 
  if (not mrr_have_range)
 
2336
  if (!mrr_have_range)
1101
2337
  {
1102
2338
    mrr_have_range= true;
1103
2339
    goto start;
1146
2382
}
1147
2383
 
1148
2384
 
 
2385
/**
 
2386
  Get cost of reading nrows table records in a "disk sweep"
 
2387
 
 
2388
  A disk sweep read is a sequence of handler->rnd_pos(rowid) calls that made
 
2389
  for an ordered sequence of rowids.
 
2390
 
 
2391
  We assume hard disk IO. The read is performed as follows:
 
2392
 
 
2393
   1. The disk head is moved to the needed cylinder
 
2394
   2. The controller waits for the plate to rotate
 
2395
   3. The data is transferred
 
2396
 
 
2397
  Time to do #3 is insignificant compared to #2+#1.
 
2398
 
 
2399
  Time to move the disk head is proportional to head travel distance.
 
2400
 
 
2401
  Time to wait for the plate to rotate depends on whether the disk head
 
2402
  was moved or not.
 
2403
 
 
2404
  If disk head wasn't moved, the wait time is proportional to distance
 
2405
  between the previous block and the block we're reading.
 
2406
 
 
2407
  If the head was moved, we don't know how much we'll need to wait for the
 
2408
  plate to rotate. We assume the wait time to be a variate with a mean of
 
2409
  0.5 of full rotation time.
 
2410
 
 
2411
  Our cost units are "random disk seeks". The cost of random disk seek is
 
2412
  actually not a constant, it depends one range of cylinders we're going
 
2413
  to access. We make it constant by introducing a fuzzy concept of "typical
 
2414
  datafile length" (it's fuzzy as it's hard to tell whether it should
 
2415
  include index file, temp.tables etc). Then random seek cost is:
 
2416
 
 
2417
    1 = half_rotation_cost + move_cost * 1/3 * typical_data_file_length
 
2418
 
 
2419
  We define half_rotation_cost as DISK_SEEK_BASE_COST=0.9.
 
2420
 
 
2421
  @param table             Table to be accessed
 
2422
  @param nrows             Number of rows to retrieve
 
2423
  @param interrupted       true <=> Assume that the disk sweep will be
 
2424
                           interrupted by other disk IO. false - otherwise.
 
2425
  @param cost         OUT  The cost.
 
2426
*/
 
2427
 
 
2428
void get_sweep_read_cost(Table *table, ha_rows nrows, bool interrupted,
 
2429
                         COST_VECT *cost)
 
2430
{
 
2431
  cost->zero();
 
2432
  if (table->file->primary_key_is_clustered())
 
2433
  {
 
2434
    cost->io_count= table->file->read_time(table->s->primary_key,
 
2435
                                           (uint32_t) nrows, nrows);
 
2436
  }
 
2437
  else
 
2438
  {
 
2439
    double n_blocks=
 
2440
      ceil(uint64_t2double(table->file->stats.data_file_length) / IO_SIZE);
 
2441
    double busy_blocks=
 
2442
      n_blocks * (1.0 - pow(1.0 - 1.0/n_blocks, rows2double(nrows)));
 
2443
    if (busy_blocks < 1.0)
 
2444
      busy_blocks= 1.0;
 
2445
 
 
2446
    cost->io_count= busy_blocks;
 
2447
 
 
2448
    if (!interrupted)
 
2449
    {
 
2450
      /* Assume reading is done in one 'sweep' */
 
2451
      cost->avg_io_cost= (DISK_SEEK_BASE_COST +
 
2452
                          DISK_SEEK_PROP_COST*n_blocks/busy_blocks);
 
2453
    }
 
2454
  }
 
2455
}
 
2456
 
 
2457
 
1149
2458
/* **************************************************************************
1150
2459
 * DS-MRR implementation ends
1151
2460
 ***************************************************************************/
1159
2468
  @param sorted         Set to 1 if result should be sorted per key
1160
2469
 
1161
2470
  @note
1162
 
    Record is read into table->getInsertRecord()
 
2471
    Record is read into table->record[0]
1163
2472
 
1164
2473
  @retval
1165
2474
    0                   Found row
1168
2477
  @retval
1169
2478
    \#                  Error code
1170
2479
*/
1171
 
int Cursor::read_range_first(const key_range *start_key,
1172
 
                             const key_range *end_key,
1173
 
                             bool eq_range_arg,
1174
 
                             bool )
 
2480
int handler::read_range_first(const key_range *start_key,
 
2481
                              const key_range *end_key,
 
2482
                              bool eq_range_arg,
 
2483
                              bool )
1175
2484
{
1176
2485
  int result;
1177
2486
 
1184
2493
    key_compare_result_on_equal= ((end_key->flag == HA_READ_BEFORE_KEY) ? 1 :
1185
2494
                                  (end_key->flag == HA_READ_AFTER_KEY) ? -1 : 0);
1186
2495
  }
1187
 
  range_key_part= getTable()->key_info[active_index].key_part;
 
2496
  range_key_part= table->key_info[active_index].key_part;
1188
2497
 
1189
2498
  if (!start_key)                       // Read first record
1190
 
    result= index_first(getTable()->getInsertRecord());
 
2499
    result= index_first(table->record[0]);
1191
2500
  else
1192
 
    result= index_read_map(getTable()->getInsertRecord(),
 
2501
    result= index_read_map(table->record[0],
1193
2502
                           start_key->key,
1194
2503
                           start_key->keypart_map,
1195
2504
                           start_key->flag);
1206
2515
  Read next row between two endpoints.
1207
2516
 
1208
2517
  @note
1209
 
    Record is read into table->getInsertRecord()
 
2518
    Record is read into table->record[0]
1210
2519
 
1211
2520
  @retval
1212
2521
    0                   Found row
1215
2524
  @retval
1216
2525
    \#                  Error code
1217
2526
*/
1218
 
int Cursor::read_range_next()
 
2527
int handler::read_range_next()
1219
2528
{
1220
2529
  int result;
1221
2530
 
1222
2531
  if (eq_range)
1223
2532
  {
1224
2533
    /* We trust that index_next_same always gives a row in range */
1225
 
    return(index_next_same(getTable()->getInsertRecord(),
 
2534
    return(index_next_same(table->record[0],
1226
2535
                                end_range->key,
1227
2536
                                end_range->length));
1228
2537
  }
1229
 
  result= index_next(getTable()->getInsertRecord());
 
2538
  result= index_next(table->record[0]);
1230
2539
  if (result)
1231
2540
    return result;
1232
2541
  return(compare_key(end_range) <= 0 ? 0 : HA_ERR_END_OF_FILE);
1248
2557
    - -1  : Key is less than range
1249
2558
    - 1   : Key is larger than range
1250
2559
*/
1251
 
int Cursor::compare_key(key_range *range)
 
2560
int handler::compare_key(key_range *range)
1252
2561
{
1253
2562
  int cmp;
1254
 
  if (not range)
 
2563
  if (!range || in_range_check_pushed_down)
1255
2564
    return 0;                                   // No max range
1256
2565
  cmp= key_cmp(range_key_part, range->key, range->length);
1257
2566
  if (!cmp)
1259
2568
  return cmp;
1260
2569
}
1261
2570
 
1262
 
int Cursor::index_read_idx_map(unsigned char * buf, uint32_t index,
 
2571
 
 
2572
/*
 
2573
  Same as compare_key() but doesn't check have in_range_check_pushed_down.
 
2574
  This is used by index condition pushdown implementation.
 
2575
*/
 
2576
 
 
2577
int handler::compare_key2(key_range *range)
 
2578
{
 
2579
  int cmp;
 
2580
  if (!range)
 
2581
    return 0;                                   // no max range
 
2582
  cmp= key_cmp(range_key_part, range->key, range->length);
 
2583
  if (!cmp)
 
2584
    cmp= key_compare_result_on_equal;
 
2585
  return cmp;
 
2586
}
 
2587
 
 
2588
int handler::index_read_idx_map(unsigned char * buf, uint32_t index,
1263
2589
                                const unsigned char * key,
1264
2590
                                key_part_map keypart_map,
1265
2591
                                enum ha_rkey_function find_flag)
1266
2592
{
1267
2593
  int error, error1;
1268
 
  error= doStartIndexScan(index, 0);
 
2594
  error= index_init(index, 0);
1269
2595
  if (!error)
1270
2596
  {
1271
2597
    error= index_read_map(buf, key, keypart_map, find_flag);
1272
 
    error1= doEndIndexScan();
 
2598
    error1= index_end();
1273
2599
  }
1274
2600
  return error ?  error : error1;
1275
2601
}
1276
2602
 
 
2603
static bool stat_print(Session *session, const char *type, uint32_t type_len,
 
2604
                       const char *file, uint32_t file_len,
 
2605
                       const char *status, uint32_t status_len)
 
2606
{
 
2607
  plugin::Protocol *protocol= session->protocol;
 
2608
  protocol->prepareForResend();
 
2609
  protocol->store(type, type_len);
 
2610
  protocol->store(file, file_len);
 
2611
  protocol->store(status, status_len);
 
2612
  if (protocol->write())
 
2613
    return true;
 
2614
  return false;
 
2615
}
 
2616
 
 
2617
bool ha_show_status(Session *session, StorageEngine *engine, enum ha_stat_type stat)
 
2618
{
 
2619
  List<Item> field_list;
 
2620
  plugin::Protocol *protocol= session->protocol;
 
2621
  bool result;
 
2622
 
 
2623
  field_list.push_back(new Item_empty_string("Type",10));
 
2624
  field_list.push_back(new Item_empty_string("Name",FN_REFLEN));
 
2625
  field_list.push_back(new Item_empty_string("Status",10));
 
2626
 
 
2627
  if (protocol->sendFields(&field_list))
 
2628
    return true;
 
2629
 
 
2630
  result= engine->show_status(session, stat_print, stat) ? 1 : 0;
 
2631
 
 
2632
  if (!result)
 
2633
    session->my_eof();
 
2634
  return result;
 
2635
}
 
2636
 
 
2637
 
1277
2638
/**
1278
2639
  Check if the conditions for row-based binlogging is correct for the table.
1279
2640
 
1280
2641
  A row in the given table should be replicated if:
 
2642
  - Row-based replication is enabled in the current thread
 
2643
  - The binlog is enabled
1281
2644
  - It is not a temporary table
 
2645
  - The binary log is open
 
2646
  - The database the table resides in shall be binlogged (binlog_*_db rules)
 
2647
  - table is not mysql.event
1282
2648
*/
1283
2649
 
1284
2650
static bool log_row_for_replication(Table* table,
1285
 
                                    const unsigned char *before_record,
1286
 
                                    const unsigned char *after_record)
 
2651
                           const unsigned char *before_record,
 
2652
                           const unsigned char *after_record)
1287
2653
{
1288
 
  TransactionServices &transaction_services= TransactionServices::singleton();
 
2654
  ReplicationServices &replication_services= ReplicationServices::singleton();
1289
2655
  Session *const session= table->in_use;
1290
2656
 
1291
 
  if (table->getShare()->getType() || not transaction_services.shouldConstructMessages())
1292
 
    return false;
1293
 
 
1294
 
  bool result= false;
1295
 
 
1296
2657
  switch (session->lex->sql_command)
1297
2658
  {
1298
 
  case SQLCOM_CREATE_TABLE:
1299
 
    /*
1300
 
     * We are in a CREATE TABLE ... SELECT statement
1301
 
     * and the kernel has already created the table
1302
 
     * and put a CreateTableStatement in the active
1303
 
     * Transaction message.  Here, we add a new InsertRecord
1304
 
     * to a new Transaction message (because the above
1305
 
     * CREATE TABLE will commit the transaction containing
1306
 
     * it).
1307
 
     */
1308
 
    result= transaction_services.insertRecord(session, table);
1309
 
    break;
1310
2659
  case SQLCOM_REPLACE:
 
2660
  case SQLCOM_INSERT:
1311
2661
  case SQLCOM_REPLACE_SELECT:
1312
 
    /*
1313
 
     * This is a total hack because of the code that is
1314
 
     * in write_record() in sql_insert.cc. During
1315
 
     * a REPLACE statement, a call to insertRecord() is
1316
 
     * called.  If it fails, then a call to deleteRecord()
1317
 
     * is called, followed by a repeat of the original
1318
 
     * call to insertRecord().  So, log_row_for_replication
1319
 
     * could be called multiple times for a REPLACE
1320
 
     * statement.  The below looks at the values of before_record
1321
 
     * and after_record to determine which call to this
1322
 
     * function is for the delete or the insert, since NULL
1323
 
     * is passed for after_record for the delete and NULL is
1324
 
     * passed for before_record for the insert...
1325
 
     *
1326
 
     * In addition, there is an optimization that allows an
1327
 
     * engine to convert the above delete + insert into an
1328
 
     * update, so we must also check for this case below...
1329
 
     */
1330
 
    if (after_record == NULL)
1331
 
    {
1332
 
      /*
1333
 
       * The storage engine is passed the record in table->record[1]
1334
 
       * as the row to delete (this is the conflicting row), so
1335
 
       * we need to notify TransactionService to use that row.
1336
 
       */
1337
 
      transaction_services.deleteRecord(session, table, true);
1338
 
      /* 
1339
 
       * We set the "current" statement message to NULL.  This triggers
1340
 
       * the replication services component to generate a new statement
1341
 
       * message for the inserted record which will come next.
1342
 
       */
1343
 
      transaction_services.finalizeStatementMessage(*session->getStatementMessage(), session);
1344
 
    }
1345
 
    else
1346
 
    {
1347
 
      if (before_record == NULL)
1348
 
        result= transaction_services.insertRecord(session, table);
1349
 
      else
1350
 
        transaction_services.updateRecord(session, table, before_record, after_record);
1351
 
    }
1352
 
    break;
1353
 
  case SQLCOM_INSERT:
1354
2662
  case SQLCOM_INSERT_SELECT:
1355
 
  case SQLCOM_LOAD:
1356
 
    /*
1357
 
     * The else block below represents an 
1358
 
     * INSERT ... ON DUPLICATE KEY UPDATE that
1359
 
     * has hit a key conflict and actually done
1360
 
     * an update.
1361
 
     */
1362
 
    if (before_record == NULL)
1363
 
      result= transaction_services.insertRecord(session, table);
1364
 
    else
1365
 
      transaction_services.updateRecord(session, table, before_record, after_record);
 
2663
  case SQLCOM_CREATE_TABLE:
 
2664
    replication_services.insertRecord(session, table);
1366
2665
    break;
1367
2666
 
1368
2667
  case SQLCOM_UPDATE:
1369
 
    transaction_services.updateRecord(session, table, before_record, after_record);
 
2668
    replication_services.updateRecord(session, table, before_record, after_record);
1370
2669
    break;
1371
2670
 
1372
2671
  case SQLCOM_DELETE:
1373
 
    transaction_services.deleteRecord(session, table);
 
2672
    replication_services.deleteRecord(session, table);
1374
2673
    break;
 
2674
 
 
2675
    /*
 
2676
      For everything else we ignore the event (since it just involves a temp table)
 
2677
    */
1375
2678
  default:
1376
2679
    break;
1377
2680
  }
1378
2681
 
1379
 
  return result;
 
2682
  return false; //error;
1380
2683
}
1381
2684
 
1382
 
int Cursor::ha_external_lock(Session *session, int lock_type)
 
2685
int handler::ha_external_lock(Session *session, int lock_type)
1383
2686
{
1384
2687
  /*
1385
2688
    Whether this is lock or unlock, this should be true, and is to verify that
1388
2691
  */
1389
2692
  assert(next_insert_id == 0);
1390
2693
 
1391
 
  if (DRIZZLE_CURSOR_RDLOCK_START_ENABLED() ||
1392
 
      DRIZZLE_CURSOR_WRLOCK_START_ENABLED() ||
1393
 
      DRIZZLE_CURSOR_UNLOCK_START_ENABLED())
1394
 
  {
1395
 
    if (lock_type == F_RDLCK)
1396
 
    {
1397
 
      DRIZZLE_CURSOR_RDLOCK_START(getTable()->getShare()->getSchemaName(),
1398
 
                                  getTable()->getShare()->getTableName());
1399
 
    }
1400
 
    else if (lock_type == F_WRLCK)
1401
 
    {
1402
 
      DRIZZLE_CURSOR_WRLOCK_START(getTable()->getShare()->getSchemaName(),
1403
 
                                  getTable()->getShare()->getTableName());
1404
 
    }
1405
 
    else if (lock_type == F_UNLCK)
1406
 
    {
1407
 
      DRIZZLE_CURSOR_UNLOCK_START(getTable()->getShare()->getSchemaName(),
1408
 
                                  getTable()->getShare()->getTableName());
1409
 
    }
1410
 
  }
1411
 
 
1412
2694
  /*
1413
2695
    We cache the table flags if the locking succeeded. Otherwise, we
1414
2696
    keep them as they were when they were fetched in ha_open().
1415
2697
  */
 
2698
  DRIZZLE_EXTERNAL_LOCK(lock_type);
1416
2699
 
1417
2700
  int error= external_lock(session, lock_type);
1418
 
 
1419
 
  if (DRIZZLE_CURSOR_RDLOCK_DONE_ENABLED() ||
1420
 
      DRIZZLE_CURSOR_WRLOCK_DONE_ENABLED() ||
1421
 
      DRIZZLE_CURSOR_UNLOCK_DONE_ENABLED())
1422
 
  {
1423
 
    if (lock_type == F_RDLCK)
1424
 
    {
1425
 
      DRIZZLE_CURSOR_RDLOCK_DONE(error);
1426
 
    }
1427
 
    else if (lock_type == F_WRLCK)
1428
 
    {
1429
 
      DRIZZLE_CURSOR_WRLOCK_DONE(error);
1430
 
    }
1431
 
    else if (lock_type == F_UNLCK)
1432
 
    {
1433
 
      DRIZZLE_CURSOR_UNLOCK_DONE(error);
1434
 
    }
1435
 
  }
1436
 
 
 
2701
  if (error == 0)
 
2702
    cached_table_flags= table_flags();
1437
2703
  return error;
1438
2704
}
1439
2705
 
1440
2706
 
1441
2707
/**
1442
 
  Check Cursor usage and reset state of file to after 'open'
 
2708
  Check handler usage and reset state of file to after 'open'
1443
2709
*/
1444
 
int Cursor::ha_reset()
 
2710
int handler::ha_reset()
1445
2711
{
1446
2712
  /* Check that we have called all proper deallocation functions */
1447
 
  assert(! getTable()->getShare()->all_set.none());
1448
 
  assert(getTable()->key_read == 0);
1449
 
  /* ensure that ha_index_end / endTableScan has been called */
 
2713
  assert((unsigned char*) table->def_read_set.getBitmap() +
 
2714
              table->s->column_bitmap_size ==
 
2715
              (unsigned char*) table->def_write_set.getBitmap());
 
2716
  assert(table->s->all_set.isSetAll());
 
2717
  assert(table->key_read == 0);
 
2718
  /* ensure that ha_index_end / ha_rnd_end has been called */
1450
2719
  assert(inited == NONE);
1451
2720
  /* Free cache used by filesort */
1452
 
  getTable()->free_io_cache();
 
2721
  table->free_io_cache();
1453
2722
  /* reset the bitmaps to point to defaults */
1454
 
  getTable()->default_column_bitmaps();
 
2723
  table->default_column_bitmaps();
1455
2724
  return(reset());
1456
2725
}
1457
2726
 
1458
2727
 
1459
 
int Cursor::insertRecord(unsigned char *buf)
 
2728
int handler::ha_write_row(unsigned char *buf)
1460
2729
{
1461
2730
  int error;
 
2731
  DRIZZLE_INSERT_ROW_START();
1462
2732
 
1463
 
  /*
1464
 
   * If we have a timestamp column, update it to the current time
1465
 
   *
 
2733
  /* 
 
2734
   * If we have a timestamp column, update it to the current time 
 
2735
   * 
1466
2736
   * @TODO Technically, the below two lines can be take even further out of the
1467
 
   * Cursor interface and into the fill_record() method.
 
2737
   * handler interface and into the fill_record() method.
1468
2738
   */
1469
 
  if (getTable()->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
1470
 
  {
1471
 
    getTable()->timestamp_field->set_time();
1472
 
  }
1473
 
 
1474
 
  DRIZZLE_INSERT_ROW_START(getTable()->getShare()->getSchemaName(), getTable()->getShare()->getTableName());
1475
 
  setTransactionReadWrite();
1476
 
  
1477
 
  if (unlikely(plugin::EventObserver::beforeInsertRecord(*getTable(), buf)))
1478
 
  {
1479
 
    error= ER_EVENT_OBSERVER_PLUGIN;
1480
 
  }
1481
 
  else
1482
 
  {
1483
 
    error= doInsertRecord(buf);
1484
 
    if (unlikely(plugin::EventObserver::afterInsertRecord(*getTable(), buf, error))) 
1485
 
    {
1486
 
      error= ER_EVENT_OBSERVER_PLUGIN;
1487
 
    }
1488
 
  }
1489
 
 
1490
 
  ha_statistic_increment(&system_status_var::ha_write_count);
1491
 
 
1492
 
  DRIZZLE_INSERT_ROW_DONE(error);
1493
 
 
1494
 
  if (unlikely(error))
1495
 
  {
 
2739
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
 
2740
    table->timestamp_field->set_time();
 
2741
 
 
2742
  mark_trx_read_write();
 
2743
 
 
2744
  if (unlikely(error= write_row(buf)))
1496
2745
    return error;
1497
 
  }
1498
 
 
1499
 
  if (unlikely(log_row_for_replication(getTable(), NULL, buf)))
1500
 
    return HA_ERR_RBR_LOGGING_FAILED;
1501
 
 
 
2746
 
 
2747
  if (unlikely(log_row_for_replication(table, 0, buf)))
 
2748
    return HA_ERR_RBR_LOGGING_FAILED; /* purecov: inspected */
 
2749
 
 
2750
  DRIZZLE_INSERT_ROW_END();
1502
2751
  return 0;
1503
2752
}
1504
2753
 
1505
2754
 
1506
 
int Cursor::updateRecord(const unsigned char *old_data, unsigned char *new_data)
 
2755
int handler::ha_update_row(const unsigned char *old_data, unsigned char *new_data)
1507
2756
{
1508
2757
  int error;
1509
2758
 
1510
2759
  /*
1511
 
    Some storage engines require that the new record is in getInsertRecord()
1512
 
    (and the old record is in getUpdateRecord()).
 
2760
    Some storage engines require that the new record is in record[0]
 
2761
    (and the old record is in record[1]).
1513
2762
   */
1514
 
  assert(new_data == getTable()->getInsertRecord());
1515
 
 
1516
 
  DRIZZLE_UPDATE_ROW_START(getTable()->getShare()->getSchemaName(), getTable()->getShare()->getTableName());
1517
 
  setTransactionReadWrite();
1518
 
  if (unlikely(plugin::EventObserver::beforeUpdateRecord(*getTable(), old_data, new_data)))
1519
 
  {
1520
 
    error= ER_EVENT_OBSERVER_PLUGIN;
1521
 
  }
1522
 
  else
1523
 
  {
1524
 
    if (getTable()->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
1525
 
    {
1526
 
      getTable()->timestamp_field->set_time();
1527
 
    }
1528
 
 
1529
 
    error= doUpdateRecord(old_data, new_data);
1530
 
    if (unlikely(plugin::EventObserver::afterUpdateRecord(*getTable(), old_data, new_data, error)))
1531
 
    {
1532
 
      error= ER_EVENT_OBSERVER_PLUGIN;
1533
 
    }
1534
 
  }
1535
 
 
1536
 
  ha_statistic_increment(&system_status_var::ha_update_count);
1537
 
 
1538
 
  DRIZZLE_UPDATE_ROW_DONE(error);
1539
 
 
1540
 
  if (unlikely(error))
1541
 
  {
 
2763
  assert(new_data == table->record[0]);
 
2764
 
 
2765
  mark_trx_read_write();
 
2766
 
 
2767
  if (unlikely(error= update_row(old_data, new_data)))
1542
2768
    return error;
1543
 
  }
1544
2769
 
1545
 
  if (unlikely(log_row_for_replication(getTable(), old_data, new_data)))
 
2770
  if (unlikely(log_row_for_replication(table, old_data, new_data)))
1546
2771
    return HA_ERR_RBR_LOGGING_FAILED;
1547
2772
 
1548
2773
  return 0;
1549
2774
}
1550
 
TableShare *Cursor::getShare()
1551
 
{
1552
 
  return getTable()->getMutableShare();
1553
 
}
1554
2775
 
1555
 
int Cursor::deleteRecord(const unsigned char *buf)
 
2776
int handler::ha_delete_row(const unsigned char *buf)
1556
2777
{
1557
2778
  int error;
1558
2779
 
1559
 
  DRIZZLE_DELETE_ROW_START(getTable()->getShare()->getSchemaName(), getTable()->getShare()->getTableName());
1560
 
  setTransactionReadWrite();
1561
 
  if (unlikely(plugin::EventObserver::beforeDeleteRecord(*getTable(), buf)))
1562
 
  {
1563
 
    error= ER_EVENT_OBSERVER_PLUGIN;
1564
 
  }
1565
 
  else
1566
 
  {
1567
 
    error= doDeleteRecord(buf);
1568
 
    if (unlikely(plugin::EventObserver::afterDeleteRecord(*getTable(), buf, error)))
1569
 
    {
1570
 
      error= ER_EVENT_OBSERVER_PLUGIN;
1571
 
    }
1572
 
  }
1573
 
 
1574
 
  ha_statistic_increment(&system_status_var::ha_delete_count);
1575
 
 
1576
 
  DRIZZLE_DELETE_ROW_DONE(error);
1577
 
 
1578
 
  if (unlikely(error))
 
2780
  mark_trx_read_write();
 
2781
 
 
2782
  if (unlikely(error= delete_row(buf)))
1579
2783
    return error;
1580
2784
 
1581
 
  if (unlikely(log_row_for_replication(getTable(), buf, NULL)))
 
2785
  if (unlikely(log_row_for_replication(table, buf, 0)))
1582
2786
    return HA_ERR_RBR_LOGGING_FAILED;
1583
2787
 
1584
2788
  return 0;
1585
2789
}
1586
 
 
1587
 
} /* namespace drizzled */