~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/cursor.cc

Merge Stewart's dead code removal

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
  Handler-calling-functions
24
24
*/
25
25
 
26
 
#include "config.h"
27
 
 
28
 
#include <fcntl.h>
29
 
 
30
 
#include "drizzled/my_hash.h"
 
26
#include "drizzled/server_includes.h"
 
27
#include "mysys/hash.h"
31
28
#include "drizzled/error.h"
32
29
#include "drizzled/gettext.h"
33
30
#include "drizzled/probes.h"
34
31
#include "drizzled/sql_parse.h"
35
 
#include "drizzled/optimizer/cost_vector.h"
 
32
#include "drizzled/cost_vect.h"
36
33
#include "drizzled/session.h"
37
34
#include "drizzled/sql_base.h"
38
 
#include "drizzled/transaction_services.h"
39
35
#include "drizzled/replication_services.h"
40
36
#include "drizzled/lock.h"
41
37
#include "drizzled/item/int.h"
42
38
#include "drizzled/item/empty_string.h"
 
39
#include "drizzled/unireg.h" // for mysql_frm_type
43
40
#include "drizzled/field/timestamp.h"
44
41
#include "drizzled/message/table.pb.h"
45
42
#include "drizzled/plugin/client.h"
46
 
#include "drizzled/internal/my_sys.h"
47
 
#include "drizzled/transaction_services.h"
48
43
 
49
44
using namespace std;
50
 
 
51
 
namespace drizzled
52
 
{
 
45
using namespace drizzled;
 
46
 
 
47
KEY_CREATE_INFO default_key_create_info= { HA_KEY_ALG_UNDEF, 0, {NULL,0} };
 
48
 
 
49
/* number of entries in storage_engines[] */
 
50
uint32_t total_ha= 0;
 
51
/* number of storage engines (from storage_engines[]) that support 2pc */
 
52
uint32_t total_ha_2pc= 0;
 
53
/* size of savepoint storage area (see ha_init) */
 
54
uint32_t savepoint_alloc_size= 0;
 
55
 
 
56
const char *ha_row_type[] = {
 
57
  "", "FIXED", "DYNAMIC", "COMPRESSED", "REDUNDANT", "COMPACT", "PAGE", "?","?","?"
 
58
};
 
59
 
 
60
const char *tx_isolation_names[] =
 
61
{ "READ-UNCOMMITTED", "READ-COMMITTED", "REPEATABLE-READ", "SERIALIZABLE",
 
62
  NULL};
 
63
 
 
64
TYPELIB tx_isolation_typelib= {array_elements(tx_isolation_names)-1,"",
 
65
                               tx_isolation_names, NULL};
 
66
 
 
67
 
 
68
/**
 
69
  Register Cursor error messages for use with my_error().
 
70
 
 
71
  @retval
 
72
    0           OK
 
73
  @retval
 
74
    !=0         Error
 
75
*/
 
76
 
 
77
int ha_init_errors(void)
 
78
{
 
79
#define SETMSG(nr, msg) errmsgs[(nr) - HA_ERR_FIRST]= (msg)
 
80
  const char    **errmsgs;
 
81
 
 
82
  /* Allocate a pointer array for the error message strings. */
 
83
  /* Zerofill it to avoid uninitialized gaps. */
 
84
  if (! (errmsgs= (const char**) malloc(HA_ERR_ERRORS * sizeof(char*))))
 
85
    return 1;
 
86
  memset(errmsgs, 0, HA_ERR_ERRORS * sizeof(char *));
 
87
 
 
88
  /* Set the dedicated error messages. */
 
89
  SETMSG(HA_ERR_KEY_NOT_FOUND,          ER(ER_KEY_NOT_FOUND));
 
90
  SETMSG(HA_ERR_FOUND_DUPP_KEY,         ER(ER_DUP_KEY));
 
91
  SETMSG(HA_ERR_RECORD_CHANGED,         "Update wich is recoverable");
 
92
  SETMSG(HA_ERR_WRONG_INDEX,            "Wrong index given to function");
 
93
  SETMSG(HA_ERR_CRASHED,                ER(ER_NOT_KEYFILE));
 
94
  SETMSG(HA_ERR_WRONG_IN_RECORD,        ER(ER_CRASHED_ON_USAGE));
 
95
  SETMSG(HA_ERR_OUT_OF_MEM,             "Table Cursor out of memory");
 
96
  SETMSG(HA_ERR_NOT_A_TABLE,            "Incorrect file format '%.64s'");
 
97
  SETMSG(HA_ERR_WRONG_COMMAND,          "Command not supported");
 
98
  SETMSG(HA_ERR_OLD_FILE,               ER(ER_OLD_KEYFILE));
 
99
  SETMSG(HA_ERR_NO_ACTIVE_RECORD,       "No record read in update");
 
100
  SETMSG(HA_ERR_RECORD_DELETED,         "Intern record deleted");
 
101
  SETMSG(HA_ERR_RECORD_FILE_FULL,       ER(ER_RECORD_FILE_FULL));
 
102
  SETMSG(HA_ERR_INDEX_FILE_FULL,        "No more room in index file '%.64s'");
 
103
  SETMSG(HA_ERR_END_OF_FILE,            "End in next/prev/first/last");
 
104
  SETMSG(HA_ERR_UNSUPPORTED,            ER(ER_ILLEGAL_HA));
 
105
  SETMSG(HA_ERR_TO_BIG_ROW,             "Too big row");
 
106
  SETMSG(HA_WRONG_CREATE_OPTION,        "Wrong create option");
 
107
  SETMSG(HA_ERR_FOUND_DUPP_UNIQUE,      ER(ER_DUP_UNIQUE));
 
108
  SETMSG(HA_ERR_UNKNOWN_CHARSET,        "Can't open charset");
 
109
  SETMSG(HA_ERR_WRONG_MRG_TABLE_DEF,    ER(ER_WRONG_MRG_TABLE));
 
110
  SETMSG(HA_ERR_CRASHED_ON_REPAIR,      ER(ER_CRASHED_ON_REPAIR));
 
111
  SETMSG(HA_ERR_CRASHED_ON_USAGE,       ER(ER_CRASHED_ON_USAGE));
 
112
  SETMSG(HA_ERR_LOCK_WAIT_TIMEOUT,      ER(ER_LOCK_WAIT_TIMEOUT));
 
113
  SETMSG(HA_ERR_LOCK_TABLE_FULL,        ER(ER_LOCK_TABLE_FULL));
 
114
  SETMSG(HA_ERR_READ_ONLY_TRANSACTION,  ER(ER_READ_ONLY_TRANSACTION));
 
115
  SETMSG(HA_ERR_LOCK_DEADLOCK,          ER(ER_LOCK_DEADLOCK));
 
116
  SETMSG(HA_ERR_CANNOT_ADD_FOREIGN,     ER(ER_CANNOT_ADD_FOREIGN));
 
117
  SETMSG(HA_ERR_NO_REFERENCED_ROW,      ER(ER_NO_REFERENCED_ROW_2));
 
118
  SETMSG(HA_ERR_ROW_IS_REFERENCED,      ER(ER_ROW_IS_REFERENCED_2));
 
119
  SETMSG(HA_ERR_NO_SAVEPOINT,           "No savepoint with that name");
 
120
  SETMSG(HA_ERR_NON_UNIQUE_BLOCK_SIZE,  "Non unique key block size");
 
121
  SETMSG(HA_ERR_NO_SUCH_TABLE,          "No such table: '%.64s'");
 
122
  SETMSG(HA_ERR_TABLE_EXIST,            ER(ER_TABLE_EXISTS_ERROR));
 
123
  SETMSG(HA_ERR_NO_CONNECTION,          "Could not connect to storage engine");
 
124
  SETMSG(HA_ERR_TABLE_DEF_CHANGED,      ER(ER_TABLE_DEF_CHANGED));
 
125
  SETMSG(HA_ERR_FOREIGN_DUPLICATE_KEY,  "FK constraint would lead to duplicate key");
 
126
  SETMSG(HA_ERR_TABLE_NEEDS_UPGRADE,    ER(ER_TABLE_NEEDS_UPGRADE));
 
127
  SETMSG(HA_ERR_TABLE_READONLY,         ER(ER_OPEN_AS_READONLY));
 
128
  SETMSG(HA_ERR_AUTOINC_READ_FAILED,    ER(ER_AUTOINC_READ_FAILED));
 
129
  SETMSG(HA_ERR_AUTOINC_ERANGE,         ER(ER_WARN_DATA_OUT_OF_RANGE));
 
130
 
 
131
  /* Register the error messages for use with my_error(). */
 
132
  return my_error_register(errmsgs, HA_ERR_FIRST, HA_ERR_LAST);
 
133
}
 
134
 
 
135
 
 
136
/**
 
137
  Unregister Cursor error messages.
 
138
 
 
139
  @retval
 
140
    0           OK
 
141
  @retval
 
142
    !=0         Error
 
143
*/
 
144
static int ha_finish_errors(void)
 
145
{
 
146
  const char    **errmsgs;
 
147
 
 
148
  /* Allocate a pointer array for the error message strings. */
 
149
  if (! (errmsgs= my_error_unregister(HA_ERR_FIRST, HA_ERR_LAST)))
 
150
    return 1;
 
151
  free((unsigned char*) errmsgs);
 
152
  return 0;
 
153
}
 
154
 
 
155
int ha_init()
 
156
{
 
157
  int error= 0;
 
158
 
 
159
  assert(total_ha < MAX_HA);
 
160
  /*
 
161
    Check if there is a transaction-capable storage engine besides the
 
162
    binary log (which is considered a transaction-capable storage engine in
 
163
    counting total_ha)
 
164
  */
 
165
  savepoint_alloc_size+= sizeof(SAVEPOINT);
 
166
  return error;
 
167
}
 
168
 
 
169
int ha_end()
 
170
{
 
171
  int error= 0;
 
172
 
 
173
  /*
 
174
    This should be eventualy based  on the graceful shutdown flag.
 
175
    So if flag is equal to HA_PANIC_CLOSE, the deallocate
 
176
    the errors.
 
177
  */
 
178
  if (ha_finish_errors())
 
179
    error= 1;
 
180
 
 
181
  return error;
 
182
}
 
183
 
 
184
 
 
185
 
 
186
/* ========================================================================
 
187
 ======================= TRANSACTIONS ===================================*/
 
188
 
 
189
/**
 
190
  Transaction handling in the server
 
191
  ==================================
 
192
 
 
193
  In each client connection, MySQL maintains two transactional
 
194
  states:
 
195
  - a statement transaction,
 
196
  - a standard, also called normal transaction.
 
197
 
 
198
  Historical note
 
199
  ---------------
 
200
  "Statement transaction" is a non-standard term that comes
 
201
  from the times when MySQL supported BerkeleyDB storage engine.
 
202
 
 
203
  First of all, it should be said that in BerkeleyDB auto-commit
 
204
  mode auto-commits operations that are atomic to the storage
 
205
  engine itself, such as a write of a record, and are too
 
206
  high-granular to be atomic from the application perspective
 
207
  (MySQL). One SQL statement could involve many BerkeleyDB
 
208
  auto-committed operations and thus BerkeleyDB auto-commit was of
 
209
  little use to MySQL.
 
210
 
 
211
  Secondly, instead of SQL standard savepoints, BerkeleyDB
 
212
  provided the concept of "nested transactions". In a nutshell,
 
213
  transactions could be arbitrarily nested, but when the parent
 
214
  transaction was committed or aborted, all its child (nested)
 
215
  transactions were handled committed or aborted as well.
 
216
  Commit of a nested transaction, in turn, made its changes
 
217
  visible, but not durable: it destroyed the nested transaction,
 
218
  all its changes would become available to the parent and
 
219
  currently active nested transactions of this parent.
 
220
 
 
221
  So the mechanism of nested transactions was employed to
 
222
  provide "all or nothing" guarantee of SQL statements
 
223
  required by the standard.
 
224
  A nested transaction would be created at start of each SQL
 
225
  statement, and destroyed (committed or aborted) at statement
 
226
  end. Such nested transaction was internally referred to as
 
227
  a "statement transaction" and gave birth to the term.
 
228
 
 
229
  <Historical note ends>
 
230
 
 
231
  Since then a statement transaction is started for each statement
 
232
  that accesses transactional tables or uses the binary log.  If
 
233
  the statement succeeds, the statement transaction is committed.
 
234
  If the statement fails, the transaction is rolled back. Commits
 
235
  of statement transactions are not durable -- each such
 
236
  transaction is nested in the normal transaction, and if the
 
237
  normal transaction is rolled back, the effects of all enclosed
 
238
  statement transactions are undone as well.  Technically,
 
239
  a statement transaction can be viewed as a savepoint which is
 
240
  maintained automatically in order to make effects of one
 
241
  statement atomic.
 
242
 
 
243
  The normal transaction is started by the user and is ended
 
244
  usually upon a user request as well. The normal transaction
 
245
  encloses transactions of all statements issued between
 
246
  its beginning and its end.
 
247
  In autocommit mode, the normal transaction is equivalent
 
248
  to the statement transaction.
 
249
 
 
250
  Since MySQL supports PSEA (pluggable storage engine
 
251
  architecture), more than one transactional engine can be
 
252
  active at a time. Hence transactions, from the server
 
253
  point of view, are always distributed. In particular,
 
254
  transactional state is maintained independently for each
 
255
  engine. In order to commit a transaction the two phase
 
256
  commit protocol is employed.
 
257
 
 
258
  Not all statements are executed in context of a transaction.
 
259
  Administrative and status information statements do not modify
 
260
  engine data, and thus do not start a statement transaction and
 
261
  also have no effect on the normal transaction. Examples of such
 
262
  statements are SHOW STATUS and RESET SLAVE.
 
263
 
 
264
  Similarly DDL statements are not transactional,
 
265
  and therefore a transaction is [almost] never started for a DDL
 
266
  statement. The difference between a DDL statement and a purely
 
267
  administrative statement though is that a DDL statement always
 
268
  commits the current transaction before proceeding, if there is
 
269
  any.
 
270
 
 
271
  At last, SQL statements that work with non-transactional
 
272
  engines also have no effect on the transaction state of the
 
273
  connection. Even though they are written to the binary log,
 
274
  and the binary log is, overall, transactional, the writes
 
275
  are done in "write-through" mode, directly to the binlog
 
276
  file, followed with a OS cache sync, in other words,
 
277
  bypassing the binlog undo log (translog).
 
278
  They do not commit the current normal transaction.
 
279
  A failure of a statement that uses non-transactional tables
 
280
  would cause a rollback of the statement transaction, but
 
281
  in case there no non-transactional tables are used,
 
282
  no statement transaction is started.
 
283
 
 
284
  Data layout
 
285
  -----------
 
286
 
 
287
  The server stores its transaction-related data in
 
288
  session->transaction. This structure has two members of type
 
289
  Session_TRANS. These members correspond to the statement and
 
290
  normal transactions respectively:
 
291
 
 
292
  - session->transaction.stmt contains a list of engines
 
293
  that are participating in the given statement
 
294
  - session->transaction.all contains a list of engines that
 
295
  have participated in any of the statement transactions started
 
296
  within the context of the normal transaction.
 
297
  Each element of the list contains a pointer to the storage
 
298
  engine, engine-specific transactional data, and engine-specific
 
299
  transaction flags.
 
300
 
 
301
  In autocommit mode session->transaction.all is empty.
 
302
  Instead, data of session->transaction.stmt is
 
303
  used to commit/rollback the normal transaction.
 
304
 
 
305
  The list of registered engines has a few important properties:
 
306
  - no engine is registered in the list twice
 
307
  - engines are present in the list a reverse temporal order --
 
308
  new participants are always added to the beginning of the list.
 
309
 
 
310
  Transaction life cycle
 
311
  ----------------------
 
312
 
 
313
  When a new connection is established, session->transaction
 
314
  members are initialized to an empty state.
 
315
  If a statement uses any tables, all affected engines
 
316
  are registered in the statement engine list. In
 
317
  non-autocommit mode, the same engines are registered in
 
318
  the normal transaction list.
 
319
  At the end of the statement, the server issues a commit
 
320
  or a roll back for all engines in the statement list.
 
321
  At this point transaction flags of an engine, if any, are
 
322
  propagated from the statement list to the list of the normal
 
323
  transaction.
 
324
  When commit/rollback is finished, the statement list is
 
325
  cleared. It will be filled in again by the next statement,
 
326
  and emptied again at the next statement's end.
 
327
 
 
328
  The normal transaction is committed in a similar way
 
329
  (by going over all engines in session->transaction.all list)
 
330
  but at different times:
 
331
  - upon COMMIT SQL statement is issued by the user
 
332
  - implicitly, by the server, at the beginning of a DDL statement
 
333
  or SET AUTOCOMMIT={0|1} statement.
 
334
 
 
335
  The normal transaction can be rolled back as well:
 
336
  - if the user has requested so, by issuing ROLLBACK SQL
 
337
  statement
 
338
  - if one of the storage engines requested a rollback
 
339
  by setting session->transaction_rollback_request. This may
 
340
  happen in case, e.g., when the transaction in the engine was
 
341
  chosen a victim of the internal deadlock resolution algorithm
 
342
  and rolled back internally. When such a situation happens, there
 
343
  is little the server can do and the only option is to rollback
 
344
  transactions in all other participating engines.  In this case
 
345
  the rollback is accompanied by an error sent to the user.
 
346
 
 
347
  As follows from the use cases above, the normal transaction
 
348
  is never committed when there is an outstanding statement
 
349
  transaction. In most cases there is no conflict, since
 
350
  commits of the normal transaction are issued by a stand-alone
 
351
  administrative or DDL statement, thus no outstanding statement
 
352
  transaction of the previous statement exists. Besides,
 
353
  all statements that manipulate with the normal transaction
 
354
  are prohibited in stored functions and triggers, therefore
 
355
  no conflicting situation can occur in a sub-statement either.
 
356
  The remaining rare cases when the server explicitly has
 
357
  to commit the statement transaction prior to committing the normal
 
358
  one cover error-handling scenarios (see for example
 
359
  ?).
 
360
 
 
361
  When committing a statement or a normal transaction, the server
 
362
  either uses the two-phase commit protocol, or issues a commit
 
363
  in each engine independently. The two-phase commit protocol
 
364
  is used only if:
 
365
  - all participating engines support two-phase commit (provide
 
366
    plugin::StorageEngine::prepare PSEA API call) and
 
367
  - transactions in at least two engines modify data (i.e. are
 
368
  not read-only).
 
369
 
 
370
  Note that the two phase commit is used for
 
371
  statement transactions, even though they are not durable anyway.
 
372
  This is done to ensure logical consistency of data in a multiple-
 
373
  engine transaction.
 
374
  For example, imagine that some day MySQL supports unique
 
375
  constraint checks deferred till the end of statement. In such
 
376
  case a commit in one of the engines may yield ER_DUP_KEY,
 
377
  and MySQL should be able to gracefully abort statement
 
378
  transactions of other participants.
 
379
 
 
380
  After the normal transaction has been committed,
 
381
  session->transaction.all list is cleared.
 
382
 
 
383
  When a connection is closed, the current normal transaction, if
 
384
  any, is rolled back.
 
385
 
 
386
  Roles and responsibilities
 
387
  --------------------------
 
388
 
 
389
  The server has no way to know that an engine participates in
 
390
  the statement and a transaction has been started
 
391
  in it unless the engine says so. Thus, in order to be
 
392
  a part of a transaction, the engine must "register" itself.
 
393
  This is done by invoking trans_register_ha() server call.
 
394
  Normally the engine registers itself whenever Cursor::external_lock()
 
395
  is called. trans_register_ha() can be invoked many times: if
 
396
  an engine is already registered, the call does nothing.
 
397
  In case autocommit is not set, the engine must register itself
 
398
  twice -- both in the statement list and in the normal transaction
 
399
  list.
 
400
  In which list to register is a parameter of trans_register_ha().
 
401
 
 
402
  Note, that although the registration interface in itself is
 
403
  fairly clear, the current usage practice often leads to undesired
 
404
  effects. E.g. since a call to trans_register_ha() in most engines
 
405
  is embedded into implementation of Cursor::external_lock(), some
 
406
  DDL statements start a transaction (at least from the server
 
407
  point of view) even though they are not expected to. E.g.
 
408
  CREATE TABLE does not start a transaction, since
 
409
  Cursor::external_lock() is never called during CREATE TABLE. But
 
410
  CREATE TABLE ... SELECT does, since Cursor::external_lock() is
 
411
  called for the table that is being selected from. This has no
 
412
  practical effects currently, but must be kept in mind
 
413
  nevertheless.
 
414
 
 
415
  Once an engine is registered, the server will do the rest
 
416
  of the work.
 
417
 
 
418
  During statement execution, whenever any of data-modifying
 
419
  PSEA API methods is used, e.g. Cursor::write_row() or
 
420
  Cursor::update_row(), the read-write flag is raised in the
 
421
  statement transaction for the involved engine.
 
422
  Currently All PSEA calls are "traced", and the data can not be
 
423
  changed in a way other than issuing a PSEA call. Important:
 
424
  unless this invariant is preserved the server will not know that
 
425
  a transaction in a given engine is read-write and will not
 
426
  involve the two-phase commit protocol!
 
427
 
 
428
  At the end of a statement, server call
 
429
  ha_autocommit_or_rollback() is invoked. This call in turn
 
430
  invokes plugin::StorageEngine::prepare() for every involved engine.
 
431
  Prepare is followed by a call to plugin::StorageEngine::commit_one_phase()
 
432
  If a one-phase commit will suffice, plugin::StorageEngine::prepare() is not
 
433
  invoked and the server only calls plugin::StorageEngine::commit_one_phase().
 
434
  At statement commit, the statement-related read-write engine
 
435
  flag is propagated to the corresponding flag in the normal
 
436
  transaction.  When the commit is complete, the list of registered
 
437
  engines is cleared.
 
438
 
 
439
  Rollback is handled in a similar fashion.
 
440
 
 
441
  Additional notes on DDL and the normal transaction.
 
442
  ---------------------------------------------------
 
443
 
 
444
  DDLs and operations with non-transactional engines
 
445
  do not "register" in session->transaction lists, and thus do not
 
446
  modify the transaction state. Besides, each DDL in
 
447
  MySQL is prefixed with an implicit normal transaction commit
 
448
  (a call to Session::endActiveTransaction()), and thus leaves nothing
 
449
  to modify.
 
450
  However, as it has been pointed out with CREATE TABLE .. SELECT,
 
451
  some DDL statements can start a *new* transaction.
 
452
 
 
453
  Behaviour of the server in this case is currently badly
 
454
  defined.
 
455
  DDL statements use a form of "semantic" logging
 
456
  to maintain atomicity: if CREATE TABLE .. SELECT failed,
 
457
  the newly created table is deleted.
 
458
  In addition, some DDL statements issue interim transaction
 
459
  commits: e.g. ALTER Table issues a commit after data is copied
 
460
  from the original table to the internal temporary table. Other
 
461
  statements, e.g. CREATE TABLE ... SELECT do not always commit
 
462
  after itself.
 
463
  And finally there is a group of DDL statements such as
 
464
  RENAME/DROP Table that doesn't start a new transaction
 
465
  and doesn't commit.
 
466
 
 
467
  This diversity makes it hard to say what will happen if
 
468
  by chance a stored function is invoked during a DDL --
 
469
  whether any modifications it makes will be committed or not
 
470
  is not clear. Fortunately, SQL grammar of few DDLs allows
 
471
  invocation of a stored function.
 
472
 
 
473
  A consistent behaviour is perhaps to always commit the normal
 
474
  transaction after all DDLs, just like the statement transaction
 
475
  is always committed at the end of all statements.
 
476
*/
 
477
 
 
478
/**
 
479
  Register a storage engine for a transaction.
 
480
 
 
481
  Every storage engine MUST call this function when it starts
 
482
  a transaction or a statement (that is it must be called both for the
 
483
  "beginning of transaction" and "beginning of statement").
 
484
  Only storage engines registered for the transaction/statement
 
485
  will know when to commit/rollback it.
 
486
 
 
487
  @note
 
488
    trans_register_ha is idempotent - storage engine may register many
 
489
    times per transaction.
 
490
 
 
491
*/
 
492
void trans_register_ha(Session *session, bool all, plugin::StorageEngine *engine)
 
493
{
 
494
  Session_TRANS *trans;
 
495
  Ha_trx_info *ha_info;
 
496
 
 
497
  if (all)
 
498
  {
 
499
    trans= &session->transaction.all;
 
500
    session->server_status|= SERVER_STATUS_IN_TRANS;
 
501
  }
 
502
  else
 
503
    trans= &session->transaction.stmt;
 
504
 
 
505
  ha_info= session->ha_data[engine->getSlot()].ha_info + static_cast<unsigned>(all);
 
506
 
 
507
  if (ha_info->is_started())
 
508
    return; /* already registered, return */
 
509
 
 
510
  ha_info->register_ha(trans, engine);
 
511
 
 
512
  trans->no_2pc|= not engine->has_2pc();
 
513
  if (session->transaction.xid_state.xid.is_null())
 
514
    session->transaction.xid_state.xid.set(session->query_id);
 
515
}
 
516
 
 
517
/**
 
518
  Check if we can skip the two-phase commit.
 
519
 
 
520
  A helper function to evaluate if two-phase commit is mandatory.
 
521
  As a side effect, propagates the read-only/read-write flags
 
522
  of the statement transaction to its enclosing normal transaction.
 
523
 
 
524
  @retval true   we must run a two-phase commit. Returned
 
525
                 if we have at least two engines with read-write changes.
 
526
  @retval false  Don't need two-phase commit. Even if we have two
 
527
                 transactional engines, we can run two independent
 
528
                 commits if changes in one of the engines are read-only.
 
529
*/
 
530
 
 
531
static
 
532
bool
 
533
ha_check_and_coalesce_trx_read_only(Session *session, Ha_trx_info *ha_list,
 
534
                                    bool all)
 
535
{
 
536
  /* The number of storage engines that have actual changes. */
 
537
  unsigned rw_ha_count= 0;
 
538
  Ha_trx_info *ha_info;
 
539
 
 
540
  for (ha_info= ha_list; ha_info; ha_info= ha_info->next())
 
541
  {
 
542
    if (ha_info->is_trx_read_write())
 
543
      ++rw_ha_count;
 
544
 
 
545
    if (! all)
 
546
    {
 
547
      Ha_trx_info *ha_info_all= &session->ha_data[ha_info->engine()->getSlot()].ha_info[1];
 
548
      assert(ha_info != ha_info_all);
 
549
      /*
 
550
        Merge read-only/read-write information about statement
 
551
        transaction to its enclosing normal transaction. Do this
 
552
        only if in a real transaction -- that is, if we know
 
553
        that ha_info_all is registered in session->transaction.all.
 
554
        Since otherwise we only clutter the normal transaction flags.
 
555
      */
 
556
      if (ha_info_all->is_started()) /* false if autocommit. */
 
557
        ha_info_all->coalesce_trx_with(ha_info);
 
558
    }
 
559
    else if (rw_ha_count > 1)
 
560
    {
 
561
      /*
 
562
        It is a normal transaction, so we don't need to merge read/write
 
563
        information up, and the need for two-phase commit has been
 
564
        already established. Break the loop prematurely.
 
565
      */
 
566
      break;
 
567
    }
 
568
  }
 
569
  return rw_ha_count > 1;
 
570
}
 
571
 
 
572
 
 
573
/**
 
574
  @retval
 
575
    0   ok
 
576
  @retval
 
577
    1   transaction was rolled back
 
578
  @retval
 
579
    2   error during commit, data may be inconsistent
 
580
 
 
581
  @todo
 
582
    Since we don't support nested statement transactions in 5.0,
 
583
    we can't commit or rollback stmt transactions while we are inside
 
584
    stored functions or triggers. So we simply do nothing now.
 
585
    TODO: This should be fixed in later ( >= 5.1) releases.
 
586
*/
 
587
int ha_commit_trans(Session *session, bool all)
 
588
{
 
589
  int error= 0, cookie= 0;
 
590
  /*
 
591
    'all' means that this is either an explicit commit issued by
 
592
    user, or an implicit commit issued by a DDL.
 
593
  */
 
594
  Session_TRANS *trans= all ? &session->transaction.all : &session->transaction.stmt;
 
595
  bool is_real_trans= all || session->transaction.all.ha_list == 0;
 
596
  Ha_trx_info *ha_info= trans->ha_list;
 
597
 
 
598
  /*
 
599
    We must not commit the normal transaction if a statement
 
600
    transaction is pending. Otherwise statement transaction
 
601
    flags will not get propagated to its normal transaction's
 
602
    counterpart.
 
603
  */
 
604
  assert(session->transaction.stmt.ha_list == NULL ||
 
605
              trans == &session->transaction.stmt);
 
606
 
 
607
  if (ha_info)
 
608
  {
 
609
    bool must_2pc;
 
610
 
 
611
    if (is_real_trans && wait_if_global_read_lock(session, 0, 0))
 
612
    {
 
613
      ha_rollback_trans(session, all);
 
614
      return 1;
 
615
    }
 
616
 
 
617
    must_2pc= ha_check_and_coalesce_trx_read_only(session, ha_info, all);
 
618
 
 
619
    if (!trans->no_2pc && must_2pc)
 
620
    {
 
621
      for (; ha_info && !error; ha_info= ha_info->next())
 
622
      {
 
623
        int err;
 
624
        plugin::StorageEngine *engine= ha_info->engine();
 
625
        /*
 
626
          Do not call two-phase commit if this particular
 
627
          transaction is read-only. This allows for simpler
 
628
          implementation in engines that are always read-only.
 
629
        */
 
630
        if (! ha_info->is_trx_read_write())
 
631
          continue;
 
632
        /*
 
633
          Sic: we know that prepare() is not NULL since otherwise
 
634
          trans->no_2pc would have been set.
 
635
        */
 
636
        if ((err= engine->prepare(session, all)))
 
637
        {
 
638
          my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
 
639
          error= 1;
 
640
        }
 
641
        status_var_increment(session->status_var.ha_prepare_count);
 
642
      }
 
643
      if (error)
 
644
      {
 
645
        ha_rollback_trans(session, all);
 
646
        error= 1;
 
647
        goto end;
 
648
      }
 
649
    }
 
650
    error=ha_commit_one_phase(session, all) ? (cookie ? 2 : 1) : 0;
 
651
end:
 
652
    if (is_real_trans)
 
653
      start_waiting_global_read_lock(session);
 
654
  }
 
655
  return error;
 
656
}
 
657
 
 
658
/**
 
659
  @note
 
660
  This function does not care about global read lock. A caller should.
 
661
*/
 
662
int ha_commit_one_phase(Session *session, bool all)
 
663
{
 
664
  int error=0;
 
665
  Session_TRANS *trans=all ? &session->transaction.all : &session->transaction.stmt;
 
666
  bool is_real_trans=all || session->transaction.all.ha_list == 0;
 
667
  Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
 
668
  if (ha_info)
 
669
  {
 
670
    for (; ha_info; ha_info= ha_info_next)
 
671
    {
 
672
      int err;
 
673
      plugin::StorageEngine *engine= ha_info->engine();
 
674
      if ((err= engine->commit(session, all)))
 
675
      {
 
676
        my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
 
677
        error=1;
 
678
      }
 
679
      status_var_increment(session->status_var.ha_commit_count);
 
680
      ha_info_next= ha_info->next();
 
681
      ha_info->reset(); /* keep it conveniently zero-filled */
 
682
    }
 
683
    trans->ha_list= 0;
 
684
    trans->no_2pc=0;
 
685
    if (is_real_trans)
 
686
      session->transaction.xid_state.xid.null();
 
687
    if (all)
 
688
    {
 
689
      session->variables.tx_isolation=session->session_tx_isolation;
 
690
      session->transaction.cleanup();
 
691
    }
 
692
  }
 
693
  return error;
 
694
}
 
695
 
 
696
 
 
697
int ha_rollback_trans(Session *session, bool all)
 
698
{
 
699
  int error=0;
 
700
  Session_TRANS *trans=all ? &session->transaction.all : &session->transaction.stmt;
 
701
  Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
 
702
  bool is_real_trans=all || session->transaction.all.ha_list == 0;
 
703
 
 
704
  /*
 
705
    We must not rollback the normal transaction if a statement
 
706
    transaction is pending.
 
707
  */
 
708
  assert(session->transaction.stmt.ha_list == NULL ||
 
709
              trans == &session->transaction.stmt);
 
710
 
 
711
  if (ha_info)
 
712
  {
 
713
    for (; ha_info; ha_info= ha_info_next)
 
714
    {
 
715
      int err;
 
716
      plugin::StorageEngine *engine= ha_info->engine();
 
717
      if ((err= engine->rollback(session, all)))
 
718
      { // cannot happen
 
719
        my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
 
720
        error=1;
 
721
      }
 
722
      status_var_increment(session->status_var.ha_rollback_count);
 
723
      ha_info_next= ha_info->next();
 
724
      ha_info->reset(); /* keep it conveniently zero-filled */
 
725
    }
 
726
    trans->ha_list= 0;
 
727
    trans->no_2pc=0;
 
728
    if (is_real_trans)
 
729
      session->transaction.xid_state.xid.null();
 
730
    if (all)
 
731
    {
 
732
      session->variables.tx_isolation=session->session_tx_isolation;
 
733
      session->transaction.cleanup();
 
734
    }
 
735
  }
 
736
  if (all)
 
737
    session->transaction_rollback_request= false;
 
738
 
 
739
  /*
 
740
    If a non-transactional table was updated, warn; don't warn if this is a
 
741
    slave thread (because when a slave thread executes a ROLLBACK, it has
 
742
    been read from the binary log, so it's 100% sure and normal to produce
 
743
    error ER_WARNING_NOT_COMPLETE_ROLLBACK. If we sent the warning to the
 
744
    slave SQL thread, it would not stop the thread but just be printed in
 
745
    the error log; but we don't want users to wonder why they have this
 
746
    message in the error log, so we don't send it.
 
747
  */
 
748
  if (is_real_trans && session->transaction.all.modified_non_trans_table && session->killed != Session::KILL_CONNECTION)
 
749
    push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
750
                 ER_WARNING_NOT_COMPLETE_ROLLBACK,
 
751
                 ER(ER_WARNING_NOT_COMPLETE_ROLLBACK));
 
752
  return error;
 
753
}
 
754
 
 
755
/**
 
756
  This is used to commit or rollback a single statement depending on
 
757
  the value of error.
 
758
 
 
759
  @note
 
760
    Note that if the autocommit is on, then the following call inside
 
761
    InnoDB will commit or rollback the whole transaction (= the statement). The
 
762
    autocommit mechanism built into InnoDB is based on counting locks, but if
 
763
    the user has used LOCK TABLES then that mechanism does not know to do the
 
764
    commit.
 
765
*/
 
766
int ha_autocommit_or_rollback(Session *session, int error)
 
767
{
 
768
  if (session->transaction.stmt.ha_list)
 
769
  {
 
770
    if (!error)
 
771
    {
 
772
      if (ha_commit_trans(session, 0))
 
773
        error= 1;
 
774
    }
 
775
    else
 
776
    {
 
777
      (void) ha_rollback_trans(session, 0);
 
778
      if (session->transaction_rollback_request)
 
779
        (void) ha_rollback(session);
 
780
    }
 
781
 
 
782
    session->variables.tx_isolation=session->session_tx_isolation;
 
783
  }
 
784
 
 
785
  return error;
 
786
}
 
787
 
 
788
/**
 
789
  return the list of XID's to a client, the same way SHOW commands do.
 
790
 
 
791
  @note
 
792
    I didn't find in XA specs that an RM cannot return the same XID twice,
 
793
    so mysql_xa_recover does not filter XID's to ensure uniqueness.
 
794
    It can be easily fixed later, if necessary.
 
795
*/
 
796
bool mysql_xa_recover(Session *session)
 
797
{
 
798
  List<Item> field_list;
 
799
  int i= 0;
 
800
  XID_STATE *xs;
 
801
 
 
802
  field_list.push_back(new Item_int("formatID", 0, MY_INT32_NUM_DECIMAL_DIGITS));
 
803
  field_list.push_back(new Item_int("gtrid_length", 0, MY_INT32_NUM_DECIMAL_DIGITS));
 
804
  field_list.push_back(new Item_int("bqual_length", 0, MY_INT32_NUM_DECIMAL_DIGITS));
 
805
  field_list.push_back(new Item_empty_string("data",XIDDATASIZE));
 
806
 
 
807
  if (session->client->sendFields(&field_list))
 
808
    return 1;
 
809
 
 
810
  pthread_mutex_lock(&LOCK_xid_cache);
 
811
  while ((xs= (XID_STATE*)hash_element(&xid_cache, i++)))
 
812
  {
 
813
    if (xs->xa_state==XA_PREPARED)
 
814
    {
 
815
      session->client->store((int64_t)xs->xid.formatID);
 
816
      session->client->store((int64_t)xs->xid.gtrid_length);
 
817
      session->client->store((int64_t)xs->xid.bqual_length);
 
818
      session->client->store(xs->xid.data,
 
819
                             xs->xid.gtrid_length+xs->xid.bqual_length);
 
820
      if (session->client->flush())
 
821
      {
 
822
        pthread_mutex_unlock(&LOCK_xid_cache);
 
823
        return 1;
 
824
      }
 
825
    }
 
826
  }
 
827
 
 
828
  pthread_mutex_unlock(&LOCK_xid_cache);
 
829
  session->my_eof();
 
830
  return 0;
 
831
}
 
832
 
 
833
 
 
834
int ha_rollback_to_savepoint(Session *session, SAVEPOINT *sv)
 
835
{
 
836
  int error= 0;
 
837
  Session_TRANS *trans= &session->transaction.all;
 
838
  Ha_trx_info *ha_info, *ha_info_next;
 
839
 
 
840
  trans->no_2pc=0;
 
841
  /*
 
842
    rolling back to savepoint in all storage engines that were part of the
 
843
    transaction when the savepoint was set
 
844
  */
 
845
  for (ha_info= sv->ha_list; ha_info; ha_info= ha_info->next())
 
846
  {
 
847
    int err;
 
848
    plugin::StorageEngine *engine= ha_info->engine();
 
849
    assert(engine);
 
850
    if ((err= engine->savepoint_rollback(session,
 
851
                                         (void *)(sv+1))))
 
852
    { // cannot happen
 
853
      my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
 
854
      error= 1;
 
855
    }
 
856
    status_var_increment(session->status_var.ha_savepoint_rollback_count);
 
857
    trans->no_2pc|= not engine->has_2pc();
 
858
  }
 
859
  /*
 
860
    rolling back the transaction in all storage engines that were not part of
 
861
    the transaction when the savepoint was set
 
862
  */
 
863
  for (ha_info= trans->ha_list; ha_info != sv->ha_list;
 
864
       ha_info= ha_info_next)
 
865
  {
 
866
    int err;
 
867
    plugin::StorageEngine *engine= ha_info->engine();
 
868
    if ((err= engine->rollback(session, !(0))))
 
869
    { // cannot happen
 
870
      my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
 
871
      error= 1;
 
872
    }
 
873
    status_var_increment(session->status_var.ha_rollback_count);
 
874
    ha_info_next= ha_info->next();
 
875
    ha_info->reset(); /* keep it conveniently zero-filled */
 
876
  }
 
877
  trans->ha_list= sv->ha_list;
 
878
  return error;
 
879
}
 
880
 
 
881
/**
 
882
  @note
 
883
  according to the sql standard (ISO/IEC 9075-2:2003)
 
884
  section "4.33.4 SQL-statements and transaction states",
 
885
  SAVEPOINT is *not* transaction-initiating SQL-statement
 
886
*/
 
887
int ha_savepoint(Session *session, SAVEPOINT *sv)
 
888
{
 
889
  int error= 0;
 
890
  Session_TRANS *trans= &session->transaction.all;
 
891
  Ha_trx_info *ha_info= trans->ha_list;
 
892
  for (; ha_info; ha_info= ha_info->next())
 
893
  {
 
894
    int err;
 
895
    plugin::StorageEngine *engine= ha_info->engine();
 
896
    assert(engine);
 
897
#ifdef NOT_IMPLEMENTED /*- TODO (examine this againt the original code base) */
 
898
    if (! engine->savepoint_set)
 
899
    {
 
900
      my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "SAVEPOINT");
 
901
      error= 1;
 
902
      break;
 
903
    } 
 
904
#endif
 
905
    if ((err= engine->savepoint_set(session, (void *)(sv+1))))
 
906
    { // cannot happen
 
907
      my_error(ER_GET_ERRNO, MYF(0), err);
 
908
      error= 1;
 
909
    }
 
910
    status_var_increment(session->status_var.ha_savepoint_count);
 
911
  }
 
912
  /*
 
913
    Remember the list of registered storage engines. All new
 
914
    engines are prepended to the beginning of the list.
 
915
  */
 
916
  sv->ha_list= trans->ha_list;
 
917
  return error;
 
918
}
 
919
 
 
920
int ha_release_savepoint(Session *session, SAVEPOINT *sv)
 
921
{
 
922
  int error= 0;
 
923
  Ha_trx_info *ha_info= sv->ha_list;
 
924
 
 
925
  for (; ha_info; ha_info= ha_info->next())
 
926
  {
 
927
    int err;
 
928
    plugin::StorageEngine *engine= ha_info->engine();
 
929
    /* Savepoint life time is enclosed into transaction life time. */
 
930
    assert(engine);
 
931
    if ((err= engine->savepoint_release(session,
 
932
                                        (void *)(sv+1))))
 
933
    { // cannot happen
 
934
      my_error(ER_GET_ERRNO, MYF(0), err);
 
935
      error= 1;
 
936
    }
 
937
  }
 
938
  return error;
 
939
}
 
940
 
 
941
 
 
942
 
 
943
 
53
944
 
54
945
/****************************************************************************
55
946
** General Cursor functions
56
947
****************************************************************************/
57
 
Cursor::Cursor(plugin::StorageEngine &engine_arg,
58
 
               TableShare &share_arg)
59
 
  : table_share(&share_arg), table(0),
60
 
    estimation_rows_to_insert(0), engine(&engine_arg),
61
 
    ref(0), in_range_check_pushed_down(false),
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), implicit_emptied(0),
66
 
    next_insert_id(0), insert_id_for_cur_row(0)
67
 
{ }
68
 
 
69
948
Cursor::~Cursor(void)
70
949
{
71
950
  assert(locked == false);
73
952
}
74
953
 
75
954
 
76
 
Cursor *Cursor::clone(memory::Root *mem_root)
 
955
Cursor *Cursor::clone(MEM_ROOT *mem_root)
77
956
{
78
 
  Cursor *new_handler= table->s->db_type()->getCursor(*table->s, mem_root);
 
957
  Cursor *new_handler= table->s->db_type()->getCursor(table->s, mem_root);
79
958
 
80
959
  /*
81
960
    Allocate Cursor->ref here because otherwise ha_open will allocate it
131
1010
  return inited == INDEX ? ha_index_end() : inited == RND ? ha_rnd_end() : 0;
132
1011
}
133
1012
 
 
1013
Cursor::Table_flags Cursor::ha_table_flags() const
 
1014
{
 
1015
  return cached_table_flags;
 
1016
}
 
1017
 
134
1018
void Cursor::ha_start_bulk_insert(ha_rows rows)
135
1019
{
136
1020
  estimation_rows_to_insert= rows;
156
1040
 
157
1041
bool Cursor::has_transactions()
158
1042
{
159
 
  return (table->s->db_type()->check_flag(HTON_BIT_DOES_TRANSACTIONS));
 
1043
  return (ha_table_flags() & HA_NO_TRANSACTIONS) == 0;
160
1044
}
161
1045
 
162
 
void Cursor::ha_statistic_increment(ulong system_status_var::*offset) const
 
1046
void Cursor::ha_statistic_increment(ulong SSV::*offset) const
163
1047
{
164
1048
  status_var_increment(table->in_use->status_var.*offset);
165
1049
}
166
1050
 
167
1051
void **Cursor::ha_data(Session *session) const
168
1052
{
169
 
  return session->getEngineData(engine);
 
1053
  return session_ha_data(session, engine);
170
1054
}
171
1055
 
172
1056
Session *Cursor::ha_session(void) const
188
1072
 
189
1073
 
190
1074
ha_rows Cursor::records() { return stats.records; }
191
 
uint64_t Cursor::tableSize() { return stats.index_file_length + stats.data_file_length; }
192
 
uint64_t Cursor::rowSize() { return table->getRecordLength() + table->sizeFields(); }
193
1075
 
194
1076
/**
195
1077
  Open database-Cursor.
206
1088
  assert(table->s == table_share);
207
1089
  assert(alloc_root_inited(&table->mem_root));
208
1090
 
209
 
  if ((error=open(name, mode, test_if_locked)))
 
1091
  if ((error=open(name,mode,test_if_locked)))
210
1092
  {
211
1093
    if ((error == EACCES || error == EROFS) && mode == O_RDWR &&
212
 
        (table->db_stat & HA_TRY_READ_ONLY))
 
1094
        (table->db_stat & HA_TRY_READ_ONLY))
213
1095
    {
214
1096
      table->db_stat|=HA_READ_ONLY;
215
1097
      error=open(name,O_RDONLY,test_if_locked);
217
1099
  }
218
1100
  if (error)
219
1101
  {
220
 
    errno= error;                            /* Safeguard */
 
1102
    my_errno= error;                            /* Safeguard */
221
1103
  }
222
1104
  else
223
1105
  {
234
1116
    }
235
1117
    else
236
1118
      dup_ref=ref+ALIGN_SIZE(ref_length);
 
1119
    cached_table_flags= table_flags();
237
1120
  }
238
1121
  return error;
239
1122
}
268
1151
{
269
1152
  register int error;
270
1153
 
271
 
  ha_statistic_increment(&system_status_var::ha_read_first_count);
 
1154
  ha_statistic_increment(&SSV::ha_read_first_count);
272
1155
 
273
1156
  /*
274
1157
    If there is very few deleted rows in the table, find the first row by
276
1159
    TODO remove the test for HA_READ_ORDER
277
1160
  */
278
1161
  if (stats.deleted < 10 || primary_key >= MAX_KEY ||
279
 
      !(table->index_flags(primary_key) & HA_READ_ORDER))
 
1162
      !(index_flags(primary_key, 0, 0) & HA_READ_ORDER))
280
1163
  {
281
1164
    (void) ha_rnd_init(1);
282
1165
    while ((error= rnd_next(buf)) == HA_ERR_RECORD_DELETED) ;
599
1482
  @param first_value         (OUT) the first value reserved by the Cursor
600
1483
  @param nb_reserved_values  (OUT) how many values the Cursor reserved
601
1484
*/
 
1485
void Cursor::get_auto_increment(uint64_t ,
 
1486
                                 uint64_t ,
 
1487
                                 uint64_t ,
 
1488
                                 uint64_t *first_value,
 
1489
                                 uint64_t *nb_reserved_values)
 
1490
{
 
1491
  uint64_t nr;
 
1492
  int error;
 
1493
 
 
1494
  (void) extra(HA_EXTRA_KEYREAD);
 
1495
  table->mark_columns_used_by_index_no_reset(table->s->next_number_index);
 
1496
  index_init(table->s->next_number_index, 1);
 
1497
  if (table->s->next_number_keypart == 0)
 
1498
  {                                             // Autoincrement at key-start
 
1499
    error=index_last(table->record[1]);
 
1500
    /*
 
1501
      MySQL implicitely assumes such method does locking (as MySQL decides to
 
1502
      use nr+increment without checking again with the Cursor, in
 
1503
      Cursor::update_auto_increment()), so reserves to infinite.
 
1504
    */
 
1505
    *nb_reserved_values= UINT64_MAX;
 
1506
  }
 
1507
  else
 
1508
  {
 
1509
    unsigned char key[MAX_KEY_LENGTH];
 
1510
    key_copy(key, table->record[0],
 
1511
             table->key_info + table->s->next_number_index,
 
1512
             table->s->next_number_key_offset);
 
1513
    error= index_read_map(table->record[1], key,
 
1514
                          make_prev_keypart_map(table->s->next_number_keypart),
 
1515
                          HA_READ_PREFIX_LAST);
 
1516
    /*
 
1517
      MySQL needs to call us for next row: assume we are inserting ("a",null)
 
1518
      here, we return 3, and next this statement will want to insert
 
1519
      ("b",null): there is no reason why ("b",3+1) would be the good row to
 
1520
      insert: maybe it already exists, maybe 3+1 is too large...
 
1521
    */
 
1522
    *nb_reserved_values= 1;
 
1523
  }
 
1524
 
 
1525
  if (error)
 
1526
    nr=1;
 
1527
  else
 
1528
    nr= ((uint64_t) table->next_number_field->
 
1529
         val_int_offset(table->s->rec_buff_length)+1);
 
1530
  index_end();
 
1531
  (void) extra(HA_EXTRA_NO_KEYREAD);
 
1532
  *first_value= nr;
 
1533
}
 
1534
 
602
1535
 
603
1536
void Cursor::ha_release_auto_increment()
604
1537
{
616
1549
  }
617
1550
}
618
1551
 
 
1552
 
 
1553
void Cursor::print_keydup_error(uint32_t key_nr, const char *msg)
 
1554
{
 
1555
  /* Write the duplicated key in the error message */
 
1556
  char key[MAX_KEY_LENGTH];
 
1557
  String str(key,sizeof(key),system_charset_info);
 
1558
 
 
1559
  if (key_nr == MAX_KEY)
 
1560
  {
 
1561
    /* Key is unknown */
 
1562
    str.copy("", 0, system_charset_info);
 
1563
    my_printf_error(ER_DUP_ENTRY, msg, MYF(0), str.c_ptr(), "*UNKNOWN*");
 
1564
  }
 
1565
  else
 
1566
  {
 
1567
    /* Table is opened and defined at this point */
 
1568
    key_unpack(&str,table,(uint32_t) key_nr);
 
1569
    uint32_t max_length=DRIZZLE_ERRMSG_SIZE-(uint32_t) strlen(msg);
 
1570
    if (str.length() >= max_length)
 
1571
    {
 
1572
      str.length(max_length-4);
 
1573
      str.append(STRING_WITH_LEN("..."));
 
1574
    }
 
1575
    my_printf_error(ER_DUP_ENTRY, msg,
 
1576
                    MYF(0), str.c_ptr(), table->key_info[key_nr].name);
 
1577
  }
 
1578
}
 
1579
 
 
1580
 
 
1581
/**
 
1582
  Print error that we got from Cursor function.
 
1583
 
 
1584
  @note
 
1585
    In case of delete table it's only safe to use the following parts of
 
1586
    the 'table' structure:
 
1587
    - table->s->path
 
1588
    - table->alias
 
1589
*/
 
1590
void Cursor::print_error(int error, myf errflag)
 
1591
{
 
1592
  int textno=ER_GET_ERRNO;
 
1593
  switch (error) {
 
1594
  case EACCES:
 
1595
    textno=ER_OPEN_AS_READONLY;
 
1596
    break;
 
1597
  case EAGAIN:
 
1598
    textno=ER_FILE_USED;
 
1599
    break;
 
1600
  case ENOENT:
 
1601
    textno=ER_FILE_NOT_FOUND;
 
1602
    break;
 
1603
  case HA_ERR_KEY_NOT_FOUND:
 
1604
  case HA_ERR_NO_ACTIVE_RECORD:
 
1605
  case HA_ERR_END_OF_FILE:
 
1606
    textno=ER_KEY_NOT_FOUND;
 
1607
    break;
 
1608
  case HA_ERR_WRONG_MRG_TABLE_DEF:
 
1609
    textno=ER_WRONG_MRG_TABLE;
 
1610
    break;
 
1611
  case HA_ERR_FOUND_DUPP_KEY:
 
1612
  {
 
1613
    uint32_t key_nr=get_dup_key(error);
 
1614
    if ((int) key_nr >= 0)
 
1615
    {
 
1616
      print_keydup_error(key_nr, ER(ER_DUP_ENTRY_WITH_KEY_NAME));
 
1617
      return;
 
1618
    }
 
1619
    textno=ER_DUP_KEY;
 
1620
    break;
 
1621
  }
 
1622
  case HA_ERR_FOREIGN_DUPLICATE_KEY:
 
1623
  {
 
1624
    uint32_t key_nr= get_dup_key(error);
 
1625
    if ((int) key_nr >= 0)
 
1626
    {
 
1627
      uint32_t max_length;
 
1628
      /* Write the key in the error message */
 
1629
      char key[MAX_KEY_LENGTH];
 
1630
      String str(key,sizeof(key),system_charset_info);
 
1631
      /* Table is opened and defined at this point */
 
1632
      key_unpack(&str,table,(uint32_t) key_nr);
 
1633
      max_length= (DRIZZLE_ERRMSG_SIZE-
 
1634
                   (uint32_t) strlen(ER(ER_FOREIGN_DUPLICATE_KEY)));
 
1635
      if (str.length() >= max_length)
 
1636
      {
 
1637
        str.length(max_length-4);
 
1638
        str.append(STRING_WITH_LEN("..."));
 
1639
      }
 
1640
      my_error(ER_FOREIGN_DUPLICATE_KEY, MYF(0), table_share->table_name.str,
 
1641
        str.c_ptr(), key_nr+1);
 
1642
      return;
 
1643
    }
 
1644
    textno= ER_DUP_KEY;
 
1645
    break;
 
1646
  }
 
1647
  case HA_ERR_FOUND_DUPP_UNIQUE:
 
1648
    textno=ER_DUP_UNIQUE;
 
1649
    break;
 
1650
  case HA_ERR_RECORD_CHANGED:
 
1651
    textno=ER_CHECKREAD;
 
1652
    break;
 
1653
  case HA_ERR_CRASHED:
 
1654
    textno=ER_NOT_KEYFILE;
 
1655
    break;
 
1656
  case HA_ERR_WRONG_IN_RECORD:
 
1657
    textno= ER_CRASHED_ON_USAGE;
 
1658
    break;
 
1659
  case HA_ERR_CRASHED_ON_USAGE:
 
1660
    textno=ER_CRASHED_ON_USAGE;
 
1661
    break;
 
1662
  case HA_ERR_NOT_A_TABLE:
 
1663
    textno= error;
 
1664
    break;
 
1665
  case HA_ERR_CRASHED_ON_REPAIR:
 
1666
    textno=ER_CRASHED_ON_REPAIR;
 
1667
    break;
 
1668
  case HA_ERR_OUT_OF_MEM:
 
1669
    textno=ER_OUT_OF_RESOURCES;
 
1670
    break;
 
1671
  case HA_ERR_WRONG_COMMAND:
 
1672
    textno=ER_ILLEGAL_HA;
 
1673
    break;
 
1674
  case HA_ERR_OLD_FILE:
 
1675
    textno=ER_OLD_KEYFILE;
 
1676
    break;
 
1677
  case HA_ERR_UNSUPPORTED:
 
1678
    textno=ER_UNSUPPORTED_EXTENSION;
 
1679
    break;
 
1680
  case HA_ERR_RECORD_FILE_FULL:
 
1681
  case HA_ERR_INDEX_FILE_FULL:
 
1682
    textno=ER_RECORD_FILE_FULL;
 
1683
    break;
 
1684
  case HA_ERR_LOCK_WAIT_TIMEOUT:
 
1685
    textno=ER_LOCK_WAIT_TIMEOUT;
 
1686
    break;
 
1687
  case HA_ERR_LOCK_TABLE_FULL:
 
1688
    textno=ER_LOCK_TABLE_FULL;
 
1689
    break;
 
1690
  case HA_ERR_LOCK_DEADLOCK:
 
1691
    textno=ER_LOCK_DEADLOCK;
 
1692
    break;
 
1693
  case HA_ERR_READ_ONLY_TRANSACTION:
 
1694
    textno=ER_READ_ONLY_TRANSACTION;
 
1695
    break;
 
1696
  case HA_ERR_CANNOT_ADD_FOREIGN:
 
1697
    textno=ER_CANNOT_ADD_FOREIGN;
 
1698
    break;
 
1699
  case HA_ERR_ROW_IS_REFERENCED:
 
1700
  {
 
1701
    String str;
 
1702
    get_error_message(error, &str);
 
1703
    my_error(ER_ROW_IS_REFERENCED_2, MYF(0), str.c_ptr_safe());
 
1704
    return;
 
1705
  }
 
1706
  case HA_ERR_NO_REFERENCED_ROW:
 
1707
  {
 
1708
    String str;
 
1709
    get_error_message(error, &str);
 
1710
    my_error(ER_NO_REFERENCED_ROW_2, MYF(0), str.c_ptr_safe());
 
1711
    return;
 
1712
  }
 
1713
  case HA_ERR_TABLE_DEF_CHANGED:
 
1714
    textno=ER_TABLE_DEF_CHANGED;
 
1715
    break;
 
1716
  case HA_ERR_NO_SUCH_TABLE:
 
1717
    my_error(ER_NO_SUCH_TABLE, MYF(0), table_share->db.str,
 
1718
             table_share->table_name.str);
 
1719
    return;
 
1720
  case HA_ERR_RBR_LOGGING_FAILED:
 
1721
    textno= ER_BINLOG_ROW_LOGGING_FAILED;
 
1722
    break;
 
1723
  case HA_ERR_DROP_INDEX_FK:
 
1724
  {
 
1725
    const char *ptr= "???";
 
1726
    uint32_t key_nr= get_dup_key(error);
 
1727
    if ((int) key_nr >= 0)
 
1728
      ptr= table->key_info[key_nr].name;
 
1729
    my_error(ER_DROP_INDEX_FK, MYF(0), ptr);
 
1730
    return;
 
1731
  }
 
1732
  case HA_ERR_TABLE_NEEDS_UPGRADE:
 
1733
    textno=ER_TABLE_NEEDS_UPGRADE;
 
1734
    break;
 
1735
  case HA_ERR_TABLE_READONLY:
 
1736
    textno= ER_OPEN_AS_READONLY;
 
1737
    break;
 
1738
  case HA_ERR_AUTOINC_READ_FAILED:
 
1739
    textno= ER_AUTOINC_READ_FAILED;
 
1740
    break;
 
1741
  case HA_ERR_AUTOINC_ERANGE:
 
1742
    textno= ER_WARN_DATA_OUT_OF_RANGE;
 
1743
    break;
 
1744
  case HA_ERR_LOCK_OR_ACTIVE_TRANSACTION:
 
1745
    my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
 
1746
               ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
 
1747
    return;
 
1748
  default:
 
1749
    {
 
1750
      /* The error was "unknown" to this function.
 
1751
         Ask Cursor if it has got a message for this error */
 
1752
      bool temporary= false;
 
1753
      String str;
 
1754
      temporary= get_error_message(error, &str);
 
1755
      if (!str.is_empty())
 
1756
      {
 
1757
        const char* engine_name= engine->getName().c_str();
 
1758
        if (temporary)
 
1759
          my_error(ER_GET_TEMPORARY_ERRMSG, MYF(0), error, str.ptr(),
 
1760
                   engine_name);
 
1761
        else
 
1762
          my_error(ER_GET_ERRMSG, MYF(0), error, str.ptr(), engine_name);
 
1763
      }
 
1764
      else
 
1765
      {
 
1766
              my_error(ER_GET_ERRNO,errflag,error);
 
1767
      }
 
1768
      return;
 
1769
    }
 
1770
  }
 
1771
  my_error(textno, errflag, table_share->table_name.str, error);
 
1772
}
 
1773
 
 
1774
 
 
1775
/**
 
1776
  Return an error message specific to this Cursor.
 
1777
 
 
1778
  @param error  error code previously returned by Cursor
 
1779
  @param buf    pointer to String where to add error message
 
1780
 
 
1781
  @return
 
1782
    Returns true if this is a temporary error
 
1783
*/
 
1784
bool Cursor::get_error_message(int , String* )
 
1785
{
 
1786
  return false;
 
1787
}
 
1788
 
 
1789
 
 
1790
/* Code left, but Drizzle has no legacy yet (while MySQL did) */
 
1791
int Cursor::check_old_types()
 
1792
{
 
1793
  return 0;
 
1794
}
 
1795
 
 
1796
/**
 
1797
  @return
 
1798
    key if error because of duplicated keys
 
1799
*/
 
1800
uint32_t Cursor::get_dup_key(int error)
 
1801
{
 
1802
  table->file->errkey  = (uint32_t) -1;
 
1803
  if (error == HA_ERR_FOUND_DUPP_KEY || error == HA_ERR_FOREIGN_DUPLICATE_KEY ||
 
1804
      error == HA_ERR_FOUND_DUPP_UNIQUE ||
 
1805
      error == HA_ERR_DROP_INDEX_FK)
 
1806
    info(HA_STATUS_ERRKEY | HA_STATUS_NO_LOCK);
 
1807
  return(table->file->errkey);
 
1808
}
 
1809
 
619
1810
void Cursor::drop_table(const char *)
620
1811
{
621
1812
  close();
649
1840
 
650
1841
inline
651
1842
void
652
 
Cursor::setTransactionReadWrite()
 
1843
Cursor::mark_trx_read_write()
653
1844
{
654
 
  ResourceContext *resource_context= ha_session()->getResourceContext(engine);
 
1845
  Ha_trx_info *ha_info= &ha_session()->ha_data[engine->getSlot()].ha_info[0];
655
1846
  /*
656
1847
    When a storage engine method is called, the transaction must
657
1848
    have been started, unless it's a DDL call, for which the
660
1851
    Unfortunately here we can't know know for sure if the engine
661
1852
    has registered the transaction or not, so we must check.
662
1853
  */
663
 
  if (resource_context->isStarted())
 
1854
  if (ha_info->is_started())
664
1855
  {
665
 
    resource_context->markModifiedData();
 
1856
      ha_info->set_trx_read_write();
666
1857
  }
667
1858
}
668
1859
 
 
1860
/**
 
1861
  Bulk update row: public interface.
 
1862
 
 
1863
  @sa Cursor::bulk_update_row()
 
1864
*/
 
1865
 
 
1866
int
 
1867
Cursor::ha_bulk_update_row(const unsigned char *old_data, unsigned char *new_data,
 
1868
                            uint32_t *dup_key_found)
 
1869
{
 
1870
  mark_trx_read_write();
 
1871
 
 
1872
  return bulk_update_row(old_data, new_data, dup_key_found);
 
1873
}
 
1874
 
669
1875
 
670
1876
/**
671
1877
  Delete all rows: public interface.
672
1878
 
673
1879
  @sa Cursor::delete_all_rows()
674
 
 
675
 
  @note
676
 
 
677
 
  This is now equalivalent to TRUNCATE TABLE.
678
1880
*/
679
1881
 
680
1882
int
681
1883
Cursor::ha_delete_all_rows()
682
1884
{
683
 
  setTransactionReadWrite();
684
 
 
685
 
  int result= delete_all_rows();
686
 
 
687
 
  if (result == 0)
688
 
  {
689
 
    /** 
690
 
     * Trigger post-truncate notification to plugins... 
691
 
     *
692
 
     * @todo Make TransactionServices generic to AfterTriggerServices
693
 
     * or similar...
694
 
     */
695
 
    Session *const session= table->in_use;
696
 
    TransactionServices &transaction_services= TransactionServices::singleton();
697
 
    transaction_services.truncateTable(session, table);
698
 
  }
699
 
 
700
 
  return result;
 
1885
  mark_trx_read_write();
 
1886
 
 
1887
  return delete_all_rows();
701
1888
}
702
1889
 
703
1890
 
710
1897
int
711
1898
Cursor::ha_reset_auto_increment(uint64_t value)
712
1899
{
713
 
  setTransactionReadWrite();
 
1900
  mark_trx_read_write();
714
1901
 
715
1902
  return reset_auto_increment(value);
716
1903
}
717
1904
 
718
1905
 
719
1906
/**
 
1907
  Optimize table: public interface.
 
1908
 
 
1909
  @sa Cursor::optimize()
 
1910
*/
 
1911
 
 
1912
int
 
1913
Cursor::ha_optimize(Session* session, HA_CHECK_OPT* check_opt)
 
1914
{
 
1915
  mark_trx_read_write();
 
1916
 
 
1917
  return optimize(session, check_opt);
 
1918
}
 
1919
 
 
1920
 
 
1921
/**
720
1922
  Analyze table: public interface.
721
1923
 
722
1924
  @sa Cursor::analyze()
723
1925
*/
724
1926
 
725
1927
int
726
 
Cursor::ha_analyze(Session* session, HA_CHECK_OPT*)
 
1928
Cursor::ha_analyze(Session* session, HA_CHECK_OPT* check_opt)
727
1929
{
728
 
  setTransactionReadWrite();
 
1930
  mark_trx_read_write();
729
1931
 
730
 
  return analyze(session);
 
1932
  return analyze(session, check_opt);
731
1933
}
732
1934
 
733
1935
/**
739
1941
int
740
1942
Cursor::ha_disable_indexes(uint32_t mode)
741
1943
{
742
 
  setTransactionReadWrite();
 
1944
  mark_trx_read_write();
743
1945
 
744
1946
  return disable_indexes(mode);
745
1947
}
754
1956
int
755
1957
Cursor::ha_enable_indexes(uint32_t mode)
756
1958
{
757
 
  setTransactionReadWrite();
 
1959
  mark_trx_read_write();
758
1960
 
759
1961
  return enable_indexes(mode);
760
1962
}
769
1971
int
770
1972
Cursor::ha_discard_or_import_tablespace(bool discard)
771
1973
{
772
 
  setTransactionReadWrite();
 
1974
  mark_trx_read_write();
773
1975
 
774
1976
  return discard_or_import_tablespace(discard);
775
1977
}
783
1985
void
784
1986
Cursor::closeMarkForDelete(const char *name)
785
1987
{
786
 
  setTransactionReadWrite();
 
1988
  mark_trx_read_write();
787
1989
 
788
1990
  return drop_table(name);
789
1991
}
790
1992
 
 
1993
/**
 
1994
  Tell the storage engine that it is allowed to "disable transaction" in the
 
1995
  Cursor. It is a hint that ACID is not required - it is used in NDB for
 
1996
  ALTER Table, for example, when data are copied to temporary table.
 
1997
  A storage engine may treat this hint any way it likes. NDB for example
 
1998
  starts to commit every now and then automatically.
 
1999
  This hint can be safely ignored.
 
2000
*/
 
2001
int ha_enable_transaction(Session *session, bool on)
 
2002
{
 
2003
  int error= 0;
 
2004
 
 
2005
  if ((session->transaction.on= on))
 
2006
  {
 
2007
    /*
 
2008
      Now all storage engines should have transaction handling enabled.
 
2009
      But some may have it enabled all the time - "disabling" transactions
 
2010
      is an optimization hint that storage engine is free to ignore.
 
2011
      So, let's commit an open transaction (if any) now.
 
2012
    */
 
2013
    if (!(error= ha_commit_trans(session, 0)))
 
2014
      if (! session->endTransaction(COMMIT))
 
2015
        error= 1;
 
2016
 
 
2017
  }
 
2018
  return error;
 
2019
}
 
2020
 
791
2021
int Cursor::index_next_same(unsigned char *buf, const unsigned char *key, uint32_t keylen)
792
2022
{
793
2023
  int error;
912
2142
Cursor::multi_range_read_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
913
2143
                                     void *seq_init_param,
914
2144
                                     uint32_t ,
915
 
                                     uint32_t *bufsz, uint32_t *flags, optimizer::CostVector *cost)
 
2145
                                     uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
916
2146
{
917
2147
  KEY_MULTI_RANGE range;
918
2148
  range_seq_t seq_it;
955
2185
    /* The following calculation is the same as in multi_range_read_info(): */
956
2186
    *flags |= HA_MRR_USE_DEFAULT_IMPL;
957
2187
    cost->zero();
958
 
    cost->setAvgIOCost(1); /* assume random seeks */
 
2188
    cost->avg_io_cost= 1; /* assume random seeks */
959
2189
    if ((*flags & HA_MRR_INDEX_ONLY) && total_rows > 2)
960
 
      cost->setIOCount(index_only_read_time(keyno, (uint32_t)total_rows));
 
2190
      cost->io_count= index_only_read_time(keyno, (uint32_t)total_rows);
961
2191
    else
962
 
      cost->setIOCount(read_time(keyno, n_ranges, total_rows));
963
 
    cost->setCpuCost((double) total_rows / TIME_FOR_COMPARE + 0.01);
 
2192
      cost->io_count= read_time(keyno, n_ranges, total_rows);
 
2193
    cost->cpu_cost= (double) total_rows / TIME_FOR_COMPARE + 0.01;
964
2194
  }
965
2195
  return total_rows;
966
2196
}
1001
2231
*/
1002
2232
 
1003
2233
int Cursor::multi_range_read_info(uint32_t keyno, uint32_t n_ranges, uint32_t n_rows,
1004
 
                                   uint32_t *bufsz, uint32_t *flags, optimizer::CostVector *cost)
 
2234
                                   uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
1005
2235
{
1006
2236
  *bufsz= 0; /* Default implementation doesn't need a buffer */
1007
2237
 
1008
2238
  *flags |= HA_MRR_USE_DEFAULT_IMPL;
1009
2239
 
1010
2240
  cost->zero();
1011
 
  cost->setAvgIOCost(1); /* assume random seeks */
 
2241
  cost->avg_io_cost= 1; /* assume random seeks */
1012
2242
 
1013
2243
  /* Produce the same cost as non-MRR code does */
1014
2244
  if (*flags & HA_MRR_INDEX_ONLY)
1015
 
    cost->setIOCount(index_only_read_time(keyno, n_rows));
 
2245
    cost->io_count= index_only_read_time(keyno, n_rows);
1016
2246
  else
1017
 
    cost->setIOCount(read_time(keyno, n_ranges, n_rows));
 
2247
    cost->io_count= read_time(keyno, n_ranges, n_rows);
1018
2248
  return 0;
1019
2249
}
1020
2250
 
1289
2519
  Check if the conditions for row-based binlogging is correct for the table.
1290
2520
 
1291
2521
  A row in the given table should be replicated if:
 
2522
  - Row-based replication is enabled in the current thread
 
2523
  - The binlog is enabled
1292
2524
  - It is not a temporary table
 
2525
  - The binary log is open
 
2526
  - The database the table resides in shall be binlogged (binlog_*_db rules)
 
2527
  - table is not mysql.event
1293
2528
*/
1294
2529
 
1295
2530
static bool log_row_for_replication(Table* table,
1296
 
                                    const unsigned char *before_record,
1297
 
                                    const unsigned char *after_record)
 
2531
                           const unsigned char *before_record,
 
2532
                           const unsigned char *after_record)
1298
2533
{
1299
 
  TransactionServices &transaction_services= TransactionServices::singleton();
1300
2534
  ReplicationServices &replication_services= ReplicationServices::singleton();
1301
2535
  Session *const session= table->in_use;
1302
2536
 
1303
 
  if (table->s->tmp_table || not replication_services.isActive())
1304
 
    return false;
1305
 
 
1306
 
  bool result= false;
1307
 
 
1308
2537
  switch (session->lex->sql_command)
1309
2538
  {
1310
 
  case SQLCOM_CREATE_TABLE:
1311
 
    /*
1312
 
     * We are in a CREATE TABLE ... SELECT statement
1313
 
     * and the kernel has already created the table
1314
 
     * and put a CreateTableStatement in the active
1315
 
     * Transaction message.  Here, we add a new InsertRecord
1316
 
     * to a new Transaction message (because the above
1317
 
     * CREATE TABLE will commit the transaction containing
1318
 
     * it).
1319
 
     */
1320
 
    result= transaction_services.insertRecord(session, table);
1321
 
    break;
1322
2539
  case SQLCOM_REPLACE:
 
2540
  case SQLCOM_INSERT:
1323
2541
  case SQLCOM_REPLACE_SELECT:
1324
 
    /*
1325
 
     * This is a total hack because of the code that is
1326
 
     * in write_record() in sql_insert.cc. During
1327
 
     * a REPLACE statement, a call to ha_write_row() is
1328
 
     * called.  If it fails, then a call to ha_delete_row()
1329
 
     * is called, followed by a repeat of the original
1330
 
     * call to ha_write_row().  So, log_row_for_replication
1331
 
     * could be called either once or twice for a REPLACE
1332
 
     * statement.  The below looks at the values of before_record
1333
 
     * and after_record to determine which call to this
1334
 
     * function is for the delete or the insert, since NULL
1335
 
     * is passed for after_record for the delete and NULL is
1336
 
     * passed for before_record for the insert...
1337
 
     *
1338
 
     * In addition, there is an optimization that allows an
1339
 
     * engine to convert the above delete + insert into an
1340
 
     * update, so we must also check for this case below...
1341
 
     */
1342
 
    if (after_record == NULL)
1343
 
    {
1344
 
      transaction_services.deleteRecord(session, table);
1345
 
      /* 
1346
 
       * We set the "current" statement message to NULL.  This triggers
1347
 
       * the replication services component to generate a new statement
1348
 
       * message for the inserted record which will come next.
1349
 
       */
1350
 
      transaction_services.finalizeStatementMessage(*session->getStatementMessage(), session);
1351
 
    }
1352
 
    else
1353
 
    {
1354
 
      if (before_record == NULL)
1355
 
        result= transaction_services.insertRecord(session, table);
1356
 
      else
1357
 
        transaction_services.updateRecord(session, table, before_record, after_record);
1358
 
    }
1359
 
    break;
1360
 
  case SQLCOM_INSERT:
1361
2542
  case SQLCOM_INSERT_SELECT:
1362
 
    /*
1363
 
     * The else block below represents an 
1364
 
     * INSERT ... ON DUPLICATE KEY UPDATE that
1365
 
     * has hit a key conflict and actually done
1366
 
     * an update.
1367
 
     */
1368
 
    if (before_record == NULL)
1369
 
      result= transaction_services.insertRecord(session, table);
1370
 
    else
1371
 
      transaction_services.updateRecord(session, table, before_record, after_record);
 
2543
  case SQLCOM_CREATE_TABLE:
 
2544
    replication_services.insertRecord(session, table);
1372
2545
    break;
1373
2546
 
1374
2547
  case SQLCOM_UPDATE:
1375
 
    transaction_services.updateRecord(session, table, before_record, after_record);
 
2548
    replication_services.updateRecord(session, table, before_record, after_record);
1376
2549
    break;
1377
2550
 
1378
2551
  case SQLCOM_DELETE:
1379
 
    transaction_services.deleteRecord(session, table);
 
2552
    replication_services.deleteRecord(session, table);
1380
2553
    break;
 
2554
 
 
2555
    /*
 
2556
      For everything else we ignore the event (since it just involves a temp table)
 
2557
    */
1381
2558
  default:
1382
2559
    break;
1383
2560
  }
1384
2561
 
1385
 
  return result;
 
2562
  return false; //error;
1386
2563
}
1387
2564
 
1388
2565
int Cursor::ha_external_lock(Session *session, int lock_type)
1394
2571
  */
1395
2572
  assert(next_insert_id == 0);
1396
2573
 
1397
 
  if (DRIZZLE_CURSOR_RDLOCK_START_ENABLED() ||
1398
 
      DRIZZLE_CURSOR_WRLOCK_START_ENABLED() ||
1399
 
      DRIZZLE_CURSOR_UNLOCK_START_ENABLED())
1400
 
  {
1401
 
    if (lock_type == F_RDLCK)
1402
 
    {
1403
 
      DRIZZLE_CURSOR_RDLOCK_START(table_share->getSchemaName(),
1404
 
                                  table_share->getTableName());
1405
 
    }
1406
 
    else if (lock_type == F_WRLCK)
1407
 
    {
1408
 
      DRIZZLE_CURSOR_WRLOCK_START(table_share->getSchemaName(),
1409
 
                                  table_share->getTableName());
1410
 
    }
1411
 
    else if (lock_type == F_UNLCK)
1412
 
    {
1413
 
      DRIZZLE_CURSOR_UNLOCK_START(table_share->getSchemaName(),
1414
 
                                  table_share->getTableName());
1415
 
    }
1416
 
  }
1417
 
 
1418
2574
  /*
1419
2575
    We cache the table flags if the locking succeeded. Otherwise, we
1420
2576
    keep them as they were when they were fetched in ha_open().
1422
2578
 
1423
2579
  int error= external_lock(session, lock_type);
1424
2580
 
1425
 
  if (DRIZZLE_CURSOR_RDLOCK_DONE_ENABLED() ||
1426
 
      DRIZZLE_CURSOR_WRLOCK_DONE_ENABLED() ||
1427
 
      DRIZZLE_CURSOR_UNLOCK_DONE_ENABLED())
1428
 
  {
1429
 
    if (lock_type == F_RDLCK)
1430
 
    {
1431
 
      DRIZZLE_CURSOR_RDLOCK_DONE(error);
1432
 
    }
1433
 
    else if (lock_type == F_WRLCK)
1434
 
    {
1435
 
      DRIZZLE_CURSOR_WRLOCK_DONE(error);
1436
 
    }
1437
 
    else if (lock_type == F_UNLCK)
1438
 
    {
1439
 
      DRIZZLE_CURSOR_UNLOCK_DONE(error);
1440
 
    }
1441
 
  }
1442
 
 
 
2581
  if (error == 0)
 
2582
    cached_table_flags= table_flags();
1443
2583
  return error;
1444
2584
}
1445
2585
 
1469
2609
{
1470
2610
  int error;
1471
2611
 
1472
 
  /*
1473
 
   * If we have a timestamp column, update it to the current time
1474
 
   *
 
2612
  /* 
 
2613
   * If we have a timestamp column, update it to the current time 
 
2614
   * 
1475
2615
   * @TODO Technically, the below two lines can be take even further out of the
1476
2616
   * Cursor interface and into the fill_record() method.
1477
2617
   */
1478
2618
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
1479
2619
    table->timestamp_field->set_time();
1480
2620
 
1481
 
  DRIZZLE_INSERT_ROW_START(table_share->getSchemaName(), table_share->getTableName());
1482
 
  setTransactionReadWrite();
1483
 
  error= write_row(buf);
1484
 
  DRIZZLE_INSERT_ROW_DONE(error);
 
2621
  mark_trx_read_write();
1485
2622
 
1486
 
  if (unlikely(error))
 
2623
  if (unlikely(error= write_row(buf)))
1487
2624
  {
1488
2625
    return error;
1489
2626
  }
1490
2627
 
1491
 
  if (unlikely(log_row_for_replication(table, NULL, buf)))
 
2628
  if (unlikely(log_row_for_replication(table, 0, buf)))
1492
2629
    return HA_ERR_RBR_LOGGING_FAILED;
1493
2630
 
1494
2631
  return 0;
1505
2642
   */
1506
2643
  assert(new_data == table->record[0]);
1507
2644
 
1508
 
  DRIZZLE_UPDATE_ROW_START(table_share->getSchemaName(), table_share->getTableName());
1509
 
  setTransactionReadWrite();
1510
 
  error= update_row(old_data, new_data);
1511
 
  DRIZZLE_UPDATE_ROW_DONE(error);
 
2645
  mark_trx_read_write();
1512
2646
 
1513
 
  if (unlikely(error))
 
2647
  if (unlikely(error= update_row(old_data, new_data)))
1514
2648
  {
1515
2649
    return error;
1516
2650
  }
1525
2659
{
1526
2660
  int error;
1527
2661
 
1528
 
  DRIZZLE_DELETE_ROW_START(table_share->getSchemaName(), table_share->getTableName());
1529
 
  setTransactionReadWrite();
1530
 
  error= delete_row(buf);
1531
 
  DRIZZLE_DELETE_ROW_DONE(error);
 
2662
  mark_trx_read_write();
1532
2663
 
1533
 
  if (unlikely(error))
 
2664
  if (unlikely(error= delete_row(buf)))
1534
2665
    return error;
1535
2666
 
1536
 
  if (unlikely(log_row_for_replication(table, buf, NULL)))
 
2667
  if (unlikely(log_row_for_replication(table, buf, 0)))
1537
2668
    return HA_ERR_RBR_LOGGING_FAILED;
1538
2669
 
1539
2670
  return 0;
1540
2671
}
1541
 
 
1542
 
} /* namespace drizzled */