~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/handler.cc

  • Committer: Brian Aker
  • Date: 2009-02-07 21:33:55 UTC
  • Revision ID: brian@tangent.org-20090207213355-j2zrs4f569g0az9m
SmallĀ formattingĀ changes.

Show diffs side-by-side

added added

removed removed

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