~drizzle-trunk/drizzle/development

575.1.5 by Monty Taylor
Moved stuff to handlerton.cc
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 *
4
 *  Copyright (C) 2008 Sun Microsystems
5
 *
6
 *  This program is free software; you can redistribute it and/or modify
7
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation; version 2 of the License.
9
 *
10
 *  This program is distributed in the hope that it will be useful,
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 *  GNU General Public License for more details.
14
 *
15
 *  You should have received a copy of the GNU General Public License
16
 *  along with this program; if not, write to the Free Software
17
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
 */
1 by brian
clean slate
19
20
/**
21
  @file handler.cc
22
23
  Handler-calling-functions
24
*/
25
873.1.17 by Jay Pipes
Fix for incomplete class definition in handler.cc. Forgot to commit it
26
#include "drizzled/server_includes.h"
27
#include "mysys/hash.h"
28
#include "drizzled/error.h"
29
#include "drizzled/gettext.h"
30
#include "drizzled/data_home.h"
31
#include "drizzled/probes.h"
32
#include "drizzled/sql_parse.h"
33
#include "drizzled/cost_vect.h"
34
#include "drizzled/session.h"
35
#include "drizzled/sql_base.h"
988.1.6 by Jay Pipes
Removed old protobuf_replicator plugin, fixed up db.cc and other files to use new
36
#include "drizzled/transaction_services.h"
873.1.17 by Jay Pipes
Fix for incomplete class definition in handler.cc. Forgot to commit it
37
#include "drizzled/lock.h"
38
#include "drizzled/item/int.h"
39
#include "drizzled/item/empty_string.h"
40
#include "drizzled/unireg.h" // for mysql_frm_type
41
#include "drizzled/field/timestamp.h"
988.1.1 by Jay Pipes
Changes libserialize to libdrizzledmessage per ML discussion. All GPB messages are now in the drizzled::message namespace.
42
#include "drizzled/message/table.pb.h"
572.1.4 by Monty Taylor
Removed a bunch of unusued tests and defines from autoconf.
43
919.2.14 by Monty Taylor
Use math.h instead of cmath... one of these days...
44
using namespace std;
1 by brian
clean slate
45
988.1.6 by Jay Pipes
Removed old protobuf_replicator plugin, fixed up db.cc and other files to use new
46
extern drizzled::TransactionServices transaction_services;
47
461 by Monty Taylor
Removed NullS. bu-bye.
48
KEY_CREATE_INFO default_key_create_info= { HA_KEY_ALG_UNDEF, 0, {NULL,0}, {NULL,0} };
1 by brian
clean slate
49
960.2.39 by Monty Taylor
Removed more handlerton naming references.
50
/* number of entries in storage_engines[] */
61 by Brian Aker
Conversion of handler type.
51
uint32_t total_ha= 0;
960.2.39 by Monty Taylor
Removed more handlerton naming references.
52
/* number of storage engines (from storage_engines[]) that support 2pc */
61 by Brian Aker
Conversion of handler type.
53
uint32_t total_ha_2pc= 0;
1 by brian
clean slate
54
/* size of savepoint storage area (see ha_init) */
61 by Brian Aker
Conversion of handler type.
55
uint32_t savepoint_alloc_size= 0;
1 by brian
clean slate
56
57
const char *ha_row_type[] = {
58
  "", "FIXED", "DYNAMIC", "COMPRESSED", "REDUNDANT", "COMPACT", "PAGE", "?","?","?"
59
};
60
61
const char *tx_isolation_names[] =
62
{ "READ-UNCOMMITTED", "READ-COMMITTED", "REPEATABLE-READ", "SERIALIZABLE",
461 by Monty Taylor
Removed NullS. bu-bye.
63
  NULL};
575.1.3 by Monty Taylor
Moved some stuff out of handler.h.
64
1 by brian
clean slate
65
TYPELIB tx_isolation_typelib= {array_elements(tx_isolation_names)-1,"",
575.1.3 by Monty Taylor
Moved some stuff out of handler.h.
66
                               tx_isolation_names, NULL};
1 by brian
clean slate
67
68
69
/**
70
  Register handler error messages for use with my_error().
71
72
  @retval
73
    0           OK
74
  @retval
75
    !=0         Error
76
*/
77
78
int ha_init_errors(void)
79
{
80
#define SETMSG(nr, msg) errmsgs[(nr) - HA_ERR_FIRST]= (msg)
81
  const char    **errmsgs;
82
83
  /* Allocate a pointer array for the error message strings. */
84
  /* Zerofill it to avoid uninitialized gaps. */
641.3.8 by Monty Taylor
Removed my_malloc from drizzled.
85
  if (! (errmsgs= (const char**) malloc(HA_ERR_ERRORS * sizeof(char*))))
1 by brian
clean slate
86
    return 1;
641.3.9 by Monty Taylor
More removal of my_malloc.
87
  memset(errmsgs, 0, HA_ERR_ERRORS * sizeof(char *));
1 by brian
clean slate
88
89
  /* Set the dedicated error messages. */
90
  SETMSG(HA_ERR_KEY_NOT_FOUND,          ER(ER_KEY_NOT_FOUND));
91
  SETMSG(HA_ERR_FOUND_DUPP_KEY,         ER(ER_DUP_KEY));
92
  SETMSG(HA_ERR_RECORD_CHANGED,         "Update wich is recoverable");
93
  SETMSG(HA_ERR_WRONG_INDEX,            "Wrong index given to function");
94
  SETMSG(HA_ERR_CRASHED,                ER(ER_NOT_KEYFILE));
95
  SETMSG(HA_ERR_WRONG_IN_RECORD,        ER(ER_CRASHED_ON_USAGE));
96
  SETMSG(HA_ERR_OUT_OF_MEM,             "Table handler out of memory");
97
  SETMSG(HA_ERR_NOT_A_TABLE,            "Incorrect file format '%.64s'");
98
  SETMSG(HA_ERR_WRONG_COMMAND,          "Command not supported");
99
  SETMSG(HA_ERR_OLD_FILE,               ER(ER_OLD_KEYFILE));
100
  SETMSG(HA_ERR_NO_ACTIVE_RECORD,       "No record read in update");
101
  SETMSG(HA_ERR_RECORD_DELETED,         "Intern record deleted");
102
  SETMSG(HA_ERR_RECORD_FILE_FULL,       ER(ER_RECORD_FILE_FULL));
103
  SETMSG(HA_ERR_INDEX_FILE_FULL,        "No more room in index file '%.64s'");
104
  SETMSG(HA_ERR_END_OF_FILE,            "End in next/prev/first/last");
105
  SETMSG(HA_ERR_UNSUPPORTED,            ER(ER_ILLEGAL_HA));
106
  SETMSG(HA_ERR_TO_BIG_ROW,             "Too big row");
107
  SETMSG(HA_WRONG_CREATE_OPTION,        "Wrong create option");
108
  SETMSG(HA_ERR_FOUND_DUPP_UNIQUE,      ER(ER_DUP_UNIQUE));
109
  SETMSG(HA_ERR_UNKNOWN_CHARSET,        "Can't open charset");
110
  SETMSG(HA_ERR_WRONG_MRG_TABLE_DEF,    ER(ER_WRONG_MRG_TABLE));
111
  SETMSG(HA_ERR_CRASHED_ON_REPAIR,      ER(ER_CRASHED_ON_REPAIR));
112
  SETMSG(HA_ERR_CRASHED_ON_USAGE,       ER(ER_CRASHED_ON_USAGE));
113
  SETMSG(HA_ERR_LOCK_WAIT_TIMEOUT,      ER(ER_LOCK_WAIT_TIMEOUT));
114
  SETMSG(HA_ERR_LOCK_TABLE_FULL,        ER(ER_LOCK_TABLE_FULL));
115
  SETMSG(HA_ERR_READ_ONLY_TRANSACTION,  ER(ER_READ_ONLY_TRANSACTION));
116
  SETMSG(HA_ERR_LOCK_DEADLOCK,          ER(ER_LOCK_DEADLOCK));
117
  SETMSG(HA_ERR_CANNOT_ADD_FOREIGN,     ER(ER_CANNOT_ADD_FOREIGN));
118
  SETMSG(HA_ERR_NO_REFERENCED_ROW,      ER(ER_NO_REFERENCED_ROW_2));
119
  SETMSG(HA_ERR_ROW_IS_REFERENCED,      ER(ER_ROW_IS_REFERENCED_2));
120
  SETMSG(HA_ERR_NO_SAVEPOINT,           "No savepoint with that name");
121
  SETMSG(HA_ERR_NON_UNIQUE_BLOCK_SIZE,  "Non unique key block size");
122
  SETMSG(HA_ERR_NO_SUCH_TABLE,          "No such table: '%.64s'");
123
  SETMSG(HA_ERR_TABLE_EXIST,            ER(ER_TABLE_EXISTS_ERROR));
124
  SETMSG(HA_ERR_NO_CONNECTION,          "Could not connect to storage engine");
125
  SETMSG(HA_ERR_TABLE_DEF_CHANGED,      ER(ER_TABLE_DEF_CHANGED));
126
  SETMSG(HA_ERR_FOREIGN_DUPLICATE_KEY,  "FK constraint would lead to duplicate key");
127
  SETMSG(HA_ERR_TABLE_NEEDS_UPGRADE,    ER(ER_TABLE_NEEDS_UPGRADE));
128
  SETMSG(HA_ERR_TABLE_READONLY,         ER(ER_OPEN_AS_READONLY));
129
  SETMSG(HA_ERR_AUTOINC_READ_FAILED,    ER(ER_AUTOINC_READ_FAILED));
130
  SETMSG(HA_ERR_AUTOINC_ERANGE,         ER(ER_WARN_DATA_OUT_OF_RANGE));
131
132
  /* Register the error messages for use with my_error(). */
133
  return my_error_register(errmsgs, HA_ERR_FIRST, HA_ERR_LAST);
134
}
135
136
137
/**
138
  Unregister handler error messages.
139
140
  @retval
141
    0           OK
142
  @retval
143
    !=0         Error
144
*/
145
static int ha_finish_errors(void)
146
{
147
  const char    **errmsgs;
148
149
  /* Allocate a pointer array for the error message strings. */
150
  if (! (errmsgs= my_error_unregister(HA_ERR_FIRST, HA_ERR_LAST)))
151
    return 1;
481 by Brian Aker
Remove all of uchar.
152
  free((unsigned char*) errmsgs);
1 by brian
clean slate
153
  return 0;
154
}
155
156
int ha_init()
157
{
158
  int error= 0;
159
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
160
  assert(total_ha < MAX_HA);
1 by brian
clean slate
161
  /*
162
    Check if there is a transaction-capable storage engine besides the
163
    binary log (which is considered a transaction-capable storage engine in
164
    counting total_ha)
165
  */
166
  savepoint_alloc_size+= sizeof(SAVEPOINT);
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
167
  return(error);
1 by brian
clean slate
168
}
169
170
int ha_end()
171
{
172
  int error= 0;
173
575.1.3 by Monty Taylor
Moved some stuff out of handler.h.
174
  /*
1 by brian
clean slate
175
    This should be eventualy based  on the graceful shutdown flag.
176
    So if flag is equal to HA_PANIC_CLOSE, the deallocate
177
    the errors.
178
  */
179
  if (ha_finish_errors())
180
    error= 1;
181
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
182
  return(error);
1 by brian
clean slate
183
}
184
185
186
187
/* ========================================================================
188
 ======================= TRANSACTIONS ===================================*/
189
190
/**
191
  Transaction handling in the server
192
  ==================================
193
194
  In each client connection, MySQL maintains two transactional
195
  states:
196
  - a statement transaction,
197
  - a standard, also called normal transaction.
198
199
  Historical note
200
  ---------------
201
  "Statement transaction" is a non-standard term that comes
202
  from the times when MySQL supported BerkeleyDB storage engine.
203
204
  First of all, it should be said that in BerkeleyDB auto-commit
205
  mode auto-commits operations that are atomic to the storage
206
  engine itself, such as a write of a record, and are too
207
  high-granular to be atomic from the application perspective
208
  (MySQL). One SQL statement could involve many BerkeleyDB
209
  auto-committed operations and thus BerkeleyDB auto-commit was of
210
  little use to MySQL.
211
212
  Secondly, instead of SQL standard savepoints, BerkeleyDB
213
  provided the concept of "nested transactions". In a nutshell,
214
  transactions could be arbitrarily nested, but when the parent
215
  transaction was committed or aborted, all its child (nested)
216
  transactions were handled committed or aborted as well.
217
  Commit of a nested transaction, in turn, made its changes
218
  visible, but not durable: it destroyed the nested transaction,
219
  all its changes would become available to the parent and
220
  currently active nested transactions of this parent.
221
222
  So the mechanism of nested transactions was employed to
223
  provide "all or nothing" guarantee of SQL statements
224
  required by the standard.
225
  A nested transaction would be created at start of each SQL
226
  statement, and destroyed (committed or aborted) at statement
227
  end. Such nested transaction was internally referred to as
228
  a "statement transaction" and gave birth to the term.
229
230
  <Historical note ends>
231
232
  Since then a statement transaction is started for each statement
233
  that accesses transactional tables or uses the binary log.  If
234
  the statement succeeds, the statement transaction is committed.
235
  If the statement fails, the transaction is rolled back. Commits
236
  of statement transactions are not durable -- each such
237
  transaction is nested in the normal transaction, and if the
238
  normal transaction is rolled back, the effects of all enclosed
239
  statement transactions are undone as well.  Technically,
240
  a statement transaction can be viewed as a savepoint which is
241
  maintained automatically in order to make effects of one
242
  statement atomic.
243
244
  The normal transaction is started by the user and is ended
245
  usually upon a user request as well. The normal transaction
246
  encloses transactions of all statements issued between
247
  its beginning and its end.
248
  In autocommit mode, the normal transaction is equivalent
249
  to the statement transaction.
250
251
  Since MySQL supports PSEA (pluggable storage engine
252
  architecture), more than one transactional engine can be
253
  active at a time. Hence transactions, from the server
254
  point of view, are always distributed. In particular,
255
  transactional state is maintained independently for each
256
  engine. In order to commit a transaction the two phase
257
  commit protocol is employed.
258
259
  Not all statements are executed in context of a transaction.
260
  Administrative and status information statements do not modify
261
  engine data, and thus do not start a statement transaction and
262
  also have no effect on the normal transaction. Examples of such
263
  statements are SHOW STATUS and RESET SLAVE.
264
265
  Similarly DDL statements are not transactional,
266
  and therefore a transaction is [almost] never started for a DDL
267
  statement. The difference between a DDL statement and a purely
268
  administrative statement though is that a DDL statement always
269
  commits the current transaction before proceeding, if there is
270
  any.
271
272
  At last, SQL statements that work with non-transactional
273
  engines also have no effect on the transaction state of the
274
  connection. Even though they are written to the binary log,
275
  and the binary log is, overall, transactional, the writes
276
  are done in "write-through" mode, directly to the binlog
277
  file, followed with a OS cache sync, in other words,
278
  bypassing the binlog undo log (translog).
279
  They do not commit the current normal transaction.
280
  A failure of a statement that uses non-transactional tables
281
  would cause a rollback of the statement transaction, but
282
  in case there no non-transactional tables are used,
283
  no statement transaction is started.
284
285
  Data layout
286
  -----------
287
288
  The server stores its transaction-related data in
520.1.22 by Brian Aker
Second pass of thd cleanup
289
  session->transaction. This structure has two members of type
520.1.21 by Brian Aker
THD -> Session rename
290
  Session_TRANS. These members correspond to the statement and
1 by brian
clean slate
291
  normal transactions respectively:
292
520.1.22 by Brian Aker
Second pass of thd cleanup
293
  - session->transaction.stmt contains a list of engines
1 by brian
clean slate
294
  that are participating in the given statement
520.1.22 by Brian Aker
Second pass of thd cleanup
295
  - session->transaction.all contains a list of engines that
1 by brian
clean slate
296
  have participated in any of the statement transactions started
297
  within the context of the normal transaction.
298
  Each element of the list contains a pointer to the storage
299
  engine, engine-specific transactional data, and engine-specific
300
  transaction flags.
301
520.1.22 by Brian Aker
Second pass of thd cleanup
302
  In autocommit mode session->transaction.all is empty.
303
  Instead, data of session->transaction.stmt is
1 by brian
clean slate
304
  used to commit/rollback the normal transaction.
305
306
  The list of registered engines has a few important properties:
307
  - no engine is registered in the list twice
308
  - engines are present in the list a reverse temporal order --
309
  new participants are always added to the beginning of the list.
310
311
  Transaction life cycle
312
  ----------------------
313
520.1.22 by Brian Aker
Second pass of thd cleanup
314
  When a new connection is established, session->transaction
1 by brian
clean slate
315
  members are initialized to an empty state.
316
  If a statement uses any tables, all affected engines
317
  are registered in the statement engine list. In
318
  non-autocommit mode, the same engines are registered in
319
  the normal transaction list.
320
  At the end of the statement, the server issues a commit
321
  or a roll back for all engines in the statement list.
322
  At this point transaction flags of an engine, if any, are
323
  propagated from the statement list to the list of the normal
324
  transaction.
325
  When commit/rollback is finished, the statement list is
326
  cleared. It will be filled in again by the next statement,
327
  and emptied again at the next statement's end.
328
329
  The normal transaction is committed in a similar way
520.1.22 by Brian Aker
Second pass of thd cleanup
330
  (by going over all engines in session->transaction.all list)
1 by brian
clean slate
331
  but at different times:
332
  - upon COMMIT SQL statement is issued by the user
333
  - implicitly, by the server, at the beginning of a DDL statement
334
  or SET AUTOCOMMIT={0|1} statement.
335
336
  The normal transaction can be rolled back as well:
337
  - if the user has requested so, by issuing ROLLBACK SQL
338
  statement
339
  - if one of the storage engines requested a rollback
520.1.22 by Brian Aker
Second pass of thd cleanup
340
  by setting session->transaction_rollback_request. This may
1 by brian
clean slate
341
  happen in case, e.g., when the transaction in the engine was
342
  chosen a victim of the internal deadlock resolution algorithm
343
  and rolled back internally. When such a situation happens, there
344
  is little the server can do and the only option is to rollback
345
  transactions in all other participating engines.  In this case
346
  the rollback is accompanied by an error sent to the user.
347
348
  As follows from the use cases above, the normal transaction
349
  is never committed when there is an outstanding statement
350
  transaction. In most cases there is no conflict, since
351
  commits of the normal transaction are issued by a stand-alone
352
  administrative or DDL statement, thus no outstanding statement
353
  transaction of the previous statement exists. Besides,
354
  all statements that manipulate with the normal transaction
355
  are prohibited in stored functions and triggers, therefore
356
  no conflicting situation can occur in a sub-statement either.
357
  The remaining rare cases when the server explicitly has
358
  to commit the statement transaction prior to committing the normal
359
  one cover error-handling scenarios (see for example
360
  SQLCOM_LOCK_TABLES).
361
362
  When committing a statement or a normal transaction, the server
363
  either uses the two-phase commit protocol, or issues a commit
364
  in each engine independently. The two-phase commit protocol
365
  is used only if:
366
  - all participating engines support two-phase commit (provide
960.2.24 by Monty Taylor
Changed handlerton to StorageEngine.
367
    StorageEngine::prepare PSEA API call) and
1 by brian
clean slate
368
  - transactions in at least two engines modify data (i.e. are
369
  not read-only).
370
371
  Note that the two phase commit is used for
372
  statement transactions, even though they are not durable anyway.
373
  This is done to ensure logical consistency of data in a multiple-
374
  engine transaction.
375
  For example, imagine that some day MySQL supports unique
376
  constraint checks deferred till the end of statement. In such
377
  case a commit in one of the engines may yield ER_DUP_KEY,
378
  and MySQL should be able to gracefully abort statement
379
  transactions of other participants.
380
381
  After the normal transaction has been committed,
520.1.22 by Brian Aker
Second pass of thd cleanup
382
  session->transaction.all list is cleared.
1 by brian
clean slate
383
384
  When a connection is closed, the current normal transaction, if
385
  any, is rolled back.
386
387
  Roles and responsibilities
388
  --------------------------
389
390
  The server has no way to know that an engine participates in
391
  the statement and a transaction has been started
392
  in it unless the engine says so. Thus, in order to be
393
  a part of a transaction, the engine must "register" itself.
394
  This is done by invoking trans_register_ha() server call.
395
  Normally the engine registers itself whenever handler::external_lock()
396
  is called. trans_register_ha() can be invoked many times: if
397
  an engine is already registered, the call does nothing.
398
  In case autocommit is not set, the engine must register itself
399
  twice -- both in the statement list and in the normal transaction
400
  list.
401
  In which list to register is a parameter of trans_register_ha().
402
403
  Note, that although the registration interface in itself is
404
  fairly clear, the current usage practice often leads to undesired
405
  effects. E.g. since a call to trans_register_ha() in most engines
406
  is embedded into implementation of handler::external_lock(), some
407
  DDL statements start a transaction (at least from the server
408
  point of view) even though they are not expected to. E.g.
409
  CREATE TABLE does not start a transaction, since
410
  handler::external_lock() is never called during CREATE TABLE. But
411
  CREATE TABLE ... SELECT does, since handler::external_lock() is
412
  called for the table that is being selected from. This has no
413
  practical effects currently, but must be kept in mind
414
  nevertheless.
415
416
  Once an engine is registered, the server will do the rest
417
  of the work.
418
419
  During statement execution, whenever any of data-modifying
420
  PSEA API methods is used, e.g. handler::write_row() or
421
  handler::update_row(), the read-write flag is raised in the
422
  statement transaction for the involved engine.
423
  Currently All PSEA calls are "traced", and the data can not be
424
  changed in a way other than issuing a PSEA call. Important:
425
  unless this invariant is preserved the server will not know that
426
  a transaction in a given engine is read-write and will not
427
  involve the two-phase commit protocol!
428
429
  At the end of a statement, server call
430
  ha_autocommit_or_rollback() is invoked. This call in turn
960.2.24 by Monty Taylor
Changed handlerton to StorageEngine.
431
  invokes StorageEngine::prepare() for every involved engine.
432
  Prepare is followed by a call to StorageEngine::commit_one_phase()
433
  If a one-phase commit will suffice, StorageEngine::prepare() is not
434
  invoked and the server only calls StorageEngine::commit_one_phase().
1 by brian
clean slate
435
  At statement commit, the statement-related read-write engine
436
  flag is propagated to the corresponding flag in the normal
437
  transaction.  When the commit is complete, the list of registered
438
  engines is cleared.
439
440
  Rollback is handled in a similar fashion.
441
442
  Additional notes on DDL and the normal transaction.
443
  ---------------------------------------------------
444
445
  DDLs and operations with non-transactional engines
520.1.22 by Brian Aker
Second pass of thd cleanup
446
  do not "register" in session->transaction lists, and thus do not
1 by brian
clean slate
447
  modify the transaction state. Besides, each DDL in
448
  MySQL is prefixed with an implicit normal transaction commit
934.2.11 by Jay Pipes
Moves end_trans(), begin_trans(), end_active_trans() out of the parser module and adds startTransaction(), endTransaction(), and endActiveTransaction() member methods of Session object.
449
  (a call to Session::endActiveTransaction()), and thus leaves nothing
1 by brian
clean slate
450
  to modify.
451
  However, as it has been pointed out with CREATE TABLE .. SELECT,
452
  some DDL statements can start a *new* transaction.
453
454
  Behaviour of the server in this case is currently badly
455
  defined.
456
  DDL statements use a form of "semantic" logging
457
  to maintain atomicity: if CREATE TABLE .. SELECT failed,
458
  the newly created table is deleted.
459
  In addition, some DDL statements issue interim transaction
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
460
  commits: e.g. ALTER Table issues a commit after data is copied
1 by brian
clean slate
461
  from the original table to the internal temporary table. Other
462
  statements, e.g. CREATE TABLE ... SELECT do not always commit
463
  after itself.
464
  And finally there is a group of DDL statements such as
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
465
  RENAME/DROP Table that doesn't start a new transaction
1 by brian
clean slate
466
  and doesn't commit.
467
468
  This diversity makes it hard to say what will happen if
469
  by chance a stored function is invoked during a DDL --
470
  whether any modifications it makes will be committed or not
471
  is not clear. Fortunately, SQL grammar of few DDLs allows
472
  invocation of a stored function.
473
474
  A consistent behaviour is perhaps to always commit the normal
475
  transaction after all DDLs, just like the statement transaction
476
  is always committed at the end of all statements.
477
*/
478
479
/**
480
  Register a storage engine for a transaction.
481
482
  Every storage engine MUST call this function when it starts
483
  a transaction or a statement (that is it must be called both for the
484
  "beginning of transaction" and "beginning of statement").
485
  Only storage engines registered for the transaction/statement
486
  will know when to commit/rollback it.
487
488
  @note
489
    trans_register_ha is idempotent - storage engine may register many
490
    times per transaction.
491
492
*/
960.2.27 by Monty Taylor
Reworked transformed handlerton into class StorageEngine.
493
void trans_register_ha(Session *session, bool all, StorageEngine *engine)
1 by brian
clean slate
494
{
520.1.21 by Brian Aker
THD -> Session rename
495
  Session_TRANS *trans;
1 by brian
clean slate
496
  Ha_trx_info *ha_info;
497
498
  if (all)
499
  {
520.1.22 by Brian Aker
Second pass of thd cleanup
500
    trans= &session->transaction.all;
501
    session->server_status|= SERVER_STATUS_IN_TRANS;
1 by brian
clean slate
502
  }
503
  else
520.1.22 by Brian Aker
Second pass of thd cleanup
504
    trans= &session->transaction.stmt;
1 by brian
clean slate
505
960.2.27 by Monty Taylor
Reworked transformed handlerton into class StorageEngine.
506
  ha_info= session->ha_data[engine->slot].ha_info + static_cast<unsigned>(all);
1 by brian
clean slate
507
508
  if (ha_info->is_started())
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
509
    return; /* already registered, return */
1 by brian
clean slate
510
960.2.27 by Monty Taylor
Reworked transformed handlerton into class StorageEngine.
511
  ha_info->register_ha(trans, engine);
1 by brian
clean slate
512
960.2.27 by Monty Taylor
Reworked transformed handlerton into class StorageEngine.
513
  trans->no_2pc|= not engine->has_2pc();
520.1.22 by Brian Aker
Second pass of thd cleanup
514
  if (session->transaction.xid_state.xid.is_null())
515
    session->transaction.xid_state.xid.set(session->query_id);
1 by brian
clean slate
516
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
517
  return;
1 by brian
clean slate
518
}
519
520
/**
521
  @retval
522
    0   ok
523
  @retval
524
    1   error, transaction was rolled back
525
*/
520.1.22 by Brian Aker
Second pass of thd cleanup
526
int ha_prepare(Session *session)
1 by brian
clean slate
527
{
528
  int error=0, all=1;
520.1.22 by Brian Aker
Second pass of thd cleanup
529
  Session_TRANS *trans=all ? &session->transaction.all : &session->transaction.stmt;
1 by brian
clean slate
530
  Ha_trx_info *ha_info= trans->ha_list;
531
  if (ha_info)
532
  {
533
    for (; ha_info; ha_info= ha_info->next())
534
    {
535
      int err;
960.2.37 by Monty Taylor
More naming fixes.
536
      StorageEngine *engine= ha_info->engine();
520.1.22 by Brian Aker
Second pass of thd cleanup
537
      status_var_increment(session->status_var.ha_prepare_count);
960.2.38 by Monty Taylor
Removed extraneous send myself to myself argument.
538
      if ((err= engine->prepare(session, all)))
1 by brian
clean slate
539
      {
960.2.27 by Monty Taylor
Reworked transformed handlerton into class StorageEngine.
540
        my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
541
        ha_rollback_trans(session, all);
542
        error=1;
543
        break;
1 by brian
clean slate
544
      }
545
      else
546
      {
520.1.22 by Brian Aker
Second pass of thd cleanup
547
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1 by brian
clean slate
548
                            ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
971.1.14 by Monty Taylor
Slurp around strings rather than char* for storage engine name.
549
                            engine->getName().c_str());
1 by brian
clean slate
550
      }
551
    }
552
  }
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
553
  return(error);
1 by brian
clean slate
554
}
555
556
/**
557
  Check if we can skip the two-phase commit.
558
559
  A helper function to evaluate if two-phase commit is mandatory.
560
  As a side effect, propagates the read-only/read-write flags
561
  of the statement transaction to its enclosing normal transaction.
562
56 by brian
Next pass of true/false update.
563
  @retval true   we must run a two-phase commit. Returned
1 by brian
clean slate
564
                 if we have at least two engines with read-write changes.
56 by brian
Next pass of true/false update.
565
  @retval false  Don't need two-phase commit. Even if we have two
1 by brian
clean slate
566
                 transactional engines, we can run two independent
567
                 commits if changes in one of the engines are read-only.
568
*/
569
570
static
571
bool
520.1.22 by Brian Aker
Second pass of thd cleanup
572
ha_check_and_coalesce_trx_read_only(Session *session, Ha_trx_info *ha_list,
1 by brian
clean slate
573
                                    bool all)
574
{
575
  /* The number of storage engines that have actual changes. */
576
  unsigned rw_ha_count= 0;
577
  Ha_trx_info *ha_info;
578
579
  for (ha_info= ha_list; ha_info; ha_info= ha_info->next())
580
  {
581
    if (ha_info->is_trx_read_write())
582
      ++rw_ha_count;
583
584
    if (! all)
585
    {
960.2.37 by Monty Taylor
More naming fixes.
586
      Ha_trx_info *ha_info_all= &session->ha_data[ha_info->engine()->slot].ha_info[1];
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
587
      assert(ha_info != ha_info_all);
1 by brian
clean slate
588
      /*
589
        Merge read-only/read-write information about statement
590
        transaction to its enclosing normal transaction. Do this
591
        only if in a real transaction -- that is, if we know
520.1.22 by Brian Aker
Second pass of thd cleanup
592
        that ha_info_all is registered in session->transaction.all.
1 by brian
clean slate
593
        Since otherwise we only clutter the normal transaction flags.
594
      */
56 by brian
Next pass of true/false update.
595
      if (ha_info_all->is_started()) /* false if autocommit. */
1 by brian
clean slate
596
        ha_info_all->coalesce_trx_with(ha_info);
597
    }
598
    else if (rw_ha_count > 1)
599
    {
600
      /*
601
        It is a normal transaction, so we don't need to merge read/write
602
        information up, and the need for two-phase commit has been
603
        already established. Break the loop prematurely.
604
      */
605
      break;
606
    }
607
  }
608
  return rw_ha_count > 1;
609
}
610
611
612
/**
613
  @retval
614
    0   ok
615
  @retval
616
    1   transaction was rolled back
617
  @retval
618
    2   error during commit, data may be inconsistent
619
620
  @todo
621
    Since we don't support nested statement transactions in 5.0,
622
    we can't commit or rollback stmt transactions while we are inside
623
    stored functions or triggers. So we simply do nothing now.
624
    TODO: This should be fixed in later ( >= 5.1) releases.
625
*/
520.1.22 by Brian Aker
Second pass of thd cleanup
626
int ha_commit_trans(Session *session, bool all)
1 by brian
clean slate
627
{
628
  int error= 0, cookie= 0;
629
  /*
630
    'all' means that this is either an explicit commit issued by
631
    user, or an implicit commit issued by a DDL.
632
  */
520.1.22 by Brian Aker
Second pass of thd cleanup
633
  Session_TRANS *trans= all ? &session->transaction.all : &session->transaction.stmt;
634
  bool is_real_trans= all || session->transaction.all.ha_list == 0;
1 by brian
clean slate
635
  Ha_trx_info *ha_info= trans->ha_list;
636
637
  /*
638
    We must not commit the normal transaction if a statement
639
    transaction is pending. Otherwise statement transaction
640
    flags will not get propagated to its normal transaction's
641
    counterpart.
642
  */
520.1.22 by Brian Aker
Second pass of thd cleanup
643
  assert(session->transaction.stmt.ha_list == NULL ||
644
              trans == &session->transaction.stmt);
1 by brian
clean slate
645
646
  if (ha_info)
647
  {
648
    bool must_2pc;
649
520.1.22 by Brian Aker
Second pass of thd cleanup
650
    if (is_real_trans && wait_if_global_read_lock(session, 0, 0))
1 by brian
clean slate
651
    {
520.1.22 by Brian Aker
Second pass of thd cleanup
652
      ha_rollback_trans(session, all);
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
653
      return(1);
1 by brian
clean slate
654
    }
655
520.1.22 by Brian Aker
Second pass of thd cleanup
656
    must_2pc= ha_check_and_coalesce_trx_read_only(session, ha_info, all);
1 by brian
clean slate
657
658
    if (!trans->no_2pc && must_2pc)
659
    {
660
      for (; ha_info && !error; ha_info= ha_info->next())
661
      {
662
        int err;
960.2.37 by Monty Taylor
More naming fixes.
663
        StorageEngine *engine= ha_info->engine();
1 by brian
clean slate
664
        /*
665
          Do not call two-phase commit if this particular
666
          transaction is read-only. This allows for simpler
667
          implementation in engines that are always read-only.
668
        */
669
        if (! ha_info->is_trx_read_write())
670
          continue;
671
        /*
672
          Sic: we know that prepare() is not NULL since otherwise
673
          trans->no_2pc would have been set.
674
        */
960.2.38 by Monty Taylor
Removed extraneous send myself to myself argument.
675
        if ((err= engine->prepare(session, all)))
1 by brian
clean slate
676
        {
677
          my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
678
          error= 1;
679
        }
520.1.22 by Brian Aker
Second pass of thd cleanup
680
        status_var_increment(session->status_var.ha_prepare_count);
1 by brian
clean slate
681
      }
798.2.30 by Brian Aker
Removed dependency on log.h
682
      if (error)
1 by brian
clean slate
683
      {
520.1.22 by Brian Aker
Second pass of thd cleanup
684
        ha_rollback_trans(session, all);
1 by brian
clean slate
685
        error= 1;
686
        goto end;
687
      }
688
    }
520.1.22 by Brian Aker
Second pass of thd cleanup
689
    error=ha_commit_one_phase(session, all) ? (cookie ? 2 : 1) : 0;
1 by brian
clean slate
690
end:
691
    if (is_real_trans)
520.1.22 by Brian Aker
Second pass of thd cleanup
692
      start_waiting_global_read_lock(session);
1 by brian
clean slate
693
  }
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
694
  return(error);
1 by brian
clean slate
695
}
696
697
/**
698
  @note
699
  This function does not care about global read lock. A caller should.
700
*/
520.1.22 by Brian Aker
Second pass of thd cleanup
701
int ha_commit_one_phase(Session *session, bool all)
1 by brian
clean slate
702
{
703
  int error=0;
520.1.22 by Brian Aker
Second pass of thd cleanup
704
  Session_TRANS *trans=all ? &session->transaction.all : &session->transaction.stmt;
705
  bool is_real_trans=all || session->transaction.all.ha_list == 0;
1 by brian
clean slate
706
  Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
707
  if (ha_info)
708
  {
709
    for (; ha_info; ha_info= ha_info_next)
710
    {
711
      int err;
960.2.37 by Monty Taylor
More naming fixes.
712
      StorageEngine *engine= ha_info->engine();
960.2.38 by Monty Taylor
Removed extraneous send myself to myself argument.
713
      if ((err= engine->commit(session, all)))
1 by brian
clean slate
714
      {
715
        my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
716
        error=1;
717
      }
520.1.22 by Brian Aker
Second pass of thd cleanup
718
      status_var_increment(session->status_var.ha_commit_count);
1 by brian
clean slate
719
      ha_info_next= ha_info->next();
720
      ha_info->reset(); /* keep it conveniently zero-filled */
721
    }
722
    trans->ha_list= 0;
723
    trans->no_2pc=0;
724
    if (is_real_trans)
520.1.22 by Brian Aker
Second pass of thd cleanup
725
      session->transaction.xid_state.xid.null();
1 by brian
clean slate
726
    if (all)
727
    {
520.1.22 by Brian Aker
Second pass of thd cleanup
728
      session->variables.tx_isolation=session->session_tx_isolation;
729
      session->transaction.cleanup();
1 by brian
clean slate
730
    }
731
  }
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
732
  return(error);
1 by brian
clean slate
733
}
734
735
520.1.22 by Brian Aker
Second pass of thd cleanup
736
int ha_rollback_trans(Session *session, bool all)
1 by brian
clean slate
737
{
738
  int error=0;
520.1.22 by Brian Aker
Second pass of thd cleanup
739
  Session_TRANS *trans=all ? &session->transaction.all : &session->transaction.stmt;
1 by brian
clean slate
740
  Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
520.1.22 by Brian Aker
Second pass of thd cleanup
741
  bool is_real_trans=all || session->transaction.all.ha_list == 0;
1 by brian
clean slate
742
743
  /*
744
    We must not rollback the normal transaction if a statement
745
    transaction is pending.
746
  */
520.1.22 by Brian Aker
Second pass of thd cleanup
747
  assert(session->transaction.stmt.ha_list == NULL ||
748
              trans == &session->transaction.stmt);
1 by brian
clean slate
749
750
  if (ha_info)
751
  {
752
    for (; ha_info; ha_info= ha_info_next)
753
    {
754
      int err;
960.2.37 by Monty Taylor
More naming fixes.
755
      StorageEngine *engine= ha_info->engine();
960.2.38 by Monty Taylor
Removed extraneous send myself to myself argument.
756
      if ((err= engine->rollback(session, all)))
1 by brian
clean slate
757
      { // cannot happen
758
        my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
759
        error=1;
760
      }
520.1.22 by Brian Aker
Second pass of thd cleanup
761
      status_var_increment(session->status_var.ha_rollback_count);
1 by brian
clean slate
762
      ha_info_next= ha_info->next();
763
      ha_info->reset(); /* keep it conveniently zero-filled */
764
    }
765
    trans->ha_list= 0;
766
    trans->no_2pc=0;
767
    if (is_real_trans)
520.1.22 by Brian Aker
Second pass of thd cleanup
768
      session->transaction.xid_state.xid.null();
1 by brian
clean slate
769
    if (all)
770
    {
520.1.22 by Brian Aker
Second pass of thd cleanup
771
      session->variables.tx_isolation=session->session_tx_isolation;
772
      session->transaction.cleanup();
1 by brian
clean slate
773
    }
774
  }
775
  if (all)
520.1.22 by Brian Aker
Second pass of thd cleanup
776
    session->transaction_rollback_request= false;
1 by brian
clean slate
777
778
  /*
779
    If a non-transactional table was updated, warn; don't warn if this is a
780
    slave thread (because when a slave thread executes a ROLLBACK, it has
781
    been read from the binary log, so it's 100% sure and normal to produce
782
    error ER_WARNING_NOT_COMPLETE_ROLLBACK. If we sent the warning to the
783
    slave SQL thread, it would not stop the thread but just be printed in
784
    the error log; but we don't want users to wonder why they have this
785
    message in the error log, so we don't send it.
786
  */
812 by Brian Aker
Merge and fix for scheduler.h
787
  if (is_real_trans && session->transaction.all.modified_non_trans_table && session->killed != Session::KILL_CONNECTION)
520.1.22 by Brian Aker
Second pass of thd cleanup
788
    push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1 by brian
clean slate
789
                 ER_WARNING_NOT_COMPLETE_ROLLBACK,
790
                 ER(ER_WARNING_NOT_COMPLETE_ROLLBACK));
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
791
  return(error);
1 by brian
clean slate
792
}
793
794
/**
795
  This is used to commit or rollback a single statement depending on
796
  the value of error.
797
798
  @note
799
    Note that if the autocommit is on, then the following call inside
800
    InnoDB will commit or rollback the whole transaction (= the statement). The
801
    autocommit mechanism built into InnoDB is based on counting locks, but if
802
    the user has used LOCK TABLES then that mechanism does not know to do the
803
    commit.
804
*/
520.1.22 by Brian Aker
Second pass of thd cleanup
805
int ha_autocommit_or_rollback(Session *session, int error)
1 by brian
clean slate
806
{
520.1.22 by Brian Aker
Second pass of thd cleanup
807
  if (session->transaction.stmt.ha_list)
1 by brian
clean slate
808
  {
809
    if (!error)
810
    {
520.1.22 by Brian Aker
Second pass of thd cleanup
811
      if (ha_commit_trans(session, 0))
575.1.3 by Monty Taylor
Moved some stuff out of handler.h.
812
        error=1;
1 by brian
clean slate
813
    }
575.1.3 by Monty Taylor
Moved some stuff out of handler.h.
814
    else
1 by brian
clean slate
815
    {
520.1.22 by Brian Aker
Second pass of thd cleanup
816
      (void) ha_rollback_trans(session, 0);
817
      if (session->transaction_rollback_request)
818
        (void) ha_rollback(session);
1 by brian
clean slate
819
    }
820
520.1.22 by Brian Aker
Second pass of thd cleanup
821
    session->variables.tx_isolation=session->session_tx_isolation;
1 by brian
clean slate
822
  }
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
823
  return(error);
1 by brian
clean slate
824
}
825
826
971.1.35 by Monty Taylor
One more plugin_foreach down.
827
1 by brian
clean slate
828
829
/**
830
  return the list of XID's to a client, the same way SHOW commands do.
831
832
  @note
833
    I didn't find in XA specs that an RM cannot return the same XID twice,
834
    so mysql_xa_recover does not filter XID's to ensure uniqueness.
835
    It can be easily fixed later, if necessary.
836
*/
520.1.22 by Brian Aker
Second pass of thd cleanup
837
bool mysql_xa_recover(Session *session)
1 by brian
clean slate
838
{
839
  List<Item> field_list;
520.1.22 by Brian Aker
Second pass of thd cleanup
840
  Protocol *protocol= session->protocol;
1 by brian
clean slate
841
  int i=0;
842
  XID_STATE *xs;
843
844
  field_list.push_back(new Item_int("formatID", 0, MY_INT32_NUM_DECIMAL_DIGITS));
845
  field_list.push_back(new Item_int("gtrid_length", 0, MY_INT32_NUM_DECIMAL_DIGITS));
846
  field_list.push_back(new Item_int("bqual_length", 0, MY_INT32_NUM_DECIMAL_DIGITS));
847
  field_list.push_back(new Item_empty_string("data",XIDDATASIZE));
848
971.3.19 by Eric Day
Finished first pass at Protocol cleanup, still some things to remove but they are a bit more involved.
849
  if (protocol->sendFields(&field_list,
850
                           Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
851
    return(1);
1 by brian
clean slate
852
853
  pthread_mutex_lock(&LOCK_xid_cache);
854
  while ((xs= (XID_STATE*)hash_element(&xid_cache, i++)))
855
  {
856
    if (xs->xa_state==XA_PREPARED)
857
    {
971.3.19 by Eric Day
Finished first pass at Protocol cleanup, still some things to remove but they are a bit more involved.
858
      protocol->prepareForResend();
971.3.17 by Eric Day
Cleaned up int/date related store functions.
859
      protocol->store((int64_t)xs->xid.formatID);
860
      protocol->store((int64_t)xs->xid.gtrid_length);
861
      protocol->store((int64_t)xs->xid.bqual_length);
1 by brian
clean slate
862
      protocol->store(xs->xid.data, xs->xid.gtrid_length+xs->xid.bqual_length,
863
                      &my_charset_bin);
864
      if (protocol->write())
865
      {
866
        pthread_mutex_unlock(&LOCK_xid_cache);
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
867
        return(1);
1 by brian
clean slate
868
      }
869
    }
870
  }
871
872
  pthread_mutex_unlock(&LOCK_xid_cache);
836 by Brian Aker
Fixed session call from function to method.
873
  session->my_eof();
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
874
  return(0);
1 by brian
clean slate
875
}
876
877
520.1.22 by Brian Aker
Second pass of thd cleanup
878
int ha_rollback_to_savepoint(Session *session, SAVEPOINT *sv)
1 by brian
clean slate
879
{
880
  int error=0;
520.1.22 by Brian Aker
Second pass of thd cleanup
881
  Session_TRANS *trans= &session->transaction.all;
1 by brian
clean slate
882
  Ha_trx_info *ha_info, *ha_info_next;
883
884
  trans->no_2pc=0;
885
  /*
886
    rolling back to savepoint in all storage engines that were part of the
887
    transaction when the savepoint was set
888
  */
889
  for (ha_info= sv->ha_list; ha_info; ha_info= ha_info->next())
890
  {
891
    int err;
960.2.37 by Monty Taylor
More naming fixes.
892
    StorageEngine *engine= ha_info->engine();
960.2.27 by Monty Taylor
Reworked transformed handlerton into class StorageEngine.
893
    assert(engine);
960.2.38 by Monty Taylor
Removed extraneous send myself to myself argument.
894
    if ((err= engine->savepoint_rollback(session,
964.1.6 by Monty Taylor
Moved savepoint stuff to protected virtual methods, moved the offset to private, and moved the logic about adding the offset to the passed-in pointer and adding the offset to the global offset inside of the class.
895
                                         (void *)(sv+1))))
1 by brian
clean slate
896
    { // cannot happen
897
      my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
898
      error=1;
899
    }
520.1.22 by Brian Aker
Second pass of thd cleanup
900
    status_var_increment(session->status_var.ha_savepoint_rollback_count);
960.2.27 by Monty Taylor
Reworked transformed handlerton into class StorageEngine.
901
    trans->no_2pc|= not engine->has_2pc();
1 by brian
clean slate
902
  }
903
  /*
904
    rolling back the transaction in all storage engines that were not part of
905
    the transaction when the savepoint was set
906
  */
907
  for (ha_info= trans->ha_list; ha_info != sv->ha_list;
908
       ha_info= ha_info_next)
909
  {
910
    int err;
960.2.37 by Monty Taylor
More naming fixes.
911
    StorageEngine *engine= ha_info->engine();
960.2.38 by Monty Taylor
Removed extraneous send myself to myself argument.
912
    if ((err= engine->rollback(session, !(0))))
1 by brian
clean slate
913
    { // cannot happen
914
      my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
915
      error=1;
916
    }
520.1.22 by Brian Aker
Second pass of thd cleanup
917
    status_var_increment(session->status_var.ha_rollback_count);
1 by brian
clean slate
918
    ha_info_next= ha_info->next();
919
    ha_info->reset(); /* keep it conveniently zero-filled */
920
  }
921
  trans->ha_list= sv->ha_list;
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
922
  return(error);
1 by brian
clean slate
923
}
924
925
/**
926
  @note
927
  according to the sql standard (ISO/IEC 9075-2:2003)
928
  section "4.33.4 SQL-statements and transaction states",
929
  SAVEPOINT is *not* transaction-initiating SQL-statement
930
*/
520.1.22 by Brian Aker
Second pass of thd cleanup
931
int ha_savepoint(Session *session, SAVEPOINT *sv)
1 by brian
clean slate
932
{
933
  int error=0;
520.1.22 by Brian Aker
Second pass of thd cleanup
934
  Session_TRANS *trans= &session->transaction.all;
1 by brian
clean slate
935
  Ha_trx_info *ha_info= trans->ha_list;
936
  for (; ha_info; ha_info= ha_info->next())
937
  {
938
    int err;
960.2.37 by Monty Taylor
More naming fixes.
939
    StorageEngine *engine= ha_info->engine();
960.2.27 by Monty Taylor
Reworked transformed handlerton into class StorageEngine.
940
    assert(engine);
941
/*    if (! engine->savepoint_set)
1 by brian
clean slate
942
    {
943
      my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "SAVEPOINT");
944
      error=1;
945
      break;
960.2.27 by Monty Taylor
Reworked transformed handlerton into class StorageEngine.
946
    } */
964.1.6 by Monty Taylor
Moved savepoint stuff to protected virtual methods, moved the offset to private, and moved the logic about adding the offset to the passed-in pointer and adding the offset to the global offset inside of the class.
947
    if ((err= engine->savepoint_set(session, (void *)(sv+1))))
1 by brian
clean slate
948
    { // cannot happen
949
      my_error(ER_GET_ERRNO, MYF(0), err);
950
      error=1;
951
    }
520.1.22 by Brian Aker
Second pass of thd cleanup
952
    status_var_increment(session->status_var.ha_savepoint_count);
1 by brian
clean slate
953
  }
954
  /*
955
    Remember the list of registered storage engines. All new
956
    engines are prepended to the beginning of the list.
957
  */
958
  sv->ha_list= trans->ha_list;
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
959
  return(error);
1 by brian
clean slate
960
}
961
520.1.22 by Brian Aker
Second pass of thd cleanup
962
int ha_release_savepoint(Session *session, SAVEPOINT *sv)
1 by brian
clean slate
963
{
964
  int error=0;
965
  Ha_trx_info *ha_info= sv->ha_list;
966
967
  for (; ha_info; ha_info= ha_info->next())
968
  {
969
    int err;
960.2.37 by Monty Taylor
More naming fixes.
970
    StorageEngine *engine= ha_info->engine();
1 by brian
clean slate
971
    /* Savepoint life time is enclosed into transaction life time. */
960.2.27 by Monty Taylor
Reworked transformed handlerton into class StorageEngine.
972
    assert(engine);
960.2.38 by Monty Taylor
Removed extraneous send myself to myself argument.
973
    if ((err= engine->savepoint_release(session,
964.1.6 by Monty Taylor
Moved savepoint stuff to protected virtual methods, moved the offset to private, and moved the logic about adding the offset to the passed-in pointer and adding the offset to the global offset inside of the class.
974
                                        (void *)(sv+1))))
1 by brian
clean slate
975
    { // cannot happen
976
      my_error(ER_GET_ERRNO, MYF(0), err);
977
      error=1;
978
    }
979
  }
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
980
  return(error);
1 by brian
clean slate
981
}
982
983
984
985
986
987
/****************************************************************************
988
** General handler functions
989
****************************************************************************/
990
handler *handler::clone(MEM_ROOT *mem_root)
991
{
992
  handler *new_handler= get_new_handler(table->s, mem_root, table->s->db_type());
993
  /*
994
    Allocate handler->ref here because otherwise ha_open will allocate it
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
995
    on this->table->mem_root and we will not be able to reclaim that memory
1 by brian
clean slate
996
    when the clone handler object is destroyed.
997
  */
481 by Brian Aker
Remove all of uchar.
998
  if (!(new_handler->ref= (unsigned char*) alloc_root(mem_root, ALIGN_SIZE(ref_length)*2)))
1 by brian
clean slate
999
    return NULL;
1000
  if (new_handler && !new_handler->ha_open(table,
1001
                                           table->s->normalized_path.str,
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
1002
                                           table->getDBStat(),
1 by brian
clean slate
1003
                                           HA_OPEN_IGNORE_IF_LOCKED))
1004
    return new_handler;
1005
  return NULL;
1006
}
1007
575.1.4 by Monty Taylor
Moved implementation of some methods into handler.cc from handler.h.
1008
int handler::ha_index_init(uint32_t idx, bool sorted)
1009
{
1010
  int result;
1011
  assert(inited==NONE);
1012
  if (!(result= index_init(idx, sorted)))
1013
    inited=INDEX;
1014
  end_range= NULL;
1015
  return(result);
1016
}
1017
1018
int handler::ha_index_end()
1019
{
1020
  assert(inited==INDEX);
1021
  inited=NONE;
1022
  end_range= NULL;
1023
  return(index_end());
1024
}
1025
1026
int handler::ha_rnd_init(bool scan)
1027
{
1028
  int result;
1029
  assert(inited==NONE || (inited==RND && scan));
1030
  inited= (result= rnd_init(scan)) ? NONE: RND;
1031
  return(result);
1032
}
1033
1034
int handler::ha_rnd_end()
1035
{
1036
  assert(inited==RND);
1037
  inited=NONE;
1038
  return(rnd_end());
1039
}
1040
1041
int handler::ha_index_or_rnd_end()
1042
{
1043
  return inited == INDEX ? ha_index_end() : inited == RND ? ha_rnd_end() : 0;
1044
}
1045
1046
handler::Table_flags handler::ha_table_flags() const
1047
{
1048
  return cached_table_flags;
1049
}
1050
1051
void handler::ha_start_bulk_insert(ha_rows rows)
1052
{
1053
  estimation_rows_to_insert= rows;
1054
  start_bulk_insert(rows);
1055
}
1056
1057
int handler::ha_end_bulk_insert()
1058
{
1059
  estimation_rows_to_insert= 0;
1060
  return end_bulk_insert();
1061
}
1062
1000.1.3 by Brian Aker
Renamed TABLE_SHARE to TableShare
1063
void handler::change_table_ptr(Table *table_arg, TableShare *share)
575.1.4 by Monty Taylor
Moved implementation of some methods into handler.cc from handler.h.
1064
{
1065
  table= table_arg;
1066
  table_share= share;
1067
}
1068
1069
const key_map *handler::keys_to_use_for_scanning()
1070
{
1071
  return &key_map_empty;
1072
}
1073
1074
bool handler::has_transactions()
1075
{
1076
  return (ha_table_flags() & HA_NO_TRANSACTIONS) == 0;
1077
}
1 by brian
clean slate
1078
1079
void handler::ha_statistic_increment(ulong SSV::*offset) const
1080
{
1081
  status_var_increment(table->in_use->status_var.*offset);
1082
}
1083
520.1.22 by Brian Aker
Second pass of thd cleanup
1084
void **handler::ha_data(Session *session) const
1 by brian
clean slate
1085
{
960.2.37 by Monty Taylor
More naming fixes.
1086
  return session_ha_data(session, engine);
1 by brian
clean slate
1087
}
1088
520.1.22 by Brian Aker
Second pass of thd cleanup
1089
Session *handler::ha_session(void) const
1 by brian
clean slate
1090
{
520.1.22 by Brian Aker
Second pass of thd cleanup
1091
  assert(!table || !table->in_use || table->in_use == current_session);
1092
  return (table && table->in_use) ? table->in_use : current_session;
1 by brian
clean slate
1093
}
1094
575.1.4 by Monty Taylor
Moved implementation of some methods into handler.cc from handler.h.
1095
1096
bool handler::is_fatal_error(int error, uint32_t flags)
1097
{
1098
  if (!error ||
1099
      ((flags & HA_CHECK_DUP_KEY) &&
1100
       (error == HA_ERR_FOUND_DUPP_KEY ||
1101
        error == HA_ERR_FOUND_DUPP_UNIQUE)))
1102
    return false;
1103
  return true;
1104
}
1105
575.1.5 by Monty Taylor
Moved stuff to handlerton.cc
1106
1107
ha_rows handler::records() { return stats.records; }
1108
1 by brian
clean slate
1109
/**
1110
  Open database-handler.
1111
1112
  Try O_RDONLY if cannot open as O_RDWR
1113
  Don't wait for locks if not HA_OPEN_WAIT_IF_LOCKED is set
1114
*/
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
1115
int handler::ha_open(Table *table_arg, const char *name, int mode,
1 by brian
clean slate
1116
                     int test_if_locked)
1117
{
1118
  int error;
1119
1120
  table= table_arg;
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
1121
  assert(table->s == table_share);
1122
  assert(alloc_root_inited(&table->mem_root));
1 by brian
clean slate
1123
1124
  if ((error=open(name,mode,test_if_locked)))
1125
  {
1126
    if ((error == EACCES || error == EROFS) && mode == O_RDWR &&
1127
	(table->db_stat & HA_TRY_READ_ONLY))
1128
    {
1129
      table->db_stat|=HA_READ_ONLY;
1130
      error=open(name,O_RDONLY,test_if_locked);
1131
    }
1132
  }
1133
  if (error)
1134
  {
1135
    my_errno= error;                            /* Safeguard */
1136
  }
1137
  else
1138
  {
1139
    if (table->s->db_options_in_use & HA_OPTION_READ_ONLY_DATA)
1140
      table->db_stat|=HA_READ_ONLY;
1141
    (void) extra(HA_EXTRA_NO_READCHECK);	// Not needed in SQL
1142
1143
    /* ref is already allocated for us if we're called from handler::clone() */
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
1144
    if (!ref && !(ref= (unsigned char*) alloc_root(&table->mem_root,
1 by brian
clean slate
1145
                                          ALIGN_SIZE(ref_length)*2)))
1146
    {
1147
      close();
1148
      error=HA_ERR_OUT_OF_MEM;
1149
    }
1150
    else
1151
      dup_ref=ref+ALIGN_SIZE(ref_length);
1152
    cached_table_flags= table_flags();
1153
  }
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
1154
  return(error);
1 by brian
clean slate
1155
}
1156
1157
/**
1158
  one has to use this method when to find
1159
  random position by record as the plain
1160
  position() call doesn't work for some
1161
  handlers for random position
1162
*/
1163
481 by Brian Aker
Remove all of uchar.
1164
int handler::rnd_pos_by_record(unsigned char *record)
1 by brian
clean slate
1165
{
1166
  register int error;
1167
1168
  position(record);
1169
  if (inited && (error= ha_index_end()))
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
1170
    return(error);
56 by brian
Next pass of true/false update.
1171
  if ((error= ha_rnd_init(false)))
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
1172
    return(error);
1 by brian
clean slate
1173
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
1174
  return(rnd_pos(record, ref));
1 by brian
clean slate
1175
}
1176
1177
/**
1178
  Read first row (only) from a table.
1179
1180
  This is never called for InnoDB tables, as these table types
1181
  has the HA_STATS_RECORDS_IS_EXACT set.
1182
*/
482 by Brian Aker
Remove uint.
1183
int handler::read_first_row(unsigned char * buf, uint32_t primary_key)
1 by brian
clean slate
1184
{
1185
  register int error;
1186
1187
  ha_statistic_increment(&SSV::ha_read_first_count);
1188
1189
  /*
1190
    If there is very few deleted rows in the table, find the first row by
1191
    scanning the table.
1192
    TODO remove the test for HA_READ_ORDER
1193
  */
1194
  if (stats.deleted < 10 || primary_key >= MAX_KEY ||
1195
      !(index_flags(primary_key, 0, 0) & HA_READ_ORDER))
1196
  {
1197
    (void) ha_rnd_init(1);
1198
    while ((error= rnd_next(buf)) == HA_ERR_RECORD_DELETED) ;
1199
    (void) ha_rnd_end();
1200
  }
1201
  else
1202
  {
1203
    /* Find the first row through the primary key */
1204
    (void) ha_index_init(primary_key, 0);
1205
    error=index_first(buf);
1206
    (void) ha_index_end();
1207
  }
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
1208
  return(error);
1 by brian
clean slate
1209
}
1210
1211
/**
1212
  Generate the next auto-increment number based on increment and offset.
1213
  computes the lowest number
1214
  - strictly greater than "nr"
1215
  - of the form: auto_increment_offset + N * auto_increment_increment
1216
1217
  In most cases increment= offset= 1, in which case we get:
1218
  @verbatim 1,2,3,4,5,... @endverbatim
1219
    If increment=10 and offset=5 and previous number is 1, we get:
1220
  @verbatim 1,5,15,25,35,... @endverbatim
1221
*/
1222
inline uint64_t
1223
compute_next_insert_id(uint64_t nr,struct system_variables *variables)
1224
{
1225
  if (variables->auto_increment_increment == 1)
1226
    return (nr+1); // optimization of the formula below
1227
  nr= (((nr+ variables->auto_increment_increment -
1228
         variables->auto_increment_offset)) /
1229
       (uint64_t) variables->auto_increment_increment);
1230
  return (nr* (uint64_t) variables->auto_increment_increment +
1231
          variables->auto_increment_offset);
1232
}
1233
1234
1235
void handler::adjust_next_insert_id_after_explicit_value(uint64_t nr)
1236
{
1237
  /*
520.1.21 by Brian Aker
THD -> Session rename
1238
    If we have set Session::next_insert_id previously and plan to insert an
1 by brian
clean slate
1239
    explicitely-specified value larger than this, we need to increase
520.1.21 by Brian Aker
THD -> Session rename
1240
    Session::next_insert_id to be greater than the explicit value.
1 by brian
clean slate
1241
  */
1242
  if ((next_insert_id > 0) && (nr >= next_insert_id))
1243
    set_next_insert_id(compute_next_insert_id(nr, &table->in_use->variables));
1244
}
1245
1246
1247
/**
1248
  Compute a previous insert id
1249
1250
  Computes the largest number X:
1251
  - smaller than or equal to "nr"
1252
  - of the form: auto_increment_offset + N * auto_increment_increment
1253
    where N>=0.
1254
1255
  @param nr            Number to "round down"
1256
  @param variables     variables struct containing auto_increment_increment and
1257
                       auto_increment_offset
1258
1259
  @return
1260
    The number X if it exists, "nr" otherwise.
1261
*/
1262
inline uint64_t
1263
prev_insert_id(uint64_t nr, struct system_variables *variables)
1264
{
1265
  if (unlikely(nr < variables->auto_increment_offset))
1266
  {
1267
    /*
1268
      There's nothing good we can do here. That is a pathological case, where
1269
      the offset is larger than the column's max possible value, i.e. not even
1270
      the first sequence value may be inserted. User will receive warning.
1271
    */
1272
    return nr;
1273
  }
1274
  if (variables->auto_increment_increment == 1)
1275
    return nr; // optimization of the formula below
1276
  nr= (((nr - variables->auto_increment_offset)) /
1277
       (uint64_t) variables->auto_increment_increment);
1278
  return (nr * (uint64_t) variables->auto_increment_increment +
1279
          variables->auto_increment_offset);
1280
}
1281
1282
1283
/**
1284
  Update the auto_increment field if necessary.
1285
1286
  Updates columns with type NEXT_NUMBER if:
1287
1288
  - If column value is set to NULL (in which case
1289
    auto_increment_field_not_null is 0)
1290
  - If column is set to 0 and (sql_mode & MODE_NO_AUTO_VALUE_ON_ZERO) is not
1291
    set. In the future we will only set NEXT_NUMBER fields if one sets them
1292
    to NULL (or they are not included in the insert list).
1293
1294
    In those cases, we check if the currently reserved interval still has
1295
    values we have not used. If yes, we pick the smallest one and use it.
1296
    Otherwise:
1297
1298
  - If a list of intervals has been provided to the statement via SET
1299
    INSERT_ID or via an Intvar_log_event (in a replication slave), we pick the
1300
    first unused interval from this list, consider it as reserved.
1301
1302
  - Otherwise we set the column for the first row to the value
1303
    next_insert_id(get_auto_increment(column))) which is usually
1304
    max-used-column-value+1.
1305
    We call get_auto_increment() for the first row in a multi-row
1306
    statement. get_auto_increment() will tell us the interval of values it
1307
    reserved for us.
1308
1309
  - In both cases, for the following rows we use those reserved values without
1310
    calling the handler again (we just progress in the interval, computing
1311
    each new value from the previous one). Until we have exhausted them, then
1312
    we either take the next provided interval or call get_auto_increment()
1313
    again to reserve a new interval.
1314
1315
  - In both cases, the reserved intervals are remembered in
520.1.22 by Brian Aker
Second pass of thd cleanup
1316
    session->auto_inc_intervals_in_cur_stmt_for_binlog if statement-based
1 by brian
clean slate
1317
    binlogging; the last reserved interval is remembered in
1318
    auto_inc_interval_for_cur_row.
1319
1320
    The idea is that generated auto_increment values are predictable and
1321
    independent of the column values in the table.  This is needed to be
1322
    able to replicate into a table that already has rows with a higher
1323
    auto-increment value than the one that is inserted.
1324
1325
    After we have already generated an auto-increment number and the user
1326
    inserts a column with a higher value than the last used one, we will
1327
    start counting from the inserted value.
1328
1329
    This function's "outputs" are: the table's auto_increment field is filled
520.1.22 by Brian Aker
Second pass of thd cleanup
1330
    with a value, session->next_insert_id is filled with the value to use for the
1 by brian
clean slate
1331
    next row, if a value was autogenerated for the current row it is stored in
520.1.22 by Brian Aker
Second pass of thd cleanup
1332
    session->insert_id_for_cur_row, if get_auto_increment() was called
1333
    session->auto_inc_interval_for_cur_row is modified, if that interval is not
1334
    present in session->auto_inc_intervals_in_cur_stmt_for_binlog it is added to
1 by brian
clean slate
1335
    this list.
1336
1337
  @todo
1338
    Replace all references to "next number" or NEXT_NUMBER to
1339
    "auto_increment", everywhere (see below: there is
1340
    table->auto_increment_field_not_null, and there also exists
1341
    table->next_number_field, it's not consistent).
1342
1343
  @retval
1344
    0	ok
1345
  @retval
1346
    HA_ERR_AUTOINC_READ_FAILED  get_auto_increment() was called and
1347
    returned ~(uint64_t) 0
1348
  @retval
1349
    HA_ERR_AUTOINC_ERANGE storing value in field caused strict mode
1350
    failure.
1351
*/
1352
1353
#define AUTO_INC_DEFAULT_NB_ROWS 1 // Some prefer 1024 here
1354
#define AUTO_INC_DEFAULT_NB_MAX_BITS 16
1355
#define AUTO_INC_DEFAULT_NB_MAX ((1 << AUTO_INC_DEFAULT_NB_MAX_BITS) - 1)
1356
1357
int handler::update_auto_increment()
1358
{
1359
  uint64_t nr, nb_reserved_values;
56 by brian
Next pass of true/false update.
1360
  bool append= false;
520.1.22 by Brian Aker
Second pass of thd cleanup
1361
  Session *session= table->in_use;
1362
  struct system_variables *variables= &session->variables;
1 by brian
clean slate
1363
1364
  /*
1365
    next_insert_id is a "cursor" into the reserved interval, it may go greater
1366
    than the interval, but not smaller.
1367
  */
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
1368
  assert(next_insert_id >= auto_inc_interval_for_cur_row.minimum());
1 by brian
clean slate
1369
359 by Brian Aker
More modes removed. 0 always becomes new number again
1370
  if ((nr= table->next_number_field->val_int()) != 0)
1 by brian
clean slate
1371
  {
1372
    /*
1373
      Update next_insert_id if we had already generated a value in this
1374
      statement (case of INSERT VALUES(null),(3763),(null):
1375
      the last NULL needs to insert 3764, not the value of the first NULL plus
1376
      1).
1377
    */
1378
    adjust_next_insert_id_after_explicit_value(nr);
1379
    insert_id_for_cur_row= 0; // didn't generate anything
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
1380
    return(0);
1 by brian
clean slate
1381
  }
1382
1383
  if ((nr= next_insert_id) >= auto_inc_interval_for_cur_row.maximum())
1384
  {
1385
    /* next_insert_id is beyond what is reserved, so we reserve more. */
1386
    const Discrete_interval *forced=
520.1.22 by Brian Aker
Second pass of thd cleanup
1387
      session->auto_inc_intervals_forced.get_next();
1 by brian
clean slate
1388
    if (forced != NULL)
1389
    {
1390
      nr= forced->minimum();
1391
      nb_reserved_values= forced->values();
1392
    }
1393
    else
1394
    {
1395
      /*
1396
        handler::estimation_rows_to_insert was set by
1397
        handler::ha_start_bulk_insert(); if 0 it means "unknown".
1398
      */
482 by Brian Aker
Remove uint.
1399
      uint32_t nb_already_reserved_intervals=
520.1.22 by Brian Aker
Second pass of thd cleanup
1400
        session->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements();
1 by brian
clean slate
1401
      uint64_t nb_desired_values;
1402
      /*
1403
        If an estimation was given to the engine:
1404
        - use it.
1405
        - if we already reserved numbers, it means the estimation was
1406
        not accurate, then we'll reserve 2*AUTO_INC_DEFAULT_NB_ROWS the 2nd
1407
        time, twice that the 3rd time etc.
1408
        If no estimation was given, use those increasing defaults from the
1409
        start, starting from AUTO_INC_DEFAULT_NB_ROWS.
1410
        Don't go beyond a max to not reserve "way too much" (because
1411
        reservation means potentially losing unused values).
1412
      */
1413
      if (nb_already_reserved_intervals == 0 &&
1414
          (estimation_rows_to_insert > 0))
1415
        nb_desired_values= estimation_rows_to_insert;
1416
      else /* go with the increasing defaults */
1417
      {
1418
        /* avoid overflow in formula, with this if() */
1419
        if (nb_already_reserved_intervals <= AUTO_INC_DEFAULT_NB_MAX_BITS)
1420
        {
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
1421
          nb_desired_values= AUTO_INC_DEFAULT_NB_ROWS *
1 by brian
clean slate
1422
            (1 << nb_already_reserved_intervals);
937.2.6 by Stewart Smith
make set_if_bigger typesafe for C and C++. Fix up everywhere.
1423
          set_if_smaller(nb_desired_values, (uint64_t)AUTO_INC_DEFAULT_NB_MAX);
1 by brian
clean slate
1424
        }
1425
        else
1426
          nb_desired_values= AUTO_INC_DEFAULT_NB_MAX;
1427
      }
1428
      /* This call ignores all its parameters but nr, currently */
1429
      get_auto_increment(variables->auto_increment_offset,
1430
                         variables->auto_increment_increment,
1431
                         nb_desired_values, &nr,
1432
                         &nb_reserved_values);
1433
      if (nr == ~(uint64_t) 0)
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
1434
        return(HA_ERR_AUTOINC_READ_FAILED);  // Mark failure
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
1435
1 by brian
clean slate
1436
      /*
1437
        That rounding below should not be needed when all engines actually
1438
        respect offset and increment in get_auto_increment(). But they don't
1439
        so we still do it. Wonder if for the not-first-in-index we should do
1440
        it. Hope that this rounding didn't push us out of the interval; even
1441
        if it did we cannot do anything about it (calling the engine again
1442
        will not help as we inserted no row).
1443
      */
1444
      nr= compute_next_insert_id(nr-1, variables);
1445
    }
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
1446
1 by brian
clean slate
1447
    if (table->s->next_number_keypart == 0)
1448
    {
1449
      /* We must defer the appending until "nr" has been possibly truncated */
56 by brian
Next pass of true/false update.
1450
      append= true;
1 by brian
clean slate
1451
    }
1452
  }
1453
152 by Brian Aker
longlong replacement
1454
  if (unlikely(table->next_number_field->store((int64_t) nr, true)))
1 by brian
clean slate
1455
  {
1456
    /*
1457
      first test if the query was aborted due to strict mode constraints
1458
    */
520.1.22 by Brian Aker
Second pass of thd cleanup
1459
    if (session->killed == Session::KILL_BAD_DATA)
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
1460
      return(HA_ERR_AUTOINC_ERANGE);
1 by brian
clean slate
1461
1462
    /*
1463
      field refused this value (overflow) and truncated it, use the result of
1464
      the truncation (which is going to be inserted); however we try to
1465
      decrease it to honour auto_increment_* variables.
1466
      That will shift the left bound of the reserved interval, we don't
1467
      bother shifting the right bound (anyway any other value from this
1468
      interval will cause a duplicate key).
1469
    */
1470
    nr= prev_insert_id(table->next_number_field->val_int(), variables);
152 by Brian Aker
longlong replacement
1471
    if (unlikely(table->next_number_field->store((int64_t) nr, true)))
1 by brian
clean slate
1472
      nr= table->next_number_field->val_int();
1473
  }
1474
  if (append)
1475
  {
1476
    auto_inc_interval_for_cur_row.replace(nr, nb_reserved_values,
1477
                                          variables->auto_increment_increment);
1478
  }
1479
1480
  /*
1481
    Record this autogenerated value. If the caller then
1482
    succeeds to insert this value, it will call
1483
    record_first_successful_insert_id_in_cur_stmt()
1484
    which will set first_successful_insert_id_in_cur_stmt if it's not
1485
    already set.
1486
  */
1487
  insert_id_for_cur_row= nr;
1488
  /*
1489
    Set next insert id to point to next auto-increment value to be able to
1490
    handle multi-row statements.
1491
  */
1492
  set_next_insert_id(compute_next_insert_id(nr, variables));
1493
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
1494
  return(0);
1 by brian
clean slate
1495
}
1496
1497
1498
/**
1499
  Reserves an interval of auto_increment values from the handler.
1500
1501
  offset and increment means that we want values to be of the form
1502
  offset + N * increment, where N>=0 is integer.
1503
  If the function sets *first_value to ~(uint64_t)0 it means an error.
163 by Brian Aker
Merge Monty's code.
1504
  If the function sets *nb_reserved_values to UINT64_MAX it means it has
1 by brian
clean slate
1505
  reserved to "positive infinite".
1506
1507
  @param offset
1508
  @param increment
1509
  @param nb_desired_values   how many values we want
1510
  @param first_value         (OUT) the first value reserved by the handler
1511
  @param nb_reserved_values  (OUT) how many values the handler reserved
1512
*/
779.1.27 by Monty Taylor
Got rid of __attribute__((unused)) and the like from the .cc files.
1513
void handler::get_auto_increment(uint64_t ,
1514
                                 uint64_t ,
1515
                                 uint64_t ,
1 by brian
clean slate
1516
                                 uint64_t *first_value,
1517
                                 uint64_t *nb_reserved_values)
1518
{
1519
  uint64_t nr;
1520
  int error;
1521
1522
  (void) extra(HA_EXTRA_KEYREAD);
1003.1.7 by Brian Aker
Add mark_columns_used_by_index_no_reset() with just index (assumes read_set
1523
  table->mark_columns_used_by_index_no_reset(table->s->next_number_index);
1 by brian
clean slate
1524
  index_init(table->s->next_number_index, 1);
1525
  if (table->s->next_number_keypart == 0)
1526
  {						// Autoincrement at key-start
1527
    error=index_last(table->record[1]);
1528
    /*
1529
      MySQL implicitely assumes such method does locking (as MySQL decides to
1530
      use nr+increment without checking again with the handler, in
1531
      handler::update_auto_increment()), so reserves to infinite.
1532
    */
163 by Brian Aker
Merge Monty's code.
1533
    *nb_reserved_values= UINT64_MAX;
1 by brian
clean slate
1534
  }
1535
  else
1536
  {
481 by Brian Aker
Remove all of uchar.
1537
    unsigned char key[MAX_KEY_LENGTH];
1 by brian
clean slate
1538
    key_copy(key, table->record[0],
1539
             table->key_info + table->s->next_number_index,
1540
             table->s->next_number_key_offset);
1541
    error= index_read_map(table->record[1], key,
1542
                          make_prev_keypart_map(table->s->next_number_keypart),
1543
                          HA_READ_PREFIX_LAST);
1544
    /*
1545
      MySQL needs to call us for next row: assume we are inserting ("a",null)
1546
      here, we return 3, and next this statement will want to insert
1547
      ("b",null): there is no reason why ("b",3+1) would be the good row to
1548
      insert: maybe it already exists, maybe 3+1 is too large...
1549
    */
1550
    *nb_reserved_values= 1;
1551
  }
1552
1553
  if (error)
1554
    nr=1;
1555
  else
1556
    nr= ((uint64_t) table->next_number_field->
1557
         val_int_offset(table->s->rec_buff_length)+1);
1558
  index_end();
1559
  (void) extra(HA_EXTRA_NO_KEYREAD);
1560
  *first_value= nr;
1561
}
1562
1563
1564
void handler::ha_release_auto_increment()
1565
{
1566
  release_auto_increment();
1567
  insert_id_for_cur_row= 0;
1568
  auto_inc_interval_for_cur_row.replace(0, 0, 0);
1569
  if (next_insert_id > 0)
1570
  {
1571
    next_insert_id= 0;
1572
    /*
1573
      this statement used forced auto_increment values if there were some,
1574
      wipe them away for other statements.
1575
    */
1576
    table->in_use->auto_inc_intervals_forced.empty();
1577
  }
1578
}
1579
1580
482 by Brian Aker
Remove uint.
1581
void handler::print_keydup_error(uint32_t key_nr, const char *msg)
1 by brian
clean slate
1582
{
1583
  /* Write the duplicated key in the error message */
1584
  char key[MAX_KEY_LENGTH];
1585
  String str(key,sizeof(key),system_charset_info);
1586
1587
  if (key_nr == MAX_KEY)
1588
  {
1589
    /* Key is unknown */
1590
    str.copy("", 0, system_charset_info);
1591
    my_printf_error(ER_DUP_ENTRY, msg, MYF(0), str.c_ptr(), "*UNKNOWN*");
1592
  }
1593
  else
1594
  {
1595
    /* Table is opened and defined at this point */
895 by Brian Aker
Completion (?) of uint conversion.
1596
    key_unpack(&str,table,(uint32_t) key_nr);
1597
    uint32_t max_length=DRIZZLE_ERRMSG_SIZE-(uint32_t) strlen(msg);
1 by brian
clean slate
1598
    if (str.length() >= max_length)
1599
    {
1600
      str.length(max_length-4);
1601
      str.append(STRING_WITH_LEN("..."));
1602
    }
1603
    my_printf_error(ER_DUP_ENTRY, msg,
1604
		    MYF(0), str.c_ptr(), table->key_info[key_nr].name);
1605
  }
1606
}
1607
1608
1609
/**
1610
  Print error that we got from handler function.
1611
1612
  @note
1613
    In case of delete table it's only safe to use the following parts of
1614
    the 'table' structure:
1615
    - table->s->path
1616
    - table->alias
1617
*/
1618
void handler::print_error(int error, myf errflag)
1619
{
1620
  int textno=ER_GET_ERRNO;
1621
  switch (error) {
1622
  case EACCES:
1623
    textno=ER_OPEN_AS_READONLY;
1624
    break;
1625
  case EAGAIN:
1626
    textno=ER_FILE_USED;
1627
    break;
1628
  case ENOENT:
1629
    textno=ER_FILE_NOT_FOUND;
1630
    break;
1631
  case HA_ERR_KEY_NOT_FOUND:
1632
  case HA_ERR_NO_ACTIVE_RECORD:
1633
  case HA_ERR_END_OF_FILE:
1634
    textno=ER_KEY_NOT_FOUND;
1635
    break;
1636
  case HA_ERR_WRONG_MRG_TABLE_DEF:
1637
    textno=ER_WRONG_MRG_TABLE;
1638
    break;
1639
  case HA_ERR_FOUND_DUPP_KEY:
1640
  {
482 by Brian Aker
Remove uint.
1641
    uint32_t key_nr=get_dup_key(error);
1 by brian
clean slate
1642
    if ((int) key_nr >= 0)
1643
    {
1644
      print_keydup_error(key_nr, ER(ER_DUP_ENTRY_WITH_KEY_NAME));
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
1645
      return;
1 by brian
clean slate
1646
    }
1647
    textno=ER_DUP_KEY;
1648
    break;
1649
  }
1650
  case HA_ERR_FOREIGN_DUPLICATE_KEY:
1651
  {
482 by Brian Aker
Remove uint.
1652
    uint32_t key_nr= get_dup_key(error);
1 by brian
clean slate
1653
    if ((int) key_nr >= 0)
1654
    {
482 by Brian Aker
Remove uint.
1655
      uint32_t max_length;
1 by brian
clean slate
1656
      /* Write the key in the error message */
1657
      char key[MAX_KEY_LENGTH];
1658
      String str(key,sizeof(key),system_charset_info);
1659
      /* Table is opened and defined at this point */
895 by Brian Aker
Completion (?) of uint conversion.
1660
      key_unpack(&str,table,(uint32_t) key_nr);
261.4.1 by Felipe
- Renamed MYSQL_ERROR to DRIZZLE_ERROR.
1661
      max_length= (DRIZZLE_ERRMSG_SIZE-
895 by Brian Aker
Completion (?) of uint conversion.
1662
                   (uint32_t) strlen(ER(ER_FOREIGN_DUPLICATE_KEY)));
1 by brian
clean slate
1663
      if (str.length() >= max_length)
1664
      {
1665
        str.length(max_length-4);
1666
        str.append(STRING_WITH_LEN("..."));
1667
      }
1668
      my_error(ER_FOREIGN_DUPLICATE_KEY, MYF(0), table_share->table_name.str,
1669
        str.c_ptr(), key_nr+1);
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
1670
      return;
1 by brian
clean slate
1671
    }
1672
    textno= ER_DUP_KEY;
1673
    break;
1674
  }
1675
  case HA_ERR_FOUND_DUPP_UNIQUE:
1676
    textno=ER_DUP_UNIQUE;
1677
    break;
1678
  case HA_ERR_RECORD_CHANGED:
1679
    textno=ER_CHECKREAD;
1680
    break;
1681
  case HA_ERR_CRASHED:
1682
    textno=ER_NOT_KEYFILE;
1683
    break;
1684
  case HA_ERR_WRONG_IN_RECORD:
1685
    textno= ER_CRASHED_ON_USAGE;
1686
    break;
1687
  case HA_ERR_CRASHED_ON_USAGE:
1688
    textno=ER_CRASHED_ON_USAGE;
1689
    break;
1690
  case HA_ERR_NOT_A_TABLE:
1691
    textno= error;
1692
    break;
1693
  case HA_ERR_CRASHED_ON_REPAIR:
1694
    textno=ER_CRASHED_ON_REPAIR;
1695
    break;
1696
  case HA_ERR_OUT_OF_MEM:
1697
    textno=ER_OUT_OF_RESOURCES;
1698
    break;
1699
  case HA_ERR_WRONG_COMMAND:
1700
    textno=ER_ILLEGAL_HA;
1701
    break;
1702
  case HA_ERR_OLD_FILE:
1703
    textno=ER_OLD_KEYFILE;
1704
    break;
1705
  case HA_ERR_UNSUPPORTED:
1706
    textno=ER_UNSUPPORTED_EXTENSION;
1707
    break;
1708
  case HA_ERR_RECORD_FILE_FULL:
1709
  case HA_ERR_INDEX_FILE_FULL:
1710
    textno=ER_RECORD_FILE_FULL;
1711
    break;
1712
  case HA_ERR_LOCK_WAIT_TIMEOUT:
1713
    textno=ER_LOCK_WAIT_TIMEOUT;
1714
    break;
1715
  case HA_ERR_LOCK_TABLE_FULL:
1716
    textno=ER_LOCK_TABLE_FULL;
1717
    break;
1718
  case HA_ERR_LOCK_DEADLOCK:
1719
    textno=ER_LOCK_DEADLOCK;
1720
    break;
1721
  case HA_ERR_READ_ONLY_TRANSACTION:
1722
    textno=ER_READ_ONLY_TRANSACTION;
1723
    break;
1724
  case HA_ERR_CANNOT_ADD_FOREIGN:
1725
    textno=ER_CANNOT_ADD_FOREIGN;
1726
    break;
1727
  case HA_ERR_ROW_IS_REFERENCED:
1728
  {
1729
    String str;
1730
    get_error_message(error, &str);
1731
    my_error(ER_ROW_IS_REFERENCED_2, MYF(0), str.c_ptr_safe());
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
1732
    return;
1 by brian
clean slate
1733
  }
1734
  case HA_ERR_NO_REFERENCED_ROW:
1735
  {
1736
    String str;
1737
    get_error_message(error, &str);
1738
    my_error(ER_NO_REFERENCED_ROW_2, MYF(0), str.c_ptr_safe());
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
1739
    return;
1 by brian
clean slate
1740
  }
1741
  case HA_ERR_TABLE_DEF_CHANGED:
1742
    textno=ER_TABLE_DEF_CHANGED;
1743
    break;
1744
  case HA_ERR_NO_SUCH_TABLE:
1745
    my_error(ER_NO_SUCH_TABLE, MYF(0), table_share->db.str,
1746
             table_share->table_name.str);
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
1747
    return;
1 by brian
clean slate
1748
  case HA_ERR_RBR_LOGGING_FAILED:
1749
    textno= ER_BINLOG_ROW_LOGGING_FAILED;
1750
    break;
1751
  case HA_ERR_DROP_INDEX_FK:
1752
  {
1753
    const char *ptr= "???";
482 by Brian Aker
Remove uint.
1754
    uint32_t key_nr= get_dup_key(error);
1 by brian
clean slate
1755
    if ((int) key_nr >= 0)
1756
      ptr= table->key_info[key_nr].name;
1757
    my_error(ER_DROP_INDEX_FK, MYF(0), ptr);
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
1758
    return;
1 by brian
clean slate
1759
  }
1760
  case HA_ERR_TABLE_NEEDS_UPGRADE:
1761
    textno=ER_TABLE_NEEDS_UPGRADE;
1762
    break;
1763
  case HA_ERR_TABLE_READONLY:
1764
    textno= ER_OPEN_AS_READONLY;
1765
    break;
1766
  case HA_ERR_AUTOINC_READ_FAILED:
1767
    textno= ER_AUTOINC_READ_FAILED;
1768
    break;
1769
  case HA_ERR_AUTOINC_ERANGE:
1770
    textno= ER_WARN_DATA_OUT_OF_RANGE;
1771
    break;
1772
  case HA_ERR_LOCK_OR_ACTIVE_TRANSACTION:
1773
    my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
1774
               ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
1775
    return;
1 by brian
clean slate
1776
  default:
1777
    {
1778
      /* The error was "unknown" to this function.
1779
	 Ask handler if it has got a message for this error */
56 by brian
Next pass of true/false update.
1780
      bool temporary= false;
1 by brian
clean slate
1781
      String str;
1782
      temporary= get_error_message(error, &str);
1783
      if (!str.is_empty())
1784
      {
960.2.37 by Monty Taylor
More naming fixes.
1785
	      const char* engine_name= table_type();
1786
	      if (temporary)
1787
	        my_error(ER_GET_TEMPORARY_ERRMSG, MYF(0), error, str.ptr(),
1788
                   engine_name);
1789
	      else
1790
	        my_error(ER_GET_ERRMSG, MYF(0), error, str.ptr(), engine_name);
1 by brian
clean slate
1791
      }
1792
      else
960.2.37 by Monty Taylor
More naming fixes.
1793
      {
1794
	      my_error(ER_GET_ERRNO,errflag,error);
1795
      }
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
1796
      return;
1 by brian
clean slate
1797
    }
1798
  }
1799
  my_error(textno, errflag, table_share->table_name.str, error);
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
1800
  return;
1 by brian
clean slate
1801
}
1802
1803
1804
/**
1805
  Return an error message specific to this handler.
1806
1807
  @param error  error code previously returned by handler
1808
  @param buf    pointer to String where to add error message
1809
1810
  @return
1811
    Returns true if this is a temporary error
1812
*/
779.1.27 by Monty Taylor
Got rid of __attribute__((unused)) and the like from the .cc files.
1813
bool handler::get_error_message(int ,
1814
                                String* )
1 by brian
clean slate
1815
{
56 by brian
Next pass of true/false update.
1816
  return false;
1 by brian
clean slate
1817
}
1818
1819
1820
int handler::ha_check_for_upgrade(HA_CHECK_OPT *check_opt)
1821
{
1822
  KEY *keyinfo, *keyend;
1823
  KEY_PART_INFO *keypart, *keypartend;
1824
1825
  if (!table->s->mysql_version)
1826
  {
1827
    /* check for blob-in-key error */
1828
    keyinfo= table->key_info;
1829
    keyend= table->key_info + table->s->keys;
1830
    for (; keyinfo < keyend; keyinfo++)
1831
    {
1832
      keypart= keyinfo->key_part;
1833
      keypartend= keypart + keyinfo->key_parts;
1834
      for (; keypart < keypartend; keypart++)
1835
      {
1836
        if (!keypart->fieldnr)
1837
          continue;
1838
        Field *field= table->field[keypart->fieldnr-1];
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
1839
        if (field->type() == DRIZZLE_TYPE_BLOB)
1 by brian
clean slate
1840
        {
1841
          return HA_ADMIN_NEEDS_CHECK;
1842
        }
1843
      }
1844
    }
1845
  }
1846
  return check_for_upgrade(check_opt);
1847
}
1848
1849
1850
/* Code left, but Drizzle has no legacy yet (while MySQL did) */
1851
int handler::check_old_types()
1852
{
1853
  return 0;
1854
}
1855
1856
/**
1857
  @return
1858
    key if error because of duplicated keys
1859
*/
482 by Brian Aker
Remove uint.
1860
uint32_t handler::get_dup_key(int error)
1 by brian
clean slate
1861
{
895 by Brian Aker
Completion (?) of uint conversion.
1862
  table->file->errkey  = (uint32_t) -1;
1 by brian
clean slate
1863
  if (error == HA_ERR_FOUND_DUPP_KEY || error == HA_ERR_FOREIGN_DUPLICATE_KEY ||
1864
      error == HA_ERR_FOUND_DUPP_UNIQUE ||
1865
      error == HA_ERR_DROP_INDEX_FK)
1866
    info(HA_STATUS_ERRKEY | HA_STATUS_NO_LOCK);
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
1867
  return(table->file->errkey);
1 by brian
clean slate
1868
}
1869
1870
1871
/**
1872
  Delete all files with extension from bas_ext().
1873
1874
  @param name		Base name of table
1875
1876
  @note
1877
    We assume that the handler may return more extensions than
1878
    was actually used for the file.
1879
1880
  @retval
1881
    0   If we successfully deleted at least one file from base_ext and
1882
    didn't get any other errors than ENOENT
1883
  @retval
1884
    !0  Error
1885
*/
1886
int handler::delete_table(const char *name)
1887
{
1888
  int error= 0;
1889
  int enoent_or_zero= ENOENT;                   // Error if no file was deleted
1890
  char buff[FN_REFLEN];
1891
1892
  for (const char **ext=bas_ext(); *ext ; ext++)
1893
  {
1894
    fn_format(buff, name, "", *ext, MY_UNPACK_FILENAME|MY_APPEND_EXT);
1895
    if (my_delete_with_symlink(buff, MYF(0)))
1896
    {
1897
      if ((error= my_errno) != ENOENT)
1898
	break;
1899
    }
1900
    else
1901
      enoent_or_zero= 0;                        // No error for ENOENT
1902
    error= enoent_or_zero;
1903
  }
1904
  return error;
1905
}
1906
1907
1908
int handler::rename_table(const char * from, const char * to)
1909
{
1910
  int error= 0;
1911
  for (const char **ext= bas_ext(); *ext ; ext++)
1912
  {
1913
    if (rename_file_ext(from, to, *ext))
1914
    {
1915
      if ((error=my_errno) != ENOENT)
1916
	break;
1917
      error= 0;
1918
    }
1919
  }
1920
  return error;
1921
}
1922
1923
1924
void handler::drop_table(const char *name)
1925
{
1926
  close();
1927
  delete_table(name);
1928
}
1929
1930
1931
/**
1932
  Performs checks upon the table.
1933
520.1.22 by Brian Aker
Second pass of thd cleanup
1934
  @param session                thread doing CHECK Table operation
1 by brian
clean slate
1935
  @param check_opt          options from the parser
1936
1937
  @retval
1938
    HA_ADMIN_OK               Successful upgrade
1939
  @retval
1940
    HA_ADMIN_NEEDS_UPGRADE    Table has structures requiring upgrade
1941
  @retval
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
1942
    HA_ADMIN_NEEDS_ALTER      Table has structures requiring ALTER Table
1 by brian
clean slate
1943
  @retval
1944
    HA_ADMIN_NOT_IMPLEMENTED
1945
*/
520.1.22 by Brian Aker
Second pass of thd cleanup
1946
int handler::ha_check(Session *session, HA_CHECK_OPT *check_opt)
1 by brian
clean slate
1947
{
1948
  int error;
1949
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
1950
  if (table->s->mysql_version < DRIZZLE_VERSION_ID)
1 by brian
clean slate
1951
  {
1952
    if ((error= check_old_types()))
1953
      return error;
1954
    error= ha_check_for_upgrade(check_opt);
1955
    if (error && (error != HA_ADMIN_NEEDS_CHECK))
1956
      return error;
1957
  }
520.1.22 by Brian Aker
Second pass of thd cleanup
1958
  if ((error= check(session, check_opt)))
1 by brian
clean slate
1959
    return error;
590.1.4 by Stewart Smith
remove frm_version from TABLE_SHARE
1960
  return HA_ADMIN_OK;
1 by brian
clean slate
1961
}
1962
1963
/**
1964
  A helper function to mark a transaction read-write,
1965
  if it is started.
1966
*/
1967
1968
inline
1969
void
1970
handler::mark_trx_read_write()
1971
{
960.2.37 by Monty Taylor
More naming fixes.
1972
  Ha_trx_info *ha_info= &ha_session()->ha_data[engine->slot].ha_info[0];
1 by brian
clean slate
1973
  /*
1974
    When a storage engine method is called, the transaction must
1975
    have been started, unless it's a DDL call, for which the
1976
    storage engine starts the transaction internally, and commits
1977
    it internally, without registering in the ha_list.
1978
    Unfortunately here we can't know know for sure if the engine
1979
    has registered the transaction or not, so we must check.
1980
  */
1981
  if (ha_info->is_started())
1982
  {
1983
    /*
1984
      table_share can be NULL in ha_delete_table(). See implementation
1985
      of standalone function ha_delete_table() in sql_base.cc.
1986
    */
1987
    if (table_share == NULL || table_share->tmp_table == NO_TMP_TABLE)
1988
      ha_info->set_trx_read_write();
1989
  }
1990
}
1991
1992
1993
/**
1994
  Repair table: public interface.
1995
1996
  @sa handler::repair()
1997
*/
1998
520.1.22 by Brian Aker
Second pass of thd cleanup
1999
int handler::ha_repair(Session* session, HA_CHECK_OPT* check_opt)
1 by brian
clean slate
2000
{
2001
  int result;
2002
2003
  mark_trx_read_write();
2004
520.1.22 by Brian Aker
Second pass of thd cleanup
2005
  if ((result= repair(session, check_opt)))
1 by brian
clean slate
2006
    return result;
590.1.4 by Stewart Smith
remove frm_version from TABLE_SHARE
2007
  return HA_ADMIN_OK;
1 by brian
clean slate
2008
}
2009
2010
2011
/**
2012
  Bulk update row: public interface.
2013
2014
  @sa handler::bulk_update_row()
2015
*/
2016
2017
int
481 by Brian Aker
Remove all of uchar.
2018
handler::ha_bulk_update_row(const unsigned char *old_data, unsigned char *new_data,
482 by Brian Aker
Remove uint.
2019
                            uint32_t *dup_key_found)
1 by brian
clean slate
2020
{
2021
  mark_trx_read_write();
2022
2023
  return bulk_update_row(old_data, new_data, dup_key_found);
2024
}
2025
2026
2027
/**
2028
  Delete all rows: public interface.
2029
2030
  @sa handler::delete_all_rows()
2031
*/
2032
2033
int
2034
handler::ha_delete_all_rows()
2035
{
2036
  mark_trx_read_write();
2037
2038
  return delete_all_rows();
2039
}
2040
2041
2042
/**
2043
  Reset auto increment: public interface.
2044
2045
  @sa handler::reset_auto_increment()
2046
*/
2047
2048
int
2049
handler::ha_reset_auto_increment(uint64_t value)
2050
{
2051
  mark_trx_read_write();
2052
2053
  return reset_auto_increment(value);
2054
}
2055
2056
2057
/**
2058
  Optimize table: public interface.
2059
2060
  @sa handler::optimize()
2061
*/
2062
2063
int
520.1.22 by Brian Aker
Second pass of thd cleanup
2064
handler::ha_optimize(Session* session, HA_CHECK_OPT* check_opt)
1 by brian
clean slate
2065
{
2066
  mark_trx_read_write();
2067
520.1.22 by Brian Aker
Second pass of thd cleanup
2068
  return optimize(session, check_opt);
1 by brian
clean slate
2069
}
2070
2071
2072
/**
2073
  Analyze table: public interface.
2074
2075
  @sa handler::analyze()
2076
*/
2077
2078
int
520.1.22 by Brian Aker
Second pass of thd cleanup
2079
handler::ha_analyze(Session* session, HA_CHECK_OPT* check_opt)
1 by brian
clean slate
2080
{
2081
  mark_trx_read_write();
2082
520.1.22 by Brian Aker
Second pass of thd cleanup
2083
  return analyze(session, check_opt);
1 by brian
clean slate
2084
}
2085
2086
2087
/**
2088
  Check and repair table: public interface.
2089
2090
  @sa handler::check_and_repair()
2091
*/
2092
2093
bool
520.1.22 by Brian Aker
Second pass of thd cleanup
2094
handler::ha_check_and_repair(Session *session)
1 by brian
clean slate
2095
{
2096
  mark_trx_read_write();
2097
520.1.22 by Brian Aker
Second pass of thd cleanup
2098
  return check_and_repair(session);
1 by brian
clean slate
2099
}
2100
2101
2102
/**
2103
  Disable indexes: public interface.
2104
2105
  @sa handler::disable_indexes()
2106
*/
2107
2108
int
482 by Brian Aker
Remove uint.
2109
handler::ha_disable_indexes(uint32_t mode)
1 by brian
clean slate
2110
{
2111
  mark_trx_read_write();
2112
2113
  return disable_indexes(mode);
2114
}
2115
2116
2117
/**
2118
  Enable indexes: public interface.
2119
2120
  @sa handler::enable_indexes()
2121
*/
2122
2123
int
482 by Brian Aker
Remove uint.
2124
handler::ha_enable_indexes(uint32_t mode)
1 by brian
clean slate
2125
{
2126
  mark_trx_read_write();
2127
2128
  return enable_indexes(mode);
2129
}
2130
2131
2132
/**
2133
  Discard or import tablespace: public interface.
2134
2135
  @sa handler::discard_or_import_tablespace()
2136
*/
2137
2138
int
200 by Brian Aker
my_bool from handler and set_var
2139
handler::ha_discard_or_import_tablespace(bool discard)
1 by brian
clean slate
2140
{
2141
  mark_trx_read_write();
2142
2143
  return discard_or_import_tablespace(discard);
2144
}
2145
2146
2147
/**
2148
  Prepare for alter: public interface.
2149
2150
  Called to prepare an *online* ALTER.
2151
2152
  @sa handler::prepare_for_alter()
2153
*/
2154
2155
void
2156
handler::ha_prepare_for_alter()
2157
{
2158
  mark_trx_read_write();
2159
2160
  prepare_for_alter();
2161
}
2162
2163
2164
/**
2165
  Rename table: public interface.
2166
2167
  @sa handler::rename_table()
2168
*/
2169
2170
int
2171
handler::ha_rename_table(const char *from, const char *to)
2172
{
2173
  mark_trx_read_write();
2174
2175
  return rename_table(from, to);
2176
}
2177
2178
2179
/**
2180
  Delete table: public interface.
2181
2182
  @sa handler::delete_table()
2183
*/
2184
2185
int
2186
handler::ha_delete_table(const char *name)
2187
{
2188
  mark_trx_read_write();
2189
2190
  return delete_table(name);
2191
}
2192
2193
2194
/**
2195
  Drop table in the engine: public interface.
2196
2197
  @sa handler::drop_table()
2198
*/
2199
2200
void
2201
handler::ha_drop_table(const char *name)
2202
{
2203
  mark_trx_read_write();
2204
2205
  return drop_table(name);
2206
}
2207
2208
2209
/**
2210
  Create a table in the engine: public interface.
2211
2212
  @sa handler::create()
2213
*/
2214
2215
int
779.3.10 by Monty Taylor
Turned on -Wshadow.
2216
handler::ha_create(const char *name, Table *form, HA_CREATE_INFO *create_info)
1 by brian
clean slate
2217
{
2218
  mark_trx_read_write();
2219
779.3.10 by Monty Taylor
Turned on -Wshadow.
2220
  return create(name, form, create_info);
1 by brian
clean slate
2221
}
2222
2223
2224
/**
2225
  Create handler files for CREATE TABLE: public interface.
2226
2227
  @sa handler::create_handler_files()
2228
*/
2229
2230
int
2231
handler::ha_create_handler_files(const char *name, const char *old_name,
779.3.10 by Monty Taylor
Turned on -Wshadow.
2232
                                 int action_flag, HA_CREATE_INFO *create_info)
1 by brian
clean slate
2233
{
2234
  mark_trx_read_write();
2235
779.3.10 by Monty Taylor
Turned on -Wshadow.
2236
  return create_handler_files(name, old_name, action_flag, create_info);
1 by brian
clean slate
2237
}
2238
2239
2240
/**
2241
  Tell the storage engine that it is allowed to "disable transaction" in the
2242
  handler. It is a hint that ACID is not required - it is used in NDB for
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
2243
  ALTER Table, for example, when data are copied to temporary table.
1 by brian
clean slate
2244
  A storage engine may treat this hint any way it likes. NDB for example
2245
  starts to commit every now and then automatically.
2246
  This hint can be safely ignored.
2247
*/
520.1.22 by Brian Aker
Second pass of thd cleanup
2248
int ha_enable_transaction(Session *session, bool on)
1 by brian
clean slate
2249
{
2250
  int error=0;
2251
520.1.22 by Brian Aker
Second pass of thd cleanup
2252
  if ((session->transaction.on= on))
1 by brian
clean slate
2253
  {
2254
    /*
2255
      Now all storage engines should have transaction handling enabled.
2256
      But some may have it enabled all the time - "disabling" transactions
2257
      is an optimization hint that storage engine is free to ignore.
2258
      So, let's commit an open transaction (if any) now.
2259
    */
520.1.22 by Brian Aker
Second pass of thd cleanup
2260
    if (!(error= ha_commit_trans(session, 0)))
934.2.11 by Jay Pipes
Moves end_trans(), begin_trans(), end_active_trans() out of the parser module and adds startTransaction(), endTransaction(), and endActiveTransaction() member methods of Session object.
2261
      if (! session->endTransaction(COMMIT))
2262
        error= 1;
2263
1 by brian
clean slate
2264
  }
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
2265
  return(error);
1 by brian
clean slate
2266
}
2267
482 by Brian Aker
Remove uint.
2268
int handler::index_next_same(unsigned char *buf, const unsigned char *key, uint32_t keylen)
1 by brian
clean slate
2269
{
2270
  int error;
2271
  if (!(error=index_next(buf)))
2272
  {
2273
    my_ptrdiff_t ptrdiff= buf - table->record[0];
481 by Brian Aker
Remove all of uchar.
2274
    unsigned char *save_record_0= NULL;
1 by brian
clean slate
2275
    KEY *key_info= NULL;
2276
    KEY_PART_INFO *key_part;
2277
    KEY_PART_INFO *key_part_end= NULL;
2278
2279
    /*
2280
      key_cmp_if_same() compares table->record[0] against 'key'.
2281
      In parts it uses table->record[0] directly, in parts it uses
2282
      field objects with their local pointers into table->record[0].
2283
      If 'buf' is distinct from table->record[0], we need to move
2284
      all record references. This is table->record[0] itself and
2285
      the field pointers of the fields used in this key.
2286
    */
2287
    if (ptrdiff)
2288
    {
2289
      save_record_0= table->record[0];
2290
      table->record[0]= buf;
2291
      key_info= table->key_info + active_index;
2292
      key_part= key_info->key_part;
2293
      key_part_end= key_part + key_info->key_parts;
2294
      for (; key_part < key_part_end; key_part++)
2295
      {
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
2296
        assert(key_part->field);
1 by brian
clean slate
2297
        key_part->field->move_field_offset(ptrdiff);
2298
      }
2299
    }
2300
2301
    if (key_cmp_if_same(table, key, active_index, keylen))
2302
    {
2303
      table->status=STATUS_NOT_FOUND;
2304
      error=HA_ERR_END_OF_FILE;
2305
    }
2306
2307
    /* Move back if necessary. */
2308
    if (ptrdiff)
2309
    {
2310
      table->record[0]= save_record_0;
2311
      for (key_part= key_info->key_part; key_part < key_part_end; key_part++)
2312
        key_part->field->move_field_offset(-ptrdiff);
2313
    }
2314
  }
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
2315
  return(error);
1 by brian
clean slate
2316
}
2317
2318
2319
/****************************************************************************
2320
** Some general functions that isn't in the handler class
2321
****************************************************************************/
2322
2323
2324
void st_ha_check_opt::init()
2325
{
792 by Brian Aker
Refactor for myisam specifics in handler
2326
  flags= 0; 
2327
  use_frm= false;
1 by brian
clean slate
2328
}
2329
2330
2331
/*****************************************************************************
2332
  Key cache handling.
2333
2334
  This code is only relevant for ISAM/MyISAM tables
2335
2336
  key_cache->cache may be 0 only in the case where a key cache is not
2337
  initialized or when we where not able to init the key cache in a previous
2338
  call to ha_init_key_cache() (probably out of memory)
2339
*****************************************************************************/
2340
2341
/**
2342
  Init a key cache if it has not been initied before.
2343
*/
779.1.27 by Monty Taylor
Got rid of __attribute__((unused)) and the like from the .cc files.
2344
int ha_init_key_cache(const char *,
77.1.15 by Monty Taylor
Bunch of warning cleanups.
2345
                      KEY_CACHE *key_cache)
1 by brian
clean slate
2346
{
2347
  if (!key_cache->key_cache_inited)
2348
  {
2349
    pthread_mutex_lock(&LOCK_global_system_variables);
61 by Brian Aker
Conversion of handler type.
2350
    uint32_t tmp_buff_size= (uint32_t) key_cache->param_buff_size;
895 by Brian Aker
Completion (?) of uint conversion.
2351
    uint32_t tmp_block_size= (uint32_t) key_cache->param_block_size;
482 by Brian Aker
Remove uint.
2352
    uint32_t division_limit= key_cache->param_division_limit;
2353
    uint32_t age_threshold=  key_cache->param_age_threshold;
1 by brian
clean slate
2354
    pthread_mutex_unlock(&LOCK_global_system_variables);
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
2355
    return(!init_key_cache(key_cache,
1 by brian
clean slate
2356
				tmp_block_size,
2357
				tmp_buff_size,
2358
				division_limit, age_threshold));
2359
  }
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
2360
  return(0);
1 by brian
clean slate
2361
}
2362
2363
2364
/**
2365
  Resize key cache.
2366
*/
2367
int ha_resize_key_cache(KEY_CACHE *key_cache)
2368
{
2369
  if (key_cache->key_cache_inited)
2370
  {
2371
    pthread_mutex_lock(&LOCK_global_system_variables);
2372
    long tmp_buff_size= (long) key_cache->param_buff_size;
2373
    long tmp_block_size= (long) key_cache->param_block_size;
482 by Brian Aker
Remove uint.
2374
    uint32_t division_limit= key_cache->param_division_limit;
2375
    uint32_t age_threshold=  key_cache->param_age_threshold;
1 by brian
clean slate
2376
    pthread_mutex_unlock(&LOCK_global_system_variables);
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
2377
    return(!resize_key_cache(key_cache, tmp_block_size,
1 by brian
clean slate
2378
				  tmp_buff_size,
2379
				  division_limit, age_threshold));
2380
  }
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
2381
  return(0);
1 by brian
clean slate
2382
}
2383
2384
2385
/**
2386
  Change parameters for key cache (like size)
2387
*/
2388
int ha_change_key_cache_param(KEY_CACHE *key_cache)
2389
{
2390
  if (key_cache->key_cache_inited)
2391
  {
2392
    pthread_mutex_lock(&LOCK_global_system_variables);
482 by Brian Aker
Remove uint.
2393
    uint32_t division_limit= key_cache->param_division_limit;
2394
    uint32_t age_threshold=  key_cache->param_age_threshold;
1 by brian
clean slate
2395
    pthread_mutex_unlock(&LOCK_global_system_variables);
2396
    change_key_cache_param(key_cache, division_limit, age_threshold);
2397
  }
2398
  return 0;
2399
}
2400
2401
/**
2402
  Free memory allocated by a key cache.
2403
*/
2404
int ha_end_key_cache(KEY_CACHE *key_cache)
2405
{
2406
  end_key_cache(key_cache, 1);		// Can never fail
2407
  return 0;
2408
}
2409
2410
/**
2411
  Move all tables from one key cache to another one.
2412
*/
2413
int ha_change_key_cache(KEY_CACHE *old_key_cache,
2414
			KEY_CACHE *new_key_cache)
2415
{
2416
  mi_change_key_cache(old_key_cache, new_key_cache);
2417
  return 0;
2418
}
2419
2420
2421
/**
2422
  Calculate cost of 'index only' scan for given index and number of records
2423
2424
  @param keynr    Index number
2425
  @param records  Estimated number of records to be retrieved
2426
2427
  @note
2428
    It is assumed that we will read trough the whole key range and that all
2429
    key blocks are half full (normally things are much better). It is also
2430
    assumed that each time we read the next key from the index, the handler
2431
    performs a random seek, thus the cost is proportional to the number of
2432
    blocks read.
2433
2434
  @todo
2435
    Consider joining this function and handler::read_time() into one
2436
    handler::read_time(keynr, records, ranges, bool index_only) function.
2437
2438
  @return
2439
    Estimated cost of 'index only' scan
2440
*/
2441
779.3.10 by Monty Taylor
Turned on -Wshadow.
2442
double handler::index_only_read_time(uint32_t keynr, double key_records)
1 by brian
clean slate
2443
{
482 by Brian Aker
Remove uint.
2444
  uint32_t keys_per_block= (stats.block_size/2/
1 by brian
clean slate
2445
			(table->key_info[keynr].key_length + ref_length) + 1);
779.3.10 by Monty Taylor
Turned on -Wshadow.
2446
  return ((double) (key_records + keys_per_block-1) /
2447
          (double) keys_per_block);
1 by brian
clean slate
2448
}
2449
2450
2451
/****************************************************************************
2452
 * Default MRR implementation (MRR to non-MRR converter)
2453
 ***************************************************************************/
2454
2455
/**
2456
  Get cost and other information about MRR scan over a known list of ranges
2457
2458
  Calculate estimated cost and other information about an MRR scan for given
2459
  sequence of ranges.
2460
2461
  @param keyno           Index number
2462
  @param seq             Range sequence to be traversed
2463
  @param seq_init_param  First parameter for seq->init()
2464
  @param n_ranges_arg    Number of ranges in the sequence, or 0 if the caller
2465
                         can't efficiently determine it
2466
  @param bufsz    INOUT  IN:  Size of the buffer available for use
2467
                         OUT: Size of the buffer that is expected to be actually
2468
                              used, or 0 if buffer is not needed.
2469
  @param flags    INOUT  A combination of HA_MRR_* flags
2470
  @param cost     OUT    Estimated cost of MRR access
2471
2472
  @note
2473
    This method (or an overriding one in a derived class) must check for
520.1.22 by Brian Aker
Second pass of thd cleanup
2474
    session->killed and return HA_POS_ERROR if it is not zero. This is required
1 by brian
clean slate
2475
    for a user to be able to interrupt the calculation by killing the
2476
    connection/query.
2477
2478
  @retval
2479
    HA_POS_ERROR  Error or the engine is unable to perform the requested
2480
                  scan. Values of OUT parameters are undefined.
2481
  @retval
2482
    other         OK, *cost contains cost of the scan, *bufsz and *flags
2483
                  contain scan parameters.
2484
*/
2485
77.1.15 by Monty Taylor
Bunch of warning cleanups.
2486
ha_rows
482 by Brian Aker
Remove uint.
2487
handler::multi_range_read_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
77.1.15 by Monty Taylor
Bunch of warning cleanups.
2488
                                     void *seq_init_param,
779.1.27 by Monty Taylor
Got rid of __attribute__((unused)) and the like from the .cc files.
2489
                                     uint32_t ,
482 by Brian Aker
Remove uint.
2490
                                     uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
1 by brian
clean slate
2491
{
2492
  KEY_MULTI_RANGE range;
2493
  range_seq_t seq_it;
2494
  ha_rows rows, total_rows= 0;
482 by Brian Aker
Remove uint.
2495
  uint32_t n_ranges=0;
520.1.22 by Brian Aker
Second pass of thd cleanup
2496
  Session *session= current_session;
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
2497
1 by brian
clean slate
2498
  /* Default MRR implementation doesn't need buffer */
2499
  *bufsz= 0;
2500
2501
  seq_it= seq->init(seq_init_param, n_ranges, *flags);
2502
  while (!seq->next(seq_it, &range))
2503
  {
520.1.22 by Brian Aker
Second pass of thd cleanup
2504
    if (unlikely(session->killed != 0))
1 by brian
clean slate
2505
      return HA_POS_ERROR;
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
2506
1 by brian
clean slate
2507
    n_ranges++;
2508
    key_range *min_endp, *max_endp;
2509
    {
2510
      min_endp= range.start_key.length? &range.start_key : NULL;
2511
      max_endp= range.end_key.length? &range.end_key : NULL;
2512
    }
2513
    if ((range.range_flag & UNIQUE_RANGE) && !(range.range_flag & NULL_RANGE))
2514
      rows= 1; /* there can be at most one row */
2515
    else
2516
    {
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
2517
      if (HA_POS_ERROR == (rows= this->records_in_range(keyno, min_endp,
1 by brian
clean slate
2518
                                                        max_endp)))
2519
      {
2520
        /* Can't scan one range => can't do MRR scan at all */
2521
        total_rows= HA_POS_ERROR;
2522
        break;
2523
      }
2524
    }
2525
    total_rows += rows;
2526
  }
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
2527
1 by brian
clean slate
2528
  if (total_rows != HA_POS_ERROR)
2529
  {
2530
    /* The following calculation is the same as in multi_range_read_info(): */
2531
    *flags |= HA_MRR_USE_DEFAULT_IMPL;
2532
    cost->zero();
2533
    cost->avg_io_cost= 1; /* assume random seeks */
2534
    if ((*flags & HA_MRR_INDEX_ONLY) && total_rows > 2)
895 by Brian Aker
Completion (?) of uint conversion.
2535
      cost->io_count= index_only_read_time(keyno, (uint32_t)total_rows);
1 by brian
clean slate
2536
    else
2537
      cost->io_count= read_time(keyno, n_ranges, total_rows);
2538
    cost->cpu_cost= (double) total_rows / TIME_FOR_COMPARE + 0.01;
2539
  }
2540
  return total_rows;
2541
}
2542
2543
2544
/**
2545
  Get cost and other information about MRR scan over some sequence of ranges
2546
2547
  Calculate estimated cost and other information about an MRR scan for some
2548
  sequence of ranges.
2549
2550
  The ranges themselves will be known only at execution phase. When this
2551
  function is called we only know number of ranges and a (rough) E(#records)
2552
  within those ranges.
2553
2554
  Currently this function is only called for "n-keypart singlepoint" ranges,
2555
  i.e. each range is "keypart1=someconst1 AND ... AND keypartN=someconstN"
2556
2557
  The flags parameter is a combination of those flags: HA_MRR_SORTED,
2558
  HA_MRR_INDEX_ONLY, HA_MRR_NO_ASSOCIATION, HA_MRR_LIMITS.
2559
2560
  @param keyno           Index number
2561
  @param n_ranges        Estimated number of ranges (i.e. intervals) in the
2562
                         range sequence.
2563
  @param n_rows          Estimated total number of records contained within all
2564
                         of the ranges
2565
  @param bufsz    INOUT  IN:  Size of the buffer available for use
2566
                         OUT: Size of the buffer that will be actually used, or
2567
                              0 if buffer is not needed.
2568
  @param flags    INOUT  A combination of HA_MRR_* flags
2569
  @param cost     OUT    Estimated cost of MRR access
2570
2571
  @retval
2572
    0     OK, *cost contains cost of the scan, *bufsz and *flags contain scan
2573
          parameters.
2574
  @retval
2575
    other Error or can't perform the requested scan
2576
*/
2577
482 by Brian Aker
Remove uint.
2578
int handler::multi_range_read_info(uint32_t keyno, uint32_t n_ranges, uint32_t n_rows,
2579
                                   uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
1 by brian
clean slate
2580
{
2581
  *bufsz= 0; /* Default implementation doesn't need a buffer */
2582
2583
  *flags |= HA_MRR_USE_DEFAULT_IMPL;
2584
2585
  cost->zero();
2586
  cost->avg_io_cost= 1; /* assume random seeks */
2587
2588
  /* Produce the same cost as non-MRR code does */
2589
  if (*flags & HA_MRR_INDEX_ONLY)
2590
    cost->io_count= index_only_read_time(keyno, n_rows);
2591
  else
2592
    cost->io_count= read_time(keyno, n_ranges, n_rows);
2593
  return 0;
2594
}
2595
2596
2597
/**
2598
  Initialize the MRR scan
2599
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
2600
  Initialize the MRR scan. This function may do heavyweight scan
1 by brian
clean slate
2601
  initialization like row prefetching/sorting/etc (NOTE: but better not do
2602
  it here as we may not need it, e.g. if we never satisfy WHERE clause on
2603
  previous tables. For many implementations it would be natural to do such
2604
  initializations in the first multi_read_range_next() call)
2605
2606
  mode is a combination of the following flags: HA_MRR_SORTED,
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
2607
  HA_MRR_INDEX_ONLY, HA_MRR_NO_ASSOCIATION
1 by brian
clean slate
2608
2609
  @param seq             Range sequence to be traversed
2610
  @param seq_init_param  First parameter for seq->init()
2611
  @param n_ranges        Number of ranges in the sequence
2612
  @param mode            Flags, see the description section for the details
2613
  @param buf             INOUT: memory buffer to be used
2614
2615
  @note
2616
    One must have called index_init() before calling this function. Several
2617
    multi_range_read_init() calls may be made in course of one query.
2618
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
2619
    Until WL#2623 is done (see its text, section 3.2), the following will
1 by brian
clean slate
2620
    also hold:
2621
    The caller will guarantee that if "seq->init == mrr_ranges_array_init"
2622
    then seq_init_param is an array of n_ranges KEY_MULTI_RANGE structures.
2623
    This property will only be used by NDB handler until WL#2623 is done.
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
2624
1 by brian
clean slate
2625
    Buffer memory management is done according to the following scenario:
2626
    The caller allocates the buffer and provides it to the callee by filling
2627
    the members of HANDLER_BUFFER structure.
2628
    The callee consumes all or some fraction of the provided buffer space, and
2629
    sets the HANDLER_BUFFER members accordingly.
2630
    The callee may use the buffer memory until the next multi_range_read_init()
2631
    call is made, all records have been read, or until index_end() call is
2632
    made, whichever comes first.
2633
2634
  @retval 0  OK
2635
  @retval 1  Error
2636
*/
2637
2638
int
2639
handler::multi_range_read_init(RANGE_SEQ_IF *seq_funcs, void *seq_init_param,
482 by Brian Aker
Remove uint.
2640
                               uint32_t n_ranges, uint32_t mode,
779.1.27 by Monty Taylor
Got rid of __attribute__((unused)) and the like from the .cc files.
2641
                               HANDLER_BUFFER *)
1 by brian
clean slate
2642
{
2643
  mrr_iter= seq_funcs->init(seq_init_param, n_ranges, mode);
2644
  mrr_funcs= *seq_funcs;
2645
  mrr_is_output_sorted= test(mode & HA_MRR_SORTED);
56 by brian
Next pass of true/false update.
2646
  mrr_have_range= false;
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
2647
  return(0);
1 by brian
clean slate
2648
}
2649
2650
2651
/**
2652
  Get next record in MRR scan
2653
2654
  Default MRR implementation: read the next record
2655
2656
  @param range_info  OUT  Undefined if HA_MRR_NO_ASSOCIATION flag is in effect
2657
                          Otherwise, the opaque value associated with the range
2658
                          that contains the returned record.
2659
2660
  @retval 0      OK
2661
  @retval other  Error code
2662
*/
2663
2664
int handler::multi_range_read_next(char **range_info)
2665
{
2666
  int result= 0;
236.2.2 by rbradfor
Using correct coding standards for variable initialization
2667
  int range_res= 0;
1 by brian
clean slate
2668
2669
  if (!mrr_have_range)
2670
  {
56 by brian
Next pass of true/false update.
2671
    mrr_have_range= true;
1 by brian
clean slate
2672
    goto start;
2673
  }
2674
2675
  do
2676
  {
2677
    /* Save a call if there can be only one row in range. */
2678
    if (mrr_cur_range.range_flag != (UNIQUE_RANGE | EQ_RANGE))
2679
    {
2680
      result= read_range_next();
2681
      /* On success or non-EOF errors jump to the end. */
2682
      if (result != HA_ERR_END_OF_FILE)
2683
        break;
2684
    }
2685
    else
2686
    {
2687
      if (was_semi_consistent_read())
2688
        goto scan_it_again;
2689
      /*
2690
        We need to set this for the last range only, but checking this
2691
        condition is more expensive than just setting the result code.
2692
      */
2693
      result= HA_ERR_END_OF_FILE;
2694
    }
2695
2696
start:
2697
    /* Try the next range(s) until one matches a record. */
2698
    while (!(range_res= mrr_funcs.next(mrr_iter, &mrr_cur_range)))
2699
    {
2700
scan_it_again:
2701
      result= read_range_first(mrr_cur_range.start_key.keypart_map ?
2702
                                 &mrr_cur_range.start_key : 0,
2703
                               mrr_cur_range.end_key.keypart_map ?
2704
                                 &mrr_cur_range.end_key : 0,
2705
                               test(mrr_cur_range.range_flag & EQ_RANGE),
2706
                               mrr_is_output_sorted);
2707
      if (result != HA_ERR_END_OF_FILE)
2708
        break;
2709
    }
2710
  }
2711
  while ((result == HA_ERR_END_OF_FILE) && !range_res);
2712
2713
  *range_info= mrr_cur_range.ptr;
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
2714
  return(result);
1 by brian
clean slate
2715
}
2716
2717
2718
/* **************************************************************************
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
2719
 * DS-MRR implementation
1 by brian
clean slate
2720
 ***************************************************************************/
2721
2722
/**
2723
  DS-MRR: Initialize and start MRR scan
2724
2725
  Initialize and start the MRR scan. Depending on the mode parameter, this
2726
  may use default or DS-MRR implementation.
2727
2728
  @param h               Table handler to be used
2729
  @param key             Index to be used
2730
  @param seq_funcs       Interval sequence enumeration functions
2731
  @param seq_init_param  Interval sequence enumeration parameter
2732
  @param n_ranges        Number of ranges in the sequence.
2733
  @param mode            HA_MRR_* modes to use
2734
  @param buf             INOUT Buffer to use
2735
2736
  @retval 0     Ok, Scan started.
2737
  @retval other Error
2738
*/
2739
779.3.10 by Monty Taylor
Turned on -Wshadow.
2740
int DsMrr_impl::dsmrr_init(handler *h_in, KEY *key,
1 by brian
clean slate
2741
                           RANGE_SEQ_IF *seq_funcs, void *seq_init_param,
482 by Brian Aker
Remove uint.
2742
                           uint32_t n_ranges, uint32_t mode, HANDLER_BUFFER *buf)
1 by brian
clean slate
2743
{
482 by Brian Aker
Remove uint.
2744
  uint32_t elem_size;
2745
  uint32_t keyno;
1 by brian
clean slate
2746
  Item *pushed_cond= NULL;
2747
  handler *new_h2;
779.3.10 by Monty Taylor
Turned on -Wshadow.
2748
  keyno= h_in->active_index;
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
2749
  assert(h2 == NULL);
1 by brian
clean slate
2750
  if (mode & HA_MRR_USE_DEFAULT_IMPL || mode & HA_MRR_SORTED)
2751
  {
56 by brian
Next pass of true/false update.
2752
    use_default_impl= true;
779.3.10 by Monty Taylor
Turned on -Wshadow.
2753
    return(h_in->handler::multi_range_read_init(seq_funcs, seq_init_param,
1 by brian
clean slate
2754
                                                  n_ranges, mode, buf));
2755
  }
2756
  rowids_buf= buf->buffer;
2757
  //psergey-todo: don't add key_length as it is not needed anymore
779.3.10 by Monty Taylor
Turned on -Wshadow.
2758
  rowids_buf += key->key_length + h_in->ref_length;
1 by brian
clean slate
2759
2760
  is_mrr_assoc= !test(mode & HA_MRR_NO_ASSOCIATION);
2761
  rowids_buf_end= buf->buffer_end;
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
2762
779.3.10 by Monty Taylor
Turned on -Wshadow.
2763
  elem_size= h_in->ref_length + (int)is_mrr_assoc * sizeof(void*);
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
2764
  rowids_buf_last= rowids_buf +
1 by brian
clean slate
2765
                      ((rowids_buf_end - rowids_buf)/ elem_size)*
2766
                      elem_size;
2767
  rowids_buf_end= rowids_buf_last;
2768
2769
  /* Create a separate handler object to do rndpos() calls. */
520.1.22 by Brian Aker
Second pass of thd cleanup
2770
  Session *session= current_session;
779.3.10 by Monty Taylor
Turned on -Wshadow.
2771
  if (!(new_h2= h_in->clone(session->mem_root)) ||
520.1.22 by Brian Aker
Second pass of thd cleanup
2772
      new_h2->ha_external_lock(session, F_RDLCK))
1 by brian
clean slate
2773
  {
2774
    delete new_h2;
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
2775
    return(1);
1 by brian
clean slate
2776
  }
2777
779.3.10 by Monty Taylor
Turned on -Wshadow.
2778
  if (keyno == h_in->pushed_idx_cond_keyno)
2779
    pushed_cond= h_in->pushed_idx_cond;
2780
  if (h_in->ha_index_end())
1 by brian
clean slate
2781
  {
2782
    new_h2= h2;
2783
    goto error;
2784
  }
2785
2786
  h2= new_h2;
2787
  table->prepare_for_position();
2788
  new_h2->extra(HA_EXTRA_KEYREAD);
2789
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
2790
  if (h2->ha_index_init(keyno, false) ||
1 by brian
clean slate
2791
      h2->handler::multi_range_read_init(seq_funcs, seq_init_param, n_ranges,
2792
                                         mode, buf))
2793
    goto error;
56 by brian
Next pass of true/false update.
2794
  use_default_impl= false;
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
2795
1 by brian
clean slate
2796
  if (pushed_cond)
2797
    h2->idx_cond_push(keyno, pushed_cond);
2798
  if (dsmrr_fill_buffer(new_h2))
2799
    goto error;
2800
2801
  /*
2802
    If the above call has scanned through all intervals in *seq, then
2803
    adjust *buf to indicate that the remaining buffer space will not be used.
2804
  */
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
2805
  if (dsmrr_eof)
1 by brian
clean slate
2806
    buf->end_of_used_area= rowids_buf_last;
2807
779.3.10 by Monty Taylor
Turned on -Wshadow.
2808
  if (h_in->ha_rnd_init(false))
1 by brian
clean slate
2809
    goto error;
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
2810
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
2811
  return(0);
1 by brian
clean slate
2812
error:
2813
  h2->ha_index_or_rnd_end();
520.1.22 by Brian Aker
Second pass of thd cleanup
2814
  h2->ha_external_lock(session, F_UNLCK);
1 by brian
clean slate
2815
  h2->close();
2816
  delete h2;
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
2817
  return(1);
1 by brian
clean slate
2818
}
2819
2820
2821
void DsMrr_impl::dsmrr_close()
2822
{
2823
  if (h2)
2824
  {
520.1.22 by Brian Aker
Second pass of thd cleanup
2825
    h2->ha_external_lock(current_session, F_UNLCK);
1 by brian
clean slate
2826
    h2->close();
2827
    delete h2;
2828
    h2= NULL;
2829
  }
56 by brian
Next pass of true/false update.
2830
  use_default_impl= true;
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
2831
  return;
1 by brian
clean slate
2832
}
2833
2834
481 by Brian Aker
Remove all of uchar.
2835
static int rowid_cmp(void *h, unsigned char *a, unsigned char *b)
1 by brian
clean slate
2836
{
2837
  return ((handler*)h)->cmp_ref(a, b);
2838
}
2839
2840
2841
/**
2842
  DS-MRR: Fill the buffer with rowids and sort it by rowid
2843
2844
  {This is an internal function of DiskSweep MRR implementation}
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
2845
  Scan the MRR ranges and collect ROWIDs (or {ROWID, range_id} pairs) into
2846
  buffer. When the buffer is full or scan is completed, sort the buffer by
1 by brian
clean slate
2847
  rowid and return.
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
2848
2849
  The function assumes that rowids buffer is empty when it is invoked.
2850
1 by brian
clean slate
2851
  @param h  Table handler
2852
2853
  @retval 0      OK, the next portion of rowids is in the buffer,
2854
                 properly ordered
2855
  @retval other  Error
2856
*/
2857
779.1.27 by Monty Taylor
Got rid of __attribute__((unused)) and the like from the .cc files.
2858
int DsMrr_impl::dsmrr_fill_buffer(handler *)
1 by brian
clean slate
2859
{
2860
  char *range_info;
236.2.1 by rbradfor
Mac OS/X with darwin ports corrected uninitialized variable warnings
2861
  int res = 0;
1 by brian
clean slate
2862
2863
  rowids_buf_cur= rowids_buf;
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
2864
  while ((rowids_buf_cur < rowids_buf_end) &&
1 by brian
clean slate
2865
         !(res= h2->handler::multi_range_read_next(&range_info)))
2866
  {
2867
    /* Put rowid, or {rowid, range_id} pair into the buffer */
2868
    h2->position(table->record[0]);
2869
    memcpy(rowids_buf_cur, h2->ref, h2->ref_length);
2870
    rowids_buf_cur += h->ref_length;
2871
2872
    if (is_mrr_assoc)
2873
    {
2874
      memcpy(rowids_buf_cur, &range_info, sizeof(void*));
2875
      rowids_buf_cur += sizeof(void*);
2876
    }
2877
  }
2878
2879
  if (res && res != HA_ERR_END_OF_FILE)
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
2880
    return(res);
1 by brian
clean slate
2881
  dsmrr_eof= test(res == HA_ERR_END_OF_FILE);
2882
2883
  /* Sort the buffer contents by rowid */
482 by Brian Aker
Remove uint.
2884
  uint32_t elem_size= h->ref_length + (int)is_mrr_assoc * sizeof(void*);
2885
  uint32_t n_rowids= (rowids_buf_cur - rowids_buf) / elem_size;
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
2886
1 by brian
clean slate
2887
  my_qsort2(rowids_buf, n_rowids, elem_size, (qsort2_cmp)rowid_cmp,
2888
            (void*)h);
2889
  rowids_buf_last= rowids_buf_cur;
2890
  rowids_buf_cur=  rowids_buf;
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
2891
  return(0);
1 by brian
clean slate
2892
}
2893
2894
2895
/**
2896
  DS-MRR implementation: multi_range_read_next() function
2897
*/
2898
779.3.10 by Monty Taylor
Turned on -Wshadow.
2899
int DsMrr_impl::dsmrr_next(handler *h_in, char **range_info)
1 by brian
clean slate
2900
{
2901
  int res;
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
2902
1 by brian
clean slate
2903
  if (use_default_impl)
779.3.10 by Monty Taylor
Turned on -Wshadow.
2904
    return h_in->handler::multi_range_read_next(range_info);
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
2905
1 by brian
clean slate
2906
  if (rowids_buf_cur == rowids_buf_last)
2907
  {
2908
    if (dsmrr_eof)
2909
    {
2910
      res= HA_ERR_END_OF_FILE;
2911
      goto end;
2912
    }
2913
    res= dsmrr_fill_buffer(h);
2914
    if (res)
2915
      goto end;
2916
  }
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
2917
1 by brian
clean slate
2918
  /* Return EOF if there are no rowids in the buffer after re-fill attempt */
2919
  if (rowids_buf_cur == rowids_buf_last)
2920
  {
2921
    res= HA_ERR_END_OF_FILE;
2922
    goto end;
2923
  }
2924
779.3.10 by Monty Taylor
Turned on -Wshadow.
2925
  res= h_in->rnd_pos(table->record[0], rowids_buf_cur);
2926
  rowids_buf_cur += h_in->ref_length;
1 by brian
clean slate
2927
  if (is_mrr_assoc)
2928
  {
2929
    memcpy(range_info, rowids_buf_cur, sizeof(void*));
2930
    rowids_buf_cur += sizeof(void*);
2931
  }
2932
2933
end:
2934
  if (res)
2935
    dsmrr_close();
2936
  return res;
2937
}
2938
2939
2940
/**
2941
  DS-MRR implementation: multi_range_read_info() function
2942
*/
482 by Brian Aker
Remove uint.
2943
int DsMrr_impl::dsmrr_info(uint32_t keyno, uint32_t n_ranges, uint32_t rows, uint32_t *bufsz,
2944
                           uint32_t *flags, COST_VECT *cost)
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
2945
{
1 by brian
clean slate
2946
  int res;
482 by Brian Aker
Remove uint.
2947
  uint32_t def_flags= *flags;
2948
  uint32_t def_bufsz= *bufsz;
1 by brian
clean slate
2949
2950
  /* Get cost/flags/mem_usage of default MRR implementation */
2951
  res= h->handler::multi_range_read_info(keyno, n_ranges, rows, &def_bufsz,
2952
                                         &def_flags, cost);
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
2953
  assert(!res);
1 by brian
clean slate
2954
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
2955
  if ((*flags & HA_MRR_USE_DEFAULT_IMPL) ||
1 by brian
clean slate
2956
      choose_mrr_impl(keyno, rows, &def_flags, &def_bufsz, cost))
2957
  {
2958
    /* Default implementation is choosen */
2959
    *flags= def_flags;
2960
    *bufsz= def_bufsz;
2961
  }
2962
  return 0;
2963
}
2964
2965
2966
/**
2967
  DS-MRR Implementation: multi_range_read_info_const() function
2968
*/
2969
482 by Brian Aker
Remove uint.
2970
ha_rows DsMrr_impl::dsmrr_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
2971
                                 void *seq_init_param, uint32_t n_ranges,
482 by Brian Aker
Remove uint.
2972
                                 uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
1 by brian
clean slate
2973
{
2974
  ha_rows rows;
482 by Brian Aker
Remove uint.
2975
  uint32_t def_flags= *flags;
2976
  uint32_t def_bufsz= *bufsz;
1 by brian
clean slate
2977
  /* Get cost/flags/mem_usage of default MRR implementation */
2978
  rows= h->handler::multi_range_read_info_const(keyno, seq, seq_init_param,
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
2979
                                                n_ranges, &def_bufsz,
1 by brian
clean slate
2980
                                                &def_flags, cost);
2981
  if (rows == HA_POS_ERROR)
2982
  {
2983
    /* Default implementation can't perform MRR scan => we can't either */
2984
    return rows;
2985
  }
2986
2987
  /*
2988
    If HA_MRR_USE_DEFAULT_IMPL has been passed to us, that is an order to
2989
    use the default MRR implementation (we need it for UPDATE/DELETE).
2990
    Otherwise, make a choice based on cost and @@optimizer_use_mrr.
2991
  */
2992
  if ((*flags & HA_MRR_USE_DEFAULT_IMPL) ||
2993
      choose_mrr_impl(keyno, rows, flags, bufsz, cost))
2994
  {
2995
    *flags= def_flags;
2996
    *bufsz= def_bufsz;
2997
  }
2998
  else
2999
  {
3000
    *flags &= ~HA_MRR_USE_DEFAULT_IMPL;
3001
  }
3002
  return rows;
3003
}
3004
3005
3006
/**
3007
  Check if key has partially-covered columns
3008
3009
  We can't use DS-MRR to perform range scans when the ranges are over
3010
  partially-covered keys, because we'll not have full key part values
3011
  (we'll have their prefixes from the index) and will not be able to check
3012
  if we've reached the end the range.
3013
3014
  @param keyno  Key to check
3015
3016
  @todo
3017
    Allow use of DS-MRR in cases where the index has partially-covered
3018
    components but they are not used for scanning.
3019
56 by brian
Next pass of true/false update.
3020
  @retval true   Yes
3021
  @retval false  No
1 by brian
clean slate
3022
*/
3023
482 by Brian Aker
Remove uint.
3024
bool DsMrr_impl::key_uses_partial_cols(uint32_t keyno)
1 by brian
clean slate
3025
{
3026
  KEY_PART_INFO *kp= table->key_info[keyno].key_part;
3027
  KEY_PART_INFO *kp_end= kp + table->key_info[keyno].key_parts;
3028
  for (; kp != kp_end; kp++)
3029
  {
1005.2.6 by Monty Taylor
Re-added bitset<> as a replacement for Bitmap<>
3030
    if (!kp->field->part_of_key.test(keyno))
56 by brian
Next pass of true/false update.
3031
      return true;
1 by brian
clean slate
3032
  }
56 by brian
Next pass of true/false update.
3033
  return false;
1 by brian
clean slate
3034
}
3035
3036
3037
/**
3038
  DS-MRR Internals: Choose between Default MRR implementation and DS-MRR
3039
3040
  Make the choice between using Default MRR implementation and DS-MRR.
3041
  This function contains common functionality factored out of dsmrr_info()
3042
  and dsmrr_info_const(). The function assumes that the default MRR
3043
  implementation's applicability requirements are satisfied.
3044
3045
  @param keyno       Index number
3046
  @param rows        E(full rows to be retrieved)
3047
  @param flags  IN   MRR flags provided by the MRR user
3048
                OUT  If DS-MRR is choosen, flags of DS-MRR implementation
3049
                     else the value is not modified
3050
  @param bufsz  IN   If DS-MRR is choosen, buffer use of DS-MRR implementation
3051
                     else the value is not modified
3052
  @param cost   IN   Cost of default MRR implementation
3053
                OUT  If DS-MRR is choosen, cost of DS-MRR scan
3054
                     else the value is not modified
3055
56 by brian
Next pass of true/false update.
3056
  @retval true   Default MRR implementation should be used
3057
  @retval false  DS-MRR implementation should be used
1 by brian
clean slate
3058
*/
3059
482 by Brian Aker
Remove uint.
3060
bool DsMrr_impl::choose_mrr_impl(uint32_t keyno, ha_rows rows, uint32_t *flags,
3061
                                 uint32_t *bufsz, COST_VECT *cost)
1 by brian
clean slate
3062
{
3063
  COST_VECT dsmrr_cost;
3064
  bool res;
520.1.22 by Brian Aker
Second pass of thd cleanup
3065
  Session *session= current_session;
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
3066
  if ((session->variables.optimizer_use_mrr == 2) ||
1 by brian
clean slate
3067
      (*flags & HA_MRR_INDEX_ONLY) || (*flags & HA_MRR_SORTED) ||
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
3068
      (keyno == table->s->primary_key &&
3069
       h->primary_key_is_clustered()) ||
1 by brian
clean slate
3070
       key_uses_partial_cols(keyno))
3071
  {
3072
    /* Use the default implementation */
3073
    *flags |= HA_MRR_USE_DEFAULT_IMPL;
56 by brian
Next pass of true/false update.
3074
    return true;
1 by brian
clean slate
3075
  }
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
3076
3077
  uint32_t add_len= table->key_info[keyno].key_length + h->ref_length;
1 by brian
clean slate
3078
  *bufsz -= add_len;
3079
  if (get_disk_sweep_mrr_cost(keyno, rows, *flags, bufsz, &dsmrr_cost))
56 by brian
Next pass of true/false update.
3080
    return true;
1 by brian
clean slate
3081
  *bufsz += add_len;
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
3082
1 by brian
clean slate
3083
  bool force_dsmrr;
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
3084
  /*
1 by brian
clean slate
3085
    If @@optimizer_use_mrr==force, then set cost of DS-MRR to be minimum of
3086
    DS-MRR and Default implementations cost. This allows one to force use of
3087
    DS-MRR whenever it is applicable without affecting other cost-based
3088
    choices.
3089
  */
520.1.22 by Brian Aker
Second pass of thd cleanup
3090
  if ((force_dsmrr= (session->variables.optimizer_use_mrr == 1)) &&
1 by brian
clean slate
3091
      dsmrr_cost.total_cost() > cost->total_cost())
3092
    dsmrr_cost= *cost;
3093
3094
  if (force_dsmrr || dsmrr_cost.total_cost() <= cost->total_cost())
3095
  {
3096
    *flags &= ~HA_MRR_USE_DEFAULT_IMPL;  /* Use the DS-MRR implementation */
3097
    *flags &= ~HA_MRR_SORTED;          /* We will return unordered output */
3098
    *cost= dsmrr_cost;
56 by brian
Next pass of true/false update.
3099
    res= false;
1 by brian
clean slate
3100
  }
3101
  else
3102
  {
3103
    /* Use the default MRR implementation */
56 by brian
Next pass of true/false update.
3104
    res= true;
1 by brian
clean slate
3105
  }
3106
  return res;
3107
}
3108
3109
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
3110
static void get_sort_and_sweep_cost(Table *table, ha_rows nrows, COST_VECT *cost);
1 by brian
clean slate
3111
3112
3113
/**
3114
  Get cost of DS-MRR scan
3115
3116
  @param keynr              Index to be used
3117
  @param rows               E(Number of rows to be scanned)
3118
  @param flags              Scan parameters (HA_MRR_* flags)
3119
  @param buffer_size INOUT  Buffer size
3120
  @param cost        OUT    The cost
3121
56 by brian
Next pass of true/false update.
3122
  @retval false  OK
3123
  @retval true   Error, DS-MRR cannot be used (the buffer is too small
1 by brian
clean slate
3124
                 for even 1 rowid)
3125
*/
3126
482 by Brian Aker
Remove uint.
3127
bool DsMrr_impl::get_disk_sweep_mrr_cost(uint32_t keynr, ha_rows rows, uint32_t flags,
3128
                                         uint32_t *buffer_size, COST_VECT *cost)
1 by brian
clean slate
3129
{
61 by Brian Aker
Conversion of handler type.
3130
  uint32_t max_buff_entries, elem_size;
1 by brian
clean slate
3131
  ha_rows rows_in_full_step, rows_in_last_step;
482 by Brian Aker
Remove uint.
3132
  uint32_t n_full_steps;
1 by brian
clean slate
3133
  double index_read_cost;
3134
3135
  elem_size= h->ref_length + sizeof(void*) * (!test(flags & HA_MRR_NO_ASSOCIATION));
3136
  max_buff_entries = *buffer_size / elem_size;
3137
3138
  if (!max_buff_entries)
56 by brian
Next pass of true/false update.
3139
    return true; /* Buffer has not enough space for even 1 rowid */
1 by brian
clean slate
3140
3141
  /* Number of iterations we'll make with full buffer */
895 by Brian Aker
Completion (?) of uint conversion.
3142
  n_full_steps= (uint32_t)floor(rows2double(rows) / max_buff_entries);
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
3143
3144
  /*
3145
    Get numbers of rows we'll be processing in
3146
     - non-last sweep, with full buffer
1 by brian
clean slate
3147
     - last iteration, with non-full buffer
3148
  */
3149
  rows_in_full_step= max_buff_entries;
3150
  rows_in_last_step= rows % max_buff_entries;
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
3151
1 by brian
clean slate
3152
  /* Adjust buffer size if we expect to use only part of the buffer */
3153
  if (n_full_steps)
3154
  {
3155
    get_sort_and_sweep_cost(table, rows, cost);
3156
    cost->multiply(n_full_steps);
3157
  }
3158
  else
3159
  {
3160
    cost->zero();
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
3161
    *buffer_size= cmax((ulong)*buffer_size,
3162
                      (size_t)(1.2*rows_in_last_step) * elem_size +
1 by brian
clean slate
3163
                      h->ref_length + table->key_info[keynr].key_length);
3164
  }
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
3165
1 by brian
clean slate
3166
  COST_VECT last_step_cost;
3167
  get_sort_and_sweep_cost(table, rows_in_last_step, &last_step_cost);
3168
  cost->add(&last_step_cost);
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
3169
1 by brian
clean slate
3170
  if (n_full_steps != 0)
3171
    cost->mem_cost= *buffer_size;
3172
  else
3173
    cost->mem_cost= (double)rows_in_last_step * elem_size;
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
3174
1 by brian
clean slate
3175
  /* Total cost of all index accesses */
3176
  index_read_cost= h->index_only_read_time(keynr, (double)rows);
3177
  cost->add_io(index_read_cost, 1 /* Random seeks */);
56 by brian
Next pass of true/false update.
3178
  return false;
1 by brian
clean slate
3179
}
3180
3181
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
3182
/*
1 by brian
clean slate
3183
  Get cost of one sort-and-sweep step
3184
3185
  SYNOPSIS
3186
    get_sort_and_sweep_cost()
3187
      table       Table being accessed
3188
      nrows       Number of rows to be sorted and retrieved
3189
      cost   OUT  The cost
3190
3191
  DESCRIPTION
3192
    Get cost of these operations:
3193
     - sort an array of #nrows ROWIDs using qsort
3194
     - read #nrows records from table in a sweep.
3195
*/
3196
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
3197
static
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
3198
void get_sort_and_sweep_cost(Table *table, ha_rows nrows, COST_VECT *cost)
1 by brian
clean slate
3199
{
3200
  if (nrows)
3201
  {
56 by brian
Next pass of true/false update.
3202
    get_sweep_read_cost(table, nrows, false, cost);
1 by brian
clean slate
3203
    /* Add cost of qsort call: n * log2(n) * cost(rowid_comparison) */
3204
    double cmp_op= rows2double(nrows) * (1.0 / TIME_FOR_COMPARE_ROWID);
3205
    if (cmp_op < 3)
3206
      cmp_op= 3;
3207
    cost->cpu_cost += cmp_op * log2(cmp_op);
3208
  }
3209
  else
3210
    cost->zero();
3211
}
3212
3213
3214
/**
3215
  Get cost of reading nrows table records in a "disk sweep"
3216
3217
  A disk sweep read is a sequence of handler->rnd_pos(rowid) calls that made
3218
  for an ordered sequence of rowids.
3219
3220
  We assume hard disk IO. The read is performed as follows:
3221
3222
   1. The disk head is moved to the needed cylinder
3223
   2. The controller waits for the plate to rotate
3224
   3. The data is transferred
3225
3226
  Time to do #3 is insignificant compared to #2+#1.
3227
3228
  Time to move the disk head is proportional to head travel distance.
3229
3230
  Time to wait for the plate to rotate depends on whether the disk head
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
3231
  was moved or not.
1 by brian
clean slate
3232
3233
  If disk head wasn't moved, the wait time is proportional to distance
3234
  between the previous block and the block we're reading.
3235
3236
  If the head was moved, we don't know how much we'll need to wait for the
3237
  plate to rotate. We assume the wait time to be a variate with a mean of
3238
  0.5 of full rotation time.
3239
3240
  Our cost units are "random disk seeks". The cost of random disk seek is
3241
  actually not a constant, it depends one range of cylinders we're going
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
3242
  to access. We make it constant by introducing a fuzzy concept of "typical
1 by brian
clean slate
3243
  datafile length" (it's fuzzy as it's hard to tell whether it should
3244
  include index file, temp.tables etc). Then random seek cost is:
3245
3246
    1 = half_rotation_cost + move_cost * 1/3 * typical_data_file_length
3247
3248
  We define half_rotation_cost as DISK_SEEK_BASE_COST=0.9.
3249
3250
  @param table             Table to be accessed
3251
  @param nrows             Number of rows to retrieve
56 by brian
Next pass of true/false update.
3252
  @param interrupted       true <=> Assume that the disk sweep will be
3253
                           interrupted by other disk IO. false - otherwise.
1 by brian
clean slate
3254
  @param cost         OUT  The cost.
3255
*/
3256
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
3257
void get_sweep_read_cost(Table *table, ha_rows nrows, bool interrupted,
1 by brian
clean slate
3258
                         COST_VECT *cost)
3259
{
3260
  cost->zero();
3261
  if (table->file->primary_key_is_clustered())
3262
  {
3263
    cost->io_count= table->file->read_time(table->s->primary_key,
895 by Brian Aker
Completion (?) of uint conversion.
3264
                                           (uint32_t) nrows, nrows);
1 by brian
clean slate
3265
  }
3266
  else
3267
  {
3268
    double n_blocks=
151 by Brian Aker
Ulonglong to uint64_t
3269
      ceil(uint64_t2double(table->file->stats.data_file_length) / IO_SIZE);
1 by brian
clean slate
3270
    double busy_blocks=
3271
      n_blocks * (1.0 - pow(1.0 - 1.0/n_blocks, rows2double(nrows)));
3272
    if (busy_blocks < 1.0)
3273
      busy_blocks= 1.0;
3274
3275
    cost->io_count= busy_blocks;
3276
3277
    if (!interrupted)
3278
    {
3279
      /* Assume reading is done in one 'sweep' */
3280
      cost->avg_io_cost= (DISK_SEEK_BASE_COST +
3281
                          DISK_SEEK_PROP_COST*n_blocks/busy_blocks);
3282
    }
3283
  }
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
3284
  return;
1 by brian
clean slate
3285
}
3286
3287
3288
/* **************************************************************************
3289
 * DS-MRR implementation ends
3290
 ***************************************************************************/
3291
3292
/**
3293
  Read first row between two ranges.
3294
3295
  @param start_key		Start key. Is 0 if no min range
3296
  @param end_key		End key.  Is 0 if no max range
3297
  @param eq_range_arg	        Set to 1 if start_key == end_key
3298
  @param sorted		Set to 1 if result should be sorted per key
3299
3300
  @note
3301
    Record is read into table->record[0]
3302
3303
  @retval
3304
    0			Found row
3305
  @retval
3306
    HA_ERR_END_OF_FILE	No rows in range
3307
  @retval
3308
    \#			Error code
3309
*/
3310
int handler::read_range_first(const key_range *start_key,
3311
			      const key_range *end_key,
3312
			      bool eq_range_arg,
779.1.27 by Monty Taylor
Got rid of __attribute__((unused)) and the like from the .cc files.
3313
                              bool )
1 by brian
clean slate
3314
{
3315
  int result;
3316
3317
  eq_range= eq_range_arg;
3318
  end_range= 0;
3319
  if (end_key)
3320
  {
3321
    end_range= &save_end_range;
3322
    save_end_range= *end_key;
3323
    key_compare_result_on_equal= ((end_key->flag == HA_READ_BEFORE_KEY) ? 1 :
3324
				  (end_key->flag == HA_READ_AFTER_KEY) ? -1 : 0);
3325
  }
3326
  range_key_part= table->key_info[active_index].key_part;
3327
3328
  if (!start_key)			// Read first record
3329
    result= index_first(table->record[0]);
3330
  else
3331
    result= index_read_map(table->record[0],
3332
                           start_key->key,
3333
                           start_key->keypart_map,
3334
                           start_key->flag);
3335
  if (result)
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
3336
    return((result == HA_ERR_KEY_NOT_FOUND)
1 by brian
clean slate
3337
		? HA_ERR_END_OF_FILE
3338
		: result);
3339
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
3340
  return (compare_key(end_range) <= 0 ? 0 : HA_ERR_END_OF_FILE);
1 by brian
clean slate
3341
}
3342
3343
3344
/**
3345
  Read next row between two endpoints.
3346
3347
  @note
3348
    Record is read into table->record[0]
3349
3350
  @retval
3351
    0			Found row
3352
  @retval
3353
    HA_ERR_END_OF_FILE	No rows in range
3354
  @retval
3355
    \#			Error code
3356
*/
3357
int handler::read_range_next()
3358
{
3359
  int result;
3360
3361
  if (eq_range)
3362
  {
3363
    /* We trust that index_next_same always gives a row in range */
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
3364
    return(index_next_same(table->record[0],
1 by brian
clean slate
3365
                                end_range->key,
3366
                                end_range->length));
3367
  }
3368
  result= index_next(table->record[0]);
3369
  if (result)
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
3370
    return(result);
3371
  return(compare_key(end_range) <= 0 ? 0 : HA_ERR_END_OF_FILE);
1 by brian
clean slate
3372
}
3373
3374
3375
/**
3376
  Compare if found key (in row) is over max-value.
3377
3378
  @param range		range to compare to row. May be 0 for no range
3379
3380
  @seealso
3381
    key.cc::key_cmp()
3382
3383
  @return
3384
    The return value is SIGN(key_in_row - range_key):
3385
3386
    - 0   : Key is equal to range or 'range' == 0 (no range)
3387
    - -1  : Key is less than range
3388
    - 1   : Key is larger than range
3389
*/
3390
int handler::compare_key(key_range *range)
3391
{
3392
  int cmp;
3393
  if (!range || in_range_check_pushed_down)
3394
    return 0;					// No max range
3395
  cmp= key_cmp(range_key_part, range->key, range->length);
3396
  if (!cmp)
3397
    cmp= key_compare_result_on_equal;
3398
  return cmp;
3399
}
3400
3401
3402
/*
3403
  Same as compare_key() but doesn't check have in_range_check_pushed_down.
3404
  This is used by index condition pushdown implementation.
3405
*/
3406
3407
int handler::compare_key2(key_range *range)
3408
{
3409
  int cmp;
3410
  if (!range)
3411
    return 0;					// no max range
3412
  cmp= key_cmp(range_key_part, range->key, range->length);
3413
  if (!cmp)
3414
    cmp= key_compare_result_on_equal;
3415
  return cmp;
3416
}
3417
656.1.1 by Monty Taylor
OOOh doggie. Got rid of my_alloca.
3418
int handler::index_read_idx_map(unsigned char * buf, uint32_t index,
3419
                                const unsigned char * key,
1 by brian
clean slate
3420
                                key_part_map keypart_map,
3421
                                enum ha_rkey_function find_flag)
3422
{
3423
  int error, error1;
3424
  error= index_init(index, 0);
3425
  if (!error)
3426
  {
3427
    error= index_read_map(buf, key, keypart_map, find_flag);
3428
    error1= index_end();
3429
  }
3430
  return error ?  error : error1;
3431
}
3432
3433
520.1.22 by Brian Aker
Second pass of thd cleanup
3434
static bool stat_print(Session *session, const char *type, uint32_t type_len,
482 by Brian Aker
Remove uint.
3435
                       const char *file, uint32_t file_len,
3436
                       const char *status, uint32_t status_len)
1 by brian
clean slate
3437
{
520.1.22 by Brian Aker
Second pass of thd cleanup
3438
  Protocol *protocol= session->protocol;
971.3.19 by Eric Day
Finished first pass at Protocol cleanup, still some things to remove but they are a bit more involved.
3439
  protocol->prepareForResend();
1 by brian
clean slate
3440
  protocol->store(type, type_len, system_charset_info);
3441
  protocol->store(file, file_len, system_charset_info);
3442
  protocol->store(status, status_len, system_charset_info);
3443
  if (protocol->write())
56 by brian
Next pass of true/false update.
3444
    return true;
3445
  return false;
1 by brian
clean slate
3446
}
3447
960.2.27 by Monty Taylor
Reworked transformed handlerton into class StorageEngine.
3448
bool ha_show_status(Session *session, StorageEngine *engine, enum ha_stat_type stat)
1 by brian
clean slate
3449
{
3450
  List<Item> field_list;
520.1.22 by Brian Aker
Second pass of thd cleanup
3451
  Protocol *protocol= session->protocol;
1 by brian
clean slate
3452
  bool result;
3453
3454
  field_list.push_back(new Item_empty_string("Type",10));
3455
  field_list.push_back(new Item_empty_string("Name",FN_REFLEN));
3456
  field_list.push_back(new Item_empty_string("Status",10));
3457
971.3.19 by Eric Day
Finished first pass at Protocol cleanup, still some things to remove but they are a bit more involved.
3458
  if (protocol->sendFields(&field_list,
3459
                           Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
56 by brian
Next pass of true/false update.
3460
    return true;
1 by brian
clean slate
3461
960.2.38 by Monty Taylor
Removed extraneous send myself to myself argument.
3462
  result= engine->show_status(session, stat_print, stat) ? 1 : 0;
1 by brian
clean slate
3463
3464
  if (!result)
836 by Brian Aker
Fixed session call from function to method.
3465
    session->my_eof();
1 by brian
clean slate
3466
  return result;
3467
}
3468
3469
3470
/**
3471
  Check if the conditions for row-based binlogging is correct for the table.
3472
3473
  A row in the given table should be replicated if:
3474
  - Row-based replication is enabled in the current thread
3475
  - The binlog is enabled
3476
  - It is not a temporary table
3477
  - The binary log is open
3478
  - The database the table resides in shall be binlogged (binlog_*_db rules)
3479
  - table is not mysql.event
3480
*/
3481
667 by Brian Aker
Partial fix (more of replication flushed out)
3482
static bool binlog_log_row(Table* table,
3483
                           const unsigned char *before_record,
3484
                           const unsigned char *after_record)
1 by brian
clean slate
3485
{
520.1.22 by Brian Aker
Second pass of thd cleanup
3486
  Session *const session= table->in_use;
1 by brian
clean slate
3487
661 by Brian Aker
First major pass through new replication.
3488
  switch (session->lex->sql_command)
3489
  {
3490
  case SQLCOM_REPLACE:
3491
  case SQLCOM_INSERT:
3492
  case SQLCOM_REPLACE_SELECT:
3493
  case SQLCOM_INSERT_SELECT:
669 by Brian Aker
Replication bits (getting CREATE..SELECT right)
3494
  case SQLCOM_CREATE_TABLE:
988.1.6 by Jay Pipes
Removed old protobuf_replicator plugin, fixed up db.cc and other files to use new
3495
    transaction_services.insertRecord(session, table);
661 by Brian Aker
First major pass through new replication.
3496
    break;
3497
3498
  case SQLCOM_UPDATE:
3499
  case SQLCOM_UPDATE_MULTI:
988.1.6 by Jay Pipes
Removed old protobuf_replicator plugin, fixed up db.cc and other files to use new
3500
    transaction_services.updateRecord(session, table, before_record, after_record);
661 by Brian Aker
First major pass through new replication.
3501
    break;
3502
3503
  case SQLCOM_DELETE:
3504
  case SQLCOM_DELETE_MULTI:
988.1.6 by Jay Pipes
Removed old protobuf_replicator plugin, fixed up db.cc and other files to use new
3505
    transaction_services.deleteRecord(session, table);
661 by Brian Aker
First major pass through new replication.
3506
    break;
3507
665.1.1 by Eric Herman
more EOL whitespace fixups
3508
    /*
662 by Brian Aker
Remove dead methods.
3509
      For everything else we ignore the event (since it just involves a temp table)
3510
    */
661 by Brian Aker
First major pass through new replication.
3511
  default:
3512
    break;
1 by brian
clean slate
3513
  }
592 by Brian Aker
Remove one set.
3514
988.1.6 by Jay Pipes
Removed old protobuf_replicator plugin, fixed up db.cc and other files to use new
3515
  return false; //error;
1 by brian
clean slate
3516
}
3517
520.1.22 by Brian Aker
Second pass of thd cleanup
3518
int handler::ha_external_lock(Session *session, int lock_type)
1 by brian
clean slate
3519
{
3520
  /*
3521
    Whether this is lock or unlock, this should be true, and is to verify that
3522
    if get_auto_increment() was called (thus may have reserved intervals or
3523
    taken a table lock), ha_release_auto_increment() was too.
3524
  */
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
3525
  assert(next_insert_id == 0);
1 by brian
clean slate
3526
3527
  /*
3528
    We cache the table flags if the locking succeeded. Otherwise, we
3529
    keep them as they were when they were fetched in ha_open().
3530
  */
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
3531
  DRIZZLE_EXTERNAL_LOCK(lock_type);
1 by brian
clean slate
3532
520.1.22 by Brian Aker
Second pass of thd cleanup
3533
  int error= external_lock(session, lock_type);
1 by brian
clean slate
3534
  if (error == 0)
3535
    cached_table_flags= table_flags();
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
3536
  return(error);
1 by brian
clean slate
3537
}
3538
3539
3540
/**
3541
  Check handler usage and reset state of file to after 'open'
3542
*/
3543
int handler::ha_reset()
3544
{
1005.2.3 by Monty Taylor
Further reversion of P.
3545
  /* Check that we have called all proper deallocation functions */
3546
  assert((unsigned char*) table->def_read_set.bitmap +
3547
              table->s->column_bitmap_size ==
3548
              (unsigned char*) table->def_write_set.bitmap);
3549
  assert(bitmap_is_set_all(&table->s->all_set));
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
3550
  assert(table->key_read == 0);
1 by brian
clean slate
3551
  /* ensure that ha_index_end / ha_rnd_end has been called */
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
3552
  assert(inited == NONE);
1 by brian
clean slate
3553
  /* Free cache used by filesort */
3554
  free_io_cache(table);
3555
  /* reset the bitmaps to point to defaults */
3556
  table->default_column_bitmaps();
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
3557
  return(reset());
1 by brian
clean slate
3558
}
3559
3560
481 by Brian Aker
Remove all of uchar.
3561
int handler::ha_write_row(unsigned char *buf)
1 by brian
clean slate
3562
{
3563
  int error;
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
3564
  DRIZZLE_INSERT_ROW_START();
1 by brian
clean slate
3565
873.1.16 by Jay Pipes
This patch pulls the setting of the auto-set timestamp out of the individual
3566
  /* 
3567
   * If we have a timestamp column, update it to the current time 
3568
   * 
3569
   * @TODO Technically, the below two lines can be take even further out of the
3570
   * handler interface and into the fill_record() method.
3571
   */
3572
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
3573
    table->timestamp_field->set_time();
3574
1 by brian
clean slate
3575
  mark_trx_read_write();
3576
3577
  if (unlikely(error= write_row(buf)))
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
3578
    return(error);
662 by Brian Aker
Remove dead methods.
3579
3580
  if (unlikely(binlog_log_row(table, 0, buf)))
3581
    return HA_ERR_RBR_LOGGING_FAILED; /* purecov: inspected */
3582
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
3583
  DRIZZLE_INSERT_ROW_END();
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
3584
  return(0);
1 by brian
clean slate
3585
}
3586
3587
481 by Brian Aker
Remove all of uchar.
3588
int handler::ha_update_row(const unsigned char *old_data, unsigned char *new_data)
1 by brian
clean slate
3589
{
3590
  int error;
3591
3592
  /*
3593
    Some storage engines require that the new record is in record[0]
3594
    (and the old record is in record[1]).
3595
   */
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
3596
  assert(new_data == table->record[0]);
1 by brian
clean slate
3597
3598
  mark_trx_read_write();
3599
3600
  if (unlikely(error= update_row(old_data, new_data)))
3601
    return error;
662 by Brian Aker
Remove dead methods.
3602
3603
  if (unlikely(binlog_log_row(table, old_data, new_data)))
3604
    return HA_ERR_RBR_LOGGING_FAILED;
3605
1 by brian
clean slate
3606
  return 0;
3607
}
3608
481 by Brian Aker
Remove all of uchar.
3609
int handler::ha_delete_row(const unsigned char *buf)
1 by brian
clean slate
3610
{
3611
  int error;
3612
3613
  mark_trx_read_write();
3614
3615
  if (unlikely(error= delete_row(buf)))
3616
    return error;
662 by Brian Aker
Remove dead methods.
3617
3618
  if (unlikely(binlog_log_row(table, buf, 0)))
3619
    return HA_ERR_RBR_LOGGING_FAILED;
3620
1 by brian
clean slate
3621
  return 0;
3622
}
3623
520.6.7 by Monty Taylor
Moved a bunch of crap out of common_includes.
3624
void table_case_convert(char * name, uint32_t length)
3625
{
3626
  if (lower_case_table_names)
3627
    files_charset_info->cset->casedn(files_charset_info,
3628
                                     name, length, name, length);
3629
}
3630
3631
const char *table_case_name(HA_CREATE_INFO *info, const char *name)
3632
{
3633
  return ((lower_case_table_names == 2 && info->alias) ? info->alias : name);
3634
}