~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/handler.cc

  • Committer: Padraig O'Sullivan
  • Date: 2009-07-22 23:26:26 UTC
  • mto: (1039.5.43 replication)
  • mto: This revision was merged to the branch mainline in revision 1130.
  • Revision ID: osullivan.padraig@gmail.com-20090722232626-mu4khq7ho6dqcf7q
Created a simple filtered replicator that can filter by schema name or table
name.

Show diffs side-by-side

added added

removed removed

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