~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/handler.cc

  • Committer: Brian Aker
  • Date: 2009-02-21 00:18:15 UTC
  • Revision ID: brian@tangent.org-20090221001815-x20e8h71e984lvs1
Completion (?) of uint conversion.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
3
 *
4
 
 *  Copyright (C) 2008 Sun Microsystems, Inc.
 
4
 *  Copyright (C) 2008 Sun Microsystems
5
5
 *
6
6
 *  This program is free software; you can redistribute it and/or modify
7
7
 *  it under the terms of the GNU General Public License as published by
18
18
 */
19
19
 
20
20
/**
21
 
  @file Cursor.cc
 
21
  @file handler.cc
22
22
 
23
23
  Handler-calling-functions
24
24
*/
25
25
 
26
 
#include "config.h"
27
 
 
28
 
#include <fcntl.h>
29
 
 
 
26
#include "drizzled/server_includes.h"
 
27
#include "libdrizzleclient/libdrizzle.h"
 
28
#include "mysys/hash.h"
30
29
#include "drizzled/error.h"
31
 
#include "drizzled/field/epoch.h"
32
30
#include "drizzled/gettext.h"
33
 
#include "drizzled/internal/my_sys.h"
34
 
#include "drizzled/item/empty_string.h"
35
 
#include "drizzled/item/int.h"
36
 
#include "drizzled/lock.h"
37
 
#include "drizzled/message/table.h"
38
 
#include "drizzled/my_hash.h"
39
 
#include "drizzled/optimizer/cost_vector.h"
40
 
#include "drizzled/plugin/client.h"
41
 
#include "drizzled/plugin/event_observer.h"
42
 
#include "drizzled/plugin/storage_engine.h"
 
31
#include "drizzled/data_home.h"
43
32
#include "drizzled/probes.h"
 
33
#include "drizzled/sql_parse.h"
 
34
#include "drizzled/cost_vect.h"
 
35
#include CMATH_H
44
36
#include "drizzled/session.h"
45
37
#include "drizzled/sql_base.h"
46
 
#include "drizzled/sql_parse.h"
47
 
#include "drizzled/transaction_services.h"
48
 
 
49
 
using namespace std;
50
 
 
51
 
namespace drizzled
52
 
{
 
38
#include "drizzled/replicator.h"
 
39
#include "drizzled/lock.h"
 
40
#include "drizzled/item/int.h"
 
41
#include "drizzled/item/empty_string.h"
 
42
#include "drizzled/unireg.h" // for mysql_frm_type
 
43
#include "drizzled/field/timestamp.h"
 
44
#include "drizzled/serialize/table.pb.h"
 
45
 
 
46
#if defined(CMATH_NAMESPACE)
 
47
using namespace CMATH_NAMESPACE;
 
48
#endif
 
49
 
 
50
 
 
51
KEY_CREATE_INFO default_key_create_info= { HA_KEY_ALG_UNDEF, 0, {NULL,0}, {NULL,0} };
 
52
 
 
53
/* number of entries in handlertons[] */
 
54
uint32_t total_ha= 0;
 
55
/* number of storage engines (from handlertons[]) that support 2pc */
 
56
uint32_t total_ha_2pc= 0;
 
57
/* size of savepoint storage area (see ha_init) */
 
58
uint32_t savepoint_alloc_size= 0;
 
59
 
 
60
const char *ha_row_type[] = {
 
61
  "", "FIXED", "DYNAMIC", "COMPRESSED", "REDUNDANT", "COMPACT", "PAGE", "?","?","?"
 
62
};
 
63
 
 
64
const char *tx_isolation_names[] =
 
65
{ "READ-UNCOMMITTED", "READ-COMMITTED", "REPEATABLE-READ", "SERIALIZABLE",
 
66
  NULL};
 
67
 
 
68
TYPELIB tx_isolation_typelib= {array_elements(tx_isolation_names)-1,"",
 
69
                               tx_isolation_names, NULL};
 
70
 
 
71
static TYPELIB known_extensions= {0,"known_exts", NULL, NULL};
 
72
uint32_t known_extensions_id= 0;
 
73
 
 
74
 
 
75
/**
 
76
  Register handler error messages for use with my_error().
 
77
 
 
78
  @retval
 
79
    0           OK
 
80
  @retval
 
81
    !=0         Error
 
82
*/
 
83
 
 
84
int ha_init_errors(void)
 
85
{
 
86
#define SETMSG(nr, msg) errmsgs[(nr) - HA_ERR_FIRST]= (msg)
 
87
  const char    **errmsgs;
 
88
 
 
89
  /* Allocate a pointer array for the error message strings. */
 
90
  /* Zerofill it to avoid uninitialized gaps. */
 
91
  if (! (errmsgs= (const char**) malloc(HA_ERR_ERRORS * sizeof(char*))))
 
92
    return 1;
 
93
  memset(errmsgs, 0, HA_ERR_ERRORS * sizeof(char *));
 
94
 
 
95
  /* Set the dedicated error messages. */
 
96
  SETMSG(HA_ERR_KEY_NOT_FOUND,          ER(ER_KEY_NOT_FOUND));
 
97
  SETMSG(HA_ERR_FOUND_DUPP_KEY,         ER(ER_DUP_KEY));
 
98
  SETMSG(HA_ERR_RECORD_CHANGED,         "Update wich is recoverable");
 
99
  SETMSG(HA_ERR_WRONG_INDEX,            "Wrong index given to function");
 
100
  SETMSG(HA_ERR_CRASHED,                ER(ER_NOT_KEYFILE));
 
101
  SETMSG(HA_ERR_WRONG_IN_RECORD,        ER(ER_CRASHED_ON_USAGE));
 
102
  SETMSG(HA_ERR_OUT_OF_MEM,             "Table handler out of memory");
 
103
  SETMSG(HA_ERR_NOT_A_TABLE,            "Incorrect file format '%.64s'");
 
104
  SETMSG(HA_ERR_WRONG_COMMAND,          "Command not supported");
 
105
  SETMSG(HA_ERR_OLD_FILE,               ER(ER_OLD_KEYFILE));
 
106
  SETMSG(HA_ERR_NO_ACTIVE_RECORD,       "No record read in update");
 
107
  SETMSG(HA_ERR_RECORD_DELETED,         "Intern record deleted");
 
108
  SETMSG(HA_ERR_RECORD_FILE_FULL,       ER(ER_RECORD_FILE_FULL));
 
109
  SETMSG(HA_ERR_INDEX_FILE_FULL,        "No more room in index file '%.64s'");
 
110
  SETMSG(HA_ERR_END_OF_FILE,            "End in next/prev/first/last");
 
111
  SETMSG(HA_ERR_UNSUPPORTED,            ER(ER_ILLEGAL_HA));
 
112
  SETMSG(HA_ERR_TO_BIG_ROW,             "Too big row");
 
113
  SETMSG(HA_WRONG_CREATE_OPTION,        "Wrong create option");
 
114
  SETMSG(HA_ERR_FOUND_DUPP_UNIQUE,      ER(ER_DUP_UNIQUE));
 
115
  SETMSG(HA_ERR_UNKNOWN_CHARSET,        "Can't open charset");
 
116
  SETMSG(HA_ERR_WRONG_MRG_TABLE_DEF,    ER(ER_WRONG_MRG_TABLE));
 
117
  SETMSG(HA_ERR_CRASHED_ON_REPAIR,      ER(ER_CRASHED_ON_REPAIR));
 
118
  SETMSG(HA_ERR_CRASHED_ON_USAGE,       ER(ER_CRASHED_ON_USAGE));
 
119
  SETMSG(HA_ERR_LOCK_WAIT_TIMEOUT,      ER(ER_LOCK_WAIT_TIMEOUT));
 
120
  SETMSG(HA_ERR_LOCK_TABLE_FULL,        ER(ER_LOCK_TABLE_FULL));
 
121
  SETMSG(HA_ERR_READ_ONLY_TRANSACTION,  ER(ER_READ_ONLY_TRANSACTION));
 
122
  SETMSG(HA_ERR_LOCK_DEADLOCK,          ER(ER_LOCK_DEADLOCK));
 
123
  SETMSG(HA_ERR_CANNOT_ADD_FOREIGN,     ER(ER_CANNOT_ADD_FOREIGN));
 
124
  SETMSG(HA_ERR_NO_REFERENCED_ROW,      ER(ER_NO_REFERENCED_ROW_2));
 
125
  SETMSG(HA_ERR_ROW_IS_REFERENCED,      ER(ER_ROW_IS_REFERENCED_2));
 
126
  SETMSG(HA_ERR_NO_SAVEPOINT,           "No savepoint with that name");
 
127
  SETMSG(HA_ERR_NON_UNIQUE_BLOCK_SIZE,  "Non unique key block size");
 
128
  SETMSG(HA_ERR_NO_SUCH_TABLE,          "No such table: '%.64s'");
 
129
  SETMSG(HA_ERR_TABLE_EXIST,            ER(ER_TABLE_EXISTS_ERROR));
 
130
  SETMSG(HA_ERR_NO_CONNECTION,          "Could not connect to storage engine");
 
131
  SETMSG(HA_ERR_TABLE_DEF_CHANGED,      ER(ER_TABLE_DEF_CHANGED));
 
132
  SETMSG(HA_ERR_FOREIGN_DUPLICATE_KEY,  "FK constraint would lead to duplicate key");
 
133
  SETMSG(HA_ERR_TABLE_NEEDS_UPGRADE,    ER(ER_TABLE_NEEDS_UPGRADE));
 
134
  SETMSG(HA_ERR_TABLE_READONLY,         ER(ER_OPEN_AS_READONLY));
 
135
  SETMSG(HA_ERR_AUTOINC_READ_FAILED,    ER(ER_AUTOINC_READ_FAILED));
 
136
  SETMSG(HA_ERR_AUTOINC_ERANGE,         ER(ER_WARN_DATA_OUT_OF_RANGE));
 
137
 
 
138
  /* Register the error messages for use with my_error(). */
 
139
  return my_error_register(errmsgs, HA_ERR_FIRST, HA_ERR_LAST);
 
140
}
 
141
 
 
142
 
 
143
/**
 
144
  Unregister handler error messages.
 
145
 
 
146
  @retval
 
147
    0           OK
 
148
  @retval
 
149
    !=0         Error
 
150
*/
 
151
static int ha_finish_errors(void)
 
152
{
 
153
  const char    **errmsgs;
 
154
 
 
155
  /* Allocate a pointer array for the error message strings. */
 
156
  if (! (errmsgs= my_error_unregister(HA_ERR_FIRST, HA_ERR_LAST)))
 
157
    return 1;
 
158
  free((unsigned char*) errmsgs);
 
159
  return 0;
 
160
}
 
161
 
 
162
int ha_init()
 
163
{
 
164
  int error= 0;
 
165
 
 
166
  assert(total_ha < MAX_HA);
 
167
  /*
 
168
    Check if there is a transaction-capable storage engine besides the
 
169
    binary log (which is considered a transaction-capable storage engine in
 
170
    counting total_ha)
 
171
  */
 
172
  opt_using_transactions= total_ha>(uint32_t)opt_bin_log;
 
173
  savepoint_alloc_size+= sizeof(SAVEPOINT);
 
174
  return(error);
 
175
}
 
176
 
 
177
int ha_end()
 
178
{
 
179
  int error= 0;
 
180
 
 
181
  /*
 
182
    This should be eventualy based  on the graceful shutdown flag.
 
183
    So if flag is equal to HA_PANIC_CLOSE, the deallocate
 
184
    the errors.
 
185
  */
 
186
  if (ha_finish_errors())
 
187
    error= 1;
 
188
 
 
189
  return(error);
 
190
}
 
191
 
 
192
static bool dropdb_handlerton(Session *,
 
193
                              plugin_ref plugin,
 
194
                              void *path)
 
195
{
 
196
  handlerton *hton= plugin_data(plugin, handlerton *);
 
197
  if (hton->state == SHOW_OPTION_YES && hton->drop_database)
 
198
    hton->drop_database(hton, (char *)path);
 
199
  return false;
 
200
}
 
201
 
 
202
 
 
203
void ha_drop_database(char* path)
 
204
{
 
205
  plugin_foreach(NULL, dropdb_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN, path);
 
206
}
 
207
 
 
208
 
 
209
static bool closecon_handlerton(Session *session, plugin_ref plugin,
 
210
                                void *)
 
211
{
 
212
  handlerton *hton= plugin_data(plugin, handlerton *);
 
213
  /*
 
214
    there's no need to rollback here as all transactions must
 
215
    be rolled back already
 
216
  */
 
217
  if (hton->state == SHOW_OPTION_YES && hton->close_connection &&
 
218
      session_get_ha_data(session, hton))
 
219
    hton->close_connection(hton, session);
 
220
  return false;
 
221
}
 
222
 
 
223
 
 
224
/**
 
225
  @note
 
226
    don't bother to rollback here, it's done already
 
227
*/
 
228
void ha_close_connection(Session* session)
 
229
{
 
230
  plugin_foreach(session, closecon_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN, 0);
 
231
}
 
232
 
 
233
/* ========================================================================
 
234
 ======================= TRANSACTIONS ===================================*/
 
235
 
 
236
/**
 
237
  Transaction handling in the server
 
238
  ==================================
 
239
 
 
240
  In each client connection, MySQL maintains two transactional
 
241
  states:
 
242
  - a statement transaction,
 
243
  - a standard, also called normal transaction.
 
244
 
 
245
  Historical note
 
246
  ---------------
 
247
  "Statement transaction" is a non-standard term that comes
 
248
  from the times when MySQL supported BerkeleyDB storage engine.
 
249
 
 
250
  First of all, it should be said that in BerkeleyDB auto-commit
 
251
  mode auto-commits operations that are atomic to the storage
 
252
  engine itself, such as a write of a record, and are too
 
253
  high-granular to be atomic from the application perspective
 
254
  (MySQL). One SQL statement could involve many BerkeleyDB
 
255
  auto-committed operations and thus BerkeleyDB auto-commit was of
 
256
  little use to MySQL.
 
257
 
 
258
  Secondly, instead of SQL standard savepoints, BerkeleyDB
 
259
  provided the concept of "nested transactions". In a nutshell,
 
260
  transactions could be arbitrarily nested, but when the parent
 
261
  transaction was committed or aborted, all its child (nested)
 
262
  transactions were handled committed or aborted as well.
 
263
  Commit of a nested transaction, in turn, made its changes
 
264
  visible, but not durable: it destroyed the nested transaction,
 
265
  all its changes would become available to the parent and
 
266
  currently active nested transactions of this parent.
 
267
 
 
268
  So the mechanism of nested transactions was employed to
 
269
  provide "all or nothing" guarantee of SQL statements
 
270
  required by the standard.
 
271
  A nested transaction would be created at start of each SQL
 
272
  statement, and destroyed (committed or aborted) at statement
 
273
  end. Such nested transaction was internally referred to as
 
274
  a "statement transaction" and gave birth to the term.
 
275
 
 
276
  <Historical note ends>
 
277
 
 
278
  Since then a statement transaction is started for each statement
 
279
  that accesses transactional tables or uses the binary log.  If
 
280
  the statement succeeds, the statement transaction is committed.
 
281
  If the statement fails, the transaction is rolled back. Commits
 
282
  of statement transactions are not durable -- each such
 
283
  transaction is nested in the normal transaction, and if the
 
284
  normal transaction is rolled back, the effects of all enclosed
 
285
  statement transactions are undone as well.  Technically,
 
286
  a statement transaction can be viewed as a savepoint which is
 
287
  maintained automatically in order to make effects of one
 
288
  statement atomic.
 
289
 
 
290
  The normal transaction is started by the user and is ended
 
291
  usually upon a user request as well. The normal transaction
 
292
  encloses transactions of all statements issued between
 
293
  its beginning and its end.
 
294
  In autocommit mode, the normal transaction is equivalent
 
295
  to the statement transaction.
 
296
 
 
297
  Since MySQL supports PSEA (pluggable storage engine
 
298
  architecture), more than one transactional engine can be
 
299
  active at a time. Hence transactions, from the server
 
300
  point of view, are always distributed. In particular,
 
301
  transactional state is maintained independently for each
 
302
  engine. In order to commit a transaction the two phase
 
303
  commit protocol is employed.
 
304
 
 
305
  Not all statements are executed in context of a transaction.
 
306
  Administrative and status information statements do not modify
 
307
  engine data, and thus do not start a statement transaction and
 
308
  also have no effect on the normal transaction. Examples of such
 
309
  statements are SHOW STATUS and RESET SLAVE.
 
310
 
 
311
  Similarly DDL statements are not transactional,
 
312
  and therefore a transaction is [almost] never started for a DDL
 
313
  statement. The difference between a DDL statement and a purely
 
314
  administrative statement though is that a DDL statement always
 
315
  commits the current transaction before proceeding, if there is
 
316
  any.
 
317
 
 
318
  At last, SQL statements that work with non-transactional
 
319
  engines also have no effect on the transaction state of the
 
320
  connection. Even though they are written to the binary log,
 
321
  and the binary log is, overall, transactional, the writes
 
322
  are done in "write-through" mode, directly to the binlog
 
323
  file, followed with a OS cache sync, in other words,
 
324
  bypassing the binlog undo log (translog).
 
325
  They do not commit the current normal transaction.
 
326
  A failure of a statement that uses non-transactional tables
 
327
  would cause a rollback of the statement transaction, but
 
328
  in case there no non-transactional tables are used,
 
329
  no statement transaction is started.
 
330
 
 
331
  Data layout
 
332
  -----------
 
333
 
 
334
  The server stores its transaction-related data in
 
335
  session->transaction. This structure has two members of type
 
336
  Session_TRANS. These members correspond to the statement and
 
337
  normal transactions respectively:
 
338
 
 
339
  - session->transaction.stmt contains a list of engines
 
340
  that are participating in the given statement
 
341
  - session->transaction.all contains a list of engines that
 
342
  have participated in any of the statement transactions started
 
343
  within the context of the normal transaction.
 
344
  Each element of the list contains a pointer to the storage
 
345
  engine, engine-specific transactional data, and engine-specific
 
346
  transaction flags.
 
347
 
 
348
  In autocommit mode session->transaction.all is empty.
 
349
  Instead, data of session->transaction.stmt is
 
350
  used to commit/rollback the normal transaction.
 
351
 
 
352
  The list of registered engines has a few important properties:
 
353
  - no engine is registered in the list twice
 
354
  - engines are present in the list a reverse temporal order --
 
355
  new participants are always added to the beginning of the list.
 
356
 
 
357
  Transaction life cycle
 
358
  ----------------------
 
359
 
 
360
  When a new connection is established, session->transaction
 
361
  members are initialized to an empty state.
 
362
  If a statement uses any tables, all affected engines
 
363
  are registered in the statement engine list. In
 
364
  non-autocommit mode, the same engines are registered in
 
365
  the normal transaction list.
 
366
  At the end of the statement, the server issues a commit
 
367
  or a roll back for all engines in the statement list.
 
368
  At this point transaction flags of an engine, if any, are
 
369
  propagated from the statement list to the list of the normal
 
370
  transaction.
 
371
  When commit/rollback is finished, the statement list is
 
372
  cleared. It will be filled in again by the next statement,
 
373
  and emptied again at the next statement's end.
 
374
 
 
375
  The normal transaction is committed in a similar way
 
376
  (by going over all engines in session->transaction.all list)
 
377
  but at different times:
 
378
  - upon COMMIT SQL statement is issued by the user
 
379
  - implicitly, by the server, at the beginning of a DDL statement
 
380
  or SET AUTOCOMMIT={0|1} statement.
 
381
 
 
382
  The normal transaction can be rolled back as well:
 
383
  - if the user has requested so, by issuing ROLLBACK SQL
 
384
  statement
 
385
  - if one of the storage engines requested a rollback
 
386
  by setting session->transaction_rollback_request. This may
 
387
  happen in case, e.g., when the transaction in the engine was
 
388
  chosen a victim of the internal deadlock resolution algorithm
 
389
  and rolled back internally. When such a situation happens, there
 
390
  is little the server can do and the only option is to rollback
 
391
  transactions in all other participating engines.  In this case
 
392
  the rollback is accompanied by an error sent to the user.
 
393
 
 
394
  As follows from the use cases above, the normal transaction
 
395
  is never committed when there is an outstanding statement
 
396
  transaction. In most cases there is no conflict, since
 
397
  commits of the normal transaction are issued by a stand-alone
 
398
  administrative or DDL statement, thus no outstanding statement
 
399
  transaction of the previous statement exists. Besides,
 
400
  all statements that manipulate with the normal transaction
 
401
  are prohibited in stored functions and triggers, therefore
 
402
  no conflicting situation can occur in a sub-statement either.
 
403
  The remaining rare cases when the server explicitly has
 
404
  to commit the statement transaction prior to committing the normal
 
405
  one cover error-handling scenarios (see for example
 
406
  SQLCOM_LOCK_TABLES).
 
407
 
 
408
  When committing a statement or a normal transaction, the server
 
409
  either uses the two-phase commit protocol, or issues a commit
 
410
  in each engine independently. The two-phase commit protocol
 
411
  is used only if:
 
412
  - all participating engines support two-phase commit (provide
 
413
    handlerton::prepare PSEA API call) and
 
414
  - transactions in at least two engines modify data (i.e. are
 
415
  not read-only).
 
416
 
 
417
  Note that the two phase commit is used for
 
418
  statement transactions, even though they are not durable anyway.
 
419
  This is done to ensure logical consistency of data in a multiple-
 
420
  engine transaction.
 
421
  For example, imagine that some day MySQL supports unique
 
422
  constraint checks deferred till the end of statement. In such
 
423
  case a commit in one of the engines may yield ER_DUP_KEY,
 
424
  and MySQL should be able to gracefully abort statement
 
425
  transactions of other participants.
 
426
 
 
427
  After the normal transaction has been committed,
 
428
  session->transaction.all list is cleared.
 
429
 
 
430
  When a connection is closed, the current normal transaction, if
 
431
  any, is rolled back.
 
432
 
 
433
  Roles and responsibilities
 
434
  --------------------------
 
435
 
 
436
  The server has no way to know that an engine participates in
 
437
  the statement and a transaction has been started
 
438
  in it unless the engine says so. Thus, in order to be
 
439
  a part of a transaction, the engine must "register" itself.
 
440
  This is done by invoking trans_register_ha() server call.
 
441
  Normally the engine registers itself whenever handler::external_lock()
 
442
  is called. trans_register_ha() can be invoked many times: if
 
443
  an engine is already registered, the call does nothing.
 
444
  In case autocommit is not set, the engine must register itself
 
445
  twice -- both in the statement list and in the normal transaction
 
446
  list.
 
447
  In which list to register is a parameter of trans_register_ha().
 
448
 
 
449
  Note, that although the registration interface in itself is
 
450
  fairly clear, the current usage practice often leads to undesired
 
451
  effects. E.g. since a call to trans_register_ha() in most engines
 
452
  is embedded into implementation of handler::external_lock(), some
 
453
  DDL statements start a transaction (at least from the server
 
454
  point of view) even though they are not expected to. E.g.
 
455
  CREATE TABLE does not start a transaction, since
 
456
  handler::external_lock() is never called during CREATE TABLE. But
 
457
  CREATE TABLE ... SELECT does, since handler::external_lock() is
 
458
  called for the table that is being selected from. This has no
 
459
  practical effects currently, but must be kept in mind
 
460
  nevertheless.
 
461
 
 
462
  Once an engine is registered, the server will do the rest
 
463
  of the work.
 
464
 
 
465
  During statement execution, whenever any of data-modifying
 
466
  PSEA API methods is used, e.g. handler::write_row() or
 
467
  handler::update_row(), the read-write flag is raised in the
 
468
  statement transaction for the involved engine.
 
469
  Currently All PSEA calls are "traced", and the data can not be
 
470
  changed in a way other than issuing a PSEA call. Important:
 
471
  unless this invariant is preserved the server will not know that
 
472
  a transaction in a given engine is read-write and will not
 
473
  involve the two-phase commit protocol!
 
474
 
 
475
  At the end of a statement, server call
 
476
  ha_autocommit_or_rollback() is invoked. This call in turn
 
477
  invokes handlerton::prepare() for every involved engine.
 
478
  Prepare is followed by a call to handlerton::commit_one_phase()
 
479
  If a one-phase commit will suffice, handlerton::prepare() is not
 
480
  invoked and the server only calls handlerton::commit_one_phase().
 
481
  At statement commit, the statement-related read-write engine
 
482
  flag is propagated to the corresponding flag in the normal
 
483
  transaction.  When the commit is complete, the list of registered
 
484
  engines is cleared.
 
485
 
 
486
  Rollback is handled in a similar fashion.
 
487
 
 
488
  Additional notes on DDL and the normal transaction.
 
489
  ---------------------------------------------------
 
490
 
 
491
  DDLs and operations with non-transactional engines
 
492
  do not "register" in session->transaction lists, and thus do not
 
493
  modify the transaction state. Besides, each DDL in
 
494
  MySQL is prefixed with an implicit normal transaction commit
 
495
  (a call to end_active_trans()), and thus leaves nothing
 
496
  to modify.
 
497
  However, as it has been pointed out with CREATE TABLE .. SELECT,
 
498
  some DDL statements can start a *new* transaction.
 
499
 
 
500
  Behaviour of the server in this case is currently badly
 
501
  defined.
 
502
  DDL statements use a form of "semantic" logging
 
503
  to maintain atomicity: if CREATE TABLE .. SELECT failed,
 
504
  the newly created table is deleted.
 
505
  In addition, some DDL statements issue interim transaction
 
506
  commits: e.g. ALTER Table issues a commit after data is copied
 
507
  from the original table to the internal temporary table. Other
 
508
  statements, e.g. CREATE TABLE ... SELECT do not always commit
 
509
  after itself.
 
510
  And finally there is a group of DDL statements such as
 
511
  RENAME/DROP Table that doesn't start a new transaction
 
512
  and doesn't commit.
 
513
 
 
514
  This diversity makes it hard to say what will happen if
 
515
  by chance a stored function is invoked during a DDL --
 
516
  whether any modifications it makes will be committed or not
 
517
  is not clear. Fortunately, SQL grammar of few DDLs allows
 
518
  invocation of a stored function.
 
519
 
 
520
  A consistent behaviour is perhaps to always commit the normal
 
521
  transaction after all DDLs, just like the statement transaction
 
522
  is always committed at the end of all statements.
 
523
*/
 
524
 
 
525
/**
 
526
  Register a storage engine for a transaction.
 
527
 
 
528
  Every storage engine MUST call this function when it starts
 
529
  a transaction or a statement (that is it must be called both for the
 
530
  "beginning of transaction" and "beginning of statement").
 
531
  Only storage engines registered for the transaction/statement
 
532
  will know when to commit/rollback it.
 
533
 
 
534
  @note
 
535
    trans_register_ha is idempotent - storage engine may register many
 
536
    times per transaction.
 
537
 
 
538
*/
 
539
void trans_register_ha(Session *session, bool all, handlerton *ht_arg)
 
540
{
 
541
  Session_TRANS *trans;
 
542
  Ha_trx_info *ha_info;
 
543
 
 
544
  if (all)
 
545
  {
 
546
    trans= &session->transaction.all;
 
547
    session->server_status|= SERVER_STATUS_IN_TRANS;
 
548
  }
 
549
  else
 
550
    trans= &session->transaction.stmt;
 
551
 
 
552
  ha_info= session->ha_data[ht_arg->slot].ha_info + static_cast<unsigned>(all);
 
553
 
 
554
  if (ha_info->is_started())
 
555
    return; /* already registered, return */
 
556
 
 
557
  ha_info->register_ha(trans, ht_arg);
 
558
 
 
559
  trans->no_2pc|=(ht_arg->prepare==0);
 
560
  if (session->transaction.xid_state.xid.is_null())
 
561
    session->transaction.xid_state.xid.set(session->query_id);
 
562
 
 
563
  return;
 
564
}
 
565
 
 
566
/**
 
567
  @retval
 
568
    0   ok
 
569
  @retval
 
570
    1   error, transaction was rolled back
 
571
*/
 
572
int ha_prepare(Session *session)
 
573
{
 
574
  int error=0, all=1;
 
575
  Session_TRANS *trans=all ? &session->transaction.all : &session->transaction.stmt;
 
576
  Ha_trx_info *ha_info= trans->ha_list;
 
577
  if (ha_info)
 
578
  {
 
579
    for (; ha_info; ha_info= ha_info->next())
 
580
    {
 
581
      int err;
 
582
      handlerton *ht= ha_info->ht();
 
583
      status_var_increment(session->status_var.ha_prepare_count);
 
584
      if (ht->prepare)
 
585
      {
 
586
        if ((err= ht->prepare(ht, session, all)))
 
587
        {
 
588
          my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
 
589
          ha_rollback_trans(session, all);
 
590
          error=1;
 
591
          break;
 
592
        }
 
593
      }
 
594
      else
 
595
      {
 
596
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
597
                            ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
 
598
                            ha_resolve_storage_engine_name(ht));
 
599
      }
 
600
    }
 
601
  }
 
602
  return(error);
 
603
}
 
604
 
 
605
/**
 
606
  Check if we can skip the two-phase commit.
 
607
 
 
608
  A helper function to evaluate if two-phase commit is mandatory.
 
609
  As a side effect, propagates the read-only/read-write flags
 
610
  of the statement transaction to its enclosing normal transaction.
 
611
 
 
612
  @retval true   we must run a two-phase commit. Returned
 
613
                 if we have at least two engines with read-write changes.
 
614
  @retval false  Don't need two-phase commit. Even if we have two
 
615
                 transactional engines, we can run two independent
 
616
                 commits if changes in one of the engines are read-only.
 
617
*/
 
618
 
 
619
static
 
620
bool
 
621
ha_check_and_coalesce_trx_read_only(Session *session, Ha_trx_info *ha_list,
 
622
                                    bool all)
 
623
{
 
624
  /* The number of storage engines that have actual changes. */
 
625
  unsigned rw_ha_count= 0;
 
626
  Ha_trx_info *ha_info;
 
627
 
 
628
  for (ha_info= ha_list; ha_info; ha_info= ha_info->next())
 
629
  {
 
630
    if (ha_info->is_trx_read_write())
 
631
      ++rw_ha_count;
 
632
 
 
633
    if (! all)
 
634
    {
 
635
      Ha_trx_info *ha_info_all= &session->ha_data[ha_info->ht()->slot].ha_info[1];
 
636
      assert(ha_info != ha_info_all);
 
637
      /*
 
638
        Merge read-only/read-write information about statement
 
639
        transaction to its enclosing normal transaction. Do this
 
640
        only if in a real transaction -- that is, if we know
 
641
        that ha_info_all is registered in session->transaction.all.
 
642
        Since otherwise we only clutter the normal transaction flags.
 
643
      */
 
644
      if (ha_info_all->is_started()) /* false if autocommit. */
 
645
        ha_info_all->coalesce_trx_with(ha_info);
 
646
    }
 
647
    else if (rw_ha_count > 1)
 
648
    {
 
649
      /*
 
650
        It is a normal transaction, so we don't need to merge read/write
 
651
        information up, and the need for two-phase commit has been
 
652
        already established. Break the loop prematurely.
 
653
      */
 
654
      break;
 
655
    }
 
656
  }
 
657
  return rw_ha_count > 1;
 
658
}
 
659
 
 
660
 
 
661
/**
 
662
  @retval
 
663
    0   ok
 
664
  @retval
 
665
    1   transaction was rolled back
 
666
  @retval
 
667
    2   error during commit, data may be inconsistent
 
668
 
 
669
  @todo
 
670
    Since we don't support nested statement transactions in 5.0,
 
671
    we can't commit or rollback stmt transactions while we are inside
 
672
    stored functions or triggers. So we simply do nothing now.
 
673
    TODO: This should be fixed in later ( >= 5.1) releases.
 
674
*/
 
675
int ha_commit_trans(Session *session, bool all)
 
676
{
 
677
  int error= 0, cookie= 0;
 
678
  /*
 
679
    'all' means that this is either an explicit commit issued by
 
680
    user, or an implicit commit issued by a DDL.
 
681
  */
 
682
  Session_TRANS *trans= all ? &session->transaction.all : &session->transaction.stmt;
 
683
  bool is_real_trans= all || session->transaction.all.ha_list == 0;
 
684
  Ha_trx_info *ha_info= trans->ha_list;
 
685
 
 
686
  /*
 
687
    We must not commit the normal transaction if a statement
 
688
    transaction is pending. Otherwise statement transaction
 
689
    flags will not get propagated to its normal transaction's
 
690
    counterpart.
 
691
  */
 
692
  assert(session->transaction.stmt.ha_list == NULL ||
 
693
              trans == &session->transaction.stmt);
 
694
 
 
695
  if (ha_info)
 
696
  {
 
697
    bool must_2pc;
 
698
 
 
699
    if (is_real_trans && wait_if_global_read_lock(session, 0, 0))
 
700
    {
 
701
      ha_rollback_trans(session, all);
 
702
      return(1);
 
703
    }
 
704
 
 
705
    must_2pc= ha_check_and_coalesce_trx_read_only(session, ha_info, all);
 
706
 
 
707
    if (!trans->no_2pc && must_2pc)
 
708
    {
 
709
      for (; ha_info && !error; ha_info= ha_info->next())
 
710
      {
 
711
        int err;
 
712
        handlerton *ht= ha_info->ht();
 
713
        /*
 
714
          Do not call two-phase commit if this particular
 
715
          transaction is read-only. This allows for simpler
 
716
          implementation in engines that are always read-only.
 
717
        */
 
718
        if (! ha_info->is_trx_read_write())
 
719
          continue;
 
720
        /*
 
721
          Sic: we know that prepare() is not NULL since otherwise
 
722
          trans->no_2pc would have been set.
 
723
        */
 
724
        if ((err= ht->prepare(ht, session, all)))
 
725
        {
 
726
          my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
 
727
          error= 1;
 
728
        }
 
729
        status_var_increment(session->status_var.ha_prepare_count);
 
730
      }
 
731
      if (error)
 
732
      {
 
733
        ha_rollback_trans(session, all);
 
734
        error= 1;
 
735
        goto end;
 
736
      }
 
737
    }
 
738
    error=ha_commit_one_phase(session, all) ? (cookie ? 2 : 1) : 0;
 
739
end:
 
740
    if (is_real_trans)
 
741
      start_waiting_global_read_lock(session);
 
742
  }
 
743
  return(error);
 
744
}
 
745
 
 
746
/**
 
747
  @note
 
748
  This function does not care about global read lock. A caller should.
 
749
*/
 
750
int ha_commit_one_phase(Session *session, bool all)
 
751
{
 
752
  int error=0;
 
753
  Session_TRANS *trans=all ? &session->transaction.all : &session->transaction.stmt;
 
754
  bool is_real_trans=all || session->transaction.all.ha_list == 0;
 
755
  Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
 
756
  if (ha_info)
 
757
  {
 
758
    for (; ha_info; ha_info= ha_info_next)
 
759
    {
 
760
      int err;
 
761
      handlerton *ht= ha_info->ht();
 
762
      if ((err= ht->commit(ht, session, all)))
 
763
      {
 
764
        my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
 
765
        error=1;
 
766
      }
 
767
      status_var_increment(session->status_var.ha_commit_count);
 
768
      ha_info_next= ha_info->next();
 
769
      ha_info->reset(); /* keep it conveniently zero-filled */
 
770
    }
 
771
    trans->ha_list= 0;
 
772
    trans->no_2pc=0;
 
773
    if (is_real_trans)
 
774
      session->transaction.xid_state.xid.null();
 
775
    if (all)
 
776
    {
 
777
      session->variables.tx_isolation=session->session_tx_isolation;
 
778
      session->transaction.cleanup();
 
779
    }
 
780
  }
 
781
  return(error);
 
782
}
 
783
 
 
784
 
 
785
int ha_rollback_trans(Session *session, bool all)
 
786
{
 
787
  int error=0;
 
788
  Session_TRANS *trans=all ? &session->transaction.all : &session->transaction.stmt;
 
789
  Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
 
790
  bool is_real_trans=all || session->transaction.all.ha_list == 0;
 
791
 
 
792
  /*
 
793
    We must not rollback the normal transaction if a statement
 
794
    transaction is pending.
 
795
  */
 
796
  assert(session->transaction.stmt.ha_list == NULL ||
 
797
              trans == &session->transaction.stmt);
 
798
 
 
799
  if (ha_info)
 
800
  {
 
801
    for (; ha_info; ha_info= ha_info_next)
 
802
    {
 
803
      int err;
 
804
      handlerton *ht= ha_info->ht();
 
805
      if ((err= ht->rollback(ht, session, all)))
 
806
      { // cannot happen
 
807
        my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
 
808
        error=1;
 
809
      }
 
810
      status_var_increment(session->status_var.ha_rollback_count);
 
811
      ha_info_next= ha_info->next();
 
812
      ha_info->reset(); /* keep it conveniently zero-filled */
 
813
    }
 
814
    trans->ha_list= 0;
 
815
    trans->no_2pc=0;
 
816
    if (is_real_trans)
 
817
      session->transaction.xid_state.xid.null();
 
818
    if (all)
 
819
    {
 
820
      session->variables.tx_isolation=session->session_tx_isolation;
 
821
      session->transaction.cleanup();
 
822
    }
 
823
  }
 
824
  if (all)
 
825
    session->transaction_rollback_request= false;
 
826
 
 
827
  /*
 
828
    If a non-transactional table was updated, warn; don't warn if this is a
 
829
    slave thread (because when a slave thread executes a ROLLBACK, it has
 
830
    been read from the binary log, so it's 100% sure and normal to produce
 
831
    error ER_WARNING_NOT_COMPLETE_ROLLBACK. If we sent the warning to the
 
832
    slave SQL thread, it would not stop the thread but just be printed in
 
833
    the error log; but we don't want users to wonder why they have this
 
834
    message in the error log, so we don't send it.
 
835
  */
 
836
  if (is_real_trans && session->transaction.all.modified_non_trans_table && session->killed != Session::KILL_CONNECTION)
 
837
    push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
838
                 ER_WARNING_NOT_COMPLETE_ROLLBACK,
 
839
                 ER(ER_WARNING_NOT_COMPLETE_ROLLBACK));
 
840
  return(error);
 
841
}
 
842
 
 
843
/**
 
844
  This is used to commit or rollback a single statement depending on
 
845
  the value of error.
 
846
 
 
847
  @note
 
848
    Note that if the autocommit is on, then the following call inside
 
849
    InnoDB will commit or rollback the whole transaction (= the statement). The
 
850
    autocommit mechanism built into InnoDB is based on counting locks, but if
 
851
    the user has used LOCK TABLES then that mechanism does not know to do the
 
852
    commit.
 
853
*/
 
854
int ha_autocommit_or_rollback(Session *session, int error)
 
855
{
 
856
  if (session->transaction.stmt.ha_list)
 
857
  {
 
858
    if (!error)
 
859
    {
 
860
      if (ha_commit_trans(session, 0))
 
861
        error=1;
 
862
    }
 
863
    else
 
864
    {
 
865
      (void) ha_rollback_trans(session, 0);
 
866
      if (session->transaction_rollback_request)
 
867
        (void) ha_rollback(session);
 
868
    }
 
869
 
 
870
    session->variables.tx_isolation=session->session_tx_isolation;
 
871
  }
 
872
  return(error);
 
873
}
 
874
 
 
875
 
 
876
struct xahton_st {
 
877
  XID *xid;
 
878
  int result;
 
879
};
 
880
 
 
881
static bool xacommit_handlerton(Session *,
 
882
                                plugin_ref plugin,
 
883
                                void *arg)
 
884
{
 
885
  handlerton *hton= plugin_data(plugin, handlerton *);
 
886
  if (hton->state == SHOW_OPTION_YES && hton->recover)
 
887
  {
 
888
    hton->commit_by_xid(hton, ((struct xahton_st *)arg)->xid);
 
889
    ((struct xahton_st *)arg)->result= 0;
 
890
  }
 
891
  return false;
 
892
}
 
893
 
 
894
static bool xarollback_handlerton(Session *,
 
895
                                  plugin_ref plugin,
 
896
                                  void *arg)
 
897
{
 
898
  handlerton *hton= plugin_data(plugin, handlerton *);
 
899
  if (hton->state == SHOW_OPTION_YES && hton->recover)
 
900
  {
 
901
    hton->rollback_by_xid(hton, ((struct xahton_st *)arg)->xid);
 
902
    ((struct xahton_st *)arg)->result= 0;
 
903
  }
 
904
  return false;
 
905
}
 
906
 
 
907
 
 
908
int ha_commit_or_rollback_by_xid(XID *xid, bool commit)
 
909
{
 
910
  struct xahton_st xaop;
 
911
  xaop.xid= xid;
 
912
  xaop.result= 1;
 
913
 
 
914
  plugin_foreach(NULL, commit ? xacommit_handlerton : xarollback_handlerton,
 
915
                 DRIZZLE_STORAGE_ENGINE_PLUGIN, &xaop);
 
916
 
 
917
  return xaop.result;
 
918
}
 
919
 
 
920
/**
 
921
  recover() step of xa.
 
922
 
 
923
  @note
 
924
    there are three modes of operation:
 
925
    - automatic recover after a crash
 
926
    in this case commit_list != 0, tc_heuristic_recover==0
 
927
    all xids from commit_list are committed, others are rolled back
 
928
    - manual (heuristic) recover
 
929
    in this case commit_list==0, tc_heuristic_recover != 0
 
930
    DBA has explicitly specified that all prepared transactions should
 
931
    be committed (or rolled back).
 
932
    - no recovery (MySQL did not detect a crash)
 
933
    in this case commit_list==0, tc_heuristic_recover == 0
 
934
    there should be no prepared transactions in this case.
 
935
*/
 
936
struct xarecover_st
 
937
{
 
938
  int len, found_foreign_xids, found_my_xids;
 
939
  XID *list;
 
940
  HASH *commit_list;
 
941
  bool dry_run;
 
942
};
 
943
 
 
944
static bool xarecover_handlerton(Session *,
 
945
                                 plugin_ref plugin,
 
946
                                 void *arg)
 
947
{
 
948
  handlerton *hton= plugin_data(plugin, handlerton *);
 
949
  struct xarecover_st *info= (struct xarecover_st *) arg;
 
950
  int got;
 
951
 
 
952
  if (hton->state == SHOW_OPTION_YES && hton->recover)
 
953
  {
 
954
    while ((got= hton->recover(hton, info->list, info->len)) > 0 )
 
955
    {
 
956
      errmsg_printf(ERRMSG_LVL_INFO, _("Found %d prepared transaction(s) in %s"),
 
957
                            got, ha_resolve_storage_engine_name(hton));
 
958
      for (int i=0; i < got; i ++)
 
959
      {
 
960
        my_xid x=info->list[i].get_my_xid();
 
961
        if (!x) // not "mine" - that is generated by external TM
 
962
        {
 
963
          xid_cache_insert(info->list+i, XA_PREPARED);
 
964
          info->found_foreign_xids++;
 
965
          continue;
 
966
        }
 
967
        if (info->dry_run)
 
968
        {
 
969
          info->found_my_xids++;
 
970
          continue;
 
971
        }
 
972
        // recovery mode
 
973
        if (info->commit_list ?
 
974
            hash_search(info->commit_list, (unsigned char *)&x, sizeof(x)) != 0 :
 
975
            tc_heuristic_recover == TC_HEURISTIC_RECOVER_COMMIT)
 
976
        {
 
977
          hton->commit_by_xid(hton, info->list+i);
 
978
        }
 
979
        else
 
980
        {
 
981
          hton->rollback_by_xid(hton, info->list+i);
 
982
        }
 
983
      }
 
984
      if (got < info->len)
 
985
        break;
 
986
    }
 
987
  }
 
988
  return false;
 
989
}
 
990
 
 
991
int ha_recover(HASH *commit_list)
 
992
{
 
993
  struct xarecover_st info;
 
994
  info.found_foreign_xids= info.found_my_xids= 0;
 
995
  info.commit_list= commit_list;
 
996
  info.dry_run= (info.commit_list==0 && tc_heuristic_recover==0);
 
997
  info.list= NULL;
 
998
 
 
999
  /* commit_list and tc_heuristic_recover cannot be set both */
 
1000
  assert(info.commit_list==0 || tc_heuristic_recover==0);
 
1001
  /* if either is set, total_ha_2pc must be set too */
 
1002
  assert(info.dry_run || total_ha_2pc>(uint32_t)opt_bin_log);
 
1003
 
 
1004
  if (total_ha_2pc <= (uint32_t)opt_bin_log)
 
1005
    return(0);
 
1006
 
 
1007
  if (info.commit_list)
 
1008
    errmsg_printf(ERRMSG_LVL_INFO, _("Starting crash recovery..."));
 
1009
 
 
1010
 
 
1011
#ifndef WILL_BE_DELETED_LATER
 
1012
 
 
1013
  /*
 
1014
    for now, only InnoDB supports 2pc. It means we can always safely
 
1015
    rollback all pending transactions, without risking inconsistent data
 
1016
  */
 
1017
 
 
1018
  assert(total_ha_2pc == (uint32_t) opt_bin_log+1); // only InnoDB and binlog
 
1019
  tc_heuristic_recover= TC_HEURISTIC_RECOVER_ROLLBACK; // forcing ROLLBACK
 
1020
  info.dry_run=false;
 
1021
#endif
 
1022
 
 
1023
 
 
1024
  for (info.len= MAX_XID_LIST_SIZE ;
 
1025
       info.list==0 && info.len > MIN_XID_LIST_SIZE; info.len/=2)
 
1026
  {
 
1027
    info.list=(XID *)malloc(info.len*sizeof(XID));
 
1028
  }
 
1029
  if (!info.list)
 
1030
  {
 
1031
    errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_OUTOFMEMORY), info.len*sizeof(XID));
 
1032
    return(1);
 
1033
  }
 
1034
 
 
1035
  plugin_foreach(NULL, xarecover_handlerton,
 
1036
                 DRIZZLE_STORAGE_ENGINE_PLUGIN, &info);
 
1037
 
 
1038
  free((unsigned char*)info.list);
 
1039
  if (info.found_foreign_xids)
 
1040
    errmsg_printf(ERRMSG_LVL_WARN, _("Found %d prepared XA transactions"),
 
1041
                  info.found_foreign_xids);
 
1042
  if (info.dry_run && info.found_my_xids)
 
1043
  {
 
1044
    errmsg_printf(ERRMSG_LVL_ERROR,
 
1045
                  _("Found %d prepared transactions! It means that drizzled "
 
1046
                    "was not shut down properly last time and critical "
 
1047
                    "recovery information (last binlog or %s file) was "
 
1048
                    "manually deleted after a crash. You have to start "
 
1049
                    "drizzled with the --tc-heuristic-recover switch to "
 
1050
                    "commit or rollback pending transactions."),
 
1051
                    info.found_my_xids, opt_tc_log_file);
 
1052
    return(1);
 
1053
  }
 
1054
  if (info.commit_list)
 
1055
    errmsg_printf(ERRMSG_LVL_INFO, _("Crash recovery finished."));
 
1056
  return(0);
 
1057
}
 
1058
 
 
1059
/**
 
1060
  return the list of XID's to a client, the same way SHOW commands do.
 
1061
 
 
1062
  @note
 
1063
    I didn't find in XA specs that an RM cannot return the same XID twice,
 
1064
    so mysql_xa_recover does not filter XID's to ensure uniqueness.
 
1065
    It can be easily fixed later, if necessary.
 
1066
*/
 
1067
bool mysql_xa_recover(Session *session)
 
1068
{
 
1069
  List<Item> field_list;
 
1070
  Protocol *protocol= session->protocol;
 
1071
  int i=0;
 
1072
  XID_STATE *xs;
 
1073
 
 
1074
  field_list.push_back(new Item_int("formatID", 0, MY_INT32_NUM_DECIMAL_DIGITS));
 
1075
  field_list.push_back(new Item_int("gtrid_length", 0, MY_INT32_NUM_DECIMAL_DIGITS));
 
1076
  field_list.push_back(new Item_int("bqual_length", 0, MY_INT32_NUM_DECIMAL_DIGITS));
 
1077
  field_list.push_back(new Item_empty_string("data",XIDDATASIZE));
 
1078
 
 
1079
  if (protocol->send_fields(&field_list,
 
1080
                            Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
 
1081
    return(1);
 
1082
 
 
1083
  pthread_mutex_lock(&LOCK_xid_cache);
 
1084
  while ((xs= (XID_STATE*)hash_element(&xid_cache, i++)))
 
1085
  {
 
1086
    if (xs->xa_state==XA_PREPARED)
 
1087
    {
 
1088
      protocol->prepare_for_resend();
 
1089
      protocol->store_int64_t((int64_t)xs->xid.formatID, false);
 
1090
      protocol->store_int64_t((int64_t)xs->xid.gtrid_length, false);
 
1091
      protocol->store_int64_t((int64_t)xs->xid.bqual_length, false);
 
1092
      protocol->store(xs->xid.data, xs->xid.gtrid_length+xs->xid.bqual_length,
 
1093
                      &my_charset_bin);
 
1094
      if (protocol->write())
 
1095
      {
 
1096
        pthread_mutex_unlock(&LOCK_xid_cache);
 
1097
        return(1);
 
1098
      }
 
1099
    }
 
1100
  }
 
1101
 
 
1102
  pthread_mutex_unlock(&LOCK_xid_cache);
 
1103
  session->my_eof();
 
1104
  return(0);
 
1105
}
 
1106
 
 
1107
/**
 
1108
  @details
 
1109
  This function should be called when MySQL sends rows of a SELECT result set
 
1110
  or the EOF mark to the client. It releases a possible adaptive hash index
 
1111
  S-latch held by session in InnoDB and also releases a possible InnoDB query
 
1112
  FIFO ticket to enter InnoDB. To save CPU time, InnoDB allows a session to
 
1113
  keep them over several calls of the InnoDB handler interface when a join
 
1114
  is executed. But when we let the control to pass to the client they have
 
1115
  to be released because if the application program uses mysql_use_result(),
 
1116
  it may deadlock on the S-latch if the application on another connection
 
1117
  performs another SQL query. In MySQL-4.1 this is even more important because
 
1118
  there a connection can have several SELECT queries open at the same time.
 
1119
 
 
1120
  @param session           the thread handle of the current connection
 
1121
 
 
1122
  @return
 
1123
    always 0
 
1124
*/
 
1125
static bool release_temporary_latches(Session *session, plugin_ref plugin,
 
1126
                                      void *)
 
1127
{
 
1128
  handlerton *hton= plugin_data(plugin, handlerton *);
 
1129
 
 
1130
  if (hton->state == SHOW_OPTION_YES && hton->release_temporary_latches)
 
1131
    hton->release_temporary_latches(hton, session);
 
1132
 
 
1133
  return false;
 
1134
}
 
1135
 
 
1136
 
 
1137
int ha_release_temporary_latches(Session *session)
 
1138
{
 
1139
  plugin_foreach(session, release_temporary_latches, DRIZZLE_STORAGE_ENGINE_PLUGIN,
 
1140
                 NULL);
 
1141
 
 
1142
  return 0;
 
1143
}
 
1144
 
 
1145
int ha_rollback_to_savepoint(Session *session, SAVEPOINT *sv)
 
1146
{
 
1147
  int error=0;
 
1148
  Session_TRANS *trans= &session->transaction.all;
 
1149
  Ha_trx_info *ha_info, *ha_info_next;
 
1150
 
 
1151
  trans->no_2pc=0;
 
1152
  /*
 
1153
    rolling back to savepoint in all storage engines that were part of the
 
1154
    transaction when the savepoint was set
 
1155
  */
 
1156
  for (ha_info= sv->ha_list; ha_info; ha_info= ha_info->next())
 
1157
  {
 
1158
    int err;
 
1159
    handlerton *ht= ha_info->ht();
 
1160
    assert(ht);
 
1161
    assert(ht->savepoint_set != 0);
 
1162
    if ((err= ht->savepoint_rollback(ht, session,
 
1163
                                     (unsigned char *)(sv+1)+ht->savepoint_offset)))
 
1164
    { // cannot happen
 
1165
      my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
 
1166
      error=1;
 
1167
    }
 
1168
    status_var_increment(session->status_var.ha_savepoint_rollback_count);
 
1169
    trans->no_2pc|= ht->prepare == 0;
 
1170
  }
 
1171
  /*
 
1172
    rolling back the transaction in all storage engines that were not part of
 
1173
    the transaction when the savepoint was set
 
1174
  */
 
1175
  for (ha_info= trans->ha_list; ha_info != sv->ha_list;
 
1176
       ha_info= ha_info_next)
 
1177
  {
 
1178
    int err;
 
1179
    handlerton *ht= ha_info->ht();
 
1180
    if ((err= ht->rollback(ht, session, !(0))))
 
1181
    { // cannot happen
 
1182
      my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
 
1183
      error=1;
 
1184
    }
 
1185
    status_var_increment(session->status_var.ha_rollback_count);
 
1186
    ha_info_next= ha_info->next();
 
1187
    ha_info->reset(); /* keep it conveniently zero-filled */
 
1188
  }
 
1189
  trans->ha_list= sv->ha_list;
 
1190
  return(error);
 
1191
}
 
1192
 
 
1193
/**
 
1194
  @note
 
1195
  according to the sql standard (ISO/IEC 9075-2:2003)
 
1196
  section "4.33.4 SQL-statements and transaction states",
 
1197
  SAVEPOINT is *not* transaction-initiating SQL-statement
 
1198
*/
 
1199
int ha_savepoint(Session *session, SAVEPOINT *sv)
 
1200
{
 
1201
  int error=0;
 
1202
  Session_TRANS *trans= &session->transaction.all;
 
1203
  Ha_trx_info *ha_info= trans->ha_list;
 
1204
  for (; ha_info; ha_info= ha_info->next())
 
1205
  {
 
1206
    int err;
 
1207
    handlerton *ht= ha_info->ht();
 
1208
    assert(ht);
 
1209
    if (! ht->savepoint_set)
 
1210
    {
 
1211
      my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "SAVEPOINT");
 
1212
      error=1;
 
1213
      break;
 
1214
    }
 
1215
    if ((err= ht->savepoint_set(ht, session, (unsigned char *)(sv+1)+ht->savepoint_offset)))
 
1216
    { // cannot happen
 
1217
      my_error(ER_GET_ERRNO, MYF(0), err);
 
1218
      error=1;
 
1219
    }
 
1220
    status_var_increment(session->status_var.ha_savepoint_count);
 
1221
  }
 
1222
  /*
 
1223
    Remember the list of registered storage engines. All new
 
1224
    engines are prepended to the beginning of the list.
 
1225
  */
 
1226
  sv->ha_list= trans->ha_list;
 
1227
  return(error);
 
1228
}
 
1229
 
 
1230
int ha_release_savepoint(Session *session, SAVEPOINT *sv)
 
1231
{
 
1232
  int error=0;
 
1233
  Ha_trx_info *ha_info= sv->ha_list;
 
1234
 
 
1235
  for (; ha_info; ha_info= ha_info->next())
 
1236
  {
 
1237
    int err;
 
1238
    handlerton *ht= ha_info->ht();
 
1239
    /* Savepoint life time is enclosed into transaction life time. */
 
1240
    assert(ht);
 
1241
    if (!ht->savepoint_release)
 
1242
      continue;
 
1243
    if ((err= ht->savepoint_release(ht, session,
 
1244
                                    (unsigned char *)(sv+1) + ht->savepoint_offset)))
 
1245
    { // cannot happen
 
1246
      my_error(ER_GET_ERRNO, MYF(0), err);
 
1247
      error=1;
 
1248
    }
 
1249
  }
 
1250
  return(error);
 
1251
}
 
1252
 
 
1253
 
 
1254
static bool snapshot_handlerton(Session *session, plugin_ref plugin, void *arg)
 
1255
{
 
1256
  handlerton *hton= plugin_data(plugin, handlerton *);
 
1257
  if (hton->state == SHOW_OPTION_YES &&
 
1258
      hton->start_consistent_snapshot)
 
1259
  {
 
1260
    hton->start_consistent_snapshot(hton, session);
 
1261
    *((bool *)arg)= false;
 
1262
  }
 
1263
  return false;
 
1264
}
 
1265
 
 
1266
int ha_start_consistent_snapshot(Session *session)
 
1267
{
 
1268
  bool warn= true;
 
1269
 
 
1270
  plugin_foreach(session, snapshot_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN, &warn);
 
1271
 
 
1272
  /*
 
1273
    Same idea as when one wants to CREATE TABLE in one engine which does not
 
1274
    exist:
 
1275
  */
 
1276
  if (warn)
 
1277
    push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
 
1278
                 "This Drizzle server does not support any "
 
1279
                 "consistent-read capable storage engine");
 
1280
  return 0;
 
1281
}
 
1282
 
 
1283
 
 
1284
static bool flush_handlerton(Session *,
 
1285
                             plugin_ref plugin,
 
1286
                             void *)
 
1287
{
 
1288
  handlerton *hton= plugin_data(plugin, handlerton *);
 
1289
  if (hton->state == SHOW_OPTION_YES && hton->flush_logs &&
 
1290
      hton->flush_logs(hton))
 
1291
    return true;
 
1292
  return false;
 
1293
}
 
1294
 
 
1295
 
 
1296
bool ha_flush_logs(handlerton *db_type)
 
1297
{
 
1298
  if (db_type == NULL)
 
1299
  {
 
1300
    if (plugin_foreach(NULL, flush_handlerton,
 
1301
                          DRIZZLE_STORAGE_ENGINE_PLUGIN, 0))
 
1302
      return true;
 
1303
  }
 
1304
  else
 
1305
  {
 
1306
    if (db_type->state != SHOW_OPTION_YES ||
 
1307
        (db_type->flush_logs && db_type->flush_logs(db_type)))
 
1308
      return true;
 
1309
  }
 
1310
  return false;
 
1311
}
 
1312
 
 
1313
static const char *check_lowercase_names(handler *file, const char *path,
 
1314
                                         char *tmp_path)
 
1315
{
 
1316
  if (lower_case_table_names != 2 || (file->ha_table_flags() & HA_FILE_BASED))
 
1317
    return path;
 
1318
 
 
1319
  /* Ensure that table handler get path in lower case */
 
1320
  if (tmp_path != path)
 
1321
    strcpy(tmp_path, path);
 
1322
 
 
1323
  /*
 
1324
    we only should turn into lowercase database/table part
 
1325
    so start the process after homedirectory
 
1326
  */
 
1327
  my_casedn_str(files_charset_info, tmp_path + drizzle_data_home_len);
 
1328
  return tmp_path;
 
1329
}
 
1330
 
 
1331
 
 
1332
/**
 
1333
  An interceptor to hijack the text of the error message without
 
1334
  setting an error in the thread. We need the text to present it
 
1335
  in the form of a warning to the user.
 
1336
*/
 
1337
 
 
1338
struct Ha_delete_table_error_handler: public Internal_error_handler
 
1339
{
 
1340
public:
 
1341
  virtual bool handle_error(uint32_t sql_errno,
 
1342
                            const char *message,
 
1343
                            DRIZZLE_ERROR::enum_warning_level level,
 
1344
                            Session *session);
 
1345
  char buff[DRIZZLE_ERRMSG_SIZE];
 
1346
};
 
1347
 
 
1348
 
 
1349
bool
 
1350
Ha_delete_table_error_handler::
 
1351
handle_error(uint32_t ,
 
1352
             const char *message,
 
1353
             DRIZZLE_ERROR::enum_warning_level ,
 
1354
             Session *)
 
1355
{
 
1356
  /* Grab the error message */
 
1357
  strncpy(buff, message, sizeof(buff)-1);
 
1358
  return true;
 
1359
}
 
1360
 
 
1361
 
 
1362
struct handlerton_delete_table_args {
 
1363
  Session *session;
 
1364
  const char *path;
 
1365
  handler *file;
 
1366
  int error;
 
1367
};
 
1368
 
 
1369
static bool deletetable_handlerton(Session *,
 
1370
                                   plugin_ref plugin,
 
1371
                                   void *args)
 
1372
{
 
1373
  struct handlerton_delete_table_args *dtargs= (struct handlerton_delete_table_args *) args;
 
1374
 
 
1375
  Session *session= dtargs->session;
 
1376
  const char *path= dtargs->path;
 
1377
 
 
1378
  handler *file;
 
1379
  char tmp_path[FN_REFLEN];
 
1380
 
 
1381
  if(dtargs->error!=ENOENT) /* already deleted table */
 
1382
    return false;
 
1383
 
 
1384
  handlerton *table_type= plugin_data(plugin, handlerton *);
 
1385
 
 
1386
  if(!table_type)
 
1387
    return false;
 
1388
 
 
1389
  if(!(table_type->state == SHOW_OPTION_YES && table_type->create))
 
1390
    return false;
 
1391
 
 
1392
  if ((file= table_type->create(table_type, NULL, session->mem_root)))
 
1393
    file->init();
 
1394
  else
 
1395
    return false;
 
1396
 
 
1397
  path= check_lowercase_names(file, path, tmp_path);
 
1398
  int error= file->ha_delete_table(path);
 
1399
 
 
1400
  if(error!=ENOENT)
 
1401
  {
 
1402
    dtargs->error= error;
 
1403
    if(dtargs->file)
 
1404
      delete dtargs->file;
 
1405
    dtargs->file= file;
 
1406
    return true;
 
1407
  }
 
1408
 
 
1409
  return false;
 
1410
}
 
1411
 
 
1412
/**
 
1413
  This should return ENOENT if the file doesn't exists.
 
1414
  The .frm file will be deleted only if we return 0 or ENOENT
 
1415
*/
 
1416
int ha_delete_table(Session *session, const char *path,
 
1417
                    const char *db, const char *alias, bool generate_warning)
 
1418
{
 
1419
  TABLE_SHARE dummy_share;
 
1420
  Table dummy_table;
 
1421
 
 
1422
  struct handlerton_delete_table_args dtargs;
 
1423
  dtargs.error= ENOENT;
 
1424
  dtargs.session= session;
 
1425
  dtargs.path= path;
 
1426
  dtargs.file= NULL;
 
1427
 
 
1428
  plugin_foreach(NULL, deletetable_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN,
 
1429
                 &dtargs);
 
1430
 
 
1431
  memset(&dummy_table, 0, sizeof(dummy_table));
 
1432
  memset(&dummy_share, 0, sizeof(dummy_share));
 
1433
  dummy_table.s= &dummy_share;
 
1434
 
 
1435
  if (dtargs.error && generate_warning)
 
1436
  {
 
1437
    /*
 
1438
      Because file->print_error() use my_error() to generate the error message
 
1439
      we use an internal error handler to intercept it and store the text
 
1440
      in a temporary buffer. Later the message will be presented to user
 
1441
      as a warning.
 
1442
    */
 
1443
    Ha_delete_table_error_handler ha_delete_table_error_handler;
 
1444
 
 
1445
    /* Fill up strucutures that print_error may need */
 
1446
    dummy_share.path.str= (char*) path;
 
1447
    dummy_share.path.length= strlen(path);
 
1448
    dummy_share.db.str= (char*) db;
 
1449
    dummy_share.db.length= strlen(db);
 
1450
    dummy_share.table_name.str= (char*) alias;
 
1451
    dummy_share.table_name.length= strlen(alias);
 
1452
    dummy_table.alias= alias;
 
1453
 
 
1454
    if(dtargs.file)
 
1455
    {
 
1456
      handler *file= dtargs.file;
 
1457
      file->change_table_ptr(&dummy_table, &dummy_share);
 
1458
 
 
1459
      session->push_internal_handler(&ha_delete_table_error_handler);
 
1460
      file->print_error(dtargs.error, 0);
 
1461
 
 
1462
      session->pop_internal_handler();
 
1463
    }
 
1464
    else
 
1465
      dtargs.error= -1; /* General form of fail. maybe bad FRM */
 
1466
 
 
1467
    /*
 
1468
      XXX: should we convert *all* errors to warnings here?
 
1469
      What if the error is fatal?
 
1470
    */
 
1471
    push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR, dtargs.error,
 
1472
                ha_delete_table_error_handler.buff);
 
1473
  }
 
1474
 
 
1475
  if(dtargs.file)
 
1476
    delete dtargs.file;
 
1477
 
 
1478
  return dtargs.error;
 
1479
}
53
1480
 
54
1481
/****************************************************************************
55
 
** General Cursor functions
 
1482
** General handler functions
56
1483
****************************************************************************/
57
 
Cursor::Cursor(plugin::StorageEngine &engine_arg,
58
 
               Table &arg)
59
 
  : table(arg),
60
 
    engine(engine_arg),
61
 
    estimation_rows_to_insert(0),
62
 
    ref(0),
63
 
    key_used_on_scan(MAX_KEY), active_index(MAX_KEY),
64
 
    ref_length(sizeof(internal::my_off_t)),
65
 
    inited(NONE),
66
 
    locked(false),
67
 
    next_insert_id(0), insert_id_for_cur_row(0)
68
 
{ }
69
 
 
70
 
Cursor::~Cursor(void)
71
 
{
72
 
  assert(locked == false);
73
 
  /* TODO: assert(inited == NONE); */
74
 
}
75
 
 
76
 
 
77
 
/*
78
 
 * @note this only used in
79
 
 * optimizer::QuickRangeSelect::init_ror_merged_scan(bool reuse_handler) as
80
 
 * of the writing of this comment. -Brian
81
 
 */
82
 
Cursor *Cursor::clone(memory::Root *mem_root)
83
 
{
84
 
  Cursor *new_handler= getTable()->getMutableShare()->db_type()->getCursor(*getTable());
85
 
 
 
1484
handler *handler::clone(MEM_ROOT *mem_root)
 
1485
{
 
1486
  handler *new_handler= get_new_handler(table->s, mem_root, table->s->db_type());
86
1487
  /*
87
 
    Allocate Cursor->ref here because otherwise ha_open will allocate it
 
1488
    Allocate handler->ref here because otherwise ha_open will allocate it
88
1489
    on this->table->mem_root and we will not be able to reclaim that memory
89
 
    when the clone Cursor object is destroyed.
 
1490
    when the clone handler object is destroyed.
90
1491
  */
91
 
  if (!(new_handler->ref= (unsigned char*) mem_root->alloc_root(ALIGN_SIZE(ref_length)*2)))
 
1492
  if (!(new_handler->ref= (unsigned char*) alloc_root(mem_root, ALIGN_SIZE(ref_length)*2)))
92
1493
    return NULL;
93
 
 
94
 
  identifier::Table identifier(getTable()->getShare()->getSchemaName(),
95
 
                             getTable()->getShare()->getTableName(),
96
 
                             getTable()->getShare()->getType());
97
 
 
98
 
  if (new_handler && !new_handler->ha_open(identifier,
99
 
                                           getTable()->getDBStat(),
 
1494
  if (new_handler && !new_handler->ha_open(table,
 
1495
                                           table->s->normalized_path.str,
 
1496
                                           table->getDBStat(),
100
1497
                                           HA_OPEN_IGNORE_IF_LOCKED))
101
1498
    return new_handler;
102
1499
  return NULL;
103
1500
}
104
1501
 
105
 
/*
106
 
  DESCRIPTION
107
 
    given a buffer with a key value, and a map of keyparts
108
 
    that are present in this value, returns the length of the value
109
 
*/
110
 
uint32_t Cursor::calculate_key_len(uint32_t key_position, key_part_map keypart_map_arg)
111
 
{
112
 
  /* works only with key prefixes */
113
 
  assert(((keypart_map_arg + 1) & keypart_map_arg) == 0);
114
 
 
115
 
  const KeyPartInfo *key_part_found= getTable()->getShare()->getKeyInfo(key_position).key_part;
116
 
  const KeyPartInfo *end_key_part_found= key_part_found + getTable()->getShare()->getKeyInfo(key_position).key_parts;
117
 
  uint32_t length= 0;
118
 
 
119
 
  while (key_part_found < end_key_part_found && keypart_map_arg)
120
 
  {
121
 
    length+= key_part_found->store_length;
122
 
    keypart_map_arg >>= 1;
123
 
    key_part_found++;
124
 
  }
125
 
  return length;
126
 
}
127
 
 
128
 
int Cursor::startIndexScan(uint32_t idx, bool sorted)
 
1502
int handler::ha_index_init(uint32_t idx, bool sorted)
129
1503
{
130
1504
  int result;
131
 
  assert(inited == NONE);
132
 
  if (!(result= doStartIndexScan(idx, sorted)))
 
1505
  assert(inited==NONE);
 
1506
  if (!(result= index_init(idx, sorted)))
133
1507
    inited=INDEX;
134
1508
  end_range= NULL;
135
 
  return result;
 
1509
  return(result);
136
1510
}
137
1511
 
138
 
int Cursor::endIndexScan()
 
1512
int handler::ha_index_end()
139
1513
{
140
1514
  assert(inited==INDEX);
141
1515
  inited=NONE;
142
1516
  end_range= NULL;
143
 
  return(doEndIndexScan());
 
1517
  return(index_end());
144
1518
}
145
1519
 
146
 
int Cursor::startTableScan(bool scan)
 
1520
int handler::ha_rnd_init(bool scan)
147
1521
{
148
1522
  int result;
149
1523
  assert(inited==NONE || (inited==RND && scan));
150
 
  inited= (result= doStartTableScan(scan)) ? NONE: RND;
151
 
 
152
 
  return result;
 
1524
  inited= (result= rnd_init(scan)) ? NONE: RND;
 
1525
  return(result);
153
1526
}
154
1527
 
155
 
int Cursor::endTableScan()
 
1528
int handler::ha_rnd_end()
156
1529
{
157
1530
  assert(inited==RND);
158
1531
  inited=NONE;
159
 
  return(doEndTableScan());
160
 
}
161
 
 
162
 
int Cursor::ha_index_or_rnd_end()
163
 
{
164
 
  return inited == INDEX ? endIndexScan() : inited == RND ? endTableScan() : 0;
165
 
}
166
 
 
167
 
void Cursor::ha_start_bulk_insert(ha_rows rows)
 
1532
  return(rnd_end());
 
1533
}
 
1534
 
 
1535
int handler::ha_index_or_rnd_end()
 
1536
{
 
1537
  return inited == INDEX ? ha_index_end() : inited == RND ? ha_rnd_end() : 0;
 
1538
}
 
1539
 
 
1540
handler::Table_flags handler::ha_table_flags() const
 
1541
{
 
1542
  return cached_table_flags;
 
1543
}
 
1544
 
 
1545
void handler::ha_start_bulk_insert(ha_rows rows)
168
1546
{
169
1547
  estimation_rows_to_insert= rows;
170
1548
  start_bulk_insert(rows);
171
1549
}
172
1550
 
173
 
int Cursor::ha_end_bulk_insert()
 
1551
int handler::ha_end_bulk_insert()
174
1552
{
175
1553
  estimation_rows_to_insert= 0;
176
1554
  return end_bulk_insert();
177
1555
}
178
1556
 
179
 
const key_map *Cursor::keys_to_use_for_scanning()
 
1557
void handler::change_table_ptr(Table *table_arg, TABLE_SHARE *share)
 
1558
{
 
1559
  table= table_arg;
 
1560
  table_share= share;
 
1561
}
 
1562
 
 
1563
const key_map *handler::keys_to_use_for_scanning()
180
1564
{
181
1565
  return &key_map_empty;
182
1566
}
183
1567
 
184
 
bool Cursor::has_transactions()
185
 
{
186
 
  return (getTable()->getShare()->db_type()->check_flag(HTON_BIT_DOES_TRANSACTIONS));
187
 
}
188
 
 
189
 
void Cursor::ha_statistic_increment(uint64_t system_status_var::*offset) const
190
 
{
191
 
  (getTable()->in_use->status_var.*offset)++;
192
 
}
193
 
 
194
 
void **Cursor::ha_data(Session *session) const
195
 
{
196
 
  return session->getEngineData(getEngine());
197
 
}
198
 
 
199
 
bool Cursor::is_fatal_error(int error, uint32_t flags)
 
1568
bool handler::has_transactions()
 
1569
{
 
1570
  return (ha_table_flags() & HA_NO_TRANSACTIONS) == 0;
 
1571
}
 
1572
 
 
1573
void handler::ha_statistic_increment(ulong SSV::*offset) const
 
1574
{
 
1575
  status_var_increment(table->in_use->status_var.*offset);
 
1576
}
 
1577
 
 
1578
void **handler::ha_data(Session *session) const
 
1579
{
 
1580
  return session_ha_data(session, ht);
 
1581
}
 
1582
 
 
1583
Session *handler::ha_session(void) const
 
1584
{
 
1585
  assert(!table || !table->in_use || table->in_use == current_session);
 
1586
  return (table && table->in_use) ? table->in_use : current_session;
 
1587
}
 
1588
 
 
1589
 
 
1590
bool handler::is_fatal_error(int error, uint32_t flags)
200
1591
{
201
1592
  if (!error ||
202
1593
      ((flags & HA_CHECK_DUP_KEY) &&
207
1598
}
208
1599
 
209
1600
 
210
 
ha_rows Cursor::records() { return stats.records; }
211
 
uint64_t Cursor::tableSize() { return stats.index_file_length + stats.data_file_length; }
212
 
uint64_t Cursor::rowSize() { return getTable()->getRecordLength() + getTable()->sizeFields(); }
213
 
 
214
 
int Cursor::doOpen(const identifier::Table &identifier, int mode, uint32_t test_if_locked)
215
 
{
216
 
  return open(identifier.getPath().c_str(), mode, test_if_locked);
217
 
}
 
1601
ha_rows handler::records() { return stats.records; }
218
1602
 
219
1603
/**
220
 
  Open database-Cursor.
 
1604
  Open database-handler.
221
1605
 
222
1606
  Try O_RDONLY if cannot open as O_RDWR
223
1607
  Don't wait for locks if not HA_OPEN_WAIT_IF_LOCKED is set
224
1608
*/
225
 
int Cursor::ha_open(const identifier::Table &identifier,
226
 
                    int mode,
227
 
                    int test_if_locked)
 
1609
int handler::ha_open(Table *table_arg, const char *name, int mode,
 
1610
                     int test_if_locked)
228
1611
{
229
1612
  int error;
230
1613
 
231
 
  if ((error= doOpen(identifier, mode, test_if_locked)))
 
1614
  table= table_arg;
 
1615
  assert(table->s == table_share);
 
1616
  assert(alloc_root_inited(&table->mem_root));
 
1617
 
 
1618
  if ((error=open(name,mode,test_if_locked)))
232
1619
  {
233
1620
    if ((error == EACCES || error == EROFS) && mode == O_RDWR &&
234
 
        (getTable()->db_stat & HA_TRY_READ_ONLY))
 
1621
        (table->db_stat & HA_TRY_READ_ONLY))
235
1622
    {
236
 
      getTable()->db_stat|=HA_READ_ONLY;
237
 
      error= doOpen(identifier, O_RDONLY,test_if_locked);
 
1623
      table->db_stat|=HA_READ_ONLY;
 
1624
      error=open(name,O_RDONLY,test_if_locked);
238
1625
    }
239
1626
  }
240
1627
  if (error)
241
1628
  {
242
 
    errno= error;                            /* Safeguard */
 
1629
    my_errno= error;                            /* Safeguard */
243
1630
  }
244
1631
  else
245
1632
  {
246
 
    if (getTable()->getShare()->db_options_in_use & HA_OPTION_READ_ONLY_DATA)
247
 
      getTable()->db_stat|=HA_READ_ONLY;
 
1633
    if (table->s->db_options_in_use & HA_OPTION_READ_ONLY_DATA)
 
1634
      table->db_stat|=HA_READ_ONLY;
248
1635
    (void) extra(HA_EXTRA_NO_READCHECK);        // Not needed in SQL
249
1636
 
250
 
    /* ref is already allocated for us if we're called from Cursor::clone() */
251
 
    if (!ref && !(ref= (unsigned char*) getTable()->alloc_root(ALIGN_SIZE(ref_length)*2)))
 
1637
    /* ref is already allocated for us if we're called from handler::clone() */
 
1638
    if (!ref && !(ref= (unsigned char*) alloc_root(&table->mem_root,
 
1639
                                          ALIGN_SIZE(ref_length)*2)))
252
1640
    {
253
1641
      close();
254
1642
      error=HA_ERR_OUT_OF_MEM;
255
1643
    }
256
1644
    else
257
1645
      dup_ref=ref+ALIGN_SIZE(ref_length);
 
1646
    cached_table_flags= table_flags();
258
1647
  }
259
 
  return error;
 
1648
  return(error);
 
1649
}
 
1650
 
 
1651
/**
 
1652
  one has to use this method when to find
 
1653
  random position by record as the plain
 
1654
  position() call doesn't work for some
 
1655
  handlers for random position
 
1656
*/
 
1657
 
 
1658
int handler::rnd_pos_by_record(unsigned char *record)
 
1659
{
 
1660
  register int error;
 
1661
 
 
1662
  position(record);
 
1663
  if (inited && (error= ha_index_end()))
 
1664
    return(error);
 
1665
  if ((error= ha_rnd_init(false)))
 
1666
    return(error);
 
1667
 
 
1668
  return(rnd_pos(record, ref));
260
1669
}
261
1670
 
262
1671
/**
265
1674
  This is never called for InnoDB tables, as these table types
266
1675
  has the HA_STATS_RECORDS_IS_EXACT set.
267
1676
*/
268
 
int Cursor::read_first_row(unsigned char * buf, uint32_t primary_key)
 
1677
int handler::read_first_row(unsigned char * buf, uint32_t primary_key)
269
1678
{
270
1679
  register int error;
271
1680
 
272
 
  ha_statistic_increment(&system_status_var::ha_read_first_count);
 
1681
  ha_statistic_increment(&SSV::ha_read_first_count);
273
1682
 
274
1683
  /*
275
1684
    If there is very few deleted rows in the table, find the first row by
277
1686
    TODO remove the test for HA_READ_ORDER
278
1687
  */
279
1688
  if (stats.deleted < 10 || primary_key >= MAX_KEY ||
280
 
      !(getTable()->index_flags(primary_key) & HA_READ_ORDER))
 
1689
      !(index_flags(primary_key, 0, 0) & HA_READ_ORDER))
281
1690
  {
282
 
    error= startTableScan(1);
283
 
    if (error == 0)
284
 
    {
285
 
      while ((error= rnd_next(buf)) == HA_ERR_RECORD_DELETED) ;
286
 
      (void) endTableScan();
287
 
    }
 
1691
    (void) ha_rnd_init(1);
 
1692
    while ((error= rnd_next(buf)) == HA_ERR_RECORD_DELETED) ;
 
1693
    (void) ha_rnd_end();
288
1694
  }
289
1695
  else
290
1696
  {
291
1697
    /* Find the first row through the primary key */
292
 
    error= startIndexScan(primary_key, 0);
293
 
    if (error == 0)
294
 
    {
295
 
      error=index_first(buf);
296
 
      (void) endIndexScan();
297
 
    }
 
1698
    (void) ha_index_init(primary_key, 0);
 
1699
    error=index_first(buf);
 
1700
    (void) ha_index_end();
298
1701
  }
299
 
  return error;
 
1702
  return(error);
300
1703
}
301
1704
 
302
1705
/**
311
1714
  @verbatim 1,5,15,25,35,... @endverbatim
312
1715
*/
313
1716
inline uint64_t
314
 
compute_next_insert_id(uint64_t nr, drizzle_system_variables *variables)
 
1717
compute_next_insert_id(uint64_t nr,struct system_variables *variables)
315
1718
{
316
1719
  if (variables->auto_increment_increment == 1)
317
1720
    return (nr+1); // optimization of the formula below
323
1726
}
324
1727
 
325
1728
 
326
 
void Cursor::adjust_next_insert_id_after_explicit_value(uint64_t nr)
 
1729
void handler::adjust_next_insert_id_after_explicit_value(uint64_t nr)
327
1730
{
328
1731
  /*
329
1732
    If we have set Session::next_insert_id previously and plan to insert an
331
1734
    Session::next_insert_id to be greater than the explicit value.
332
1735
  */
333
1736
  if ((next_insert_id > 0) && (nr >= next_insert_id))
334
 
    set_next_insert_id(compute_next_insert_id(nr, &getTable()->in_use->variables));
 
1737
    set_next_insert_id(compute_next_insert_id(nr, &table->in_use->variables));
335
1738
}
336
1739
 
337
1740
 
351
1754
    The number X if it exists, "nr" otherwise.
352
1755
*/
353
1756
inline uint64_t
354
 
prev_insert_id(uint64_t nr, drizzle_system_variables *variables)
 
1757
prev_insert_id(uint64_t nr, struct system_variables *variables)
355
1758
{
356
1759
  if (unlikely(nr < variables->auto_increment_offset))
357
1760
  {
376
1779
 
377
1780
  Updates columns with type NEXT_NUMBER if:
378
1781
 
379
 
  - If column value is set to NULL (in which case auto_increment_field_not_null is false)
 
1782
  - If column value is set to NULL (in which case
 
1783
    auto_increment_field_not_null is 0)
380
1784
  - If column is set to 0 and (sql_mode & MODE_NO_AUTO_VALUE_ON_ZERO) is not
381
1785
    set. In the future we will only set NEXT_NUMBER fields if one sets them
382
1786
    to NULL (or they are not included in the insert list).
397
1801
    reserved for us.
398
1802
 
399
1803
  - In both cases, for the following rows we use those reserved values without
400
 
    calling the Cursor again (we just progress in the interval, computing
 
1804
    calling the handler again (we just progress in the interval, computing
401
1805
    each new value from the previous one). Until we have exhausted them, then
402
1806
    we either take the next provided interval or call get_auto_increment()
403
1807
    again to reserve a new interval.
444
1848
#define AUTO_INC_DEFAULT_NB_MAX_BITS 16
445
1849
#define AUTO_INC_DEFAULT_NB_MAX ((1 << AUTO_INC_DEFAULT_NB_MAX_BITS) - 1)
446
1850
 
447
 
int Cursor::update_auto_increment()
 
1851
int handler::update_auto_increment()
448
1852
{
449
1853
  uint64_t nr, nb_reserved_values;
450
1854
  bool append= false;
451
 
  Session *session= getTable()->in_use;
452
 
  drizzle_system_variables *variables= &session->variables;
 
1855
  Session *session= table->in_use;
 
1856
  struct system_variables *variables= &session->variables;
453
1857
 
454
1858
  /*
455
1859
    next_insert_id is a "cursor" into the reserved interval, it may go greater
457
1861
  */
458
1862
  assert(next_insert_id >= auto_inc_interval_for_cur_row.minimum());
459
1863
 
460
 
  /* We check if auto_increment_field_not_null is false
461
 
     for an auto increment column, not a magic value like NULL is.
462
 
     same as sql_mode=NO_AUTO_VALUE_ON_ZERO */
463
 
 
464
 
  if ((nr= getTable()->next_number_field->val_int()) != 0
465
 
      || getTable()->auto_increment_field_not_null)
 
1864
  if ((nr= table->next_number_field->val_int()) != 0)
466
1865
  {
467
1866
    /*
468
1867
      Update next_insert_id if we had already generated a value in this
472
1871
    */
473
1872
    adjust_next_insert_id_after_explicit_value(nr);
474
1873
    insert_id_for_cur_row= 0; // didn't generate anything
475
 
 
476
 
    return 0;
 
1874
    return(0);
477
1875
  }
478
1876
 
479
1877
  if ((nr= next_insert_id) >= auto_inc_interval_for_cur_row.maximum())
489
1887
    else
490
1888
    {
491
1889
      /*
492
 
        Cursor::estimation_rows_to_insert was set by
493
 
        Cursor::ha_start_bulk_insert(); if 0 it means "unknown".
 
1890
        handler::estimation_rows_to_insert was set by
 
1891
        handler::ha_start_bulk_insert(); if 0 it means "unknown".
494
1892
      */
495
1893
      uint32_t nb_already_reserved_intervals=
496
1894
        session->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements();
516
1914
        {
517
1915
          nb_desired_values= AUTO_INC_DEFAULT_NB_ROWS *
518
1916
            (1 << nb_already_reserved_intervals);
519
 
          set_if_smaller(nb_desired_values, (uint64_t)AUTO_INC_DEFAULT_NB_MAX);
 
1917
          set_if_smaller(nb_desired_values, AUTO_INC_DEFAULT_NB_MAX);
520
1918
        }
521
1919
        else
522
1920
          nb_desired_values= AUTO_INC_DEFAULT_NB_MAX;
527
1925
                         nb_desired_values, &nr,
528
1926
                         &nb_reserved_values);
529
1927
      if (nr == ~(uint64_t) 0)
530
 
        return HA_ERR_AUTOINC_READ_FAILED;  // Mark failure
 
1928
        return(HA_ERR_AUTOINC_READ_FAILED);  // Mark failure
531
1929
 
532
1930
      /*
533
1931
        That rounding below should not be needed when all engines actually
540
1938
      nr= compute_next_insert_id(nr-1, variables);
541
1939
    }
542
1940
 
543
 
    if (getTable()->getShare()->next_number_keypart == 0)
 
1941
    if (table->s->next_number_keypart == 0)
544
1942
    {
545
1943
      /* We must defer the appending until "nr" has been possibly truncated */
546
1944
      append= true;
547
1945
    }
548
1946
  }
549
1947
 
550
 
  if (unlikely(getTable()->next_number_field->store((int64_t) nr, true)))
 
1948
  if (unlikely(table->next_number_field->store((int64_t) nr, true)))
551
1949
  {
552
1950
    /*
553
1951
      first test if the query was aborted due to strict mode constraints
554
1952
    */
555
 
    if (session->getKilled() == Session::KILL_BAD_DATA)
556
 
      return HA_ERR_AUTOINC_ERANGE;
 
1953
    if (session->killed == Session::KILL_BAD_DATA)
 
1954
      return(HA_ERR_AUTOINC_ERANGE);
557
1955
 
558
1956
    /*
559
1957
      field refused this value (overflow) and truncated it, use the result of
563
1961
      bother shifting the right bound (anyway any other value from this
564
1962
      interval will cause a duplicate key).
565
1963
    */
566
 
    nr= prev_insert_id(getTable()->next_number_field->val_int(), variables);
567
 
    if (unlikely(getTable()->next_number_field->store((int64_t) nr, true)))
568
 
      nr= getTable()->next_number_field->val_int();
 
1964
    nr= prev_insert_id(table->next_number_field->val_int(), variables);
 
1965
    if (unlikely(table->next_number_field->store((int64_t) nr, true)))
 
1966
      nr= table->next_number_field->val_int();
569
1967
  }
570
1968
  if (append)
571
1969
  {
587
1985
  */
588
1986
  set_next_insert_id(compute_next_insert_id(nr, variables));
589
1987
 
590
 
  return 0;
591
 
}
592
 
 
593
 
 
594
 
/**
595
 
  Reserves an interval of auto_increment values from the Cursor.
 
1988
  return(0);
 
1989
}
 
1990
 
 
1991
 
 
1992
/**
 
1993
  MySQL signal that it changed the column bitmap
 
1994
 
 
1995
  This is for handlers that needs to setup their own column bitmaps.
 
1996
  Normally the handler should set up their own column bitmaps in
 
1997
  index_init() or rnd_init() and in any column_bitmaps_signal() call after
 
1998
  this.
 
1999
 
 
2000
  The handler is allowed to do changes to the bitmap after a index_init or
 
2001
  rnd_init() call is made as after this, MySQL will not use the bitmap
 
2002
  for any program logic checking.
 
2003
*/
 
2004
void handler::column_bitmaps_signal()
 
2005
{
 
2006
  return;
 
2007
}
 
2008
 
 
2009
 
 
2010
/**
 
2011
  Reserves an interval of auto_increment values from the handler.
596
2012
 
597
2013
  offset and increment means that we want values to be of the form
598
2014
  offset + N * increment, where N>=0 is integer.
603
2019
  @param offset
604
2020
  @param increment
605
2021
  @param nb_desired_values   how many values we want
606
 
  @param first_value         (OUT) the first value reserved by the Cursor
607
 
  @param nb_reserved_values  (OUT) how many values the Cursor reserved
 
2022
  @param first_value         (OUT) the first value reserved by the handler
 
2023
  @param nb_reserved_values  (OUT) how many values the handler reserved
608
2024
*/
609
 
 
610
 
void Cursor::ha_release_auto_increment()
 
2025
void handler::get_auto_increment(uint64_t ,
 
2026
                                 uint64_t ,
 
2027
                                 uint64_t ,
 
2028
                                 uint64_t *first_value,
 
2029
                                 uint64_t *nb_reserved_values)
 
2030
{
 
2031
  uint64_t nr;
 
2032
  int error;
 
2033
 
 
2034
  (void) extra(HA_EXTRA_KEYREAD);
 
2035
  table->mark_columns_used_by_index_no_reset(table->s->next_number_index,
 
2036
                                        table->read_set);
 
2037
  column_bitmaps_signal();
 
2038
  index_init(table->s->next_number_index, 1);
 
2039
  if (table->s->next_number_keypart == 0)
 
2040
  {                                             // Autoincrement at key-start
 
2041
    error=index_last(table->record[1]);
 
2042
    /*
 
2043
      MySQL implicitely assumes such method does locking (as MySQL decides to
 
2044
      use nr+increment without checking again with the handler, in
 
2045
      handler::update_auto_increment()), so reserves to infinite.
 
2046
    */
 
2047
    *nb_reserved_values= UINT64_MAX;
 
2048
  }
 
2049
  else
 
2050
  {
 
2051
    unsigned char key[MAX_KEY_LENGTH];
 
2052
    key_copy(key, table->record[0],
 
2053
             table->key_info + table->s->next_number_index,
 
2054
             table->s->next_number_key_offset);
 
2055
    error= index_read_map(table->record[1], key,
 
2056
                          make_prev_keypart_map(table->s->next_number_keypart),
 
2057
                          HA_READ_PREFIX_LAST);
 
2058
    /*
 
2059
      MySQL needs to call us for next row: assume we are inserting ("a",null)
 
2060
      here, we return 3, and next this statement will want to insert
 
2061
      ("b",null): there is no reason why ("b",3+1) would be the good row to
 
2062
      insert: maybe it already exists, maybe 3+1 is too large...
 
2063
    */
 
2064
    *nb_reserved_values= 1;
 
2065
  }
 
2066
 
 
2067
  if (error)
 
2068
    nr=1;
 
2069
  else
 
2070
    nr= ((uint64_t) table->next_number_field->
 
2071
         val_int_offset(table->s->rec_buff_length)+1);
 
2072
  index_end();
 
2073
  (void) extra(HA_EXTRA_NO_KEYREAD);
 
2074
  *first_value= nr;
 
2075
}
 
2076
 
 
2077
 
 
2078
void handler::ha_release_auto_increment()
611
2079
{
612
2080
  release_auto_increment();
613
2081
  insert_id_for_cur_row= 0;
619
2087
      this statement used forced auto_increment values if there were some,
620
2088
      wipe them away for other statements.
621
2089
    */
622
 
    getTable()->in_use->auto_inc_intervals_forced.empty();
623
 
  }
624
 
}
625
 
 
626
 
void Cursor::drop_table(const char *)
 
2090
    table->in_use->auto_inc_intervals_forced.empty();
 
2091
  }
 
2092
}
 
2093
 
 
2094
 
 
2095
void handler::print_keydup_error(uint32_t key_nr, const char *msg)
 
2096
{
 
2097
  /* Write the duplicated key in the error message */
 
2098
  char key[MAX_KEY_LENGTH];
 
2099
  String str(key,sizeof(key),system_charset_info);
 
2100
 
 
2101
  if (key_nr == MAX_KEY)
 
2102
  {
 
2103
    /* Key is unknown */
 
2104
    str.copy("", 0, system_charset_info);
 
2105
    my_printf_error(ER_DUP_ENTRY, msg, MYF(0), str.c_ptr(), "*UNKNOWN*");
 
2106
  }
 
2107
  else
 
2108
  {
 
2109
    /* Table is opened and defined at this point */
 
2110
    key_unpack(&str,table,(uint32_t) key_nr);
 
2111
    uint32_t max_length=DRIZZLE_ERRMSG_SIZE-(uint32_t) strlen(msg);
 
2112
    if (str.length() >= max_length)
 
2113
    {
 
2114
      str.length(max_length-4);
 
2115
      str.append(STRING_WITH_LEN("..."));
 
2116
    }
 
2117
    my_printf_error(ER_DUP_ENTRY, msg,
 
2118
                    MYF(0), str.c_ptr(), table->key_info[key_nr].name);
 
2119
  }
 
2120
}
 
2121
 
 
2122
 
 
2123
/**
 
2124
  Print error that we got from handler function.
 
2125
 
 
2126
  @note
 
2127
    In case of delete table it's only safe to use the following parts of
 
2128
    the 'table' structure:
 
2129
    - table->s->path
 
2130
    - table->alias
 
2131
*/
 
2132
void handler::print_error(int error, myf errflag)
 
2133
{
 
2134
  int textno=ER_GET_ERRNO;
 
2135
  switch (error) {
 
2136
  case EACCES:
 
2137
    textno=ER_OPEN_AS_READONLY;
 
2138
    break;
 
2139
  case EAGAIN:
 
2140
    textno=ER_FILE_USED;
 
2141
    break;
 
2142
  case ENOENT:
 
2143
    textno=ER_FILE_NOT_FOUND;
 
2144
    break;
 
2145
  case HA_ERR_KEY_NOT_FOUND:
 
2146
  case HA_ERR_NO_ACTIVE_RECORD:
 
2147
  case HA_ERR_END_OF_FILE:
 
2148
    textno=ER_KEY_NOT_FOUND;
 
2149
    break;
 
2150
  case HA_ERR_WRONG_MRG_TABLE_DEF:
 
2151
    textno=ER_WRONG_MRG_TABLE;
 
2152
    break;
 
2153
  case HA_ERR_FOUND_DUPP_KEY:
 
2154
  {
 
2155
    uint32_t key_nr=get_dup_key(error);
 
2156
    if ((int) key_nr >= 0)
 
2157
    {
 
2158
      print_keydup_error(key_nr, ER(ER_DUP_ENTRY_WITH_KEY_NAME));
 
2159
      return;
 
2160
    }
 
2161
    textno=ER_DUP_KEY;
 
2162
    break;
 
2163
  }
 
2164
  case HA_ERR_FOREIGN_DUPLICATE_KEY:
 
2165
  {
 
2166
    uint32_t key_nr= get_dup_key(error);
 
2167
    if ((int) key_nr >= 0)
 
2168
    {
 
2169
      uint32_t max_length;
 
2170
      /* Write the key in the error message */
 
2171
      char key[MAX_KEY_LENGTH];
 
2172
      String str(key,sizeof(key),system_charset_info);
 
2173
      /* Table is opened and defined at this point */
 
2174
      key_unpack(&str,table,(uint32_t) key_nr);
 
2175
      max_length= (DRIZZLE_ERRMSG_SIZE-
 
2176
                   (uint32_t) strlen(ER(ER_FOREIGN_DUPLICATE_KEY)));
 
2177
      if (str.length() >= max_length)
 
2178
      {
 
2179
        str.length(max_length-4);
 
2180
        str.append(STRING_WITH_LEN("..."));
 
2181
      }
 
2182
      my_error(ER_FOREIGN_DUPLICATE_KEY, MYF(0), table_share->table_name.str,
 
2183
        str.c_ptr(), key_nr+1);
 
2184
      return;
 
2185
    }
 
2186
    textno= ER_DUP_KEY;
 
2187
    break;
 
2188
  }
 
2189
  case HA_ERR_FOUND_DUPP_UNIQUE:
 
2190
    textno=ER_DUP_UNIQUE;
 
2191
    break;
 
2192
  case HA_ERR_RECORD_CHANGED:
 
2193
    textno=ER_CHECKREAD;
 
2194
    break;
 
2195
  case HA_ERR_CRASHED:
 
2196
    textno=ER_NOT_KEYFILE;
 
2197
    break;
 
2198
  case HA_ERR_WRONG_IN_RECORD:
 
2199
    textno= ER_CRASHED_ON_USAGE;
 
2200
    break;
 
2201
  case HA_ERR_CRASHED_ON_USAGE:
 
2202
    textno=ER_CRASHED_ON_USAGE;
 
2203
    break;
 
2204
  case HA_ERR_NOT_A_TABLE:
 
2205
    textno= error;
 
2206
    break;
 
2207
  case HA_ERR_CRASHED_ON_REPAIR:
 
2208
    textno=ER_CRASHED_ON_REPAIR;
 
2209
    break;
 
2210
  case HA_ERR_OUT_OF_MEM:
 
2211
    textno=ER_OUT_OF_RESOURCES;
 
2212
    break;
 
2213
  case HA_ERR_WRONG_COMMAND:
 
2214
    textno=ER_ILLEGAL_HA;
 
2215
    break;
 
2216
  case HA_ERR_OLD_FILE:
 
2217
    textno=ER_OLD_KEYFILE;
 
2218
    break;
 
2219
  case HA_ERR_UNSUPPORTED:
 
2220
    textno=ER_UNSUPPORTED_EXTENSION;
 
2221
    break;
 
2222
  case HA_ERR_RECORD_FILE_FULL:
 
2223
  case HA_ERR_INDEX_FILE_FULL:
 
2224
    textno=ER_RECORD_FILE_FULL;
 
2225
    break;
 
2226
  case HA_ERR_LOCK_WAIT_TIMEOUT:
 
2227
    textno=ER_LOCK_WAIT_TIMEOUT;
 
2228
    break;
 
2229
  case HA_ERR_LOCK_TABLE_FULL:
 
2230
    textno=ER_LOCK_TABLE_FULL;
 
2231
    break;
 
2232
  case HA_ERR_LOCK_DEADLOCK:
 
2233
    textno=ER_LOCK_DEADLOCK;
 
2234
    break;
 
2235
  case HA_ERR_READ_ONLY_TRANSACTION:
 
2236
    textno=ER_READ_ONLY_TRANSACTION;
 
2237
    break;
 
2238
  case HA_ERR_CANNOT_ADD_FOREIGN:
 
2239
    textno=ER_CANNOT_ADD_FOREIGN;
 
2240
    break;
 
2241
  case HA_ERR_ROW_IS_REFERENCED:
 
2242
  {
 
2243
    String str;
 
2244
    get_error_message(error, &str);
 
2245
    my_error(ER_ROW_IS_REFERENCED_2, MYF(0), str.c_ptr_safe());
 
2246
    return;
 
2247
  }
 
2248
  case HA_ERR_NO_REFERENCED_ROW:
 
2249
  {
 
2250
    String str;
 
2251
    get_error_message(error, &str);
 
2252
    my_error(ER_NO_REFERENCED_ROW_2, MYF(0), str.c_ptr_safe());
 
2253
    return;
 
2254
  }
 
2255
  case HA_ERR_TABLE_DEF_CHANGED:
 
2256
    textno=ER_TABLE_DEF_CHANGED;
 
2257
    break;
 
2258
  case HA_ERR_NO_SUCH_TABLE:
 
2259
    my_error(ER_NO_SUCH_TABLE, MYF(0), table_share->db.str,
 
2260
             table_share->table_name.str);
 
2261
    return;
 
2262
  case HA_ERR_RBR_LOGGING_FAILED:
 
2263
    textno= ER_BINLOG_ROW_LOGGING_FAILED;
 
2264
    break;
 
2265
  case HA_ERR_DROP_INDEX_FK:
 
2266
  {
 
2267
    const char *ptr= "???";
 
2268
    uint32_t key_nr= get_dup_key(error);
 
2269
    if ((int) key_nr >= 0)
 
2270
      ptr= table->key_info[key_nr].name;
 
2271
    my_error(ER_DROP_INDEX_FK, MYF(0), ptr);
 
2272
    return;
 
2273
  }
 
2274
  case HA_ERR_TABLE_NEEDS_UPGRADE:
 
2275
    textno=ER_TABLE_NEEDS_UPGRADE;
 
2276
    break;
 
2277
  case HA_ERR_TABLE_READONLY:
 
2278
    textno= ER_OPEN_AS_READONLY;
 
2279
    break;
 
2280
  case HA_ERR_AUTOINC_READ_FAILED:
 
2281
    textno= ER_AUTOINC_READ_FAILED;
 
2282
    break;
 
2283
  case HA_ERR_AUTOINC_ERANGE:
 
2284
    textno= ER_WARN_DATA_OUT_OF_RANGE;
 
2285
    break;
 
2286
  case HA_ERR_LOCK_OR_ACTIVE_TRANSACTION:
 
2287
    my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
 
2288
               ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
 
2289
    return;
 
2290
  default:
 
2291
    {
 
2292
      /* The error was "unknown" to this function.
 
2293
         Ask handler if it has got a message for this error */
 
2294
      bool temporary= false;
 
2295
      String str;
 
2296
      temporary= get_error_message(error, &str);
 
2297
      if (!str.is_empty())
 
2298
      {
 
2299
        const char* engine= table_type();
 
2300
        if (temporary)
 
2301
          my_error(ER_GET_TEMPORARY_ERRMSG, MYF(0), error, str.ptr(), engine);
 
2302
        else
 
2303
          my_error(ER_GET_ERRMSG, MYF(0), error, str.ptr(), engine);
 
2304
      }
 
2305
      else
 
2306
        my_error(ER_GET_ERRNO,errflag,error);
 
2307
      return;
 
2308
    }
 
2309
  }
 
2310
  my_error(textno, errflag, table_share->table_name.str, error);
 
2311
  return;
 
2312
}
 
2313
 
 
2314
 
 
2315
/**
 
2316
  Return an error message specific to this handler.
 
2317
 
 
2318
  @param error  error code previously returned by handler
 
2319
  @param buf    pointer to String where to add error message
 
2320
 
 
2321
  @return
 
2322
    Returns true if this is a temporary error
 
2323
*/
 
2324
bool handler::get_error_message(int ,
 
2325
                                String* )
 
2326
{
 
2327
  return false;
 
2328
}
 
2329
 
 
2330
 
 
2331
int handler::ha_check_for_upgrade(HA_CHECK_OPT *check_opt)
 
2332
{
 
2333
  KEY *keyinfo, *keyend;
 
2334
  KEY_PART_INFO *keypart, *keypartend;
 
2335
 
 
2336
  if (!table->s->mysql_version)
 
2337
  {
 
2338
    /* check for blob-in-key error */
 
2339
    keyinfo= table->key_info;
 
2340
    keyend= table->key_info + table->s->keys;
 
2341
    for (; keyinfo < keyend; keyinfo++)
 
2342
    {
 
2343
      keypart= keyinfo->key_part;
 
2344
      keypartend= keypart + keyinfo->key_parts;
 
2345
      for (; keypart < keypartend; keypart++)
 
2346
      {
 
2347
        if (!keypart->fieldnr)
 
2348
          continue;
 
2349
        Field *field= table->field[keypart->fieldnr-1];
 
2350
        if (field->type() == DRIZZLE_TYPE_BLOB)
 
2351
        {
 
2352
          return HA_ADMIN_NEEDS_CHECK;
 
2353
        }
 
2354
      }
 
2355
    }
 
2356
  }
 
2357
  return check_for_upgrade(check_opt);
 
2358
}
 
2359
 
 
2360
 
 
2361
/* Code left, but Drizzle has no legacy yet (while MySQL did) */
 
2362
int handler::check_old_types()
 
2363
{
 
2364
  return 0;
 
2365
}
 
2366
 
 
2367
/**
 
2368
  @return
 
2369
    key if error because of duplicated keys
 
2370
*/
 
2371
uint32_t handler::get_dup_key(int error)
 
2372
{
 
2373
  table->file->errkey  = (uint32_t) -1;
 
2374
  if (error == HA_ERR_FOUND_DUPP_KEY || error == HA_ERR_FOREIGN_DUPLICATE_KEY ||
 
2375
      error == HA_ERR_FOUND_DUPP_UNIQUE ||
 
2376
      error == HA_ERR_DROP_INDEX_FK)
 
2377
    info(HA_STATUS_ERRKEY | HA_STATUS_NO_LOCK);
 
2378
  return(table->file->errkey);
 
2379
}
 
2380
 
 
2381
 
 
2382
/**
 
2383
  Delete all files with extension from bas_ext().
 
2384
 
 
2385
  @param name           Base name of table
 
2386
 
 
2387
  @note
 
2388
    We assume that the handler may return more extensions than
 
2389
    was actually used for the file.
 
2390
 
 
2391
  @retval
 
2392
    0   If we successfully deleted at least one file from base_ext and
 
2393
    didn't get any other errors than ENOENT
 
2394
  @retval
 
2395
    !0  Error
 
2396
*/
 
2397
int handler::delete_table(const char *name)
 
2398
{
 
2399
  int error= 0;
 
2400
  int enoent_or_zero= ENOENT;                   // Error if no file was deleted
 
2401
  char buff[FN_REFLEN];
 
2402
 
 
2403
  for (const char **ext=bas_ext(); *ext ; ext++)
 
2404
  {
 
2405
    fn_format(buff, name, "", *ext, MY_UNPACK_FILENAME|MY_APPEND_EXT);
 
2406
    if (my_delete_with_symlink(buff, MYF(0)))
 
2407
    {
 
2408
      if ((error= my_errno) != ENOENT)
 
2409
        break;
 
2410
    }
 
2411
    else
 
2412
      enoent_or_zero= 0;                        // No error for ENOENT
 
2413
    error= enoent_or_zero;
 
2414
  }
 
2415
  return error;
 
2416
}
 
2417
 
 
2418
 
 
2419
int handler::rename_table(const char * from, const char * to)
 
2420
{
 
2421
  int error= 0;
 
2422
  for (const char **ext= bas_ext(); *ext ; ext++)
 
2423
  {
 
2424
    if (rename_file_ext(from, to, *ext))
 
2425
    {
 
2426
      if ((error=my_errno) != ENOENT)
 
2427
        break;
 
2428
      error= 0;
 
2429
    }
 
2430
  }
 
2431
  return error;
 
2432
}
 
2433
 
 
2434
 
 
2435
void handler::drop_table(const char *name)
627
2436
{
628
2437
  close();
 
2438
  delete_table(name);
629
2439
}
630
2440
 
631
2441
 
644
2454
  @retval
645
2455
    HA_ADMIN_NOT_IMPLEMENTED
646
2456
*/
647
 
int Cursor::ha_check(Session *, HA_CHECK_OPT *)
 
2457
int handler::ha_check(Session *session, HA_CHECK_OPT *check_opt)
648
2458
{
 
2459
  int error;
 
2460
 
 
2461
  if (table->s->mysql_version < DRIZZLE_VERSION_ID)
 
2462
  {
 
2463
    if ((error= check_old_types()))
 
2464
      return error;
 
2465
    error= ha_check_for_upgrade(check_opt);
 
2466
    if (error && (error != HA_ADMIN_NEEDS_CHECK))
 
2467
      return error;
 
2468
  }
 
2469
  if ((error= check(session, check_opt)))
 
2470
    return error;
649
2471
  return HA_ADMIN_OK;
650
2472
}
651
2473
 
656
2478
 
657
2479
inline
658
2480
void
659
 
Cursor::setTransactionReadWrite()
 
2481
handler::mark_trx_read_write()
660
2482
{
661
 
  ResourceContext *resource_context;
662
 
 
663
 
  /*
664
 
   * If the cursor has not context for execution then there should be no
665
 
   * possible resource to gain (and if there is... then there is a bug such
666
 
   * that in_use should have been set.
667
 
 */
668
 
  if (not getTable()->in_use)
669
 
    return;
670
 
 
671
 
  resource_context= getTable()->in_use->getResourceContext(getEngine());
 
2483
  Ha_trx_info *ha_info= &ha_session()->ha_data[ht->slot].ha_info[0];
672
2484
  /*
673
2485
    When a storage engine method is called, the transaction must
674
2486
    have been started, unless it's a DDL call, for which the
677
2489
    Unfortunately here we can't know know for sure if the engine
678
2490
    has registered the transaction or not, so we must check.
679
2491
  */
680
 
  if (resource_context->isStarted())
 
2492
  if (ha_info->is_started())
681
2493
  {
682
 
    resource_context->markModifiedData();
 
2494
    /*
 
2495
      table_share can be NULL in ha_delete_table(). See implementation
 
2496
      of standalone function ha_delete_table() in sql_base.cc.
 
2497
    */
 
2498
    if (table_share == NULL || table_share->tmp_table == NO_TMP_TABLE)
 
2499
      ha_info->set_trx_read_write();
683
2500
  }
684
2501
}
685
2502
 
686
2503
 
687
2504
/**
 
2505
  Repair table: public interface.
 
2506
 
 
2507
  @sa handler::repair()
 
2508
*/
 
2509
 
 
2510
int handler::ha_repair(Session* session, HA_CHECK_OPT* check_opt)
 
2511
{
 
2512
  int result;
 
2513
 
 
2514
  mark_trx_read_write();
 
2515
 
 
2516
  if ((result= repair(session, check_opt)))
 
2517
    return result;
 
2518
  return HA_ADMIN_OK;
 
2519
}
 
2520
 
 
2521
 
 
2522
/**
 
2523
  Bulk update row: public interface.
 
2524
 
 
2525
  @sa handler::bulk_update_row()
 
2526
*/
 
2527
 
 
2528
int
 
2529
handler::ha_bulk_update_row(const unsigned char *old_data, unsigned char *new_data,
 
2530
                            uint32_t *dup_key_found)
 
2531
{
 
2532
  mark_trx_read_write();
 
2533
 
 
2534
  return bulk_update_row(old_data, new_data, dup_key_found);
 
2535
}
 
2536
 
 
2537
 
 
2538
/**
688
2539
  Delete all rows: public interface.
689
2540
 
690
 
  @sa Cursor::delete_all_rows()
691
 
 
692
 
  @note
693
 
 
694
 
  This is now equalivalent to TRUNCATE TABLE.
 
2541
  @sa handler::delete_all_rows()
695
2542
*/
696
2543
 
697
2544
int
698
 
Cursor::ha_delete_all_rows()
 
2545
handler::ha_delete_all_rows()
699
2546
{
700
 
  setTransactionReadWrite();
701
 
 
702
 
  int result= delete_all_rows();
703
 
 
704
 
  if (result == 0)
705
 
  {
706
 
    /** 
707
 
     * Trigger post-truncate notification to plugins... 
708
 
     *
709
 
     * @todo Make TransactionServices generic to AfterTriggerServices
710
 
     * or similar...
711
 
     */
712
 
    Session *const session= getTable()->in_use;
713
 
    TransactionServices &transaction_services= TransactionServices::singleton();
714
 
    transaction_services.truncateTable(*session, *getTable());
715
 
  }
716
 
 
717
 
  return result;
 
2547
  mark_trx_read_write();
 
2548
 
 
2549
  return delete_all_rows();
718
2550
}
719
2551
 
720
2552
 
721
2553
/**
722
2554
  Reset auto increment: public interface.
723
2555
 
724
 
  @sa Cursor::reset_auto_increment()
 
2556
  @sa handler::reset_auto_increment()
725
2557
*/
726
2558
 
727
2559
int
728
 
Cursor::ha_reset_auto_increment(uint64_t value)
 
2560
handler::ha_reset_auto_increment(uint64_t value)
729
2561
{
730
 
  setTransactionReadWrite();
 
2562
  mark_trx_read_write();
731
2563
 
732
2564
  return reset_auto_increment(value);
733
2565
}
734
2566
 
735
2567
 
736
2568
/**
 
2569
  Optimize table: public interface.
 
2570
 
 
2571
  @sa handler::optimize()
 
2572
*/
 
2573
 
 
2574
int
 
2575
handler::ha_optimize(Session* session, HA_CHECK_OPT* check_opt)
 
2576
{
 
2577
  mark_trx_read_write();
 
2578
 
 
2579
  return optimize(session, check_opt);
 
2580
}
 
2581
 
 
2582
 
 
2583
/**
737
2584
  Analyze table: public interface.
738
2585
 
739
 
  @sa Cursor::analyze()
 
2586
  @sa handler::analyze()
740
2587
*/
741
2588
 
742
2589
int
743
 
Cursor::ha_analyze(Session* session, HA_CHECK_OPT*)
744
 
{
745
 
  setTransactionReadWrite();
746
 
 
747
 
  return analyze(session);
748
 
}
 
2590
handler::ha_analyze(Session* session, HA_CHECK_OPT* check_opt)
 
2591
{
 
2592
  mark_trx_read_write();
 
2593
 
 
2594
  return analyze(session, check_opt);
 
2595
}
 
2596
 
 
2597
 
 
2598
/**
 
2599
  Check and repair table: public interface.
 
2600
 
 
2601
  @sa handler::check_and_repair()
 
2602
*/
 
2603
 
 
2604
bool
 
2605
handler::ha_check_and_repair(Session *session)
 
2606
{
 
2607
  mark_trx_read_write();
 
2608
 
 
2609
  return check_and_repair(session);
 
2610
}
 
2611
 
749
2612
 
750
2613
/**
751
2614
  Disable indexes: public interface.
752
2615
 
753
 
  @sa Cursor::disable_indexes()
 
2616
  @sa handler::disable_indexes()
754
2617
*/
755
2618
 
756
2619
int
757
 
Cursor::ha_disable_indexes(uint32_t mode)
 
2620
handler::ha_disable_indexes(uint32_t mode)
758
2621
{
759
 
  setTransactionReadWrite();
 
2622
  mark_trx_read_write();
760
2623
 
761
2624
  return disable_indexes(mode);
762
2625
}
765
2628
/**
766
2629
  Enable indexes: public interface.
767
2630
 
768
 
  @sa Cursor::enable_indexes()
 
2631
  @sa handler::enable_indexes()
769
2632
*/
770
2633
 
771
2634
int
772
 
Cursor::ha_enable_indexes(uint32_t mode)
 
2635
handler::ha_enable_indexes(uint32_t mode)
773
2636
{
774
 
  setTransactionReadWrite();
 
2637
  mark_trx_read_write();
775
2638
 
776
2639
  return enable_indexes(mode);
777
2640
}
780
2643
/**
781
2644
  Discard or import tablespace: public interface.
782
2645
 
783
 
  @sa Cursor::discard_or_import_tablespace()
 
2646
  @sa handler::discard_or_import_tablespace()
784
2647
*/
785
2648
 
786
2649
int
787
 
Cursor::ha_discard_or_import_tablespace(bool discard)
 
2650
handler::ha_discard_or_import_tablespace(bool discard)
788
2651
{
789
 
  setTransactionReadWrite();
 
2652
  mark_trx_read_write();
790
2653
 
791
2654
  return discard_or_import_tablespace(discard);
792
2655
}
793
2656
 
 
2657
 
 
2658
/**
 
2659
  Prepare for alter: public interface.
 
2660
 
 
2661
  Called to prepare an *online* ALTER.
 
2662
 
 
2663
  @sa handler::prepare_for_alter()
 
2664
*/
 
2665
 
 
2666
void
 
2667
handler::ha_prepare_for_alter()
 
2668
{
 
2669
  mark_trx_read_write();
 
2670
 
 
2671
  prepare_for_alter();
 
2672
}
 
2673
 
 
2674
 
 
2675
/**
 
2676
  Rename table: public interface.
 
2677
 
 
2678
  @sa handler::rename_table()
 
2679
*/
 
2680
 
 
2681
int
 
2682
handler::ha_rename_table(const char *from, const char *to)
 
2683
{
 
2684
  mark_trx_read_write();
 
2685
 
 
2686
  return rename_table(from, to);
 
2687
}
 
2688
 
 
2689
 
 
2690
/**
 
2691
  Delete table: public interface.
 
2692
 
 
2693
  @sa handler::delete_table()
 
2694
*/
 
2695
 
 
2696
int
 
2697
handler::ha_delete_table(const char *name)
 
2698
{
 
2699
  mark_trx_read_write();
 
2700
 
 
2701
  return delete_table(name);
 
2702
}
 
2703
 
 
2704
 
794
2705
/**
795
2706
  Drop table in the engine: public interface.
796
2707
 
797
 
  @sa Cursor::drop_table()
 
2708
  @sa handler::drop_table()
798
2709
*/
799
2710
 
800
2711
void
801
 
Cursor::closeMarkForDelete(const char *name)
 
2712
handler::ha_drop_table(const char *name)
802
2713
{
803
 
  setTransactionReadWrite();
 
2714
  mark_trx_read_write();
804
2715
 
805
2716
  return drop_table(name);
806
2717
}
807
2718
 
808
 
int Cursor::index_next_same(unsigned char *buf, const unsigned char *key, uint32_t keylen)
 
2719
 
 
2720
/**
 
2721
  Create a table in the engine: public interface.
 
2722
 
 
2723
  @sa handler::create()
 
2724
*/
 
2725
 
 
2726
int
 
2727
handler::ha_create(const char *name, Table *form, HA_CREATE_INFO *create_info)
 
2728
{
 
2729
  mark_trx_read_write();
 
2730
 
 
2731
  return create(name, form, create_info);
 
2732
}
 
2733
 
 
2734
 
 
2735
/**
 
2736
  Create handler files for CREATE TABLE: public interface.
 
2737
 
 
2738
  @sa handler::create_handler_files()
 
2739
*/
 
2740
 
 
2741
int
 
2742
handler::ha_create_handler_files(const char *name, const char *old_name,
 
2743
                                 int action_flag, HA_CREATE_INFO *create_info)
 
2744
{
 
2745
  mark_trx_read_write();
 
2746
 
 
2747
  return create_handler_files(name, old_name, action_flag, create_info);
 
2748
}
 
2749
 
 
2750
 
 
2751
/**
 
2752
  Tell the storage engine that it is allowed to "disable transaction" in the
 
2753
  handler. It is a hint that ACID is not required - it is used in NDB for
 
2754
  ALTER Table, for example, when data are copied to temporary table.
 
2755
  A storage engine may treat this hint any way it likes. NDB for example
 
2756
  starts to commit every now and then automatically.
 
2757
  This hint can be safely ignored.
 
2758
*/
 
2759
int ha_enable_transaction(Session *session, bool on)
 
2760
{
 
2761
  int error=0;
 
2762
 
 
2763
  if ((session->transaction.on= on))
 
2764
  {
 
2765
    /*
 
2766
      Now all storage engines should have transaction handling enabled.
 
2767
      But some may have it enabled all the time - "disabling" transactions
 
2768
      is an optimization hint that storage engine is free to ignore.
 
2769
      So, let's commit an open transaction (if any) now.
 
2770
    */
 
2771
    if (!(error= ha_commit_trans(session, 0)))
 
2772
      error= end_trans(session, COMMIT);
 
2773
  }
 
2774
  return(error);
 
2775
}
 
2776
 
 
2777
int handler::index_next_same(unsigned char *buf, const unsigned char *key, uint32_t keylen)
809
2778
{
810
2779
  int error;
811
2780
  if (!(error=index_next(buf)))
812
2781
  {
813
 
    ptrdiff_t ptrdiff= buf - getTable()->getInsertRecord();
 
2782
    my_ptrdiff_t ptrdiff= buf - table->record[0];
814
2783
    unsigned char *save_record_0= NULL;
815
 
    KeyInfo *key_info= NULL;
816
 
    KeyPartInfo *key_part;
817
 
    KeyPartInfo *key_part_end= NULL;
 
2784
    KEY *key_info= NULL;
 
2785
    KEY_PART_INFO *key_part;
 
2786
    KEY_PART_INFO *key_part_end= NULL;
818
2787
 
819
2788
    /*
820
 
      key_cmp_if_same() compares table->getInsertRecord() against 'key'.
821
 
      In parts it uses table->getInsertRecord() directly, in parts it uses
822
 
      field objects with their local pointers into table->getInsertRecord().
823
 
      If 'buf' is distinct from table->getInsertRecord(), we need to move
824
 
      all record references. This is table->getInsertRecord() itself and
 
2789
      key_cmp_if_same() compares table->record[0] against 'key'.
 
2790
      In parts it uses table->record[0] directly, in parts it uses
 
2791
      field objects with their local pointers into table->record[0].
 
2792
      If 'buf' is distinct from table->record[0], we need to move
 
2793
      all record references. This is table->record[0] itself and
825
2794
      the field pointers of the fields used in this key.
826
2795
    */
827
2796
    if (ptrdiff)
828
2797
    {
829
 
      save_record_0= getTable()->getInsertRecord();
830
 
      getTable()->record[0]= buf;
831
 
      key_info= getTable()->key_info + active_index;
 
2798
      save_record_0= table->record[0];
 
2799
      table->record[0]= buf;
 
2800
      key_info= table->key_info + active_index;
832
2801
      key_part= key_info->key_part;
833
2802
      key_part_end= key_part + key_info->key_parts;
834
2803
      for (; key_part < key_part_end; key_part++)
838
2807
      }
839
2808
    }
840
2809
 
841
 
    if (key_cmp_if_same(getTable(), key, active_index, keylen))
 
2810
    if (key_cmp_if_same(table, key, active_index, keylen))
842
2811
    {
843
 
      getTable()->status=STATUS_NOT_FOUND;
 
2812
      table->status=STATUS_NOT_FOUND;
844
2813
      error=HA_ERR_END_OF_FILE;
845
2814
    }
846
2815
 
847
2816
    /* Move back if necessary. */
848
2817
    if (ptrdiff)
849
2818
    {
850
 
      getTable()->record[0]= save_record_0;
 
2819
      table->record[0]= save_record_0;
851
2820
      for (key_part= key_info->key_part; key_part < key_part_end; key_part++)
852
2821
        key_part->field->move_field_offset(-ptrdiff);
853
2822
    }
854
2823
  }
855
 
  return error;
 
2824
  return(error);
856
2825
}
857
2826
 
858
2827
 
859
2828
/****************************************************************************
860
 
** Some general functions that isn't in the Cursor class
 
2829
** Some general functions that isn't in the handler class
861
2830
****************************************************************************/
862
2831
 
863
2832
/**
 
2833
  Initiates table-file and calls appropriate database-creator.
 
2834
 
 
2835
  @retval
 
2836
   0  ok
 
2837
  @retval
 
2838
   1  error
 
2839
*/
 
2840
int ha_create_table(Session *session, const char *path,
 
2841
                    const char *db, const char *table_name,
 
2842
                    HA_CREATE_INFO *create_info,
 
2843
                    bool update_create_info)
 
2844
{
 
2845
  int error= 1;
 
2846
  Table table;
 
2847
  char name_buff[FN_REFLEN];
 
2848
  const char *name;
 
2849
  TABLE_SHARE share;
 
2850
 
 
2851
  init_tmp_table_share(session, &share, db, 0, table_name, path);
 
2852
  if (open_table_def(session, &share, 0) ||
 
2853
      open_table_from_share(session, &share, "", 0, (uint32_t) READ_ALL, 0, &table,
 
2854
                            OTM_CREATE))
 
2855
    goto err;
 
2856
 
 
2857
  if (update_create_info)
 
2858
    table.updateCreateInfo(create_info);
 
2859
 
 
2860
  name= check_lowercase_names(table.file, share.path.str, name_buff);
 
2861
 
 
2862
  error= table.file->ha_create(name, &table, create_info);
 
2863
  table.closefrm(false);
 
2864
  if (error)
 
2865
  {
 
2866
    sprintf(name_buff,"%s.%s",db,table_name);
 
2867
    my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), name_buff, error);
 
2868
  }
 
2869
err:
 
2870
  free_table_share(&share);
 
2871
  return(error != 0);
 
2872
}
 
2873
 
 
2874
void st_ha_check_opt::init()
 
2875
{
 
2876
  flags= 0; 
 
2877
  use_frm= false;
 
2878
}
 
2879
 
 
2880
 
 
2881
/*****************************************************************************
 
2882
  Key cache handling.
 
2883
 
 
2884
  This code is only relevant for ISAM/MyISAM tables
 
2885
 
 
2886
  key_cache->cache may be 0 only in the case where a key cache is not
 
2887
  initialized or when we where not able to init the key cache in a previous
 
2888
  call to ha_init_key_cache() (probably out of memory)
 
2889
*****************************************************************************/
 
2890
 
 
2891
/**
 
2892
  Init a key cache if it has not been initied before.
 
2893
*/
 
2894
int ha_init_key_cache(const char *,
 
2895
                      KEY_CACHE *key_cache)
 
2896
{
 
2897
  if (!key_cache->key_cache_inited)
 
2898
  {
 
2899
    pthread_mutex_lock(&LOCK_global_system_variables);
 
2900
    uint32_t tmp_buff_size= (uint32_t) key_cache->param_buff_size;
 
2901
    uint32_t tmp_block_size= (uint32_t) key_cache->param_block_size;
 
2902
    uint32_t division_limit= key_cache->param_division_limit;
 
2903
    uint32_t age_threshold=  key_cache->param_age_threshold;
 
2904
    pthread_mutex_unlock(&LOCK_global_system_variables);
 
2905
    return(!init_key_cache(key_cache,
 
2906
                                tmp_block_size,
 
2907
                                tmp_buff_size,
 
2908
                                division_limit, age_threshold));
 
2909
  }
 
2910
  return(0);
 
2911
}
 
2912
 
 
2913
 
 
2914
/**
 
2915
  Resize key cache.
 
2916
*/
 
2917
int ha_resize_key_cache(KEY_CACHE *key_cache)
 
2918
{
 
2919
  if (key_cache->key_cache_inited)
 
2920
  {
 
2921
    pthread_mutex_lock(&LOCK_global_system_variables);
 
2922
    long tmp_buff_size= (long) key_cache->param_buff_size;
 
2923
    long tmp_block_size= (long) key_cache->param_block_size;
 
2924
    uint32_t division_limit= key_cache->param_division_limit;
 
2925
    uint32_t age_threshold=  key_cache->param_age_threshold;
 
2926
    pthread_mutex_unlock(&LOCK_global_system_variables);
 
2927
    return(!resize_key_cache(key_cache, tmp_block_size,
 
2928
                                  tmp_buff_size,
 
2929
                                  division_limit, age_threshold));
 
2930
  }
 
2931
  return(0);
 
2932
}
 
2933
 
 
2934
 
 
2935
/**
 
2936
  Change parameters for key cache (like size)
 
2937
*/
 
2938
int ha_change_key_cache_param(KEY_CACHE *key_cache)
 
2939
{
 
2940
  if (key_cache->key_cache_inited)
 
2941
  {
 
2942
    pthread_mutex_lock(&LOCK_global_system_variables);
 
2943
    uint32_t division_limit= key_cache->param_division_limit;
 
2944
    uint32_t age_threshold=  key_cache->param_age_threshold;
 
2945
    pthread_mutex_unlock(&LOCK_global_system_variables);
 
2946
    change_key_cache_param(key_cache, division_limit, age_threshold);
 
2947
  }
 
2948
  return 0;
 
2949
}
 
2950
 
 
2951
/**
 
2952
  Free memory allocated by a key cache.
 
2953
*/
 
2954
int ha_end_key_cache(KEY_CACHE *key_cache)
 
2955
{
 
2956
  end_key_cache(key_cache, 1);          // Can never fail
 
2957
  return 0;
 
2958
}
 
2959
 
 
2960
/**
 
2961
  Move all tables from one key cache to another one.
 
2962
*/
 
2963
int ha_change_key_cache(KEY_CACHE *old_key_cache,
 
2964
                        KEY_CACHE *new_key_cache)
 
2965
{
 
2966
  mi_change_key_cache(old_key_cache, new_key_cache);
 
2967
  return 0;
 
2968
}
 
2969
 
 
2970
/**
 
2971
  Call this function in order to give the handler the possiblity
 
2972
  to ask engine if there are any new tables that should be written to disk
 
2973
  or any dropped tables that need to be removed from disk
 
2974
*/
 
2975
struct st_find_files_args
 
2976
{
 
2977
  const char *db;
 
2978
  const char *path;
 
2979
  const char *wild;
 
2980
  bool dir;
 
2981
  List<LEX_STRING> *files;
 
2982
};
 
2983
 
 
2984
/**
 
2985
  Ask handler if the table exists in engine.
 
2986
  @retval
 
2987
    HA_ERR_NO_SUCH_TABLE     Table does not exist
 
2988
  @retval
 
2989
    HA_ERR_TABLE_EXIST       Table exists
 
2990
  @retval
 
2991
    \#                  Error code
 
2992
*/
 
2993
struct st_table_exists_in_engine_args
 
2994
{
 
2995
  const char *db;
 
2996
  const char *name;
 
2997
  int err;
 
2998
  handlerton* hton;
 
2999
};
 
3000
 
 
3001
static bool table_exists_in_engine_handlerton(Session *session, plugin_ref plugin,
 
3002
                                              void *arg)
 
3003
{
 
3004
  st_table_exists_in_engine_args *vargs= (st_table_exists_in_engine_args *)arg;
 
3005
  handlerton *hton= plugin_data(plugin, handlerton *);
 
3006
 
 
3007
  int err= HA_ERR_NO_SUCH_TABLE;
 
3008
 
 
3009
  if (hton->state == SHOW_OPTION_YES && hton->table_exists_in_engine)
 
3010
    err = hton->table_exists_in_engine(hton, session, vargs->db, vargs->name);
 
3011
 
 
3012
  vargs->err = err;
 
3013
  if (vargs->err == HA_ERR_TABLE_EXIST)
 
3014
  {
 
3015
    vargs->hton= hton;
 
3016
    return true;
 
3017
  }
 
3018
 
 
3019
  return false;
 
3020
}
 
3021
 
 
3022
int ha_table_exists_in_engine(Session* session,
 
3023
                              const char* db, const char* name,
 
3024
                              handlerton **hton)
 
3025
{
 
3026
  st_table_exists_in_engine_args args= {db, name, HA_ERR_NO_SUCH_TABLE, NULL};
 
3027
  plugin_foreach(session, table_exists_in_engine_handlerton,
 
3028
                 DRIZZLE_STORAGE_ENGINE_PLUGIN, &args);
 
3029
 
 
3030
  if(args.err==HA_ERR_NO_SUCH_TABLE)
 
3031
  {
 
3032
    /* Default way of knowing if a table exists. (checking .frm exists) */
 
3033
 
 
3034
    char path[FN_REFLEN];
 
3035
    build_table_filename(path, sizeof(path),
 
3036
                         db, name, ".dfe", 0);
 
3037
    if (!access(path, F_OK))
 
3038
      args.err= HA_ERR_TABLE_EXIST;
 
3039
    else
 
3040
      args.err= HA_ERR_NO_SUCH_TABLE;
 
3041
 
 
3042
    if(args.err==HA_ERR_TABLE_EXIST)
 
3043
    {
 
3044
      drizzle::Table table;
 
3045
      if(drizzle_read_table_proto(path, &table)==0)
 
3046
      {
 
3047
        LEX_STRING engine_name= { (char*)table.engine().name().c_str(),
 
3048
                                 strlen(table.engine().name().c_str()) };
 
3049
        plugin_ref plugin= ha_resolve_by_name(session, &engine_name);
 
3050
        if(plugin)
 
3051
          args.hton= plugin_data(plugin,handlerton *);
 
3052
      }
 
3053
    }
 
3054
  }
 
3055
 
 
3056
  if(hton)
 
3057
    *hton= args.hton;
 
3058
 
 
3059
  return(args.err);
 
3060
}
 
3061
 
 
3062
/**
864
3063
  Calculate cost of 'index only' scan for given index and number of records
865
3064
 
866
3065
  @param keynr    Index number
869
3068
  @note
870
3069
    It is assumed that we will read trough the whole key range and that all
871
3070
    key blocks are half full (normally things are much better). It is also
872
 
    assumed that each time we read the next key from the index, the Cursor
 
3071
    assumed that each time we read the next key from the index, the handler
873
3072
    performs a random seek, thus the cost is proportional to the number of
874
3073
    blocks read.
875
3074
 
876
3075
  @todo
877
 
    Consider joining this function and Cursor::read_time() into one
878
 
    Cursor::read_time(keynr, records, ranges, bool index_only) function.
 
3076
    Consider joining this function and handler::read_time() into one
 
3077
    handler::read_time(keynr, records, ranges, bool index_only) function.
879
3078
 
880
3079
  @return
881
3080
    Estimated cost of 'index only' scan
882
3081
*/
883
3082
 
884
 
double Cursor::index_only_read_time(uint32_t keynr, double key_records)
 
3083
double handler::index_only_read_time(uint32_t keynr, double key_records)
885
3084
{
886
3085
  uint32_t keys_per_block= (stats.block_size/2/
887
 
                        (getTable()->key_info[keynr].key_length + ref_length) + 1);
 
3086
                        (table->key_info[keynr].key_length + ref_length) + 1);
888
3087
  return ((double) (key_records + keys_per_block-1) /
889
3088
          (double) keys_per_block);
890
3089
}
913
3112
 
914
3113
  @note
915
3114
    This method (or an overriding one in a derived class) must check for
916
 
    session->getKilled() and return HA_POS_ERROR if it is not zero. This is required
 
3115
    session->killed and return HA_POS_ERROR if it is not zero. This is required
917
3116
    for a user to be able to interrupt the calculation by killing the
918
3117
    connection/query.
919
3118
 
926
3125
*/
927
3126
 
928
3127
ha_rows
929
 
Cursor::multi_range_read_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
 
3128
handler::multi_range_read_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
930
3129
                                     void *seq_init_param,
931
3130
                                     uint32_t ,
932
 
                                     uint32_t *bufsz, uint32_t *flags, optimizer::CostVector *cost)
 
3131
                                     uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
933
3132
{
934
3133
  KEY_MULTI_RANGE range;
935
3134
  range_seq_t seq_it;
936
3135
  ha_rows rows, total_rows= 0;
937
3136
  uint32_t n_ranges=0;
 
3137
  Session *session= current_session;
938
3138
 
939
3139
  /* Default MRR implementation doesn't need buffer */
940
3140
  *bufsz= 0;
942
3142
  seq_it= seq->init(seq_init_param, n_ranges, *flags);
943
3143
  while (!seq->next(seq_it, &range))
944
3144
  {
 
3145
    if (unlikely(session->killed != 0))
 
3146
      return HA_POS_ERROR;
 
3147
 
945
3148
    n_ranges++;
946
3149
    key_range *min_endp, *max_endp;
947
3150
    {
968
3171
    /* The following calculation is the same as in multi_range_read_info(): */
969
3172
    *flags |= HA_MRR_USE_DEFAULT_IMPL;
970
3173
    cost->zero();
971
 
    cost->setAvgIOCost(1); /* assume random seeks */
 
3174
    cost->avg_io_cost= 1; /* assume random seeks */
972
3175
    if ((*flags & HA_MRR_INDEX_ONLY) && total_rows > 2)
973
 
      cost->setIOCount(index_only_read_time(keyno, (uint32_t)total_rows));
 
3176
      cost->io_count= index_only_read_time(keyno, (uint32_t)total_rows);
974
3177
    else
975
 
      cost->setIOCount(read_time(keyno, n_ranges, total_rows));
976
 
    cost->setCpuCost((double) total_rows / TIME_FOR_COMPARE + 0.01);
 
3178
      cost->io_count= read_time(keyno, n_ranges, total_rows);
 
3179
    cost->cpu_cost= (double) total_rows / TIME_FOR_COMPARE + 0.01;
977
3180
  }
978
3181
  return total_rows;
979
3182
}
1013
3216
    other Error or can't perform the requested scan
1014
3217
*/
1015
3218
 
1016
 
int Cursor::multi_range_read_info(uint32_t keyno, uint32_t n_ranges, uint32_t n_rows,
1017
 
                                   uint32_t *bufsz, uint32_t *flags, optimizer::CostVector *cost)
 
3219
int handler::multi_range_read_info(uint32_t keyno, uint32_t n_ranges, uint32_t n_rows,
 
3220
                                   uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
1018
3221
{
1019
3222
  *bufsz= 0; /* Default implementation doesn't need a buffer */
1020
3223
 
1021
3224
  *flags |= HA_MRR_USE_DEFAULT_IMPL;
1022
3225
 
1023
3226
  cost->zero();
1024
 
  cost->setAvgIOCost(1); /* assume random seeks */
 
3227
  cost->avg_io_cost= 1; /* assume random seeks */
1025
3228
 
1026
3229
  /* Produce the same cost as non-MRR code does */
1027
3230
  if (*flags & HA_MRR_INDEX_ONLY)
1028
 
    cost->setIOCount(index_only_read_time(keyno, n_rows));
 
3231
    cost->io_count= index_only_read_time(keyno, n_rows);
1029
3232
  else
1030
 
    cost->setIOCount(read_time(keyno, n_ranges, n_rows));
 
3233
    cost->io_count= read_time(keyno, n_ranges, n_rows);
1031
3234
  return 0;
1032
3235
}
1033
3236
 
1051
3254
  @param buf             INOUT: memory buffer to be used
1052
3255
 
1053
3256
  @note
1054
 
    One must have called doStartIndexScan() before calling this function. Several
 
3257
    One must have called index_init() before calling this function. Several
1055
3258
    multi_range_read_init() calls may be made in course of one query.
1056
3259
 
1057
3260
    Until WL#2623 is done (see its text, section 3.2), the following will
1058
3261
    also hold:
1059
3262
    The caller will guarantee that if "seq->init == mrr_ranges_array_init"
1060
3263
    then seq_init_param is an array of n_ranges KEY_MULTI_RANGE structures.
1061
 
    This property will only be used by NDB Cursor until WL#2623 is done.
 
3264
    This property will only be used by NDB handler until WL#2623 is done.
1062
3265
 
1063
3266
    Buffer memory management is done according to the following scenario:
1064
3267
    The caller allocates the buffer and provides it to the callee by filling
1066
3269
    The callee consumes all or some fraction of the provided buffer space, and
1067
3270
    sets the HANDLER_BUFFER members accordingly.
1068
3271
    The callee may use the buffer memory until the next multi_range_read_init()
1069
 
    call is made, all records have been read, or until doEndIndexScan() call is
 
3272
    call is made, all records have been read, or until index_end() call is
1070
3273
    made, whichever comes first.
1071
3274
 
1072
3275
  @retval 0  OK
1074
3277
*/
1075
3278
 
1076
3279
int
1077
 
Cursor::multi_range_read_init(RANGE_SEQ_IF *seq_funcs, void *seq_init_param,
1078
 
                               uint32_t n_ranges, uint32_t mode)
 
3280
handler::multi_range_read_init(RANGE_SEQ_IF *seq_funcs, void *seq_init_param,
 
3281
                               uint32_t n_ranges, uint32_t mode,
 
3282
                               HANDLER_BUFFER *)
1079
3283
{
1080
3284
  mrr_iter= seq_funcs->init(seq_init_param, n_ranges, mode);
1081
3285
  mrr_funcs= *seq_funcs;
1082
3286
  mrr_is_output_sorted= test(mode & HA_MRR_SORTED);
1083
3287
  mrr_have_range= false;
1084
 
 
1085
 
  return 0;
 
3288
  return(0);
1086
3289
}
1087
3290
 
1088
3291
 
1099
3302
  @retval other  Error code
1100
3303
*/
1101
3304
 
1102
 
int Cursor::multi_range_read_next(char **range_info)
 
3305
int handler::multi_range_read_next(char **range_info)
1103
3306
{
1104
3307
  int result= 0;
1105
3308
  int range_res= 0;
1106
3309
 
1107
 
  if (not mrr_have_range)
 
3310
  if (!mrr_have_range)
1108
3311
  {
1109
3312
    mrr_have_range= true;
1110
3313
    goto start;
1149
3352
  while ((result == HA_ERR_END_OF_FILE) && !range_res);
1150
3353
 
1151
3354
  *range_info= mrr_cur_range.ptr;
1152
 
  return result;
 
3355
  return(result);
 
3356
}
 
3357
 
 
3358
 
 
3359
/* **************************************************************************
 
3360
 * DS-MRR implementation
 
3361
 ***************************************************************************/
 
3362
 
 
3363
/**
 
3364
  DS-MRR: Initialize and start MRR scan
 
3365
 
 
3366
  Initialize and start the MRR scan. Depending on the mode parameter, this
 
3367
  may use default or DS-MRR implementation.
 
3368
 
 
3369
  @param h               Table handler to be used
 
3370
  @param key             Index to be used
 
3371
  @param seq_funcs       Interval sequence enumeration functions
 
3372
  @param seq_init_param  Interval sequence enumeration parameter
 
3373
  @param n_ranges        Number of ranges in the sequence.
 
3374
  @param mode            HA_MRR_* modes to use
 
3375
  @param buf             INOUT Buffer to use
 
3376
 
 
3377
  @retval 0     Ok, Scan started.
 
3378
  @retval other Error
 
3379
*/
 
3380
 
 
3381
int DsMrr_impl::dsmrr_init(handler *h_in, KEY *key,
 
3382
                           RANGE_SEQ_IF *seq_funcs, void *seq_init_param,
 
3383
                           uint32_t n_ranges, uint32_t mode, HANDLER_BUFFER *buf)
 
3384
{
 
3385
  uint32_t elem_size;
 
3386
  uint32_t keyno;
 
3387
  Item *pushed_cond= NULL;
 
3388
  handler *new_h2;
 
3389
  keyno= h_in->active_index;
 
3390
  assert(h2 == NULL);
 
3391
  if (mode & HA_MRR_USE_DEFAULT_IMPL || mode & HA_MRR_SORTED)
 
3392
  {
 
3393
    use_default_impl= true;
 
3394
    return(h_in->handler::multi_range_read_init(seq_funcs, seq_init_param,
 
3395
                                                  n_ranges, mode, buf));
 
3396
  }
 
3397
  rowids_buf= buf->buffer;
 
3398
  //psergey-todo: don't add key_length as it is not needed anymore
 
3399
  rowids_buf += key->key_length + h_in->ref_length;
 
3400
 
 
3401
  is_mrr_assoc= !test(mode & HA_MRR_NO_ASSOCIATION);
 
3402
  rowids_buf_end= buf->buffer_end;
 
3403
 
 
3404
  elem_size= h_in->ref_length + (int)is_mrr_assoc * sizeof(void*);
 
3405
  rowids_buf_last= rowids_buf +
 
3406
                      ((rowids_buf_end - rowids_buf)/ elem_size)*
 
3407
                      elem_size;
 
3408
  rowids_buf_end= rowids_buf_last;
 
3409
 
 
3410
  /* Create a separate handler object to do rndpos() calls. */
 
3411
  Session *session= current_session;
 
3412
  if (!(new_h2= h_in->clone(session->mem_root)) ||
 
3413
      new_h2->ha_external_lock(session, F_RDLCK))
 
3414
  {
 
3415
    delete new_h2;
 
3416
    return(1);
 
3417
  }
 
3418
 
 
3419
  if (keyno == h_in->pushed_idx_cond_keyno)
 
3420
    pushed_cond= h_in->pushed_idx_cond;
 
3421
  if (h_in->ha_index_end())
 
3422
  {
 
3423
    new_h2= h2;
 
3424
    goto error;
 
3425
  }
 
3426
 
 
3427
  h2= new_h2;
 
3428
  table->prepare_for_position();
 
3429
  new_h2->extra(HA_EXTRA_KEYREAD);
 
3430
 
 
3431
  if (h2->ha_index_init(keyno, false) ||
 
3432
      h2->handler::multi_range_read_init(seq_funcs, seq_init_param, n_ranges,
 
3433
                                         mode, buf))
 
3434
    goto error;
 
3435
  use_default_impl= false;
 
3436
 
 
3437
  if (pushed_cond)
 
3438
    h2->idx_cond_push(keyno, pushed_cond);
 
3439
  if (dsmrr_fill_buffer(new_h2))
 
3440
    goto error;
 
3441
 
 
3442
  /*
 
3443
    If the above call has scanned through all intervals in *seq, then
 
3444
    adjust *buf to indicate that the remaining buffer space will not be used.
 
3445
  */
 
3446
  if (dsmrr_eof)
 
3447
    buf->end_of_used_area= rowids_buf_last;
 
3448
 
 
3449
  if (h_in->ha_rnd_init(false))
 
3450
    goto error;
 
3451
 
 
3452
  return(0);
 
3453
error:
 
3454
  h2->ha_index_or_rnd_end();
 
3455
  h2->ha_external_lock(session, F_UNLCK);
 
3456
  h2->close();
 
3457
  delete h2;
 
3458
  return(1);
 
3459
}
 
3460
 
 
3461
 
 
3462
void DsMrr_impl::dsmrr_close()
 
3463
{
 
3464
  if (h2)
 
3465
  {
 
3466
    h2->ha_external_lock(current_session, F_UNLCK);
 
3467
    h2->close();
 
3468
    delete h2;
 
3469
    h2= NULL;
 
3470
  }
 
3471
  use_default_impl= true;
 
3472
  return;
 
3473
}
 
3474
 
 
3475
 
 
3476
static int rowid_cmp(void *h, unsigned char *a, unsigned char *b)
 
3477
{
 
3478
  return ((handler*)h)->cmp_ref(a, b);
 
3479
}
 
3480
 
 
3481
 
 
3482
/**
 
3483
  DS-MRR: Fill the buffer with rowids and sort it by rowid
 
3484
 
 
3485
  {This is an internal function of DiskSweep MRR implementation}
 
3486
  Scan the MRR ranges and collect ROWIDs (or {ROWID, range_id} pairs) into
 
3487
  buffer. When the buffer is full or scan is completed, sort the buffer by
 
3488
  rowid and return.
 
3489
 
 
3490
  The function assumes that rowids buffer is empty when it is invoked.
 
3491
 
 
3492
  @param h  Table handler
 
3493
 
 
3494
  @retval 0      OK, the next portion of rowids is in the buffer,
 
3495
                 properly ordered
 
3496
  @retval other  Error
 
3497
*/
 
3498
 
 
3499
int DsMrr_impl::dsmrr_fill_buffer(handler *)
 
3500
{
 
3501
  char *range_info;
 
3502
  int res = 0;
 
3503
 
 
3504
  rowids_buf_cur= rowids_buf;
 
3505
  while ((rowids_buf_cur < rowids_buf_end) &&
 
3506
         !(res= h2->handler::multi_range_read_next(&range_info)))
 
3507
  {
 
3508
    /* Put rowid, or {rowid, range_id} pair into the buffer */
 
3509
    h2->position(table->record[0]);
 
3510
    memcpy(rowids_buf_cur, h2->ref, h2->ref_length);
 
3511
    rowids_buf_cur += h->ref_length;
 
3512
 
 
3513
    if (is_mrr_assoc)
 
3514
    {
 
3515
      memcpy(rowids_buf_cur, &range_info, sizeof(void*));
 
3516
      rowids_buf_cur += sizeof(void*);
 
3517
    }
 
3518
  }
 
3519
 
 
3520
  if (res && res != HA_ERR_END_OF_FILE)
 
3521
    return(res);
 
3522
  dsmrr_eof= test(res == HA_ERR_END_OF_FILE);
 
3523
 
 
3524
  /* Sort the buffer contents by rowid */
 
3525
  uint32_t elem_size= h->ref_length + (int)is_mrr_assoc * sizeof(void*);
 
3526
  uint32_t n_rowids= (rowids_buf_cur - rowids_buf) / elem_size;
 
3527
 
 
3528
  my_qsort2(rowids_buf, n_rowids, elem_size, (qsort2_cmp)rowid_cmp,
 
3529
            (void*)h);
 
3530
  rowids_buf_last= rowids_buf_cur;
 
3531
  rowids_buf_cur=  rowids_buf;
 
3532
  return(0);
 
3533
}
 
3534
 
 
3535
 
 
3536
/**
 
3537
  DS-MRR implementation: multi_range_read_next() function
 
3538
*/
 
3539
 
 
3540
int DsMrr_impl::dsmrr_next(handler *h_in, char **range_info)
 
3541
{
 
3542
  int res;
 
3543
 
 
3544
  if (use_default_impl)
 
3545
    return h_in->handler::multi_range_read_next(range_info);
 
3546
 
 
3547
  if (rowids_buf_cur == rowids_buf_last)
 
3548
  {
 
3549
    if (dsmrr_eof)
 
3550
    {
 
3551
      res= HA_ERR_END_OF_FILE;
 
3552
      goto end;
 
3553
    }
 
3554
    res= dsmrr_fill_buffer(h);
 
3555
    if (res)
 
3556
      goto end;
 
3557
  }
 
3558
 
 
3559
  /* Return EOF if there are no rowids in the buffer after re-fill attempt */
 
3560
  if (rowids_buf_cur == rowids_buf_last)
 
3561
  {
 
3562
    res= HA_ERR_END_OF_FILE;
 
3563
    goto end;
 
3564
  }
 
3565
 
 
3566
  res= h_in->rnd_pos(table->record[0], rowids_buf_cur);
 
3567
  rowids_buf_cur += h_in->ref_length;
 
3568
  if (is_mrr_assoc)
 
3569
  {
 
3570
    memcpy(range_info, rowids_buf_cur, sizeof(void*));
 
3571
    rowids_buf_cur += sizeof(void*);
 
3572
  }
 
3573
 
 
3574
end:
 
3575
  if (res)
 
3576
    dsmrr_close();
 
3577
  return res;
 
3578
}
 
3579
 
 
3580
 
 
3581
/**
 
3582
  DS-MRR implementation: multi_range_read_info() function
 
3583
*/
 
3584
int DsMrr_impl::dsmrr_info(uint32_t keyno, uint32_t n_ranges, uint32_t rows, uint32_t *bufsz,
 
3585
                           uint32_t *flags, COST_VECT *cost)
 
3586
{
 
3587
  int res;
 
3588
  uint32_t def_flags= *flags;
 
3589
  uint32_t def_bufsz= *bufsz;
 
3590
 
 
3591
  /* Get cost/flags/mem_usage of default MRR implementation */
 
3592
  res= h->handler::multi_range_read_info(keyno, n_ranges, rows, &def_bufsz,
 
3593
                                         &def_flags, cost);
 
3594
  assert(!res);
 
3595
 
 
3596
  if ((*flags & HA_MRR_USE_DEFAULT_IMPL) ||
 
3597
      choose_mrr_impl(keyno, rows, &def_flags, &def_bufsz, cost))
 
3598
  {
 
3599
    /* Default implementation is choosen */
 
3600
    *flags= def_flags;
 
3601
    *bufsz= def_bufsz;
 
3602
  }
 
3603
  return 0;
 
3604
}
 
3605
 
 
3606
 
 
3607
/**
 
3608
  DS-MRR Implementation: multi_range_read_info_const() function
 
3609
*/
 
3610
 
 
3611
ha_rows DsMrr_impl::dsmrr_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
 
3612
                                 void *seq_init_param, uint32_t n_ranges,
 
3613
                                 uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
 
3614
{
 
3615
  ha_rows rows;
 
3616
  uint32_t def_flags= *flags;
 
3617
  uint32_t def_bufsz= *bufsz;
 
3618
  /* Get cost/flags/mem_usage of default MRR implementation */
 
3619
  rows= h->handler::multi_range_read_info_const(keyno, seq, seq_init_param,
 
3620
                                                n_ranges, &def_bufsz,
 
3621
                                                &def_flags, cost);
 
3622
  if (rows == HA_POS_ERROR)
 
3623
  {
 
3624
    /* Default implementation can't perform MRR scan => we can't either */
 
3625
    return rows;
 
3626
  }
 
3627
 
 
3628
  /*
 
3629
    If HA_MRR_USE_DEFAULT_IMPL has been passed to us, that is an order to
 
3630
    use the default MRR implementation (we need it for UPDATE/DELETE).
 
3631
    Otherwise, make a choice based on cost and @@optimizer_use_mrr.
 
3632
  */
 
3633
  if ((*flags & HA_MRR_USE_DEFAULT_IMPL) ||
 
3634
      choose_mrr_impl(keyno, rows, flags, bufsz, cost))
 
3635
  {
 
3636
    *flags= def_flags;
 
3637
    *bufsz= def_bufsz;
 
3638
  }
 
3639
  else
 
3640
  {
 
3641
    *flags &= ~HA_MRR_USE_DEFAULT_IMPL;
 
3642
  }
 
3643
  return rows;
 
3644
}
 
3645
 
 
3646
 
 
3647
/**
 
3648
  Check if key has partially-covered columns
 
3649
 
 
3650
  We can't use DS-MRR to perform range scans when the ranges are over
 
3651
  partially-covered keys, because we'll not have full key part values
 
3652
  (we'll have their prefixes from the index) and will not be able to check
 
3653
  if we've reached the end the range.
 
3654
 
 
3655
  @param keyno  Key to check
 
3656
 
 
3657
  @todo
 
3658
    Allow use of DS-MRR in cases where the index has partially-covered
 
3659
    components but they are not used for scanning.
 
3660
 
 
3661
  @retval true   Yes
 
3662
  @retval false  No
 
3663
*/
 
3664
 
 
3665
bool DsMrr_impl::key_uses_partial_cols(uint32_t keyno)
 
3666
{
 
3667
  KEY_PART_INFO *kp= table->key_info[keyno].key_part;
 
3668
  KEY_PART_INFO *kp_end= kp + table->key_info[keyno].key_parts;
 
3669
  for (; kp != kp_end; kp++)
 
3670
  {
 
3671
    if (!kp->field->part_of_key.is_set(keyno))
 
3672
      return true;
 
3673
  }
 
3674
  return false;
 
3675
}
 
3676
 
 
3677
 
 
3678
/**
 
3679
  DS-MRR Internals: Choose between Default MRR implementation and DS-MRR
 
3680
 
 
3681
  Make the choice between using Default MRR implementation and DS-MRR.
 
3682
  This function contains common functionality factored out of dsmrr_info()
 
3683
  and dsmrr_info_const(). The function assumes that the default MRR
 
3684
  implementation's applicability requirements are satisfied.
 
3685
 
 
3686
  @param keyno       Index number
 
3687
  @param rows        E(full rows to be retrieved)
 
3688
  @param flags  IN   MRR flags provided by the MRR user
 
3689
                OUT  If DS-MRR is choosen, flags of DS-MRR implementation
 
3690
                     else the value is not modified
 
3691
  @param bufsz  IN   If DS-MRR is choosen, buffer use of DS-MRR implementation
 
3692
                     else the value is not modified
 
3693
  @param cost   IN   Cost of default MRR implementation
 
3694
                OUT  If DS-MRR is choosen, cost of DS-MRR scan
 
3695
                     else the value is not modified
 
3696
 
 
3697
  @retval true   Default MRR implementation should be used
 
3698
  @retval false  DS-MRR implementation should be used
 
3699
*/
 
3700
 
 
3701
bool DsMrr_impl::choose_mrr_impl(uint32_t keyno, ha_rows rows, uint32_t *flags,
 
3702
                                 uint32_t *bufsz, COST_VECT *cost)
 
3703
{
 
3704
  COST_VECT dsmrr_cost;
 
3705
  bool res;
 
3706
  Session *session= current_session;
 
3707
  if ((session->variables.optimizer_use_mrr == 2) ||
 
3708
      (*flags & HA_MRR_INDEX_ONLY) || (*flags & HA_MRR_SORTED) ||
 
3709
      (keyno == table->s->primary_key &&
 
3710
       h->primary_key_is_clustered()) ||
 
3711
       key_uses_partial_cols(keyno))
 
3712
  {
 
3713
    /* Use the default implementation */
 
3714
    *flags |= HA_MRR_USE_DEFAULT_IMPL;
 
3715
    return true;
 
3716
  }
 
3717
 
 
3718
  uint32_t add_len= table->key_info[keyno].key_length + h->ref_length;
 
3719
  *bufsz -= add_len;
 
3720
  if (get_disk_sweep_mrr_cost(keyno, rows, *flags, bufsz, &dsmrr_cost))
 
3721
    return true;
 
3722
  *bufsz += add_len;
 
3723
 
 
3724
  bool force_dsmrr;
 
3725
  /*
 
3726
    If @@optimizer_use_mrr==force, then set cost of DS-MRR to be minimum of
 
3727
    DS-MRR and Default implementations cost. This allows one to force use of
 
3728
    DS-MRR whenever it is applicable without affecting other cost-based
 
3729
    choices.
 
3730
  */
 
3731
  if ((force_dsmrr= (session->variables.optimizer_use_mrr == 1)) &&
 
3732
      dsmrr_cost.total_cost() > cost->total_cost())
 
3733
    dsmrr_cost= *cost;
 
3734
 
 
3735
  if (force_dsmrr || dsmrr_cost.total_cost() <= cost->total_cost())
 
3736
  {
 
3737
    *flags &= ~HA_MRR_USE_DEFAULT_IMPL;  /* Use the DS-MRR implementation */
 
3738
    *flags &= ~HA_MRR_SORTED;          /* We will return unordered output */
 
3739
    *cost= dsmrr_cost;
 
3740
    res= false;
 
3741
  }
 
3742
  else
 
3743
  {
 
3744
    /* Use the default MRR implementation */
 
3745
    res= true;
 
3746
  }
 
3747
  return res;
 
3748
}
 
3749
 
 
3750
 
 
3751
static void get_sort_and_sweep_cost(Table *table, ha_rows nrows, COST_VECT *cost);
 
3752
 
 
3753
 
 
3754
/**
 
3755
  Get cost of DS-MRR scan
 
3756
 
 
3757
  @param keynr              Index to be used
 
3758
  @param rows               E(Number of rows to be scanned)
 
3759
  @param flags              Scan parameters (HA_MRR_* flags)
 
3760
  @param buffer_size INOUT  Buffer size
 
3761
  @param cost        OUT    The cost
 
3762
 
 
3763
  @retval false  OK
 
3764
  @retval true   Error, DS-MRR cannot be used (the buffer is too small
 
3765
                 for even 1 rowid)
 
3766
*/
 
3767
 
 
3768
bool DsMrr_impl::get_disk_sweep_mrr_cost(uint32_t keynr, ha_rows rows, uint32_t flags,
 
3769
                                         uint32_t *buffer_size, COST_VECT *cost)
 
3770
{
 
3771
  uint32_t max_buff_entries, elem_size;
 
3772
  ha_rows rows_in_full_step, rows_in_last_step;
 
3773
  uint32_t n_full_steps;
 
3774
  double index_read_cost;
 
3775
 
 
3776
  elem_size= h->ref_length + sizeof(void*) * (!test(flags & HA_MRR_NO_ASSOCIATION));
 
3777
  max_buff_entries = *buffer_size / elem_size;
 
3778
 
 
3779
  if (!max_buff_entries)
 
3780
    return true; /* Buffer has not enough space for even 1 rowid */
 
3781
 
 
3782
  /* Number of iterations we'll make with full buffer */
 
3783
  n_full_steps= (uint32_t)floor(rows2double(rows) / max_buff_entries);
 
3784
 
 
3785
  /*
 
3786
    Get numbers of rows we'll be processing in
 
3787
     - non-last sweep, with full buffer
 
3788
     - last iteration, with non-full buffer
 
3789
  */
 
3790
  rows_in_full_step= max_buff_entries;
 
3791
  rows_in_last_step= rows % max_buff_entries;
 
3792
 
 
3793
  /* Adjust buffer size if we expect to use only part of the buffer */
 
3794
  if (n_full_steps)
 
3795
  {
 
3796
    get_sort_and_sweep_cost(table, rows, cost);
 
3797
    cost->multiply(n_full_steps);
 
3798
  }
 
3799
  else
 
3800
  {
 
3801
    cost->zero();
 
3802
    *buffer_size= cmax((ulong)*buffer_size,
 
3803
                      (size_t)(1.2*rows_in_last_step) * elem_size +
 
3804
                      h->ref_length + table->key_info[keynr].key_length);
 
3805
  }
 
3806
 
 
3807
  COST_VECT last_step_cost;
 
3808
  get_sort_and_sweep_cost(table, rows_in_last_step, &last_step_cost);
 
3809
  cost->add(&last_step_cost);
 
3810
 
 
3811
  if (n_full_steps != 0)
 
3812
    cost->mem_cost= *buffer_size;
 
3813
  else
 
3814
    cost->mem_cost= (double)rows_in_last_step * elem_size;
 
3815
 
 
3816
  /* Total cost of all index accesses */
 
3817
  index_read_cost= h->index_only_read_time(keynr, (double)rows);
 
3818
  cost->add_io(index_read_cost, 1 /* Random seeks */);
 
3819
  return false;
 
3820
}
 
3821
 
 
3822
 
 
3823
/*
 
3824
  Get cost of one sort-and-sweep step
 
3825
 
 
3826
  SYNOPSIS
 
3827
    get_sort_and_sweep_cost()
 
3828
      table       Table being accessed
 
3829
      nrows       Number of rows to be sorted and retrieved
 
3830
      cost   OUT  The cost
 
3831
 
 
3832
  DESCRIPTION
 
3833
    Get cost of these operations:
 
3834
     - sort an array of #nrows ROWIDs using qsort
 
3835
     - read #nrows records from table in a sweep.
 
3836
*/
 
3837
 
 
3838
static
 
3839
void get_sort_and_sweep_cost(Table *table, ha_rows nrows, COST_VECT *cost)
 
3840
{
 
3841
  if (nrows)
 
3842
  {
 
3843
    get_sweep_read_cost(table, nrows, false, cost);
 
3844
    /* Add cost of qsort call: n * log2(n) * cost(rowid_comparison) */
 
3845
    double cmp_op= rows2double(nrows) * (1.0 / TIME_FOR_COMPARE_ROWID);
 
3846
    if (cmp_op < 3)
 
3847
      cmp_op= 3;
 
3848
    cost->cpu_cost += cmp_op * log2(cmp_op);
 
3849
  }
 
3850
  else
 
3851
    cost->zero();
 
3852
}
 
3853
 
 
3854
 
 
3855
/**
 
3856
  Get cost of reading nrows table records in a "disk sweep"
 
3857
 
 
3858
  A disk sweep read is a sequence of handler->rnd_pos(rowid) calls that made
 
3859
  for an ordered sequence of rowids.
 
3860
 
 
3861
  We assume hard disk IO. The read is performed as follows:
 
3862
 
 
3863
   1. The disk head is moved to the needed cylinder
 
3864
   2. The controller waits for the plate to rotate
 
3865
   3. The data is transferred
 
3866
 
 
3867
  Time to do #3 is insignificant compared to #2+#1.
 
3868
 
 
3869
  Time to move the disk head is proportional to head travel distance.
 
3870
 
 
3871
  Time to wait for the plate to rotate depends on whether the disk head
 
3872
  was moved or not.
 
3873
 
 
3874
  If disk head wasn't moved, the wait time is proportional to distance
 
3875
  between the previous block and the block we're reading.
 
3876
 
 
3877
  If the head was moved, we don't know how much we'll need to wait for the
 
3878
  plate to rotate. We assume the wait time to be a variate with a mean of
 
3879
  0.5 of full rotation time.
 
3880
 
 
3881
  Our cost units are "random disk seeks". The cost of random disk seek is
 
3882
  actually not a constant, it depends one range of cylinders we're going
 
3883
  to access. We make it constant by introducing a fuzzy concept of "typical
 
3884
  datafile length" (it's fuzzy as it's hard to tell whether it should
 
3885
  include index file, temp.tables etc). Then random seek cost is:
 
3886
 
 
3887
    1 = half_rotation_cost + move_cost * 1/3 * typical_data_file_length
 
3888
 
 
3889
  We define half_rotation_cost as DISK_SEEK_BASE_COST=0.9.
 
3890
 
 
3891
  @param table             Table to be accessed
 
3892
  @param nrows             Number of rows to retrieve
 
3893
  @param interrupted       true <=> Assume that the disk sweep will be
 
3894
                           interrupted by other disk IO. false - otherwise.
 
3895
  @param cost         OUT  The cost.
 
3896
*/
 
3897
 
 
3898
void get_sweep_read_cost(Table *table, ha_rows nrows, bool interrupted,
 
3899
                         COST_VECT *cost)
 
3900
{
 
3901
  cost->zero();
 
3902
  if (table->file->primary_key_is_clustered())
 
3903
  {
 
3904
    cost->io_count= table->file->read_time(table->s->primary_key,
 
3905
                                           (uint32_t) nrows, nrows);
 
3906
  }
 
3907
  else
 
3908
  {
 
3909
    double n_blocks=
 
3910
      ceil(uint64_t2double(table->file->stats.data_file_length) / IO_SIZE);
 
3911
    double busy_blocks=
 
3912
      n_blocks * (1.0 - pow(1.0 - 1.0/n_blocks, rows2double(nrows)));
 
3913
    if (busy_blocks < 1.0)
 
3914
      busy_blocks= 1.0;
 
3915
 
 
3916
    cost->io_count= busy_blocks;
 
3917
 
 
3918
    if (!interrupted)
 
3919
    {
 
3920
      /* Assume reading is done in one 'sweep' */
 
3921
      cost->avg_io_cost= (DISK_SEEK_BASE_COST +
 
3922
                          DISK_SEEK_PROP_COST*n_blocks/busy_blocks);
 
3923
    }
 
3924
  }
 
3925
  return;
1153
3926
}
1154
3927
 
1155
3928
 
1166
3939
  @param sorted         Set to 1 if result should be sorted per key
1167
3940
 
1168
3941
  @note
1169
 
    Record is read into table->getInsertRecord()
 
3942
    Record is read into table->record[0]
1170
3943
 
1171
3944
  @retval
1172
3945
    0                   Found row
1175
3948
  @retval
1176
3949
    \#                  Error code
1177
3950
*/
1178
 
int Cursor::read_range_first(const key_range *start_key,
1179
 
                             const key_range *end_key,
1180
 
                             bool eq_range_arg,
1181
 
                             bool )
 
3951
int handler::read_range_first(const key_range *start_key,
 
3952
                              const key_range *end_key,
 
3953
                              bool eq_range_arg,
 
3954
                              bool )
1182
3955
{
1183
3956
  int result;
1184
3957
 
1191
3964
    key_compare_result_on_equal= ((end_key->flag == HA_READ_BEFORE_KEY) ? 1 :
1192
3965
                                  (end_key->flag == HA_READ_AFTER_KEY) ? -1 : 0);
1193
3966
  }
1194
 
  range_key_part= getTable()->key_info[active_index].key_part;
 
3967
  range_key_part= table->key_info[active_index].key_part;
1195
3968
 
1196
3969
  if (!start_key)                       // Read first record
1197
 
    result= index_first(getTable()->getInsertRecord());
 
3970
    result= index_first(table->record[0]);
1198
3971
  else
1199
 
    result= index_read_map(getTable()->getInsertRecord(),
 
3972
    result= index_read_map(table->record[0],
1200
3973
                           start_key->key,
1201
3974
                           start_key->keypart_map,
1202
3975
                           start_key->flag);
1213
3986
  Read next row between two endpoints.
1214
3987
 
1215
3988
  @note
1216
 
    Record is read into table->getInsertRecord()
 
3989
    Record is read into table->record[0]
1217
3990
 
1218
3991
  @retval
1219
3992
    0                   Found row
1222
3995
  @retval
1223
3996
    \#                  Error code
1224
3997
*/
1225
 
int Cursor::read_range_next()
 
3998
int handler::read_range_next()
1226
3999
{
1227
4000
  int result;
1228
4001
 
1229
4002
  if (eq_range)
1230
4003
  {
1231
4004
    /* We trust that index_next_same always gives a row in range */
1232
 
    return(index_next_same(getTable()->getInsertRecord(),
 
4005
    return(index_next_same(table->record[0],
1233
4006
                                end_range->key,
1234
4007
                                end_range->length));
1235
4008
  }
1236
 
  result= index_next(getTable()->getInsertRecord());
 
4009
  result= index_next(table->record[0]);
1237
4010
  if (result)
1238
 
    return result;
 
4011
    return(result);
1239
4012
  return(compare_key(end_range) <= 0 ? 0 : HA_ERR_END_OF_FILE);
1240
4013
}
1241
4014
 
1255
4028
    - -1  : Key is less than range
1256
4029
    - 1   : Key is larger than range
1257
4030
*/
1258
 
int Cursor::compare_key(key_range *range)
 
4031
int handler::compare_key(key_range *range)
1259
4032
{
1260
4033
  int cmp;
1261
 
  if (not range)
 
4034
  if (!range || in_range_check_pushed_down)
1262
4035
    return 0;                                   // No max range
1263
4036
  cmp= key_cmp(range_key_part, range->key, range->length);
1264
4037
  if (!cmp)
1266
4039
  return cmp;
1267
4040
}
1268
4041
 
1269
 
int Cursor::index_read_idx_map(unsigned char * buf, uint32_t index,
 
4042
 
 
4043
/*
 
4044
  Same as compare_key() but doesn't check have in_range_check_pushed_down.
 
4045
  This is used by index condition pushdown implementation.
 
4046
*/
 
4047
 
 
4048
int handler::compare_key2(key_range *range)
 
4049
{
 
4050
  int cmp;
 
4051
  if (!range)
 
4052
    return 0;                                   // no max range
 
4053
  cmp= key_cmp(range_key_part, range->key, range->length);
 
4054
  if (!cmp)
 
4055
    cmp= key_compare_result_on_equal;
 
4056
  return cmp;
 
4057
}
 
4058
 
 
4059
int handler::index_read_idx_map(unsigned char * buf, uint32_t index,
1270
4060
                                const unsigned char * key,
1271
4061
                                key_part_map keypart_map,
1272
4062
                                enum ha_rkey_function find_flag)
1273
4063
{
1274
4064
  int error, error1;
1275
 
  error= doStartIndexScan(index, 0);
 
4065
  error= index_init(index, 0);
1276
4066
  if (!error)
1277
4067
  {
1278
4068
    error= index_read_map(buf, key, keypart_map, find_flag);
1279
 
    error1= doEndIndexScan();
 
4069
    error1= index_end();
1280
4070
  }
1281
4071
  return error ?  error : error1;
1282
4072
}
1283
4073
 
 
4074
 
 
4075
/**
 
4076
  Returns a list of all known extensions.
 
4077
 
 
4078
    No mutexes, worst case race is a minor surplus memory allocation
 
4079
    We have to recreate the extension map if mysqld is restarted (for example
 
4080
    within libmysqld)
 
4081
 
 
4082
  @retval
 
4083
    pointer             pointer to TYPELIB structure
 
4084
*/
 
4085
static bool exts_handlerton(Session *,
 
4086
                            plugin_ref plugin,
 
4087
                            void *arg)
 
4088
{
 
4089
  List<char> *found_exts= (List<char> *) arg;
 
4090
  handlerton *hton= plugin_data(plugin, handlerton *);
 
4091
  handler *file;
 
4092
  if (hton->state == SHOW_OPTION_YES && hton->create &&
 
4093
      (file= hton->create(hton, (TABLE_SHARE*) 0, current_session->mem_root)))
 
4094
  {
 
4095
    List_iterator_fast<char> it(*found_exts);
 
4096
    const char **ext, *old_ext;
 
4097
 
 
4098
    for (ext= file->bas_ext(); *ext; ext++)
 
4099
    {
 
4100
      while ((old_ext= it++))
 
4101
      {
 
4102
        if (!strcmp(old_ext, *ext))
 
4103
          break;
 
4104
      }
 
4105
      if (!old_ext)
 
4106
        found_exts->push_back((char *) *ext);
 
4107
 
 
4108
      it.rewind();
 
4109
    }
 
4110
    delete file;
 
4111
  }
 
4112
  return false;
 
4113
}
 
4114
 
 
4115
TYPELIB *ha_known_exts(void)
 
4116
{
 
4117
  if (!known_extensions.type_names || mysys_usage_id != known_extensions_id)
 
4118
  {
 
4119
    List<char> found_exts;
 
4120
    const char **ext, *old_ext;
 
4121
 
 
4122
    known_extensions_id= mysys_usage_id;
 
4123
 
 
4124
    plugin_foreach(NULL, exts_handlerton,
 
4125
                   DRIZZLE_STORAGE_ENGINE_PLUGIN, &found_exts);
 
4126
 
 
4127
    ext= (const char **) malloc(sizeof(char *)*
 
4128
                                (found_exts.elements+1));
 
4129
                              
 
4130
 
 
4131
    assert(ext != 0);
 
4132
    known_extensions.count= found_exts.elements;
 
4133
    known_extensions.type_names= ext;
 
4134
 
 
4135
    List_iterator_fast<char> it(found_exts);
 
4136
    while ((old_ext= it++))
 
4137
      *ext++= old_ext;
 
4138
    *ext= 0;
 
4139
  }
 
4140
  return &known_extensions;
 
4141
}
 
4142
 
 
4143
 
 
4144
static bool stat_print(Session *session, const char *type, uint32_t type_len,
 
4145
                       const char *file, uint32_t file_len,
 
4146
                       const char *status, uint32_t status_len)
 
4147
{
 
4148
  Protocol *protocol= session->protocol;
 
4149
  protocol->prepare_for_resend();
 
4150
  protocol->store(type, type_len, system_charset_info);
 
4151
  protocol->store(file, file_len, system_charset_info);
 
4152
  protocol->store(status, status_len, system_charset_info);
 
4153
  if (protocol->write())
 
4154
    return true;
 
4155
  return false;
 
4156
}
 
4157
 
 
4158
bool ha_show_status(Session *session, handlerton *db_type, enum ha_stat_type stat)
 
4159
{
 
4160
  List<Item> field_list;
 
4161
  Protocol *protocol= session->protocol;
 
4162
  bool result;
 
4163
 
 
4164
  field_list.push_back(new Item_empty_string("Type",10));
 
4165
  field_list.push_back(new Item_empty_string("Name",FN_REFLEN));
 
4166
  field_list.push_back(new Item_empty_string("Status",10));
 
4167
 
 
4168
  if (protocol->send_fields(&field_list,
 
4169
                            Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
 
4170
    return true;
 
4171
 
 
4172
  result= db_type->show_status &&
 
4173
    db_type->show_status(db_type, session, stat_print, stat) ? 1 : 0;
 
4174
 
 
4175
  if (!result)
 
4176
    session->my_eof();
 
4177
  return result;
 
4178
}
 
4179
 
 
4180
 
1284
4181
/**
1285
4182
  Check if the conditions for row-based binlogging is correct for the table.
1286
4183
 
1287
4184
  A row in the given table should be replicated if:
 
4185
  - Row-based replication is enabled in the current thread
 
4186
  - The binlog is enabled
1288
4187
  - It is not a temporary table
 
4188
  - The binary log is open
 
4189
  - The database the table resides in shall be binlogged (binlog_*_db rules)
 
4190
  - table is not mysql.event
1289
4191
*/
1290
4192
 
1291
 
static bool log_row_for_replication(Table* table,
1292
 
                                    const unsigned char *before_record,
1293
 
                                    const unsigned char *after_record)
 
4193
static bool binlog_log_row(Table* table,
 
4194
                           const unsigned char *before_record,
 
4195
                           const unsigned char *after_record)
1294
4196
{
1295
 
  TransactionServices &transaction_services= TransactionServices::singleton();
 
4197
  bool error= false;
1296
4198
  Session *const session= table->in_use;
1297
4199
 
1298
 
  if (table->getShare()->getType() || not transaction_services.shouldConstructMessages())
 
4200
  if (table->no_replicate == false)
1299
4201
    return false;
1300
4202
 
1301
 
  bool result= false;
 
4203
  error= replicator_session_init(session);
1302
4204
 
1303
4205
  switch (session->lex->sql_command)
1304
4206
  {
1305
 
  case SQLCOM_CREATE_TABLE:
1306
 
    /*
1307
 
     * We are in a CREATE TABLE ... SELECT statement
1308
 
     * and the kernel has already created the table
1309
 
     * and put a CreateTableStatement in the active
1310
 
     * Transaction message.  Here, we add a new InsertRecord
1311
 
     * to a new Transaction message (because the above
1312
 
     * CREATE TABLE will commit the transaction containing
1313
 
     * it).
1314
 
     */
1315
 
    result= transaction_services.insertRecord(*session, *table);
1316
 
    break;
1317
4207
  case SQLCOM_REPLACE:
 
4208
  case SQLCOM_INSERT:
1318
4209
  case SQLCOM_REPLACE_SELECT:
1319
 
    /*
1320
 
     * This is a total hack because of the code that is
1321
 
     * in write_record() in sql_insert.cc. During
1322
 
     * a REPLACE statement, a call to insertRecord() is
1323
 
     * called.  If it fails, then a call to deleteRecord()
1324
 
     * is called, followed by a repeat of the original
1325
 
     * call to insertRecord().  So, log_row_for_replication
1326
 
     * could be called multiple times for a REPLACE
1327
 
     * statement.  The below looks at the values of before_record
1328
 
     * and after_record to determine which call to this
1329
 
     * function is for the delete or the insert, since NULL
1330
 
     * is passed for after_record for the delete and NULL is
1331
 
     * passed for before_record for the insert...
1332
 
     *
1333
 
     * In addition, there is an optimization that allows an
1334
 
     * engine to convert the above delete + insert into an
1335
 
     * update, so we must also check for this case below...
1336
 
     */
1337
 
    if (after_record == NULL)
1338
 
    {
1339
 
      /*
1340
 
       * The storage engine is passed the record in table->record[1]
1341
 
       * as the row to delete (this is the conflicting row), so
1342
 
       * we need to notify TransactionService to use that row.
1343
 
       */
1344
 
      transaction_services.deleteRecord(*session, *table, true);
1345
 
      /* 
1346
 
       * We set the "current" statement message to NULL.  This triggers
1347
 
       * the replication services component to generate a new statement
1348
 
       * message for the inserted record which will come next.
1349
 
       */
1350
 
      transaction_services.finalizeStatementMessage(*session->getStatementMessage(), *session);
1351
 
    }
1352
 
    else
1353
 
    {
1354
 
      if (before_record == NULL)
1355
 
        result= transaction_services.insertRecord(*session, *table);
1356
 
      else
1357
 
        transaction_services.updateRecord(*session, *table, before_record, after_record);
1358
 
    }
1359
 
    break;
1360
 
  case SQLCOM_INSERT:
1361
4210
  case SQLCOM_INSERT_SELECT:
1362
 
  case SQLCOM_LOAD:
1363
 
    /*
1364
 
     * The else block below represents an 
1365
 
     * INSERT ... ON DUPLICATE KEY UPDATE that
1366
 
     * has hit a key conflict and actually done
1367
 
     * an update.
1368
 
     */
1369
 
    if (before_record == NULL)
1370
 
      result= transaction_services.insertRecord(*session, *table);
1371
 
    else
1372
 
      transaction_services.updateRecord(*session, *table, before_record, after_record);
 
4211
  case SQLCOM_CREATE_TABLE:
 
4212
    error= replicator_write_row(session, table);
1373
4213
    break;
1374
4214
 
1375
4215
  case SQLCOM_UPDATE:
1376
 
    transaction_services.updateRecord(*session, *table, before_record, after_record);
 
4216
  case SQLCOM_UPDATE_MULTI:
 
4217
    error= replicator_update_row(session, table, before_record, after_record);
1377
4218
    break;
1378
4219
 
1379
4220
  case SQLCOM_DELETE:
1380
 
    transaction_services.deleteRecord(*session, *table);
 
4221
  case SQLCOM_DELETE_MULTI:
 
4222
    error= replicator_delete_row(session, table);
1381
4223
    break;
 
4224
 
 
4225
    /*
 
4226
      For everything else we ignore the event (since it just involves a temp table)
 
4227
    */
1382
4228
  default:
1383
4229
    break;
1384
4230
  }
1385
4231
 
1386
 
  return result;
 
4232
  return error;
1387
4233
}
1388
4234
 
1389
 
int Cursor::ha_external_lock(Session *session, int lock_type)
 
4235
int handler::ha_external_lock(Session *session, int lock_type)
1390
4236
{
1391
4237
  /*
1392
4238
    Whether this is lock or unlock, this should be true, and is to verify that
1395
4241
  */
1396
4242
  assert(next_insert_id == 0);
1397
4243
 
1398
 
  if (DRIZZLE_CURSOR_RDLOCK_START_ENABLED() ||
1399
 
      DRIZZLE_CURSOR_WRLOCK_START_ENABLED() ||
1400
 
      DRIZZLE_CURSOR_UNLOCK_START_ENABLED())
1401
 
  {
1402
 
    if (lock_type == F_RDLCK)
1403
 
    {
1404
 
      DRIZZLE_CURSOR_RDLOCK_START(getTable()->getShare()->getSchemaName(),
1405
 
                                  getTable()->getShare()->getTableName());
1406
 
    }
1407
 
    else if (lock_type == F_WRLCK)
1408
 
    {
1409
 
      DRIZZLE_CURSOR_WRLOCK_START(getTable()->getShare()->getSchemaName(),
1410
 
                                  getTable()->getShare()->getTableName());
1411
 
    }
1412
 
    else if (lock_type == F_UNLCK)
1413
 
    {
1414
 
      DRIZZLE_CURSOR_UNLOCK_START(getTable()->getShare()->getSchemaName(),
1415
 
                                  getTable()->getShare()->getTableName());
1416
 
    }
1417
 
  }
1418
 
 
1419
4244
  /*
1420
4245
    We cache the table flags if the locking succeeded. Otherwise, we
1421
4246
    keep them as they were when they were fetched in ha_open().
1422
4247
  */
 
4248
  DRIZZLE_EXTERNAL_LOCK(lock_type);
1423
4249
 
1424
4250
  int error= external_lock(session, lock_type);
1425
 
 
1426
 
  if (DRIZZLE_CURSOR_RDLOCK_DONE_ENABLED() ||
1427
 
      DRIZZLE_CURSOR_WRLOCK_DONE_ENABLED() ||
1428
 
      DRIZZLE_CURSOR_UNLOCK_DONE_ENABLED())
1429
 
  {
1430
 
    if (lock_type == F_RDLCK)
1431
 
    {
1432
 
      DRIZZLE_CURSOR_RDLOCK_DONE(error);
1433
 
    }
1434
 
    else if (lock_type == F_WRLCK)
1435
 
    {
1436
 
      DRIZZLE_CURSOR_WRLOCK_DONE(error);
1437
 
    }
1438
 
    else if (lock_type == F_UNLCK)
1439
 
    {
1440
 
      DRIZZLE_CURSOR_UNLOCK_DONE(error);
1441
 
    }
1442
 
  }
1443
 
 
1444
 
  return error;
 
4251
  if (error == 0)
 
4252
    cached_table_flags= table_flags();
 
4253
  return(error);
1445
4254
}
1446
4255
 
1447
4256
 
1448
4257
/**
1449
 
  Check Cursor usage and reset state of file to after 'open'
 
4258
  Check handler usage and reset state of file to after 'open'
1450
4259
*/
1451
 
int Cursor::ha_reset()
 
4260
int handler::ha_reset()
1452
4261
{
1453
4262
  /* Check that we have called all proper deallocation functions */
1454
 
  assert(! getTable()->getShare()->all_set.none());
1455
 
  assert(getTable()->key_read == 0);
1456
 
  /* ensure that ha_index_end / endTableScan has been called */
 
4263
  assert((unsigned char*) table->def_read_set.bitmap +
 
4264
              table->s->column_bitmap_size ==
 
4265
              (unsigned char*) table->def_write_set.bitmap);
 
4266
  assert(bitmap_is_set_all(&table->s->all_set));
 
4267
  assert(table->key_read == 0);
 
4268
  /* ensure that ha_index_end / ha_rnd_end has been called */
1457
4269
  assert(inited == NONE);
1458
4270
  /* Free cache used by filesort */
1459
 
  getTable()->free_io_cache();
 
4271
  free_io_cache(table);
1460
4272
  /* reset the bitmaps to point to defaults */
1461
 
  getTable()->default_column_bitmaps();
 
4273
  table->default_column_bitmaps();
1462
4274
  return(reset());
1463
4275
}
1464
4276
 
1465
4277
 
1466
 
int Cursor::insertRecord(unsigned char *buf)
 
4278
int handler::ha_write_row(unsigned char *buf)
1467
4279
{
1468
4280
  int error;
 
4281
  DRIZZLE_INSERT_ROW_START();
1469
4282
 
1470
 
  /*
1471
 
   * If we have a timestamp column, update it to the current time
1472
 
   *
 
4283
  /* 
 
4284
   * If we have a timestamp column, update it to the current time 
 
4285
   * 
1473
4286
   * @TODO Technically, the below two lines can be take even further out of the
1474
 
   * Cursor interface and into the fill_record() method.
 
4287
   * handler interface and into the fill_record() method.
1475
4288
   */
1476
 
  if (getTable()->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
1477
 
  {
1478
 
    getTable()->timestamp_field->set_time();
1479
 
  }
1480
 
 
1481
 
  DRIZZLE_INSERT_ROW_START(getTable()->getShare()->getSchemaName(), getTable()->getShare()->getTableName());
1482
 
  setTransactionReadWrite();
1483
 
  
1484
 
  if (unlikely(plugin::EventObserver::beforeInsertRecord(*getTable(), buf)))
1485
 
  {
1486
 
    error= ER_EVENT_OBSERVER_PLUGIN;
1487
 
  }
1488
 
  else
1489
 
  {
1490
 
    error= doInsertRecord(buf);
1491
 
    if (unlikely(plugin::EventObserver::afterInsertRecord(*getTable(), buf, error))) 
1492
 
    {
1493
 
      error= ER_EVENT_OBSERVER_PLUGIN;
1494
 
    }
1495
 
  }
1496
 
 
1497
 
  ha_statistic_increment(&system_status_var::ha_write_count);
1498
 
 
1499
 
  DRIZZLE_INSERT_ROW_DONE(error);
1500
 
 
1501
 
  if (unlikely(error))
1502
 
  {
1503
 
    return error;
1504
 
  }
1505
 
 
1506
 
  if (unlikely(log_row_for_replication(getTable(), NULL, buf)))
1507
 
    return HA_ERR_RBR_LOGGING_FAILED;
1508
 
 
1509
 
  return 0;
 
4289
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
 
4290
    table->timestamp_field->set_time();
 
4291
 
 
4292
  mark_trx_read_write();
 
4293
 
 
4294
  if (unlikely(error= write_row(buf)))
 
4295
    return(error);
 
4296
 
 
4297
  if (unlikely(binlog_log_row(table, 0, buf)))
 
4298
    return HA_ERR_RBR_LOGGING_FAILED; /* purecov: inspected */
 
4299
 
 
4300
  DRIZZLE_INSERT_ROW_END();
 
4301
  return(0);
1510
4302
}
1511
4303
 
1512
4304
 
1513
 
int Cursor::updateRecord(const unsigned char *old_data, unsigned char *new_data)
 
4305
int handler::ha_update_row(const unsigned char *old_data, unsigned char *new_data)
1514
4306
{
1515
4307
  int error;
1516
4308
 
1517
4309
  /*
1518
 
    Some storage engines require that the new record is in getInsertRecord()
1519
 
    (and the old record is in getUpdateRecord()).
 
4310
    Some storage engines require that the new record is in record[0]
 
4311
    (and the old record is in record[1]).
1520
4312
   */
1521
 
  assert(new_data == getTable()->getInsertRecord());
1522
 
 
1523
 
  DRIZZLE_UPDATE_ROW_START(getTable()->getShare()->getSchemaName(), getTable()->getShare()->getTableName());
1524
 
  setTransactionReadWrite();
1525
 
  if (unlikely(plugin::EventObserver::beforeUpdateRecord(*getTable(), old_data, new_data)))
1526
 
  {
1527
 
    error= ER_EVENT_OBSERVER_PLUGIN;
1528
 
  }
1529
 
  else
1530
 
  {
1531
 
    if (getTable()->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
1532
 
    {
1533
 
      getTable()->timestamp_field->set_time();
1534
 
    }
1535
 
 
1536
 
    error= doUpdateRecord(old_data, new_data);
1537
 
    if (unlikely(plugin::EventObserver::afterUpdateRecord(*getTable(), old_data, new_data, error)))
1538
 
    {
1539
 
      error= ER_EVENT_OBSERVER_PLUGIN;
1540
 
    }
1541
 
  }
1542
 
 
1543
 
  ha_statistic_increment(&system_status_var::ha_update_count);
1544
 
 
1545
 
  DRIZZLE_UPDATE_ROW_DONE(error);
1546
 
 
1547
 
  if (unlikely(error))
1548
 
  {
 
4313
  assert(new_data == table->record[0]);
 
4314
 
 
4315
  mark_trx_read_write();
 
4316
 
 
4317
  if (unlikely(error= update_row(old_data, new_data)))
1549
4318
    return error;
1550
 
  }
1551
4319
 
1552
 
  if (unlikely(log_row_for_replication(getTable(), old_data, new_data)))
 
4320
  if (unlikely(binlog_log_row(table, old_data, new_data)))
1553
4321
    return HA_ERR_RBR_LOGGING_FAILED;
1554
4322
 
1555
4323
  return 0;
1556
4324
}
1557
 
TableShare *Cursor::getShare()
1558
 
{
1559
 
  return getTable()->getMutableShare();
1560
 
}
1561
4325
 
1562
 
int Cursor::deleteRecord(const unsigned char *buf)
 
4326
int handler::ha_delete_row(const unsigned char *buf)
1563
4327
{
1564
4328
  int error;
1565
4329
 
1566
 
  DRIZZLE_DELETE_ROW_START(getTable()->getShare()->getSchemaName(), getTable()->getShare()->getTableName());
1567
 
  setTransactionReadWrite();
1568
 
  if (unlikely(plugin::EventObserver::beforeDeleteRecord(*getTable(), buf)))
1569
 
  {
1570
 
    error= ER_EVENT_OBSERVER_PLUGIN;
1571
 
  }
1572
 
  else
1573
 
  {
1574
 
    error= doDeleteRecord(buf);
1575
 
    if (unlikely(plugin::EventObserver::afterDeleteRecord(*getTable(), buf, error)))
1576
 
    {
1577
 
      error= ER_EVENT_OBSERVER_PLUGIN;
1578
 
    }
1579
 
  }
1580
 
 
1581
 
  ha_statistic_increment(&system_status_var::ha_delete_count);
1582
 
 
1583
 
  DRIZZLE_DELETE_ROW_DONE(error);
1584
 
 
1585
 
  if (unlikely(error))
 
4330
  mark_trx_read_write();
 
4331
 
 
4332
  if (unlikely(error= delete_row(buf)))
1586
4333
    return error;
1587
4334
 
1588
 
  if (unlikely(log_row_for_replication(getTable(), buf, NULL)))
 
4335
  if (unlikely(binlog_log_row(table, buf, 0)))
1589
4336
    return HA_ERR_RBR_LOGGING_FAILED;
1590
4337
 
1591
4338
  return 0;
1592
4339
}
1593
4340
 
1594
 
} /* namespace drizzled */
 
4341
 
 
4342
 
 
4343
/**
 
4344
  @details
 
4345
  use_hidden_primary_key() is called in case of an update/delete when
 
4346
  (table_flags() and HA_PRIMARY_KEY_REQUIRED_FOR_DELETE) is defined
 
4347
  but we don't have a primary key
 
4348
*/
 
4349
void handler::use_hidden_primary_key()
 
4350
{
 
4351
  /* fallback to use all columns in the table to identify row */
 
4352
  table->use_all_columns();
 
4353
}
 
4354
 
 
4355
void table_case_convert(char * name, uint32_t length)
 
4356
{
 
4357
  if (lower_case_table_names)
 
4358
    files_charset_info->cset->casedn(files_charset_info,
 
4359
                                     name, length, name, length);
 
4360
}
 
4361
 
 
4362
const char *table_case_name(HA_CREATE_INFO *info, const char *name)
 
4363
{
 
4364
  return ((lower_case_table_names == 2 && info->alias) ? info->alias : name);
 
4365
}