~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/handler.cc

  • Committer: Eric Lambert
  • Date: 2009-06-11 21:19:36 UTC
  • mto: (1061.1.1 merge-all)
  • mto: This revision was merged to the branch mainline in revision 1062.
  • Revision ID: eric.d.lambert@gmail.com-20090611211936-g2gij43xakupz1dw
-removed rm_dir_w_symlink method call with rmdir since dir should not be a sym link in the first place.

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"
 
30
#include "drizzled/data_home.h"
33
31
#include "drizzled/probes.h"
34
32
#include "drizzled/sql_parse.h"
35
 
#include "drizzled/optimizer/cost_vector.h"
 
33
#include "drizzled/cost_vect.h"
36
34
#include "drizzled/session.h"
37
35
#include "drizzled/sql_base.h"
38
36
#include "drizzled/transaction_services.h"
39
37
#include "drizzled/lock.h"
40
38
#include "drizzled/item/int.h"
41
39
#include "drizzled/item/empty_string.h"
 
40
#include "drizzled/unireg.h" // for mysql_frm_type
42
41
#include "drizzled/field/timestamp.h"
43
42
#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
43
 
48
44
using namespace std;
49
45
 
50
 
namespace drizzled
51
 
{
 
46
extern drizzled::TransactionServices transaction_services;
 
47
 
 
48
KEY_CREATE_INFO default_key_create_info= { HA_KEY_ALG_UNDEF, 0, {NULL,0}, {NULL,0} };
 
49
 
 
50
/* number of entries in storage_engines[] */
 
51
uint32_t total_ha= 0;
 
52
/* number of storage engines (from storage_engines[]) that support 2pc */
 
53
uint32_t total_ha_2pc= 0;
 
54
/* size of savepoint storage area (see ha_init) */
 
55
uint32_t savepoint_alloc_size= 0;
 
56
 
 
57
const char *ha_row_type[] = {
 
58
  "", "FIXED", "DYNAMIC", "COMPRESSED", "REDUNDANT", "COMPACT", "PAGE", "?","?","?"
 
59
};
 
60
 
 
61
const char *tx_isolation_names[] =
 
62
{ "READ-UNCOMMITTED", "READ-COMMITTED", "REPEATABLE-READ", "SERIALIZABLE",
 
63
  NULL};
 
64
 
 
65
TYPELIB tx_isolation_typelib= {array_elements(tx_isolation_names)-1,"",
 
66
                               tx_isolation_names, NULL};
 
67
 
 
68
 
 
69
/**
 
70
  Register handler error messages for use with my_error().
 
71
 
 
72
  @retval
 
73
    0           OK
 
74
  @retval
 
75
    !=0         Error
 
76
*/
 
77
 
 
78
int ha_init_errors(void)
 
79
{
 
80
#define SETMSG(nr, msg) errmsgs[(nr) - HA_ERR_FIRST]= (msg)
 
81
  const char    **errmsgs;
 
82
 
 
83
  /* Allocate a pointer array for the error message strings. */
 
84
  /* Zerofill it to avoid uninitialized gaps. */
 
85
  if (! (errmsgs= (const char**) malloc(HA_ERR_ERRORS * sizeof(char*))))
 
86
    return 1;
 
87
  memset(errmsgs, 0, HA_ERR_ERRORS * sizeof(char *));
 
88
 
 
89
  /* Set the dedicated error messages. */
 
90
  SETMSG(HA_ERR_KEY_NOT_FOUND,          ER(ER_KEY_NOT_FOUND));
 
91
  SETMSG(HA_ERR_FOUND_DUPP_KEY,         ER(ER_DUP_KEY));
 
92
  SETMSG(HA_ERR_RECORD_CHANGED,         "Update wich is recoverable");
 
93
  SETMSG(HA_ERR_WRONG_INDEX,            "Wrong index given to function");
 
94
  SETMSG(HA_ERR_CRASHED,                ER(ER_NOT_KEYFILE));
 
95
  SETMSG(HA_ERR_WRONG_IN_RECORD,        ER(ER_CRASHED_ON_USAGE));
 
96
  SETMSG(HA_ERR_OUT_OF_MEM,             "Table handler out of memory");
 
97
  SETMSG(HA_ERR_NOT_A_TABLE,            "Incorrect file format '%.64s'");
 
98
  SETMSG(HA_ERR_WRONG_COMMAND,          "Command not supported");
 
99
  SETMSG(HA_ERR_OLD_FILE,               ER(ER_OLD_KEYFILE));
 
100
  SETMSG(HA_ERR_NO_ACTIVE_RECORD,       "No record read in update");
 
101
  SETMSG(HA_ERR_RECORD_DELETED,         "Intern record deleted");
 
102
  SETMSG(HA_ERR_RECORD_FILE_FULL,       ER(ER_RECORD_FILE_FULL));
 
103
  SETMSG(HA_ERR_INDEX_FILE_FULL,        "No more room in index file '%.64s'");
 
104
  SETMSG(HA_ERR_END_OF_FILE,            "End in next/prev/first/last");
 
105
  SETMSG(HA_ERR_UNSUPPORTED,            ER(ER_ILLEGAL_HA));
 
106
  SETMSG(HA_ERR_TO_BIG_ROW,             "Too big row");
 
107
  SETMSG(HA_WRONG_CREATE_OPTION,        "Wrong create option");
 
108
  SETMSG(HA_ERR_FOUND_DUPP_UNIQUE,      ER(ER_DUP_UNIQUE));
 
109
  SETMSG(HA_ERR_UNKNOWN_CHARSET,        "Can't open charset");
 
110
  SETMSG(HA_ERR_WRONG_MRG_TABLE_DEF,    ER(ER_WRONG_MRG_TABLE));
 
111
  SETMSG(HA_ERR_CRASHED_ON_REPAIR,      ER(ER_CRASHED_ON_REPAIR));
 
112
  SETMSG(HA_ERR_CRASHED_ON_USAGE,       ER(ER_CRASHED_ON_USAGE));
 
113
  SETMSG(HA_ERR_LOCK_WAIT_TIMEOUT,      ER(ER_LOCK_WAIT_TIMEOUT));
 
114
  SETMSG(HA_ERR_LOCK_TABLE_FULL,        ER(ER_LOCK_TABLE_FULL));
 
115
  SETMSG(HA_ERR_READ_ONLY_TRANSACTION,  ER(ER_READ_ONLY_TRANSACTION));
 
116
  SETMSG(HA_ERR_LOCK_DEADLOCK,          ER(ER_LOCK_DEADLOCK));
 
117
  SETMSG(HA_ERR_CANNOT_ADD_FOREIGN,     ER(ER_CANNOT_ADD_FOREIGN));
 
118
  SETMSG(HA_ERR_NO_REFERENCED_ROW,      ER(ER_NO_REFERENCED_ROW_2));
 
119
  SETMSG(HA_ERR_ROW_IS_REFERENCED,      ER(ER_ROW_IS_REFERENCED_2));
 
120
  SETMSG(HA_ERR_NO_SAVEPOINT,           "No savepoint with that name");
 
121
  SETMSG(HA_ERR_NON_UNIQUE_BLOCK_SIZE,  "Non unique key block size");
 
122
  SETMSG(HA_ERR_NO_SUCH_TABLE,          "No such table: '%.64s'");
 
123
  SETMSG(HA_ERR_TABLE_EXIST,            ER(ER_TABLE_EXISTS_ERROR));
 
124
  SETMSG(HA_ERR_NO_CONNECTION,          "Could not connect to storage engine");
 
125
  SETMSG(HA_ERR_TABLE_DEF_CHANGED,      ER(ER_TABLE_DEF_CHANGED));
 
126
  SETMSG(HA_ERR_FOREIGN_DUPLICATE_KEY,  "FK constraint would lead to duplicate key");
 
127
  SETMSG(HA_ERR_TABLE_NEEDS_UPGRADE,    ER(ER_TABLE_NEEDS_UPGRADE));
 
128
  SETMSG(HA_ERR_TABLE_READONLY,         ER(ER_OPEN_AS_READONLY));
 
129
  SETMSG(HA_ERR_AUTOINC_READ_FAILED,    ER(ER_AUTOINC_READ_FAILED));
 
130
  SETMSG(HA_ERR_AUTOINC_ERANGE,         ER(ER_WARN_DATA_OUT_OF_RANGE));
 
131
 
 
132
  /* Register the error messages for use with my_error(). */
 
133
  return my_error_register(errmsgs, HA_ERR_FIRST, HA_ERR_LAST);
 
134
}
 
135
 
 
136
 
 
137
/**
 
138
  Unregister handler error messages.
 
139
 
 
140
  @retval
 
141
    0           OK
 
142
  @retval
 
143
    !=0         Error
 
144
*/
 
145
static int ha_finish_errors(void)
 
146
{
 
147
  const char    **errmsgs;
 
148
 
 
149
  /* Allocate a pointer array for the error message strings. */
 
150
  if (! (errmsgs= my_error_unregister(HA_ERR_FIRST, HA_ERR_LAST)))
 
151
    return 1;
 
152
  free((unsigned char*) errmsgs);
 
153
  return 0;
 
154
}
 
155
 
 
156
int ha_init()
 
157
{
 
158
  int error= 0;
 
159
 
 
160
  assert(total_ha < MAX_HA);
 
161
  /*
 
162
    Check if there is a transaction-capable storage engine besides the
 
163
    binary log (which is considered a transaction-capable storage engine in
 
164
    counting total_ha)
 
165
  */
 
166
  savepoint_alloc_size+= sizeof(SAVEPOINT);
 
167
  return error;
 
168
}
 
169
 
 
170
int ha_end()
 
171
{
 
172
  int error= 0;
 
173
 
 
174
  /*
 
175
    This should be eventualy based  on the graceful shutdown flag.
 
176
    So if flag is equal to HA_PANIC_CLOSE, the deallocate
 
177
    the errors.
 
178
  */
 
179
  if (ha_finish_errors())
 
180
    error= 1;
 
181
 
 
182
  return error;
 
183
}
 
184
 
 
185
 
 
186
 
 
187
/* ========================================================================
 
188
 ======================= TRANSACTIONS ===================================*/
 
189
 
 
190
/**
 
191
  Transaction handling in the server
 
192
  ==================================
 
193
 
 
194
  In each client connection, MySQL maintains two transactional
 
195
  states:
 
196
  - a statement transaction,
 
197
  - a standard, also called normal transaction.
 
198
 
 
199
  Historical note
 
200
  ---------------
 
201
  "Statement transaction" is a non-standard term that comes
 
202
  from the times when MySQL supported BerkeleyDB storage engine.
 
203
 
 
204
  First of all, it should be said that in BerkeleyDB auto-commit
 
205
  mode auto-commits operations that are atomic to the storage
 
206
  engine itself, such as a write of a record, and are too
 
207
  high-granular to be atomic from the application perspective
 
208
  (MySQL). One SQL statement could involve many BerkeleyDB
 
209
  auto-committed operations and thus BerkeleyDB auto-commit was of
 
210
  little use to MySQL.
 
211
 
 
212
  Secondly, instead of SQL standard savepoints, BerkeleyDB
 
213
  provided the concept of "nested transactions". In a nutshell,
 
214
  transactions could be arbitrarily nested, but when the parent
 
215
  transaction was committed or aborted, all its child (nested)
 
216
  transactions were handled committed or aborted as well.
 
217
  Commit of a nested transaction, in turn, made its changes
 
218
  visible, but not durable: it destroyed the nested transaction,
 
219
  all its changes would become available to the parent and
 
220
  currently active nested transactions of this parent.
 
221
 
 
222
  So the mechanism of nested transactions was employed to
 
223
  provide "all or nothing" guarantee of SQL statements
 
224
  required by the standard.
 
225
  A nested transaction would be created at start of each SQL
 
226
  statement, and destroyed (committed or aborted) at statement
 
227
  end. Such nested transaction was internally referred to as
 
228
  a "statement transaction" and gave birth to the term.
 
229
 
 
230
  <Historical note ends>
 
231
 
 
232
  Since then a statement transaction is started for each statement
 
233
  that accesses transactional tables or uses the binary log.  If
 
234
  the statement succeeds, the statement transaction is committed.
 
235
  If the statement fails, the transaction is rolled back. Commits
 
236
  of statement transactions are not durable -- each such
 
237
  transaction is nested in the normal transaction, and if the
 
238
  normal transaction is rolled back, the effects of all enclosed
 
239
  statement transactions are undone as well.  Technically,
 
240
  a statement transaction can be viewed as a savepoint which is
 
241
  maintained automatically in order to make effects of one
 
242
  statement atomic.
 
243
 
 
244
  The normal transaction is started by the user and is ended
 
245
  usually upon a user request as well. The normal transaction
 
246
  encloses transactions of all statements issued between
 
247
  its beginning and its end.
 
248
  In autocommit mode, the normal transaction is equivalent
 
249
  to the statement transaction.
 
250
 
 
251
  Since MySQL supports PSEA (pluggable storage engine
 
252
  architecture), more than one transactional engine can be
 
253
  active at a time. Hence transactions, from the server
 
254
  point of view, are always distributed. In particular,
 
255
  transactional state is maintained independently for each
 
256
  engine. In order to commit a transaction the two phase
 
257
  commit protocol is employed.
 
258
 
 
259
  Not all statements are executed in context of a transaction.
 
260
  Administrative and status information statements do not modify
 
261
  engine data, and thus do not start a statement transaction and
 
262
  also have no effect on the normal transaction. Examples of such
 
263
  statements are SHOW STATUS and RESET SLAVE.
 
264
 
 
265
  Similarly DDL statements are not transactional,
 
266
  and therefore a transaction is [almost] never started for a DDL
 
267
  statement. The difference between a DDL statement and a purely
 
268
  administrative statement though is that a DDL statement always
 
269
  commits the current transaction before proceeding, if there is
 
270
  any.
 
271
 
 
272
  At last, SQL statements that work with non-transactional
 
273
  engines also have no effect on the transaction state of the
 
274
  connection. Even though they are written to the binary log,
 
275
  and the binary log is, overall, transactional, the writes
 
276
  are done in "write-through" mode, directly to the binlog
 
277
  file, followed with a OS cache sync, in other words,
 
278
  bypassing the binlog undo log (translog).
 
279
  They do not commit the current normal transaction.
 
280
  A failure of a statement that uses non-transactional tables
 
281
  would cause a rollback of the statement transaction, but
 
282
  in case there no non-transactional tables are used,
 
283
  no statement transaction is started.
 
284
 
 
285
  Data layout
 
286
  -----------
 
287
 
 
288
  The server stores its transaction-related data in
 
289
  session->transaction. This structure has two members of type
 
290
  Session_TRANS. These members correspond to the statement and
 
291
  normal transactions respectively:
 
292
 
 
293
  - session->transaction.stmt contains a list of engines
 
294
  that are participating in the given statement
 
295
  - session->transaction.all contains a list of engines that
 
296
  have participated in any of the statement transactions started
 
297
  within the context of the normal transaction.
 
298
  Each element of the list contains a pointer to the storage
 
299
  engine, engine-specific transactional data, and engine-specific
 
300
  transaction flags.
 
301
 
 
302
  In autocommit mode session->transaction.all is empty.
 
303
  Instead, data of session->transaction.stmt is
 
304
  used to commit/rollback the normal transaction.
 
305
 
 
306
  The list of registered engines has a few important properties:
 
307
  - no engine is registered in the list twice
 
308
  - engines are present in the list a reverse temporal order --
 
309
  new participants are always added to the beginning of the list.
 
310
 
 
311
  Transaction life cycle
 
312
  ----------------------
 
313
 
 
314
  When a new connection is established, session->transaction
 
315
  members are initialized to an empty state.
 
316
  If a statement uses any tables, all affected engines
 
317
  are registered in the statement engine list. In
 
318
  non-autocommit mode, the same engines are registered in
 
319
  the normal transaction list.
 
320
  At the end of the statement, the server issues a commit
 
321
  or a roll back for all engines in the statement list.
 
322
  At this point transaction flags of an engine, if any, are
 
323
  propagated from the statement list to the list of the normal
 
324
  transaction.
 
325
  When commit/rollback is finished, the statement list is
 
326
  cleared. It will be filled in again by the next statement,
 
327
  and emptied again at the next statement's end.
 
328
 
 
329
  The normal transaction is committed in a similar way
 
330
  (by going over all engines in session->transaction.all list)
 
331
  but at different times:
 
332
  - upon COMMIT SQL statement is issued by the user
 
333
  - implicitly, by the server, at the beginning of a DDL statement
 
334
  or SET AUTOCOMMIT={0|1} statement.
 
335
 
 
336
  The normal transaction can be rolled back as well:
 
337
  - if the user has requested so, by issuing ROLLBACK SQL
 
338
  statement
 
339
  - if one of the storage engines requested a rollback
 
340
  by setting session->transaction_rollback_request. This may
 
341
  happen in case, e.g., when the transaction in the engine was
 
342
  chosen a victim of the internal deadlock resolution algorithm
 
343
  and rolled back internally. When such a situation happens, there
 
344
  is little the server can do and the only option is to rollback
 
345
  transactions in all other participating engines.  In this case
 
346
  the rollback is accompanied by an error sent to the user.
 
347
 
 
348
  As follows from the use cases above, the normal transaction
 
349
  is never committed when there is an outstanding statement
 
350
  transaction. In most cases there is no conflict, since
 
351
  commits of the normal transaction are issued by a stand-alone
 
352
  administrative or DDL statement, thus no outstanding statement
 
353
  transaction of the previous statement exists. Besides,
 
354
  all statements that manipulate with the normal transaction
 
355
  are prohibited in stored functions and triggers, therefore
 
356
  no conflicting situation can occur in a sub-statement either.
 
357
  The remaining rare cases when the server explicitly has
 
358
  to commit the statement transaction prior to committing the normal
 
359
  one cover error-handling scenarios (see for example
 
360
  ?).
 
361
 
 
362
  When committing a statement or a normal transaction, the server
 
363
  either uses the two-phase commit protocol, or issues a commit
 
364
  in each engine independently. The two-phase commit protocol
 
365
  is used only if:
 
366
  - all participating engines support two-phase commit (provide
 
367
    StorageEngine::prepare PSEA API call) and
 
368
  - transactions in at least two engines modify data (i.e. are
 
369
  not read-only).
 
370
 
 
371
  Note that the two phase commit is used for
 
372
  statement transactions, even though they are not durable anyway.
 
373
  This is done to ensure logical consistency of data in a multiple-
 
374
  engine transaction.
 
375
  For example, imagine that some day MySQL supports unique
 
376
  constraint checks deferred till the end of statement. In such
 
377
  case a commit in one of the engines may yield ER_DUP_KEY,
 
378
  and MySQL should be able to gracefully abort statement
 
379
  transactions of other participants.
 
380
 
 
381
  After the normal transaction has been committed,
 
382
  session->transaction.all list is cleared.
 
383
 
 
384
  When a connection is closed, the current normal transaction, if
 
385
  any, is rolled back.
 
386
 
 
387
  Roles and responsibilities
 
388
  --------------------------
 
389
 
 
390
  The server has no way to know that an engine participates in
 
391
  the statement and a transaction has been started
 
392
  in it unless the engine says so. Thus, in order to be
 
393
  a part of a transaction, the engine must "register" itself.
 
394
  This is done by invoking trans_register_ha() server call.
 
395
  Normally the engine registers itself whenever handler::external_lock()
 
396
  is called. trans_register_ha() can be invoked many times: if
 
397
  an engine is already registered, the call does nothing.
 
398
  In case autocommit is not set, the engine must register itself
 
399
  twice -- both in the statement list and in the normal transaction
 
400
  list.
 
401
  In which list to register is a parameter of trans_register_ha().
 
402
 
 
403
  Note, that although the registration interface in itself is
 
404
  fairly clear, the current usage practice often leads to undesired
 
405
  effects. E.g. since a call to trans_register_ha() in most engines
 
406
  is embedded into implementation of handler::external_lock(), some
 
407
  DDL statements start a transaction (at least from the server
 
408
  point of view) even though they are not expected to. E.g.
 
409
  CREATE TABLE does not start a transaction, since
 
410
  handler::external_lock() is never called during CREATE TABLE. But
 
411
  CREATE TABLE ... SELECT does, since handler::external_lock() is
 
412
  called for the table that is being selected from. This has no
 
413
  practical effects currently, but must be kept in mind
 
414
  nevertheless.
 
415
 
 
416
  Once an engine is registered, the server will do the rest
 
417
  of the work.
 
418
 
 
419
  During statement execution, whenever any of data-modifying
 
420
  PSEA API methods is used, e.g. handler::write_row() or
 
421
  handler::update_row(), the read-write flag is raised in the
 
422
  statement transaction for the involved engine.
 
423
  Currently All PSEA calls are "traced", and the data can not be
 
424
  changed in a way other than issuing a PSEA call. Important:
 
425
  unless this invariant is preserved the server will not know that
 
426
  a transaction in a given engine is read-write and will not
 
427
  involve the two-phase commit protocol!
 
428
 
 
429
  At the end of a statement, server call
 
430
  ha_autocommit_or_rollback() is invoked. This call in turn
 
431
  invokes StorageEngine::prepare() for every involved engine.
 
432
  Prepare is followed by a call to StorageEngine::commit_one_phase()
 
433
  If a one-phase commit will suffice, StorageEngine::prepare() is not
 
434
  invoked and the server only calls StorageEngine::commit_one_phase().
 
435
  At statement commit, the statement-related read-write engine
 
436
  flag is propagated to the corresponding flag in the normal
 
437
  transaction.  When the commit is complete, the list of registered
 
438
  engines is cleared.
 
439
 
 
440
  Rollback is handled in a similar fashion.
 
441
 
 
442
  Additional notes on DDL and the normal transaction.
 
443
  ---------------------------------------------------
 
444
 
 
445
  DDLs and operations with non-transactional engines
 
446
  do not "register" in session->transaction lists, and thus do not
 
447
  modify the transaction state. Besides, each DDL in
 
448
  MySQL is prefixed with an implicit normal transaction commit
 
449
  (a call to Session::endActiveTransaction()), and thus leaves nothing
 
450
  to modify.
 
451
  However, as it has been pointed out with CREATE TABLE .. SELECT,
 
452
  some DDL statements can start a *new* transaction.
 
453
 
 
454
  Behaviour of the server in this case is currently badly
 
455
  defined.
 
456
  DDL statements use a form of "semantic" logging
 
457
  to maintain atomicity: if CREATE TABLE .. SELECT failed,
 
458
  the newly created table is deleted.
 
459
  In addition, some DDL statements issue interim transaction
 
460
  commits: e.g. ALTER Table issues a commit after data is copied
 
461
  from the original table to the internal temporary table. Other
 
462
  statements, e.g. CREATE TABLE ... SELECT do not always commit
 
463
  after itself.
 
464
  And finally there is a group of DDL statements such as
 
465
  RENAME/DROP Table that doesn't start a new transaction
 
466
  and doesn't commit.
 
467
 
 
468
  This diversity makes it hard to say what will happen if
 
469
  by chance a stored function is invoked during a DDL --
 
470
  whether any modifications it makes will be committed or not
 
471
  is not clear. Fortunately, SQL grammar of few DDLs allows
 
472
  invocation of a stored function.
 
473
 
 
474
  A consistent behaviour is perhaps to always commit the normal
 
475
  transaction after all DDLs, just like the statement transaction
 
476
  is always committed at the end of all statements.
 
477
*/
 
478
 
 
479
/**
 
480
  Register a storage engine for a transaction.
 
481
 
 
482
  Every storage engine MUST call this function when it starts
 
483
  a transaction or a statement (that is it must be called both for the
 
484
  "beginning of transaction" and "beginning of statement").
 
485
  Only storage engines registered for the transaction/statement
 
486
  will know when to commit/rollback it.
 
487
 
 
488
  @note
 
489
    trans_register_ha is idempotent - storage engine may register many
 
490
    times per transaction.
 
491
 
 
492
*/
 
493
void trans_register_ha(Session *session, bool all, StorageEngine *engine)
 
494
{
 
495
  Session_TRANS *trans;
 
496
  Ha_trx_info *ha_info;
 
497
 
 
498
  if (all)
 
499
  {
 
500
    trans= &session->transaction.all;
 
501
    session->server_status|= SERVER_STATUS_IN_TRANS;
 
502
  }
 
503
  else
 
504
    trans= &session->transaction.stmt;
 
505
 
 
506
  ha_info= session->ha_data[engine->getSlot()].ha_info + static_cast<unsigned>(all);
 
507
 
 
508
  if (ha_info->is_started())
 
509
    return; /* already registered, return */
 
510
 
 
511
  ha_info->register_ha(trans, engine);
 
512
 
 
513
  trans->no_2pc|= not engine->has_2pc();
 
514
  if (session->transaction.xid_state.xid.is_null())
 
515
    session->transaction.xid_state.xid.set(session->query_id);
 
516
}
 
517
 
 
518
/**
 
519
  Check if we can skip the two-phase commit.
 
520
 
 
521
  A helper function to evaluate if two-phase commit is mandatory.
 
522
  As a side effect, propagates the read-only/read-write flags
 
523
  of the statement transaction to its enclosing normal transaction.
 
524
 
 
525
  @retval true   we must run a two-phase commit. Returned
 
526
                 if we have at least two engines with read-write changes.
 
527
  @retval false  Don't need two-phase commit. Even if we have two
 
528
                 transactional engines, we can run two independent
 
529
                 commits if changes in one of the engines are read-only.
 
530
*/
 
531
 
 
532
static
 
533
bool
 
534
ha_check_and_coalesce_trx_read_only(Session *session, Ha_trx_info *ha_list,
 
535
                                    bool all)
 
536
{
 
537
  /* The number of storage engines that have actual changes. */
 
538
  unsigned rw_ha_count= 0;
 
539
  Ha_trx_info *ha_info;
 
540
 
 
541
  for (ha_info= ha_list; ha_info; ha_info= ha_info->next())
 
542
  {
 
543
    if (ha_info->is_trx_read_write())
 
544
      ++rw_ha_count;
 
545
 
 
546
    if (! all)
 
547
    {
 
548
      Ha_trx_info *ha_info_all= &session->ha_data[ha_info->engine()->getSlot()].ha_info[1];
 
549
      assert(ha_info != ha_info_all);
 
550
      /*
 
551
        Merge read-only/read-write information about statement
 
552
        transaction to its enclosing normal transaction. Do this
 
553
        only if in a real transaction -- that is, if we know
 
554
        that ha_info_all is registered in session->transaction.all.
 
555
        Since otherwise we only clutter the normal transaction flags.
 
556
      */
 
557
      if (ha_info_all->is_started()) /* false if autocommit. */
 
558
        ha_info_all->coalesce_trx_with(ha_info);
 
559
    }
 
560
    else if (rw_ha_count > 1)
 
561
    {
 
562
      /*
 
563
        It is a normal transaction, so we don't need to merge read/write
 
564
        information up, and the need for two-phase commit has been
 
565
        already established. Break the loop prematurely.
 
566
      */
 
567
      break;
 
568
    }
 
569
  }
 
570
  return rw_ha_count > 1;
 
571
}
 
572
 
 
573
 
 
574
/**
 
575
  @retval
 
576
    0   ok
 
577
  @retval
 
578
    1   transaction was rolled back
 
579
  @retval
 
580
    2   error during commit, data may be inconsistent
 
581
 
 
582
  @todo
 
583
    Since we don't support nested statement transactions in 5.0,
 
584
    we can't commit or rollback stmt transactions while we are inside
 
585
    stored functions or triggers. So we simply do nothing now.
 
586
    TODO: This should be fixed in later ( >= 5.1) releases.
 
587
*/
 
588
int ha_commit_trans(Session *session, bool all)
 
589
{
 
590
  int error= 0, cookie= 0;
 
591
  /*
 
592
    'all' means that this is either an explicit commit issued by
 
593
    user, or an implicit commit issued by a DDL.
 
594
  */
 
595
  Session_TRANS *trans= all ? &session->transaction.all : &session->transaction.stmt;
 
596
  bool is_real_trans= all || session->transaction.all.ha_list == 0;
 
597
  Ha_trx_info *ha_info= trans->ha_list;
 
598
 
 
599
  /*
 
600
    We must not commit the normal transaction if a statement
 
601
    transaction is pending. Otherwise statement transaction
 
602
    flags will not get propagated to its normal transaction's
 
603
    counterpart.
 
604
  */
 
605
  assert(session->transaction.stmt.ha_list == NULL ||
 
606
              trans == &session->transaction.stmt);
 
607
 
 
608
  if (ha_info)
 
609
  {
 
610
    bool must_2pc;
 
611
 
 
612
    if (is_real_trans && wait_if_global_read_lock(session, 0, 0))
 
613
    {
 
614
      ha_rollback_trans(session, all);
 
615
      return 1;
 
616
    }
 
617
 
 
618
    must_2pc= ha_check_and_coalesce_trx_read_only(session, ha_info, all);
 
619
 
 
620
    if (!trans->no_2pc && must_2pc)
 
621
    {
 
622
      for (; ha_info && !error; ha_info= ha_info->next())
 
623
      {
 
624
        int err;
 
625
        StorageEngine *engine= ha_info->engine();
 
626
        /*
 
627
          Do not call two-phase commit if this particular
 
628
          transaction is read-only. This allows for simpler
 
629
          implementation in engines that are always read-only.
 
630
        */
 
631
        if (! ha_info->is_trx_read_write())
 
632
          continue;
 
633
        /*
 
634
          Sic: we know that prepare() is not NULL since otherwise
 
635
          trans->no_2pc would have been set.
 
636
        */
 
637
        if ((err= engine->prepare(session, all)))
 
638
        {
 
639
          my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
 
640
          error= 1;
 
641
        }
 
642
        status_var_increment(session->status_var.ha_prepare_count);
 
643
      }
 
644
      if (error)
 
645
      {
 
646
        ha_rollback_trans(session, all);
 
647
        error= 1;
 
648
        goto end;
 
649
      }
 
650
    }
 
651
    error=ha_commit_one_phase(session, all) ? (cookie ? 2 : 1) : 0;
 
652
end:
 
653
    if (is_real_trans)
 
654
      start_waiting_global_read_lock(session);
 
655
  }
 
656
  return error;
 
657
}
 
658
 
 
659
/**
 
660
  @note
 
661
  This function does not care about global read lock. A caller should.
 
662
*/
 
663
int ha_commit_one_phase(Session *session, bool all)
 
664
{
 
665
  int error=0;
 
666
  Session_TRANS *trans=all ? &session->transaction.all : &session->transaction.stmt;
 
667
  bool is_real_trans=all || session->transaction.all.ha_list == 0;
 
668
  Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
 
669
  if (ha_info)
 
670
  {
 
671
    for (; ha_info; ha_info= ha_info_next)
 
672
    {
 
673
      int err;
 
674
      StorageEngine *engine= ha_info->engine();
 
675
      if ((err= engine->commit(session, all)))
 
676
      {
 
677
        my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
 
678
        error=1;
 
679
      }
 
680
      status_var_increment(session->status_var.ha_commit_count);
 
681
      ha_info_next= ha_info->next();
 
682
      ha_info->reset(); /* keep it conveniently zero-filled */
 
683
    }
 
684
    trans->ha_list= 0;
 
685
    trans->no_2pc=0;
 
686
    if (is_real_trans)
 
687
      session->transaction.xid_state.xid.null();
 
688
    if (all)
 
689
    {
 
690
      session->variables.tx_isolation=session->session_tx_isolation;
 
691
      session->transaction.cleanup();
 
692
    }
 
693
  }
 
694
  return error;
 
695
}
 
696
 
 
697
 
 
698
int ha_rollback_trans(Session *session, bool all)
 
699
{
 
700
  int error=0;
 
701
  Session_TRANS *trans=all ? &session->transaction.all : &session->transaction.stmt;
 
702
  Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
 
703
  bool is_real_trans=all || session->transaction.all.ha_list == 0;
 
704
 
 
705
  /*
 
706
    We must not rollback the normal transaction if a statement
 
707
    transaction is pending.
 
708
  */
 
709
  assert(session->transaction.stmt.ha_list == NULL ||
 
710
              trans == &session->transaction.stmt);
 
711
 
 
712
  if (ha_info)
 
713
  {
 
714
    for (; ha_info; ha_info= ha_info_next)
 
715
    {
 
716
      int err;
 
717
      StorageEngine *engine= ha_info->engine();
 
718
      if ((err= engine->rollback(session, all)))
 
719
      { // cannot happen
 
720
        my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
 
721
        error=1;
 
722
      }
 
723
      status_var_increment(session->status_var.ha_rollback_count);
 
724
      ha_info_next= ha_info->next();
 
725
      ha_info->reset(); /* keep it conveniently zero-filled */
 
726
    }
 
727
    trans->ha_list= 0;
 
728
    trans->no_2pc=0;
 
729
    if (is_real_trans)
 
730
      session->transaction.xid_state.xid.null();
 
731
    if (all)
 
732
    {
 
733
      session->variables.tx_isolation=session->session_tx_isolation;
 
734
      session->transaction.cleanup();
 
735
    }
 
736
  }
 
737
  if (all)
 
738
    session->transaction_rollback_request= false;
 
739
 
 
740
  /*
 
741
    If a non-transactional table was updated, warn; don't warn if this is a
 
742
    slave thread (because when a slave thread executes a ROLLBACK, it has
 
743
    been read from the binary log, so it's 100% sure and normal to produce
 
744
    error ER_WARNING_NOT_COMPLETE_ROLLBACK. If we sent the warning to the
 
745
    slave SQL thread, it would not stop the thread but just be printed in
 
746
    the error log; but we don't want users to wonder why they have this
 
747
    message in the error log, so we don't send it.
 
748
  */
 
749
  if (is_real_trans && session->transaction.all.modified_non_trans_table && session->killed != Session::KILL_CONNECTION)
 
750
    push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
751
                 ER_WARNING_NOT_COMPLETE_ROLLBACK,
 
752
                 ER(ER_WARNING_NOT_COMPLETE_ROLLBACK));
 
753
  return error;
 
754
}
 
755
 
 
756
/**
 
757
  This is used to commit or rollback a single statement depending on
 
758
  the value of error.
 
759
 
 
760
  @note
 
761
    Note that if the autocommit is on, then the following call inside
 
762
    InnoDB will commit or rollback the whole transaction (= the statement). The
 
763
    autocommit mechanism built into InnoDB is based on counting locks, but if
 
764
    the user has used LOCK TABLES then that mechanism does not know to do the
 
765
    commit.
 
766
*/
 
767
int ha_autocommit_or_rollback(Session *session, int error)
 
768
{
 
769
  if (session->transaction.stmt.ha_list)
 
770
  {
 
771
    if (!error)
 
772
    {
 
773
      if (ha_commit_trans(session, 0))
 
774
        error= 1;
 
775
    }
 
776
    else
 
777
    {
 
778
      (void) ha_rollback_trans(session, 0);
 
779
      if (session->transaction_rollback_request)
 
780
        (void) ha_rollback(session);
 
781
    }
 
782
 
 
783
    session->variables.tx_isolation=session->session_tx_isolation;
 
784
  }
 
785
 
 
786
  return error;
 
787
}
 
788
 
 
789
 
 
790
 
 
791
 
 
792
/**
 
793
  return the list of XID's to a client, the same way SHOW commands do.
 
794
 
 
795
  @note
 
796
    I didn't find in XA specs that an RM cannot return the same XID twice,
 
797
    so mysql_xa_recover does not filter XID's to ensure uniqueness.
 
798
    It can be easily fixed later, if necessary.
 
799
*/
 
800
bool mysql_xa_recover(Session *session)
 
801
{
 
802
  List<Item> field_list;
 
803
  Protocol *protocol= session->protocol;
 
804
  int i=0;
 
805
  XID_STATE *xs;
 
806
 
 
807
  field_list.push_back(new Item_int("formatID", 0, MY_INT32_NUM_DECIMAL_DIGITS));
 
808
  field_list.push_back(new Item_int("gtrid_length", 0, MY_INT32_NUM_DECIMAL_DIGITS));
 
809
  field_list.push_back(new Item_int("bqual_length", 0, MY_INT32_NUM_DECIMAL_DIGITS));
 
810
  field_list.push_back(new Item_empty_string("data",XIDDATASIZE));
 
811
 
 
812
  if (protocol->sendFields(&field_list,
 
813
                           Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
 
814
    return 1;
 
815
 
 
816
  pthread_mutex_lock(&LOCK_xid_cache);
 
817
  while ((xs= (XID_STATE*)hash_element(&xid_cache, i++)))
 
818
  {
 
819
    if (xs->xa_state==XA_PREPARED)
 
820
    {
 
821
      protocol->prepareForResend();
 
822
      protocol->store((int64_t)xs->xid.formatID);
 
823
      protocol->store((int64_t)xs->xid.gtrid_length);
 
824
      protocol->store((int64_t)xs->xid.bqual_length);
 
825
      protocol->store(xs->xid.data, xs->xid.gtrid_length+xs->xid.bqual_length);
 
826
      if (protocol->write())
 
827
      {
 
828
        pthread_mutex_unlock(&LOCK_xid_cache);
 
829
        return 1;
 
830
      }
 
831
    }
 
832
  }
 
833
 
 
834
  pthread_mutex_unlock(&LOCK_xid_cache);
 
835
  session->my_eof();
 
836
  return 0;
 
837
}
 
838
 
 
839
 
 
840
int ha_rollback_to_savepoint(Session *session, SAVEPOINT *sv)
 
841
{
 
842
  int error= 0;
 
843
  Session_TRANS *trans= &session->transaction.all;
 
844
  Ha_trx_info *ha_info, *ha_info_next;
 
845
 
 
846
  trans->no_2pc=0;
 
847
  /*
 
848
    rolling back to savepoint in all storage engines that were part of the
 
849
    transaction when the savepoint was set
 
850
  */
 
851
  for (ha_info= sv->ha_list; ha_info; ha_info= ha_info->next())
 
852
  {
 
853
    int err;
 
854
    StorageEngine *engine= ha_info->engine();
 
855
    assert(engine);
 
856
    if ((err= engine->savepoint_rollback(session,
 
857
                                         (void *)(sv+1))))
 
858
    { // cannot happen
 
859
      my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
 
860
      error= 1;
 
861
    }
 
862
    status_var_increment(session->status_var.ha_savepoint_rollback_count);
 
863
    trans->no_2pc|= not engine->has_2pc();
 
864
  }
 
865
  /*
 
866
    rolling back the transaction in all storage engines that were not part of
 
867
    the transaction when the savepoint was set
 
868
  */
 
869
  for (ha_info= trans->ha_list; ha_info != sv->ha_list;
 
870
       ha_info= ha_info_next)
 
871
  {
 
872
    int err;
 
873
    StorageEngine *engine= ha_info->engine();
 
874
    if ((err= engine->rollback(session, !(0))))
 
875
    { // cannot happen
 
876
      my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
 
877
      error= 1;
 
878
    }
 
879
    status_var_increment(session->status_var.ha_rollback_count);
 
880
    ha_info_next= ha_info->next();
 
881
    ha_info->reset(); /* keep it conveniently zero-filled */
 
882
  }
 
883
  trans->ha_list= sv->ha_list;
 
884
  return error;
 
885
}
 
886
 
 
887
/**
 
888
  @note
 
889
  according to the sql standard (ISO/IEC 9075-2:2003)
 
890
  section "4.33.4 SQL-statements and transaction states",
 
891
  SAVEPOINT is *not* transaction-initiating SQL-statement
 
892
*/
 
893
int ha_savepoint(Session *session, SAVEPOINT *sv)
 
894
{
 
895
  int error= 0;
 
896
  Session_TRANS *trans= &session->transaction.all;
 
897
  Ha_trx_info *ha_info= trans->ha_list;
 
898
  for (; ha_info; ha_info= ha_info->next())
 
899
  {
 
900
    int err;
 
901
    StorageEngine *engine= ha_info->engine();
 
902
    assert(engine);
 
903
#ifdef NOT_IMPLEMENTED /*- TODO (examine this againt the original code base) */
 
904
    if (! engine->savepoint_set)
 
905
    {
 
906
      my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "SAVEPOINT");
 
907
      error= 1;
 
908
      break;
 
909
    } 
 
910
#endif
 
911
    if ((err= engine->savepoint_set(session, (void *)(sv+1))))
 
912
    { // cannot happen
 
913
      my_error(ER_GET_ERRNO, MYF(0), err);
 
914
      error= 1;
 
915
    }
 
916
    status_var_increment(session->status_var.ha_savepoint_count);
 
917
  }
 
918
  /*
 
919
    Remember the list of registered storage engines. All new
 
920
    engines are prepended to the beginning of the list.
 
921
  */
 
922
  sv->ha_list= trans->ha_list;
 
923
  return error;
 
924
}
 
925
 
 
926
int ha_release_savepoint(Session *session, SAVEPOINT *sv)
 
927
{
 
928
  int error= 0;
 
929
  Ha_trx_info *ha_info= sv->ha_list;
 
930
 
 
931
  for (; ha_info; ha_info= ha_info->next())
 
932
  {
 
933
    int err;
 
934
    StorageEngine *engine= ha_info->engine();
 
935
    /* Savepoint life time is enclosed into transaction life time. */
 
936
    assert(engine);
 
937
    if ((err= engine->savepoint_release(session,
 
938
                                        (void *)(sv+1))))
 
939
    { // cannot happen
 
940
      my_error(ER_GET_ERRNO, MYF(0), err);
 
941
      error= 1;
 
942
    }
 
943
  }
 
944
  return error;
 
945
}
 
946
 
 
947
 
 
948
 
 
949
 
52
950
 
53
951
/****************************************************************************
54
 
** General Cursor functions
 
952
** General handler functions
55
953
****************************************************************************/
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)
 
954
handler::~handler(void)
70
955
{
71
956
  assert(locked == false);
72
957
  /* TODO: assert(inited == NONE); */
73
958
}
74
959
 
75
960
 
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)
 
961
handler *handler::clone(MEM_ROOT *mem_root)
82
962
{
83
 
  Cursor *new_handler= getTable()->getMutableShare()->db_type()->getCursor(*getTable());
84
 
 
 
963
  handler *new_handler= get_new_handler(table->s, mem_root, table->s->db_type());
85
964
  /*
86
 
    Allocate Cursor->ref here because otherwise ha_open will allocate it
 
965
    Allocate handler->ref here because otherwise ha_open will allocate it
87
966
    on this->table->mem_root and we will not be able to reclaim that memory
88
 
    when the clone Cursor object is destroyed.
 
967
    when the clone handler object is destroyed.
89
968
  */
90
 
  if (!(new_handler->ref= (unsigned char*) mem_root->alloc_root(ALIGN_SIZE(ref_length)*2)))
 
969
  if (!(new_handler->ref= (unsigned char*) alloc_root(mem_root, ALIGN_SIZE(ref_length)*2)))
91
970
    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(),
 
971
  if (new_handler && !new_handler->ha_open(table,
 
972
                                           table->s->normalized_path.str,
 
973
                                           table->getDBStat(),
99
974
                                           HA_OPEN_IGNORE_IF_LOCKED))
100
975
    return new_handler;
101
976
  return NULL;
102
977
}
103
978
 
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)
 
979
int handler::ha_index_init(uint32_t idx, bool sorted)
128
980
{
129
981
  int result;
130
982
  assert(inited == NONE);
131
 
  if (!(result= doStartIndexScan(idx, sorted)))
 
983
  if (!(result= index_init(idx, sorted)))
132
984
    inited=INDEX;
133
985
  end_range= NULL;
134
986
  return result;
135
987
}
136
988
 
137
 
int Cursor::endIndexScan()
 
989
int handler::ha_index_end()
138
990
{
139
991
  assert(inited==INDEX);
140
992
  inited=NONE;
141
993
  end_range= NULL;
142
 
  return(doEndIndexScan());
 
994
  return(index_end());
143
995
}
144
996
 
145
 
int Cursor::startTableScan(bool scan)
 
997
int handler::ha_rnd_init(bool scan)
146
998
{
147
999
  int result;
148
1000
  assert(inited==NONE || (inited==RND && scan));
149
 
  inited= (result= doStartTableScan(scan)) ? NONE: RND;
 
1001
  inited= (result= rnd_init(scan)) ? NONE: RND;
150
1002
 
151
1003
  return result;
152
1004
}
153
1005
 
154
 
int Cursor::endTableScan()
 
1006
int handler::ha_rnd_end()
155
1007
{
156
1008
  assert(inited==RND);
157
1009
  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)
 
1010
  return(rnd_end());
 
1011
}
 
1012
 
 
1013
int handler::ha_index_or_rnd_end()
 
1014
{
 
1015
  return inited == INDEX ? ha_index_end() : inited == RND ? ha_rnd_end() : 0;
 
1016
}
 
1017
 
 
1018
handler::Table_flags handler::ha_table_flags() const
 
1019
{
 
1020
  return cached_table_flags;
 
1021
}
 
1022
 
 
1023
void handler::ha_start_bulk_insert(ha_rows rows)
167
1024
{
168
1025
  estimation_rows_to_insert= rows;
169
1026
  start_bulk_insert(rows);
170
1027
}
171
1028
 
172
 
int Cursor::ha_end_bulk_insert()
 
1029
int handler::ha_end_bulk_insert()
173
1030
{
174
1031
  estimation_rows_to_insert= 0;
175
1032
  return end_bulk_insert();
176
1033
}
177
1034
 
178
 
const key_map *Cursor::keys_to_use_for_scanning()
 
1035
void handler::change_table_ptr(Table *table_arg, TableShare *share)
 
1036
{
 
1037
  table= table_arg;
 
1038
  table_share= share;
 
1039
}
 
1040
 
 
1041
const key_map *handler::keys_to_use_for_scanning()
179
1042
{
180
1043
  return &key_map_empty;
181
1044
}
182
1045
 
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)
 
1046
bool handler::has_transactions()
 
1047
{
 
1048
  return (ha_table_flags() & HA_NO_TRANSACTIONS) == 0;
 
1049
}
 
1050
 
 
1051
void handler::ha_statistic_increment(ulong SSV::*offset) const
 
1052
{
 
1053
  status_var_increment(table->in_use->status_var.*offset);
 
1054
}
 
1055
 
 
1056
void **handler::ha_data(Session *session) const
 
1057
{
 
1058
  return session_ha_data(session, engine);
 
1059
}
 
1060
 
 
1061
Session *handler::ha_session(void) const
 
1062
{
 
1063
  assert(!table || !table->in_use || table->in_use == current_session);
 
1064
  return (table && table->in_use) ? table->in_use : current_session;
 
1065
}
 
1066
 
 
1067
 
 
1068
bool handler::is_fatal_error(int error, uint32_t flags)
199
1069
{
200
1070
  if (!error ||
201
1071
      ((flags & HA_CHECK_DUP_KEY) &&
206
1076
}
207
1077
 
208
1078
 
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
 
}
 
1079
ha_rows handler::records() { return stats.records; }
217
1080
 
218
1081
/**
219
 
  Open database-Cursor.
 
1082
  Open database-handler.
220
1083
 
221
1084
  Try O_RDONLY if cannot open as O_RDWR
222
1085
  Don't wait for locks if not HA_OPEN_WAIT_IF_LOCKED is set
223
1086
*/
224
 
int Cursor::ha_open(const TableIdentifier &identifier,
225
 
                    int mode,
226
 
                    int test_if_locked)
 
1087
int handler::ha_open(Table *table_arg, const char *name, int mode,
 
1088
                     int test_if_locked)
227
1089
{
228
1090
  int error;
229
1091
 
230
 
  if ((error= doOpen(identifier, mode, test_if_locked)))
 
1092
  table= table_arg;
 
1093
  assert(table->s == table_share);
 
1094
  assert(alloc_root_inited(&table->mem_root));
 
1095
 
 
1096
  if ((error=open(name,mode,test_if_locked)))
231
1097
  {
232
1098
    if ((error == EACCES || error == EROFS) && mode == O_RDWR &&
233
 
        (getTable()->db_stat & HA_TRY_READ_ONLY))
 
1099
        (table->db_stat & HA_TRY_READ_ONLY))
234
1100
    {
235
 
      getTable()->db_stat|=HA_READ_ONLY;
236
 
      error= doOpen(identifier, O_RDONLY,test_if_locked);
 
1101
      table->db_stat|=HA_READ_ONLY;
 
1102
      error=open(name,O_RDONLY,test_if_locked);
237
1103
    }
238
1104
  }
239
1105
  if (error)
240
1106
  {
241
 
    errno= error;                            /* Safeguard */
 
1107
    my_errno= error;                            /* Safeguard */
242
1108
  }
243
1109
  else
244
1110
  {
245
 
    if (getTable()->getShare()->db_options_in_use & HA_OPTION_READ_ONLY_DATA)
246
 
      getTable()->db_stat|=HA_READ_ONLY;
 
1111
    if (table->s->db_options_in_use & HA_OPTION_READ_ONLY_DATA)
 
1112
      table->db_stat|=HA_READ_ONLY;
247
1113
    (void) extra(HA_EXTRA_NO_READCHECK);        // Not needed in SQL
248
1114
 
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)))
 
1115
    /* ref is already allocated for us if we're called from handler::clone() */
 
1116
    if (!ref && !(ref= (unsigned char*) alloc_root(&table->mem_root,
 
1117
                                          ALIGN_SIZE(ref_length)*2)))
251
1118
    {
252
1119
      close();
253
1120
      error=HA_ERR_OUT_OF_MEM;
254
1121
    }
255
1122
    else
256
1123
      dup_ref=ref+ALIGN_SIZE(ref_length);
 
1124
    cached_table_flags= table_flags();
257
1125
  }
258
1126
  return error;
259
1127
}
260
1128
 
261
1129
/**
 
1130
  one has to use this method when to find
 
1131
  random position by record as the plain
 
1132
  position() call doesn't work for some
 
1133
  handlers for random position
 
1134
*/
 
1135
 
 
1136
int handler::rnd_pos_by_record(unsigned char *record)
 
1137
{
 
1138
  register int error;
 
1139
 
 
1140
  position(record);
 
1141
  if (inited && (error= ha_index_end()))
 
1142
    return error;
 
1143
  if ((error= ha_rnd_init(false)))
 
1144
    return error;
 
1145
 
 
1146
  return rnd_pos(record, ref);
 
1147
}
 
1148
 
 
1149
/**
262
1150
  Read first row (only) from a table.
263
1151
 
264
1152
  This is never called for InnoDB tables, as these table types
265
1153
  has the HA_STATS_RECORDS_IS_EXACT set.
266
1154
*/
267
 
int Cursor::read_first_row(unsigned char * buf, uint32_t primary_key)
 
1155
int handler::read_first_row(unsigned char * buf, uint32_t primary_key)
268
1156
{
269
1157
  register int error;
270
1158
 
271
 
  ha_statistic_increment(&system_status_var::ha_read_first_count);
 
1159
  ha_statistic_increment(&SSV::ha_read_first_count);
272
1160
 
273
1161
  /*
274
1162
    If there is very few deleted rows in the table, find the first row by
276
1164
    TODO remove the test for HA_READ_ORDER
277
1165
  */
278
1166
  if (stats.deleted < 10 || primary_key >= MAX_KEY ||
279
 
      !(getTable()->index_flags(primary_key) & HA_READ_ORDER))
 
1167
      !(index_flags(primary_key, 0, 0) & HA_READ_ORDER))
280
1168
  {
281
 
    (void) startTableScan(1);
 
1169
    (void) ha_rnd_init(1);
282
1170
    while ((error= rnd_next(buf)) == HA_ERR_RECORD_DELETED) ;
283
 
    (void) endTableScan();
 
1171
    (void) ha_rnd_end();
284
1172
  }
285
1173
  else
286
1174
  {
287
1175
    /* Find the first row through the primary key */
288
 
    (void) startIndexScan(primary_key, 0);
 
1176
    (void) ha_index_init(primary_key, 0);
289
1177
    error=index_first(buf);
290
 
    (void) endIndexScan();
 
1178
    (void) ha_index_end();
291
1179
  }
292
1180
  return error;
293
1181
}
304
1192
  @verbatim 1,5,15,25,35,... @endverbatim
305
1193
*/
306
1194
inline uint64_t
307
 
compute_next_insert_id(uint64_t nr, drizzle_system_variables *variables)
 
1195
compute_next_insert_id(uint64_t nr,struct system_variables *variables)
308
1196
{
309
1197
  if (variables->auto_increment_increment == 1)
310
1198
    return (nr+1); // optimization of the formula below
316
1204
}
317
1205
 
318
1206
 
319
 
void Cursor::adjust_next_insert_id_after_explicit_value(uint64_t nr)
 
1207
void handler::adjust_next_insert_id_after_explicit_value(uint64_t nr)
320
1208
{
321
1209
  /*
322
1210
    If we have set Session::next_insert_id previously and plan to insert an
324
1212
    Session::next_insert_id to be greater than the explicit value.
325
1213
  */
326
1214
  if ((next_insert_id > 0) && (nr >= next_insert_id))
327
 
    set_next_insert_id(compute_next_insert_id(nr, &getTable()->in_use->variables));
 
1215
    set_next_insert_id(compute_next_insert_id(nr, &table->in_use->variables));
328
1216
}
329
1217
 
330
1218
 
344
1232
    The number X if it exists, "nr" otherwise.
345
1233
*/
346
1234
inline uint64_t
347
 
prev_insert_id(uint64_t nr, drizzle_system_variables *variables)
 
1235
prev_insert_id(uint64_t nr, struct system_variables *variables)
348
1236
{
349
1237
  if (unlikely(nr < variables->auto_increment_offset))
350
1238
  {
369
1257
 
370
1258
  Updates columns with type NEXT_NUMBER if:
371
1259
 
372
 
  - If column value is set to NULL (in which case auto_increment_field_not_null is false)
 
1260
  - If column value is set to NULL (in which case
 
1261
    auto_increment_field_not_null is 0)
373
1262
  - If column is set to 0 and (sql_mode & MODE_NO_AUTO_VALUE_ON_ZERO) is not
374
1263
    set. In the future we will only set NEXT_NUMBER fields if one sets them
375
1264
    to NULL (or they are not included in the insert list).
390
1279
    reserved for us.
391
1280
 
392
1281
  - 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
 
1282
    calling the handler again (we just progress in the interval, computing
394
1283
    each new value from the previous one). Until we have exhausted them, then
395
1284
    we either take the next provided interval or call get_auto_increment()
396
1285
    again to reserve a new interval.
437
1326
#define AUTO_INC_DEFAULT_NB_MAX_BITS 16
438
1327
#define AUTO_INC_DEFAULT_NB_MAX ((1 << AUTO_INC_DEFAULT_NB_MAX_BITS) - 1)
439
1328
 
440
 
int Cursor::update_auto_increment()
 
1329
int handler::update_auto_increment()
441
1330
{
442
1331
  uint64_t nr, nb_reserved_values;
443
1332
  bool append= false;
444
 
  Session *session= getTable()->in_use;
445
 
  drizzle_system_variables *variables= &session->variables;
 
1333
  Session *session= table->in_use;
 
1334
  struct system_variables *variables= &session->variables;
446
1335
 
447
1336
  /*
448
1337
    next_insert_id is a "cursor" into the reserved interval, it may go greater
450
1339
  */
451
1340
  assert(next_insert_id >= auto_inc_interval_for_cur_row.minimum());
452
1341
 
453
 
  /* We check if auto_increment_field_not_null is false
 
1342
  /* We check for auto_increment_field_not_null as 0 is an explicit value
454
1343
     for an auto increment column, not a magic value like NULL is.
455
1344
     same as sql_mode=NO_AUTO_VALUE_ON_ZERO */
456
1345
 
457
 
  if ((nr= getTable()->next_number_field->val_int()) != 0
458
 
      || getTable()->auto_increment_field_not_null)
 
1346
  if ((nr= table->next_number_field->val_int()) != 0
 
1347
      || table->auto_increment_field_not_null)
459
1348
  {
460
1349
    /*
461
1350
      Update next_insert_id if we had already generated a value in this
482
1371
    else
483
1372
    {
484
1373
      /*
485
 
        Cursor::estimation_rows_to_insert was set by
486
 
        Cursor::ha_start_bulk_insert(); if 0 it means "unknown".
 
1374
        handler::estimation_rows_to_insert was set by
 
1375
        handler::ha_start_bulk_insert(); if 0 it means "unknown".
487
1376
      */
488
1377
      uint32_t nb_already_reserved_intervals=
489
1378
        session->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements();
533
1422
      nr= compute_next_insert_id(nr-1, variables);
534
1423
    }
535
1424
 
536
 
    if (getTable()->getShare()->next_number_keypart == 0)
 
1425
    if (table->s->next_number_keypart == 0)
537
1426
    {
538
1427
      /* We must defer the appending until "nr" has been possibly truncated */
539
1428
      append= true;
540
1429
    }
541
1430
  }
542
1431
 
543
 
  if (unlikely(getTable()->next_number_field->store((int64_t) nr, true)))
 
1432
  if (unlikely(table->next_number_field->store((int64_t) nr, true)))
544
1433
  {
545
1434
    /*
546
1435
      first test if the query was aborted due to strict mode constraints
547
1436
    */
548
 
    if (session->getKilled() == Session::KILL_BAD_DATA)
 
1437
    if (session->killed == Session::KILL_BAD_DATA)
549
1438
      return HA_ERR_AUTOINC_ERANGE;
550
1439
 
551
1440
    /*
556
1445
      bother shifting the right bound (anyway any other value from this
557
1446
      interval will cause a duplicate key).
558
1447
    */
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();
 
1448
    nr= prev_insert_id(table->next_number_field->val_int(), variables);
 
1449
    if (unlikely(table->next_number_field->store((int64_t) nr, true)))
 
1450
      nr= table->next_number_field->val_int();
562
1451
  }
563
1452
  if (append)
564
1453
  {
585
1474
 
586
1475
 
587
1476
/**
588
 
  Reserves an interval of auto_increment values from the Cursor.
 
1477
  Reserves an interval of auto_increment values from the handler.
589
1478
 
590
1479
  offset and increment means that we want values to be of the form
591
1480
  offset + N * increment, where N>=0 is integer.
596
1485
  @param offset
597
1486
  @param increment
598
1487
  @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
 
1488
  @param first_value         (OUT) the first value reserved by the handler
 
1489
  @param nb_reserved_values  (OUT) how many values the handler reserved
601
1490
*/
602
 
 
603
 
void Cursor::ha_release_auto_increment()
 
1491
void handler::get_auto_increment(uint64_t ,
 
1492
                                 uint64_t ,
 
1493
                                 uint64_t ,
 
1494
                                 uint64_t *first_value,
 
1495
                                 uint64_t *nb_reserved_values)
 
1496
{
 
1497
  uint64_t nr;
 
1498
  int error;
 
1499
 
 
1500
  (void) extra(HA_EXTRA_KEYREAD);
 
1501
  table->mark_columns_used_by_index_no_reset(table->s->next_number_index);
 
1502
  index_init(table->s->next_number_index, 1);
 
1503
  if (table->s->next_number_keypart == 0)
 
1504
  {                                             // Autoincrement at key-start
 
1505
    error=index_last(table->record[1]);
 
1506
    /*
 
1507
      MySQL implicitely assumes such method does locking (as MySQL decides to
 
1508
      use nr+increment without checking again with the handler, in
 
1509
      handler::update_auto_increment()), so reserves to infinite.
 
1510
    */
 
1511
    *nb_reserved_values= UINT64_MAX;
 
1512
  }
 
1513
  else
 
1514
  {
 
1515
    unsigned char key[MAX_KEY_LENGTH];
 
1516
    key_copy(key, table->record[0],
 
1517
             table->key_info + table->s->next_number_index,
 
1518
             table->s->next_number_key_offset);
 
1519
    error= index_read_map(table->record[1], key,
 
1520
                          make_prev_keypart_map(table->s->next_number_keypart),
 
1521
                          HA_READ_PREFIX_LAST);
 
1522
    /*
 
1523
      MySQL needs to call us for next row: assume we are inserting ("a",null)
 
1524
      here, we return 3, and next this statement will want to insert
 
1525
      ("b",null): there is no reason why ("b",3+1) would be the good row to
 
1526
      insert: maybe it already exists, maybe 3+1 is too large...
 
1527
    */
 
1528
    *nb_reserved_values= 1;
 
1529
  }
 
1530
 
 
1531
  if (error)
 
1532
    nr=1;
 
1533
  else
 
1534
    nr= ((uint64_t) table->next_number_field->
 
1535
         val_int_offset(table->s->rec_buff_length)+1);
 
1536
  index_end();
 
1537
  (void) extra(HA_EXTRA_NO_KEYREAD);
 
1538
  *first_value= nr;
 
1539
}
 
1540
 
 
1541
 
 
1542
void handler::ha_release_auto_increment()
604
1543
{
605
1544
  release_auto_increment();
606
1545
  insert_id_for_cur_row= 0;
612
1551
      this statement used forced auto_increment values if there were some,
613
1552
      wipe them away for other statements.
614
1553
    */
615
 
    getTable()->in_use->auto_inc_intervals_forced.empty();
616
 
  }
617
 
}
618
 
 
619
 
void Cursor::drop_table(const char *)
 
1554
    table->in_use->auto_inc_intervals_forced.empty();
 
1555
  }
 
1556
}
 
1557
 
 
1558
 
 
1559
void handler::print_keydup_error(uint32_t key_nr, const char *msg)
 
1560
{
 
1561
  /* Write the duplicated key in the error message */
 
1562
  char key[MAX_KEY_LENGTH];
 
1563
  String str(key,sizeof(key),system_charset_info);
 
1564
 
 
1565
  if (key_nr == MAX_KEY)
 
1566
  {
 
1567
    /* Key is unknown */
 
1568
    str.copy("", 0, system_charset_info);
 
1569
    my_printf_error(ER_DUP_ENTRY, msg, MYF(0), str.c_ptr(), "*UNKNOWN*");
 
1570
  }
 
1571
  else
 
1572
  {
 
1573
    /* Table is opened and defined at this point */
 
1574
    key_unpack(&str,table,(uint32_t) key_nr);
 
1575
    uint32_t max_length=DRIZZLE_ERRMSG_SIZE-(uint32_t) strlen(msg);
 
1576
    if (str.length() >= max_length)
 
1577
    {
 
1578
      str.length(max_length-4);
 
1579
      str.append(STRING_WITH_LEN("..."));
 
1580
    }
 
1581
    my_printf_error(ER_DUP_ENTRY, msg,
 
1582
                    MYF(0), str.c_ptr(), table->key_info[key_nr].name);
 
1583
  }
 
1584
}
 
1585
 
 
1586
 
 
1587
/**
 
1588
  Print error that we got from handler function.
 
1589
 
 
1590
  @note
 
1591
    In case of delete table it's only safe to use the following parts of
 
1592
    the 'table' structure:
 
1593
    - table->s->path
 
1594
    - table->alias
 
1595
*/
 
1596
void handler::print_error(int error, myf errflag)
 
1597
{
 
1598
  int textno=ER_GET_ERRNO;
 
1599
  switch (error) {
 
1600
  case EACCES:
 
1601
    textno=ER_OPEN_AS_READONLY;
 
1602
    break;
 
1603
  case EAGAIN:
 
1604
    textno=ER_FILE_USED;
 
1605
    break;
 
1606
  case ENOENT:
 
1607
    textno=ER_FILE_NOT_FOUND;
 
1608
    break;
 
1609
  case HA_ERR_KEY_NOT_FOUND:
 
1610
  case HA_ERR_NO_ACTIVE_RECORD:
 
1611
  case HA_ERR_END_OF_FILE:
 
1612
    textno=ER_KEY_NOT_FOUND;
 
1613
    break;
 
1614
  case HA_ERR_WRONG_MRG_TABLE_DEF:
 
1615
    textno=ER_WRONG_MRG_TABLE;
 
1616
    break;
 
1617
  case HA_ERR_FOUND_DUPP_KEY:
 
1618
  {
 
1619
    uint32_t key_nr=get_dup_key(error);
 
1620
    if ((int) key_nr >= 0)
 
1621
    {
 
1622
      print_keydup_error(key_nr, ER(ER_DUP_ENTRY_WITH_KEY_NAME));
 
1623
      return;
 
1624
    }
 
1625
    textno=ER_DUP_KEY;
 
1626
    break;
 
1627
  }
 
1628
  case HA_ERR_FOREIGN_DUPLICATE_KEY:
 
1629
  {
 
1630
    uint32_t key_nr= get_dup_key(error);
 
1631
    if ((int) key_nr >= 0)
 
1632
    {
 
1633
      uint32_t max_length;
 
1634
      /* Write the key in the error message */
 
1635
      char key[MAX_KEY_LENGTH];
 
1636
      String str(key,sizeof(key),system_charset_info);
 
1637
      /* Table is opened and defined at this point */
 
1638
      key_unpack(&str,table,(uint32_t) key_nr);
 
1639
      max_length= (DRIZZLE_ERRMSG_SIZE-
 
1640
                   (uint32_t) strlen(ER(ER_FOREIGN_DUPLICATE_KEY)));
 
1641
      if (str.length() >= max_length)
 
1642
      {
 
1643
        str.length(max_length-4);
 
1644
        str.append(STRING_WITH_LEN("..."));
 
1645
      }
 
1646
      my_error(ER_FOREIGN_DUPLICATE_KEY, MYF(0), table_share->table_name.str,
 
1647
        str.c_ptr(), key_nr+1);
 
1648
      return;
 
1649
    }
 
1650
    textno= ER_DUP_KEY;
 
1651
    break;
 
1652
  }
 
1653
  case HA_ERR_FOUND_DUPP_UNIQUE:
 
1654
    textno=ER_DUP_UNIQUE;
 
1655
    break;
 
1656
  case HA_ERR_RECORD_CHANGED:
 
1657
    textno=ER_CHECKREAD;
 
1658
    break;
 
1659
  case HA_ERR_CRASHED:
 
1660
    textno=ER_NOT_KEYFILE;
 
1661
    break;
 
1662
  case HA_ERR_WRONG_IN_RECORD:
 
1663
    textno= ER_CRASHED_ON_USAGE;
 
1664
    break;
 
1665
  case HA_ERR_CRASHED_ON_USAGE:
 
1666
    textno=ER_CRASHED_ON_USAGE;
 
1667
    break;
 
1668
  case HA_ERR_NOT_A_TABLE:
 
1669
    textno= error;
 
1670
    break;
 
1671
  case HA_ERR_CRASHED_ON_REPAIR:
 
1672
    textno=ER_CRASHED_ON_REPAIR;
 
1673
    break;
 
1674
  case HA_ERR_OUT_OF_MEM:
 
1675
    textno=ER_OUT_OF_RESOURCES;
 
1676
    break;
 
1677
  case HA_ERR_WRONG_COMMAND:
 
1678
    textno=ER_ILLEGAL_HA;
 
1679
    break;
 
1680
  case HA_ERR_OLD_FILE:
 
1681
    textno=ER_OLD_KEYFILE;
 
1682
    break;
 
1683
  case HA_ERR_UNSUPPORTED:
 
1684
    textno=ER_UNSUPPORTED_EXTENSION;
 
1685
    break;
 
1686
  case HA_ERR_RECORD_FILE_FULL:
 
1687
  case HA_ERR_INDEX_FILE_FULL:
 
1688
    textno=ER_RECORD_FILE_FULL;
 
1689
    break;
 
1690
  case HA_ERR_LOCK_WAIT_TIMEOUT:
 
1691
    textno=ER_LOCK_WAIT_TIMEOUT;
 
1692
    break;
 
1693
  case HA_ERR_LOCK_TABLE_FULL:
 
1694
    textno=ER_LOCK_TABLE_FULL;
 
1695
    break;
 
1696
  case HA_ERR_LOCK_DEADLOCK:
 
1697
    textno=ER_LOCK_DEADLOCK;
 
1698
    break;
 
1699
  case HA_ERR_READ_ONLY_TRANSACTION:
 
1700
    textno=ER_READ_ONLY_TRANSACTION;
 
1701
    break;
 
1702
  case HA_ERR_CANNOT_ADD_FOREIGN:
 
1703
    textno=ER_CANNOT_ADD_FOREIGN;
 
1704
    break;
 
1705
  case HA_ERR_ROW_IS_REFERENCED:
 
1706
  {
 
1707
    String str;
 
1708
    get_error_message(error, &str);
 
1709
    my_error(ER_ROW_IS_REFERENCED_2, MYF(0), str.c_ptr_safe());
 
1710
    return;
 
1711
  }
 
1712
  case HA_ERR_NO_REFERENCED_ROW:
 
1713
  {
 
1714
    String str;
 
1715
    get_error_message(error, &str);
 
1716
    my_error(ER_NO_REFERENCED_ROW_2, MYF(0), str.c_ptr_safe());
 
1717
    return;
 
1718
  }
 
1719
  case HA_ERR_TABLE_DEF_CHANGED:
 
1720
    textno=ER_TABLE_DEF_CHANGED;
 
1721
    break;
 
1722
  case HA_ERR_NO_SUCH_TABLE:
 
1723
    my_error(ER_NO_SUCH_TABLE, MYF(0), table_share->db.str,
 
1724
             table_share->table_name.str);
 
1725
    return;
 
1726
  case HA_ERR_RBR_LOGGING_FAILED:
 
1727
    textno= ER_BINLOG_ROW_LOGGING_FAILED;
 
1728
    break;
 
1729
  case HA_ERR_DROP_INDEX_FK:
 
1730
  {
 
1731
    const char *ptr= "???";
 
1732
    uint32_t key_nr= get_dup_key(error);
 
1733
    if ((int) key_nr >= 0)
 
1734
      ptr= table->key_info[key_nr].name;
 
1735
    my_error(ER_DROP_INDEX_FK, MYF(0), ptr);
 
1736
    return;
 
1737
  }
 
1738
  case HA_ERR_TABLE_NEEDS_UPGRADE:
 
1739
    textno=ER_TABLE_NEEDS_UPGRADE;
 
1740
    break;
 
1741
  case HA_ERR_TABLE_READONLY:
 
1742
    textno= ER_OPEN_AS_READONLY;
 
1743
    break;
 
1744
  case HA_ERR_AUTOINC_READ_FAILED:
 
1745
    textno= ER_AUTOINC_READ_FAILED;
 
1746
    break;
 
1747
  case HA_ERR_AUTOINC_ERANGE:
 
1748
    textno= ER_WARN_DATA_OUT_OF_RANGE;
 
1749
    break;
 
1750
  case HA_ERR_LOCK_OR_ACTIVE_TRANSACTION:
 
1751
    my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
 
1752
               ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
 
1753
    return;
 
1754
  default:
 
1755
    {
 
1756
      /* The error was "unknown" to this function.
 
1757
         Ask handler if it has got a message for this error */
 
1758
      bool temporary= false;
 
1759
      String str;
 
1760
      temporary= get_error_message(error, &str);
 
1761
      if (!str.is_empty())
 
1762
      {
 
1763
        const char* engine_name= engine->getName().c_str();
 
1764
        if (temporary)
 
1765
          my_error(ER_GET_TEMPORARY_ERRMSG, MYF(0), error, str.ptr(),
 
1766
                   engine_name);
 
1767
        else
 
1768
          my_error(ER_GET_ERRMSG, MYF(0), error, str.ptr(), engine_name);
 
1769
      }
 
1770
      else
 
1771
      {
 
1772
              my_error(ER_GET_ERRNO,errflag,error);
 
1773
      }
 
1774
      return;
 
1775
    }
 
1776
  }
 
1777
  my_error(textno, errflag, table_share->table_name.str, error);
 
1778
}
 
1779
 
 
1780
 
 
1781
/**
 
1782
  Return an error message specific to this handler.
 
1783
 
 
1784
  @param error  error code previously returned by handler
 
1785
  @param buf    pointer to String where to add error message
 
1786
 
 
1787
  @return
 
1788
    Returns true if this is a temporary error
 
1789
*/
 
1790
bool handler::get_error_message(int , String* )
 
1791
{
 
1792
  return false;
 
1793
}
 
1794
 
 
1795
 
 
1796
/* Code left, but Drizzle has no legacy yet (while MySQL did) */
 
1797
int handler::check_old_types()
 
1798
{
 
1799
  return 0;
 
1800
}
 
1801
 
 
1802
/**
 
1803
  @return
 
1804
    key if error because of duplicated keys
 
1805
*/
 
1806
uint32_t handler::get_dup_key(int error)
 
1807
{
 
1808
  table->file->errkey  = (uint32_t) -1;
 
1809
  if (error == HA_ERR_FOUND_DUPP_KEY || error == HA_ERR_FOREIGN_DUPLICATE_KEY ||
 
1810
      error == HA_ERR_FOUND_DUPP_UNIQUE ||
 
1811
      error == HA_ERR_DROP_INDEX_FK)
 
1812
    info(HA_STATUS_ERRKEY | HA_STATUS_NO_LOCK);
 
1813
  return(table->file->errkey);
 
1814
}
 
1815
 
 
1816
void handler::drop_table(const char *name)
620
1817
{
621
1818
  close();
 
1819
  engine->deleteTable(ha_session(), name);
622
1820
}
623
1821
 
624
1822
 
637
1835
  @retval
638
1836
    HA_ADMIN_NOT_IMPLEMENTED
639
1837
*/
640
 
int Cursor::ha_check(Session *, HA_CHECK_OPT *)
 
1838
int handler::ha_check(Session *, HA_CHECK_OPT *)
641
1839
{
642
1840
  return HA_ADMIN_OK;
643
1841
}
649
1847
 
650
1848
inline
651
1849
void
652
 
Cursor::setTransactionReadWrite()
 
1850
handler::mark_trx_read_write()
653
1851
{
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());
 
1852
  Ha_trx_info *ha_info= &ha_session()->ha_data[engine->getSlot()].ha_info[0];
665
1853
  /*
666
1854
    When a storage engine method is called, the transaction must
667
1855
    have been started, unless it's a DDL call, for which the
670
1858
    Unfortunately here we can't know know for sure if the engine
671
1859
    has registered the transaction or not, so we must check.
672
1860
  */
673
 
  if (resource_context->isStarted())
 
1861
  if (ha_info->is_started())
674
1862
  {
675
 
    resource_context->markModifiedData();
 
1863
    /*
 
1864
      table_share can be NULL in ha_delete_table(). See implementation
 
1865
      of standalone function ha_delete_table() in sql_base.cc.
 
1866
    */
 
1867
//    if (table_share == NULL || table_share->tmp_table == NO_TMP_TABLE)
 
1868
      ha_info->set_trx_read_write();
676
1869
  }
677
1870
}
678
1871
 
679
1872
 
680
1873
/**
 
1874
  Repair table: public interface.
 
1875
 
 
1876
  @sa handler::repair()
 
1877
*/
 
1878
 
 
1879
int handler::ha_repair(Session* session, HA_CHECK_OPT* check_opt)
 
1880
{
 
1881
  int result;
 
1882
 
 
1883
  mark_trx_read_write();
 
1884
 
 
1885
  if ((result= repair(session, check_opt)))
 
1886
    return result;
 
1887
  return HA_ADMIN_OK;
 
1888
}
 
1889
 
 
1890
 
 
1891
/**
 
1892
  Bulk update row: public interface.
 
1893
 
 
1894
  @sa handler::bulk_update_row()
 
1895
*/
 
1896
 
 
1897
int
 
1898
handler::ha_bulk_update_row(const unsigned char *old_data, unsigned char *new_data,
 
1899
                            uint32_t *dup_key_found)
 
1900
{
 
1901
  mark_trx_read_write();
 
1902
 
 
1903
  return bulk_update_row(old_data, new_data, dup_key_found);
 
1904
}
 
1905
 
 
1906
 
 
1907
/**
681
1908
  Delete all rows: public interface.
682
1909
 
683
 
  @sa Cursor::delete_all_rows()
684
 
 
685
 
  @note
686
 
 
687
 
  This is now equalivalent to TRUNCATE TABLE.
 
1910
  @sa handler::delete_all_rows()
688
1911
*/
689
1912
 
690
1913
int
691
 
Cursor::ha_delete_all_rows()
 
1914
handler::ha_delete_all_rows()
692
1915
{
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;
 
1916
  mark_trx_read_write();
 
1917
 
 
1918
  return delete_all_rows();
711
1919
}
712
1920
 
713
1921
 
714
1922
/**
715
1923
  Reset auto increment: public interface.
716
1924
 
717
 
  @sa Cursor::reset_auto_increment()
 
1925
  @sa handler::reset_auto_increment()
718
1926
*/
719
1927
 
720
1928
int
721
 
Cursor::ha_reset_auto_increment(uint64_t value)
 
1929
handler::ha_reset_auto_increment(uint64_t value)
722
1930
{
723
 
  setTransactionReadWrite();
 
1931
  mark_trx_read_write();
724
1932
 
725
1933
  return reset_auto_increment(value);
726
1934
}
727
1935
 
728
1936
 
729
1937
/**
 
1938
  Optimize table: public interface.
 
1939
 
 
1940
  @sa handler::optimize()
 
1941
*/
 
1942
 
 
1943
int
 
1944
handler::ha_optimize(Session* session, HA_CHECK_OPT* check_opt)
 
1945
{
 
1946
  mark_trx_read_write();
 
1947
 
 
1948
  return optimize(session, check_opt);
 
1949
}
 
1950
 
 
1951
 
 
1952
/**
730
1953
  Analyze table: public interface.
731
1954
 
732
 
  @sa Cursor::analyze()
 
1955
  @sa handler::analyze()
733
1956
*/
734
1957
 
735
1958
int
736
 
Cursor::ha_analyze(Session* session, HA_CHECK_OPT*)
737
 
{
738
 
  setTransactionReadWrite();
739
 
 
740
 
  return analyze(session);
741
 
}
 
1959
handler::ha_analyze(Session* session, HA_CHECK_OPT* check_opt)
 
1960
{
 
1961
  mark_trx_read_write();
 
1962
 
 
1963
  return analyze(session, check_opt);
 
1964
}
 
1965
 
 
1966
 
 
1967
/**
 
1968
  Check and repair table: public interface.
 
1969
 
 
1970
  @sa handler::check_and_repair()
 
1971
*/
 
1972
 
 
1973
bool
 
1974
handler::ha_check_and_repair(Session *session)
 
1975
{
 
1976
  mark_trx_read_write();
 
1977
 
 
1978
  return check_and_repair(session);
 
1979
}
 
1980
 
742
1981
 
743
1982
/**
744
1983
  Disable indexes: public interface.
745
1984
 
746
 
  @sa Cursor::disable_indexes()
 
1985
  @sa handler::disable_indexes()
747
1986
*/
748
1987
 
749
1988
int
750
 
Cursor::ha_disable_indexes(uint32_t mode)
 
1989
handler::ha_disable_indexes(uint32_t mode)
751
1990
{
752
 
  setTransactionReadWrite();
 
1991
  mark_trx_read_write();
753
1992
 
754
1993
  return disable_indexes(mode);
755
1994
}
758
1997
/**
759
1998
  Enable indexes: public interface.
760
1999
 
761
 
  @sa Cursor::enable_indexes()
 
2000
  @sa handler::enable_indexes()
762
2001
*/
763
2002
 
764
2003
int
765
 
Cursor::ha_enable_indexes(uint32_t mode)
 
2004
handler::ha_enable_indexes(uint32_t mode)
766
2005
{
767
 
  setTransactionReadWrite();
 
2006
  mark_trx_read_write();
768
2007
 
769
2008
  return enable_indexes(mode);
770
2009
}
773
2012
/**
774
2013
  Discard or import tablespace: public interface.
775
2014
 
776
 
  @sa Cursor::discard_or_import_tablespace()
 
2015
  @sa handler::discard_or_import_tablespace()
777
2016
*/
778
2017
 
779
2018
int
780
 
Cursor::ha_discard_or_import_tablespace(bool discard)
 
2019
handler::ha_discard_or_import_tablespace(bool discard)
781
2020
{
782
 
  setTransactionReadWrite();
 
2021
  mark_trx_read_write();
783
2022
 
784
2023
  return discard_or_import_tablespace(discard);
785
2024
}
786
2025
 
 
2026
 
 
2027
/**
 
2028
  Prepare for alter: public interface.
 
2029
 
 
2030
  Called to prepare an *online* ALTER.
 
2031
 
 
2032
  @sa handler::prepare_for_alter()
 
2033
*/
 
2034
 
 
2035
void
 
2036
handler::ha_prepare_for_alter()
 
2037
{
 
2038
  mark_trx_read_write();
 
2039
 
 
2040
  prepare_for_alter();
 
2041
}
 
2042
 
787
2043
/**
788
2044
  Drop table in the engine: public interface.
789
2045
 
790
 
  @sa Cursor::drop_table()
 
2046
  @sa handler::drop_table()
791
2047
*/
792
2048
 
793
2049
void
794
 
Cursor::closeMarkForDelete(const char *name)
 
2050
handler::ha_drop_table(const char *name)
795
2051
{
796
 
  setTransactionReadWrite();
 
2052
  mark_trx_read_write();
797
2053
 
798
2054
  return drop_table(name);
799
2055
}
800
2056
 
801
 
int Cursor::index_next_same(unsigned char *buf, const unsigned char *key, uint32_t keylen)
 
2057
/**
 
2058
  Tell the storage engine that it is allowed to "disable transaction" in the
 
2059
  handler. It is a hint that ACID is not required - it is used in NDB for
 
2060
  ALTER Table, for example, when data are copied to temporary table.
 
2061
  A storage engine may treat this hint any way it likes. NDB for example
 
2062
  starts to commit every now and then automatically.
 
2063
  This hint can be safely ignored.
 
2064
*/
 
2065
int ha_enable_transaction(Session *session, bool on)
 
2066
{
 
2067
  int error= 0;
 
2068
 
 
2069
  if ((session->transaction.on= on))
 
2070
  {
 
2071
    /*
 
2072
      Now all storage engines should have transaction handling enabled.
 
2073
      But some may have it enabled all the time - "disabling" transactions
 
2074
      is an optimization hint that storage engine is free to ignore.
 
2075
      So, let's commit an open transaction (if any) now.
 
2076
    */
 
2077
    if (!(error= ha_commit_trans(session, 0)))
 
2078
      if (! session->endTransaction(COMMIT))
 
2079
        error= 1;
 
2080
 
 
2081
  }
 
2082
  return error;
 
2083
}
 
2084
 
 
2085
int handler::index_next_same(unsigned char *buf, const unsigned char *key, uint32_t keylen)
802
2086
{
803
2087
  int error;
804
2088
  if (!(error=index_next(buf)))
805
2089
  {
806
 
    ptrdiff_t ptrdiff= buf - getTable()->getInsertRecord();
 
2090
    my_ptrdiff_t ptrdiff= buf - table->record[0];
807
2091
    unsigned char *save_record_0= NULL;
808
 
    KeyInfo *key_info= NULL;
809
 
    KeyPartInfo *key_part;
810
 
    KeyPartInfo *key_part_end= NULL;
 
2092
    KEY *key_info= NULL;
 
2093
    KEY_PART_INFO *key_part;
 
2094
    KEY_PART_INFO *key_part_end= NULL;
811
2095
 
812
2096
    /*
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
 
2097
      key_cmp_if_same() compares table->record[0] against 'key'.
 
2098
      In parts it uses table->record[0] directly, in parts it uses
 
2099
      field objects with their local pointers into table->record[0].
 
2100
      If 'buf' is distinct from table->record[0], we need to move
 
2101
      all record references. This is table->record[0] itself and
818
2102
      the field pointers of the fields used in this key.
819
2103
    */
820
2104
    if (ptrdiff)
821
2105
    {
822
 
      save_record_0= getTable()->getInsertRecord();
823
 
      getTable()->record[0]= buf;
824
 
      key_info= getTable()->key_info + active_index;
 
2106
      save_record_0= table->record[0];
 
2107
      table->record[0]= buf;
 
2108
      key_info= table->key_info + active_index;
825
2109
      key_part= key_info->key_part;
826
2110
      key_part_end= key_part + key_info->key_parts;
827
2111
      for (; key_part < key_part_end; key_part++)
831
2115
      }
832
2116
    }
833
2117
 
834
 
    if (key_cmp_if_same(getTable(), key, active_index, keylen))
 
2118
    if (key_cmp_if_same(table, key, active_index, keylen))
835
2119
    {
836
 
      getTable()->status=STATUS_NOT_FOUND;
 
2120
      table->status=STATUS_NOT_FOUND;
837
2121
      error=HA_ERR_END_OF_FILE;
838
2122
    }
839
2123
 
840
2124
    /* Move back if necessary. */
841
2125
    if (ptrdiff)
842
2126
    {
843
 
      getTable()->record[0]= save_record_0;
 
2127
      table->record[0]= save_record_0;
844
2128
      for (key_part= key_info->key_part; key_part < key_part_end; key_part++)
845
2129
        key_part->field->move_field_offset(-ptrdiff);
846
2130
    }
850
2134
 
851
2135
 
852
2136
/****************************************************************************
853
 
** Some general functions that isn't in the Cursor class
 
2137
** Some general functions that isn't in the handler class
854
2138
****************************************************************************/
855
2139
 
 
2140
 
 
2141
void st_ha_check_opt::init()
 
2142
{
 
2143
  flags= 0; 
 
2144
  use_frm= false;
 
2145
}
 
2146
 
 
2147
 
 
2148
/*****************************************************************************
 
2149
  Key cache handling.
 
2150
 
 
2151
  This code is only relevant for ISAM/MyISAM tables
 
2152
 
 
2153
  key_cache->cache may be 0 only in the case where a key cache is not
 
2154
  initialized or when we where not able to init the key cache in a previous
 
2155
  call to ha_init_key_cache() (probably out of memory)
 
2156
*****************************************************************************/
 
2157
 
 
2158
/**
 
2159
  Init a key cache if it has not been initied before.
 
2160
*/
 
2161
int ha_init_key_cache(const char *,
 
2162
                      KEY_CACHE *key_cache)
 
2163
{
 
2164
  if (!key_cache->key_cache_inited)
 
2165
  {
 
2166
    pthread_mutex_lock(&LOCK_global_system_variables);
 
2167
    uint32_t tmp_buff_size= (uint32_t) key_cache->param_buff_size;
 
2168
    uint32_t tmp_block_size= (uint32_t) key_cache->param_block_size;
 
2169
    uint32_t division_limit= key_cache->param_division_limit;
 
2170
    uint32_t age_threshold=  key_cache->param_age_threshold;
 
2171
    pthread_mutex_unlock(&LOCK_global_system_variables);
 
2172
    return(!init_key_cache(key_cache,
 
2173
                                tmp_block_size,
 
2174
                                tmp_buff_size,
 
2175
                                division_limit, age_threshold));
 
2176
  }
 
2177
  return 0;
 
2178
}
 
2179
 
 
2180
 
 
2181
/**
 
2182
  Resize key cache.
 
2183
*/
 
2184
int ha_resize_key_cache(KEY_CACHE *key_cache)
 
2185
{
 
2186
  if (key_cache->key_cache_inited)
 
2187
  {
 
2188
    pthread_mutex_lock(&LOCK_global_system_variables);
 
2189
    long tmp_buff_size= (long) key_cache->param_buff_size;
 
2190
    long tmp_block_size= (long) key_cache->param_block_size;
 
2191
    uint32_t division_limit= key_cache->param_division_limit;
 
2192
    uint32_t age_threshold=  key_cache->param_age_threshold;
 
2193
    pthread_mutex_unlock(&LOCK_global_system_variables);
 
2194
    return(!resize_key_cache(key_cache, tmp_block_size,
 
2195
                                  tmp_buff_size,
 
2196
                                  division_limit, age_threshold));
 
2197
  }
 
2198
  return 0;
 
2199
}
 
2200
 
 
2201
 
 
2202
/**
 
2203
  Change parameters for key cache (like size)
 
2204
*/
 
2205
int ha_change_key_cache_param(KEY_CACHE *key_cache)
 
2206
{
 
2207
  if (key_cache->key_cache_inited)
 
2208
  {
 
2209
    pthread_mutex_lock(&LOCK_global_system_variables);
 
2210
    uint32_t division_limit= key_cache->param_division_limit;
 
2211
    uint32_t age_threshold=  key_cache->param_age_threshold;
 
2212
    pthread_mutex_unlock(&LOCK_global_system_variables);
 
2213
    change_key_cache_param(key_cache, division_limit, age_threshold);
 
2214
  }
 
2215
  return 0;
 
2216
}
 
2217
 
 
2218
/**
 
2219
  Free memory allocated by a key cache.
 
2220
*/
 
2221
int ha_end_key_cache(KEY_CACHE *key_cache)
 
2222
{
 
2223
  end_key_cache(key_cache, 1);          // Can never fail
 
2224
  return 0;
 
2225
}
 
2226
 
 
2227
/**
 
2228
  Move all tables from one key cache to another one.
 
2229
*/
 
2230
int ha_change_key_cache(KEY_CACHE *old_key_cache,
 
2231
                        KEY_CACHE *new_key_cache)
 
2232
{
 
2233
  mi_change_key_cache(old_key_cache, new_key_cache);
 
2234
  return 0;
 
2235
}
 
2236
 
 
2237
 
856
2238
/**
857
2239
  Calculate cost of 'index only' scan for given index and number of records
858
2240
 
862
2244
  @note
863
2245
    It is assumed that we will read trough the whole key range and that all
864
2246
    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
 
2247
    assumed that each time we read the next key from the index, the handler
866
2248
    performs a random seek, thus the cost is proportional to the number of
867
2249
    blocks read.
868
2250
 
869
2251
  @todo
870
 
    Consider joining this function and Cursor::read_time() into one
871
 
    Cursor::read_time(keynr, records, ranges, bool index_only) function.
 
2252
    Consider joining this function and handler::read_time() into one
 
2253
    handler::read_time(keynr, records, ranges, bool index_only) function.
872
2254
 
873
2255
  @return
874
2256
    Estimated cost of 'index only' scan
875
2257
*/
876
2258
 
877
 
double Cursor::index_only_read_time(uint32_t keynr, double key_records)
 
2259
double handler::index_only_read_time(uint32_t keynr, double key_records)
878
2260
{
879
2261
  uint32_t keys_per_block= (stats.block_size/2/
880
 
                        (getTable()->key_info[keynr].key_length + ref_length) + 1);
 
2262
                        (table->key_info[keynr].key_length + ref_length) + 1);
881
2263
  return ((double) (key_records + keys_per_block-1) /
882
2264
          (double) keys_per_block);
883
2265
}
906
2288
 
907
2289
  @note
908
2290
    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
 
2291
    session->killed and return HA_POS_ERROR if it is not zero. This is required
910
2292
    for a user to be able to interrupt the calculation by killing the
911
2293
    connection/query.
912
2294
 
919
2301
*/
920
2302
 
921
2303
ha_rows
922
 
Cursor::multi_range_read_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
 
2304
handler::multi_range_read_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
923
2305
                                     void *seq_init_param,
924
2306
                                     uint32_t ,
925
 
                                     uint32_t *bufsz, uint32_t *flags, optimizer::CostVector *cost)
 
2307
                                     uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
926
2308
{
927
2309
  KEY_MULTI_RANGE range;
928
2310
  range_seq_t seq_it;
929
2311
  ha_rows rows, total_rows= 0;
930
2312
  uint32_t n_ranges=0;
 
2313
  Session *session= current_session;
931
2314
 
932
2315
  /* Default MRR implementation doesn't need buffer */
933
2316
  *bufsz= 0;
935
2318
  seq_it= seq->init(seq_init_param, n_ranges, *flags);
936
2319
  while (!seq->next(seq_it, &range))
937
2320
  {
 
2321
    if (unlikely(session->killed != 0))
 
2322
      return HA_POS_ERROR;
 
2323
 
938
2324
    n_ranges++;
939
2325
    key_range *min_endp, *max_endp;
940
2326
    {
961
2347
    /* The following calculation is the same as in multi_range_read_info(): */
962
2348
    *flags |= HA_MRR_USE_DEFAULT_IMPL;
963
2349
    cost->zero();
964
 
    cost->setAvgIOCost(1); /* assume random seeks */
 
2350
    cost->avg_io_cost= 1; /* assume random seeks */
965
2351
    if ((*flags & HA_MRR_INDEX_ONLY) && total_rows > 2)
966
 
      cost->setIOCount(index_only_read_time(keyno, (uint32_t)total_rows));
 
2352
      cost->io_count= index_only_read_time(keyno, (uint32_t)total_rows);
967
2353
    else
968
 
      cost->setIOCount(read_time(keyno, n_ranges, total_rows));
969
 
    cost->setCpuCost((double) total_rows / TIME_FOR_COMPARE + 0.01);
 
2354
      cost->io_count= read_time(keyno, n_ranges, total_rows);
 
2355
    cost->cpu_cost= (double) total_rows / TIME_FOR_COMPARE + 0.01;
970
2356
  }
971
2357
  return total_rows;
972
2358
}
1006
2392
    other Error or can't perform the requested scan
1007
2393
*/
1008
2394
 
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)
 
2395
int handler::multi_range_read_info(uint32_t keyno, uint32_t n_ranges, uint32_t n_rows,
 
2396
                                   uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
1011
2397
{
1012
2398
  *bufsz= 0; /* Default implementation doesn't need a buffer */
1013
2399
 
1014
2400
  *flags |= HA_MRR_USE_DEFAULT_IMPL;
1015
2401
 
1016
2402
  cost->zero();
1017
 
  cost->setAvgIOCost(1); /* assume random seeks */
 
2403
  cost->avg_io_cost= 1; /* assume random seeks */
1018
2404
 
1019
2405
  /* Produce the same cost as non-MRR code does */
1020
2406
  if (*flags & HA_MRR_INDEX_ONLY)
1021
 
    cost->setIOCount(index_only_read_time(keyno, n_rows));
 
2407
    cost->io_count= index_only_read_time(keyno, n_rows);
1022
2408
  else
1023
 
    cost->setIOCount(read_time(keyno, n_ranges, n_rows));
 
2409
    cost->io_count= read_time(keyno, n_ranges, n_rows);
1024
2410
  return 0;
1025
2411
}
1026
2412
 
1044
2430
  @param buf             INOUT: memory buffer to be used
1045
2431
 
1046
2432
  @note
1047
 
    One must have called doStartIndexScan() before calling this function. Several
 
2433
    One must have called index_init() before calling this function. Several
1048
2434
    multi_range_read_init() calls may be made in course of one query.
1049
2435
 
1050
2436
    Until WL#2623 is done (see its text, section 3.2), the following will
1051
2437
    also hold:
1052
2438
    The caller will guarantee that if "seq->init == mrr_ranges_array_init"
1053
2439
    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.
 
2440
    This property will only be used by NDB handler until WL#2623 is done.
1055
2441
 
1056
2442
    Buffer memory management is done according to the following scenario:
1057
2443
    The caller allocates the buffer and provides it to the callee by filling
1059
2445
    The callee consumes all or some fraction of the provided buffer space, and
1060
2446
    sets the HANDLER_BUFFER members accordingly.
1061
2447
    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
 
2448
    call is made, all records have been read, or until index_end() call is
1063
2449
    made, whichever comes first.
1064
2450
 
1065
2451
  @retval 0  OK
1067
2453
*/
1068
2454
 
1069
2455
int
1070
 
Cursor::multi_range_read_init(RANGE_SEQ_IF *seq_funcs, void *seq_init_param,
1071
 
                               uint32_t n_ranges, uint32_t mode)
 
2456
handler::multi_range_read_init(RANGE_SEQ_IF *seq_funcs, void *seq_init_param,
 
2457
                               uint32_t n_ranges, uint32_t mode,
 
2458
                               HANDLER_BUFFER *)
1072
2459
{
1073
2460
  mrr_iter= seq_funcs->init(seq_init_param, n_ranges, mode);
1074
2461
  mrr_funcs= *seq_funcs;
1075
2462
  mrr_is_output_sorted= test(mode & HA_MRR_SORTED);
1076
2463
  mrr_have_range= false;
1077
 
 
1078
2464
  return 0;
1079
2465
}
1080
2466
 
1092
2478
  @retval other  Error code
1093
2479
*/
1094
2480
 
1095
 
int Cursor::multi_range_read_next(char **range_info)
 
2481
int handler::multi_range_read_next(char **range_info)
1096
2482
{
1097
2483
  int result= 0;
1098
2484
  int range_res= 0;
1099
2485
 
1100
 
  if (not mrr_have_range)
 
2486
  if (!mrr_have_range)
1101
2487
  {
1102
2488
    mrr_have_range= true;
1103
2489
    goto start;
1147
2533
 
1148
2534
 
1149
2535
/* **************************************************************************
 
2536
 * DS-MRR implementation
 
2537
 ***************************************************************************/
 
2538
 
 
2539
/**
 
2540
  DS-MRR: Initialize and start MRR scan
 
2541
 
 
2542
  Initialize and start the MRR scan. Depending on the mode parameter, this
 
2543
  may use default or DS-MRR implementation.
 
2544
 
 
2545
  @param h               Table handler to be used
 
2546
  @param key             Index to be used
 
2547
  @param seq_funcs       Interval sequence enumeration functions
 
2548
  @param seq_init_param  Interval sequence enumeration parameter
 
2549
  @param n_ranges        Number of ranges in the sequence.
 
2550
  @param mode            HA_MRR_* modes to use
 
2551
  @param buf             INOUT Buffer to use
 
2552
 
 
2553
  @retval 0     Ok, Scan started.
 
2554
  @retval other Error
 
2555
*/
 
2556
 
 
2557
int DsMrr_impl::dsmrr_init(handler *h_in, KEY *key,
 
2558
                           RANGE_SEQ_IF *seq_funcs, void *seq_init_param,
 
2559
                           uint32_t n_ranges, uint32_t mode, HANDLER_BUFFER *buf)
 
2560
{
 
2561
  uint32_t elem_size;
 
2562
  uint32_t keyno;
 
2563
  Item *pushed_cond= NULL;
 
2564
  handler *new_h2;
 
2565
  keyno= h_in->active_index;
 
2566
  assert(h2 == NULL);
 
2567
  if (mode & HA_MRR_USE_DEFAULT_IMPL || mode & HA_MRR_SORTED)
 
2568
  {
 
2569
    use_default_impl= true;
 
2570
    return(h_in->handler::multi_range_read_init(seq_funcs, seq_init_param,
 
2571
                                                  n_ranges, mode, buf));
 
2572
  }
 
2573
  rowids_buf= buf->buffer;
 
2574
  //psergey-todo: don't add key_length as it is not needed anymore
 
2575
  rowids_buf += key->key_length + h_in->ref_length;
 
2576
 
 
2577
  is_mrr_assoc= !test(mode & HA_MRR_NO_ASSOCIATION);
 
2578
  rowids_buf_end= buf->buffer_end;
 
2579
 
 
2580
  elem_size= h_in->ref_length + (int)is_mrr_assoc * sizeof(void*);
 
2581
  rowids_buf_last= rowids_buf +
 
2582
                      ((rowids_buf_end - rowids_buf)/ elem_size)*
 
2583
                      elem_size;
 
2584
  rowids_buf_end= rowids_buf_last;
 
2585
 
 
2586
  /* Create a separate handler object to do rndpos() calls. */
 
2587
  Session *session= current_session;
 
2588
  if (!(new_h2= h_in->clone(session->mem_root)) ||
 
2589
      new_h2->ha_external_lock(session, F_RDLCK))
 
2590
  {
 
2591
    delete new_h2;
 
2592
    return 1;
 
2593
  }
 
2594
 
 
2595
  if (keyno == h_in->pushed_idx_cond_keyno)
 
2596
    pushed_cond= h_in->pushed_idx_cond;
 
2597
  if (h_in->ha_index_end())
 
2598
  {
 
2599
    new_h2= h2;
 
2600
    goto error;
 
2601
  }
 
2602
 
 
2603
  h2= new_h2;
 
2604
  table->prepare_for_position();
 
2605
  new_h2->extra(HA_EXTRA_KEYREAD);
 
2606
 
 
2607
  if (h2->ha_index_init(keyno, false) ||
 
2608
      h2->handler::multi_range_read_init(seq_funcs, seq_init_param, n_ranges,
 
2609
                                         mode, buf))
 
2610
    goto error;
 
2611
  use_default_impl= false;
 
2612
 
 
2613
  if (pushed_cond)
 
2614
    h2->idx_cond_push(keyno, pushed_cond);
 
2615
  if (dsmrr_fill_buffer(new_h2))
 
2616
    goto error;
 
2617
 
 
2618
  /*
 
2619
    If the above call has scanned through all intervals in *seq, then
 
2620
    adjust *buf to indicate that the remaining buffer space will not be used.
 
2621
  */
 
2622
  if (dsmrr_eof)
 
2623
    buf->end_of_used_area= rowids_buf_last;
 
2624
 
 
2625
  if (h_in->ha_rnd_init(false))
 
2626
    goto error;
 
2627
 
 
2628
  return 0;
 
2629
error:
 
2630
  h2->ha_index_or_rnd_end();
 
2631
  h2->ha_external_lock(session, F_UNLCK);
 
2632
  h2->close();
 
2633
  delete h2;
 
2634
  return 1;
 
2635
}
 
2636
 
 
2637
 
 
2638
void DsMrr_impl::dsmrr_close()
 
2639
{
 
2640
  if (h2)
 
2641
  {
 
2642
    h2->ha_external_lock(current_session, F_UNLCK);
 
2643
    h2->close();
 
2644
    delete h2;
 
2645
    h2= NULL;
 
2646
  }
 
2647
  use_default_impl= true;
 
2648
}
 
2649
 
 
2650
 
 
2651
static int rowid_cmp(void *h, unsigned char *a, unsigned char *b)
 
2652
{
 
2653
  return ((handler*)h)->cmp_ref(a, b);
 
2654
}
 
2655
 
 
2656
 
 
2657
/**
 
2658
  DS-MRR: Fill the buffer with rowids and sort it by rowid
 
2659
 
 
2660
  {This is an internal function of DiskSweep MRR implementation}
 
2661
  Scan the MRR ranges and collect ROWIDs (or {ROWID, range_id} pairs) into
 
2662
  buffer. When the buffer is full or scan is completed, sort the buffer by
 
2663
  rowid and return.
 
2664
 
 
2665
  The function assumes that rowids buffer is empty when it is invoked.
 
2666
 
 
2667
  @param h  Table handler
 
2668
 
 
2669
  @retval 0      OK, the next portion of rowids is in the buffer,
 
2670
                 properly ordered
 
2671
  @retval other  Error
 
2672
*/
 
2673
 
 
2674
int DsMrr_impl::dsmrr_fill_buffer(handler *)
 
2675
{
 
2676
  char *range_info;
 
2677
  int res = 0;
 
2678
 
 
2679
  rowids_buf_cur= rowids_buf;
 
2680
  while ((rowids_buf_cur < rowids_buf_end) &&
 
2681
         !(res= h2->handler::multi_range_read_next(&range_info)))
 
2682
  {
 
2683
    /* Put rowid, or {rowid, range_id} pair into the buffer */
 
2684
    h2->position(table->record[0]);
 
2685
    memcpy(rowids_buf_cur, h2->ref, h2->ref_length);
 
2686
    rowids_buf_cur += h->ref_length;
 
2687
 
 
2688
    if (is_mrr_assoc)
 
2689
    {
 
2690
      memcpy(rowids_buf_cur, &range_info, sizeof(void*));
 
2691
      rowids_buf_cur += sizeof(void*);
 
2692
    }
 
2693
  }
 
2694
 
 
2695
  if (res && res != HA_ERR_END_OF_FILE)
 
2696
    return res;
 
2697
  dsmrr_eof= test(res == HA_ERR_END_OF_FILE);
 
2698
 
 
2699
  /* Sort the buffer contents by rowid */
 
2700
  uint32_t elem_size= h->ref_length + (int)is_mrr_assoc * sizeof(void*);
 
2701
  uint32_t n_rowids= (rowids_buf_cur - rowids_buf) / elem_size;
 
2702
 
 
2703
  my_qsort2(rowids_buf, n_rowids, elem_size, (qsort2_cmp)rowid_cmp,
 
2704
            (void*)h);
 
2705
  rowids_buf_last= rowids_buf_cur;
 
2706
  rowids_buf_cur=  rowids_buf;
 
2707
  return 0;
 
2708
}
 
2709
 
 
2710
 
 
2711
/**
 
2712
  DS-MRR implementation: multi_range_read_next() function
 
2713
*/
 
2714
 
 
2715
int DsMrr_impl::dsmrr_next(handler *h_in, char **range_info)
 
2716
{
 
2717
  int res;
 
2718
 
 
2719
  if (use_default_impl)
 
2720
    return h_in->handler::multi_range_read_next(range_info);
 
2721
 
 
2722
  if (rowids_buf_cur == rowids_buf_last)
 
2723
  {
 
2724
    if (dsmrr_eof)
 
2725
    {
 
2726
      res= HA_ERR_END_OF_FILE;
 
2727
      goto end;
 
2728
    }
 
2729
    res= dsmrr_fill_buffer(h);
 
2730
    if (res)
 
2731
      goto end;
 
2732
  }
 
2733
 
 
2734
  /* Return EOF if there are no rowids in the buffer after re-fill attempt */
 
2735
  if (rowids_buf_cur == rowids_buf_last)
 
2736
  {
 
2737
    res= HA_ERR_END_OF_FILE;
 
2738
    goto end;
 
2739
  }
 
2740
 
 
2741
  res= h_in->rnd_pos(table->record[0], rowids_buf_cur);
 
2742
  rowids_buf_cur += h_in->ref_length;
 
2743
  if (is_mrr_assoc)
 
2744
  {
 
2745
    memcpy(range_info, rowids_buf_cur, sizeof(void*));
 
2746
    rowids_buf_cur += sizeof(void*);
 
2747
  }
 
2748
 
 
2749
end:
 
2750
  if (res)
 
2751
    dsmrr_close();
 
2752
  return res;
 
2753
}
 
2754
 
 
2755
 
 
2756
/**
 
2757
  DS-MRR implementation: multi_range_read_info() function
 
2758
*/
 
2759
int DsMrr_impl::dsmrr_info(uint32_t keyno, uint32_t n_ranges, uint32_t rows, uint32_t *bufsz,
 
2760
                           uint32_t *flags, COST_VECT *cost)
 
2761
{
 
2762
  int res;
 
2763
  uint32_t def_flags= *flags;
 
2764
  uint32_t def_bufsz= *bufsz;
 
2765
 
 
2766
  /* Get cost/flags/mem_usage of default MRR implementation */
 
2767
  res= h->handler::multi_range_read_info(keyno, n_ranges, rows, &def_bufsz,
 
2768
                                         &def_flags, cost);
 
2769
  assert(!res);
 
2770
 
 
2771
  if ((*flags & HA_MRR_USE_DEFAULT_IMPL) ||
 
2772
      choose_mrr_impl(keyno, rows, &def_flags, &def_bufsz, cost))
 
2773
  {
 
2774
    /* Default implementation is choosen */
 
2775
    *flags= def_flags;
 
2776
    *bufsz= def_bufsz;
 
2777
  }
 
2778
  return 0;
 
2779
}
 
2780
 
 
2781
 
 
2782
/**
 
2783
  DS-MRR Implementation: multi_range_read_info_const() function
 
2784
*/
 
2785
 
 
2786
ha_rows DsMrr_impl::dsmrr_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
 
2787
                                 void *seq_init_param, uint32_t n_ranges,
 
2788
                                 uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
 
2789
{
 
2790
  ha_rows rows;
 
2791
  uint32_t def_flags= *flags;
 
2792
  uint32_t def_bufsz= *bufsz;
 
2793
  /* Get cost/flags/mem_usage of default MRR implementation */
 
2794
  rows= h->handler::multi_range_read_info_const(keyno, seq, seq_init_param,
 
2795
                                                n_ranges, &def_bufsz,
 
2796
                                                &def_flags, cost);
 
2797
  if (rows == HA_POS_ERROR)
 
2798
  {
 
2799
    /* Default implementation can't perform MRR scan => we can't either */
 
2800
    return rows;
 
2801
  }
 
2802
 
 
2803
  /*
 
2804
    If HA_MRR_USE_DEFAULT_IMPL has been passed to us, that is an order to
 
2805
    use the default MRR implementation (we need it for UPDATE/DELETE).
 
2806
    Otherwise, make a choice based on cost and @@optimizer_use_mrr.
 
2807
  */
 
2808
  if ((*flags & HA_MRR_USE_DEFAULT_IMPL) ||
 
2809
      choose_mrr_impl(keyno, rows, flags, bufsz, cost))
 
2810
  {
 
2811
    *flags= def_flags;
 
2812
    *bufsz= def_bufsz;
 
2813
  }
 
2814
  else
 
2815
  {
 
2816
    *flags &= ~HA_MRR_USE_DEFAULT_IMPL;
 
2817
  }
 
2818
  return rows;
 
2819
}
 
2820
 
 
2821
 
 
2822
/**
 
2823
  Check if key has partially-covered columns
 
2824
 
 
2825
  We can't use DS-MRR to perform range scans when the ranges are over
 
2826
  partially-covered keys, because we'll not have full key part values
 
2827
  (we'll have their prefixes from the index) and will not be able to check
 
2828
  if we've reached the end the range.
 
2829
 
 
2830
  @param keyno  Key to check
 
2831
 
 
2832
  @todo
 
2833
    Allow use of DS-MRR in cases where the index has partially-covered
 
2834
    components but they are not used for scanning.
 
2835
 
 
2836
  @retval true   Yes
 
2837
  @retval false  No
 
2838
*/
 
2839
 
 
2840
bool DsMrr_impl::key_uses_partial_cols(uint32_t keyno)
 
2841
{
 
2842
  KEY_PART_INFO *kp= table->key_info[keyno].key_part;
 
2843
  KEY_PART_INFO *kp_end= kp + table->key_info[keyno].key_parts;
 
2844
  for (; kp != kp_end; kp++)
 
2845
  {
 
2846
    if (!kp->field->part_of_key.test(keyno))
 
2847
      return true;
 
2848
  }
 
2849
  return false;
 
2850
}
 
2851
 
 
2852
 
 
2853
/**
 
2854
  DS-MRR Internals: Choose between Default MRR implementation and DS-MRR
 
2855
 
 
2856
  Make the choice between using Default MRR implementation and DS-MRR.
 
2857
  This function contains common functionality factored out of dsmrr_info()
 
2858
  and dsmrr_info_const(). The function assumes that the default MRR
 
2859
  implementation's applicability requirements are satisfied.
 
2860
 
 
2861
  @param keyno       Index number
 
2862
  @param rows        E(full rows to be retrieved)
 
2863
  @param flags  IN   MRR flags provided by the MRR user
 
2864
                OUT  If DS-MRR is choosen, flags of DS-MRR implementation
 
2865
                     else the value is not modified
 
2866
  @param bufsz  IN   If DS-MRR is choosen, buffer use of DS-MRR implementation
 
2867
                     else the value is not modified
 
2868
  @param cost   IN   Cost of default MRR implementation
 
2869
                OUT  If DS-MRR is choosen, cost of DS-MRR scan
 
2870
                     else the value is not modified
 
2871
 
 
2872
  @retval true   Default MRR implementation should be used
 
2873
  @retval false  DS-MRR implementation should be used
 
2874
*/
 
2875
 
 
2876
bool DsMrr_impl::choose_mrr_impl(uint32_t keyno, ha_rows rows, uint32_t *flags,
 
2877
                                 uint32_t *bufsz, COST_VECT *cost)
 
2878
{
 
2879
  COST_VECT dsmrr_cost;
 
2880
  bool res;
 
2881
  Session *session= current_session;
 
2882
  if ((session->variables.optimizer_use_mrr == 2) ||
 
2883
      (*flags & HA_MRR_INDEX_ONLY) || (*flags & HA_MRR_SORTED) ||
 
2884
      (keyno == table->s->primary_key &&
 
2885
       h->primary_key_is_clustered()) ||
 
2886
       key_uses_partial_cols(keyno))
 
2887
  {
 
2888
    /* Use the default implementation */
 
2889
    *flags |= HA_MRR_USE_DEFAULT_IMPL;
 
2890
    return true;
 
2891
  }
 
2892
 
 
2893
  uint32_t add_len= table->key_info[keyno].key_length + h->ref_length;
 
2894
  *bufsz -= add_len;
 
2895
  if (get_disk_sweep_mrr_cost(keyno, rows, *flags, bufsz, &dsmrr_cost))
 
2896
    return true;
 
2897
  *bufsz += add_len;
 
2898
 
 
2899
  bool force_dsmrr;
 
2900
  /*
 
2901
    If @@optimizer_use_mrr==force, then set cost of DS-MRR to be minimum of
 
2902
    DS-MRR and Default implementations cost. This allows one to force use of
 
2903
    DS-MRR whenever it is applicable without affecting other cost-based
 
2904
    choices.
 
2905
  */
 
2906
  if ((force_dsmrr= (session->variables.optimizer_use_mrr == 1)) &&
 
2907
      dsmrr_cost.total_cost() > cost->total_cost())
 
2908
    dsmrr_cost= *cost;
 
2909
 
 
2910
  if (force_dsmrr || dsmrr_cost.total_cost() <= cost->total_cost())
 
2911
  {
 
2912
    *flags &= ~HA_MRR_USE_DEFAULT_IMPL;  /* Use the DS-MRR implementation */
 
2913
    *flags &= ~HA_MRR_SORTED;          /* We will return unordered output */
 
2914
    *cost= dsmrr_cost;
 
2915
    res= false;
 
2916
  }
 
2917
  else
 
2918
  {
 
2919
    /* Use the default MRR implementation */
 
2920
    res= true;
 
2921
  }
 
2922
  return res;
 
2923
}
 
2924
 
 
2925
 
 
2926
static void get_sort_and_sweep_cost(Table *table, ha_rows nrows, COST_VECT *cost);
 
2927
 
 
2928
 
 
2929
/**
 
2930
  Get cost of DS-MRR scan
 
2931
 
 
2932
  @param keynr              Index to be used
 
2933
  @param rows               E(Number of rows to be scanned)
 
2934
  @param flags              Scan parameters (HA_MRR_* flags)
 
2935
  @param buffer_size INOUT  Buffer size
 
2936
  @param cost        OUT    The cost
 
2937
 
 
2938
  @retval false  OK
 
2939
  @retval true   Error, DS-MRR cannot be used (the buffer is too small
 
2940
                 for even 1 rowid)
 
2941
*/
 
2942
 
 
2943
bool DsMrr_impl::get_disk_sweep_mrr_cost(uint32_t keynr, ha_rows rows, uint32_t flags,
 
2944
                                         uint32_t *buffer_size, COST_VECT *cost)
 
2945
{
 
2946
  uint32_t max_buff_entries, elem_size;
 
2947
  ha_rows rows_in_full_step, rows_in_last_step;
 
2948
  uint32_t n_full_steps;
 
2949
  double index_read_cost;
 
2950
 
 
2951
  elem_size= h->ref_length + sizeof(void*) * (!test(flags & HA_MRR_NO_ASSOCIATION));
 
2952
  max_buff_entries = *buffer_size / elem_size;
 
2953
 
 
2954
  if (!max_buff_entries)
 
2955
    return true; /* Buffer has not enough space for even 1 rowid */
 
2956
 
 
2957
  /* Number of iterations we'll make with full buffer */
 
2958
  n_full_steps= (uint32_t)floor(rows2double(rows) / max_buff_entries);
 
2959
 
 
2960
  /*
 
2961
    Get numbers of rows we'll be processing in
 
2962
     - non-last sweep, with full buffer
 
2963
     - last iteration, with non-full buffer
 
2964
  */
 
2965
  rows_in_full_step= max_buff_entries;
 
2966
  rows_in_last_step= rows % max_buff_entries;
 
2967
 
 
2968
  /* Adjust buffer size if we expect to use only part of the buffer */
 
2969
  if (n_full_steps)
 
2970
  {
 
2971
    get_sort_and_sweep_cost(table, rows, cost);
 
2972
    cost->multiply(n_full_steps);
 
2973
  }
 
2974
  else
 
2975
  {
 
2976
    cost->zero();
 
2977
    *buffer_size= cmax((ulong)*buffer_size,
 
2978
                      (size_t)(1.2*rows_in_last_step) * elem_size +
 
2979
                      h->ref_length + table->key_info[keynr].key_length);
 
2980
  }
 
2981
 
 
2982
  COST_VECT last_step_cost;
 
2983
  get_sort_and_sweep_cost(table, rows_in_last_step, &last_step_cost);
 
2984
  cost->add(&last_step_cost);
 
2985
 
 
2986
  if (n_full_steps != 0)
 
2987
    cost->mem_cost= *buffer_size;
 
2988
  else
 
2989
    cost->mem_cost= (double)rows_in_last_step * elem_size;
 
2990
 
 
2991
  /* Total cost of all index accesses */
 
2992
  index_read_cost= h->index_only_read_time(keynr, (double)rows);
 
2993
  cost->add_io(index_read_cost, 1 /* Random seeks */);
 
2994
  return false;
 
2995
}
 
2996
 
 
2997
 
 
2998
/*
 
2999
  Get cost of one sort-and-sweep step
 
3000
 
 
3001
  SYNOPSIS
 
3002
    get_sort_and_sweep_cost()
 
3003
      table       Table being accessed
 
3004
      nrows       Number of rows to be sorted and retrieved
 
3005
      cost   OUT  The cost
 
3006
 
 
3007
  DESCRIPTION
 
3008
    Get cost of these operations:
 
3009
     - sort an array of #nrows ROWIDs using qsort
 
3010
     - read #nrows records from table in a sweep.
 
3011
*/
 
3012
 
 
3013
static
 
3014
void get_sort_and_sweep_cost(Table *table, ha_rows nrows, COST_VECT *cost)
 
3015
{
 
3016
  if (nrows)
 
3017
  {
 
3018
    get_sweep_read_cost(table, nrows, false, cost);
 
3019
    /* Add cost of qsort call: n * log2(n) * cost(rowid_comparison) */
 
3020
    double cmp_op= rows2double(nrows) * (1.0 / TIME_FOR_COMPARE_ROWID);
 
3021
    if (cmp_op < 3)
 
3022
      cmp_op= 3;
 
3023
    cost->cpu_cost += cmp_op * log2(cmp_op);
 
3024
  }
 
3025
  else
 
3026
    cost->zero();
 
3027
}
 
3028
 
 
3029
 
 
3030
/**
 
3031
  Get cost of reading nrows table records in a "disk sweep"
 
3032
 
 
3033
  A disk sweep read is a sequence of handler->rnd_pos(rowid) calls that made
 
3034
  for an ordered sequence of rowids.
 
3035
 
 
3036
  We assume hard disk IO. The read is performed as follows:
 
3037
 
 
3038
   1. The disk head is moved to the needed cylinder
 
3039
   2. The controller waits for the plate to rotate
 
3040
   3. The data is transferred
 
3041
 
 
3042
  Time to do #3 is insignificant compared to #2+#1.
 
3043
 
 
3044
  Time to move the disk head is proportional to head travel distance.
 
3045
 
 
3046
  Time to wait for the plate to rotate depends on whether the disk head
 
3047
  was moved or not.
 
3048
 
 
3049
  If disk head wasn't moved, the wait time is proportional to distance
 
3050
  between the previous block and the block we're reading.
 
3051
 
 
3052
  If the head was moved, we don't know how much we'll need to wait for the
 
3053
  plate to rotate. We assume the wait time to be a variate with a mean of
 
3054
  0.5 of full rotation time.
 
3055
 
 
3056
  Our cost units are "random disk seeks". The cost of random disk seek is
 
3057
  actually not a constant, it depends one range of cylinders we're going
 
3058
  to access. We make it constant by introducing a fuzzy concept of "typical
 
3059
  datafile length" (it's fuzzy as it's hard to tell whether it should
 
3060
  include index file, temp.tables etc). Then random seek cost is:
 
3061
 
 
3062
    1 = half_rotation_cost + move_cost * 1/3 * typical_data_file_length
 
3063
 
 
3064
  We define half_rotation_cost as DISK_SEEK_BASE_COST=0.9.
 
3065
 
 
3066
  @param table             Table to be accessed
 
3067
  @param nrows             Number of rows to retrieve
 
3068
  @param interrupted       true <=> Assume that the disk sweep will be
 
3069
                           interrupted by other disk IO. false - otherwise.
 
3070
  @param cost         OUT  The cost.
 
3071
*/
 
3072
 
 
3073
void get_sweep_read_cost(Table *table, ha_rows nrows, bool interrupted,
 
3074
                         COST_VECT *cost)
 
3075
{
 
3076
  cost->zero();
 
3077
  if (table->file->primary_key_is_clustered())
 
3078
  {
 
3079
    cost->io_count= table->file->read_time(table->s->primary_key,
 
3080
                                           (uint32_t) nrows, nrows);
 
3081
  }
 
3082
  else
 
3083
  {
 
3084
    double n_blocks=
 
3085
      ceil(uint64_t2double(table->file->stats.data_file_length) / IO_SIZE);
 
3086
    double busy_blocks=
 
3087
      n_blocks * (1.0 - pow(1.0 - 1.0/n_blocks, rows2double(nrows)));
 
3088
    if (busy_blocks < 1.0)
 
3089
      busy_blocks= 1.0;
 
3090
 
 
3091
    cost->io_count= busy_blocks;
 
3092
 
 
3093
    if (!interrupted)
 
3094
    {
 
3095
      /* Assume reading is done in one 'sweep' */
 
3096
      cost->avg_io_cost= (DISK_SEEK_BASE_COST +
 
3097
                          DISK_SEEK_PROP_COST*n_blocks/busy_blocks);
 
3098
    }
 
3099
  }
 
3100
}
 
3101
 
 
3102
 
 
3103
/* **************************************************************************
1150
3104
 * DS-MRR implementation ends
1151
3105
 ***************************************************************************/
1152
3106
 
1159
3113
  @param sorted         Set to 1 if result should be sorted per key
1160
3114
 
1161
3115
  @note
1162
 
    Record is read into table->getInsertRecord()
 
3116
    Record is read into table->record[0]
1163
3117
 
1164
3118
  @retval
1165
3119
    0                   Found row
1168
3122
  @retval
1169
3123
    \#                  Error code
1170
3124
*/
1171
 
int Cursor::read_range_first(const key_range *start_key,
1172
 
                             const key_range *end_key,
1173
 
                             bool eq_range_arg,
1174
 
                             bool )
 
3125
int handler::read_range_first(const key_range *start_key,
 
3126
                              const key_range *end_key,
 
3127
                              bool eq_range_arg,
 
3128
                              bool )
1175
3129
{
1176
3130
  int result;
1177
3131
 
1184
3138
    key_compare_result_on_equal= ((end_key->flag == HA_READ_BEFORE_KEY) ? 1 :
1185
3139
                                  (end_key->flag == HA_READ_AFTER_KEY) ? -1 : 0);
1186
3140
  }
1187
 
  range_key_part= getTable()->key_info[active_index].key_part;
 
3141
  range_key_part= table->key_info[active_index].key_part;
1188
3142
 
1189
3143
  if (!start_key)                       // Read first record
1190
 
    result= index_first(getTable()->getInsertRecord());
 
3144
    result= index_first(table->record[0]);
1191
3145
  else
1192
 
    result= index_read_map(getTable()->getInsertRecord(),
 
3146
    result= index_read_map(table->record[0],
1193
3147
                           start_key->key,
1194
3148
                           start_key->keypart_map,
1195
3149
                           start_key->flag);
1206
3160
  Read next row between two endpoints.
1207
3161
 
1208
3162
  @note
1209
 
    Record is read into table->getInsertRecord()
 
3163
    Record is read into table->record[0]
1210
3164
 
1211
3165
  @retval
1212
3166
    0                   Found row
1215
3169
  @retval
1216
3170
    \#                  Error code
1217
3171
*/
1218
 
int Cursor::read_range_next()
 
3172
int handler::read_range_next()
1219
3173
{
1220
3174
  int result;
1221
3175
 
1222
3176
  if (eq_range)
1223
3177
  {
1224
3178
    /* We trust that index_next_same always gives a row in range */
1225
 
    return(index_next_same(getTable()->getInsertRecord(),
 
3179
    return(index_next_same(table->record[0],
1226
3180
                                end_range->key,
1227
3181
                                end_range->length));
1228
3182
  }
1229
 
  result= index_next(getTable()->getInsertRecord());
 
3183
  result= index_next(table->record[0]);
1230
3184
  if (result)
1231
3185
    return result;
1232
3186
  return(compare_key(end_range) <= 0 ? 0 : HA_ERR_END_OF_FILE);
1248
3202
    - -1  : Key is less than range
1249
3203
    - 1   : Key is larger than range
1250
3204
*/
1251
 
int Cursor::compare_key(key_range *range)
 
3205
int handler::compare_key(key_range *range)
1252
3206
{
1253
3207
  int cmp;
1254
 
  if (not range)
 
3208
  if (!range || in_range_check_pushed_down)
1255
3209
    return 0;                                   // No max range
1256
3210
  cmp= key_cmp(range_key_part, range->key, range->length);
1257
3211
  if (!cmp)
1259
3213
  return cmp;
1260
3214
}
1261
3215
 
1262
 
int Cursor::index_read_idx_map(unsigned char * buf, uint32_t index,
 
3216
 
 
3217
/*
 
3218
  Same as compare_key() but doesn't check have in_range_check_pushed_down.
 
3219
  This is used by index condition pushdown implementation.
 
3220
*/
 
3221
 
 
3222
int handler::compare_key2(key_range *range)
 
3223
{
 
3224
  int cmp;
 
3225
  if (!range)
 
3226
    return 0;                                   // no max range
 
3227
  cmp= key_cmp(range_key_part, range->key, range->length);
 
3228
  if (!cmp)
 
3229
    cmp= key_compare_result_on_equal;
 
3230
  return cmp;
 
3231
}
 
3232
 
 
3233
int handler::index_read_idx_map(unsigned char * buf, uint32_t index,
1263
3234
                                const unsigned char * key,
1264
3235
                                key_part_map keypart_map,
1265
3236
                                enum ha_rkey_function find_flag)
1266
3237
{
1267
3238
  int error, error1;
1268
 
  error= doStartIndexScan(index, 0);
 
3239
  error= index_init(index, 0);
1269
3240
  if (!error)
1270
3241
  {
1271
3242
    error= index_read_map(buf, key, keypart_map, find_flag);
1272
 
    error1= doEndIndexScan();
 
3243
    error1= index_end();
1273
3244
  }
1274
3245
  return error ?  error : error1;
1275
3246
}
1276
3247
 
 
3248
 
 
3249
static bool stat_print(Session *session, const char *type, uint32_t type_len,
 
3250
                       const char *file, uint32_t file_len,
 
3251
                       const char *status, uint32_t status_len)
 
3252
{
 
3253
  Protocol *protocol= session->protocol;
 
3254
  protocol->prepareForResend();
 
3255
  protocol->store(type, type_len);
 
3256
  protocol->store(file, file_len);
 
3257
  protocol->store(status, status_len);
 
3258
  if (protocol->write())
 
3259
    return true;
 
3260
  return false;
 
3261
}
 
3262
 
 
3263
bool ha_show_status(Session *session, StorageEngine *engine, enum ha_stat_type stat)
 
3264
{
 
3265
  List<Item> field_list;
 
3266
  Protocol *protocol= session->protocol;
 
3267
  bool result;
 
3268
 
 
3269
  field_list.push_back(new Item_empty_string("Type",10));
 
3270
  field_list.push_back(new Item_empty_string("Name",FN_REFLEN));
 
3271
  field_list.push_back(new Item_empty_string("Status",10));
 
3272
 
 
3273
  if (protocol->sendFields(&field_list,
 
3274
                           Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
 
3275
    return true;
 
3276
 
 
3277
  result= engine->show_status(session, stat_print, stat) ? 1 : 0;
 
3278
 
 
3279
  if (!result)
 
3280
    session->my_eof();
 
3281
  return result;
 
3282
}
 
3283
 
 
3284
 
1277
3285
/**
1278
3286
  Check if the conditions for row-based binlogging is correct for the table.
1279
3287
 
1280
3288
  A row in the given table should be replicated if:
 
3289
  - Row-based replication is enabled in the current thread
 
3290
  - The binlog is enabled
1281
3291
  - It is not a temporary table
 
3292
  - The binary log is open
 
3293
  - The database the table resides in shall be binlogged (binlog_*_db rules)
 
3294
  - table is not mysql.event
1282
3295
*/
1283
3296
 
1284
3297
static bool log_row_for_replication(Table* table,
1285
 
                                    const unsigned char *before_record,
1286
 
                                    const unsigned char *after_record)
 
3298
                           const unsigned char *before_record,
 
3299
                           const unsigned char *after_record)
1287
3300
{
1288
 
  TransactionServices &transaction_services= TransactionServices::singleton();
1289
3301
  Session *const session= table->in_use;
1290
3302
 
1291
 
  if (table->getShare()->getType() || not transaction_services.shouldConstructMessages())
1292
 
    return false;
1293
 
 
1294
 
  bool result= false;
1295
 
 
1296
3303
  switch (session->lex->sql_command)
1297
3304
  {
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
3305
  case SQLCOM_REPLACE:
 
3306
  case SQLCOM_INSERT:
1311
3307
  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
3308
  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);
 
3309
  case SQLCOM_CREATE_TABLE:
 
3310
    transaction_services.insertRecord(session, table);
1366
3311
    break;
1367
3312
 
1368
3313
  case SQLCOM_UPDATE:
 
3314
  case SQLCOM_UPDATE_MULTI:
1369
3315
    transaction_services.updateRecord(session, table, before_record, after_record);
1370
3316
    break;
1371
3317
 
1372
3318
  case SQLCOM_DELETE:
 
3319
  case SQLCOM_DELETE_MULTI:
1373
3320
    transaction_services.deleteRecord(session, table);
1374
3321
    break;
 
3322
 
 
3323
    /*
 
3324
      For everything else we ignore the event (since it just involves a temp table)
 
3325
    */
1375
3326
  default:
1376
3327
    break;
1377
3328
  }
1378
3329
 
1379
 
  return result;
 
3330
  return false; //error;
1380
3331
}
1381
3332
 
1382
 
int Cursor::ha_external_lock(Session *session, int lock_type)
 
3333
int handler::ha_external_lock(Session *session, int lock_type)
1383
3334
{
1384
3335
  /*
1385
3336
    Whether this is lock or unlock, this should be true, and is to verify that
1388
3339
  */
1389
3340
  assert(next_insert_id == 0);
1390
3341
 
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
3342
  /*
1413
3343
    We cache the table flags if the locking succeeded. Otherwise, we
1414
3344
    keep them as they were when they were fetched in ha_open().
1415
3345
  */
 
3346
  DRIZZLE_EXTERNAL_LOCK(lock_type);
1416
3347
 
1417
3348
  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
 
 
 
3349
  if (error == 0)
 
3350
    cached_table_flags= table_flags();
1437
3351
  return error;
1438
3352
}
1439
3353
 
1440
3354
 
1441
3355
/**
1442
 
  Check Cursor usage and reset state of file to after 'open'
 
3356
  Check handler usage and reset state of file to after 'open'
1443
3357
*/
1444
 
int Cursor::ha_reset()
 
3358
int handler::ha_reset()
1445
3359
{
1446
3360
  /* 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 */
 
3361
  assert((unsigned char*) table->def_read_set.bitmap +
 
3362
              table->s->column_bitmap_size ==
 
3363
              (unsigned char*) table->def_write_set.bitmap);
 
3364
  assert(bitmap_is_set_all(&table->s->all_set));
 
3365
  assert(table->key_read == 0);
 
3366
  /* ensure that ha_index_end / ha_rnd_end has been called */
1450
3367
  assert(inited == NONE);
1451
3368
  /* Free cache used by filesort */
1452
 
  getTable()->free_io_cache();
 
3369
  free_io_cache(table);
1453
3370
  /* reset the bitmaps to point to defaults */
1454
 
  getTable()->default_column_bitmaps();
 
3371
  table->default_column_bitmaps();
1455
3372
  return(reset());
1456
3373
}
1457
3374
 
1458
3375
 
1459
 
int Cursor::insertRecord(unsigned char *buf)
 
3376
int handler::ha_write_row(unsigned char *buf)
1460
3377
{
1461
3378
  int error;
 
3379
  DRIZZLE_INSERT_ROW_START();
1462
3380
 
1463
 
  /*
1464
 
   * If we have a timestamp column, update it to the current time
1465
 
   *
 
3381
  /* 
 
3382
   * If we have a timestamp column, update it to the current time 
 
3383
   * 
1466
3384
   * @TODO Technically, the below two lines can be take even further out of the
1467
 
   * Cursor interface and into the fill_record() method.
 
3385
   * handler interface and into the fill_record() method.
1468
3386
   */
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
 
  {
 
3387
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
 
3388
    table->timestamp_field->set_time();
 
3389
 
 
3390
  mark_trx_read_write();
 
3391
 
 
3392
  if (unlikely(error= write_row(buf)))
1496
3393
    return error;
1497
 
  }
1498
 
 
1499
 
  if (unlikely(log_row_for_replication(getTable(), NULL, buf)))
1500
 
    return HA_ERR_RBR_LOGGING_FAILED;
1501
 
 
 
3394
 
 
3395
  if (unlikely(log_row_for_replication(table, 0, buf)))
 
3396
    return HA_ERR_RBR_LOGGING_FAILED; /* purecov: inspected */
 
3397
 
 
3398
  DRIZZLE_INSERT_ROW_END();
1502
3399
  return 0;
1503
3400
}
1504
3401
 
1505
3402
 
1506
 
int Cursor::updateRecord(const unsigned char *old_data, unsigned char *new_data)
 
3403
int handler::ha_update_row(const unsigned char *old_data, unsigned char *new_data)
1507
3404
{
1508
3405
  int error;
1509
3406
 
1510
3407
  /*
1511
 
    Some storage engines require that the new record is in getInsertRecord()
1512
 
    (and the old record is in getUpdateRecord()).
 
3408
    Some storage engines require that the new record is in record[0]
 
3409
    (and the old record is in record[1]).
1513
3410
   */
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
 
  {
 
3411
  assert(new_data == table->record[0]);
 
3412
 
 
3413
  mark_trx_read_write();
 
3414
 
 
3415
  if (unlikely(error= update_row(old_data, new_data)))
1542
3416
    return error;
1543
 
  }
1544
3417
 
1545
 
  if (unlikely(log_row_for_replication(getTable(), old_data, new_data)))
 
3418
  if (unlikely(log_row_for_replication(table, old_data, new_data)))
1546
3419
    return HA_ERR_RBR_LOGGING_FAILED;
1547
3420
 
1548
3421
  return 0;
1549
3422
}
1550
 
TableShare *Cursor::getShare()
1551
 
{
1552
 
  return getTable()->getMutableShare();
1553
 
}
1554
3423
 
1555
 
int Cursor::deleteRecord(const unsigned char *buf)
 
3424
int handler::ha_delete_row(const unsigned char *buf)
1556
3425
{
1557
3426
  int error;
1558
3427
 
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))
 
3428
  mark_trx_read_write();
 
3429
 
 
3430
  if (unlikely(error= delete_row(buf)))
1579
3431
    return error;
1580
3432
 
1581
 
  if (unlikely(log_row_for_replication(getTable(), buf, NULL)))
 
3433
  if (unlikely(log_row_for_replication(table, buf, 0)))
1582
3434
    return HA_ERR_RBR_LOGGING_FAILED;
1583
3435
 
1584
3436
  return 0;
1585
3437
}
1586
 
 
1587
 
} /* namespace drizzled */