~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/handler.cc

  • Committer: Brian Aker
  • Date: 2009-06-03 19:30:45 UTC
  • mfrom: (1046.1.6 merge)
  • Revision ID: brian@gaz-20090603193045-4xgeczyfixh07beg
MergeĀ forĀ Brian

Show diffs side-by-side

added added

removed removed

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