~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/handler.cc

  • Committer: Brian Aker
  • Date: 2009-01-06 23:40:50 UTC
  • mfrom: (642.1.69 drizzle-clean-code)
  • Revision ID: brian@tangent.org-20090106234050-w01lo5f4r3q62nik
Finished merge for Lee

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 */
19
19
 
20
20
/**
21
 
  @file Cursor.cc
 
21
  @file handler.cc
22
22
 
23
23
  Handler-calling-functions
24
24
*/
25
25
 
26
 
#include "config.h"
27
 
 
28
 
#include <fcntl.h>
29
 
 
30
 
#include "drizzled/my_hash.h"
31
 
#include "drizzled/error.h"
32
 
#include "drizzled/gettext.h"
33
 
#include "drizzled/probes.h"
34
 
#include "drizzled/sql_parse.h"
35
 
#include "drizzled/cost_vect.h"
36
 
#include "drizzled/session.h"
37
 
#include "drizzled/sql_base.h"
38
 
#include "drizzled/replication_services.h"
39
 
#include "drizzled/lock.h"
40
 
#include "drizzled/item/int.h"
41
 
#include "drizzled/item/empty_string.h"
42
 
#include "drizzled/field/timestamp.h"
43
 
#include "drizzled/message/table.pb.h"
44
 
#include "drizzled/plugin/client.h"
45
 
#include "drizzled/internal/my_sys.h"
46
 
#include "drizzled/transaction_services.h"
47
 
 
48
 
using namespace std;
49
 
 
50
 
namespace drizzled
51
 
{
 
26
#include <drizzled/server_includes.h>
 
27
#include <libdrizzle/libdrizzle.h>
 
28
#include <mysys/hash.h>
 
29
#include <drizzled/error.h>
 
30
#include <drizzled/gettext.h>
 
31
#include <drizzled/data_home.h>
 
32
#include <drizzled/probes.h>
 
33
#include <drizzled/sql_parse.h>
 
34
#include <drizzled/cost_vect.h>
 
35
#include CMATH_H
 
36
#include <drizzled/session.h>
 
37
#include <drizzled/sql_base.h>
 
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
 
 
44
#if defined(CMATH_NAMESPACE)
 
45
using namespace CMATH_NAMESPACE;
 
46
#endif
 
47
 
 
48
 
 
49
extern HASH open_cache;
 
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 *unused1 __attribute__((unused)),
 
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 *unused __attribute__((unused)))
 
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
  my_xid xid= session->transaction.xid_state.xid.get_my_xid();
 
686
 
 
687
  /*
 
688
    We must not commit the normal transaction if a statement
 
689
    transaction is pending. Otherwise statement transaction
 
690
    flags will not get propagated to its normal transaction's
 
691
    counterpart.
 
692
  */
 
693
  assert(session->transaction.stmt.ha_list == NULL ||
 
694
              trans == &session->transaction.stmt);
 
695
 
 
696
  if (ha_info)
 
697
  {
 
698
    bool must_2pc;
 
699
 
 
700
    if (is_real_trans && wait_if_global_read_lock(session, 0, 0))
 
701
    {
 
702
      ha_rollback_trans(session, all);
 
703
      return(1);
 
704
    }
 
705
 
 
706
    must_2pc= ha_check_and_coalesce_trx_read_only(session, ha_info, all);
 
707
 
 
708
    if (!trans->no_2pc && must_2pc)
 
709
    {
 
710
      for (; ha_info && !error; ha_info= ha_info->next())
 
711
      {
 
712
        int err;
 
713
        handlerton *ht= ha_info->ht();
 
714
        /*
 
715
          Do not call two-phase commit if this particular
 
716
          transaction is read-only. This allows for simpler
 
717
          implementation in engines that are always read-only.
 
718
        */
 
719
        if (! ha_info->is_trx_read_write())
 
720
          continue;
 
721
        /*
 
722
          Sic: we know that prepare() is not NULL since otherwise
 
723
          trans->no_2pc would have been set.
 
724
        */
 
725
        if ((err= ht->prepare(ht, session, all)))
 
726
        {
 
727
          my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
 
728
          error= 1;
 
729
        }
 
730
        status_var_increment(session->status_var.ha_prepare_count);
 
731
      }
 
732
      if (error || (is_real_trans && xid &&
 
733
                    (error= !(cookie= tc_log->log_xid(session, xid)))))
 
734
      {
 
735
        ha_rollback_trans(session, all);
 
736
        error= 1;
 
737
        goto end;
 
738
      }
 
739
    }
 
740
    error=ha_commit_one_phase(session, all) ? (cookie ? 2 : 1) : 0;
 
741
    if (cookie)
 
742
      tc_log->unlog(cookie, xid);
 
743
end:
 
744
    if (is_real_trans)
 
745
      start_waiting_global_read_lock(session);
 
746
  }
 
747
  return(error);
 
748
}
 
749
 
 
750
/**
 
751
  @note
 
752
  This function does not care about global read lock. A caller should.
 
753
*/
 
754
int ha_commit_one_phase(Session *session, bool all)
 
755
{
 
756
  int error=0;
 
757
  Session_TRANS *trans=all ? &session->transaction.all : &session->transaction.stmt;
 
758
  bool is_real_trans=all || session->transaction.all.ha_list == 0;
 
759
  Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
 
760
  if (ha_info)
 
761
  {
 
762
    for (; ha_info; ha_info= ha_info_next)
 
763
    {
 
764
      int err;
 
765
      handlerton *ht= ha_info->ht();
 
766
      if ((err= ht->commit(ht, session, all)))
 
767
      {
 
768
        my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
 
769
        error=1;
 
770
      }
 
771
      status_var_increment(session->status_var.ha_commit_count);
 
772
      ha_info_next= ha_info->next();
 
773
      ha_info->reset(); /* keep it conveniently zero-filled */
 
774
    }
 
775
    trans->ha_list= 0;
 
776
    trans->no_2pc=0;
 
777
    if (is_real_trans)
 
778
      session->transaction.xid_state.xid.null();
 
779
    if (all)
 
780
    {
 
781
      session->variables.tx_isolation=session->session_tx_isolation;
 
782
      session->transaction.cleanup();
 
783
    }
 
784
  }
 
785
  return(error);
 
786
}
 
787
 
 
788
 
 
789
int ha_rollback_trans(Session *session, bool all)
 
790
{
 
791
  int error=0;
 
792
  Session_TRANS *trans=all ? &session->transaction.all : &session->transaction.stmt;
 
793
  Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
 
794
  bool is_real_trans=all || session->transaction.all.ha_list == 0;
 
795
 
 
796
  /*
 
797
    We must not rollback the normal transaction if a statement
 
798
    transaction is pending.
 
799
  */
 
800
  assert(session->transaction.stmt.ha_list == NULL ||
 
801
              trans == &session->transaction.stmt);
 
802
 
 
803
  if (ha_info)
 
804
  {
 
805
    for (; ha_info; ha_info= ha_info_next)
 
806
    {
 
807
      int err;
 
808
      handlerton *ht= ha_info->ht();
 
809
      if ((err= ht->rollback(ht, session, all)))
 
810
      { // cannot happen
 
811
        my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
 
812
        error=1;
 
813
      }
 
814
      status_var_increment(session->status_var.ha_rollback_count);
 
815
      ha_info_next= ha_info->next();
 
816
      ha_info->reset(); /* keep it conveniently zero-filled */
 
817
    }
 
818
    trans->ha_list= 0;
 
819
    trans->no_2pc=0;
 
820
    if (is_real_trans)
 
821
      session->transaction.xid_state.xid.null();
 
822
    if (all)
 
823
    {
 
824
      session->variables.tx_isolation=session->session_tx_isolation;
 
825
      session->transaction.cleanup();
 
826
    }
 
827
  }
 
828
  if (all)
 
829
    session->transaction_rollback_request= false;
 
830
 
 
831
  /*
 
832
    If a non-transactional table was updated, warn; don't warn if this is a
 
833
    slave thread (because when a slave thread executes a ROLLBACK, it has
 
834
    been read from the binary log, so it's 100% sure and normal to produce
 
835
    error ER_WARNING_NOT_COMPLETE_ROLLBACK. If we sent the warning to the
 
836
    slave SQL thread, it would not stop the thread but just be printed in
 
837
    the error log; but we don't want users to wonder why they have this
 
838
    message in the error log, so we don't send it.
 
839
  */
 
840
  if (is_real_trans && session->transaction.all.modified_non_trans_table &&
 
841
      !session->slave_thread && session->killed != Session::KILL_CONNECTION)
 
842
    push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
843
                 ER_WARNING_NOT_COMPLETE_ROLLBACK,
 
844
                 ER(ER_WARNING_NOT_COMPLETE_ROLLBACK));
 
845
  return(error);
 
846
}
 
847
 
 
848
/**
 
849
  This is used to commit or rollback a single statement depending on
 
850
  the value of error.
 
851
 
 
852
  @note
 
853
    Note that if the autocommit is on, then the following call inside
 
854
    InnoDB will commit or rollback the whole transaction (= the statement). The
 
855
    autocommit mechanism built into InnoDB is based on counting locks, but if
 
856
    the user has used LOCK TABLES then that mechanism does not know to do the
 
857
    commit.
 
858
*/
 
859
int ha_autocommit_or_rollback(Session *session, int error)
 
860
{
 
861
  if (session->transaction.stmt.ha_list)
 
862
  {
 
863
    if (!error)
 
864
    {
 
865
      if (ha_commit_trans(session, 0))
 
866
        error=1;
 
867
    }
 
868
    else
 
869
    {
 
870
      (void) ha_rollback_trans(session, 0);
 
871
      if (session->transaction_rollback_request)
 
872
        (void) ha_rollback(session);
 
873
    }
 
874
 
 
875
    session->variables.tx_isolation=session->session_tx_isolation;
 
876
  }
 
877
  return(error);
 
878
}
 
879
 
 
880
 
 
881
struct xahton_st {
 
882
  XID *xid;
 
883
  int result;
 
884
};
 
885
 
 
886
static bool xacommit_handlerton(Session *unused1 __attribute__((unused)),
 
887
                                plugin_ref plugin,
 
888
                                void *arg)
 
889
{
 
890
  handlerton *hton= plugin_data(plugin, handlerton *);
 
891
  if (hton->state == SHOW_OPTION_YES && hton->recover)
 
892
  {
 
893
    hton->commit_by_xid(hton, ((struct xahton_st *)arg)->xid);
 
894
    ((struct xahton_st *)arg)->result= 0;
 
895
  }
 
896
  return false;
 
897
}
 
898
 
 
899
static bool xarollback_handlerton(Session *unused1 __attribute__((unused)),
 
900
                                  plugin_ref plugin,
 
901
                                  void *arg)
 
902
{
 
903
  handlerton *hton= plugin_data(plugin, handlerton *);
 
904
  if (hton->state == SHOW_OPTION_YES && hton->recover)
 
905
  {
 
906
    hton->rollback_by_xid(hton, ((struct xahton_st *)arg)->xid);
 
907
    ((struct xahton_st *)arg)->result= 0;
 
908
  }
 
909
  return false;
 
910
}
 
911
 
 
912
 
 
913
int ha_commit_or_rollback_by_xid(XID *xid, bool commit)
 
914
{
 
915
  struct xahton_st xaop;
 
916
  xaop.xid= xid;
 
917
  xaop.result= 1;
 
918
 
 
919
  plugin_foreach(NULL, commit ? xacommit_handlerton : xarollback_handlerton,
 
920
                 DRIZZLE_STORAGE_ENGINE_PLUGIN, &xaop);
 
921
 
 
922
  return xaop.result;
 
923
}
 
924
 
 
925
/**
 
926
  recover() step of xa.
 
927
 
 
928
  @note
 
929
    there are three modes of operation:
 
930
    - automatic recover after a crash
 
931
    in this case commit_list != 0, tc_heuristic_recover==0
 
932
    all xids from commit_list are committed, others are rolled back
 
933
    - manual (heuristic) recover
 
934
    in this case commit_list==0, tc_heuristic_recover != 0
 
935
    DBA has explicitly specified that all prepared transactions should
 
936
    be committed (or rolled back).
 
937
    - no recovery (MySQL did not detect a crash)
 
938
    in this case commit_list==0, tc_heuristic_recover == 0
 
939
    there should be no prepared transactions in this case.
 
940
*/
 
941
struct xarecover_st
 
942
{
 
943
  int len, found_foreign_xids, found_my_xids;
 
944
  XID *list;
 
945
  HASH *commit_list;
 
946
  bool dry_run;
 
947
};
 
948
 
 
949
static bool xarecover_handlerton(Session *unused __attribute__((unused)),
 
950
                                 plugin_ref plugin,
 
951
                                 void *arg)
 
952
{
 
953
  handlerton *hton= plugin_data(plugin, handlerton *);
 
954
  struct xarecover_st *info= (struct xarecover_st *) arg;
 
955
  int got;
 
956
 
 
957
  if (hton->state == SHOW_OPTION_YES && hton->recover)
 
958
  {
 
959
    while ((got= hton->recover(hton, info->list, info->len)) > 0 )
 
960
    {
 
961
      errmsg_printf(ERRMSG_LVL_INFO, _("Found %d prepared transaction(s) in %s"),
 
962
                            got, ha_resolve_storage_engine_name(hton));
 
963
      for (int i=0; i < got; i ++)
 
964
      {
 
965
        my_xid x=info->list[i].get_my_xid();
 
966
        if (!x) // not "mine" - that is generated by external TM
 
967
        {
 
968
          xid_cache_insert(info->list+i, XA_PREPARED);
 
969
          info->found_foreign_xids++;
 
970
          continue;
 
971
        }
 
972
        if (info->dry_run)
 
973
        {
 
974
          info->found_my_xids++;
 
975
          continue;
 
976
        }
 
977
        // recovery mode
 
978
        if (info->commit_list ?
 
979
            hash_search(info->commit_list, (unsigned char *)&x, sizeof(x)) != 0 :
 
980
            tc_heuristic_recover == TC_HEURISTIC_RECOVER_COMMIT)
 
981
        {
 
982
          hton->commit_by_xid(hton, info->list+i);
 
983
        }
 
984
        else
 
985
        {
 
986
          hton->rollback_by_xid(hton, info->list+i);
 
987
        }
 
988
      }
 
989
      if (got < info->len)
 
990
        break;
 
991
    }
 
992
  }
 
993
  return false;
 
994
}
 
995
 
 
996
int ha_recover(HASH *commit_list)
 
997
{
 
998
  struct xarecover_st info;
 
999
  info.found_foreign_xids= info.found_my_xids= 0;
 
1000
  info.commit_list= commit_list;
 
1001
  info.dry_run= (info.commit_list==0 && tc_heuristic_recover==0);
 
1002
  info.list= NULL;
 
1003
 
 
1004
  /* commit_list and tc_heuristic_recover cannot be set both */
 
1005
  assert(info.commit_list==0 || tc_heuristic_recover==0);
 
1006
  /* if either is set, total_ha_2pc must be set too */
 
1007
  assert(info.dry_run || total_ha_2pc>(uint32_t)opt_bin_log);
 
1008
 
 
1009
  if (total_ha_2pc <= (uint32_t)opt_bin_log)
 
1010
    return(0);
 
1011
 
 
1012
  if (info.commit_list)
 
1013
    errmsg_printf(ERRMSG_LVL_INFO, _("Starting crash recovery..."));
 
1014
 
 
1015
 
 
1016
#ifndef WILL_BE_DELETED_LATER
 
1017
 
 
1018
  /*
 
1019
    for now, only InnoDB supports 2pc. It means we can always safely
 
1020
    rollback all pending transactions, without risking inconsistent data
 
1021
  */
 
1022
 
 
1023
  assert(total_ha_2pc == (uint32_t) opt_bin_log+1); // only InnoDB and binlog
 
1024
  tc_heuristic_recover= TC_HEURISTIC_RECOVER_ROLLBACK; // forcing ROLLBACK
 
1025
  info.dry_run=false;
 
1026
#endif
 
1027
 
 
1028
 
 
1029
  for (info.len= MAX_XID_LIST_SIZE ;
 
1030
       info.list==0 && info.len > MIN_XID_LIST_SIZE; info.len/=2)
 
1031
  {
 
1032
    info.list=(XID *)malloc(info.len*sizeof(XID));
 
1033
  }
 
1034
  if (!info.list)
 
1035
  {
 
1036
    errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_OUTOFMEMORY), info.len*sizeof(XID));
 
1037
    return(1);
 
1038
  }
 
1039
 
 
1040
  plugin_foreach(NULL, xarecover_handlerton,
 
1041
                 DRIZZLE_STORAGE_ENGINE_PLUGIN, &info);
 
1042
 
 
1043
  free((unsigned char*)info.list);
 
1044
  if (info.found_foreign_xids)
 
1045
    errmsg_printf(ERRMSG_LVL_WARN, _("Found %d prepared XA transactions"),
 
1046
                  info.found_foreign_xids);
 
1047
  if (info.dry_run && info.found_my_xids)
 
1048
  {
 
1049
    errmsg_printf(ERRMSG_LVL_ERROR,
 
1050
                  _("Found %d prepared transactions! It means that drizzled "
 
1051
                    "was not shut down properly last time and critical "
 
1052
                    "recovery information (last binlog or %s file) was "
 
1053
                    "manually deleted after a crash. You have to start "
 
1054
                    "drizzled with the --tc-heuristic-recover switch to "
 
1055
                    "commit or rollback pending transactions."),
 
1056
                    info.found_my_xids, opt_tc_log_file);
 
1057
    return(1);
 
1058
  }
 
1059
  if (info.commit_list)
 
1060
    errmsg_printf(ERRMSG_LVL_INFO, _("Crash recovery finished."));
 
1061
  return(0);
 
1062
}
 
1063
 
 
1064
/**
 
1065
  return the list of XID's to a client, the same way SHOW commands do.
 
1066
 
 
1067
  @note
 
1068
    I didn't find in XA specs that an RM cannot return the same XID twice,
 
1069
    so mysql_xa_recover does not filter XID's to ensure uniqueness.
 
1070
    It can be easily fixed later, if necessary.
 
1071
*/
 
1072
bool mysql_xa_recover(Session *session)
 
1073
{
 
1074
  List<Item> field_list;
 
1075
  Protocol *protocol= session->protocol;
 
1076
  int i=0;
 
1077
  XID_STATE *xs;
 
1078
 
 
1079
  field_list.push_back(new Item_int("formatID", 0, MY_INT32_NUM_DECIMAL_DIGITS));
 
1080
  field_list.push_back(new Item_int("gtrid_length", 0, MY_INT32_NUM_DECIMAL_DIGITS));
 
1081
  field_list.push_back(new Item_int("bqual_length", 0, MY_INT32_NUM_DECIMAL_DIGITS));
 
1082
  field_list.push_back(new Item_empty_string("data",XIDDATASIZE));
 
1083
 
 
1084
  if (protocol->send_fields(&field_list,
 
1085
                            Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
 
1086
    return(1);
 
1087
 
 
1088
  pthread_mutex_lock(&LOCK_xid_cache);
 
1089
  while ((xs= (XID_STATE*)hash_element(&xid_cache, i++)))
 
1090
  {
 
1091
    if (xs->xa_state==XA_PREPARED)
 
1092
    {
 
1093
      protocol->prepare_for_resend();
 
1094
      protocol->store_int64_t((int64_t)xs->xid.formatID, false);
 
1095
      protocol->store_int64_t((int64_t)xs->xid.gtrid_length, false);
 
1096
      protocol->store_int64_t((int64_t)xs->xid.bqual_length, false);
 
1097
      protocol->store(xs->xid.data, xs->xid.gtrid_length+xs->xid.bqual_length,
 
1098
                      &my_charset_bin);
 
1099
      if (protocol->write())
 
1100
      {
 
1101
        pthread_mutex_unlock(&LOCK_xid_cache);
 
1102
        return(1);
 
1103
      }
 
1104
    }
 
1105
  }
 
1106
 
 
1107
  pthread_mutex_unlock(&LOCK_xid_cache);
 
1108
  my_eof(session);
 
1109
  return(0);
 
1110
}
 
1111
 
 
1112
/**
 
1113
  @details
 
1114
  This function should be called when MySQL sends rows of a SELECT result set
 
1115
  or the EOF mark to the client. It releases a possible adaptive hash index
 
1116
  S-latch held by session in InnoDB and also releases a possible InnoDB query
 
1117
  FIFO ticket to enter InnoDB. To save CPU time, InnoDB allows a session to
 
1118
  keep them over several calls of the InnoDB handler interface when a join
 
1119
  is executed. But when we let the control to pass to the client they have
 
1120
  to be released because if the application program uses mysql_use_result(),
 
1121
  it may deadlock on the S-latch if the application on another connection
 
1122
  performs another SQL query. In MySQL-4.1 this is even more important because
 
1123
  there a connection can have several SELECT queries open at the same time.
 
1124
 
 
1125
  @param session           the thread handle of the current connection
 
1126
 
 
1127
  @return
 
1128
    always 0
 
1129
*/
 
1130
static bool release_temporary_latches(Session *session, plugin_ref plugin,
 
1131
                                      void *unused __attribute__((unused)))
 
1132
{
 
1133
  handlerton *hton= plugin_data(plugin, handlerton *);
 
1134
 
 
1135
  if (hton->state == SHOW_OPTION_YES && hton->release_temporary_latches)
 
1136
    hton->release_temporary_latches(hton, session);
 
1137
 
 
1138
  return false;
 
1139
}
 
1140
 
 
1141
 
 
1142
int ha_release_temporary_latches(Session *session)
 
1143
{
 
1144
  plugin_foreach(session, release_temporary_latches, DRIZZLE_STORAGE_ENGINE_PLUGIN,
 
1145
                 NULL);
 
1146
 
 
1147
  return 0;
 
1148
}
 
1149
 
 
1150
int ha_rollback_to_savepoint(Session *session, SAVEPOINT *sv)
 
1151
{
 
1152
  int error=0;
 
1153
  Session_TRANS *trans= &session->transaction.all;
 
1154
  Ha_trx_info *ha_info, *ha_info_next;
 
1155
 
 
1156
  trans->no_2pc=0;
 
1157
  /*
 
1158
    rolling back to savepoint in all storage engines that were part of the
 
1159
    transaction when the savepoint was set
 
1160
  */
 
1161
  for (ha_info= sv->ha_list; ha_info; ha_info= ha_info->next())
 
1162
  {
 
1163
    int err;
 
1164
    handlerton *ht= ha_info->ht();
 
1165
    assert(ht);
 
1166
    assert(ht->savepoint_set != 0);
 
1167
    if ((err= ht->savepoint_rollback(ht, session,
 
1168
                                     (unsigned char *)(sv+1)+ht->savepoint_offset)))
 
1169
    { // cannot happen
 
1170
      my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
 
1171
      error=1;
 
1172
    }
 
1173
    status_var_increment(session->status_var.ha_savepoint_rollback_count);
 
1174
    trans->no_2pc|= ht->prepare == 0;
 
1175
  }
 
1176
  /*
 
1177
    rolling back the transaction in all storage engines that were not part of
 
1178
    the transaction when the savepoint was set
 
1179
  */
 
1180
  for (ha_info= trans->ha_list; ha_info != sv->ha_list;
 
1181
       ha_info= ha_info_next)
 
1182
  {
 
1183
    int err;
 
1184
    handlerton *ht= ha_info->ht();
 
1185
    if ((err= ht->rollback(ht, session, !(0))))
 
1186
    { // cannot happen
 
1187
      my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
 
1188
      error=1;
 
1189
    }
 
1190
    status_var_increment(session->status_var.ha_rollback_count);
 
1191
    ha_info_next= ha_info->next();
 
1192
    ha_info->reset(); /* keep it conveniently zero-filled */
 
1193
  }
 
1194
  trans->ha_list= sv->ha_list;
 
1195
  return(error);
 
1196
}
 
1197
 
 
1198
/**
 
1199
  @note
 
1200
  according to the sql standard (ISO/IEC 9075-2:2003)
 
1201
  section "4.33.4 SQL-statements and transaction states",
 
1202
  SAVEPOINT is *not* transaction-initiating SQL-statement
 
1203
*/
 
1204
int ha_savepoint(Session *session, SAVEPOINT *sv)
 
1205
{
 
1206
  int error=0;
 
1207
  Session_TRANS *trans= &session->transaction.all;
 
1208
  Ha_trx_info *ha_info= trans->ha_list;
 
1209
  for (; ha_info; ha_info= ha_info->next())
 
1210
  {
 
1211
    int err;
 
1212
    handlerton *ht= ha_info->ht();
 
1213
    assert(ht);
 
1214
    if (! ht->savepoint_set)
 
1215
    {
 
1216
      my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "SAVEPOINT");
 
1217
      error=1;
 
1218
      break;
 
1219
    }
 
1220
    if ((err= ht->savepoint_set(ht, session, (unsigned char *)(sv+1)+ht->savepoint_offset)))
 
1221
    { // cannot happen
 
1222
      my_error(ER_GET_ERRNO, MYF(0), err);
 
1223
      error=1;
 
1224
    }
 
1225
    status_var_increment(session->status_var.ha_savepoint_count);
 
1226
  }
 
1227
  /*
 
1228
    Remember the list of registered storage engines. All new
 
1229
    engines are prepended to the beginning of the list.
 
1230
  */
 
1231
  sv->ha_list= trans->ha_list;
 
1232
  return(error);
 
1233
}
 
1234
 
 
1235
int ha_release_savepoint(Session *session, SAVEPOINT *sv)
 
1236
{
 
1237
  int error=0;
 
1238
  Ha_trx_info *ha_info= sv->ha_list;
 
1239
 
 
1240
  for (; ha_info; ha_info= ha_info->next())
 
1241
  {
 
1242
    int err;
 
1243
    handlerton *ht= ha_info->ht();
 
1244
    /* Savepoint life time is enclosed into transaction life time. */
 
1245
    assert(ht);
 
1246
    if (!ht->savepoint_release)
 
1247
      continue;
 
1248
    if ((err= ht->savepoint_release(ht, session,
 
1249
                                    (unsigned char *)(sv+1) + ht->savepoint_offset)))
 
1250
    { // cannot happen
 
1251
      my_error(ER_GET_ERRNO, MYF(0), err);
 
1252
      error=1;
 
1253
    }
 
1254
  }
 
1255
  return(error);
 
1256
}
 
1257
 
 
1258
 
 
1259
static bool snapshot_handlerton(Session *session, plugin_ref plugin, void *arg)
 
1260
{
 
1261
  handlerton *hton= plugin_data(plugin, handlerton *);
 
1262
  if (hton->state == SHOW_OPTION_YES &&
 
1263
      hton->start_consistent_snapshot)
 
1264
  {
 
1265
    hton->start_consistent_snapshot(hton, session);
 
1266
    *((bool *)arg)= false;
 
1267
  }
 
1268
  return false;
 
1269
}
 
1270
 
 
1271
int ha_start_consistent_snapshot(Session *session)
 
1272
{
 
1273
  bool warn= true;
 
1274
 
 
1275
  plugin_foreach(session, snapshot_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN, &warn);
 
1276
 
 
1277
  /*
 
1278
    Same idea as when one wants to CREATE TABLE in one engine which does not
 
1279
    exist:
 
1280
  */
 
1281
  if (warn)
 
1282
    push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
 
1283
                 "This Drizzle server does not support any "
 
1284
                 "consistent-read capable storage engine");
 
1285
  return 0;
 
1286
}
 
1287
 
 
1288
 
 
1289
static bool flush_handlerton(Session *session __attribute__((unused)),
 
1290
                             plugin_ref plugin,
 
1291
                             void *arg __attribute__((unused)))
 
1292
{
 
1293
  handlerton *hton= plugin_data(plugin, handlerton *);
 
1294
  if (hton->state == SHOW_OPTION_YES && hton->flush_logs &&
 
1295
      hton->flush_logs(hton))
 
1296
    return true;
 
1297
  return false;
 
1298
}
 
1299
 
 
1300
 
 
1301
bool ha_flush_logs(handlerton *db_type)
 
1302
{
 
1303
  if (db_type == NULL)
 
1304
  {
 
1305
    if (plugin_foreach(NULL, flush_handlerton,
 
1306
                          DRIZZLE_STORAGE_ENGINE_PLUGIN, 0))
 
1307
      return true;
 
1308
  }
 
1309
  else
 
1310
  {
 
1311
    if (db_type->state != SHOW_OPTION_YES ||
 
1312
        (db_type->flush_logs && db_type->flush_logs(db_type)))
 
1313
      return true;
 
1314
  }
 
1315
  return false;
 
1316
}
 
1317
 
 
1318
static const char *check_lowercase_names(handler *file, const char *path,
 
1319
                                         char *tmp_path)
 
1320
{
 
1321
  if (lower_case_table_names != 2 || (file->ha_table_flags() & HA_FILE_BASED))
 
1322
    return path;
 
1323
 
 
1324
  /* Ensure that table handler get path in lower case */
 
1325
  if (tmp_path != path)
 
1326
    strcpy(tmp_path, path);
 
1327
 
 
1328
  /*
 
1329
    we only should turn into lowercase database/table part
 
1330
    so start the process after homedirectory
 
1331
  */
 
1332
  my_casedn_str(files_charset_info, tmp_path + drizzle_data_home_len);
 
1333
  return tmp_path;
 
1334
}
 
1335
 
 
1336
 
 
1337
/**
 
1338
  An interceptor to hijack the text of the error message without
 
1339
  setting an error in the thread. We need the text to present it
 
1340
  in the form of a warning to the user.
 
1341
*/
 
1342
 
 
1343
struct Ha_delete_table_error_handler: public Internal_error_handler
 
1344
{
 
1345
public:
 
1346
  virtual bool handle_error(uint32_t sql_errno,
 
1347
                            const char *message,
 
1348
                            DRIZZLE_ERROR::enum_warning_level level,
 
1349
                            Session *session);
 
1350
  char buff[DRIZZLE_ERRMSG_SIZE];
 
1351
};
 
1352
 
 
1353
 
 
1354
bool
 
1355
Ha_delete_table_error_handler::
 
1356
handle_error(uint32_t sql_errno  __attribute__((unused)),
 
1357
             const char *message,
 
1358
             DRIZZLE_ERROR::enum_warning_level level __attribute__((unused)),
 
1359
             Session *session __attribute__((unused)))
 
1360
{
 
1361
  /* Grab the error message */
 
1362
  strncpy(buff, message, sizeof(buff)-1);
 
1363
  return true;
 
1364
}
 
1365
 
 
1366
 
 
1367
struct handlerton_delete_table_args {
 
1368
  Session *session;
 
1369
  const char *path;
 
1370
  handler *file;
 
1371
  int error;
 
1372
};
 
1373
 
 
1374
static bool deletetable_handlerton(Session *unused1 __attribute__((unused)),
 
1375
                                   plugin_ref plugin,
 
1376
                                   void *args)
 
1377
{
 
1378
  struct handlerton_delete_table_args *dtargs= (struct handlerton_delete_table_args *) args;
 
1379
 
 
1380
  Session *session= dtargs->session;
 
1381
  const char *path= dtargs->path;
 
1382
 
 
1383
  handler *file;
 
1384
  char tmp_path[FN_REFLEN];
 
1385
 
 
1386
  if(dtargs->error!=ENOENT) /* already deleted table */
 
1387
    return false;
 
1388
 
 
1389
  handlerton *table_type= plugin_data(plugin, handlerton *);
 
1390
 
 
1391
  if(!table_type)
 
1392
    return false;
 
1393
 
 
1394
  if(!(table_type->state == SHOW_OPTION_YES && table_type->create))
 
1395
    return false;
 
1396
 
 
1397
  if ((file= table_type->create(table_type, NULL, session->mem_root)))
 
1398
    file->init();
 
1399
  else
 
1400
    return false;
 
1401
 
 
1402
  path= check_lowercase_names(file, path, tmp_path);
 
1403
  int error= file->ha_delete_table(path);
 
1404
 
 
1405
  if(error!=ENOENT)
 
1406
  {
 
1407
    dtargs->error= error;
 
1408
    if(dtargs->file)
 
1409
      delete dtargs->file;
 
1410
    dtargs->file= file;
 
1411
    return true;
 
1412
  }
 
1413
 
 
1414
  return false;
 
1415
}
 
1416
 
 
1417
/**
 
1418
  This should return ENOENT if the file doesn't exists.
 
1419
  The .frm file will be deleted only if we return 0 or ENOENT
 
1420
*/
 
1421
int ha_delete_table(Session *session, const char *path,
 
1422
                    const char *db, const char *alias, bool generate_warning)
 
1423
{
 
1424
  TABLE_SHARE dummy_share;
 
1425
  Table dummy_table;
 
1426
 
 
1427
  struct handlerton_delete_table_args dtargs;
 
1428
  dtargs.error= ENOENT;
 
1429
  dtargs.session= session;
 
1430
  dtargs.path= path;
 
1431
  dtargs.file= NULL;
 
1432
 
 
1433
  plugin_foreach(NULL, deletetable_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN,
 
1434
                 &dtargs);
 
1435
 
 
1436
  memset(&dummy_table, 0, sizeof(dummy_table));
 
1437
  memset(&dummy_share, 0, sizeof(dummy_share));
 
1438
  dummy_table.s= &dummy_share;
 
1439
 
 
1440
  if (dtargs.error && generate_warning)
 
1441
  {
 
1442
    /*
 
1443
      Because file->print_error() use my_error() to generate the error message
 
1444
      we use an internal error handler to intercept it and store the text
 
1445
      in a temporary buffer. Later the message will be presented to user
 
1446
      as a warning.
 
1447
    */
 
1448
    Ha_delete_table_error_handler ha_delete_table_error_handler;
 
1449
 
 
1450
    /* Fill up strucutures that print_error may need */
 
1451
    dummy_share.path.str= (char*) path;
 
1452
    dummy_share.path.length= strlen(path);
 
1453
    dummy_share.db.str= (char*) db;
 
1454
    dummy_share.db.length= strlen(db);
 
1455
    dummy_share.table_name.str= (char*) alias;
 
1456
    dummy_share.table_name.length= strlen(alias);
 
1457
    dummy_table.alias= alias;
 
1458
 
 
1459
    handler *file= dtargs.file;
 
1460
    file->change_table_ptr(&dummy_table, &dummy_share);
 
1461
 
 
1462
    session->push_internal_handler(&ha_delete_table_error_handler);
 
1463
    file->print_error(dtargs.error, 0);
 
1464
 
 
1465
    session->pop_internal_handler();
 
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
}
52
1480
 
53
1481
/****************************************************************************
54
 
** General Cursor functions
 
1482
** General handler functions
55
1483
****************************************************************************/
56
 
Cursor::Cursor(plugin::StorageEngine &engine_arg,
57
 
               TableShare &share_arg)
58
 
  : table_share(&share_arg), table(0),
59
 
    estimation_rows_to_insert(0), engine(&engine_arg),
60
 
    ref(0), in_range_check_pushed_down(false),
61
 
    key_used_on_scan(MAX_KEY), active_index(MAX_KEY),
62
 
    ref_length(sizeof(internal::my_off_t)),
63
 
    inited(NONE),
64
 
    locked(false), implicit_emptied(0),
65
 
    next_insert_id(0), insert_id_for_cur_row(0)
66
 
{ }
67
 
 
68
 
Cursor::~Cursor(void)
69
 
{
70
 
  assert(locked == false);
71
 
  /* TODO: assert(inited == NONE); */
72
 
}
73
 
 
74
 
 
75
 
Cursor *Cursor::clone(memory::Root *mem_root)
76
 
{
77
 
  Cursor *new_handler= table->s->db_type()->getCursor(*table->s, mem_root);
78
 
 
 
1484
handler *handler::clone(MEM_ROOT *mem_root)
 
1485
{
 
1486
  handler *new_handler= get_new_handler(table->s, mem_root, table->s->db_type());
79
1487
  /*
80
 
    Allocate Cursor->ref here because otherwise ha_open will allocate it
 
1488
    Allocate handler->ref here because otherwise ha_open will allocate it
81
1489
    on this->table->mem_root and we will not be able to reclaim that memory
82
 
    when the clone Cursor object is destroyed.
 
1490
    when the clone handler object is destroyed.
83
1491
  */
84
1492
  if (!(new_handler->ref= (unsigned char*) alloc_root(mem_root, ALIGN_SIZE(ref_length)*2)))
85
1493
    return NULL;
91
1499
  return NULL;
92
1500
}
93
1501
 
94
 
int Cursor::ha_index_init(uint32_t idx, bool sorted)
 
1502
int handler::ha_index_init(uint32_t idx, bool sorted)
95
1503
{
96
1504
  int result;
97
 
  assert(inited == NONE);
 
1505
  assert(inited==NONE);
98
1506
  if (!(result= index_init(idx, sorted)))
99
1507
    inited=INDEX;
100
1508
  end_range= NULL;
101
 
  return result;
 
1509
  return(result);
102
1510
}
103
1511
 
104
 
int Cursor::ha_index_end()
 
1512
int handler::ha_index_end()
105
1513
{
106
1514
  assert(inited==INDEX);
107
1515
  inited=NONE;
109
1517
  return(index_end());
110
1518
}
111
1519
 
112
 
int Cursor::ha_rnd_init(bool scan)
 
1520
int handler::ha_rnd_init(bool scan)
113
1521
{
114
1522
  int result;
115
1523
  assert(inited==NONE || (inited==RND && scan));
116
1524
  inited= (result= rnd_init(scan)) ? NONE: RND;
117
 
 
118
 
  return result;
 
1525
  return(result);
119
1526
}
120
1527
 
121
 
int Cursor::ha_rnd_end()
 
1528
int handler::ha_rnd_end()
122
1529
{
123
1530
  assert(inited==RND);
124
1531
  inited=NONE;
125
1532
  return(rnd_end());
126
1533
}
127
1534
 
128
 
int Cursor::ha_index_or_rnd_end()
 
1535
int handler::ha_index_or_rnd_end()
129
1536
{
130
1537
  return inited == INDEX ? ha_index_end() : inited == RND ? ha_rnd_end() : 0;
131
1538
}
132
1539
 
133
 
void Cursor::ha_start_bulk_insert(ha_rows rows)
 
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)
134
1546
{
135
1547
  estimation_rows_to_insert= rows;
136
1548
  start_bulk_insert(rows);
137
1549
}
138
1550
 
139
 
int Cursor::ha_end_bulk_insert()
 
1551
int handler::ha_end_bulk_insert()
140
1552
{
141
1553
  estimation_rows_to_insert= 0;
142
1554
  return end_bulk_insert();
143
1555
}
144
1556
 
145
 
void Cursor::change_table_ptr(Table *table_arg, TableShare *share)
 
1557
void handler::change_table_ptr(Table *table_arg, TABLE_SHARE *share)
146
1558
{
147
1559
  table= table_arg;
148
1560
  table_share= share;
149
1561
}
150
1562
 
151
 
const key_map *Cursor::keys_to_use_for_scanning()
 
1563
const key_map *handler::keys_to_use_for_scanning()
152
1564
{
153
1565
  return &key_map_empty;
154
1566
}
155
1567
 
156
 
bool Cursor::has_transactions()
 
1568
bool handler::has_transactions()
157
1569
{
158
 
  return (table->s->db_type()->check_flag(HTON_BIT_DOES_TRANSACTIONS));
 
1570
  return (ha_table_flags() & HA_NO_TRANSACTIONS) == 0;
159
1571
}
160
1572
 
161
 
void Cursor::ha_statistic_increment(ulong system_status_var::*offset) const
 
1573
void handler::ha_statistic_increment(ulong SSV::*offset) const
162
1574
{
163
1575
  status_var_increment(table->in_use->status_var.*offset);
164
1576
}
165
1577
 
166
 
void **Cursor::ha_data(Session *session) const
 
1578
void **handler::ha_data(Session *session) const
167
1579
{
168
 
  return session->getEngineData(engine);
 
1580
  return session_ha_data(session, ht);
169
1581
}
170
1582
 
171
 
Session *Cursor::ha_session(void) const
 
1583
Session *handler::ha_session(void) const
172
1584
{
173
1585
  assert(!table || !table->in_use || table->in_use == current_session);
174
1586
  return (table && table->in_use) ? table->in_use : current_session;
175
1587
}
176
1588
 
177
1589
 
178
 
bool Cursor::is_fatal_error(int error, uint32_t flags)
 
1590
bool handler::is_fatal_error(int error, uint32_t flags)
179
1591
{
180
1592
  if (!error ||
181
1593
      ((flags & HA_CHECK_DUP_KEY) &&
186
1598
}
187
1599
 
188
1600
 
189
 
ha_rows Cursor::records() { return stats.records; }
190
 
uint64_t Cursor::tableSize() { return stats.index_file_length + stats.data_file_length; }
191
 
uint64_t Cursor::rowSize() { return table->getRecordLength() + table->sizeFields(); }
 
1601
ha_rows handler::records() { return stats.records; }
192
1602
 
193
1603
/**
194
 
  Open database-Cursor.
 
1604
  Open database-handler.
195
1605
 
196
1606
  Try O_RDONLY if cannot open as O_RDWR
197
1607
  Don't wait for locks if not HA_OPEN_WAIT_IF_LOCKED is set
198
1608
*/
199
 
int Cursor::ha_open(Table *table_arg, const char *name, int mode,
 
1609
int handler::ha_open(Table *table_arg, const char *name, int mode,
200
1610
                     int test_if_locked)
201
1611
{
202
1612
  int error;
216
1626
  }
217
1627
  if (error)
218
1628
  {
219
 
    errno= error;                            /* Safeguard */
 
1629
    my_errno= error;                            /* Safeguard */
220
1630
  }
221
1631
  else
222
1632
  {
224
1634
      table->db_stat|=HA_READ_ONLY;
225
1635
    (void) extra(HA_EXTRA_NO_READCHECK);        // Not needed in SQL
226
1636
 
227
 
    /* ref is already allocated for us if we're called from Cursor::clone() */
 
1637
    /* ref is already allocated for us if we're called from handler::clone() */
228
1638
    if (!ref && !(ref= (unsigned char*) alloc_root(&table->mem_root,
229
1639
                                          ALIGN_SIZE(ref_length)*2)))
230
1640
    {
233
1643
    }
234
1644
    else
235
1645
      dup_ref=ref+ALIGN_SIZE(ref_length);
 
1646
    cached_table_flags= table_flags();
236
1647
  }
237
 
  return error;
 
1648
  return(error);
238
1649
}
239
1650
 
240
1651
/**
244
1655
  handlers for random position
245
1656
*/
246
1657
 
247
 
int Cursor::rnd_pos_by_record(unsigned char *record)
 
1658
int handler::rnd_pos_by_record(unsigned char *record)
248
1659
{
249
1660
  register int error;
250
1661
 
251
1662
  position(record);
252
1663
  if (inited && (error= ha_index_end()))
253
 
    return error;
 
1664
    return(error);
254
1665
  if ((error= ha_rnd_init(false)))
255
 
    return error;
 
1666
    return(error);
256
1667
 
257
 
  return rnd_pos(record, ref);
 
1668
  return(rnd_pos(record, ref));
258
1669
}
259
1670
 
260
1671
/**
263
1674
  This is never called for InnoDB tables, as these table types
264
1675
  has the HA_STATS_RECORDS_IS_EXACT set.
265
1676
*/
266
 
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)
267
1678
{
268
1679
  register int error;
269
1680
 
270
 
  ha_statistic_increment(&system_status_var::ha_read_first_count);
 
1681
  ha_statistic_increment(&SSV::ha_read_first_count);
271
1682
 
272
1683
  /*
273
1684
    If there is very few deleted rows in the table, find the first row by
275
1686
    TODO remove the test for HA_READ_ORDER
276
1687
  */
277
1688
  if (stats.deleted < 10 || primary_key >= MAX_KEY ||
278
 
      !(table->index_flags(primary_key) & HA_READ_ORDER))
 
1689
      !(index_flags(primary_key, 0, 0) & HA_READ_ORDER))
279
1690
  {
280
1691
    (void) ha_rnd_init(1);
281
1692
    while ((error= rnd_next(buf)) == HA_ERR_RECORD_DELETED) ;
288
1699
    error=index_first(buf);
289
1700
    (void) ha_index_end();
290
1701
  }
291
 
  return error;
 
1702
  return(error);
292
1703
}
293
1704
 
294
1705
/**
315
1726
}
316
1727
 
317
1728
 
318
 
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)
319
1730
{
320
1731
  /*
321
1732
    If we have set Session::next_insert_id previously and plan to insert an
368
1779
 
369
1780
  Updates columns with type NEXT_NUMBER if:
370
1781
 
371
 
  - 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)
372
1784
  - If column is set to 0 and (sql_mode & MODE_NO_AUTO_VALUE_ON_ZERO) is not
373
1785
    set. In the future we will only set NEXT_NUMBER fields if one sets them
374
1786
    to NULL (or they are not included in the insert list).
389
1801
    reserved for us.
390
1802
 
391
1803
  - In both cases, for the following rows we use those reserved values without
392
 
    calling the Cursor again (we just progress in the interval, computing
 
1804
    calling the handler again (we just progress in the interval, computing
393
1805
    each new value from the previous one). Until we have exhausted them, then
394
1806
    we either take the next provided interval or call get_auto_increment()
395
1807
    again to reserve a new interval.
436
1848
#define AUTO_INC_DEFAULT_NB_MAX_BITS 16
437
1849
#define AUTO_INC_DEFAULT_NB_MAX ((1 << AUTO_INC_DEFAULT_NB_MAX_BITS) - 1)
438
1850
 
439
 
int Cursor::update_auto_increment()
 
1851
int handler::update_auto_increment()
440
1852
{
441
1853
  uint64_t nr, nb_reserved_values;
442
1854
  bool append= false;
449
1861
  */
450
1862
  assert(next_insert_id >= auto_inc_interval_for_cur_row.minimum());
451
1863
 
452
 
  /* We check if auto_increment_field_not_null is false
453
 
     for an auto increment column, not a magic value like NULL is.
454
 
     same as sql_mode=NO_AUTO_VALUE_ON_ZERO */
455
 
 
456
 
  if ((nr= table->next_number_field->val_int()) != 0
457
 
      || table->auto_increment_field_not_null)
 
1864
  if ((nr= table->next_number_field->val_int()) != 0)
458
1865
  {
459
1866
    /*
460
1867
      Update next_insert_id if we had already generated a value in this
464
1871
    */
465
1872
    adjust_next_insert_id_after_explicit_value(nr);
466
1873
    insert_id_for_cur_row= 0; // didn't generate anything
467
 
 
468
 
    return 0;
 
1874
    return(0);
469
1875
  }
470
1876
 
471
1877
  if ((nr= next_insert_id) >= auto_inc_interval_for_cur_row.maximum())
481
1887
    else
482
1888
    {
483
1889
      /*
484
 
        Cursor::estimation_rows_to_insert was set by
485
 
        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".
486
1892
      */
487
1893
      uint32_t nb_already_reserved_intervals=
488
1894
        session->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements();
508
1914
        {
509
1915
          nb_desired_values= AUTO_INC_DEFAULT_NB_ROWS *
510
1916
            (1 << nb_already_reserved_intervals);
511
 
          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);
512
1918
        }
513
1919
        else
514
1920
          nb_desired_values= AUTO_INC_DEFAULT_NB_MAX;
519
1925
                         nb_desired_values, &nr,
520
1926
                         &nb_reserved_values);
521
1927
      if (nr == ~(uint64_t) 0)
522
 
        return HA_ERR_AUTOINC_READ_FAILED;  // Mark failure
 
1928
        return(HA_ERR_AUTOINC_READ_FAILED);  // Mark failure
523
1929
 
524
1930
      /*
525
1931
        That rounding below should not be needed when all engines actually
545
1951
      first test if the query was aborted due to strict mode constraints
546
1952
    */
547
1953
    if (session->killed == Session::KILL_BAD_DATA)
548
 
      return HA_ERR_AUTOINC_ERANGE;
 
1954
      return(HA_ERR_AUTOINC_ERANGE);
549
1955
 
550
1956
    /*
551
1957
      field refused this value (overflow) and truncated it, use the result of
579
1985
  */
580
1986
  set_next_insert_id(compute_next_insert_id(nr, variables));
581
1987
 
582
 
  return 0;
583
 
}
584
 
 
585
 
 
586
 
/**
587
 
  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.
588
2012
 
589
2013
  offset and increment means that we want values to be of the form
590
2014
  offset + N * increment, where N>=0 is integer.
595
2019
  @param offset
596
2020
  @param increment
597
2021
  @param nb_desired_values   how many values we want
598
 
  @param first_value         (OUT) the first value reserved by the Cursor
599
 
  @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
600
2024
*/
601
 
void Cursor::get_auto_increment(uint64_t ,
602
 
                                 uint64_t ,
603
 
                                 uint64_t ,
 
2025
void handler::get_auto_increment(uint64_t offset __attribute__((unused)),
 
2026
                                 uint64_t increment __attribute__((unused)),
 
2027
                                 uint64_t nb_desired_values __attribute__((unused)),
604
2028
                                 uint64_t *first_value,
605
2029
                                 uint64_t *nb_reserved_values)
606
2030
{
608
2032
  int error;
609
2033
 
610
2034
  (void) extra(HA_EXTRA_KEYREAD);
611
 
  table->mark_columns_used_by_index_no_reset(table->s->next_number_index);
 
2035
  table->mark_columns_used_by_index_no_reset(table->s->next_number_index,
 
2036
                                        table->read_set);
 
2037
  column_bitmaps_signal();
612
2038
  index_init(table->s->next_number_index, 1);
613
2039
  if (table->s->next_number_keypart == 0)
614
2040
  {                                             // Autoincrement at key-start
615
2041
    error=index_last(table->record[1]);
616
2042
    /*
617
2043
      MySQL implicitely assumes such method does locking (as MySQL decides to
618
 
      use nr+increment without checking again with the Cursor, in
619
 
      Cursor::update_auto_increment()), so reserves to infinite.
 
2044
      use nr+increment without checking again with the handler, in
 
2045
      handler::update_auto_increment()), so reserves to infinite.
620
2046
    */
621
2047
    *nb_reserved_values= UINT64_MAX;
622
2048
  }
649
2075
}
650
2076
 
651
2077
 
652
 
void Cursor::ha_release_auto_increment()
 
2078
void handler::ha_release_auto_increment()
653
2079
{
654
2080
  release_auto_increment();
655
2081
  insert_id_for_cur_row= 0;
665
2091
  }
666
2092
}
667
2093
 
668
 
void Cursor::drop_table(const char *)
 
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,(uint) key_nr);
 
2111
    uint32_t max_length=DRIZZLE_ERRMSG_SIZE-(uint) 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,(uint) key_nr);
 
2175
      max_length= (DRIZZLE_ERRMSG_SIZE-
 
2176
                   (uint) 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
    break;
 
2291
  default:
 
2292
    {
 
2293
      /* The error was "unknown" to this function.
 
2294
         Ask handler if it has got a message for this error */
 
2295
      bool temporary= false;
 
2296
      String str;
 
2297
      temporary= get_error_message(error, &str);
 
2298
      if (!str.is_empty())
 
2299
      {
 
2300
        const char* engine= table_type();
 
2301
        if (temporary)
 
2302
          my_error(ER_GET_TEMPORARY_ERRMSG, MYF(0), error, str.ptr(), engine);
 
2303
        else
 
2304
          my_error(ER_GET_ERRMSG, MYF(0), error, str.ptr(), engine);
 
2305
      }
 
2306
      else
 
2307
        my_error(ER_GET_ERRNO,errflag,error);
 
2308
      return;
 
2309
    }
 
2310
  }
 
2311
  my_error(textno, errflag, table_share->table_name.str, error);
 
2312
  return;
 
2313
}
 
2314
 
 
2315
 
 
2316
/**
 
2317
  Return an error message specific to this handler.
 
2318
 
 
2319
  @param error  error code previously returned by handler
 
2320
  @param buf    pointer to String where to add error message
 
2321
 
 
2322
  @return
 
2323
    Returns true if this is a temporary error
 
2324
*/
 
2325
bool handler::get_error_message(int error __attribute__((unused)),
 
2326
                                String* buf __attribute__((unused)))
 
2327
{
 
2328
  return false;
 
2329
}
 
2330
 
 
2331
 
 
2332
int handler::ha_check_for_upgrade(HA_CHECK_OPT *check_opt)
 
2333
{
 
2334
  KEY *keyinfo, *keyend;
 
2335
  KEY_PART_INFO *keypart, *keypartend;
 
2336
 
 
2337
  if (!table->s->mysql_version)
 
2338
  {
 
2339
    /* check for blob-in-key error */
 
2340
    keyinfo= table->key_info;
 
2341
    keyend= table->key_info + table->s->keys;
 
2342
    for (; keyinfo < keyend; keyinfo++)
 
2343
    {
 
2344
      keypart= keyinfo->key_part;
 
2345
      keypartend= keypart + keyinfo->key_parts;
 
2346
      for (; keypart < keypartend; keypart++)
 
2347
      {
 
2348
        if (!keypart->fieldnr)
 
2349
          continue;
 
2350
        Field *field= table->field[keypart->fieldnr-1];
 
2351
        if (field->type() == DRIZZLE_TYPE_BLOB)
 
2352
        {
 
2353
          if (check_opt->sql_flags & TT_FOR_UPGRADE)
 
2354
            check_opt->flags= T_MEDIUM;
 
2355
          return HA_ADMIN_NEEDS_CHECK;
 
2356
        }
 
2357
      }
 
2358
    }
 
2359
  }
 
2360
  return check_for_upgrade(check_opt);
 
2361
}
 
2362
 
 
2363
 
 
2364
/* Code left, but Drizzle has no legacy yet (while MySQL did) */
 
2365
int handler::check_old_types()
 
2366
{
 
2367
  return 0;
 
2368
}
 
2369
 
 
2370
/**
 
2371
  @return
 
2372
    key if error because of duplicated keys
 
2373
*/
 
2374
uint32_t handler::get_dup_key(int error)
 
2375
{
 
2376
  table->file->errkey  = (uint) -1;
 
2377
  if (error == HA_ERR_FOUND_DUPP_KEY || error == HA_ERR_FOREIGN_DUPLICATE_KEY ||
 
2378
      error == HA_ERR_FOUND_DUPP_UNIQUE ||
 
2379
      error == HA_ERR_DROP_INDEX_FK)
 
2380
    info(HA_STATUS_ERRKEY | HA_STATUS_NO_LOCK);
 
2381
  return(table->file->errkey);
 
2382
}
 
2383
 
 
2384
 
 
2385
/**
 
2386
  Delete all files with extension from bas_ext().
 
2387
 
 
2388
  @param name           Base name of table
 
2389
 
 
2390
  @note
 
2391
    We assume that the handler may return more extensions than
 
2392
    was actually used for the file.
 
2393
 
 
2394
  @retval
 
2395
    0   If we successfully deleted at least one file from base_ext and
 
2396
    didn't get any other errors than ENOENT
 
2397
  @retval
 
2398
    !0  Error
 
2399
*/
 
2400
int handler::delete_table(const char *name)
 
2401
{
 
2402
  int error= 0;
 
2403
  int enoent_or_zero= ENOENT;                   // Error if no file was deleted
 
2404
  char buff[FN_REFLEN];
 
2405
 
 
2406
  for (const char **ext=bas_ext(); *ext ; ext++)
 
2407
  {
 
2408
    fn_format(buff, name, "", *ext, MY_UNPACK_FILENAME|MY_APPEND_EXT);
 
2409
    if (my_delete_with_symlink(buff, MYF(0)))
 
2410
    {
 
2411
      if ((error= my_errno) != ENOENT)
 
2412
        break;
 
2413
    }
 
2414
    else
 
2415
      enoent_or_zero= 0;                        // No error for ENOENT
 
2416
    error= enoent_or_zero;
 
2417
  }
 
2418
  return error;
 
2419
}
 
2420
 
 
2421
 
 
2422
int handler::rename_table(const char * from, const char * to)
 
2423
{
 
2424
  int error= 0;
 
2425
  for (const char **ext= bas_ext(); *ext ; ext++)
 
2426
  {
 
2427
    if (rename_file_ext(from, to, *ext))
 
2428
    {
 
2429
      if ((error=my_errno) != ENOENT)
 
2430
        break;
 
2431
      error= 0;
 
2432
    }
 
2433
  }
 
2434
  return error;
 
2435
}
 
2436
 
 
2437
 
 
2438
void handler::drop_table(const char *name)
669
2439
{
670
2440
  close();
 
2441
  delete_table(name);
671
2442
}
672
2443
 
673
2444
 
686
2457
  @retval
687
2458
    HA_ADMIN_NOT_IMPLEMENTED
688
2459
*/
689
 
int Cursor::ha_check(Session *, HA_CHECK_OPT *)
 
2460
int handler::ha_check(Session *session, HA_CHECK_OPT *check_opt)
690
2461
{
 
2462
  int error;
 
2463
 
 
2464
  if ((table->s->mysql_version >= DRIZZLE_VERSION_ID) &&
 
2465
      (check_opt->sql_flags & TT_FOR_UPGRADE))
 
2466
    return 0;
 
2467
 
 
2468
  if (table->s->mysql_version < DRIZZLE_VERSION_ID)
 
2469
  {
 
2470
    if ((error= check_old_types()))
 
2471
      return error;
 
2472
    error= ha_check_for_upgrade(check_opt);
 
2473
    if (error && (error != HA_ADMIN_NEEDS_CHECK))
 
2474
      return error;
 
2475
    if (!error && (check_opt->sql_flags & TT_FOR_UPGRADE))
 
2476
      return 0;
 
2477
  }
 
2478
  if ((error= check(session, check_opt)))
 
2479
    return error;
691
2480
  return HA_ADMIN_OK;
692
2481
}
693
2482
 
698
2487
 
699
2488
inline
700
2489
void
701
 
Cursor::setTransactionReadWrite()
 
2490
handler::mark_trx_read_write()
702
2491
{
703
 
  ResourceContext *resource_context= ha_session()->getResourceContext(engine);
 
2492
  Ha_trx_info *ha_info= &ha_session()->ha_data[ht->slot].ha_info[0];
704
2493
  /*
705
2494
    When a storage engine method is called, the transaction must
706
2495
    have been started, unless it's a DDL call, for which the
709
2498
    Unfortunately here we can't know know for sure if the engine
710
2499
    has registered the transaction or not, so we must check.
711
2500
  */
712
 
  if (resource_context->isStarted())
 
2501
  if (ha_info->is_started())
713
2502
  {
714
 
    resource_context->markModifiedData();
 
2503
    /*
 
2504
      table_share can be NULL in ha_delete_table(). See implementation
 
2505
      of standalone function ha_delete_table() in sql_base.cc.
 
2506
    */
 
2507
    if (table_share == NULL || table_share->tmp_table == NO_TMP_TABLE)
 
2508
      ha_info->set_trx_read_write();
715
2509
  }
716
2510
}
717
2511
 
718
2512
 
719
2513
/**
 
2514
  Repair table: public interface.
 
2515
 
 
2516
  @sa handler::repair()
 
2517
*/
 
2518
 
 
2519
int handler::ha_repair(Session* session, HA_CHECK_OPT* check_opt)
 
2520
{
 
2521
  int result;
 
2522
 
 
2523
  mark_trx_read_write();
 
2524
 
 
2525
  if ((result= repair(session, check_opt)))
 
2526
    return result;
 
2527
  return HA_ADMIN_OK;
 
2528
}
 
2529
 
 
2530
 
 
2531
/**
 
2532
  Bulk update row: public interface.
 
2533
 
 
2534
  @sa handler::bulk_update_row()
 
2535
*/
 
2536
 
 
2537
int
 
2538
handler::ha_bulk_update_row(const unsigned char *old_data, unsigned char *new_data,
 
2539
                            uint32_t *dup_key_found)
 
2540
{
 
2541
  mark_trx_read_write();
 
2542
 
 
2543
  return bulk_update_row(old_data, new_data, dup_key_found);
 
2544
}
 
2545
 
 
2546
 
 
2547
/**
720
2548
  Delete all rows: public interface.
721
2549
 
722
 
  @sa Cursor::delete_all_rows()
723
 
 
724
 
  @note
725
 
 
726
 
  This is now equalivalent to TRUNCATE TABLE.
 
2550
  @sa handler::delete_all_rows()
727
2551
*/
728
2552
 
729
2553
int
730
 
Cursor::ha_delete_all_rows()
 
2554
handler::ha_delete_all_rows()
731
2555
{
732
 
  setTransactionReadWrite();
733
 
 
734
 
  int result= delete_all_rows();
735
 
 
736
 
  if (result == 0)
737
 
  {
738
 
    /** 
739
 
     * Trigger post-truncate notification to plugins... 
740
 
     *
741
 
     * @todo Make ReplicationServices generic to AfterTriggerServices
742
 
     * or similar...
743
 
     */
744
 
    Session *const session= table->in_use;
745
 
    ReplicationServices &replication_services= ReplicationServices::singleton();
746
 
    replication_services.truncateTable(session, table);
747
 
  }
748
 
 
749
 
  return result;
 
2556
  mark_trx_read_write();
 
2557
 
 
2558
  return delete_all_rows();
750
2559
}
751
2560
 
752
2561
 
753
2562
/**
754
2563
  Reset auto increment: public interface.
755
2564
 
756
 
  @sa Cursor::reset_auto_increment()
 
2565
  @sa handler::reset_auto_increment()
757
2566
*/
758
2567
 
759
2568
int
760
 
Cursor::ha_reset_auto_increment(uint64_t value)
 
2569
handler::ha_reset_auto_increment(uint64_t value)
761
2570
{
762
 
  setTransactionReadWrite();
 
2571
  mark_trx_read_write();
763
2572
 
764
2573
  return reset_auto_increment(value);
765
2574
}
766
2575
 
767
2576
 
768
2577
/**
 
2578
  Optimize table: public interface.
 
2579
 
 
2580
  @sa handler::optimize()
 
2581
*/
 
2582
 
 
2583
int
 
2584
handler::ha_optimize(Session* session, HA_CHECK_OPT* check_opt)
 
2585
{
 
2586
  mark_trx_read_write();
 
2587
 
 
2588
  return optimize(session, check_opt);
 
2589
}
 
2590
 
 
2591
 
 
2592
/**
769
2593
  Analyze table: public interface.
770
2594
 
771
 
  @sa Cursor::analyze()
 
2595
  @sa handler::analyze()
772
2596
*/
773
2597
 
774
2598
int
775
 
Cursor::ha_analyze(Session* session, HA_CHECK_OPT*)
776
 
{
777
 
  setTransactionReadWrite();
778
 
 
779
 
  return analyze(session);
780
 
}
 
2599
handler::ha_analyze(Session* session, HA_CHECK_OPT* check_opt)
 
2600
{
 
2601
  mark_trx_read_write();
 
2602
 
 
2603
  return analyze(session, check_opt);
 
2604
}
 
2605
 
 
2606
 
 
2607
/**
 
2608
  Check and repair table: public interface.
 
2609
 
 
2610
  @sa handler::check_and_repair()
 
2611
*/
 
2612
 
 
2613
bool
 
2614
handler::ha_check_and_repair(Session *session)
 
2615
{
 
2616
  mark_trx_read_write();
 
2617
 
 
2618
  return check_and_repair(session);
 
2619
}
 
2620
 
781
2621
 
782
2622
/**
783
2623
  Disable indexes: public interface.
784
2624
 
785
 
  @sa Cursor::disable_indexes()
 
2625
  @sa handler::disable_indexes()
786
2626
*/
787
2627
 
788
2628
int
789
 
Cursor::ha_disable_indexes(uint32_t mode)
 
2629
handler::ha_disable_indexes(uint32_t mode)
790
2630
{
791
 
  setTransactionReadWrite();
 
2631
  mark_trx_read_write();
792
2632
 
793
2633
  return disable_indexes(mode);
794
2634
}
797
2637
/**
798
2638
  Enable indexes: public interface.
799
2639
 
800
 
  @sa Cursor::enable_indexes()
 
2640
  @sa handler::enable_indexes()
801
2641
*/
802
2642
 
803
2643
int
804
 
Cursor::ha_enable_indexes(uint32_t mode)
 
2644
handler::ha_enable_indexes(uint32_t mode)
805
2645
{
806
 
  setTransactionReadWrite();
 
2646
  mark_trx_read_write();
807
2647
 
808
2648
  return enable_indexes(mode);
809
2649
}
812
2652
/**
813
2653
  Discard or import tablespace: public interface.
814
2654
 
815
 
  @sa Cursor::discard_or_import_tablespace()
 
2655
  @sa handler::discard_or_import_tablespace()
816
2656
*/
817
2657
 
818
2658
int
819
 
Cursor::ha_discard_or_import_tablespace(bool discard)
 
2659
handler::ha_discard_or_import_tablespace(bool discard)
820
2660
{
821
 
  setTransactionReadWrite();
 
2661
  mark_trx_read_write();
822
2662
 
823
2663
  return discard_or_import_tablespace(discard);
824
2664
}
825
2665
 
 
2666
 
 
2667
/**
 
2668
  Prepare for alter: public interface.
 
2669
 
 
2670
  Called to prepare an *online* ALTER.
 
2671
 
 
2672
  @sa handler::prepare_for_alter()
 
2673
*/
 
2674
 
 
2675
void
 
2676
handler::ha_prepare_for_alter()
 
2677
{
 
2678
  mark_trx_read_write();
 
2679
 
 
2680
  prepare_for_alter();
 
2681
}
 
2682
 
 
2683
 
 
2684
/**
 
2685
  Rename table: public interface.
 
2686
 
 
2687
  @sa handler::rename_table()
 
2688
*/
 
2689
 
 
2690
int
 
2691
handler::ha_rename_table(const char *from, const char *to)
 
2692
{
 
2693
  mark_trx_read_write();
 
2694
 
 
2695
  return rename_table(from, to);
 
2696
}
 
2697
 
 
2698
 
 
2699
/**
 
2700
  Delete table: public interface.
 
2701
 
 
2702
  @sa handler::delete_table()
 
2703
*/
 
2704
 
 
2705
int
 
2706
handler::ha_delete_table(const char *name)
 
2707
{
 
2708
  mark_trx_read_write();
 
2709
 
 
2710
  return delete_table(name);
 
2711
}
 
2712
 
 
2713
 
826
2714
/**
827
2715
  Drop table in the engine: public interface.
828
2716
 
829
 
  @sa Cursor::drop_table()
 
2717
  @sa handler::drop_table()
830
2718
*/
831
2719
 
832
2720
void
833
 
Cursor::closeMarkForDelete(const char *name)
 
2721
handler::ha_drop_table(const char *name)
834
2722
{
835
 
  setTransactionReadWrite();
 
2723
  mark_trx_read_write();
836
2724
 
837
2725
  return drop_table(name);
838
2726
}
839
2727
 
840
 
int Cursor::index_next_same(unsigned char *buf, const unsigned char *key, uint32_t keylen)
 
2728
 
 
2729
/**
 
2730
  Create a table in the engine: public interface.
 
2731
 
 
2732
  @sa handler::create()
 
2733
*/
 
2734
 
 
2735
int
 
2736
handler::ha_create(const char *name, Table *form, HA_CREATE_INFO *info)
 
2737
{
 
2738
  mark_trx_read_write();
 
2739
 
 
2740
  return create(name, form, info);
 
2741
}
 
2742
 
 
2743
 
 
2744
/**
 
2745
  Create handler files for CREATE TABLE: public interface.
 
2746
 
 
2747
  @sa handler::create_handler_files()
 
2748
*/
 
2749
 
 
2750
int
 
2751
handler::ha_create_handler_files(const char *name, const char *old_name,
 
2752
                        int action_flag, HA_CREATE_INFO *info)
 
2753
{
 
2754
  mark_trx_read_write();
 
2755
 
 
2756
  return create_handler_files(name, old_name, action_flag, info);
 
2757
}
 
2758
 
 
2759
 
 
2760
/**
 
2761
  Tell the storage engine that it is allowed to "disable transaction" in the
 
2762
  handler. It is a hint that ACID is not required - it is used in NDB for
 
2763
  ALTER Table, for example, when data are copied to temporary table.
 
2764
  A storage engine may treat this hint any way it likes. NDB for example
 
2765
  starts to commit every now and then automatically.
 
2766
  This hint can be safely ignored.
 
2767
*/
 
2768
int ha_enable_transaction(Session *session, bool on)
 
2769
{
 
2770
  int error=0;
 
2771
 
 
2772
  if ((session->transaction.on= on))
 
2773
  {
 
2774
    /*
 
2775
      Now all storage engines should have transaction handling enabled.
 
2776
      But some may have it enabled all the time - "disabling" transactions
 
2777
      is an optimization hint that storage engine is free to ignore.
 
2778
      So, let's commit an open transaction (if any) now.
 
2779
    */
 
2780
    if (!(error= ha_commit_trans(session, 0)))
 
2781
      error= end_trans(session, COMMIT);
 
2782
  }
 
2783
  return(error);
 
2784
}
 
2785
 
 
2786
int handler::index_next_same(unsigned char *buf, const unsigned char *key, uint32_t keylen)
841
2787
{
842
2788
  int error;
843
2789
  if (!(error=index_next(buf)))
844
2790
  {
845
 
    ptrdiff_t ptrdiff= buf - table->record[0];
 
2791
    my_ptrdiff_t ptrdiff= buf - table->record[0];
846
2792
    unsigned char *save_record_0= NULL;
847
2793
    KEY *key_info= NULL;
848
2794
    KEY_PART_INFO *key_part;
884
2830
        key_part->field->move_field_offset(-ptrdiff);
885
2831
    }
886
2832
  }
887
 
  return error;
 
2833
  return(error);
888
2834
}
889
2835
 
890
2836
 
891
2837
/****************************************************************************
892
 
** Some general functions that isn't in the Cursor class
 
2838
** Some general functions that isn't in the handler class
893
2839
****************************************************************************/
894
2840
 
895
2841
/**
 
2842
  Initiates table-file and calls appropriate database-creator.
 
2843
 
 
2844
  @retval
 
2845
   0  ok
 
2846
  @retval
 
2847
   1  error
 
2848
*/
 
2849
int ha_create_table(Session *session, const char *path,
 
2850
                    const char *db, const char *table_name,
 
2851
                    HA_CREATE_INFO *create_info,
 
2852
                    bool update_create_info)
 
2853
{
 
2854
  int error= 1;
 
2855
  Table table;
 
2856
  char name_buff[FN_REFLEN];
 
2857
  const char *name;
 
2858
  TABLE_SHARE share;
 
2859
 
 
2860
  init_tmp_table_share(session, &share, db, 0, table_name, path);
 
2861
  if (open_table_def(session, &share, 0) ||
 
2862
      open_table_from_share(session, &share, "", 0, (uint) READ_ALL, 0, &table,
 
2863
                            OTM_CREATE))
 
2864
    goto err;
 
2865
 
 
2866
  if (update_create_info)
 
2867
    table.updateCreateInfo(create_info);
 
2868
 
 
2869
  name= check_lowercase_names(table.file, share.path.str, name_buff);
 
2870
 
 
2871
  error= table.file->ha_create(name, &table, create_info);
 
2872
  closefrm(&table, 0);
 
2873
  if (error)
 
2874
  {
 
2875
    sprintf(name_buff,"%s.%s",db,table_name);
 
2876
    my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), name_buff, error);
 
2877
  }
 
2878
err:
 
2879
  free_table_share(&share);
 
2880
  return(error != 0);
 
2881
}
 
2882
 
 
2883
void st_ha_check_opt::init()
 
2884
{
 
2885
  flags= sql_flags= 0;
 
2886
  sort_buffer_size = current_session->variables.myisam_sort_buff_size;
 
2887
}
 
2888
 
 
2889
 
 
2890
/*****************************************************************************
 
2891
  Key cache handling.
 
2892
 
 
2893
  This code is only relevant for ISAM/MyISAM tables
 
2894
 
 
2895
  key_cache->cache may be 0 only in the case where a key cache is not
 
2896
  initialized or when we where not able to init the key cache in a previous
 
2897
  call to ha_init_key_cache() (probably out of memory)
 
2898
*****************************************************************************/
 
2899
 
 
2900
/**
 
2901
  Init a key cache if it has not been initied before.
 
2902
*/
 
2903
int ha_init_key_cache(const char *name __attribute__((unused)),
 
2904
                      KEY_CACHE *key_cache)
 
2905
{
 
2906
  if (!key_cache->key_cache_inited)
 
2907
  {
 
2908
    pthread_mutex_lock(&LOCK_global_system_variables);
 
2909
    uint32_t tmp_buff_size= (uint32_t) key_cache->param_buff_size;
 
2910
    uint32_t tmp_block_size= (uint) key_cache->param_block_size;
 
2911
    uint32_t division_limit= key_cache->param_division_limit;
 
2912
    uint32_t age_threshold=  key_cache->param_age_threshold;
 
2913
    pthread_mutex_unlock(&LOCK_global_system_variables);
 
2914
    return(!init_key_cache(key_cache,
 
2915
                                tmp_block_size,
 
2916
                                tmp_buff_size,
 
2917
                                division_limit, age_threshold));
 
2918
  }
 
2919
  return(0);
 
2920
}
 
2921
 
 
2922
 
 
2923
/**
 
2924
  Resize key cache.
 
2925
*/
 
2926
int ha_resize_key_cache(KEY_CACHE *key_cache)
 
2927
{
 
2928
  if (key_cache->key_cache_inited)
 
2929
  {
 
2930
    pthread_mutex_lock(&LOCK_global_system_variables);
 
2931
    long tmp_buff_size= (long) key_cache->param_buff_size;
 
2932
    long tmp_block_size= (long) key_cache->param_block_size;
 
2933
    uint32_t division_limit= key_cache->param_division_limit;
 
2934
    uint32_t age_threshold=  key_cache->param_age_threshold;
 
2935
    pthread_mutex_unlock(&LOCK_global_system_variables);
 
2936
    return(!resize_key_cache(key_cache, tmp_block_size,
 
2937
                                  tmp_buff_size,
 
2938
                                  division_limit, age_threshold));
 
2939
  }
 
2940
  return(0);
 
2941
}
 
2942
 
 
2943
 
 
2944
/**
 
2945
  Change parameters for key cache (like size)
 
2946
*/
 
2947
int ha_change_key_cache_param(KEY_CACHE *key_cache)
 
2948
{
 
2949
  if (key_cache->key_cache_inited)
 
2950
  {
 
2951
    pthread_mutex_lock(&LOCK_global_system_variables);
 
2952
    uint32_t division_limit= key_cache->param_division_limit;
 
2953
    uint32_t age_threshold=  key_cache->param_age_threshold;
 
2954
    pthread_mutex_unlock(&LOCK_global_system_variables);
 
2955
    change_key_cache_param(key_cache, division_limit, age_threshold);
 
2956
  }
 
2957
  return 0;
 
2958
}
 
2959
 
 
2960
/**
 
2961
  Free memory allocated by a key cache.
 
2962
*/
 
2963
int ha_end_key_cache(KEY_CACHE *key_cache)
 
2964
{
 
2965
  end_key_cache(key_cache, 1);          // Can never fail
 
2966
  return 0;
 
2967
}
 
2968
 
 
2969
/**
 
2970
  Move all tables from one key cache to another one.
 
2971
*/
 
2972
int ha_change_key_cache(KEY_CACHE *old_key_cache,
 
2973
                        KEY_CACHE *new_key_cache)
 
2974
{
 
2975
  mi_change_key_cache(old_key_cache, new_key_cache);
 
2976
  return 0;
 
2977
}
 
2978
 
 
2979
/**
 
2980
  Call this function in order to give the handler the possiblity
 
2981
  to ask engine if there are any new tables that should be written to disk
 
2982
  or any dropped tables that need to be removed from disk
 
2983
*/
 
2984
struct st_find_files_args
 
2985
{
 
2986
  const char *db;
 
2987
  const char *path;
 
2988
  const char *wild;
 
2989
  bool dir;
 
2990
  List<LEX_STRING> *files;
 
2991
};
 
2992
 
 
2993
/**
 
2994
  Ask handler if the table exists in engine.
 
2995
  @retval
 
2996
    HA_ERR_NO_SUCH_TABLE     Table does not exist
 
2997
  @retval
 
2998
    HA_ERR_TABLE_EXIST       Table exists
 
2999
  @retval
 
3000
    \#                  Error code
 
3001
*/
 
3002
struct st_table_exists_in_engine_args
 
3003
{
 
3004
  const char *db;
 
3005
  const char *name;
 
3006
  int err;
 
3007
  handlerton* hton;
 
3008
};
 
3009
 
 
3010
static bool table_exists_in_engine_handlerton(Session *session, plugin_ref plugin,
 
3011
                                              void *arg)
 
3012
{
 
3013
  st_table_exists_in_engine_args *vargs= (st_table_exists_in_engine_args *)arg;
 
3014
  handlerton *hton= plugin_data(plugin, handlerton *);
 
3015
 
 
3016
  int err= HA_ERR_NO_SUCH_TABLE;
 
3017
 
 
3018
  if (hton->state == SHOW_OPTION_YES && hton->table_exists_in_engine)
 
3019
    err = hton->table_exists_in_engine(hton, session, vargs->db, vargs->name);
 
3020
 
 
3021
  vargs->err = err;
 
3022
  if (vargs->err == HA_ERR_TABLE_EXIST)
 
3023
  {
 
3024
    vargs->hton= hton;
 
3025
    return true;
 
3026
  }
 
3027
 
 
3028
  return false;
 
3029
}
 
3030
 
 
3031
int ha_table_exists_in_engine(Session* session,
 
3032
                              const char* db, const char* name,
 
3033
                              handlerton **hton)
 
3034
{
 
3035
  st_table_exists_in_engine_args args= {db, name, HA_ERR_NO_SUCH_TABLE, NULL};
 
3036
  plugin_foreach(session, table_exists_in_engine_handlerton,
 
3037
                 DRIZZLE_STORAGE_ENGINE_PLUGIN, &args);
 
3038
 
 
3039
  if(args.err==HA_ERR_NO_SUCH_TABLE)
 
3040
  {
 
3041
    /* Default way of knowing if a table exists. (checking .frm exists) */
 
3042
 
 
3043
    char path[FN_REFLEN];
 
3044
    build_table_filename(path, sizeof(path),
 
3045
                         db, name, ".frm", 0);
 
3046
    if (!access(path, F_OK))
 
3047
      args.err= HA_ERR_TABLE_EXIST;
 
3048
    else
 
3049
      args.err= HA_ERR_NO_SUCH_TABLE;
 
3050
 
 
3051
    enum legacy_db_type table_type;
 
3052
    if(args.err==HA_ERR_TABLE_EXIST && mysql_frm_type(path, &table_type)==0)
 
3053
    {
 
3054
      args.hton= ha_resolve_by_legacy_type(session, table_type);
 
3055
    }
 
3056
  }
 
3057
 
 
3058
  if(hton)
 
3059
    *hton= args.hton;
 
3060
 
 
3061
  return(args.err);
 
3062
}
 
3063
 
 
3064
/**
896
3065
  Calculate cost of 'index only' scan for given index and number of records
897
3066
 
898
3067
  @param keynr    Index number
901
3070
  @note
902
3071
    It is assumed that we will read trough the whole key range and that all
903
3072
    key blocks are half full (normally things are much better). It is also
904
 
    assumed that each time we read the next key from the index, the Cursor
 
3073
    assumed that each time we read the next key from the index, the handler
905
3074
    performs a random seek, thus the cost is proportional to the number of
906
3075
    blocks read.
907
3076
 
908
3077
  @todo
909
 
    Consider joining this function and Cursor::read_time() into one
910
 
    Cursor::read_time(keynr, records, ranges, bool index_only) function.
 
3078
    Consider joining this function and handler::read_time() into one
 
3079
    handler::read_time(keynr, records, ranges, bool index_only) function.
911
3080
 
912
3081
  @return
913
3082
    Estimated cost of 'index only' scan
914
3083
*/
915
3084
 
916
 
double Cursor::index_only_read_time(uint32_t keynr, double key_records)
 
3085
double handler::index_only_read_time(uint32_t keynr, double records)
917
3086
{
 
3087
  double read_time;
918
3088
  uint32_t keys_per_block= (stats.block_size/2/
919
3089
                        (table->key_info[keynr].key_length + ref_length) + 1);
920
 
  return ((double) (key_records + keys_per_block-1) /
921
 
          (double) keys_per_block);
 
3090
  read_time=((double) (records + keys_per_block-1) /
 
3091
             (double) keys_per_block);
 
3092
  return read_time;
922
3093
}
923
3094
 
924
3095
 
958
3129
*/
959
3130
 
960
3131
ha_rows
961
 
Cursor::multi_range_read_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
 
3132
handler::multi_range_read_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
962
3133
                                     void *seq_init_param,
963
 
                                     uint32_t ,
 
3134
                                     uint32_t n_ranges_arg __attribute__((unused)),
964
3135
                                     uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
965
3136
{
966
3137
  KEY_MULTI_RANGE range;
1006
3177
    cost->zero();
1007
3178
    cost->avg_io_cost= 1; /* assume random seeks */
1008
3179
    if ((*flags & HA_MRR_INDEX_ONLY) && total_rows > 2)
1009
 
      cost->io_count= index_only_read_time(keyno, (uint32_t)total_rows);
 
3180
      cost->io_count= index_only_read_time(keyno, (uint)total_rows);
1010
3181
    else
1011
3182
      cost->io_count= read_time(keyno, n_ranges, total_rows);
1012
3183
    cost->cpu_cost= (double) total_rows / TIME_FOR_COMPARE + 0.01;
1049
3220
    other Error or can't perform the requested scan
1050
3221
*/
1051
3222
 
1052
 
int Cursor::multi_range_read_info(uint32_t keyno, uint32_t n_ranges, uint32_t n_rows,
 
3223
int handler::multi_range_read_info(uint32_t keyno, uint32_t n_ranges, uint32_t n_rows,
1053
3224
                                   uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
1054
3225
{
1055
3226
  *bufsz= 0; /* Default implementation doesn't need a buffer */
1094
3265
    also hold:
1095
3266
    The caller will guarantee that if "seq->init == mrr_ranges_array_init"
1096
3267
    then seq_init_param is an array of n_ranges KEY_MULTI_RANGE structures.
1097
 
    This property will only be used by NDB Cursor until WL#2623 is done.
 
3268
    This property will only be used by NDB handler until WL#2623 is done.
1098
3269
 
1099
3270
    Buffer memory management is done according to the following scenario:
1100
3271
    The caller allocates the buffer and provides it to the callee by filling
1110
3281
*/
1111
3282
 
1112
3283
int
1113
 
Cursor::multi_range_read_init(RANGE_SEQ_IF *seq_funcs, void *seq_init_param,
 
3284
handler::multi_range_read_init(RANGE_SEQ_IF *seq_funcs, void *seq_init_param,
1114
3285
                               uint32_t n_ranges, uint32_t mode,
1115
 
                               HANDLER_BUFFER *)
 
3286
                               HANDLER_BUFFER *buf __attribute__((unused)))
1116
3287
{
1117
3288
  mrr_iter= seq_funcs->init(seq_init_param, n_ranges, mode);
1118
3289
  mrr_funcs= *seq_funcs;
1119
3290
  mrr_is_output_sorted= test(mode & HA_MRR_SORTED);
1120
3291
  mrr_have_range= false;
1121
 
  return 0;
 
3292
  return(0);
1122
3293
}
1123
3294
 
1124
3295
 
1135
3306
  @retval other  Error code
1136
3307
*/
1137
3308
 
1138
 
int Cursor::multi_range_read_next(char **range_info)
 
3309
int handler::multi_range_read_next(char **range_info)
1139
3310
{
1140
3311
  int result= 0;
1141
3312
  int range_res= 0;
1185
3356
  while ((result == HA_ERR_END_OF_FILE) && !range_res);
1186
3357
 
1187
3358
  *range_info= mrr_cur_range.ptr;
1188
 
  return result;
 
3359
  return(result);
 
3360
}
 
3361
 
 
3362
 
 
3363
/* **************************************************************************
 
3364
 * DS-MRR implementation
 
3365
 ***************************************************************************/
 
3366
 
 
3367
/**
 
3368
  DS-MRR: Initialize and start MRR scan
 
3369
 
 
3370
  Initialize and start the MRR scan. Depending on the mode parameter, this
 
3371
  may use default or DS-MRR implementation.
 
3372
 
 
3373
  @param h               Table handler to be used
 
3374
  @param key             Index to be used
 
3375
  @param seq_funcs       Interval sequence enumeration functions
 
3376
  @param seq_init_param  Interval sequence enumeration parameter
 
3377
  @param n_ranges        Number of ranges in the sequence.
 
3378
  @param mode            HA_MRR_* modes to use
 
3379
  @param buf             INOUT Buffer to use
 
3380
 
 
3381
  @retval 0     Ok, Scan started.
 
3382
  @retval other Error
 
3383
*/
 
3384
 
 
3385
int DsMrr_impl::dsmrr_init(handler *h, KEY *key,
 
3386
                           RANGE_SEQ_IF *seq_funcs, void *seq_init_param,
 
3387
                           uint32_t n_ranges, uint32_t mode, HANDLER_BUFFER *buf)
 
3388
{
 
3389
  uint32_t elem_size;
 
3390
  uint32_t keyno;
 
3391
  Item *pushed_cond= NULL;
 
3392
  handler *new_h2;
 
3393
  keyno= h->active_index;
 
3394
  assert(h2 == NULL);
 
3395
  if (mode & HA_MRR_USE_DEFAULT_IMPL || mode & HA_MRR_SORTED)
 
3396
  {
 
3397
    use_default_impl= true;
 
3398
    return(h->handler::multi_range_read_init(seq_funcs, seq_init_param,
 
3399
                                                  n_ranges, mode, buf));
 
3400
  }
 
3401
  rowids_buf= buf->buffer;
 
3402
  //psergey-todo: don't add key_length as it is not needed anymore
 
3403
  rowids_buf += key->key_length + h->ref_length;
 
3404
 
 
3405
  is_mrr_assoc= !test(mode & HA_MRR_NO_ASSOCIATION);
 
3406
  rowids_buf_end= buf->buffer_end;
 
3407
 
 
3408
  elem_size= h->ref_length + (int)is_mrr_assoc * sizeof(void*);
 
3409
  rowids_buf_last= rowids_buf +
 
3410
                      ((rowids_buf_end - rowids_buf)/ elem_size)*
 
3411
                      elem_size;
 
3412
  rowids_buf_end= rowids_buf_last;
 
3413
 
 
3414
  /* Create a separate handler object to do rndpos() calls. */
 
3415
  Session *session= current_session;
 
3416
  if (!(new_h2= h->clone(session->mem_root)) ||
 
3417
      new_h2->ha_external_lock(session, F_RDLCK))
 
3418
  {
 
3419
    delete new_h2;
 
3420
    return(1);
 
3421
  }
 
3422
 
 
3423
  if (keyno == h->pushed_idx_cond_keyno)
 
3424
    pushed_cond= h->pushed_idx_cond;
 
3425
  if (h->ha_index_end())
 
3426
  {
 
3427
    new_h2= h2;
 
3428
    goto error;
 
3429
  }
 
3430
 
 
3431
  h2= new_h2;
 
3432
  table->prepare_for_position();
 
3433
  new_h2->extra(HA_EXTRA_KEYREAD);
 
3434
 
 
3435
  if (h2->ha_index_init(keyno, false) ||
 
3436
      h2->handler::multi_range_read_init(seq_funcs, seq_init_param, n_ranges,
 
3437
                                         mode, buf))
 
3438
    goto error;
 
3439
  use_default_impl= false;
 
3440
 
 
3441
  if (pushed_cond)
 
3442
    h2->idx_cond_push(keyno, pushed_cond);
 
3443
  if (dsmrr_fill_buffer(new_h2))
 
3444
    goto error;
 
3445
 
 
3446
  /*
 
3447
    If the above call has scanned through all intervals in *seq, then
 
3448
    adjust *buf to indicate that the remaining buffer space will not be used.
 
3449
  */
 
3450
  if (dsmrr_eof)
 
3451
    buf->end_of_used_area= rowids_buf_last;
 
3452
 
 
3453
  if (h->ha_rnd_init(false))
 
3454
    goto error;
 
3455
 
 
3456
  return(0);
 
3457
error:
 
3458
  h2->ha_index_or_rnd_end();
 
3459
  h2->ha_external_lock(session, F_UNLCK);
 
3460
  h2->close();
 
3461
  delete h2;
 
3462
  return(1);
 
3463
}
 
3464
 
 
3465
 
 
3466
void DsMrr_impl::dsmrr_close()
 
3467
{
 
3468
  if (h2)
 
3469
  {
 
3470
    h2->ha_external_lock(current_session, F_UNLCK);
 
3471
    h2->close();
 
3472
    delete h2;
 
3473
    h2= NULL;
 
3474
  }
 
3475
  use_default_impl= true;
 
3476
  return;
 
3477
}
 
3478
 
 
3479
 
 
3480
static int rowid_cmp(void *h, unsigned char *a, unsigned char *b)
 
3481
{
 
3482
  return ((handler*)h)->cmp_ref(a, b);
 
3483
}
 
3484
 
 
3485
 
 
3486
/**
 
3487
  DS-MRR: Fill the buffer with rowids and sort it by rowid
 
3488
 
 
3489
  {This is an internal function of DiskSweep MRR implementation}
 
3490
  Scan the MRR ranges and collect ROWIDs (or {ROWID, range_id} pairs) into
 
3491
  buffer. When the buffer is full or scan is completed, sort the buffer by
 
3492
  rowid and return.
 
3493
 
 
3494
  The function assumes that rowids buffer is empty when it is invoked.
 
3495
 
 
3496
  @param h  Table handler
 
3497
 
 
3498
  @retval 0      OK, the next portion of rowids is in the buffer,
 
3499
                 properly ordered
 
3500
  @retval other  Error
 
3501
*/
 
3502
 
 
3503
int DsMrr_impl::dsmrr_fill_buffer(handler *unused __attribute__((unused)))
 
3504
{
 
3505
  char *range_info;
 
3506
  int res = 0;
 
3507
 
 
3508
  rowids_buf_cur= rowids_buf;
 
3509
  while ((rowids_buf_cur < rowids_buf_end) &&
 
3510
         !(res= h2->handler::multi_range_read_next(&range_info)))
 
3511
  {
 
3512
    /* Put rowid, or {rowid, range_id} pair into the buffer */
 
3513
    h2->position(table->record[0]);
 
3514
    memcpy(rowids_buf_cur, h2->ref, h2->ref_length);
 
3515
    rowids_buf_cur += h->ref_length;
 
3516
 
 
3517
    if (is_mrr_assoc)
 
3518
    {
 
3519
      memcpy(rowids_buf_cur, &range_info, sizeof(void*));
 
3520
      rowids_buf_cur += sizeof(void*);
 
3521
    }
 
3522
  }
 
3523
 
 
3524
  if (res && res != HA_ERR_END_OF_FILE)
 
3525
    return(res);
 
3526
  dsmrr_eof= test(res == HA_ERR_END_OF_FILE);
 
3527
 
 
3528
  /* Sort the buffer contents by rowid */
 
3529
  uint32_t elem_size= h->ref_length + (int)is_mrr_assoc * sizeof(void*);
 
3530
  uint32_t n_rowids= (rowids_buf_cur - rowids_buf) / elem_size;
 
3531
 
 
3532
  my_qsort2(rowids_buf, n_rowids, elem_size, (qsort2_cmp)rowid_cmp,
 
3533
            (void*)h);
 
3534
  rowids_buf_last= rowids_buf_cur;
 
3535
  rowids_buf_cur=  rowids_buf;
 
3536
  return(0);
 
3537
}
 
3538
 
 
3539
 
 
3540
/**
 
3541
  DS-MRR implementation: multi_range_read_next() function
 
3542
*/
 
3543
 
 
3544
int DsMrr_impl::dsmrr_next(handler *h, char **range_info)
 
3545
{
 
3546
  int res;
 
3547
 
 
3548
  if (use_default_impl)
 
3549
    return h->handler::multi_range_read_next(range_info);
 
3550
 
 
3551
  if (rowids_buf_cur == rowids_buf_last)
 
3552
  {
 
3553
    if (dsmrr_eof)
 
3554
    {
 
3555
      res= HA_ERR_END_OF_FILE;
 
3556
      goto end;
 
3557
    }
 
3558
    res= dsmrr_fill_buffer(h);
 
3559
    if (res)
 
3560
      goto end;
 
3561
  }
 
3562
 
 
3563
  /* Return EOF if there are no rowids in the buffer after re-fill attempt */
 
3564
  if (rowids_buf_cur == rowids_buf_last)
 
3565
  {
 
3566
    res= HA_ERR_END_OF_FILE;
 
3567
    goto end;
 
3568
  }
 
3569
 
 
3570
  res= h->rnd_pos(table->record[0], rowids_buf_cur);
 
3571
  rowids_buf_cur += h->ref_length;
 
3572
  if (is_mrr_assoc)
 
3573
  {
 
3574
    memcpy(range_info, rowids_buf_cur, sizeof(void*));
 
3575
    rowids_buf_cur += sizeof(void*);
 
3576
  }
 
3577
 
 
3578
end:
 
3579
  if (res)
 
3580
    dsmrr_close();
 
3581
  return res;
 
3582
}
 
3583
 
 
3584
 
 
3585
/**
 
3586
  DS-MRR implementation: multi_range_read_info() function
 
3587
*/
 
3588
int DsMrr_impl::dsmrr_info(uint32_t keyno, uint32_t n_ranges, uint32_t rows, uint32_t *bufsz,
 
3589
                           uint32_t *flags, COST_VECT *cost)
 
3590
{
 
3591
  int res;
 
3592
  uint32_t def_flags= *flags;
 
3593
  uint32_t def_bufsz= *bufsz;
 
3594
 
 
3595
  /* Get cost/flags/mem_usage of default MRR implementation */
 
3596
  res= h->handler::multi_range_read_info(keyno, n_ranges, rows, &def_bufsz,
 
3597
                                         &def_flags, cost);
 
3598
  assert(!res);
 
3599
 
 
3600
  if ((*flags & HA_MRR_USE_DEFAULT_IMPL) ||
 
3601
      choose_mrr_impl(keyno, rows, &def_flags, &def_bufsz, cost))
 
3602
  {
 
3603
    /* Default implementation is choosen */
 
3604
    *flags= def_flags;
 
3605
    *bufsz= def_bufsz;
 
3606
  }
 
3607
  return 0;
 
3608
}
 
3609
 
 
3610
 
 
3611
/**
 
3612
  DS-MRR Implementation: multi_range_read_info_const() function
 
3613
*/
 
3614
 
 
3615
ha_rows DsMrr_impl::dsmrr_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
 
3616
                                 void *seq_init_param, uint32_t n_ranges,
 
3617
                                 uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
 
3618
{
 
3619
  ha_rows rows;
 
3620
  uint32_t def_flags= *flags;
 
3621
  uint32_t def_bufsz= *bufsz;
 
3622
  /* Get cost/flags/mem_usage of default MRR implementation */
 
3623
  rows= h->handler::multi_range_read_info_const(keyno, seq, seq_init_param,
 
3624
                                                n_ranges, &def_bufsz,
 
3625
                                                &def_flags, cost);
 
3626
  if (rows == HA_POS_ERROR)
 
3627
  {
 
3628
    /* Default implementation can't perform MRR scan => we can't either */
 
3629
    return rows;
 
3630
  }
 
3631
 
 
3632
  /*
 
3633
    If HA_MRR_USE_DEFAULT_IMPL has been passed to us, that is an order to
 
3634
    use the default MRR implementation (we need it for UPDATE/DELETE).
 
3635
    Otherwise, make a choice based on cost and @@optimizer_use_mrr.
 
3636
  */
 
3637
  if ((*flags & HA_MRR_USE_DEFAULT_IMPL) ||
 
3638
      choose_mrr_impl(keyno, rows, flags, bufsz, cost))
 
3639
  {
 
3640
    *flags= def_flags;
 
3641
    *bufsz= def_bufsz;
 
3642
  }
 
3643
  else
 
3644
  {
 
3645
    *flags &= ~HA_MRR_USE_DEFAULT_IMPL;
 
3646
  }
 
3647
  return rows;
 
3648
}
 
3649
 
 
3650
 
 
3651
/**
 
3652
  Check if key has partially-covered columns
 
3653
 
 
3654
  We can't use DS-MRR to perform range scans when the ranges are over
 
3655
  partially-covered keys, because we'll not have full key part values
 
3656
  (we'll have their prefixes from the index) and will not be able to check
 
3657
  if we've reached the end the range.
 
3658
 
 
3659
  @param keyno  Key to check
 
3660
 
 
3661
  @todo
 
3662
    Allow use of DS-MRR in cases where the index has partially-covered
 
3663
    components but they are not used for scanning.
 
3664
 
 
3665
  @retval true   Yes
 
3666
  @retval false  No
 
3667
*/
 
3668
 
 
3669
bool DsMrr_impl::key_uses_partial_cols(uint32_t keyno)
 
3670
{
 
3671
  KEY_PART_INFO *kp= table->key_info[keyno].key_part;
 
3672
  KEY_PART_INFO *kp_end= kp + table->key_info[keyno].key_parts;
 
3673
  for (; kp != kp_end; kp++)
 
3674
  {
 
3675
    if (!kp->field->part_of_key.is_set(keyno))
 
3676
      return true;
 
3677
  }
 
3678
  return false;
 
3679
}
 
3680
 
 
3681
 
 
3682
/**
 
3683
  DS-MRR Internals: Choose between Default MRR implementation and DS-MRR
 
3684
 
 
3685
  Make the choice between using Default MRR implementation and DS-MRR.
 
3686
  This function contains common functionality factored out of dsmrr_info()
 
3687
  and dsmrr_info_const(). The function assumes that the default MRR
 
3688
  implementation's applicability requirements are satisfied.
 
3689
 
 
3690
  @param keyno       Index number
 
3691
  @param rows        E(full rows to be retrieved)
 
3692
  @param flags  IN   MRR flags provided by the MRR user
 
3693
                OUT  If DS-MRR is choosen, flags of DS-MRR implementation
 
3694
                     else the value is not modified
 
3695
  @param bufsz  IN   If DS-MRR is choosen, buffer use of DS-MRR implementation
 
3696
                     else the value is not modified
 
3697
  @param cost   IN   Cost of default MRR implementation
 
3698
                OUT  If DS-MRR is choosen, cost of DS-MRR scan
 
3699
                     else the value is not modified
 
3700
 
 
3701
  @retval true   Default MRR implementation should be used
 
3702
  @retval false  DS-MRR implementation should be used
 
3703
*/
 
3704
 
 
3705
bool DsMrr_impl::choose_mrr_impl(uint32_t keyno, ha_rows rows, uint32_t *flags,
 
3706
                                 uint32_t *bufsz, COST_VECT *cost)
 
3707
{
 
3708
  COST_VECT dsmrr_cost;
 
3709
  bool res;
 
3710
  Session *session= current_session;
 
3711
  if ((session->variables.optimizer_use_mrr == 2) ||
 
3712
      (*flags & HA_MRR_INDEX_ONLY) || (*flags & HA_MRR_SORTED) ||
 
3713
      (keyno == table->s->primary_key &&
 
3714
       h->primary_key_is_clustered()) ||
 
3715
       key_uses_partial_cols(keyno))
 
3716
  {
 
3717
    /* Use the default implementation */
 
3718
    *flags |= HA_MRR_USE_DEFAULT_IMPL;
 
3719
    return true;
 
3720
  }
 
3721
 
 
3722
  uint32_t add_len= table->key_info[keyno].key_length + h->ref_length;
 
3723
  *bufsz -= add_len;
 
3724
  if (get_disk_sweep_mrr_cost(keyno, rows, *flags, bufsz, &dsmrr_cost))
 
3725
    return true;
 
3726
  *bufsz += add_len;
 
3727
 
 
3728
  bool force_dsmrr;
 
3729
  /*
 
3730
    If @@optimizer_use_mrr==force, then set cost of DS-MRR to be minimum of
 
3731
    DS-MRR and Default implementations cost. This allows one to force use of
 
3732
    DS-MRR whenever it is applicable without affecting other cost-based
 
3733
    choices.
 
3734
  */
 
3735
  if ((force_dsmrr= (session->variables.optimizer_use_mrr == 1)) &&
 
3736
      dsmrr_cost.total_cost() > cost->total_cost())
 
3737
    dsmrr_cost= *cost;
 
3738
 
 
3739
  if (force_dsmrr || dsmrr_cost.total_cost() <= cost->total_cost())
 
3740
  {
 
3741
    *flags &= ~HA_MRR_USE_DEFAULT_IMPL;  /* Use the DS-MRR implementation */
 
3742
    *flags &= ~HA_MRR_SORTED;          /* We will return unordered output */
 
3743
    *cost= dsmrr_cost;
 
3744
    res= false;
 
3745
  }
 
3746
  else
 
3747
  {
 
3748
    /* Use the default MRR implementation */
 
3749
    res= true;
 
3750
  }
 
3751
  return res;
 
3752
}
 
3753
 
 
3754
 
 
3755
static void get_sort_and_sweep_cost(Table *table, ha_rows nrows, COST_VECT *cost);
 
3756
 
 
3757
 
 
3758
/**
 
3759
  Get cost of DS-MRR scan
 
3760
 
 
3761
  @param keynr              Index to be used
 
3762
  @param rows               E(Number of rows to be scanned)
 
3763
  @param flags              Scan parameters (HA_MRR_* flags)
 
3764
  @param buffer_size INOUT  Buffer size
 
3765
  @param cost        OUT    The cost
 
3766
 
 
3767
  @retval false  OK
 
3768
  @retval true   Error, DS-MRR cannot be used (the buffer is too small
 
3769
                 for even 1 rowid)
 
3770
*/
 
3771
 
 
3772
bool DsMrr_impl::get_disk_sweep_mrr_cost(uint32_t keynr, ha_rows rows, uint32_t flags,
 
3773
                                         uint32_t *buffer_size, COST_VECT *cost)
 
3774
{
 
3775
  uint32_t max_buff_entries, elem_size;
 
3776
  ha_rows rows_in_full_step, rows_in_last_step;
 
3777
  uint32_t n_full_steps;
 
3778
  double index_read_cost;
 
3779
 
 
3780
  elem_size= h->ref_length + sizeof(void*) * (!test(flags & HA_MRR_NO_ASSOCIATION));
 
3781
  max_buff_entries = *buffer_size / elem_size;
 
3782
 
 
3783
  if (!max_buff_entries)
 
3784
    return true; /* Buffer has not enough space for even 1 rowid */
 
3785
 
 
3786
  /* Number of iterations we'll make with full buffer */
 
3787
  n_full_steps= (uint)floor(rows2double(rows) / max_buff_entries);
 
3788
 
 
3789
  /*
 
3790
    Get numbers of rows we'll be processing in
 
3791
     - non-last sweep, with full buffer
 
3792
     - last iteration, with non-full buffer
 
3793
  */
 
3794
  rows_in_full_step= max_buff_entries;
 
3795
  rows_in_last_step= rows % max_buff_entries;
 
3796
 
 
3797
  /* Adjust buffer size if we expect to use only part of the buffer */
 
3798
  if (n_full_steps)
 
3799
  {
 
3800
    get_sort_and_sweep_cost(table, rows, cost);
 
3801
    cost->multiply(n_full_steps);
 
3802
  }
 
3803
  else
 
3804
  {
 
3805
    cost->zero();
 
3806
    *buffer_size= cmax((ulong)*buffer_size,
 
3807
                      (size_t)(1.2*rows_in_last_step) * elem_size +
 
3808
                      h->ref_length + table->key_info[keynr].key_length);
 
3809
  }
 
3810
 
 
3811
  COST_VECT last_step_cost;
 
3812
  get_sort_and_sweep_cost(table, rows_in_last_step, &last_step_cost);
 
3813
  cost->add(&last_step_cost);
 
3814
 
 
3815
  if (n_full_steps != 0)
 
3816
    cost->mem_cost= *buffer_size;
 
3817
  else
 
3818
    cost->mem_cost= (double)rows_in_last_step * elem_size;
 
3819
 
 
3820
  /* Total cost of all index accesses */
 
3821
  index_read_cost= h->index_only_read_time(keynr, (double)rows);
 
3822
  cost->add_io(index_read_cost, 1 /* Random seeks */);
 
3823
  return false;
 
3824
}
 
3825
 
 
3826
 
 
3827
/*
 
3828
  Get cost of one sort-and-sweep step
 
3829
 
 
3830
  SYNOPSIS
 
3831
    get_sort_and_sweep_cost()
 
3832
      table       Table being accessed
 
3833
      nrows       Number of rows to be sorted and retrieved
 
3834
      cost   OUT  The cost
 
3835
 
 
3836
  DESCRIPTION
 
3837
    Get cost of these operations:
 
3838
     - sort an array of #nrows ROWIDs using qsort
 
3839
     - read #nrows records from table in a sweep.
 
3840
*/
 
3841
 
 
3842
static
 
3843
void get_sort_and_sweep_cost(Table *table, ha_rows nrows, COST_VECT *cost)
 
3844
{
 
3845
  if (nrows)
 
3846
  {
 
3847
    get_sweep_read_cost(table, nrows, false, cost);
 
3848
    /* Add cost of qsort call: n * log2(n) * cost(rowid_comparison) */
 
3849
    double cmp_op= rows2double(nrows) * (1.0 / TIME_FOR_COMPARE_ROWID);
 
3850
    if (cmp_op < 3)
 
3851
      cmp_op= 3;
 
3852
    cost->cpu_cost += cmp_op * log2(cmp_op);
 
3853
  }
 
3854
  else
 
3855
    cost->zero();
 
3856
}
 
3857
 
 
3858
 
 
3859
/**
 
3860
  Get cost of reading nrows table records in a "disk sweep"
 
3861
 
 
3862
  A disk sweep read is a sequence of handler->rnd_pos(rowid) calls that made
 
3863
  for an ordered sequence of rowids.
 
3864
 
 
3865
  We assume hard disk IO. The read is performed as follows:
 
3866
 
 
3867
   1. The disk head is moved to the needed cylinder
 
3868
   2. The controller waits for the plate to rotate
 
3869
   3. The data is transferred
 
3870
 
 
3871
  Time to do #3 is insignificant compared to #2+#1.
 
3872
 
 
3873
  Time to move the disk head is proportional to head travel distance.
 
3874
 
 
3875
  Time to wait for the plate to rotate depends on whether the disk head
 
3876
  was moved or not.
 
3877
 
 
3878
  If disk head wasn't moved, the wait time is proportional to distance
 
3879
  between the previous block and the block we're reading.
 
3880
 
 
3881
  If the head was moved, we don't know how much we'll need to wait for the
 
3882
  plate to rotate. We assume the wait time to be a variate with a mean of
 
3883
  0.5 of full rotation time.
 
3884
 
 
3885
  Our cost units are "random disk seeks". The cost of random disk seek is
 
3886
  actually not a constant, it depends one range of cylinders we're going
 
3887
  to access. We make it constant by introducing a fuzzy concept of "typical
 
3888
  datafile length" (it's fuzzy as it's hard to tell whether it should
 
3889
  include index file, temp.tables etc). Then random seek cost is:
 
3890
 
 
3891
    1 = half_rotation_cost + move_cost * 1/3 * typical_data_file_length
 
3892
 
 
3893
  We define half_rotation_cost as DISK_SEEK_BASE_COST=0.9.
 
3894
 
 
3895
  @param table             Table to be accessed
 
3896
  @param nrows             Number of rows to retrieve
 
3897
  @param interrupted       true <=> Assume that the disk sweep will be
 
3898
                           interrupted by other disk IO. false - otherwise.
 
3899
  @param cost         OUT  The cost.
 
3900
*/
 
3901
 
 
3902
void get_sweep_read_cost(Table *table, ha_rows nrows, bool interrupted,
 
3903
                         COST_VECT *cost)
 
3904
{
 
3905
  cost->zero();
 
3906
  if (table->file->primary_key_is_clustered())
 
3907
  {
 
3908
    cost->io_count= table->file->read_time(table->s->primary_key,
 
3909
                                           (uint) nrows, nrows);
 
3910
  }
 
3911
  else
 
3912
  {
 
3913
    double n_blocks=
 
3914
      ceil(uint64_t2double(table->file->stats.data_file_length) / IO_SIZE);
 
3915
    double busy_blocks=
 
3916
      n_blocks * (1.0 - pow(1.0 - 1.0/n_blocks, rows2double(nrows)));
 
3917
    if (busy_blocks < 1.0)
 
3918
      busy_blocks= 1.0;
 
3919
 
 
3920
    cost->io_count= busy_blocks;
 
3921
 
 
3922
    if (!interrupted)
 
3923
    {
 
3924
      /* Assume reading is done in one 'sweep' */
 
3925
      cost->avg_io_cost= (DISK_SEEK_BASE_COST +
 
3926
                          DISK_SEEK_PROP_COST*n_blocks/busy_blocks);
 
3927
    }
 
3928
  }
 
3929
  return;
1189
3930
}
1190
3931
 
1191
3932
 
1211
3952
  @retval
1212
3953
    \#                  Error code
1213
3954
*/
1214
 
int Cursor::read_range_first(const key_range *start_key,
1215
 
                             const key_range *end_key,
1216
 
                             bool eq_range_arg,
1217
 
                             bool )
 
3955
int handler::read_range_first(const key_range *start_key,
 
3956
                              const key_range *end_key,
 
3957
                              bool eq_range_arg,
 
3958
                              bool sorted  __attribute__((unused)))
1218
3959
{
1219
3960
  int result;
1220
3961
 
1258
3999
  @retval
1259
4000
    \#                  Error code
1260
4001
*/
1261
 
int Cursor::read_range_next()
 
4002
int handler::read_range_next()
1262
4003
{
1263
4004
  int result;
1264
4005
 
1271
4012
  }
1272
4013
  result= index_next(table->record[0]);
1273
4014
  if (result)
1274
 
    return result;
 
4015
    return(result);
1275
4016
  return(compare_key(end_range) <= 0 ? 0 : HA_ERR_END_OF_FILE);
1276
4017
}
1277
4018
 
1291
4032
    - -1  : Key is less than range
1292
4033
    - 1   : Key is larger than range
1293
4034
*/
1294
 
int Cursor::compare_key(key_range *range)
 
4035
int handler::compare_key(key_range *range)
1295
4036
{
1296
4037
  int cmp;
1297
4038
  if (!range || in_range_check_pushed_down)
1308
4049
  This is used by index condition pushdown implementation.
1309
4050
*/
1310
4051
 
1311
 
int Cursor::compare_key2(key_range *range)
 
4052
int handler::compare_key2(key_range *range)
1312
4053
{
1313
4054
  int cmp;
1314
4055
  if (!range)
1319
4060
  return cmp;
1320
4061
}
1321
4062
 
1322
 
int Cursor::index_read_idx_map(unsigned char * buf, uint32_t index,
 
4063
int handler::index_read_idx_map(unsigned char * buf, uint32_t index,
1323
4064
                                const unsigned char * key,
1324
4065
                                key_part_map keypart_map,
1325
4066
                                enum ha_rkey_function find_flag)
1334
4075
  return error ?  error : error1;
1335
4076
}
1336
4077
 
 
4078
 
 
4079
/**
 
4080
  Returns a list of all known extensions.
 
4081
 
 
4082
    No mutexes, worst case race is a minor surplus memory allocation
 
4083
    We have to recreate the extension map if mysqld is restarted (for example
 
4084
    within libmysqld)
 
4085
 
 
4086
  @retval
 
4087
    pointer             pointer to TYPELIB structure
 
4088
*/
 
4089
static bool exts_handlerton(Session *unused __attribute__((unused)),
 
4090
                            plugin_ref plugin,
 
4091
                            void *arg)
 
4092
{
 
4093
  List<char> *found_exts= (List<char> *) arg;
 
4094
  handlerton *hton= plugin_data(plugin, handlerton *);
 
4095
  handler *file;
 
4096
  if (hton->state == SHOW_OPTION_YES && hton->create &&
 
4097
      (file= hton->create(hton, (TABLE_SHARE*) 0, current_session->mem_root)))
 
4098
  {
 
4099
    List_iterator_fast<char> it(*found_exts);
 
4100
    const char **ext, *old_ext;
 
4101
 
 
4102
    for (ext= file->bas_ext(); *ext; ext++)
 
4103
    {
 
4104
      while ((old_ext= it++))
 
4105
      {
 
4106
        if (!strcmp(old_ext, *ext))
 
4107
          break;
 
4108
      }
 
4109
      if (!old_ext)
 
4110
        found_exts->push_back((char *) *ext);
 
4111
 
 
4112
      it.rewind();
 
4113
    }
 
4114
    delete file;
 
4115
  }
 
4116
  return false;
 
4117
}
 
4118
 
 
4119
TYPELIB *ha_known_exts(void)
 
4120
{
 
4121
  if (!known_extensions.type_names || mysys_usage_id != known_extensions_id)
 
4122
  {
 
4123
    List<char> found_exts;
 
4124
    const char **ext, *old_ext;
 
4125
 
 
4126
    known_extensions_id= mysys_usage_id;
 
4127
 
 
4128
    plugin_foreach(NULL, exts_handlerton,
 
4129
                   DRIZZLE_STORAGE_ENGINE_PLUGIN, &found_exts);
 
4130
 
 
4131
    ext= (const char **) malloc(sizeof(char *)*
 
4132
                                (found_exts.elements+1));
 
4133
                              
 
4134
 
 
4135
    assert(ext != 0);
 
4136
    known_extensions.count= found_exts.elements;
 
4137
    known_extensions.type_names= ext;
 
4138
 
 
4139
    List_iterator_fast<char> it(found_exts);
 
4140
    while ((old_ext= it++))
 
4141
      *ext++= old_ext;
 
4142
    *ext= 0;
 
4143
  }
 
4144
  return &known_extensions;
 
4145
}
 
4146
 
 
4147
 
 
4148
static bool stat_print(Session *session, const char *type, uint32_t type_len,
 
4149
                       const char *file, uint32_t file_len,
 
4150
                       const char *status, uint32_t status_len)
 
4151
{
 
4152
  Protocol *protocol= session->protocol;
 
4153
  protocol->prepare_for_resend();
 
4154
  protocol->store(type, type_len, system_charset_info);
 
4155
  protocol->store(file, file_len, system_charset_info);
 
4156
  protocol->store(status, status_len, system_charset_info);
 
4157
  if (protocol->write())
 
4158
    return true;
 
4159
  return false;
 
4160
}
 
4161
 
 
4162
bool ha_show_status(Session *session, handlerton *db_type, enum ha_stat_type stat)
 
4163
{
 
4164
  List<Item> field_list;
 
4165
  Protocol *protocol= session->protocol;
 
4166
  bool result;
 
4167
 
 
4168
  field_list.push_back(new Item_empty_string("Type",10));
 
4169
  field_list.push_back(new Item_empty_string("Name",FN_REFLEN));
 
4170
  field_list.push_back(new Item_empty_string("Status",10));
 
4171
 
 
4172
  if (protocol->send_fields(&field_list,
 
4173
                            Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
 
4174
    return true;
 
4175
 
 
4176
  result= db_type->show_status &&
 
4177
    db_type->show_status(db_type, session, stat_print, stat) ? 1 : 0;
 
4178
 
 
4179
  if (!result)
 
4180
    my_eof(session);
 
4181
  return result;
 
4182
}
 
4183
 
 
4184
 
1337
4185
/**
1338
4186
  Check if the conditions for row-based binlogging is correct for the table.
1339
4187
 
1340
4188
  A row in the given table should be replicated if:
 
4189
  - Row-based replication is enabled in the current thread
 
4190
  - The binlog is enabled
1341
4191
  - It is not a temporary table
 
4192
  - The binary log is open
 
4193
  - The database the table resides in shall be binlogged (binlog_*_db rules)
 
4194
  - table is not mysql.event
1342
4195
*/
1343
4196
 
1344
 
static bool log_row_for_replication(Table* table,
1345
 
                                    const unsigned char *before_record,
1346
 
                                    const unsigned char *after_record)
 
4197
static bool binlog_log_row(Table* table,
 
4198
                           const unsigned char *before_record,
 
4199
                           const unsigned char *after_record)
1347
4200
{
1348
 
  ReplicationServices &replication_services= ReplicationServices::singleton();
 
4201
  bool error= false;
1349
4202
  Session *const session= table->in_use;
1350
4203
 
1351
 
  if (table->s->tmp_table || ! replication_services.isActive())
 
4204
  if (table->no_replicate == false)
1352
4205
    return false;
1353
4206
 
1354
 
  bool result= false;
 
4207
  error= replicator_session_init(session);
1355
4208
 
1356
4209
  switch (session->lex->sql_command)
1357
4210
  {
1358
 
  case SQLCOM_CREATE_TABLE:
1359
 
    /*
1360
 
     * We are in a CREATE TABLE ... SELECT statement
1361
 
     * and the kernel has already created the table
1362
 
     * and put a CreateTableStatement in the active
1363
 
     * Transaction message.  Here, we add a new InsertRecord
1364
 
     * to a new Transaction message (because the above
1365
 
     * CREATE TABLE will commit the transaction containing
1366
 
     * it).
1367
 
     */
1368
 
    result= replication_services.insertRecord(session, table);
1369
 
    break;
1370
4211
  case SQLCOM_REPLACE:
 
4212
  case SQLCOM_INSERT:
1371
4213
  case SQLCOM_REPLACE_SELECT:
1372
 
    /*
1373
 
     * This is a total hack because of the code that is
1374
 
     * in write_record() in sql_insert.cc. During
1375
 
     * a REPLACE statement, a call to ha_write_row() is
1376
 
     * called.  If it fails, then a call to ha_delete_row()
1377
 
     * is called, followed by a repeat of the original
1378
 
     * call to ha_write_row().  So, log_row_for_replication
1379
 
     * could be called either once or twice for a REPLACE
1380
 
     * statement.  The below looks at the values of before_record
1381
 
     * and after_record to determine which call to this
1382
 
     * function is for the delete or the insert, since NULL
1383
 
     * is passed for after_record for the delete and NULL is
1384
 
     * passed for before_record for the insert...
1385
 
     *
1386
 
     * In addition, there is an optimization that allows an
1387
 
     * engine to convert the above delete + insert into an
1388
 
     * update, so we must also check for this case below...
1389
 
     */
1390
 
    if (after_record == NULL)
1391
 
    {
1392
 
      replication_services.deleteRecord(session, table);
1393
 
      /* 
1394
 
       * We set the "current" statement message to NULL.  This triggers
1395
 
       * the replication services component to generate a new statement
1396
 
       * message for the inserted record which will come next.
1397
 
       */
1398
 
      replication_services.finalizeStatement(*session->getStatementMessage(), session);
1399
 
    }
1400
 
    else
1401
 
    {
1402
 
      if (before_record == NULL)
1403
 
        result= replication_services.insertRecord(session, table);
1404
 
      else
1405
 
        replication_services.updateRecord(session, table, before_record, after_record);
1406
 
    }
1407
 
    break;
1408
 
  case SQLCOM_INSERT:
1409
4214
  case SQLCOM_INSERT_SELECT:
1410
 
    /*
1411
 
     * The else block below represents an 
1412
 
     * INSERT ... ON DUPLICATE KEY UPDATE that
1413
 
     * has hit a key conflict and actually done
1414
 
     * an update.
1415
 
     */
1416
 
    if (before_record == NULL)
1417
 
      result= replication_services.insertRecord(session, table);
1418
 
    else
1419
 
      replication_services.updateRecord(session, table, before_record, after_record);
 
4215
  case SQLCOM_CREATE_TABLE:
 
4216
    error= replicator_write_row(session, table);
1420
4217
    break;
1421
4218
 
1422
4219
  case SQLCOM_UPDATE:
1423
 
    replication_services.updateRecord(session, table, before_record, after_record);
 
4220
  case SQLCOM_UPDATE_MULTI:
 
4221
    error= replicator_update_row(session, table, before_record, after_record);
1424
4222
    break;
1425
4223
 
1426
4224
  case SQLCOM_DELETE:
1427
 
    replication_services.deleteRecord(session, table);
 
4225
  case SQLCOM_DELETE_MULTI:
 
4226
    error= replicator_delete_row(session, table);
1428
4227
    break;
 
4228
 
 
4229
    /*
 
4230
      For everything else we ignore the event (since it just involves a temp table)
 
4231
    */
1429
4232
  default:
1430
4233
    break;
1431
4234
  }
1432
4235
 
1433
 
  return result;
 
4236
  return error;
1434
4237
}
1435
4238
 
1436
 
int Cursor::ha_external_lock(Session *session, int lock_type)
 
4239
int handler::ha_external_lock(Session *session, int lock_type)
1437
4240
{
1438
4241
  /*
1439
4242
    Whether this is lock or unlock, this should be true, and is to verify that
1442
4245
  */
1443
4246
  assert(next_insert_id == 0);
1444
4247
 
1445
 
  if (DRIZZLE_CURSOR_RDLOCK_START_ENABLED() ||
1446
 
      DRIZZLE_CURSOR_WRLOCK_START_ENABLED() ||
1447
 
      DRIZZLE_CURSOR_UNLOCK_START_ENABLED())
1448
 
  {
1449
 
    if (lock_type == F_RDLCK)
1450
 
    {
1451
 
      DRIZZLE_CURSOR_RDLOCK_START(table_share->db.str,
1452
 
                                  table_share->table_name.str);
1453
 
    }
1454
 
    else if (lock_type == F_WRLCK)
1455
 
    {
1456
 
      DRIZZLE_CURSOR_WRLOCK_START(table_share->db.str,
1457
 
                                  table_share->table_name.str);
1458
 
    }
1459
 
    else if (lock_type == F_UNLCK)
1460
 
    {
1461
 
      DRIZZLE_CURSOR_UNLOCK_START(table_share->db.str,
1462
 
                                  table_share->table_name.str);
1463
 
    }
1464
 
  }
1465
 
 
1466
4248
  /*
1467
4249
    We cache the table flags if the locking succeeded. Otherwise, we
1468
4250
    keep them as they were when they were fetched in ha_open().
1469
4251
  */
 
4252
  DRIZZLE_EXTERNAL_LOCK(lock_type);
1470
4253
 
1471
4254
  int error= external_lock(session, lock_type);
1472
 
 
1473
 
  if (DRIZZLE_CURSOR_RDLOCK_DONE_ENABLED() ||
1474
 
      DRIZZLE_CURSOR_WRLOCK_DONE_ENABLED() ||
1475
 
      DRIZZLE_CURSOR_UNLOCK_DONE_ENABLED())
1476
 
  {
1477
 
    if (lock_type == F_RDLCK)
1478
 
    {
1479
 
      DRIZZLE_CURSOR_RDLOCK_DONE(error);
1480
 
    }
1481
 
    else if (lock_type == F_WRLCK)
1482
 
    {
1483
 
      DRIZZLE_CURSOR_WRLOCK_DONE(error);
1484
 
    }
1485
 
    else if (lock_type == F_UNLCK)
1486
 
    {
1487
 
      DRIZZLE_CURSOR_UNLOCK_DONE(error);
1488
 
    }
1489
 
  }
1490
 
 
1491
 
  return error;
 
4255
  if (error == 0)
 
4256
    cached_table_flags= table_flags();
 
4257
  return(error);
1492
4258
}
1493
4259
 
1494
4260
 
1495
4261
/**
1496
 
  Check Cursor usage and reset state of file to after 'open'
 
4262
  Check handler usage and reset state of file to after 'open'
1497
4263
*/
1498
 
int Cursor::ha_reset()
 
4264
int handler::ha_reset()
1499
4265
{
1500
4266
  /* Check that we have called all proper deallocation functions */
1501
 
  assert((unsigned char*) table->def_read_set.getBitmap() +
 
4267
  assert((unsigned char*) table->def_read_set.bitmap +
1502
4268
              table->s->column_bitmap_size ==
1503
 
              (unsigned char*) table->def_write_set.getBitmap());
1504
 
  assert(table->s->all_set.isSetAll());
 
4269
              (unsigned char*) table->def_write_set.bitmap);
 
4270
  assert(bitmap_is_set_all(&table->s->all_set));
1505
4271
  assert(table->key_read == 0);
1506
4272
  /* ensure that ha_index_end / ha_rnd_end has been called */
1507
4273
  assert(inited == NONE);
1508
4274
  /* Free cache used by filesort */
1509
 
  table->free_io_cache();
 
4275
  free_io_cache(table);
1510
4276
  /* reset the bitmaps to point to defaults */
1511
4277
  table->default_column_bitmaps();
1512
4278
  return(reset());
1513
4279
}
1514
4280
 
1515
4281
 
1516
 
int Cursor::ha_write_row(unsigned char *buf)
 
4282
int handler::ha_write_row(unsigned char *buf)
1517
4283
{
1518
4284
  int error;
1519
 
 
1520
 
  /*
1521
 
   * If we have a timestamp column, update it to the current time
1522
 
   *
1523
 
   * @TODO Technically, the below two lines can be take even further out of the
1524
 
   * Cursor interface and into the fill_record() method.
1525
 
   */
1526
 
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
1527
 
    table->timestamp_field->set_time();
1528
 
 
1529
 
  DRIZZLE_INSERT_ROW_START(table_share->db.str, table_share->table_name.str);
1530
 
  setTransactionReadWrite();
1531
 
  error= write_row(buf);
1532
 
  DRIZZLE_INSERT_ROW_DONE(error);
1533
 
 
1534
 
  if (unlikely(error))
1535
 
  {
1536
 
    return error;
1537
 
  }
1538
 
 
1539
 
  if (unlikely(log_row_for_replication(table, NULL, buf)))
1540
 
    return HA_ERR_RBR_LOGGING_FAILED;
1541
 
 
1542
 
  return 0;
 
4285
  DRIZZLE_INSERT_ROW_START();
 
4286
 
 
4287
  mark_trx_read_write();
 
4288
 
 
4289
  if (unlikely(error= write_row(buf)))
 
4290
    return(error);
 
4291
 
 
4292
  if (unlikely(binlog_log_row(table, 0, buf)))
 
4293
    return HA_ERR_RBR_LOGGING_FAILED; /* purecov: inspected */
 
4294
 
 
4295
  DRIZZLE_INSERT_ROW_END();
 
4296
  return(0);
1543
4297
}
1544
4298
 
1545
4299
 
1546
 
int Cursor::ha_update_row(const unsigned char *old_data, unsigned char *new_data)
 
4300
int handler::ha_update_row(const unsigned char *old_data, unsigned char *new_data)
1547
4301
{
1548
4302
  int error;
1549
4303
 
1553
4307
   */
1554
4308
  assert(new_data == table->record[0]);
1555
4309
 
1556
 
  DRIZZLE_UPDATE_ROW_START(table_share->db.str, table_share->table_name.str);
1557
 
  setTransactionReadWrite();
1558
 
  error= update_row(old_data, new_data);
1559
 
  DRIZZLE_UPDATE_ROW_DONE(error);
 
4310
  mark_trx_read_write();
1560
4311
 
1561
 
  if (unlikely(error))
1562
 
  {
 
4312
  if (unlikely(error= update_row(old_data, new_data)))
1563
4313
    return error;
1564
 
  }
1565
4314
 
1566
 
  if (unlikely(log_row_for_replication(table, old_data, new_data)))
 
4315
  if (unlikely(binlog_log_row(table, old_data, new_data)))
1567
4316
    return HA_ERR_RBR_LOGGING_FAILED;
1568
4317
 
1569
4318
  return 0;
1570
4319
}
1571
4320
 
1572
 
int Cursor::ha_delete_row(const unsigned char *buf)
 
4321
int handler::ha_delete_row(const unsigned char *buf)
1573
4322
{
1574
4323
  int error;
1575
4324
 
1576
 
  DRIZZLE_DELETE_ROW_START(table_share->db.str, table_share->table_name.str);
1577
 
  setTransactionReadWrite();
1578
 
  error= delete_row(buf);
1579
 
  DRIZZLE_DELETE_ROW_DONE(error);
 
4325
  mark_trx_read_write();
1580
4326
 
1581
 
  if (unlikely(error))
 
4327
  if (unlikely(error= delete_row(buf)))
1582
4328
    return error;
1583
4329
 
1584
 
  if (unlikely(log_row_for_replication(table, buf, NULL)))
 
4330
  if (unlikely(binlog_log_row(table, buf, 0)))
1585
4331
    return HA_ERR_RBR_LOGGING_FAILED;
1586
4332
 
1587
4333
  return 0;
1588
4334
}
1589
4335
 
1590
 
} /* namespace drizzled */
 
4336
 
 
4337
 
 
4338
/**
 
4339
  @details
 
4340
  use_hidden_primary_key() is called in case of an update/delete when
 
4341
  (table_flags() and HA_PRIMARY_KEY_REQUIRED_FOR_DELETE) is defined
 
4342
  but we don't have a primary key
 
4343
*/
 
4344
void handler::use_hidden_primary_key()
 
4345
{
 
4346
  /* fallback to use all columns in the table to identify row */
 
4347
  table->use_all_columns();
 
4348
}
 
4349
 
 
4350
void table_case_convert(char * name, uint32_t length)
 
4351
{
 
4352
  if (lower_case_table_names)
 
4353
    files_charset_info->cset->casedn(files_charset_info,
 
4354
                                     name, length, name, length);
 
4355
}
 
4356
 
 
4357
const char *table_case_name(HA_CREATE_INFO *info, const char *name)
 
4358
{
 
4359
  return ((lower_case_table_names == 2 && info->alias) ? info->alias : name);
 
4360
}