~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/handler.cc

  • Committer: Monty Taylor
  • Date: 2009-03-04 02:48:12 UTC
  • mto: (917.1.2 mordred)
  • mto: This revision was merged to the branch mainline in revision 918.
  • Revision ID: mordred@inaugust.com-20090304024812-5wb6wpye5c1iitbq
Applied atomic patch to current tree.

Show diffs side-by-side

added added

removed removed

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