~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/probes.h"
31
#include "drizzled/sql_parse.h"
32
#include "drizzled/cost_vect.h"
33
#include "drizzled/session.h"
34
#include "drizzled/sql_base.h"
1039.5.31 by Jay Pipes
This patch does a few things:
35
#include "drizzled/replication_services.h"
873.1.17 by Jay Pipes
Fix for incomplete class definition in handler.cc. Forgot to commit it
36
#include "drizzled/lock.h"
37
#include "drizzled/item/int.h"
38
#include "drizzled/item/empty_string.h"
39
#include "drizzled/unireg.h" // for mysql_frm_type
40
#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.
41
#include "drizzled/message/table.pb.h"
971.6.1 by Eric Day
Renamed Protocol to Client, cleaned up some unnecessary methods along the way.
42
#include "drizzled/plugin/client.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;
971.3.70 by Eric Day
Fixed style issues found by Jay.
45
using namespace drizzled;
1 by brian
clean slate
46
1039.5.31 by Jay Pipes
This patch does a few things:
47
extern drizzled::ReplicationServices replication_services;
988.1.6 by Jay Pipes
Removed old protobuf_replicator plugin, fixed up db.cc and other files to use new
48
1121.1.5 by Brian Aker
Remove parser bit from index.
49
KEY_CREATE_INFO default_key_create_info= { HA_KEY_ALG_UNDEF, 0, {NULL,0} };
1 by brian
clean slate
50
960.2.39 by Monty Taylor
Removed more handlerton naming references.
51
/* number of entries in storage_engines[] */
61 by Brian Aker
Conversion of handler type.
52
uint32_t total_ha= 0;
960.2.39 by Monty Taylor
Removed more handlerton naming references.
53
/* number of storage engines (from storage_engines[]) that support 2pc */
61 by Brian Aker
Conversion of handler type.
54
uint32_t total_ha_2pc= 0;
1 by brian
clean slate
55
/* size of savepoint storage area (see ha_init) */
61 by Brian Aker
Conversion of handler type.
56
uint32_t savepoint_alloc_size= 0;
1 by brian
clean slate
57
58
const char *ha_row_type[] = {
59
  "", "FIXED", "DYNAMIC", "COMPRESSED", "REDUNDANT", "COMPACT", "PAGE", "?","?","?"
60
};
61
62
const char *tx_isolation_names[] =
63
{ "READ-UNCOMMITTED", "READ-COMMITTED", "REPEATABLE-READ", "SERIALIZABLE",
461 by Monty Taylor
Removed NullS. bu-bye.
64
  NULL};
575.1.3 by Monty Taylor
Moved some stuff out of handler.h.
65
1 by brian
clean slate
66
TYPELIB tx_isolation_typelib= {array_elements(tx_isolation_names)-1,"",
575.1.3 by Monty Taylor
Moved some stuff out of handler.h.
67
                               tx_isolation_names, NULL};
1 by brian
clean slate
68
69
70
/**
71
  Register handler error messages for use with my_error().
72
73
  @retval
74
    0           OK
75
  @retval
76
    !=0         Error
77
*/
78
79
int ha_init_errors(void)
80
{
81
#define SETMSG(nr, msg) errmsgs[(nr) - HA_ERR_FIRST]= (msg)
82
  const char    **errmsgs;
83
84
  /* Allocate a pointer array for the error message strings. */
85
  /* Zerofill it to avoid uninitialized gaps. */
641.3.8 by Monty Taylor
Removed my_malloc from drizzled.
86
  if (! (errmsgs= (const char**) malloc(HA_ERR_ERRORS * sizeof(char*))))
1 by brian
clean slate
87
    return 1;
641.3.9 by Monty Taylor
More removal of my_malloc.
88
  memset(errmsgs, 0, HA_ERR_ERRORS * sizeof(char *));
1 by brian
clean slate
89
90
  /* Set the dedicated error messages. */
91
  SETMSG(HA_ERR_KEY_NOT_FOUND,          ER(ER_KEY_NOT_FOUND));
92
  SETMSG(HA_ERR_FOUND_DUPP_KEY,         ER(ER_DUP_KEY));
93
  SETMSG(HA_ERR_RECORD_CHANGED,         "Update wich is recoverable");
94
  SETMSG(HA_ERR_WRONG_INDEX,            "Wrong index given to function");
95
  SETMSG(HA_ERR_CRASHED,                ER(ER_NOT_KEYFILE));
96
  SETMSG(HA_ERR_WRONG_IN_RECORD,        ER(ER_CRASHED_ON_USAGE));
97
  SETMSG(HA_ERR_OUT_OF_MEM,             "Table handler out of memory");
98
  SETMSG(HA_ERR_NOT_A_TABLE,            "Incorrect file format '%.64s'");
99
  SETMSG(HA_ERR_WRONG_COMMAND,          "Command not supported");
100
  SETMSG(HA_ERR_OLD_FILE,               ER(ER_OLD_KEYFILE));
101
  SETMSG(HA_ERR_NO_ACTIVE_RECORD,       "No record read in update");
102
  SETMSG(HA_ERR_RECORD_DELETED,         "Intern record deleted");
103
  SETMSG(HA_ERR_RECORD_FILE_FULL,       ER(ER_RECORD_FILE_FULL));
104
  SETMSG(HA_ERR_INDEX_FILE_FULL,        "No more room in index file '%.64s'");
105
  SETMSG(HA_ERR_END_OF_FILE,            "End in next/prev/first/last");
106
  SETMSG(HA_ERR_UNSUPPORTED,            ER(ER_ILLEGAL_HA));
107
  SETMSG(HA_ERR_TO_BIG_ROW,             "Too big row");
108
  SETMSG(HA_WRONG_CREATE_OPTION,        "Wrong create option");
109
  SETMSG(HA_ERR_FOUND_DUPP_UNIQUE,      ER(ER_DUP_UNIQUE));
110
  SETMSG(HA_ERR_UNKNOWN_CHARSET,        "Can't open charset");
111
  SETMSG(HA_ERR_WRONG_MRG_TABLE_DEF,    ER(ER_WRONG_MRG_TABLE));
112
  SETMSG(HA_ERR_CRASHED_ON_REPAIR,      ER(ER_CRASHED_ON_REPAIR));
113
  SETMSG(HA_ERR_CRASHED_ON_USAGE,       ER(ER_CRASHED_ON_USAGE));
114
  SETMSG(HA_ERR_LOCK_WAIT_TIMEOUT,      ER(ER_LOCK_WAIT_TIMEOUT));
115
  SETMSG(HA_ERR_LOCK_TABLE_FULL,        ER(ER_LOCK_TABLE_FULL));
116
  SETMSG(HA_ERR_READ_ONLY_TRANSACTION,  ER(ER_READ_ONLY_TRANSACTION));
117
  SETMSG(HA_ERR_LOCK_DEADLOCK,          ER(ER_LOCK_DEADLOCK));
118
  SETMSG(HA_ERR_CANNOT_ADD_FOREIGN,     ER(ER_CANNOT_ADD_FOREIGN));
119
  SETMSG(HA_ERR_NO_REFERENCED_ROW,      ER(ER_NO_REFERENCED_ROW_2));
120
  SETMSG(HA_ERR_ROW_IS_REFERENCED,      ER(ER_ROW_IS_REFERENCED_2));
121
  SETMSG(HA_ERR_NO_SAVEPOINT,           "No savepoint with that name");
122
  SETMSG(HA_ERR_NON_UNIQUE_BLOCK_SIZE,  "Non unique key block size");
123
  SETMSG(HA_ERR_NO_SUCH_TABLE,          "No such table: '%.64s'");
124
  SETMSG(HA_ERR_TABLE_EXIST,            ER(ER_TABLE_EXISTS_ERROR));
125
  SETMSG(HA_ERR_NO_CONNECTION,          "Could not connect to storage engine");
126
  SETMSG(HA_ERR_TABLE_DEF_CHANGED,      ER(ER_TABLE_DEF_CHANGED));
127
  SETMSG(HA_ERR_FOREIGN_DUPLICATE_KEY,  "FK constraint would lead to duplicate key");
128
  SETMSG(HA_ERR_TABLE_NEEDS_UPGRADE,    ER(ER_TABLE_NEEDS_UPGRADE));
129
  SETMSG(HA_ERR_TABLE_READONLY,         ER(ER_OPEN_AS_READONLY));
130
  SETMSG(HA_ERR_AUTOINC_READ_FAILED,    ER(ER_AUTOINC_READ_FAILED));
131
  SETMSG(HA_ERR_AUTOINC_ERANGE,         ER(ER_WARN_DATA_OUT_OF_RANGE));
132
133
  /* Register the error messages for use with my_error(). */
134
  return my_error_register(errmsgs, HA_ERR_FIRST, HA_ERR_LAST);
135
}
136
137
138
/**
139
  Unregister handler error messages.
140
141
  @retval
142
    0           OK
143
  @retval
144
    !=0         Error
145
*/
146
static int ha_finish_errors(void)
147
{
148
  const char    **errmsgs;
149
150
  /* Allocate a pointer array for the error message strings. */
151
  if (! (errmsgs= my_error_unregister(HA_ERR_FIRST, HA_ERR_LAST)))
152
    return 1;
481 by Brian Aker
Remove all of uchar.
153
  free((unsigned char*) errmsgs);
1 by brian
clean slate
154
  return 0;
155
}
156
157
int ha_init()
158
{
159
  int error= 0;
160
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
161
  assert(total_ha < MAX_HA);
1 by brian
clean slate
162
  /*
163
    Check if there is a transaction-capable storage engine besides the
164
    binary log (which is considered a transaction-capable storage engine in
165
    counting total_ha)
166
  */
167
  savepoint_alloc_size+= sizeof(SAVEPOINT);
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
168
  return error;
1 by brian
clean slate
169
}
170
171
int ha_end()
172
{
173
  int error= 0;
174
575.1.3 by Monty Taylor
Moved some stuff out of handler.h.
175
  /*
1 by brian
clean slate
176
    This should be eventualy based  on the graceful shutdown flag.
177
    So if flag is equal to HA_PANIC_CLOSE, the deallocate
178
    the errors.
179
  */
180
  if (ha_finish_errors())
181
    error= 1;
182
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
183
  return error;
1 by brian
clean slate
184
}
185
186
187
188
/* ========================================================================
189
 ======================= TRANSACTIONS ===================================*/
190
191
/**
192
  Transaction handling in the server
193
  ==================================
194
195
  In each client connection, MySQL maintains two transactional
196
  states:
197
  - a statement transaction,
198
  - a standard, also called normal transaction.
199
200
  Historical note
201
  ---------------
202
  "Statement transaction" is a non-standard term that comes
203
  from the times when MySQL supported BerkeleyDB storage engine.
204
205
  First of all, it should be said that in BerkeleyDB auto-commit
206
  mode auto-commits operations that are atomic to the storage
207
  engine itself, such as a write of a record, and are too
208
  high-granular to be atomic from the application perspective
209
  (MySQL). One SQL statement could involve many BerkeleyDB
210
  auto-committed operations and thus BerkeleyDB auto-commit was of
211
  little use to MySQL.
212
213
  Secondly, instead of SQL standard savepoints, BerkeleyDB
214
  provided the concept of "nested transactions". In a nutshell,
215
  transactions could be arbitrarily nested, but when the parent
216
  transaction was committed or aborted, all its child (nested)
217
  transactions were handled committed or aborted as well.
218
  Commit of a nested transaction, in turn, made its changes
219
  visible, but not durable: it destroyed the nested transaction,
220
  all its changes would become available to the parent and
221
  currently active nested transactions of this parent.
222
223
  So the mechanism of nested transactions was employed to
224
  provide "all or nothing" guarantee of SQL statements
225
  required by the standard.
226
  A nested transaction would be created at start of each SQL
227
  statement, and destroyed (committed or aborted) at statement
228
  end. Such nested transaction was internally referred to as
229
  a "statement transaction" and gave birth to the term.
230
231
  <Historical note ends>
232
233
  Since then a statement transaction is started for each statement
234
  that accesses transactional tables or uses the binary log.  If
235
  the statement succeeds, the statement transaction is committed.
236
  If the statement fails, the transaction is rolled back. Commits
237
  of statement transactions are not durable -- each such
238
  transaction is nested in the normal transaction, and if the
239
  normal transaction is rolled back, the effects of all enclosed
240
  statement transactions are undone as well.  Technically,
241
  a statement transaction can be viewed as a savepoint which is
242
  maintained automatically in order to make effects of one
243
  statement atomic.
244
245
  The normal transaction is started by the user and is ended
246
  usually upon a user request as well. The normal transaction
247
  encloses transactions of all statements issued between
248
  its beginning and its end.
249
  In autocommit mode, the normal transaction is equivalent
250
  to the statement transaction.
251
252
  Since MySQL supports PSEA (pluggable storage engine
253
  architecture), more than one transactional engine can be
254
  active at a time. Hence transactions, from the server
255
  point of view, are always distributed. In particular,
256
  transactional state is maintained independently for each
257
  engine. In order to commit a transaction the two phase
258
  commit protocol is employed.
259
260
  Not all statements are executed in context of a transaction.
261
  Administrative and status information statements do not modify
262
  engine data, and thus do not start a statement transaction and
263
  also have no effect on the normal transaction. Examples of such
264
  statements are SHOW STATUS and RESET SLAVE.
265
266
  Similarly DDL statements are not transactional,
267
  and therefore a transaction is [almost] never started for a DDL
268
  statement. The difference between a DDL statement and a purely
269
  administrative statement though is that a DDL statement always
270
  commits the current transaction before proceeding, if there is
271
  any.
272
273
  At last, SQL statements that work with non-transactional
274
  engines also have no effect on the transaction state of the
275
  connection. Even though they are written to the binary log,
276
  and the binary log is, overall, transactional, the writes
277
  are done in "write-through" mode, directly to the binlog
278
  file, followed with a OS cache sync, in other words,
279
  bypassing the binlog undo log (translog).
280
  They do not commit the current normal transaction.
281
  A failure of a statement that uses non-transactional tables
282
  would cause a rollback of the statement transaction, but
283
  in case there no non-transactional tables are used,
284
  no statement transaction is started.
285
286
  Data layout
287
  -----------
288
289
  The server stores its transaction-related data in
520.1.22 by Brian Aker
Second pass of thd cleanup
290
  session->transaction. This structure has two members of type
520.1.21 by Brian Aker
THD -> Session rename
291
  Session_TRANS. These members correspond to the statement and
1 by brian
clean slate
292
  normal transactions respectively:
293
520.1.22 by Brian Aker
Second pass of thd cleanup
294
  - session->transaction.stmt contains a list of engines
1 by brian
clean slate
295
  that are participating in the given statement
520.1.22 by Brian Aker
Second pass of thd cleanup
296
  - session->transaction.all contains a list of engines that
1 by brian
clean slate
297
  have participated in any of the statement transactions started
298
  within the context of the normal transaction.
299
  Each element of the list contains a pointer to the storage
300
  engine, engine-specific transactional data, and engine-specific
301
  transaction flags.
302
520.1.22 by Brian Aker
Second pass of thd cleanup
303
  In autocommit mode session->transaction.all is empty.
304
  Instead, data of session->transaction.stmt is
1 by brian
clean slate
305
  used to commit/rollback the normal transaction.
306
307
  The list of registered engines has a few important properties:
308
  - no engine is registered in the list twice
309
  - engines are present in the list a reverse temporal order --
310
  new participants are always added to the beginning of the list.
311
312
  Transaction life cycle
313
  ----------------------
314
520.1.22 by Brian Aker
Second pass of thd cleanup
315
  When a new connection is established, session->transaction
1 by brian
clean slate
316
  members are initialized to an empty state.
317
  If a statement uses any tables, all affected engines
318
  are registered in the statement engine list. In
319
  non-autocommit mode, the same engines are registered in
320
  the normal transaction list.
321
  At the end of the statement, the server issues a commit
322
  or a roll back for all engines in the statement list.
323
  At this point transaction flags of an engine, if any, are
324
  propagated from the statement list to the list of the normal
325
  transaction.
326
  When commit/rollback is finished, the statement list is
327
  cleared. It will be filled in again by the next statement,
328
  and emptied again at the next statement's end.
329
330
  The normal transaction is committed in a similar way
520.1.22 by Brian Aker
Second pass of thd cleanup
331
  (by going over all engines in session->transaction.all list)
1 by brian
clean slate
332
  but at different times:
333
  - upon COMMIT SQL statement is issued by the user
334
  - implicitly, by the server, at the beginning of a DDL statement
335
  or SET AUTOCOMMIT={0|1} statement.
336
337
  The normal transaction can be rolled back as well:
338
  - if the user has requested so, by issuing ROLLBACK SQL
339
  statement
340
  - if one of the storage engines requested a rollback
520.1.22 by Brian Aker
Second pass of thd cleanup
341
  by setting session->transaction_rollback_request. This may
1 by brian
clean slate
342
  happen in case, e.g., when the transaction in the engine was
343
  chosen a victim of the internal deadlock resolution algorithm
344
  and rolled back internally. When such a situation happens, there
345
  is little the server can do and the only option is to rollback
346
  transactions in all other participating engines.  In this case
347
  the rollback is accompanied by an error sent to the user.
348
349
  As follows from the use cases above, the normal transaction
350
  is never committed when there is an outstanding statement
351
  transaction. In most cases there is no conflict, since
352
  commits of the normal transaction are issued by a stand-alone
353
  administrative or DDL statement, thus no outstanding statement
354
  transaction of the previous statement exists. Besides,
355
  all statements that manipulate with the normal transaction
356
  are prohibited in stored functions and triggers, therefore
357
  no conflicting situation can occur in a sub-statement either.
358
  The remaining rare cases when the server explicitly has
359
  to commit the statement transaction prior to committing the normal
360
  one cover error-handling scenarios (see for example
1054.1.2 by Brian Aker
Remove SQLCOM_LOCK_TABLES
361
  ?).
1 by brian
clean slate
362
363
  When committing a statement or a normal transaction, the server
364
  either uses the two-phase commit protocol, or issues a commit
365
  in each engine independently. The two-phase commit protocol
366
  is used only if:
367
  - all participating engines support two-phase commit (provide
960.2.24 by Monty Taylor
Changed handlerton to StorageEngine.
368
    StorageEngine::prepare PSEA API call) and
1 by brian
clean slate
369
  - transactions in at least two engines modify data (i.e. are
370
  not read-only).
371
372
  Note that the two phase commit is used for
373
  statement transactions, even though they are not durable anyway.
374
  This is done to ensure logical consistency of data in a multiple-
375
  engine transaction.
376
  For example, imagine that some day MySQL supports unique
377
  constraint checks deferred till the end of statement. In such
378
  case a commit in one of the engines may yield ER_DUP_KEY,
379
  and MySQL should be able to gracefully abort statement
380
  transactions of other participants.
381
382
  After the normal transaction has been committed,
520.1.22 by Brian Aker
Second pass of thd cleanup
383
  session->transaction.all list is cleared.
1 by brian
clean slate
384
385
  When a connection is closed, the current normal transaction, if
386
  any, is rolled back.
387
388
  Roles and responsibilities
389
  --------------------------
390
391
  The server has no way to know that an engine participates in
392
  the statement and a transaction has been started
393
  in it unless the engine says so. Thus, in order to be
394
  a part of a transaction, the engine must "register" itself.
395
  This is done by invoking trans_register_ha() server call.
396
  Normally the engine registers itself whenever handler::external_lock()
397
  is called. trans_register_ha() can be invoked many times: if
398
  an engine is already registered, the call does nothing.
399
  In case autocommit is not set, the engine must register itself
400
  twice -- both in the statement list and in the normal transaction
401
  list.
402
  In which list to register is a parameter of trans_register_ha().
403
404
  Note, that although the registration interface in itself is
405
  fairly clear, the current usage practice often leads to undesired
406
  effects. E.g. since a call to trans_register_ha() in most engines
407
  is embedded into implementation of handler::external_lock(), some
408
  DDL statements start a transaction (at least from the server
409
  point of view) even though they are not expected to. E.g.
410
  CREATE TABLE does not start a transaction, since
411
  handler::external_lock() is never called during CREATE TABLE. But
412
  CREATE TABLE ... SELECT does, since handler::external_lock() is
413
  called for the table that is being selected from. This has no
414
  practical effects currently, but must be kept in mind
415
  nevertheless.
416
417
  Once an engine is registered, the server will do the rest
418
  of the work.
419
420
  During statement execution, whenever any of data-modifying
421
  PSEA API methods is used, e.g. handler::write_row() or
422
  handler::update_row(), the read-write flag is raised in the
423
  statement transaction for the involved engine.
424
  Currently All PSEA calls are "traced", and the data can not be
425
  changed in a way other than issuing a PSEA call. Important:
426
  unless this invariant is preserved the server will not know that
427
  a transaction in a given engine is read-write and will not
428
  involve the two-phase commit protocol!
429
430
  At the end of a statement, server call
431
  ha_autocommit_or_rollback() is invoked. This call in turn
960.2.24 by Monty Taylor
Changed handlerton to StorageEngine.
432
  invokes StorageEngine::prepare() for every involved engine.
433
  Prepare is followed by a call to StorageEngine::commit_one_phase()
434
  If a one-phase commit will suffice, StorageEngine::prepare() is not
435
  invoked and the server only calls StorageEngine::commit_one_phase().
1 by brian
clean slate
436
  At statement commit, the statement-related read-write engine
437
  flag is propagated to the corresponding flag in the normal
438
  transaction.  When the commit is complete, the list of registered
439
  engines is cleared.
440
441
  Rollback is handled in a similar fashion.
442
443
  Additional notes on DDL and the normal transaction.
444
  ---------------------------------------------------
445
446
  DDLs and operations with non-transactional engines
520.1.22 by Brian Aker
Second pass of thd cleanup
447
  do not "register" in session->transaction lists, and thus do not
1 by brian
clean slate
448
  modify the transaction state. Besides, each DDL in
449
  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.
450
  (a call to Session::endActiveTransaction()), and thus leaves nothing
1 by brian
clean slate
451
  to modify.
452
  However, as it has been pointed out with CREATE TABLE .. SELECT,
453
  some DDL statements can start a *new* transaction.
454
455
  Behaviour of the server in this case is currently badly
456
  defined.
457
  DDL statements use a form of "semantic" logging
458
  to maintain atomicity: if CREATE TABLE .. SELECT failed,
459
  the newly created table is deleted.
460
  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
461
  commits: e.g. ALTER Table issues a commit after data is copied
1 by brian
clean slate
462
  from the original table to the internal temporary table. Other
463
  statements, e.g. CREATE TABLE ... SELECT do not always commit
464
  after itself.
465
  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
466
  RENAME/DROP Table that doesn't start a new transaction
1 by brian
clean slate
467
  and doesn't commit.
468
469
  This diversity makes it hard to say what will happen if
470
  by chance a stored function is invoked during a DDL --
471
  whether any modifications it makes will be committed or not
472
  is not clear. Fortunately, SQL grammar of few DDLs allows
473
  invocation of a stored function.
474
475
  A consistent behaviour is perhaps to always commit the normal
476
  transaction after all DDLs, just like the statement transaction
477
  is always committed at the end of all statements.
478
*/
479
480
/**
481
  Register a storage engine for a transaction.
482
483
  Every storage engine MUST call this function when it starts
484
  a transaction or a statement (that is it must be called both for the
485
  "beginning of transaction" and "beginning of statement").
486
  Only storage engines registered for the transaction/statement
487
  will know when to commit/rollback it.
488
489
  @note
490
    trans_register_ha is idempotent - storage engine may register many
491
    times per transaction.
492
493
*/
960.2.27 by Monty Taylor
Reworked transformed handlerton into class StorageEngine.
494
void trans_register_ha(Session *session, bool all, StorageEngine *engine)
1 by brian
clean slate
495
{
520.1.21 by Brian Aker
THD -> Session rename
496
  Session_TRANS *trans;
1 by brian
clean slate
497
  Ha_trx_info *ha_info;
498
499
  if (all)
500
  {
520.1.22 by Brian Aker
Second pass of thd cleanup
501
    trans= &session->transaction.all;
502
    session->server_status|= SERVER_STATUS_IN_TRANS;
1 by brian
clean slate
503
  }
504
  else
520.1.22 by Brian Aker
Second pass of thd cleanup
505
    trans= &session->transaction.stmt;
1 by brian
clean slate
506
1030.1.1 by Brian Aker
Straighten out structures (remove some some dead bits).
507
  ha_info= session->ha_data[engine->getSlot()].ha_info + static_cast<unsigned>(all);
1 by brian
clean slate
508
509
  if (ha_info->is_started())
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
510
    return; /* already registered, return */
1 by brian
clean slate
511
960.2.27 by Monty Taylor
Reworked transformed handlerton into class StorageEngine.
512
  ha_info->register_ha(trans, engine);
1 by brian
clean slate
513
960.2.27 by Monty Taylor
Reworked transformed handlerton into class StorageEngine.
514
  trans->no_2pc|= not engine->has_2pc();
520.1.22 by Brian Aker
Second pass of thd cleanup
515
  if (session->transaction.xid_state.xid.is_null())
516
    session->transaction.xid_state.xid.set(session->query_id);
1 by brian
clean slate
517
}
518
519
/**
520
  Check if we can skip the two-phase commit.
521
522
  A helper function to evaluate if two-phase commit is mandatory.
523
  As a side effect, propagates the read-only/read-write flags
524
  of the statement transaction to its enclosing normal transaction.
525
56 by brian
Next pass of true/false update.
526
  @retval true   we must run a two-phase commit. Returned
1 by brian
clean slate
527
                 if we have at least two engines with read-write changes.
56 by brian
Next pass of true/false update.
528
  @retval false  Don't need two-phase commit. Even if we have two
1 by brian
clean slate
529
                 transactional engines, we can run two independent
530
                 commits if changes in one of the engines are read-only.
531
*/
532
533
static
534
bool
520.1.22 by Brian Aker
Second pass of thd cleanup
535
ha_check_and_coalesce_trx_read_only(Session *session, Ha_trx_info *ha_list,
1 by brian
clean slate
536
                                    bool all)
537
{
538
  /* The number of storage engines that have actual changes. */
539
  unsigned rw_ha_count= 0;
540
  Ha_trx_info *ha_info;
541
542
  for (ha_info= ha_list; ha_info; ha_info= ha_info->next())
543
  {
544
    if (ha_info->is_trx_read_write())
545
      ++rw_ha_count;
546
547
    if (! all)
548
    {
1030.1.1 by Brian Aker
Straighten out structures (remove some some dead bits).
549
      Ha_trx_info *ha_info_all= &session->ha_data[ha_info->engine()->getSlot()].ha_info[1];
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
550
      assert(ha_info != ha_info_all);
1 by brian
clean slate
551
      /*
552
        Merge read-only/read-write information about statement
553
        transaction to its enclosing normal transaction. Do this
554
        only if in a real transaction -- that is, if we know
520.1.22 by Brian Aker
Second pass of thd cleanup
555
        that ha_info_all is registered in session->transaction.all.
1 by brian
clean slate
556
        Since otherwise we only clutter the normal transaction flags.
557
      */
56 by brian
Next pass of true/false update.
558
      if (ha_info_all->is_started()) /* false if autocommit. */
1 by brian
clean slate
559
        ha_info_all->coalesce_trx_with(ha_info);
560
    }
561
    else if (rw_ha_count > 1)
562
    {
563
      /*
564
        It is a normal transaction, so we don't need to merge read/write
565
        information up, and the need for two-phase commit has been
566
        already established. Break the loop prematurely.
567
      */
568
      break;
569
    }
570
  }
571
  return rw_ha_count > 1;
572
}
573
574
575
/**
576
  @retval
577
    0   ok
578
  @retval
579
    1   transaction was rolled back
580
  @retval
581
    2   error during commit, data may be inconsistent
582
583
  @todo
584
    Since we don't support nested statement transactions in 5.0,
585
    we can't commit or rollback stmt transactions while we are inside
586
    stored functions or triggers. So we simply do nothing now.
587
    TODO: This should be fixed in later ( >= 5.1) releases.
588
*/
520.1.22 by Brian Aker
Second pass of thd cleanup
589
int ha_commit_trans(Session *session, bool all)
1 by brian
clean slate
590
{
591
  int error= 0, cookie= 0;
592
  /*
593
    'all' means that this is either an explicit commit issued by
594
    user, or an implicit commit issued by a DDL.
595
  */
520.1.22 by Brian Aker
Second pass of thd cleanup
596
  Session_TRANS *trans= all ? &session->transaction.all : &session->transaction.stmt;
597
  bool is_real_trans= all || session->transaction.all.ha_list == 0;
1 by brian
clean slate
598
  Ha_trx_info *ha_info= trans->ha_list;
599
600
  /*
601
    We must not commit the normal transaction if a statement
602
    transaction is pending. Otherwise statement transaction
603
    flags will not get propagated to its normal transaction's
604
    counterpart.
605
  */
520.1.22 by Brian Aker
Second pass of thd cleanup
606
  assert(session->transaction.stmt.ha_list == NULL ||
607
              trans == &session->transaction.stmt);
1 by brian
clean slate
608
609
  if (ha_info)
610
  {
611
    bool must_2pc;
612
520.1.22 by Brian Aker
Second pass of thd cleanup
613
    if (is_real_trans && wait_if_global_read_lock(session, 0, 0))
1 by brian
clean slate
614
    {
520.1.22 by Brian Aker
Second pass of thd cleanup
615
      ha_rollback_trans(session, all);
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
616
      return 1;
1 by brian
clean slate
617
    }
618
520.1.22 by Brian Aker
Second pass of thd cleanup
619
    must_2pc= ha_check_and_coalesce_trx_read_only(session, ha_info, all);
1 by brian
clean slate
620
621
    if (!trans->no_2pc && must_2pc)
622
    {
623
      for (; ha_info && !error; ha_info= ha_info->next())
624
      {
625
        int err;
960.2.37 by Monty Taylor
More naming fixes.
626
        StorageEngine *engine= ha_info->engine();
1 by brian
clean slate
627
        /*
628
          Do not call two-phase commit if this particular
629
          transaction is read-only. This allows for simpler
630
          implementation in engines that are always read-only.
631
        */
632
        if (! ha_info->is_trx_read_write())
633
          continue;
634
        /*
635
          Sic: we know that prepare() is not NULL since otherwise
636
          trans->no_2pc would have been set.
637
        */
960.2.38 by Monty Taylor
Removed extraneous send myself to myself argument.
638
        if ((err= engine->prepare(session, all)))
1 by brian
clean slate
639
        {
640
          my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
641
          error= 1;
642
        }
520.1.22 by Brian Aker
Second pass of thd cleanup
643
        status_var_increment(session->status_var.ha_prepare_count);
1 by brian
clean slate
644
      }
798.2.30 by Brian Aker
Removed dependency on log.h
645
      if (error)
1 by brian
clean slate
646
      {
520.1.22 by Brian Aker
Second pass of thd cleanup
647
        ha_rollback_trans(session, all);
1 by brian
clean slate
648
        error= 1;
649
        goto end;
650
      }
651
    }
520.1.22 by Brian Aker
Second pass of thd cleanup
652
    error=ha_commit_one_phase(session, all) ? (cookie ? 2 : 1) : 0;
1 by brian
clean slate
653
end:
654
    if (is_real_trans)
520.1.22 by Brian Aker
Second pass of thd cleanup
655
      start_waiting_global_read_lock(session);
1 by brian
clean slate
656
  }
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
657
  return error;
1 by brian
clean slate
658
}
659
660
/**
661
  @note
662
  This function does not care about global read lock. A caller should.
663
*/
520.1.22 by Brian Aker
Second pass of thd cleanup
664
int ha_commit_one_phase(Session *session, bool all)
1 by brian
clean slate
665
{
666
  int error=0;
520.1.22 by Brian Aker
Second pass of thd cleanup
667
  Session_TRANS *trans=all ? &session->transaction.all : &session->transaction.stmt;
668
  bool is_real_trans=all || session->transaction.all.ha_list == 0;
1 by brian
clean slate
669
  Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
670
  if (ha_info)
671
  {
672
    for (; ha_info; ha_info= ha_info_next)
673
    {
674
      int err;
960.2.37 by Monty Taylor
More naming fixes.
675
      StorageEngine *engine= ha_info->engine();
960.2.38 by Monty Taylor
Removed extraneous send myself to myself argument.
676
      if ((err= engine->commit(session, all)))
1 by brian
clean slate
677
      {
678
        my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
679
        error=1;
680
      }
520.1.22 by Brian Aker
Second pass of thd cleanup
681
      status_var_increment(session->status_var.ha_commit_count);
1 by brian
clean slate
682
      ha_info_next= ha_info->next();
683
      ha_info->reset(); /* keep it conveniently zero-filled */
684
    }
685
    trans->ha_list= 0;
686
    trans->no_2pc=0;
687
    if (is_real_trans)
520.1.22 by Brian Aker
Second pass of thd cleanup
688
      session->transaction.xid_state.xid.null();
1 by brian
clean slate
689
    if (all)
690
    {
520.1.22 by Brian Aker
Second pass of thd cleanup
691
      session->variables.tx_isolation=session->session_tx_isolation;
692
      session->transaction.cleanup();
1 by brian
clean slate
693
    }
694
  }
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
695
  return error;
1 by brian
clean slate
696
}
697
698
520.1.22 by Brian Aker
Second pass of thd cleanup
699
int ha_rollback_trans(Session *session, bool all)
1 by brian
clean slate
700
{
701
  int error=0;
520.1.22 by Brian Aker
Second pass of thd cleanup
702
  Session_TRANS *trans=all ? &session->transaction.all : &session->transaction.stmt;
1 by brian
clean slate
703
  Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
520.1.22 by Brian Aker
Second pass of thd cleanup
704
  bool is_real_trans=all || session->transaction.all.ha_list == 0;
1 by brian
clean slate
705
706
  /*
707
    We must not rollback the normal transaction if a statement
708
    transaction is pending.
709
  */
520.1.22 by Brian Aker
Second pass of thd cleanup
710
  assert(session->transaction.stmt.ha_list == NULL ||
711
              trans == &session->transaction.stmt);
1 by brian
clean slate
712
713
  if (ha_info)
714
  {
715
    for (; ha_info; ha_info= ha_info_next)
716
    {
717
      int err;
960.2.37 by Monty Taylor
More naming fixes.
718
      StorageEngine *engine= ha_info->engine();
960.2.38 by Monty Taylor
Removed extraneous send myself to myself argument.
719
      if ((err= engine->rollback(session, all)))
1 by brian
clean slate
720
      { // cannot happen
721
        my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
722
        error=1;
723
      }
520.1.22 by Brian Aker
Second pass of thd cleanup
724
      status_var_increment(session->status_var.ha_rollback_count);
1 by brian
clean slate
725
      ha_info_next= ha_info->next();
726
      ha_info->reset(); /* keep it conveniently zero-filled */
727
    }
728
    trans->ha_list= 0;
729
    trans->no_2pc=0;
730
    if (is_real_trans)
520.1.22 by Brian Aker
Second pass of thd cleanup
731
      session->transaction.xid_state.xid.null();
1 by brian
clean slate
732
    if (all)
733
    {
520.1.22 by Brian Aker
Second pass of thd cleanup
734
      session->variables.tx_isolation=session->session_tx_isolation;
735
      session->transaction.cleanup();
1 by brian
clean slate
736
    }
737
  }
738
  if (all)
520.1.22 by Brian Aker
Second pass of thd cleanup
739
    session->transaction_rollback_request= false;
1 by brian
clean slate
740
741
  /*
742
    If a non-transactional table was updated, warn; don't warn if this is a
743
    slave thread (because when a slave thread executes a ROLLBACK, it has
744
    been read from the binary log, so it's 100% sure and normal to produce
745
    error ER_WARNING_NOT_COMPLETE_ROLLBACK. If we sent the warning to the
746
    slave SQL thread, it would not stop the thread but just be printed in
747
    the error log; but we don't want users to wonder why they have this
748
    message in the error log, so we don't send it.
749
  */
812 by Brian Aker
Merge and fix for scheduler.h
750
  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
751
    push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1 by brian
clean slate
752
                 ER_WARNING_NOT_COMPLETE_ROLLBACK,
753
                 ER(ER_WARNING_NOT_COMPLETE_ROLLBACK));
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
754
  return error;
1 by brian
clean slate
755
}
756
757
/**
758
  This is used to commit or rollback a single statement depending on
759
  the value of error.
760
761
  @note
762
    Note that if the autocommit is on, then the following call inside
763
    InnoDB will commit or rollback the whole transaction (= the statement). The
764
    autocommit mechanism built into InnoDB is based on counting locks, but if
765
    the user has used LOCK TABLES then that mechanism does not know to do the
766
    commit.
767
*/
520.1.22 by Brian Aker
Second pass of thd cleanup
768
int ha_autocommit_or_rollback(Session *session, int error)
1 by brian
clean slate
769
{
520.1.22 by Brian Aker
Second pass of thd cleanup
770
  if (session->transaction.stmt.ha_list)
1 by brian
clean slate
771
  {
772
    if (!error)
773
    {
520.1.22 by Brian Aker
Second pass of thd cleanup
774
      if (ha_commit_trans(session, 0))
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
775
        error= 1;
1 by brian
clean slate
776
    }
575.1.3 by Monty Taylor
Moved some stuff out of handler.h.
777
    else
1 by brian
clean slate
778
    {
520.1.22 by Brian Aker
Second pass of thd cleanup
779
      (void) ha_rollback_trans(session, 0);
780
      if (session->transaction_rollback_request)
781
        (void) ha_rollback(session);
1 by brian
clean slate
782
    }
783
520.1.22 by Brian Aker
Second pass of thd cleanup
784
    session->variables.tx_isolation=session->session_tx_isolation;
1 by brian
clean slate
785
  }
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
786
787
  return error;
1 by brian
clean slate
788
}
789
790
/**
791
  return the list of XID's to a client, the same way SHOW commands do.
792
793
  @note
794
    I didn't find in XA specs that an RM cannot return the same XID twice,
795
    so mysql_xa_recover does not filter XID's to ensure uniqueness.
796
    It can be easily fixed later, if necessary.
797
*/
520.1.22 by Brian Aker
Second pass of thd cleanup
798
bool mysql_xa_recover(Session *session)
1 by brian
clean slate
799
{
800
  List<Item> field_list;
1093.1.57 by Jay Pipes
Merge and resolved conflicts for Monty's plugins/slots reorganization
801
  int i= 0;
1 by brian
clean slate
802
  XID_STATE *xs;
803
804
  field_list.push_back(new Item_int("formatID", 0, MY_INT32_NUM_DECIMAL_DIGITS));
805
  field_list.push_back(new Item_int("gtrid_length", 0, MY_INT32_NUM_DECIMAL_DIGITS));
806
  field_list.push_back(new Item_int("bqual_length", 0, MY_INT32_NUM_DECIMAL_DIGITS));
807
  field_list.push_back(new Item_empty_string("data",XIDDATASIZE));
808
971.6.1 by Eric Day
Renamed Protocol to Client, cleaned up some unnecessary methods along the way.
809
  if (session->client->sendFields(&field_list))
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
810
    return 1;
1 by brian
clean slate
811
812
  pthread_mutex_lock(&LOCK_xid_cache);
813
  while ((xs= (XID_STATE*)hash_element(&xid_cache, i++)))
814
  {
815
    if (xs->xa_state==XA_PREPARED)
816
    {
971.6.1 by Eric Day
Renamed Protocol to Client, cleaned up some unnecessary methods along the way.
817
      session->client->store((int64_t)xs->xid.formatID);
818
      session->client->store((int64_t)xs->xid.gtrid_length);
819
      session->client->store((int64_t)xs->xid.bqual_length);
820
      session->client->store(xs->xid.data,
821
                             xs->xid.gtrid_length+xs->xid.bqual_length);
822
      if (session->client->flush())
1 by brian
clean slate
823
      {
824
        pthread_mutex_unlock(&LOCK_xid_cache);
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
825
        return 1;
1 by brian
clean slate
826
      }
827
    }
828
  }
829
830
  pthread_mutex_unlock(&LOCK_xid_cache);
836 by Brian Aker
Fixed session call from function to method.
831
  session->my_eof();
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
832
  return 0;
1 by brian
clean slate
833
}
834
835
520.1.22 by Brian Aker
Second pass of thd cleanup
836
int ha_rollback_to_savepoint(Session *session, SAVEPOINT *sv)
1 by brian
clean slate
837
{
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
838
  int error= 0;
520.1.22 by Brian Aker
Second pass of thd cleanup
839
  Session_TRANS *trans= &session->transaction.all;
1 by brian
clean slate
840
  Ha_trx_info *ha_info, *ha_info_next;
841
842
  trans->no_2pc=0;
843
  /*
844
    rolling back to savepoint in all storage engines that were part of the
845
    transaction when the savepoint was set
846
  */
847
  for (ha_info= sv->ha_list; ha_info; ha_info= ha_info->next())
848
  {
849
    int err;
960.2.37 by Monty Taylor
More naming fixes.
850
    StorageEngine *engine= ha_info->engine();
960.2.27 by Monty Taylor
Reworked transformed handlerton into class StorageEngine.
851
    assert(engine);
960.2.38 by Monty Taylor
Removed extraneous send myself to myself argument.
852
    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.
853
                                         (void *)(sv+1))))
1 by brian
clean slate
854
    { // cannot happen
855
      my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
856
      error= 1;
1 by brian
clean slate
857
    }
520.1.22 by Brian Aker
Second pass of thd cleanup
858
    status_var_increment(session->status_var.ha_savepoint_rollback_count);
960.2.27 by Monty Taylor
Reworked transformed handlerton into class StorageEngine.
859
    trans->no_2pc|= not engine->has_2pc();
1 by brian
clean slate
860
  }
861
  /*
862
    rolling back the transaction in all storage engines that were not part of
863
    the transaction when the savepoint was set
864
  */
865
  for (ha_info= trans->ha_list; ha_info != sv->ha_list;
866
       ha_info= ha_info_next)
867
  {
868
    int err;
960.2.37 by Monty Taylor
More naming fixes.
869
    StorageEngine *engine= ha_info->engine();
960.2.38 by Monty Taylor
Removed extraneous send myself to myself argument.
870
    if ((err= engine->rollback(session, !(0))))
1 by brian
clean slate
871
    { // cannot happen
872
      my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
873
      error= 1;
1 by brian
clean slate
874
    }
520.1.22 by Brian Aker
Second pass of thd cleanup
875
    status_var_increment(session->status_var.ha_rollback_count);
1 by brian
clean slate
876
    ha_info_next= ha_info->next();
877
    ha_info->reset(); /* keep it conveniently zero-filled */
878
  }
879
  trans->ha_list= sv->ha_list;
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
880
  return error;
1 by brian
clean slate
881
}
882
883
/**
884
  @note
885
  according to the sql standard (ISO/IEC 9075-2:2003)
886
  section "4.33.4 SQL-statements and transaction states",
887
  SAVEPOINT is *not* transaction-initiating SQL-statement
888
*/
520.1.22 by Brian Aker
Second pass of thd cleanup
889
int ha_savepoint(Session *session, SAVEPOINT *sv)
1 by brian
clean slate
890
{
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
891
  int error= 0;
520.1.22 by Brian Aker
Second pass of thd cleanup
892
  Session_TRANS *trans= &session->transaction.all;
1 by brian
clean slate
893
  Ha_trx_info *ha_info= trans->ha_list;
894
  for (; ha_info; ha_info= ha_info->next())
895
  {
896
    int err;
960.2.37 by Monty Taylor
More naming fixes.
897
    StorageEngine *engine= ha_info->engine();
960.2.27 by Monty Taylor
Reworked transformed handlerton into class StorageEngine.
898
    assert(engine);
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
899
#ifdef NOT_IMPLEMENTED /*- TODO (examine this againt the original code base) */
900
    if (! engine->savepoint_set)
1 by brian
clean slate
901
    {
902
      my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "SAVEPOINT");
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
903
      error= 1;
1 by brian
clean slate
904
      break;
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
905
    } 
906
#endif
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.
907
    if ((err= engine->savepoint_set(session, (void *)(sv+1))))
1 by brian
clean slate
908
    { // cannot happen
909
      my_error(ER_GET_ERRNO, MYF(0), err);
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
910
      error= 1;
1 by brian
clean slate
911
    }
520.1.22 by Brian Aker
Second pass of thd cleanup
912
    status_var_increment(session->status_var.ha_savepoint_count);
1 by brian
clean slate
913
  }
914
  /*
915
    Remember the list of registered storage engines. All new
916
    engines are prepended to the beginning of the list.
917
  */
918
  sv->ha_list= trans->ha_list;
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
919
  return error;
1 by brian
clean slate
920
}
921
520.1.22 by Brian Aker
Second pass of thd cleanup
922
int ha_release_savepoint(Session *session, SAVEPOINT *sv)
1 by brian
clean slate
923
{
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
924
  int error= 0;
1 by brian
clean slate
925
  Ha_trx_info *ha_info= sv->ha_list;
926
927
  for (; ha_info; ha_info= ha_info->next())
928
  {
929
    int err;
960.2.37 by Monty Taylor
More naming fixes.
930
    StorageEngine *engine= ha_info->engine();
1 by brian
clean slate
931
    /* Savepoint life time is enclosed into transaction life time. */
960.2.27 by Monty Taylor
Reworked transformed handlerton into class StorageEngine.
932
    assert(engine);
960.2.38 by Monty Taylor
Removed extraneous send myself to myself argument.
933
    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.
934
                                        (void *)(sv+1))))
1 by brian
clean slate
935
    { // cannot happen
936
      my_error(ER_GET_ERRNO, MYF(0), err);
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
937
      error= 1;
1 by brian
clean slate
938
    }
939
  }
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
940
  return error;
1 by brian
clean slate
941
}
942
943
944
945
946
947
/****************************************************************************
948
** General handler functions
949
****************************************************************************/
1022.2.29 by Monty Taylor
Fixed some no-inline warnings.
950
handler::~handler(void)
951
{
952
  assert(locked == false);
953
  /* TODO: assert(inited == NONE); */
954
}
955
956
1 by brian
clean slate
957
handler *handler::clone(MEM_ROOT *mem_root)
958
{
959
  handler *new_handler= get_new_handler(table->s, mem_root, table->s->db_type());
960
  /*
961
    Allocate handler->ref here because otherwise ha_open will allocate it
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
962
    on this->table->mem_root and we will not be able to reclaim that memory
1 by brian
clean slate
963
    when the clone handler object is destroyed.
964
  */
481 by Brian Aker
Remove all of uchar.
965
  if (!(new_handler->ref= (unsigned char*) alloc_root(mem_root, ALIGN_SIZE(ref_length)*2)))
1 by brian
clean slate
966
    return NULL;
967
  if (new_handler && !new_handler->ha_open(table,
968
                                           table->s->normalized_path.str,
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
969
                                           table->getDBStat(),
1 by brian
clean slate
970
                                           HA_OPEN_IGNORE_IF_LOCKED))
971
    return new_handler;
972
  return NULL;
973
}
974
575.1.4 by Monty Taylor
Moved implementation of some methods into handler.cc from handler.h.
975
int handler::ha_index_init(uint32_t idx, bool sorted)
976
{
977
  int result;
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
978
  assert(inited == NONE);
575.1.4 by Monty Taylor
Moved implementation of some methods into handler.cc from handler.h.
979
  if (!(result= index_init(idx, sorted)))
980
    inited=INDEX;
981
  end_range= NULL;
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
982
  return result;
575.1.4 by Monty Taylor
Moved implementation of some methods into handler.cc from handler.h.
983
}
984
985
int handler::ha_index_end()
986
{
987
  assert(inited==INDEX);
988
  inited=NONE;
989
  end_range= NULL;
990
  return(index_end());
991
}
992
993
int handler::ha_rnd_init(bool scan)
994
{
995
  int result;
996
  assert(inited==NONE || (inited==RND && scan));
997
  inited= (result= rnd_init(scan)) ? NONE: RND;
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
998
999
  return result;
575.1.4 by Monty Taylor
Moved implementation of some methods into handler.cc from handler.h.
1000
}
1001
1002
int handler::ha_rnd_end()
1003
{
1004
  assert(inited==RND);
1005
  inited=NONE;
1006
  return(rnd_end());
1007
}
1008
1009
int handler::ha_index_or_rnd_end()
1010
{
1011
  return inited == INDEX ? ha_index_end() : inited == RND ? ha_rnd_end() : 0;
1012
}
1013
1014
handler::Table_flags handler::ha_table_flags() const
1015
{
1016
  return cached_table_flags;
1017
}
1018
1019
void handler::ha_start_bulk_insert(ha_rows rows)
1020
{
1021
  estimation_rows_to_insert= rows;
1022
  start_bulk_insert(rows);
1023
}
1024
1025
int handler::ha_end_bulk_insert()
1026
{
1027
  estimation_rows_to_insert= 0;
1028
  return end_bulk_insert();
1029
}
1030
1000.1.3 by Brian Aker
Renamed TABLE_SHARE to TableShare
1031
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.
1032
{
1033
  table= table_arg;
1034
  table_share= share;
1035
}
1036
1037
const key_map *handler::keys_to_use_for_scanning()
1038
{
1039
  return &key_map_empty;
1040
}
1041
1042
bool handler::has_transactions()
1043
{
1044
  return (ha_table_flags() & HA_NO_TRANSACTIONS) == 0;
1045
}
1 by brian
clean slate
1046
1047
void handler::ha_statistic_increment(ulong SSV::*offset) const
1048
{
1049
  status_var_increment(table->in_use->status_var.*offset);
1050
}
1051
520.1.22 by Brian Aker
Second pass of thd cleanup
1052
void **handler::ha_data(Session *session) const
1 by brian
clean slate
1053
{
960.2.37 by Monty Taylor
More naming fixes.
1054
  return session_ha_data(session, engine);
1 by brian
clean slate
1055
}
1056
520.1.22 by Brian Aker
Second pass of thd cleanup
1057
Session *handler::ha_session(void) const
1 by brian
clean slate
1058
{
520.1.22 by Brian Aker
Second pass of thd cleanup
1059
  assert(!table || !table->in_use || table->in_use == current_session);
1060
  return (table && table->in_use) ? table->in_use : current_session;
1 by brian
clean slate
1061
}
1062
575.1.4 by Monty Taylor
Moved implementation of some methods into handler.cc from handler.h.
1063
1064
bool handler::is_fatal_error(int error, uint32_t flags)
1065
{
1066
  if (!error ||
1067
      ((flags & HA_CHECK_DUP_KEY) &&
1068
       (error == HA_ERR_FOUND_DUPP_KEY ||
1069
        error == HA_ERR_FOUND_DUPP_UNIQUE)))
1070
    return false;
1071
  return true;
1072
}
1073
575.1.5 by Monty Taylor
Moved stuff to handlerton.cc
1074
1075
ha_rows handler::records() { return stats.records; }
1076
1 by brian
clean slate
1077
/**
1078
  Open database-handler.
1079
1080
  Try O_RDONLY if cannot open as O_RDWR
1081
  Don't wait for locks if not HA_OPEN_WAIT_IF_LOCKED is set
1082
*/
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
1083
int handler::ha_open(Table *table_arg, const char *name, int mode,
1 by brian
clean slate
1084
                     int test_if_locked)
1085
{
1086
  int error;
1087
1088
  table= table_arg;
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
1089
  assert(table->s == table_share);
1090
  assert(alloc_root_inited(&table->mem_root));
1 by brian
clean slate
1091
1092
  if ((error=open(name,mode,test_if_locked)))
1093
  {
1094
    if ((error == EACCES || error == EROFS) && mode == O_RDWR &&
1095
	(table->db_stat & HA_TRY_READ_ONLY))
1096
    {
1097
      table->db_stat|=HA_READ_ONLY;
1098
      error=open(name,O_RDONLY,test_if_locked);
1099
    }
1100
  }
1101
  if (error)
1102
  {
1103
    my_errno= error;                            /* Safeguard */
1104
  }
1105
  else
1106
  {
1107
    if (table->s->db_options_in_use & HA_OPTION_READ_ONLY_DATA)
1108
      table->db_stat|=HA_READ_ONLY;
1109
    (void) extra(HA_EXTRA_NO_READCHECK);	// Not needed in SQL
1110
1111
    /* ref is already allocated for us if we're called from handler::clone() */
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
1112
    if (!ref && !(ref= (unsigned char*) alloc_root(&table->mem_root,
1 by brian
clean slate
1113
                                          ALIGN_SIZE(ref_length)*2)))
1114
    {
1115
      close();
1116
      error=HA_ERR_OUT_OF_MEM;
1117
    }
1118
    else
1119
      dup_ref=ref+ALIGN_SIZE(ref_length);
1120
    cached_table_flags= table_flags();
1121
  }
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
1122
  return error;
1 by brian
clean slate
1123
}
1124
1125
/**
1126
  one has to use this method when to find
1127
  random position by record as the plain
1128
  position() call doesn't work for some
1129
  handlers for random position
1130
*/
1131
481 by Brian Aker
Remove all of uchar.
1132
int handler::rnd_pos_by_record(unsigned char *record)
1 by brian
clean slate
1133
{
1134
  register int error;
1135
1136
  position(record);
1137
  if (inited && (error= ha_index_end()))
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
1138
    return error;
56 by brian
Next pass of true/false update.
1139
  if ((error= ha_rnd_init(false)))
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
1140
    return error;
1 by brian
clean slate
1141
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
1142
  return rnd_pos(record, ref);
1 by brian
clean slate
1143
}
1144
1145
/**
1146
  Read first row (only) from a table.
1147
1148
  This is never called for InnoDB tables, as these table types
1149
  has the HA_STATS_RECORDS_IS_EXACT set.
1150
*/
482 by Brian Aker
Remove uint.
1151
int handler::read_first_row(unsigned char * buf, uint32_t primary_key)
1 by brian
clean slate
1152
{
1153
  register int error;
1154
1155
  ha_statistic_increment(&SSV::ha_read_first_count);
1156
1157
  /*
1158
    If there is very few deleted rows in the table, find the first row by
1159
    scanning the table.
1160
    TODO remove the test for HA_READ_ORDER
1161
  */
1162
  if (stats.deleted < 10 || primary_key >= MAX_KEY ||
1163
      !(index_flags(primary_key, 0, 0) & HA_READ_ORDER))
1164
  {
1165
    (void) ha_rnd_init(1);
1166
    while ((error= rnd_next(buf)) == HA_ERR_RECORD_DELETED) ;
1167
    (void) ha_rnd_end();
1168
  }
1169
  else
1170
  {
1171
    /* Find the first row through the primary key */
1172
    (void) ha_index_init(primary_key, 0);
1173
    error=index_first(buf);
1174
    (void) ha_index_end();
1175
  }
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
1176
  return error;
1 by brian
clean slate
1177
}
1178
1179
/**
1180
  Generate the next auto-increment number based on increment and offset.
1181
  computes the lowest number
1182
  - strictly greater than "nr"
1183
  - of the form: auto_increment_offset + N * auto_increment_increment
1184
1185
  In most cases increment= offset= 1, in which case we get:
1186
  @verbatim 1,2,3,4,5,... @endverbatim
1187
    If increment=10 and offset=5 and previous number is 1, we get:
1188
  @verbatim 1,5,15,25,35,... @endverbatim
1189
*/
1190
inline uint64_t
1191
compute_next_insert_id(uint64_t nr,struct system_variables *variables)
1192
{
1193
  if (variables->auto_increment_increment == 1)
1194
    return (nr+1); // optimization of the formula below
1195
  nr= (((nr+ variables->auto_increment_increment -
1196
         variables->auto_increment_offset)) /
1197
       (uint64_t) variables->auto_increment_increment);
1198
  return (nr* (uint64_t) variables->auto_increment_increment +
1199
          variables->auto_increment_offset);
1200
}
1201
1202
1203
void handler::adjust_next_insert_id_after_explicit_value(uint64_t nr)
1204
{
1205
  /*
520.1.21 by Brian Aker
THD -> Session rename
1206
    If we have set Session::next_insert_id previously and plan to insert an
1 by brian
clean slate
1207
    explicitely-specified value larger than this, we need to increase
520.1.21 by Brian Aker
THD -> Session rename
1208
    Session::next_insert_id to be greater than the explicit value.
1 by brian
clean slate
1209
  */
1210
  if ((next_insert_id > 0) && (nr >= next_insert_id))
1211
    set_next_insert_id(compute_next_insert_id(nr, &table->in_use->variables));
1212
}
1213
1214
1215
/**
1216
  Compute a previous insert id
1217
1218
  Computes the largest number X:
1219
  - smaller than or equal to "nr"
1220
  - of the form: auto_increment_offset + N * auto_increment_increment
1221
    where N>=0.
1222
1223
  @param nr            Number to "round down"
1224
  @param variables     variables struct containing auto_increment_increment and
1225
                       auto_increment_offset
1226
1227
  @return
1228
    The number X if it exists, "nr" otherwise.
1229
*/
1230
inline uint64_t
1231
prev_insert_id(uint64_t nr, struct system_variables *variables)
1232
{
1233
  if (unlikely(nr < variables->auto_increment_offset))
1234
  {
1235
    /*
1236
      There's nothing good we can do here. That is a pathological case, where
1237
      the offset is larger than the column's max possible value, i.e. not even
1238
      the first sequence value may be inserted. User will receive warning.
1239
    */
1240
    return nr;
1241
  }
1242
  if (variables->auto_increment_increment == 1)
1243
    return nr; // optimization of the formula below
1244
  nr= (((nr - variables->auto_increment_offset)) /
1245
       (uint64_t) variables->auto_increment_increment);
1246
  return (nr * (uint64_t) variables->auto_increment_increment +
1247
          variables->auto_increment_offset);
1248
}
1249
1250
1251
/**
1252
  Update the auto_increment field if necessary.
1253
1254
  Updates columns with type NEXT_NUMBER if:
1255
1055.2.2 by Jay Pipes
Cleanup of style, indentation, and documentation of Table class members. Removed 5 or 6 dead Table member variables.
1256
  - If column value is set to NULL (in which case auto_increment_field_not_null is false)
1 by brian
clean slate
1257
  - If column is set to 0 and (sql_mode & MODE_NO_AUTO_VALUE_ON_ZERO) is not
1258
    set. In the future we will only set NEXT_NUMBER fields if one sets them
1259
    to NULL (or they are not included in the insert list).
1260
1261
    In those cases, we check if the currently reserved interval still has
1262
    values we have not used. If yes, we pick the smallest one and use it.
1263
    Otherwise:
1264
1265
  - If a list of intervals has been provided to the statement via SET
1266
    INSERT_ID or via an Intvar_log_event (in a replication slave), we pick the
1267
    first unused interval from this list, consider it as reserved.
1268
1269
  - Otherwise we set the column for the first row to the value
1270
    next_insert_id(get_auto_increment(column))) which is usually
1271
    max-used-column-value+1.
1272
    We call get_auto_increment() for the first row in a multi-row
1273
    statement. get_auto_increment() will tell us the interval of values it
1274
    reserved for us.
1275
1276
  - In both cases, for the following rows we use those reserved values without
1277
    calling the handler again (we just progress in the interval, computing
1278
    each new value from the previous one). Until we have exhausted them, then
1279
    we either take the next provided interval or call get_auto_increment()
1280
    again to reserve a new interval.
1281
1282
  - In both cases, the reserved intervals are remembered in
520.1.22 by Brian Aker
Second pass of thd cleanup
1283
    session->auto_inc_intervals_in_cur_stmt_for_binlog if statement-based
1 by brian
clean slate
1284
    binlogging; the last reserved interval is remembered in
1285
    auto_inc_interval_for_cur_row.
1286
1287
    The idea is that generated auto_increment values are predictable and
1288
    independent of the column values in the table.  This is needed to be
1289
    able to replicate into a table that already has rows with a higher
1290
    auto-increment value than the one that is inserted.
1291
1292
    After we have already generated an auto-increment number and the user
1293
    inserts a column with a higher value than the last used one, we will
1294
    start counting from the inserted value.
1295
1296
    This function's "outputs" are: the table's auto_increment field is filled
520.1.22 by Brian Aker
Second pass of thd cleanup
1297
    with a value, session->next_insert_id is filled with the value to use for the
1 by brian
clean slate
1298
    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
1299
    session->insert_id_for_cur_row, if get_auto_increment() was called
1300
    session->auto_inc_interval_for_cur_row is modified, if that interval is not
1301
    present in session->auto_inc_intervals_in_cur_stmt_for_binlog it is added to
1 by brian
clean slate
1302
    this list.
1303
1304
  @todo
1305
    Replace all references to "next number" or NEXT_NUMBER to
1306
    "auto_increment", everywhere (see below: there is
1307
    table->auto_increment_field_not_null, and there also exists
1308
    table->next_number_field, it's not consistent).
1309
1310
  @retval
1311
    0	ok
1312
  @retval
1313
    HA_ERR_AUTOINC_READ_FAILED  get_auto_increment() was called and
1314
    returned ~(uint64_t) 0
1315
  @retval
1316
    HA_ERR_AUTOINC_ERANGE storing value in field caused strict mode
1317
    failure.
1318
*/
1319
1320
#define AUTO_INC_DEFAULT_NB_ROWS 1 // Some prefer 1024 here
1321
#define AUTO_INC_DEFAULT_NB_MAX_BITS 16
1322
#define AUTO_INC_DEFAULT_NB_MAX ((1 << AUTO_INC_DEFAULT_NB_MAX_BITS) - 1)
1323
1324
int handler::update_auto_increment()
1325
{
1326
  uint64_t nr, nb_reserved_values;
56 by brian
Next pass of true/false update.
1327
  bool append= false;
520.1.22 by Brian Aker
Second pass of thd cleanup
1328
  Session *session= table->in_use;
1329
  struct system_variables *variables= &session->variables;
1 by brian
clean slate
1330
1331
  /*
1332
    next_insert_id is a "cursor" into the reserved interval, it may go greater
1333
    than the interval, but not smaller.
1334
  */
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
1335
  assert(next_insert_id >= auto_inc_interval_for_cur_row.minimum());
1 by brian
clean slate
1336
1055.2.2 by Jay Pipes
Cleanup of style, indentation, and documentation of Table class members. Removed 5 or 6 dead Table member variables.
1337
  /* We check if auto_increment_field_not_null is false
1008.3.2 by Stewart Smith
Make sql_mode=NO_AUTO_VALUE_ON_ZERO default for Drizzle.
1338
     for an auto increment column, not a magic value like NULL is.
1339
     same as sql_mode=NO_AUTO_VALUE_ON_ZERO */
1340
1341
  if ((nr= table->next_number_field->val_int()) != 0
1342
      || table->auto_increment_field_not_null)
1 by brian
clean slate
1343
  {
1344
    /*
1345
      Update next_insert_id if we had already generated a value in this
1346
      statement (case of INSERT VALUES(null),(3763),(null):
1347
      the last NULL needs to insert 3764, not the value of the first NULL plus
1348
      1).
1349
    */
1350
    adjust_next_insert_id_after_explicit_value(nr);
1351
    insert_id_for_cur_row= 0; // didn't generate anything
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
1352
1353
    return 0;
1 by brian
clean slate
1354
  }
1355
1356
  if ((nr= next_insert_id) >= auto_inc_interval_for_cur_row.maximum())
1357
  {
1358
    /* next_insert_id is beyond what is reserved, so we reserve more. */
1359
    const Discrete_interval *forced=
520.1.22 by Brian Aker
Second pass of thd cleanup
1360
      session->auto_inc_intervals_forced.get_next();
1 by brian
clean slate
1361
    if (forced != NULL)
1362
    {
1363
      nr= forced->minimum();
1364
      nb_reserved_values= forced->values();
1365
    }
1366
    else
1367
    {
1368
      /*
1369
        handler::estimation_rows_to_insert was set by
1370
        handler::ha_start_bulk_insert(); if 0 it means "unknown".
1371
      */
482 by Brian Aker
Remove uint.
1372
      uint32_t nb_already_reserved_intervals=
520.1.22 by Brian Aker
Second pass of thd cleanup
1373
        session->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements();
1 by brian
clean slate
1374
      uint64_t nb_desired_values;
1375
      /*
1376
        If an estimation was given to the engine:
1377
        - use it.
1378
        - if we already reserved numbers, it means the estimation was
1379
        not accurate, then we'll reserve 2*AUTO_INC_DEFAULT_NB_ROWS the 2nd
1380
        time, twice that the 3rd time etc.
1381
        If no estimation was given, use those increasing defaults from the
1382
        start, starting from AUTO_INC_DEFAULT_NB_ROWS.
1383
        Don't go beyond a max to not reserve "way too much" (because
1384
        reservation means potentially losing unused values).
1385
      */
1386
      if (nb_already_reserved_intervals == 0 &&
1387
          (estimation_rows_to_insert > 0))
1388
        nb_desired_values= estimation_rows_to_insert;
1389
      else /* go with the increasing defaults */
1390
      {
1391
        /* avoid overflow in formula, with this if() */
1392
        if (nb_already_reserved_intervals <= AUTO_INC_DEFAULT_NB_MAX_BITS)
1393
        {
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
1394
          nb_desired_values= AUTO_INC_DEFAULT_NB_ROWS *
1 by brian
clean slate
1395
            (1 << nb_already_reserved_intervals);
937.2.6 by Stewart Smith
make set_if_bigger typesafe for C and C++. Fix up everywhere.
1396
          set_if_smaller(nb_desired_values, (uint64_t)AUTO_INC_DEFAULT_NB_MAX);
1 by brian
clean slate
1397
        }
1398
        else
1399
          nb_desired_values= AUTO_INC_DEFAULT_NB_MAX;
1400
      }
1401
      /* This call ignores all its parameters but nr, currently */
1402
      get_auto_increment(variables->auto_increment_offset,
1403
                         variables->auto_increment_increment,
1404
                         nb_desired_values, &nr,
1405
                         &nb_reserved_values);
1406
      if (nr == ~(uint64_t) 0)
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
1407
        return HA_ERR_AUTOINC_READ_FAILED;  // Mark failure
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
1408
1 by brian
clean slate
1409
      /*
1410
        That rounding below should not be needed when all engines actually
1411
        respect offset and increment in get_auto_increment(). But they don't
1412
        so we still do it. Wonder if for the not-first-in-index we should do
1413
        it. Hope that this rounding didn't push us out of the interval; even
1414
        if it did we cannot do anything about it (calling the engine again
1415
        will not help as we inserted no row).
1416
      */
1417
      nr= compute_next_insert_id(nr-1, variables);
1418
    }
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
1419
1 by brian
clean slate
1420
    if (table->s->next_number_keypart == 0)
1421
    {
1422
      /* We must defer the appending until "nr" has been possibly truncated */
56 by brian
Next pass of true/false update.
1423
      append= true;
1 by brian
clean slate
1424
    }
1425
  }
1426
152 by Brian Aker
longlong replacement
1427
  if (unlikely(table->next_number_field->store((int64_t) nr, true)))
1 by brian
clean slate
1428
  {
1429
    /*
1430
      first test if the query was aborted due to strict mode constraints
1431
    */
520.1.22 by Brian Aker
Second pass of thd cleanup
1432
    if (session->killed == Session::KILL_BAD_DATA)
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
1433
      return HA_ERR_AUTOINC_ERANGE;
1 by brian
clean slate
1434
1435
    /*
1436
      field refused this value (overflow) and truncated it, use the result of
1437
      the truncation (which is going to be inserted); however we try to
1438
      decrease it to honour auto_increment_* variables.
1439
      That will shift the left bound of the reserved interval, we don't
1440
      bother shifting the right bound (anyway any other value from this
1441
      interval will cause a duplicate key).
1442
    */
1443
    nr= prev_insert_id(table->next_number_field->val_int(), variables);
152 by Brian Aker
longlong replacement
1444
    if (unlikely(table->next_number_field->store((int64_t) nr, true)))
1 by brian
clean slate
1445
      nr= table->next_number_field->val_int();
1446
  }
1447
  if (append)
1448
  {
1449
    auto_inc_interval_for_cur_row.replace(nr, nb_reserved_values,
1450
                                          variables->auto_increment_increment);
1451
  }
1452
1453
  /*
1454
    Record this autogenerated value. If the caller then
1455
    succeeds to insert this value, it will call
1456
    record_first_successful_insert_id_in_cur_stmt()
1457
    which will set first_successful_insert_id_in_cur_stmt if it's not
1458
    already set.
1459
  */
1460
  insert_id_for_cur_row= nr;
1461
  /*
1462
    Set next insert id to point to next auto-increment value to be able to
1463
    handle multi-row statements.
1464
  */
1465
  set_next_insert_id(compute_next_insert_id(nr, variables));
1466
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
1467
  return 0;
1 by brian
clean slate
1468
}
1469
1470
1471
/**
1472
  Reserves an interval of auto_increment values from the handler.
1473
1474
  offset and increment means that we want values to be of the form
1475
  offset + N * increment, where N>=0 is integer.
1476
  If the function sets *first_value to ~(uint64_t)0 it means an error.
163 by Brian Aker
Merge Monty's code.
1477
  If the function sets *nb_reserved_values to UINT64_MAX it means it has
1 by brian
clean slate
1478
  reserved to "positive infinite".
1479
1480
  @param offset
1481
  @param increment
1482
  @param nb_desired_values   how many values we want
1483
  @param first_value         (OUT) the first value reserved by the handler
1484
  @param nb_reserved_values  (OUT) how many values the handler reserved
1485
*/
779.1.27 by Monty Taylor
Got rid of __attribute__((unused)) and the like from the .cc files.
1486
void handler::get_auto_increment(uint64_t ,
1487
                                 uint64_t ,
1488
                                 uint64_t ,
1 by brian
clean slate
1489
                                 uint64_t *first_value,
1490
                                 uint64_t *nb_reserved_values)
1491
{
1492
  uint64_t nr;
1493
  int error;
1494
1495
  (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
1496
  table->mark_columns_used_by_index_no_reset(table->s->next_number_index);
1 by brian
clean slate
1497
  index_init(table->s->next_number_index, 1);
1498
  if (table->s->next_number_keypart == 0)
1499
  {						// Autoincrement at key-start
1500
    error=index_last(table->record[1]);
1501
    /*
1502
      MySQL implicitely assumes such method does locking (as MySQL decides to
1503
      use nr+increment without checking again with the handler, in
1504
      handler::update_auto_increment()), so reserves to infinite.
1505
    */
163 by Brian Aker
Merge Monty's code.
1506
    *nb_reserved_values= UINT64_MAX;
1 by brian
clean slate
1507
  }
1508
  else
1509
  {
481 by Brian Aker
Remove all of uchar.
1510
    unsigned char key[MAX_KEY_LENGTH];
1 by brian
clean slate
1511
    key_copy(key, table->record[0],
1512
             table->key_info + table->s->next_number_index,
1513
             table->s->next_number_key_offset);
1514
    error= index_read_map(table->record[1], key,
1515
                          make_prev_keypart_map(table->s->next_number_keypart),
1516
                          HA_READ_PREFIX_LAST);
1517
    /*
1518
      MySQL needs to call us for next row: assume we are inserting ("a",null)
1519
      here, we return 3, and next this statement will want to insert
1520
      ("b",null): there is no reason why ("b",3+1) would be the good row to
1521
      insert: maybe it already exists, maybe 3+1 is too large...
1522
    */
1523
    *nb_reserved_values= 1;
1524
  }
1525
1526
  if (error)
1527
    nr=1;
1528
  else
1529
    nr= ((uint64_t) table->next_number_field->
1530
         val_int_offset(table->s->rec_buff_length)+1);
1531
  index_end();
1532
  (void) extra(HA_EXTRA_NO_KEYREAD);
1533
  *first_value= nr;
1534
}
1535
1536
1537
void handler::ha_release_auto_increment()
1538
{
1539
  release_auto_increment();
1540
  insert_id_for_cur_row= 0;
1541
  auto_inc_interval_for_cur_row.replace(0, 0, 0);
1542
  if (next_insert_id > 0)
1543
  {
1544
    next_insert_id= 0;
1545
    /*
1546
      this statement used forced auto_increment values if there were some,
1547
      wipe them away for other statements.
1548
    */
1549
    table->in_use->auto_inc_intervals_forced.empty();
1550
  }
1551
}
1552
1553
482 by Brian Aker
Remove uint.
1554
void handler::print_keydup_error(uint32_t key_nr, const char *msg)
1 by brian
clean slate
1555
{
1556
  /* Write the duplicated key in the error message */
1557
  char key[MAX_KEY_LENGTH];
1558
  String str(key,sizeof(key),system_charset_info);
1559
1560
  if (key_nr == MAX_KEY)
1561
  {
1562
    /* Key is unknown */
1563
    str.copy("", 0, system_charset_info);
1564
    my_printf_error(ER_DUP_ENTRY, msg, MYF(0), str.c_ptr(), "*UNKNOWN*");
1565
  }
1566
  else
1567
  {
1568
    /* Table is opened and defined at this point */
895 by Brian Aker
Completion (?) of uint conversion.
1569
    key_unpack(&str,table,(uint32_t) key_nr);
1570
    uint32_t max_length=DRIZZLE_ERRMSG_SIZE-(uint32_t) strlen(msg);
1 by brian
clean slate
1571
    if (str.length() >= max_length)
1572
    {
1573
      str.length(max_length-4);
1574
      str.append(STRING_WITH_LEN("..."));
1575
    }
1576
    my_printf_error(ER_DUP_ENTRY, msg,
1577
		    MYF(0), str.c_ptr(), table->key_info[key_nr].name);
1578
  }
1579
}
1580
1581
1582
/**
1583
  Print error that we got from handler function.
1584
1585
  @note
1586
    In case of delete table it's only safe to use the following parts of
1587
    the 'table' structure:
1588
    - table->s->path
1589
    - table->alias
1590
*/
1591
void handler::print_error(int error, myf errflag)
1592
{
1593
  int textno=ER_GET_ERRNO;
1594
  switch (error) {
1595
  case EACCES:
1596
    textno=ER_OPEN_AS_READONLY;
1597
    break;
1598
  case EAGAIN:
1599
    textno=ER_FILE_USED;
1600
    break;
1601
  case ENOENT:
1602
    textno=ER_FILE_NOT_FOUND;
1603
    break;
1604
  case HA_ERR_KEY_NOT_FOUND:
1605
  case HA_ERR_NO_ACTIVE_RECORD:
1606
  case HA_ERR_END_OF_FILE:
1607
    textno=ER_KEY_NOT_FOUND;
1608
    break;
1609
  case HA_ERR_WRONG_MRG_TABLE_DEF:
1610
    textno=ER_WRONG_MRG_TABLE;
1611
    break;
1612
  case HA_ERR_FOUND_DUPP_KEY:
1613
  {
482 by Brian Aker
Remove uint.
1614
    uint32_t key_nr=get_dup_key(error);
1 by brian
clean slate
1615
    if ((int) key_nr >= 0)
1616
    {
1617
      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
1618
      return;
1 by brian
clean slate
1619
    }
1620
    textno=ER_DUP_KEY;
1621
    break;
1622
  }
1623
  case HA_ERR_FOREIGN_DUPLICATE_KEY:
1624
  {
482 by Brian Aker
Remove uint.
1625
    uint32_t key_nr= get_dup_key(error);
1 by brian
clean slate
1626
    if ((int) key_nr >= 0)
1627
    {
482 by Brian Aker
Remove uint.
1628
      uint32_t max_length;
1 by brian
clean slate
1629
      /* Write the key in the error message */
1630
      char key[MAX_KEY_LENGTH];
1631
      String str(key,sizeof(key),system_charset_info);
1632
      /* Table is opened and defined at this point */
895 by Brian Aker
Completion (?) of uint conversion.
1633
      key_unpack(&str,table,(uint32_t) key_nr);
261.4.1 by Felipe
- Renamed MYSQL_ERROR to DRIZZLE_ERROR.
1634
      max_length= (DRIZZLE_ERRMSG_SIZE-
895 by Brian Aker
Completion (?) of uint conversion.
1635
                   (uint32_t) strlen(ER(ER_FOREIGN_DUPLICATE_KEY)));
1 by brian
clean slate
1636
      if (str.length() >= max_length)
1637
      {
1638
        str.length(max_length-4);
1639
        str.append(STRING_WITH_LEN("..."));
1640
      }
1641
      my_error(ER_FOREIGN_DUPLICATE_KEY, MYF(0), table_share->table_name.str,
1642
        str.c_ptr(), key_nr+1);
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
1643
      return;
1 by brian
clean slate
1644
    }
1645
    textno= ER_DUP_KEY;
1646
    break;
1647
  }
1648
  case HA_ERR_FOUND_DUPP_UNIQUE:
1649
    textno=ER_DUP_UNIQUE;
1650
    break;
1651
  case HA_ERR_RECORD_CHANGED:
1652
    textno=ER_CHECKREAD;
1653
    break;
1654
  case HA_ERR_CRASHED:
1655
    textno=ER_NOT_KEYFILE;
1656
    break;
1657
  case HA_ERR_WRONG_IN_RECORD:
1658
    textno= ER_CRASHED_ON_USAGE;
1659
    break;
1660
  case HA_ERR_CRASHED_ON_USAGE:
1661
    textno=ER_CRASHED_ON_USAGE;
1662
    break;
1663
  case HA_ERR_NOT_A_TABLE:
1001.1.3 by Andrew Ettinger
Revert bad spacing
1664
    textno= error;
1 by brian
clean slate
1665
    break;
1666
  case HA_ERR_CRASHED_ON_REPAIR:
1667
    textno=ER_CRASHED_ON_REPAIR;
1668
    break;
1669
  case HA_ERR_OUT_OF_MEM:
1670
    textno=ER_OUT_OF_RESOURCES;
1671
    break;
1672
  case HA_ERR_WRONG_COMMAND:
1673
    textno=ER_ILLEGAL_HA;
1674
    break;
1675
  case HA_ERR_OLD_FILE:
1676
    textno=ER_OLD_KEYFILE;
1677
    break;
1678
  case HA_ERR_UNSUPPORTED:
1679
    textno=ER_UNSUPPORTED_EXTENSION;
1680
    break;
1681
  case HA_ERR_RECORD_FILE_FULL:
1682
  case HA_ERR_INDEX_FILE_FULL:
1683
    textno=ER_RECORD_FILE_FULL;
1684
    break;
1685
  case HA_ERR_LOCK_WAIT_TIMEOUT:
1686
    textno=ER_LOCK_WAIT_TIMEOUT;
1687
    break;
1688
  case HA_ERR_LOCK_TABLE_FULL:
1689
    textno=ER_LOCK_TABLE_FULL;
1690
    break;
1691
  case HA_ERR_LOCK_DEADLOCK:
1692
    textno=ER_LOCK_DEADLOCK;
1693
    break;
1694
  case HA_ERR_READ_ONLY_TRANSACTION:
1695
    textno=ER_READ_ONLY_TRANSACTION;
1696
    break;
1697
  case HA_ERR_CANNOT_ADD_FOREIGN:
1698
    textno=ER_CANNOT_ADD_FOREIGN;
1699
    break;
1700
  case HA_ERR_ROW_IS_REFERENCED:
1701
  {
1702
    String str;
1703
    get_error_message(error, &str);
1704
    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
1705
    return;
1 by brian
clean slate
1706
  }
1707
  case HA_ERR_NO_REFERENCED_ROW:
1708
  {
1709
    String str;
1710
    get_error_message(error, &str);
1711
    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
1712
    return;
1 by brian
clean slate
1713
  }
1714
  case HA_ERR_TABLE_DEF_CHANGED:
1715
    textno=ER_TABLE_DEF_CHANGED;
1716
    break;
1717
  case HA_ERR_NO_SUCH_TABLE:
1718
    my_error(ER_NO_SUCH_TABLE, MYF(0), table_share->db.str,
1719
             table_share->table_name.str);
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
1720
    return;
1 by brian
clean slate
1721
  case HA_ERR_RBR_LOGGING_FAILED:
1722
    textno= ER_BINLOG_ROW_LOGGING_FAILED;
1723
    break;
1724
  case HA_ERR_DROP_INDEX_FK:
1725
  {
1726
    const char *ptr= "???";
482 by Brian Aker
Remove uint.
1727
    uint32_t key_nr= get_dup_key(error);
1 by brian
clean slate
1728
    if ((int) key_nr >= 0)
1729
      ptr= table->key_info[key_nr].name;
1730
    my_error(ER_DROP_INDEX_FK, MYF(0), ptr);
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
1731
    return;
1 by brian
clean slate
1732
  }
1733
  case HA_ERR_TABLE_NEEDS_UPGRADE:
1734
    textno=ER_TABLE_NEEDS_UPGRADE;
1735
    break;
1736
  case HA_ERR_TABLE_READONLY:
1737
    textno= ER_OPEN_AS_READONLY;
1738
    break;
1739
  case HA_ERR_AUTOINC_READ_FAILED:
1740
    textno= ER_AUTOINC_READ_FAILED;
1741
    break;
1742
  case HA_ERR_AUTOINC_ERANGE:
1743
    textno= ER_WARN_DATA_OUT_OF_RANGE;
1744
    break;
1745
  case HA_ERR_LOCK_OR_ACTIVE_TRANSACTION:
1746
    my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
1747
               ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
1748
    return;
1 by brian
clean slate
1749
  default:
1750
    {
1751
      /* The error was "unknown" to this function.
1752
	 Ask handler if it has got a message for this error */
56 by brian
Next pass of true/false update.
1753
      bool temporary= false;
1 by brian
clean slate
1754
      String str;
1755
      temporary= get_error_message(error, &str);
1756
      if (!str.is_empty())
1757
      {
1008.3.26 by Stewart Smith
remove handler::table_type() as same information can be retrieved from handler::engine->getName()
1758
        const char* engine_name= engine->getName().c_str();
1759
        if (temporary)
1760
          my_error(ER_GET_TEMPORARY_ERRMSG, MYF(0), error, str.ptr(),
960.2.37 by Monty Taylor
More naming fixes.
1761
                   engine_name);
1008.3.26 by Stewart Smith
remove handler::table_type() as same information can be retrieved from handler::engine->getName()
1762
        else
1763
          my_error(ER_GET_ERRMSG, MYF(0), error, str.ptr(), engine_name);
1 by brian
clean slate
1764
      }
1765
      else
960.2.37 by Monty Taylor
More naming fixes.
1766
      {
1767
	      my_error(ER_GET_ERRNO,errflag,error);
1768
      }
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
1769
      return;
1 by brian
clean slate
1770
    }
1771
  }
1772
  my_error(textno, errflag, table_share->table_name.str, error);
1773
}
1774
1775
1776
/**
1777
  Return an error message specific to this handler.
1778
1779
  @param error  error code previously returned by handler
1780
  @param buf    pointer to String where to add error message
1781
1782
  @return
1783
    Returns true if this is a temporary error
1784
*/
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
1785
bool handler::get_error_message(int , String* )
1 by brian
clean slate
1786
{
56 by brian
Next pass of true/false update.
1787
  return false;
1 by brian
clean slate
1788
}
1789
1790
1791
/* Code left, but Drizzle has no legacy yet (while MySQL did) */
1792
int handler::check_old_types()
1793
{
1794
  return 0;
1795
}
1796
1797
/**
1798
  @return
1799
    key if error because of duplicated keys
1800
*/
482 by Brian Aker
Remove uint.
1801
uint32_t handler::get_dup_key(int error)
1 by brian
clean slate
1802
{
895 by Brian Aker
Completion (?) of uint conversion.
1803
  table->file->errkey  = (uint32_t) -1;
1 by brian
clean slate
1804
  if (error == HA_ERR_FOUND_DUPP_KEY || error == HA_ERR_FOREIGN_DUPLICATE_KEY ||
1805
      error == HA_ERR_FOUND_DUPP_UNIQUE ||
1806
      error == HA_ERR_DROP_INDEX_FK)
1807
    info(HA_STATUS_ERRKEY | HA_STATUS_NO_LOCK);
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
1808
  return(table->file->errkey);
1 by brian
clean slate
1809
}
1810
1811
void handler::drop_table(const char *name)
1812
{
1813
  close();
1039.3.12 by Stewart Smith
remove handler::ha_delete_table and have StorageEngine::deleteTable instead
1814
  engine->deleteTable(ha_session(), name);
1 by brian
clean slate
1815
}
1816
1817
1818
/**
1819
  Performs checks upon the table.
1820
520.1.22 by Brian Aker
Second pass of thd cleanup
1821
  @param session                thread doing CHECK Table operation
1 by brian
clean slate
1822
  @param check_opt          options from the parser
1823
1824
  @retval
1825
    HA_ADMIN_OK               Successful upgrade
1826
  @retval
1827
    HA_ADMIN_NEEDS_UPGRADE    Table has structures requiring upgrade
1828
  @retval
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
1829
    HA_ADMIN_NEEDS_ALTER      Table has structures requiring ALTER Table
1 by brian
clean slate
1830
  @retval
1831
    HA_ADMIN_NOT_IMPLEMENTED
1832
*/
1039.1.16 by Brian Aker
A lot of little cleanups (most based off lcov)
1833
int handler::ha_check(Session *, HA_CHECK_OPT *)
1 by brian
clean slate
1834
{
590.1.4 by Stewart Smith
remove frm_version from TABLE_SHARE
1835
  return HA_ADMIN_OK;
1 by brian
clean slate
1836
}
1837
1838
/**
1839
  A helper function to mark a transaction read-write,
1840
  if it is started.
1841
*/
1842
1843
inline
1844
void
1845
handler::mark_trx_read_write()
1846
{
1030.1.1 by Brian Aker
Straighten out structures (remove some some dead bits).
1847
  Ha_trx_info *ha_info= &ha_session()->ha_data[engine->getSlot()].ha_info[0];
1 by brian
clean slate
1848
  /*
1849
    When a storage engine method is called, the transaction must
1850
    have been started, unless it's a DDL call, for which the
1851
    storage engine starts the transaction internally, and commits
1852
    it internally, without registering in the ha_list.
1853
    Unfortunately here we can't know know for sure if the engine
1854
    has registered the transaction or not, so we must check.
1855
  */
1856
  if (ha_info->is_started())
1857
  {
1858
    /*
1859
      table_share can be NULL in ha_delete_table(). See implementation
1860
      of standalone function ha_delete_table() in sql_base.cc.
1861
    */
1039.3.8 by Stewart Smith
Re-introduce marking transaction as read-write for engine on create_table:
1862
//    if (table_share == NULL || table_share->tmp_table == NO_TMP_TABLE)
1 by brian
clean slate
1863
      ha_info->set_trx_read_write();
1864
  }
1865
}
1866
1867
/**
1868
  Bulk update row: public interface.
1869
1870
  @sa handler::bulk_update_row()
1871
*/
1872
1873
int
481 by Brian Aker
Remove all of uchar.
1874
handler::ha_bulk_update_row(const unsigned char *old_data, unsigned char *new_data,
482 by Brian Aker
Remove uint.
1875
                            uint32_t *dup_key_found)
1 by brian
clean slate
1876
{
1877
  mark_trx_read_write();
1878
1879
  return bulk_update_row(old_data, new_data, dup_key_found);
1880
}
1881
1882
1883
/**
1884
  Delete all rows: public interface.
1885
1886
  @sa handler::delete_all_rows()
1887
*/
1888
1889
int
1890
handler::ha_delete_all_rows()
1891
{
1892
  mark_trx_read_write();
1893
1894
  return delete_all_rows();
1895
}
1896
1897
1898
/**
1899
  Reset auto increment: public interface.
1900
1901
  @sa handler::reset_auto_increment()
1902
*/
1903
1904
int
1905
handler::ha_reset_auto_increment(uint64_t value)
1906
{
1907
  mark_trx_read_write();
1908
1909
  return reset_auto_increment(value);
1910
}
1911
1912
1913
/**
1914
  Optimize table: public interface.
1915
1916
  @sa handler::optimize()
1917
*/
1918
1919
int
520.1.22 by Brian Aker
Second pass of thd cleanup
1920
handler::ha_optimize(Session* session, HA_CHECK_OPT* check_opt)
1 by brian
clean slate
1921
{
1922
  mark_trx_read_write();
1923
520.1.22 by Brian Aker
Second pass of thd cleanup
1924
  return optimize(session, check_opt);
1 by brian
clean slate
1925
}
1926
1927
1928
/**
1929
  Analyze table: public interface.
1930
1931
  @sa handler::analyze()
1932
*/
1933
1934
int
520.1.22 by Brian Aker
Second pass of thd cleanup
1935
handler::ha_analyze(Session* session, HA_CHECK_OPT* check_opt)
1 by brian
clean slate
1936
{
1937
  mark_trx_read_write();
1938
520.1.22 by Brian Aker
Second pass of thd cleanup
1939
  return analyze(session, check_opt);
1 by brian
clean slate
1940
}
1941
1942
/**
1943
  Disable indexes: public interface.
1944
1945
  @sa handler::disable_indexes()
1946
*/
1947
1948
int
482 by Brian Aker
Remove uint.
1949
handler::ha_disable_indexes(uint32_t mode)
1 by brian
clean slate
1950
{
1951
  mark_trx_read_write();
1952
1953
  return disable_indexes(mode);
1954
}
1955
1956
1957
/**
1958
  Enable indexes: public interface.
1959
1960
  @sa handler::enable_indexes()
1961
*/
1962
1963
int
482 by Brian Aker
Remove uint.
1964
handler::ha_enable_indexes(uint32_t mode)
1 by brian
clean slate
1965
{
1966
  mark_trx_read_write();
1967
1968
  return enable_indexes(mode);
1969
}
1970
1971
1972
/**
1973
  Discard or import tablespace: public interface.
1974
1975
  @sa handler::discard_or_import_tablespace()
1976
*/
1977
1978
int
200 by Brian Aker
my_bool from handler and set_var
1979
handler::ha_discard_or_import_tablespace(bool discard)
1 by brian
clean slate
1980
{
1981
  mark_trx_read_write();
1982
1983
  return discard_or_import_tablespace(discard);
1984
}
1985
1986
/**
1987
  Drop table in the engine: public interface.
1988
1989
  @sa handler::drop_table()
1990
*/
1991
1992
void
1993
handler::ha_drop_table(const char *name)
1994
{
1995
  mark_trx_read_write();
1996
1997
  return drop_table(name);
1998
}
1999
2000
/**
2001
  Tell the storage engine that it is allowed to "disable transaction" in the
2002
  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
2003
  ALTER Table, for example, when data are copied to temporary table.
1 by brian
clean slate
2004
  A storage engine may treat this hint any way it likes. NDB for example
2005
  starts to commit every now and then automatically.
2006
  This hint can be safely ignored.
2007
*/
520.1.22 by Brian Aker
Second pass of thd cleanup
2008
int ha_enable_transaction(Session *session, bool on)
1 by brian
clean slate
2009
{
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
2010
  int error= 0;
1 by brian
clean slate
2011
520.1.22 by Brian Aker
Second pass of thd cleanup
2012
  if ((session->transaction.on= on))
1 by brian
clean slate
2013
  {
2014
    /*
2015
      Now all storage engines should have transaction handling enabled.
2016
      But some may have it enabled all the time - "disabling" transactions
2017
      is an optimization hint that storage engine is free to ignore.
2018
      So, let's commit an open transaction (if any) now.
2019
    */
520.1.22 by Brian Aker
Second pass of thd cleanup
2020
    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.
2021
      if (! session->endTransaction(COMMIT))
2022
        error= 1;
2023
1 by brian
clean slate
2024
  }
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
2025
  return error;
1 by brian
clean slate
2026
}
2027
482 by Brian Aker
Remove uint.
2028
int handler::index_next_same(unsigned char *buf, const unsigned char *key, uint32_t keylen)
1 by brian
clean slate
2029
{
2030
  int error;
2031
  if (!(error=index_next(buf)))
2032
  {
2033
    my_ptrdiff_t ptrdiff= buf - table->record[0];
481 by Brian Aker
Remove all of uchar.
2034
    unsigned char *save_record_0= NULL;
1 by brian
clean slate
2035
    KEY *key_info= NULL;
2036
    KEY_PART_INFO *key_part;
2037
    KEY_PART_INFO *key_part_end= NULL;
2038
2039
    /*
2040
      key_cmp_if_same() compares table->record[0] against 'key'.
2041
      In parts it uses table->record[0] directly, in parts it uses
2042
      field objects with their local pointers into table->record[0].
2043
      If 'buf' is distinct from table->record[0], we need to move
2044
      all record references. This is table->record[0] itself and
2045
      the field pointers of the fields used in this key.
2046
    */
2047
    if (ptrdiff)
2048
    {
2049
      save_record_0= table->record[0];
2050
      table->record[0]= buf;
2051
      key_info= table->key_info + active_index;
2052
      key_part= key_info->key_part;
2053
      key_part_end= key_part + key_info->key_parts;
2054
      for (; key_part < key_part_end; key_part++)
2055
      {
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
2056
        assert(key_part->field);
1 by brian
clean slate
2057
        key_part->field->move_field_offset(ptrdiff);
2058
      }
2059
    }
2060
2061
    if (key_cmp_if_same(table, key, active_index, keylen))
2062
    {
2063
      table->status=STATUS_NOT_FOUND;
2064
      error=HA_ERR_END_OF_FILE;
2065
    }
2066
2067
    /* Move back if necessary. */
2068
    if (ptrdiff)
2069
    {
2070
      table->record[0]= save_record_0;
2071
      for (key_part= key_info->key_part; key_part < key_part_end; key_part++)
2072
        key_part->field->move_field_offset(-ptrdiff);
2073
    }
2074
  }
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
2075
  return error;
1 by brian
clean slate
2076
}
2077
2078
2079
/****************************************************************************
2080
** Some general functions that isn't in the handler class
2081
****************************************************************************/
2082
2083
2084
void st_ha_check_opt::init()
2085
{
792 by Brian Aker
Refactor for myisam specifics in handler
2086
  flags= 0; 
2087
  use_frm= false;
1 by brian
clean slate
2088
}
2089
2090
/**
2091
  Calculate cost of 'index only' scan for given index and number of records
2092
2093
  @param keynr    Index number
2094
  @param records  Estimated number of records to be retrieved
2095
2096
  @note
2097
    It is assumed that we will read trough the whole key range and that all
2098
    key blocks are half full (normally things are much better). It is also
2099
    assumed that each time we read the next key from the index, the handler
2100
    performs a random seek, thus the cost is proportional to the number of
2101
    blocks read.
2102
2103
  @todo
2104
    Consider joining this function and handler::read_time() into one
2105
    handler::read_time(keynr, records, ranges, bool index_only) function.
2106
2107
  @return
2108
    Estimated cost of 'index only' scan
2109
*/
2110
779.3.10 by Monty Taylor
Turned on -Wshadow.
2111
double handler::index_only_read_time(uint32_t keynr, double key_records)
1 by brian
clean slate
2112
{
482 by Brian Aker
Remove uint.
2113
  uint32_t keys_per_block= (stats.block_size/2/
1 by brian
clean slate
2114
			(table->key_info[keynr].key_length + ref_length) + 1);
779.3.10 by Monty Taylor
Turned on -Wshadow.
2115
  return ((double) (key_records + keys_per_block-1) /
2116
          (double) keys_per_block);
1 by brian
clean slate
2117
}
2118
2119
2120
/****************************************************************************
2121
 * Default MRR implementation (MRR to non-MRR converter)
2122
 ***************************************************************************/
2123
2124
/**
2125
  Get cost and other information about MRR scan over a known list of ranges
2126
2127
  Calculate estimated cost and other information about an MRR scan for given
2128
  sequence of ranges.
2129
2130
  @param keyno           Index number
2131
  @param seq             Range sequence to be traversed
2132
  @param seq_init_param  First parameter for seq->init()
2133
  @param n_ranges_arg    Number of ranges in the sequence, or 0 if the caller
2134
                         can't efficiently determine it
2135
  @param bufsz    INOUT  IN:  Size of the buffer available for use
2136
                         OUT: Size of the buffer that is expected to be actually
2137
                              used, or 0 if buffer is not needed.
2138
  @param flags    INOUT  A combination of HA_MRR_* flags
2139
  @param cost     OUT    Estimated cost of MRR access
2140
2141
  @note
2142
    This method (or an overriding one in a derived class) must check for
520.1.22 by Brian Aker
Second pass of thd cleanup
2143
    session->killed and return HA_POS_ERROR if it is not zero. This is required
1 by brian
clean slate
2144
    for a user to be able to interrupt the calculation by killing the
2145
    connection/query.
2146
2147
  @retval
2148
    HA_POS_ERROR  Error or the engine is unable to perform the requested
2149
                  scan. Values of OUT parameters are undefined.
2150
  @retval
2151
    other         OK, *cost contains cost of the scan, *bufsz and *flags
2152
                  contain scan parameters.
2153
*/
2154
77.1.15 by Monty Taylor
Bunch of warning cleanups.
2155
ha_rows
482 by Brian Aker
Remove uint.
2156
handler::multi_range_read_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
77.1.15 by Monty Taylor
Bunch of warning cleanups.
2157
                                     void *seq_init_param,
779.1.27 by Monty Taylor
Got rid of __attribute__((unused)) and the like from the .cc files.
2158
                                     uint32_t ,
482 by Brian Aker
Remove uint.
2159
                                     uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
1 by brian
clean slate
2160
{
2161
  KEY_MULTI_RANGE range;
2162
  range_seq_t seq_it;
2163
  ha_rows rows, total_rows= 0;
482 by Brian Aker
Remove uint.
2164
  uint32_t n_ranges=0;
520.1.22 by Brian Aker
Second pass of thd cleanup
2165
  Session *session= current_session;
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
2166
1 by brian
clean slate
2167
  /* Default MRR implementation doesn't need buffer */
2168
  *bufsz= 0;
2169
2170
  seq_it= seq->init(seq_init_param, n_ranges, *flags);
2171
  while (!seq->next(seq_it, &range))
2172
  {
520.1.22 by Brian Aker
Second pass of thd cleanup
2173
    if (unlikely(session->killed != 0))
1 by brian
clean slate
2174
      return HA_POS_ERROR;
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
2175
1 by brian
clean slate
2176
    n_ranges++;
2177
    key_range *min_endp, *max_endp;
2178
    {
2179
      min_endp= range.start_key.length? &range.start_key : NULL;
2180
      max_endp= range.end_key.length? &range.end_key : NULL;
2181
    }
2182
    if ((range.range_flag & UNIQUE_RANGE) && !(range.range_flag & NULL_RANGE))
2183
      rows= 1; /* there can be at most one row */
2184
    else
2185
    {
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
2186
      if (HA_POS_ERROR == (rows= this->records_in_range(keyno, min_endp,
1 by brian
clean slate
2187
                                                        max_endp)))
2188
      {
2189
        /* Can't scan one range => can't do MRR scan at all */
2190
        total_rows= HA_POS_ERROR;
2191
        break;
2192
      }
2193
    }
2194
    total_rows += rows;
2195
  }
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
2196
1 by brian
clean slate
2197
  if (total_rows != HA_POS_ERROR)
2198
  {
2199
    /* The following calculation is the same as in multi_range_read_info(): */
2200
    *flags |= HA_MRR_USE_DEFAULT_IMPL;
2201
    cost->zero();
2202
    cost->avg_io_cost= 1; /* assume random seeks */
2203
    if ((*flags & HA_MRR_INDEX_ONLY) && total_rows > 2)
895 by Brian Aker
Completion (?) of uint conversion.
2204
      cost->io_count= index_only_read_time(keyno, (uint32_t)total_rows);
1 by brian
clean slate
2205
    else
2206
      cost->io_count= read_time(keyno, n_ranges, total_rows);
2207
    cost->cpu_cost= (double) total_rows / TIME_FOR_COMPARE + 0.01;
2208
  }
2209
  return total_rows;
2210
}
2211
2212
2213
/**
2214
  Get cost and other information about MRR scan over some sequence of ranges
2215
2216
  Calculate estimated cost and other information about an MRR scan for some
2217
  sequence of ranges.
2218
2219
  The ranges themselves will be known only at execution phase. When this
2220
  function is called we only know number of ranges and a (rough) E(#records)
2221
  within those ranges.
2222
2223
  Currently this function is only called for "n-keypart singlepoint" ranges,
2224
  i.e. each range is "keypart1=someconst1 AND ... AND keypartN=someconstN"
2225
2226
  The flags parameter is a combination of those flags: HA_MRR_SORTED,
2227
  HA_MRR_INDEX_ONLY, HA_MRR_NO_ASSOCIATION, HA_MRR_LIMITS.
2228
2229
  @param keyno           Index number
2230
  @param n_ranges        Estimated number of ranges (i.e. intervals) in the
2231
                         range sequence.
2232
  @param n_rows          Estimated total number of records contained within all
2233
                         of the ranges
2234
  @param bufsz    INOUT  IN:  Size of the buffer available for use
2235
                         OUT: Size of the buffer that will be actually used, or
2236
                              0 if buffer is not needed.
2237
  @param flags    INOUT  A combination of HA_MRR_* flags
2238
  @param cost     OUT    Estimated cost of MRR access
2239
2240
  @retval
2241
    0     OK, *cost contains cost of the scan, *bufsz and *flags contain scan
2242
          parameters.
2243
  @retval
2244
    other Error or can't perform the requested scan
2245
*/
2246
482 by Brian Aker
Remove uint.
2247
int handler::multi_range_read_info(uint32_t keyno, uint32_t n_ranges, uint32_t n_rows,
2248
                                   uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
1 by brian
clean slate
2249
{
2250
  *bufsz= 0; /* Default implementation doesn't need a buffer */
2251
2252
  *flags |= HA_MRR_USE_DEFAULT_IMPL;
2253
2254
  cost->zero();
2255
  cost->avg_io_cost= 1; /* assume random seeks */
2256
2257
  /* Produce the same cost as non-MRR code does */
2258
  if (*flags & HA_MRR_INDEX_ONLY)
2259
    cost->io_count= index_only_read_time(keyno, n_rows);
2260
  else
2261
    cost->io_count= read_time(keyno, n_ranges, n_rows);
2262
  return 0;
2263
}
2264
2265
2266
/**
2267
  Initialize the MRR scan
2268
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
2269
  Initialize the MRR scan. This function may do heavyweight scan
1 by brian
clean slate
2270
  initialization like row prefetching/sorting/etc (NOTE: but better not do
2271
  it here as we may not need it, e.g. if we never satisfy WHERE clause on
2272
  previous tables. For many implementations it would be natural to do such
2273
  initializations in the first multi_read_range_next() call)
2274
2275
  mode is a combination of the following flags: HA_MRR_SORTED,
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
2276
  HA_MRR_INDEX_ONLY, HA_MRR_NO_ASSOCIATION
1 by brian
clean slate
2277
2278
  @param seq             Range sequence to be traversed
2279
  @param seq_init_param  First parameter for seq->init()
2280
  @param n_ranges        Number of ranges in the sequence
2281
  @param mode            Flags, see the description section for the details
2282
  @param buf             INOUT: memory buffer to be used
2283
2284
  @note
2285
    One must have called index_init() before calling this function. Several
2286
    multi_range_read_init() calls may be made in course of one query.
2287
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
2288
    Until WL#2623 is done (see its text, section 3.2), the following will
1 by brian
clean slate
2289
    also hold:
2290
    The caller will guarantee that if "seq->init == mrr_ranges_array_init"
2291
    then seq_init_param is an array of n_ranges KEY_MULTI_RANGE structures.
2292
    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.
2293
1 by brian
clean slate
2294
    Buffer memory management is done according to the following scenario:
2295
    The caller allocates the buffer and provides it to the callee by filling
2296
    the members of HANDLER_BUFFER structure.
2297
    The callee consumes all or some fraction of the provided buffer space, and
2298
    sets the HANDLER_BUFFER members accordingly.
2299
    The callee may use the buffer memory until the next multi_range_read_init()
2300
    call is made, all records have been read, or until index_end() call is
2301
    made, whichever comes first.
2302
2303
  @retval 0  OK
2304
  @retval 1  Error
2305
*/
2306
2307
int
2308
handler::multi_range_read_init(RANGE_SEQ_IF *seq_funcs, void *seq_init_param,
482 by Brian Aker
Remove uint.
2309
                               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.
2310
                               HANDLER_BUFFER *)
1 by brian
clean slate
2311
{
2312
  mrr_iter= seq_funcs->init(seq_init_param, n_ranges, mode);
2313
  mrr_funcs= *seq_funcs;
2314
  mrr_is_output_sorted= test(mode & HA_MRR_SORTED);
56 by brian
Next pass of true/false update.
2315
  mrr_have_range= false;
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
2316
  return 0;
1 by brian
clean slate
2317
}
2318
2319
2320
/**
2321
  Get next record in MRR scan
2322
2323
  Default MRR implementation: read the next record
2324
2325
  @param range_info  OUT  Undefined if HA_MRR_NO_ASSOCIATION flag is in effect
2326
                          Otherwise, the opaque value associated with the range
2327
                          that contains the returned record.
2328
2329
  @retval 0      OK
2330
  @retval other  Error code
2331
*/
2332
2333
int handler::multi_range_read_next(char **range_info)
2334
{
2335
  int result= 0;
236.2.2 by rbradfor
Using correct coding standards for variable initialization
2336
  int range_res= 0;
1 by brian
clean slate
2337
2338
  if (!mrr_have_range)
2339
  {
56 by brian
Next pass of true/false update.
2340
    mrr_have_range= true;
1 by brian
clean slate
2341
    goto start;
2342
  }
2343
2344
  do
2345
  {
2346
    /* Save a call if there can be only one row in range. */
2347
    if (mrr_cur_range.range_flag != (UNIQUE_RANGE | EQ_RANGE))
2348
    {
2349
      result= read_range_next();
2350
      /* On success or non-EOF errors jump to the end. */
2351
      if (result != HA_ERR_END_OF_FILE)
2352
        break;
2353
    }
2354
    else
2355
    {
2356
      if (was_semi_consistent_read())
2357
        goto scan_it_again;
2358
      /*
2359
        We need to set this for the last range only, but checking this
2360
        condition is more expensive than just setting the result code.
2361
      */
2362
      result= HA_ERR_END_OF_FILE;
2363
    }
2364
2365
start:
2366
    /* Try the next range(s) until one matches a record. */
2367
    while (!(range_res= mrr_funcs.next(mrr_iter, &mrr_cur_range)))
2368
    {
2369
scan_it_again:
2370
      result= read_range_first(mrr_cur_range.start_key.keypart_map ?
2371
                                 &mrr_cur_range.start_key : 0,
2372
                               mrr_cur_range.end_key.keypart_map ?
2373
                                 &mrr_cur_range.end_key : 0,
2374
                               test(mrr_cur_range.range_flag & EQ_RANGE),
2375
                               mrr_is_output_sorted);
2376
      if (result != HA_ERR_END_OF_FILE)
2377
        break;
2378
    }
2379
  }
2380
  while ((result == HA_ERR_END_OF_FILE) && !range_res);
2381
2382
  *range_info= mrr_cur_range.ptr;
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
2383
  return result;
1 by brian
clean slate
2384
}
2385
2386
2387
/**
2388
  Get cost of reading nrows table records in a "disk sweep"
2389
2390
  A disk sweep read is a sequence of handler->rnd_pos(rowid) calls that made
2391
  for an ordered sequence of rowids.
2392
2393
  We assume hard disk IO. The read is performed as follows:
2394
2395
   1. The disk head is moved to the needed cylinder
2396
   2. The controller waits for the plate to rotate
2397
   3. The data is transferred
2398
2399
  Time to do #3 is insignificant compared to #2+#1.
2400
2401
  Time to move the disk head is proportional to head travel distance.
2402
2403
  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.
2404
  was moved or not.
1 by brian
clean slate
2405
2406
  If disk head wasn't moved, the wait time is proportional to distance
2407
  between the previous block and the block we're reading.
2408
2409
  If the head was moved, we don't know how much we'll need to wait for the
2410
  plate to rotate. We assume the wait time to be a variate with a mean of
2411
  0.5 of full rotation time.
2412
2413
  Our cost units are "random disk seeks". The cost of random disk seek is
2414
  actually not a constant, it depends one range of cylinders we're going
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
2415
  to access. We make it constant by introducing a fuzzy concept of "typical
1 by brian
clean slate
2416
  datafile length" (it's fuzzy as it's hard to tell whether it should
2417
  include index file, temp.tables etc). Then random seek cost is:
2418
2419
    1 = half_rotation_cost + move_cost * 1/3 * typical_data_file_length
2420
2421
  We define half_rotation_cost as DISK_SEEK_BASE_COST=0.9.
2422
2423
  @param table             Table to be accessed
2424
  @param nrows             Number of rows to retrieve
56 by brian
Next pass of true/false update.
2425
  @param interrupted       true <=> Assume that the disk sweep will be
2426
                           interrupted by other disk IO. false - otherwise.
1 by brian
clean slate
2427
  @param cost         OUT  The cost.
2428
*/
2429
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
2430
void get_sweep_read_cost(Table *table, ha_rows nrows, bool interrupted,
1 by brian
clean slate
2431
                         COST_VECT *cost)
2432
{
2433
  cost->zero();
2434
  if (table->file->primary_key_is_clustered())
2435
  {
2436
    cost->io_count= table->file->read_time(table->s->primary_key,
895 by Brian Aker
Completion (?) of uint conversion.
2437
                                           (uint32_t) nrows, nrows);
1 by brian
clean slate
2438
  }
2439
  else
2440
  {
2441
    double n_blocks=
151 by Brian Aker
Ulonglong to uint64_t
2442
      ceil(uint64_t2double(table->file->stats.data_file_length) / IO_SIZE);
1 by brian
clean slate
2443
    double busy_blocks=
2444
      n_blocks * (1.0 - pow(1.0 - 1.0/n_blocks, rows2double(nrows)));
2445
    if (busy_blocks < 1.0)
2446
      busy_blocks= 1.0;
2447
2448
    cost->io_count= busy_blocks;
2449
2450
    if (!interrupted)
2451
    {
2452
      /* Assume reading is done in one 'sweep' */
2453
      cost->avg_io_cost= (DISK_SEEK_BASE_COST +
2454
                          DISK_SEEK_PROP_COST*n_blocks/busy_blocks);
2455
    }
2456
  }
2457
}
2458
2459
2460
/* **************************************************************************
2461
 * DS-MRR implementation ends
2462
 ***************************************************************************/
2463
2464
/**
2465
  Read first row between two ranges.
2466
2467
  @param start_key		Start key. Is 0 if no min range
2468
  @param end_key		End key.  Is 0 if no max range
2469
  @param eq_range_arg	        Set to 1 if start_key == end_key
2470
  @param sorted		Set to 1 if result should be sorted per key
2471
2472
  @note
2473
    Record is read into table->record[0]
2474
2475
  @retval
2476
    0			Found row
2477
  @retval
2478
    HA_ERR_END_OF_FILE	No rows in range
2479
  @retval
2480
    \#			Error code
2481
*/
2482
int handler::read_range_first(const key_range *start_key,
2483
			      const key_range *end_key,
2484
			      bool eq_range_arg,
779.1.27 by Monty Taylor
Got rid of __attribute__((unused)) and the like from the .cc files.
2485
                              bool )
1 by brian
clean slate
2486
{
2487
  int result;
2488
2489
  eq_range= eq_range_arg;
2490
  end_range= 0;
2491
  if (end_key)
2492
  {
2493
    end_range= &save_end_range;
2494
    save_end_range= *end_key;
2495
    key_compare_result_on_equal= ((end_key->flag == HA_READ_BEFORE_KEY) ? 1 :
2496
				  (end_key->flag == HA_READ_AFTER_KEY) ? -1 : 0);
2497
  }
2498
  range_key_part= table->key_info[active_index].key_part;
2499
2500
  if (!start_key)			// Read first record
2501
    result= index_first(table->record[0]);
2502
  else
2503
    result= index_read_map(table->record[0],
2504
                           start_key->key,
2505
                           start_key->keypart_map,
2506
                           start_key->flag);
2507
  if (result)
575.2.2 by Monty Taylor
Moved vio stuff into libdrizzle.
2508
    return((result == HA_ERR_KEY_NOT_FOUND)
1 by brian
clean slate
2509
		? HA_ERR_END_OF_FILE
2510
		: result);
2511
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
2512
  return (compare_key(end_range) <= 0 ? 0 : HA_ERR_END_OF_FILE);
1 by brian
clean slate
2513
}
2514
2515
2516
/**
2517
  Read next row between two endpoints.
2518
2519
  @note
2520
    Record is read into table->record[0]
2521
2522
  @retval
2523
    0			Found row
2524
  @retval
2525
    HA_ERR_END_OF_FILE	No rows in range
2526
  @retval
2527
    \#			Error code
2528
*/
2529
int handler::read_range_next()
2530
{
2531
  int result;
2532
2533
  if (eq_range)
2534
  {
2535
    /* 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
2536
    return(index_next_same(table->record[0],
1 by brian
clean slate
2537
                                end_range->key,
2538
                                end_range->length));
2539
  }
2540
  result= index_next(table->record[0]);
2541
  if (result)
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
2542
    return result;
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
2543
  return(compare_key(end_range) <= 0 ? 0 : HA_ERR_END_OF_FILE);
1 by brian
clean slate
2544
}
2545
2546
2547
/**
2548
  Compare if found key (in row) is over max-value.
2549
2550
  @param range		range to compare to row. May be 0 for no range
2551
2552
  @seealso
2553
    key.cc::key_cmp()
2554
2555
  @return
2556
    The return value is SIGN(key_in_row - range_key):
2557
2558
    - 0   : Key is equal to range or 'range' == 0 (no range)
2559
    - -1  : Key is less than range
2560
    - 1   : Key is larger than range
2561
*/
2562
int handler::compare_key(key_range *range)
2563
{
2564
  int cmp;
2565
  if (!range || in_range_check_pushed_down)
2566
    return 0;					// No max range
2567
  cmp= key_cmp(range_key_part, range->key, range->length);
2568
  if (!cmp)
2569
    cmp= key_compare_result_on_equal;
2570
  return cmp;
2571
}
2572
2573
2574
/*
2575
  Same as compare_key() but doesn't check have in_range_check_pushed_down.
2576
  This is used by index condition pushdown implementation.
2577
*/
2578
2579
int handler::compare_key2(key_range *range)
2580
{
2581
  int cmp;
2582
  if (!range)
2583
    return 0;					// no max range
2584
  cmp= key_cmp(range_key_part, range->key, range->length);
2585
  if (!cmp)
2586
    cmp= key_compare_result_on_equal;
2587
  return cmp;
2588
}
2589
656.1.1 by Monty Taylor
OOOh doggie. Got rid of my_alloca.
2590
int handler::index_read_idx_map(unsigned char * buf, uint32_t index,
2591
                                const unsigned char * key,
1 by brian
clean slate
2592
                                key_part_map keypart_map,
2593
                                enum ha_rkey_function find_flag)
2594
{
2595
  int error, error1;
2596
  error= index_init(index, 0);
2597
  if (!error)
2598
  {
2599
    error= index_read_map(buf, key, keypart_map, find_flag);
2600
    error1= index_end();
2601
  }
2602
  return error ?  error : error1;
2603
}
2604
520.1.22 by Brian Aker
Second pass of thd cleanup
2605
static bool stat_print(Session *session, const char *type, uint32_t type_len,
482 by Brian Aker
Remove uint.
2606
                       const char *file, uint32_t file_len,
2607
                       const char *status, uint32_t status_len)
1 by brian
clean slate
2608
{
971.6.1 by Eric Day
Renamed Protocol to Client, cleaned up some unnecessary methods along the way.
2609
  session->client->store(type, type_len);
2610
  session->client->store(file, file_len);
2611
  session->client->store(status, status_len);
2612
  if (session->client->flush())
56 by brian
Next pass of true/false update.
2613
    return true;
2614
  return false;
1 by brian
clean slate
2615
}
2616
960.2.27 by Monty Taylor
Reworked transformed handlerton into class StorageEngine.
2617
bool ha_show_status(Session *session, StorageEngine *engine, enum ha_stat_type stat)
1 by brian
clean slate
2618
{
2619
  List<Item> field_list;
2620
  bool result;
2621
2622
  field_list.push_back(new Item_empty_string("Type",10));
2623
  field_list.push_back(new Item_empty_string("Name",FN_REFLEN));
2624
  field_list.push_back(new Item_empty_string("Status",10));
2625
971.6.1 by Eric Day
Renamed Protocol to Client, cleaned up some unnecessary methods along the way.
2626
  if (session->client->sendFields(&field_list))
56 by brian
Next pass of true/false update.
2627
    return true;
1 by brian
clean slate
2628
960.2.38 by Monty Taylor
Removed extraneous send myself to myself argument.
2629
  result= engine->show_status(session, stat_print, stat) ? 1 : 0;
1 by brian
clean slate
2630
2631
  if (!result)
836 by Brian Aker
Fixed session call from function to method.
2632
    session->my_eof();
1 by brian
clean slate
2633
  return result;
2634
}
2635
2636
2637
/**
2638
  Check if the conditions for row-based binlogging is correct for the table.
2639
2640
  A row in the given table should be replicated if:
2641
  - Row-based replication is enabled in the current thread
2642
  - The binlog is enabled
2643
  - It is not a temporary table
2644
  - The binary log is open
2645
  - The database the table resides in shall be binlogged (binlog_*_db rules)
2646
  - table is not mysql.event
2647
*/
2648
1039.1.16 by Brian Aker
A lot of little cleanups (most based off lcov)
2649
static bool log_row_for_replication(Table* table,
667 by Brian Aker
Partial fix (more of replication flushed out)
2650
                           const unsigned char *before_record,
2651
                           const unsigned char *after_record)
1 by brian
clean slate
2652
{
520.1.22 by Brian Aker
Second pass of thd cleanup
2653
  Session *const session= table->in_use;
1 by brian
clean slate
2654
661 by Brian Aker
First major pass through new replication.
2655
  switch (session->lex->sql_command)
2656
  {
2657
  case SQLCOM_REPLACE:
2658
  case SQLCOM_INSERT:
2659
  case SQLCOM_REPLACE_SELECT:
2660
  case SQLCOM_INSERT_SELECT:
669 by Brian Aker
Replication bits (getting CREATE..SELECT right)
2661
  case SQLCOM_CREATE_TABLE:
1039.5.31 by Jay Pipes
This patch does a few things:
2662
    replication_services.insertRecord(session, table);
661 by Brian Aker
First major pass through new replication.
2663
    break;
2664
2665
  case SQLCOM_UPDATE:
1039.5.31 by Jay Pipes
This patch does a few things:
2666
    replication_services.updateRecord(session, table, before_record, after_record);
661 by Brian Aker
First major pass through new replication.
2667
    break;
2668
2669
  case SQLCOM_DELETE:
1039.5.31 by Jay Pipes
This patch does a few things:
2670
    replication_services.deleteRecord(session, table);
661 by Brian Aker
First major pass through new replication.
2671
    break;
2672
665.1.1 by Eric Herman
more EOL whitespace fixups
2673
    /*
662 by Brian Aker
Remove dead methods.
2674
      For everything else we ignore the event (since it just involves a temp table)
2675
    */
661 by Brian Aker
First major pass through new replication.
2676
  default:
2677
    break;
1 by brian
clean slate
2678
  }
592 by Brian Aker
Remove one set.
2679
988.1.6 by Jay Pipes
Removed old protobuf_replicator plugin, fixed up db.cc and other files to use new
2680
  return false; //error;
1 by brian
clean slate
2681
}
2682
520.1.22 by Brian Aker
Second pass of thd cleanup
2683
int handler::ha_external_lock(Session *session, int lock_type)
1 by brian
clean slate
2684
{
2685
  /*
2686
    Whether this is lock or unlock, this should be true, and is to verify that
2687
    if get_auto_increment() was called (thus may have reserved intervals or
2688
    taken a table lock), ha_release_auto_increment() was too.
2689
  */
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
2690
  assert(next_insert_id == 0);
1 by brian
clean slate
2691
2692
  /*
2693
    We cache the table flags if the locking succeeded. Otherwise, we
2694
    keep them as they were when they were fetched in ha_open().
2695
  */
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
2696
  DRIZZLE_EXTERNAL_LOCK(lock_type);
1 by brian
clean slate
2697
520.1.22 by Brian Aker
Second pass of thd cleanup
2698
  int error= external_lock(session, lock_type);
1 by brian
clean slate
2699
  if (error == 0)
2700
    cached_table_flags= table_flags();
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
2701
  return error;
1 by brian
clean slate
2702
}
2703
2704
2705
/**
2706
  Check handler usage and reset state of file to after 'open'
2707
*/
2708
int handler::ha_reset()
2709
{
1005.2.3 by Monty Taylor
Further reversion of P.
2710
  /* Check that we have called all proper deallocation functions */
1103.6.4 by Padraig O'Sullivan
Correct all remaining references to the old bitmap interface in the code
2711
  assert((unsigned char*) table->def_read_set.getBitmap() +
1005.2.3 by Monty Taylor
Further reversion of P.
2712
              table->s->column_bitmap_size ==
1103.6.4 by Padraig O'Sullivan
Correct all remaining references to the old bitmap interface in the code
2713
              (unsigned char*) table->def_write_set.getBitmap());
2714
  assert(table->s->all_set.isSetAll());
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
2715
  assert(table->key_read == 0);
1 by brian
clean slate
2716
  /* ensure that ha_index_end / ha_rnd_end has been called */
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
2717
  assert(inited == NONE);
1 by brian
clean slate
2718
  /* Free cache used by filesort */
1109.1.4 by Brian Aker
More Table refactor
2719
  table->free_io_cache();
1 by brian
clean slate
2720
  /* reset the bitmaps to point to defaults */
2721
  table->default_column_bitmaps();
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
2722
  return(reset());
1 by brian
clean slate
2723
}
2724
2725
481 by Brian Aker
Remove all of uchar.
2726
int handler::ha_write_row(unsigned char *buf)
1 by brian
clean slate
2727
{
2728
  int error;
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
2729
  DRIZZLE_INSERT_ROW_START();
1 by brian
clean slate
2730
873.1.16 by Jay Pipes
This patch pulls the setting of the auto-set timestamp out of the individual
2731
  /* 
2732
   * If we have a timestamp column, update it to the current time 
2733
   * 
2734
   * @TODO Technically, the below two lines can be take even further out of the
2735
   * handler interface and into the fill_record() method.
2736
   */
2737
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
2738
    table->timestamp_field->set_time();
2739
1 by brian
clean slate
2740
  mark_trx_read_write();
2741
2742
  if (unlikely(error= write_row(buf)))
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
2743
    return error;
662 by Brian Aker
Remove dead methods.
2744
1039.1.16 by Brian Aker
A lot of little cleanups (most based off lcov)
2745
  if (unlikely(log_row_for_replication(table, 0, buf)))
662 by Brian Aker
Remove dead methods.
2746
    return HA_ERR_RBR_LOGGING_FAILED; /* purecov: inspected */
2747
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
2748
  DRIZZLE_INSERT_ROW_END();
1046.1.9 by Brian Aker
Remove caller that wasn't correctly locking, and reverted code to 5.1
2749
  return 0;
1 by brian
clean slate
2750
}
2751
2752
481 by Brian Aker
Remove all of uchar.
2753
int handler::ha_update_row(const unsigned char *old_data, unsigned char *new_data)
1 by brian
clean slate
2754
{
2755
  int error;
2756
2757
  /*
2758
    Some storage engines require that the new record is in record[0]
2759
    (and the old record is in record[1]).
2760
   */
51.1.77 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
2761
  assert(new_data == table->record[0]);
1 by brian
clean slate
2762
2763
  mark_trx_read_write();
2764
2765
  if (unlikely(error= update_row(old_data, new_data)))
2766
    return error;
662 by Brian Aker
Remove dead methods.
2767
1039.1.16 by Brian Aker
A lot of little cleanups (most based off lcov)
2768
  if (unlikely(log_row_for_replication(table, old_data, new_data)))
662 by Brian Aker
Remove dead methods.
2769
    return HA_ERR_RBR_LOGGING_FAILED;
2770
1 by brian
clean slate
2771
  return 0;
2772
}
2773
481 by Brian Aker
Remove all of uchar.
2774
int handler::ha_delete_row(const unsigned char *buf)
1 by brian
clean slate
2775
{
2776
  int error;
2777
2778
  mark_trx_read_write();
2779
2780
  if (unlikely(error= delete_row(buf)))
2781
    return error;
662 by Brian Aker
Remove dead methods.
2782
1039.1.16 by Brian Aker
A lot of little cleanups (most based off lcov)
2783
  if (unlikely(log_row_for_replication(table, buf, 0)))
662 by Brian Aker
Remove dead methods.
2784
    return HA_ERR_RBR_LOGGING_FAILED;
2785
1 by brian
clean slate
2786
  return 0;
2787
}