~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to sql/handler.cc

  • Committer: Brian Aker
  • Date: 2008-07-01 07:17:30 UTC
  • Revision ID: brian@tangent.org-20080701071730-y843dzfwz1nbca79
More mysys removal

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
/* Copyright (C) 2000-2006 MySQL AB
 
2
 
 
3
   This program is free software; you can redistribute it and/or modify
 
4
   it under the terms of the GNU General Public License as published by
 
5
   the Free Software Foundation; version 2 of the License.
 
6
 
 
7
   This program is distributed in the hope that it will be useful,
 
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
10
   GNU General Public License for more details.
 
11
 
 
12
   You should have received a copy of the GNU General Public License
 
13
   along with this program; if not, write to the Free Software
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
19
15
 
20
16
/**
21
17
  @file handler.cc
23
19
  Handler-calling-functions
24
20
*/
25
21
 
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"
35
 
#include "drizzled/transaction_services.h"
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"
41
 
#include "drizzled/message/table.pb.h"
42
 
 
43
 
using namespace std;
44
 
 
45
 
extern drizzled::TransactionServices transaction_services;
46
 
 
47
 
KEY_CREATE_INFO default_key_create_info= { HA_KEY_ALG_UNDEF, 0, {NULL,0}, {NULL,0} };
48
 
 
49
 
/* number of entries in storage_engines[] */
50
 
uint32_t total_ha= 0;
51
 
/* number of storage engines (from storage_engines[]) that support 2pc */
52
 
uint32_t total_ha_2pc= 0;
 
22
#ifdef USE_PRAGMA_IMPLEMENTATION
 
23
#pragma implementation                          // gcc: Class implementation
 
24
#endif
 
25
 
 
26
#include "mysql_priv.h"
 
27
#include "rpl_filter.h"
 
28
#include <myisampack.h>
 
29
#include <errno.h>
 
30
 
 
31
/*
 
32
  While we have legacy_db_type, we have this array to
 
33
  check for dups and to find handlerton from legacy_db_type.
 
34
  Remove when legacy_db_type is finally gone
 
35
*/
 
36
st_plugin_int *hton2plugin[MAX_HA];
 
37
 
 
38
static handlerton *installed_htons[128];
 
39
 
 
40
#define BITMAP_STACKBUF_SIZE (128/8)
 
41
 
 
42
KEY_CREATE_INFO default_key_create_info= { HA_KEY_ALG_UNDEF, 0, {NullS,0}, {NullS,0} };
 
43
 
 
44
/* number of entries in handlertons[] */
 
45
ulong total_ha= 0;
 
46
/* number of storage engines (from handlertons[]) that support 2pc */
 
47
ulong total_ha_2pc= 0;
53
48
/* size of savepoint storage area (see ha_init) */
54
 
uint32_t savepoint_alloc_size= 0;
 
49
ulong savepoint_alloc_size= 0;
 
50
 
 
51
static const LEX_STRING sys_table_aliases[]=
 
52
{
 
53
  { C_STRING_WITH_LEN("INNOBASE") },  { C_STRING_WITH_LEN("INNODB") },
 
54
  { C_STRING_WITH_LEN("HEAP") },      { C_STRING_WITH_LEN("MEMORY") },
 
55
  {NullS, 0}
 
56
};
55
57
 
56
58
const char *ha_row_type[] = {
57
59
  "", "FIXED", "DYNAMIC", "COMPRESSED", "REDUNDANT", "COMPACT", "PAGE", "?","?","?"
59
61
 
60
62
const char *tx_isolation_names[] =
61
63
{ "READ-UNCOMMITTED", "READ-COMMITTED", "REPEATABLE-READ", "SERIALIZABLE",
62
 
  NULL};
63
 
 
 
64
  NullS};
64
65
TYPELIB tx_isolation_typelib= {array_elements(tx_isolation_names)-1,"",
65
 
                               tx_isolation_names, NULL};
 
66
                               tx_isolation_names, NULL};
 
67
 
 
68
static TYPELIB known_extensions= {0,"known_exts", NULL, NULL};
 
69
uint known_extensions_id= 0;
 
70
 
 
71
 
 
72
 
 
73
static plugin_ref ha_default_plugin(THD *thd)
 
74
{
 
75
  if (thd->variables.table_plugin)
 
76
    return thd->variables.table_plugin;
 
77
  return my_plugin_lock(thd, &global_system_variables.table_plugin);
 
78
}
 
79
 
 
80
 
 
81
/**
 
82
  Return the default storage engine handlerton for thread
 
83
 
 
84
  @param ha_default_handlerton(thd)
 
85
  @param thd         current thread
 
86
 
 
87
  @return
 
88
    pointer to handlerton
 
89
*/
 
90
handlerton *ha_default_handlerton(THD *thd)
 
91
{
 
92
  plugin_ref plugin= ha_default_plugin(thd);
 
93
  DBUG_ASSERT(plugin);
 
94
  handlerton *hton= plugin_data(plugin, handlerton*);
 
95
  DBUG_ASSERT(hton);
 
96
  return hton;
 
97
}
 
98
 
 
99
 
 
100
/**
 
101
  Return the storage engine handlerton for the supplied name
 
102
  
 
103
  @param thd         current thread
 
104
  @param name        name of storage engine
 
105
  
 
106
  @return
 
107
    pointer to storage engine plugin handle
 
108
*/
 
109
plugin_ref ha_resolve_by_name(THD *thd, const LEX_STRING *name)
 
110
{
 
111
  const LEX_STRING *table_alias;
 
112
  plugin_ref plugin;
 
113
 
 
114
redo:
 
115
  /* my_strnncoll is a macro and gcc doesn't do early expansion of macro */
 
116
  if (thd && !my_charset_latin1.coll->strnncoll(&my_charset_latin1,
 
117
                           (const uchar *)name->str, name->length,
 
118
                           (const uchar *)STRING_WITH_LEN("DEFAULT"), 0))
 
119
    return ha_default_plugin(thd);
 
120
 
 
121
  if ((plugin= my_plugin_lock_by_name(thd, name, MYSQL_STORAGE_ENGINE_PLUGIN)))
 
122
  {
 
123
    handlerton *hton= plugin_data(plugin, handlerton *);
 
124
    if (!(hton->flags & HTON_NOT_USER_SELECTABLE))
 
125
      return plugin;
 
126
      
 
127
    /*
 
128
      unlocking plugin immediately after locking is relatively low cost.
 
129
    */
 
130
    plugin_unlock(thd, plugin);
 
131
  }
 
132
 
 
133
  /*
 
134
    We check for the historical aliases.
 
135
  */
 
136
  for (table_alias= sys_table_aliases; table_alias->str; table_alias+= 2)
 
137
  {
 
138
    if (!my_strnncoll(&my_charset_latin1,
 
139
                      (const uchar *)name->str, name->length,
 
140
                      (const uchar *)table_alias->str, table_alias->length))
 
141
    {
 
142
      name= table_alias + 1;
 
143
      goto redo;
 
144
    }
 
145
  }
 
146
 
 
147
  return NULL;
 
148
}
 
149
 
 
150
 
 
151
plugin_ref ha_lock_engine(THD *thd, handlerton *hton)
 
152
{
 
153
  if (hton)
 
154
  {
 
155
    st_plugin_int **plugin= hton2plugin + hton->slot;
 
156
    
 
157
#ifdef DBUG_OFF
 
158
    return my_plugin_lock(thd, plugin);
 
159
#else
 
160
    return my_plugin_lock(thd, &plugin);
 
161
#endif
 
162
  }
 
163
  return NULL;
 
164
}
 
165
 
 
166
 
 
167
handlerton *ha_resolve_by_legacy_type(THD *thd, enum legacy_db_type db_type)
 
168
{
 
169
  plugin_ref plugin;
 
170
  switch (db_type) {
 
171
  case DB_TYPE_DEFAULT:
 
172
    return ha_default_handlerton(thd);
 
173
  default:
 
174
    if (db_type > DB_TYPE_UNKNOWN && db_type < DB_TYPE_DEFAULT &&
 
175
        (plugin= ha_lock_engine(thd, installed_htons[db_type])))
 
176
      return plugin_data(plugin, handlerton*);
 
177
    /* fall through */
 
178
  case DB_TYPE_UNKNOWN:
 
179
    return NULL;
 
180
  }
 
181
}
 
182
 
 
183
 
 
184
/**
 
185
  Use other database handler if databasehandler is not compiled in.
 
186
*/
 
187
handlerton *ha_checktype(THD *thd, enum legacy_db_type database_type,
 
188
                          bool no_substitute, bool report_error)
 
189
{
 
190
  handlerton *hton= ha_resolve_by_legacy_type(thd, database_type);
 
191
  if (ha_storage_engine_is_enabled(hton))
 
192
    return hton;
 
193
 
 
194
  if (no_substitute)
 
195
  {
 
196
    if (report_error)
 
197
    {
 
198
      const char *engine_name= ha_resolve_storage_engine_name(hton);
 
199
      my_error(ER_FEATURE_DISABLED,MYF(0),engine_name,engine_name);
 
200
    }
 
201
    return NULL;
 
202
  }
 
203
 
 
204
  switch (database_type) {
 
205
  case DB_TYPE_HASH:
 
206
    return ha_resolve_by_legacy_type(thd, DB_TYPE_HASH);
 
207
  default:
 
208
    break;
 
209
  }
 
210
 
 
211
  return ha_default_handlerton(thd);
 
212
} /* ha_checktype */
 
213
 
 
214
 
 
215
handler *get_new_handler(TABLE_SHARE *share, MEM_ROOT *alloc,
 
216
                         handlerton *db_type)
 
217
{
 
218
  handler *file;
 
219
  DBUG_ENTER("get_new_handler");
 
220
  DBUG_PRINT("enter", ("alloc: 0x%lx", (long) alloc));
 
221
 
 
222
  if (db_type && db_type->state == SHOW_OPTION_YES && db_type->create)
 
223
  {
 
224
    if ((file= db_type->create(db_type, share, alloc)))
 
225
      file->init();
 
226
    DBUG_RETURN(file);
 
227
  }
 
228
  /*
 
229
    Try the default table type
 
230
    Here the call to current_thd() is ok as we call this function a lot of
 
231
    times but we enter this branch very seldom.
 
232
  */
 
233
  DBUG_RETURN(get_new_handler(share, alloc, ha_default_handlerton(current_thd)));
 
234
}
66
235
 
67
236
 
68
237
/**
81
250
 
82
251
  /* Allocate a pointer array for the error message strings. */
83
252
  /* Zerofill it to avoid uninitialized gaps. */
84
 
  if (! (errmsgs= (const char**) malloc(HA_ERR_ERRORS * sizeof(char*))))
 
253
  if (! (errmsgs= (const char**) my_malloc(HA_ERR_ERRORS * sizeof(char*),
 
254
                                           MYF(MY_WME | MY_ZEROFILL))))
85
255
    return 1;
86
 
  memset(errmsgs, 0, HA_ERR_ERRORS * sizeof(char *));
87
256
 
88
257
  /* Set the dedicated error messages. */
89
258
  SETMSG(HA_ERR_KEY_NOT_FOUND,          ER(ER_KEY_NOT_FOUND));
148
317
  /* Allocate a pointer array for the error message strings. */
149
318
  if (! (errmsgs= my_error_unregister(HA_ERR_FIRST, HA_ERR_LAST)))
150
319
    return 1;
151
 
  free((unsigned char*) errmsgs);
 
320
  my_free((uchar*) errmsgs, MYF(0));
152
321
  return 0;
153
322
}
154
323
 
 
324
 
 
325
int ha_finalize_handlerton(st_plugin_int *plugin)
 
326
{
 
327
  handlerton *hton= (handlerton *)plugin->data;
 
328
  DBUG_ENTER("ha_finalize_handlerton");
 
329
 
 
330
  switch (hton->state)
 
331
  {
 
332
  case SHOW_OPTION_NO:
 
333
  case SHOW_OPTION_DISABLED:
 
334
    break;
 
335
  case SHOW_OPTION_YES:
 
336
    if (installed_htons[hton->db_type] == hton)
 
337
      installed_htons[hton->db_type]= NULL;
 
338
    break;
 
339
  };
 
340
 
 
341
  if (hton->panic)
 
342
    hton->panic(hton, HA_PANIC_CLOSE);
 
343
 
 
344
  if (plugin->plugin->deinit)
 
345
  {
 
346
    /*
 
347
      Today we have no defined/special behavior for uninstalling
 
348
      engine plugins.
 
349
    */
 
350
    DBUG_PRINT("info", ("Deinitializing plugin: '%s'", plugin->name.str));
 
351
    if (plugin->plugin->deinit(NULL))
 
352
    {
 
353
      DBUG_PRINT("warning", ("Plugin '%s' deinit function returned error.",
 
354
                             plugin->name.str));
 
355
    }
 
356
  }
 
357
 
 
358
  my_free((uchar*)hton, MYF(0));
 
359
 
 
360
  DBUG_RETURN(0);
 
361
}
 
362
 
 
363
 
 
364
int ha_initialize_handlerton(st_plugin_int *plugin)
 
365
{
 
366
  handlerton *hton;
 
367
  DBUG_ENTER("ha_initialize_handlerton");
 
368
  DBUG_PRINT("plugin", ("initialize plugin: '%s'", plugin->name.str));
 
369
 
 
370
  hton= (handlerton *)my_malloc(sizeof(handlerton),
 
371
                                MYF(MY_WME | MY_ZEROFILL));
 
372
  /* 
 
373
    FIXME: the MY_ZEROFILL flag above doesn't zero all the bytes.
 
374
    
 
375
    This was detected after adding get_backup_engine member to handlerton
 
376
    structure. Apparently get_backup_engine was not NULL even though it was
 
377
    not initialized.
 
378
   */
 
379
  bzero(hton, sizeof(hton));
 
380
  /* Historical Requirement */
 
381
  plugin->data= hton; // shortcut for the future
 
382
  if (plugin->plugin->init)
 
383
  {
 
384
    if (plugin->plugin->init(hton))
 
385
    {
 
386
      sql_print_error("Plugin '%s' init function returned error.",
 
387
                      plugin->name.str);
 
388
      goto err;
 
389
    }
 
390
  }
 
391
 
 
392
  /*
 
393
    the switch below and hton->state should be removed when
 
394
    command-line options for plugins will be implemented
 
395
  */
 
396
  switch (hton->state) {
 
397
  case SHOW_OPTION_NO:
 
398
    break;
 
399
  case SHOW_OPTION_YES:
 
400
    {
 
401
      uint tmp;
 
402
      /* now check the db_type for conflict */
 
403
      if (hton->db_type <= DB_TYPE_UNKNOWN ||
 
404
          hton->db_type >= DB_TYPE_DEFAULT ||
 
405
          installed_htons[hton->db_type])
 
406
      {
 
407
        int idx= (int) DB_TYPE_FIRST_DYNAMIC;
 
408
 
 
409
        while (idx < (int) DB_TYPE_DEFAULT && installed_htons[idx])
 
410
          idx++;
 
411
 
 
412
        if (idx == (int) DB_TYPE_DEFAULT)
 
413
        {
 
414
          sql_print_warning("Too many storage engines!");
 
415
          DBUG_RETURN(1);
 
416
        }
 
417
        if (hton->db_type != DB_TYPE_UNKNOWN)
 
418
          sql_print_warning("Storage engine '%s' has conflicting typecode. "
 
419
                            "Assigning value %d.", plugin->plugin->name, idx);
 
420
        hton->db_type= (enum legacy_db_type) idx;
 
421
      }
 
422
      installed_htons[hton->db_type]= hton;
 
423
      tmp= hton->savepoint_offset;
 
424
      hton->savepoint_offset= savepoint_alloc_size;
 
425
      savepoint_alloc_size+= tmp;
 
426
      hton->slot= total_ha++;
 
427
      hton2plugin[hton->slot]=plugin;
 
428
      if (hton->prepare)
 
429
        total_ha_2pc++;
 
430
      break;
 
431
    }
 
432
    /* fall through */
 
433
  default:
 
434
    hton->state= SHOW_OPTION_DISABLED;
 
435
    break;
 
436
  }
 
437
  
 
438
  /* 
 
439
    This is entirely for legacy. We will create a new "disk based" hton and a 
 
440
    "memory" hton which will be configurable longterm. We should be able to 
 
441
    remove partition and myisammrg.
 
442
  */
 
443
  switch (hton->db_type) {
 
444
  case DB_TYPE_HEAP:
 
445
    heap_hton= hton;
 
446
    break;
 
447
  case DB_TYPE_MYISAM:
 
448
    myisam_hton= hton;
 
449
    break;
 
450
  default:
 
451
    break;
 
452
  };
 
453
 
 
454
  DBUG_RETURN(0);
 
455
err:
 
456
  DBUG_RETURN(1);
 
457
}
 
458
 
155
459
int ha_init()
156
460
{
157
461
  int error= 0;
 
462
  DBUG_ENTER("ha_init");
158
463
 
159
 
  assert(total_ha < MAX_HA);
 
464
  DBUG_ASSERT(total_ha < MAX_HA);
160
465
  /*
161
466
    Check if there is a transaction-capable storage engine besides the
162
467
    binary log (which is considered a transaction-capable storage engine in
163
468
    counting total_ha)
164
469
  */
 
470
  opt_using_transactions= total_ha>(ulong)opt_bin_log;
165
471
  savepoint_alloc_size+= sizeof(SAVEPOINT);
166
 
  return error;
 
472
  DBUG_RETURN(error);
167
473
}
168
474
 
169
475
int ha_end()
170
476
{
171
477
  int error= 0;
172
 
 
173
 
  /*
 
478
  DBUG_ENTER("ha_end");
 
479
 
 
480
 
 
481
  /* 
174
482
    This should be eventualy based  on the graceful shutdown flag.
175
483
    So if flag is equal to HA_PANIC_CLOSE, the deallocate
176
484
    the errors.
178
486
  if (ha_finish_errors())
179
487
    error= 1;
180
488
 
181
 
  return error;
182
 
}
183
 
 
184
 
 
 
489
  DBUG_RETURN(error);
 
490
}
 
491
 
 
492
static my_bool dropdb_handlerton(THD *unused1, plugin_ref plugin,
 
493
                                 void *path)
 
494
{
 
495
  handlerton *hton= plugin_data(plugin, handlerton *);
 
496
  if (hton->state == SHOW_OPTION_YES && hton->drop_database)
 
497
    hton->drop_database(hton, (char *)path);
 
498
  return FALSE;
 
499
}
 
500
 
 
501
 
 
502
void ha_drop_database(char* path)
 
503
{
 
504
  plugin_foreach(NULL, dropdb_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, path);
 
505
}
 
506
 
 
507
 
 
508
static my_bool closecon_handlerton(THD *thd, plugin_ref plugin,
 
509
                                   void *unused)
 
510
{
 
511
  handlerton *hton= plugin_data(plugin, handlerton *);
 
512
  /*
 
513
    there's no need to rollback here as all transactions must
 
514
    be rolled back already
 
515
  */
 
516
  if (hton->state == SHOW_OPTION_YES && hton->close_connection &&
 
517
      thd_get_ha_data(thd, hton))
 
518
    hton->close_connection(hton, thd);
 
519
  return FALSE;
 
520
}
 
521
 
 
522
 
 
523
/**
 
524
  @note
 
525
    don't bother to rollback here, it's done already
 
526
*/
 
527
void ha_close_connection(THD* thd)
 
528
{
 
529
  plugin_foreach(thd, closecon_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, 0);
 
530
}
185
531
 
186
532
/* ========================================================================
187
533
 ======================= TRANSACTIONS ===================================*/
285
631
  -----------
286
632
 
287
633
  The server stores its transaction-related data in
288
 
  session->transaction. This structure has two members of type
289
 
  Session_TRANS. These members correspond to the statement and
 
634
  thd->transaction. This structure has two members of type
 
635
  THD_TRANS. These members correspond to the statement and
290
636
  normal transactions respectively:
291
637
 
292
 
  - session->transaction.stmt contains a list of engines
 
638
  - thd->transaction.stmt contains a list of engines
293
639
  that are participating in the given statement
294
 
  - session->transaction.all contains a list of engines that
 
640
  - thd->transaction.all contains a list of engines that
295
641
  have participated in any of the statement transactions started
296
642
  within the context of the normal transaction.
297
643
  Each element of the list contains a pointer to the storage
298
644
  engine, engine-specific transactional data, and engine-specific
299
645
  transaction flags.
300
646
 
301
 
  In autocommit mode session->transaction.all is empty.
302
 
  Instead, data of session->transaction.stmt is
 
647
  In autocommit mode thd->transaction.all is empty.
 
648
  Instead, data of thd->transaction.stmt is
303
649
  used to commit/rollback the normal transaction.
304
650
 
305
651
  The list of registered engines has a few important properties:
310
656
  Transaction life cycle
311
657
  ----------------------
312
658
 
313
 
  When a new connection is established, session->transaction
 
659
  When a new connection is established, thd->transaction
314
660
  members are initialized to an empty state.
315
661
  If a statement uses any tables, all affected engines
316
662
  are registered in the statement engine list. In
326
672
  and emptied again at the next statement's end.
327
673
 
328
674
  The normal transaction is committed in a similar way
329
 
  (by going over all engines in session->transaction.all list)
 
675
  (by going over all engines in thd->transaction.all list)
330
676
  but at different times:
331
677
  - upon COMMIT SQL statement is issued by the user
332
678
  - implicitly, by the server, at the beginning of a DDL statement
336
682
  - if the user has requested so, by issuing ROLLBACK SQL
337
683
  statement
338
684
  - if one of the storage engines requested a rollback
339
 
  by setting session->transaction_rollback_request. This may
 
685
  by setting thd->transaction_rollback_request. This may
340
686
  happen in case, e.g., when the transaction in the engine was
341
687
  chosen a victim of the internal deadlock resolution algorithm
342
688
  and rolled back internally. When such a situation happens, there
356
702
  The remaining rare cases when the server explicitly has
357
703
  to commit the statement transaction prior to committing the normal
358
704
  one cover error-handling scenarios (see for example
359
 
  ?).
 
705
  SQLCOM_LOCK_TABLES).
360
706
 
361
707
  When committing a statement or a normal transaction, the server
362
708
  either uses the two-phase commit protocol, or issues a commit
363
709
  in each engine independently. The two-phase commit protocol
364
710
  is used only if:
365
711
  - all participating engines support two-phase commit (provide
366
 
    StorageEngine::prepare PSEA API call) and
 
712
    handlerton::prepare PSEA API call) and
367
713
  - transactions in at least two engines modify data (i.e. are
368
714
  not read-only).
369
715
 
378
724
  transactions of other participants.
379
725
 
380
726
  After the normal transaction has been committed,
381
 
  session->transaction.all list is cleared.
 
727
  thd->transaction.all list is cleared.
382
728
 
383
729
  When a connection is closed, the current normal transaction, if
384
730
  any, is rolled back.
427
773
 
428
774
  At the end of a statement, server call
429
775
  ha_autocommit_or_rollback() is invoked. This call in turn
430
 
  invokes StorageEngine::prepare() for every involved engine.
431
 
  Prepare is followed by a call to StorageEngine::commit_one_phase()
432
 
  If a one-phase commit will suffice, StorageEngine::prepare() is not
433
 
  invoked and the server only calls StorageEngine::commit_one_phase().
 
776
  invokes handlerton::prepare() for every involved engine.
 
777
  Prepare is followed by a call to handlerton::commit_one_phase()
 
778
  If a one-phase commit will suffice, handlerton::prepare() is not
 
779
  invoked and the server only calls handlerton::commit_one_phase().
434
780
  At statement commit, the statement-related read-write engine
435
781
  flag is propagated to the corresponding flag in the normal
436
782
  transaction.  When the commit is complete, the list of registered
442
788
  ---------------------------------------------------
443
789
 
444
790
  DDLs and operations with non-transactional engines
445
 
  do not "register" in session->transaction lists, and thus do not
 
791
  do not "register" in thd->transaction lists, and thus do not
446
792
  modify the transaction state. Besides, each DDL in
447
793
  MySQL is prefixed with an implicit normal transaction commit
448
 
  (a call to Session::endActiveTransaction()), and thus leaves nothing
 
794
  (a call to end_active_trans()), and thus leaves nothing
449
795
  to modify.
450
796
  However, as it has been pointed out with CREATE TABLE .. SELECT,
451
797
  some DDL statements can start a *new* transaction.
456
802
  to maintain atomicity: if CREATE TABLE .. SELECT failed,
457
803
  the newly created table is deleted.
458
804
  In addition, some DDL statements issue interim transaction
459
 
  commits: e.g. ALTER Table issues a commit after data is copied
 
805
  commits: e.g. ALTER TABLE issues a commit after data is copied
460
806
  from the original table to the internal temporary table. Other
461
807
  statements, e.g. CREATE TABLE ... SELECT do not always commit
462
808
  after itself.
463
809
  And finally there is a group of DDL statements such as
464
 
  RENAME/DROP Table that doesn't start a new transaction
 
810
  RENAME/DROP TABLE that doesn't start a new transaction
465
811
  and doesn't commit.
466
812
 
467
813
  This diversity makes it hard to say what will happen if
489
835
    times per transaction.
490
836
 
491
837
*/
492
 
void trans_register_ha(Session *session, bool all, StorageEngine *engine)
 
838
void trans_register_ha(THD *thd, bool all, handlerton *ht_arg)
493
839
{
494
 
  Session_TRANS *trans;
 
840
  THD_TRANS *trans;
495
841
  Ha_trx_info *ha_info;
 
842
  DBUG_ENTER("trans_register_ha");
 
843
  DBUG_PRINT("enter",("%s", all ? "all" : "stmt"));
496
844
 
497
845
  if (all)
498
846
  {
499
 
    trans= &session->transaction.all;
500
 
    session->server_status|= SERVER_STATUS_IN_TRANS;
 
847
    trans= &thd->transaction.all;
 
848
    thd->server_status|= SERVER_STATUS_IN_TRANS;
501
849
  }
502
850
  else
503
 
    trans= &session->transaction.stmt;
 
851
    trans= &thd->transaction.stmt;
504
852
 
505
 
  ha_info= session->ha_data[engine->getSlot()].ha_info + static_cast<unsigned>(all);
 
853
  ha_info= thd->ha_data[ht_arg->slot].ha_info + static_cast<unsigned>(all);
506
854
 
507
855
  if (ha_info->is_started())
508
 
    return; /* already registered, return */
509
 
 
510
 
  ha_info->register_ha(trans, engine);
511
 
 
512
 
  trans->no_2pc|= not engine->has_2pc();
513
 
  if (session->transaction.xid_state.xid.is_null())
514
 
    session->transaction.xid_state.xid.set(session->query_id);
 
856
    DBUG_VOID_RETURN; /* already registered, return */
 
857
 
 
858
  ha_info->register_ha(trans, ht_arg);
 
859
 
 
860
  trans->no_2pc|=(ht_arg->prepare==0);
 
861
  if (thd->transaction.xid_state.xid.is_null())
 
862
    thd->transaction.xid_state.xid.set(thd->query_id);
 
863
 
 
864
  DBUG_VOID_RETURN;
 
865
}
 
866
 
 
867
/**
 
868
  @retval
 
869
    0   ok
 
870
  @retval
 
871
    1   error, transaction was rolled back
 
872
*/
 
873
int ha_prepare(THD *thd)
 
874
{
 
875
  int error=0, all=1;
 
876
  THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt;
 
877
  Ha_trx_info *ha_info= trans->ha_list;
 
878
  DBUG_ENTER("ha_prepare");
 
879
  if (ha_info)
 
880
  {
 
881
    for (; ha_info; ha_info= ha_info->next())
 
882
    {
 
883
      int err;
 
884
      handlerton *ht= ha_info->ht();
 
885
      status_var_increment(thd->status_var.ha_prepare_count);
 
886
      if (ht->prepare)
 
887
      {
 
888
        if ((err= ht->prepare(ht, thd, all)))
 
889
        {
 
890
          my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
 
891
          ha_rollback_trans(thd, all);
 
892
          error=1;
 
893
          break;
 
894
        }
 
895
      }
 
896
      else
 
897
      {
 
898
        push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
 
899
                            ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
 
900
                            ha_resolve_storage_engine_name(ht));
 
901
      }
 
902
    }
 
903
  }
 
904
  DBUG_RETURN(error);
515
905
}
516
906
 
517
907
/**
521
911
  As a side effect, propagates the read-only/read-write flags
522
912
  of the statement transaction to its enclosing normal transaction.
523
913
 
524
 
  @retval true   we must run a two-phase commit. Returned
 
914
  @retval TRUE   we must run a two-phase commit. Returned
525
915
                 if we have at least two engines with read-write changes.
526
 
  @retval false  Don't need two-phase commit. Even if we have two
 
916
  @retval FALSE  Don't need two-phase commit. Even if we have two
527
917
                 transactional engines, we can run two independent
528
918
                 commits if changes in one of the engines are read-only.
529
919
*/
530
920
 
531
921
static
532
922
bool
533
 
ha_check_and_coalesce_trx_read_only(Session *session, Ha_trx_info *ha_list,
 
923
ha_check_and_coalesce_trx_read_only(THD *thd, Ha_trx_info *ha_list,
534
924
                                    bool all)
535
925
{
536
926
  /* The number of storage engines that have actual changes. */
544
934
 
545
935
    if (! all)
546
936
    {
547
 
      Ha_trx_info *ha_info_all= &session->ha_data[ha_info->engine()->getSlot()].ha_info[1];
548
 
      assert(ha_info != ha_info_all);
 
937
      Ha_trx_info *ha_info_all= &thd->ha_data[ha_info->ht()->slot].ha_info[1];
 
938
      DBUG_ASSERT(ha_info != ha_info_all);
549
939
      /*
550
940
        Merge read-only/read-write information about statement
551
941
        transaction to its enclosing normal transaction. Do this
552
942
        only if in a real transaction -- that is, if we know
553
 
        that ha_info_all is registered in session->transaction.all.
 
943
        that ha_info_all is registered in thd->transaction.all.
554
944
        Since otherwise we only clutter the normal transaction flags.
555
945
      */
556
 
      if (ha_info_all->is_started()) /* false if autocommit. */
 
946
      if (ha_info_all->is_started()) /* FALSE if autocommit. */
557
947
        ha_info_all->coalesce_trx_with(ha_info);
558
948
    }
559
949
    else if (rw_ha_count > 1)
584
974
    stored functions or triggers. So we simply do nothing now.
585
975
    TODO: This should be fixed in later ( >= 5.1) releases.
586
976
*/
587
 
int ha_commit_trans(Session *session, bool all)
 
977
int ha_commit_trans(THD *thd, bool all)
588
978
{
589
979
  int error= 0, cookie= 0;
590
980
  /*
591
981
    'all' means that this is either an explicit commit issued by
592
982
    user, or an implicit commit issued by a DDL.
593
983
  */
594
 
  Session_TRANS *trans= all ? &session->transaction.all : &session->transaction.stmt;
595
 
  bool is_real_trans= all || session->transaction.all.ha_list == 0;
 
984
  THD_TRANS *trans= all ? &thd->transaction.all : &thd->transaction.stmt;
 
985
  bool is_real_trans= all || thd->transaction.all.ha_list == 0;
596
986
  Ha_trx_info *ha_info= trans->ha_list;
 
987
  my_xid xid= thd->transaction.xid_state.xid.get_my_xid();
 
988
  DBUG_ENTER("ha_commit_trans");
597
989
 
598
990
  /*
599
991
    We must not commit the normal transaction if a statement
601
993
    flags will not get propagated to its normal transaction's
602
994
    counterpart.
603
995
  */
604
 
  assert(session->transaction.stmt.ha_list == NULL ||
605
 
              trans == &session->transaction.stmt);
 
996
  DBUG_ASSERT(thd->transaction.stmt.ha_list == NULL ||
 
997
              trans == &thd->transaction.stmt);
606
998
 
 
999
  if (thd->in_sub_stmt)
 
1000
  {
 
1001
    /*
 
1002
      Since we don't support nested statement transactions in 5.0,
 
1003
      we can't commit or rollback stmt transactions while we are inside
 
1004
      stored functions or triggers. So we simply do nothing now.
 
1005
      TODO: This should be fixed in later ( >= 5.1) releases.
 
1006
    */
 
1007
    if (!all)
 
1008
      DBUG_RETURN(0);
 
1009
    /*
 
1010
      We assume that all statements which commit or rollback main transaction
 
1011
      are prohibited inside of stored functions or triggers. So they should
 
1012
      bail out with error even before ha_commit_trans() call. To be 100% safe
 
1013
      let us throw error in non-debug builds.
 
1014
    */
 
1015
    DBUG_ASSERT(0);
 
1016
    my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
 
1017
    DBUG_RETURN(2);
 
1018
  }
607
1019
  if (ha_info)
608
1020
  {
609
1021
    bool must_2pc;
610
1022
 
611
 
    if (is_real_trans && wait_if_global_read_lock(session, 0, 0))
612
 
    {
613
 
      ha_rollback_trans(session, all);
614
 
      return 1;
615
 
    }
616
 
 
617
 
    must_2pc= ha_check_and_coalesce_trx_read_only(session, ha_info, all);
 
1023
    if (is_real_trans && wait_if_global_read_lock(thd, 0, 0))
 
1024
    {
 
1025
      ha_rollback_trans(thd, all);
 
1026
      DBUG_RETURN(1);
 
1027
    }
 
1028
 
 
1029
    if (   is_real_trans
 
1030
        && opt_readonly
 
1031
        && ! thd->slave_thread
 
1032
       )
 
1033
    {
 
1034
      my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only");
 
1035
      ha_rollback_trans(thd, all);
 
1036
      error= 1;
 
1037
      goto end;
 
1038
    }
 
1039
 
 
1040
    must_2pc= ha_check_and_coalesce_trx_read_only(thd, ha_info, all);
618
1041
 
619
1042
    if (!trans->no_2pc && must_2pc)
620
1043
    {
621
1044
      for (; ha_info && !error; ha_info= ha_info->next())
622
1045
      {
623
1046
        int err;
624
 
        StorageEngine *engine= ha_info->engine();
 
1047
        handlerton *ht= ha_info->ht();
625
1048
        /*
626
1049
          Do not call two-phase commit if this particular
627
1050
          transaction is read-only. This allows for simpler
633
1056
          Sic: we know that prepare() is not NULL since otherwise
634
1057
          trans->no_2pc would have been set.
635
1058
        */
636
 
        if ((err= engine->prepare(session, all)))
 
1059
        if ((err= ht->prepare(ht, thd, all)))
637
1060
        {
638
1061
          my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
639
1062
          error= 1;
640
1063
        }
641
 
        status_var_increment(session->status_var.ha_prepare_count);
 
1064
        status_var_increment(thd->status_var.ha_prepare_count);
642
1065
      }
643
 
      if (error)
 
1066
      DBUG_EXECUTE_IF("crash_commit_after_prepare", abort(););
 
1067
      if (error || (is_real_trans && xid &&
 
1068
                    (error= !(cookie= tc_log->log_xid(thd, xid)))))
644
1069
      {
645
 
        ha_rollback_trans(session, all);
 
1070
        ha_rollback_trans(thd, all);
646
1071
        error= 1;
647
1072
        goto end;
648
1073
      }
 
1074
      DBUG_EXECUTE_IF("crash_commit_after_log", abort(););
649
1075
    }
650
 
    error=ha_commit_one_phase(session, all) ? (cookie ? 2 : 1) : 0;
 
1076
    error=ha_commit_one_phase(thd, all) ? (cookie ? 2 : 1) : 0;
 
1077
    DBUG_EXECUTE_IF("crash_commit_before_unlog", abort(););
 
1078
    if (cookie)
 
1079
      tc_log->unlog(cookie, xid);
 
1080
    DBUG_EXECUTE_IF("crash_commit_after", abort(););
651
1081
end:
652
1082
    if (is_real_trans)
653
 
      start_waiting_global_read_lock(session);
 
1083
      start_waiting_global_read_lock(thd);
654
1084
  }
655
 
  return error;
 
1085
  DBUG_RETURN(error);
656
1086
}
657
1087
 
658
1088
/**
659
1089
  @note
660
1090
  This function does not care about global read lock. A caller should.
661
1091
*/
662
 
int ha_commit_one_phase(Session *session, bool all)
 
1092
int ha_commit_one_phase(THD *thd, bool all)
663
1093
{
664
1094
  int error=0;
665
 
  Session_TRANS *trans=all ? &session->transaction.all : &session->transaction.stmt;
666
 
  bool is_real_trans=all || session->transaction.all.ha_list == 0;
 
1095
  THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt;
 
1096
  bool is_real_trans=all || thd->transaction.all.ha_list == 0;
667
1097
  Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
 
1098
  DBUG_ENTER("ha_commit_one_phase");
668
1099
  if (ha_info)
669
1100
  {
670
1101
    for (; ha_info; ha_info= ha_info_next)
671
1102
    {
672
1103
      int err;
673
 
      StorageEngine *engine= ha_info->engine();
674
 
      if ((err= engine->commit(session, all)))
 
1104
      handlerton *ht= ha_info->ht();
 
1105
      if ((err= ht->commit(ht, thd, all)))
675
1106
      {
676
1107
        my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
677
1108
        error=1;
678
1109
      }
679
 
      status_var_increment(session->status_var.ha_commit_count);
 
1110
      status_var_increment(thd->status_var.ha_commit_count);
680
1111
      ha_info_next= ha_info->next();
681
1112
      ha_info->reset(); /* keep it conveniently zero-filled */
682
1113
    }
683
1114
    trans->ha_list= 0;
684
1115
    trans->no_2pc=0;
685
1116
    if (is_real_trans)
686
 
      session->transaction.xid_state.xid.null();
 
1117
      thd->transaction.xid_state.xid.null();
687
1118
    if (all)
688
1119
    {
689
 
      session->variables.tx_isolation=session->session_tx_isolation;
690
 
      session->transaction.cleanup();
 
1120
      thd->variables.tx_isolation=thd->session_tx_isolation;
 
1121
      thd->transaction.cleanup();
691
1122
    }
692
1123
  }
693
 
  return error;
 
1124
  DBUG_RETURN(error);
694
1125
}
695
1126
 
696
1127
 
697
 
int ha_rollback_trans(Session *session, bool all)
 
1128
int ha_rollback_trans(THD *thd, bool all)
698
1129
{
699
1130
  int error=0;
700
 
  Session_TRANS *trans=all ? &session->transaction.all : &session->transaction.stmt;
 
1131
  THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt;
701
1132
  Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
702
 
  bool is_real_trans=all || session->transaction.all.ha_list == 0;
 
1133
  bool is_real_trans=all || thd->transaction.all.ha_list == 0;
 
1134
  DBUG_ENTER("ha_rollback_trans");
703
1135
 
704
1136
  /*
705
1137
    We must not rollback the normal transaction if a statement
706
1138
    transaction is pending.
707
1139
  */
708
 
  assert(session->transaction.stmt.ha_list == NULL ||
709
 
              trans == &session->transaction.stmt);
 
1140
  DBUG_ASSERT(thd->transaction.stmt.ha_list == NULL ||
 
1141
              trans == &thd->transaction.stmt);
710
1142
 
 
1143
  if (thd->in_sub_stmt)
 
1144
  {
 
1145
    /*
 
1146
      If we are inside stored function or trigger we should not commit or
 
1147
      rollback current statement transaction. See comment in ha_commit_trans()
 
1148
      call for more information.
 
1149
    */
 
1150
    if (!all)
 
1151
      DBUG_RETURN(0);
 
1152
    DBUG_ASSERT(0);
 
1153
    my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
 
1154
    DBUG_RETURN(1);
 
1155
  }
711
1156
  if (ha_info)
712
1157
  {
713
1158
    for (; ha_info; ha_info= ha_info_next)
714
1159
    {
715
1160
      int err;
716
 
      StorageEngine *engine= ha_info->engine();
717
 
      if ((err= engine->rollback(session, all)))
 
1161
      handlerton *ht= ha_info->ht();
 
1162
      if ((err= ht->rollback(ht, thd, all)))
718
1163
      { // cannot happen
719
1164
        my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
720
1165
        error=1;
721
1166
      }
722
 
      status_var_increment(session->status_var.ha_rollback_count);
 
1167
      status_var_increment(thd->status_var.ha_rollback_count);
723
1168
      ha_info_next= ha_info->next();
724
1169
      ha_info->reset(); /* keep it conveniently zero-filled */
725
1170
    }
726
1171
    trans->ha_list= 0;
727
1172
    trans->no_2pc=0;
728
1173
    if (is_real_trans)
729
 
      session->transaction.xid_state.xid.null();
 
1174
      thd->transaction.xid_state.xid.null();
730
1175
    if (all)
731
1176
    {
732
 
      session->variables.tx_isolation=session->session_tx_isolation;
733
 
      session->transaction.cleanup();
 
1177
      thd->variables.tx_isolation=thd->session_tx_isolation;
 
1178
      thd->transaction.cleanup();
734
1179
    }
735
1180
  }
736
1181
  if (all)
737
 
    session->transaction_rollback_request= false;
 
1182
    thd->transaction_rollback_request= FALSE;
738
1183
 
739
1184
  /*
740
1185
    If a non-transactional table was updated, warn; don't warn if this is a
745
1190
    the error log; but we don't want users to wonder why they have this
746
1191
    message in the error log, so we don't send it.
747
1192
  */
748
 
  if (is_real_trans && session->transaction.all.modified_non_trans_table && session->killed != Session::KILL_CONNECTION)
749
 
    push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
1193
  if (is_real_trans && thd->transaction.all.modified_non_trans_table &&
 
1194
      !thd->slave_thread && thd->killed != THD::KILL_CONNECTION)
 
1195
    push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
750
1196
                 ER_WARNING_NOT_COMPLETE_ROLLBACK,
751
1197
                 ER(ER_WARNING_NOT_COMPLETE_ROLLBACK));
752
 
  return error;
 
1198
  DBUG_RETURN(error);
753
1199
}
754
1200
 
755
1201
/**
763
1209
    the user has used LOCK TABLES then that mechanism does not know to do the
764
1210
    commit.
765
1211
*/
766
 
int ha_autocommit_or_rollback(Session *session, int error)
 
1212
int ha_autocommit_or_rollback(THD *thd, int error)
767
1213
{
768
 
  if (session->transaction.stmt.ha_list)
 
1214
  DBUG_ENTER("ha_autocommit_or_rollback");
 
1215
  if (thd->transaction.stmt.ha_list)
769
1216
  {
770
1217
    if (!error)
771
1218
    {
772
 
      if (ha_commit_trans(session, 0))
773
 
        error= 1;
 
1219
      if (ha_commit_trans(thd, 0))
 
1220
        error=1;
 
1221
    }
 
1222
    else 
 
1223
    {
 
1224
      (void) ha_rollback_trans(thd, 0);
 
1225
      if (thd->transaction_rollback_request && !thd->in_sub_stmt)
 
1226
        (void) ha_rollback(thd);
 
1227
    }
 
1228
 
 
1229
    thd->variables.tx_isolation=thd->session_tx_isolation;
 
1230
  }
 
1231
  DBUG_RETURN(error);
 
1232
}
 
1233
 
 
1234
 
 
1235
struct xahton_st {
 
1236
  XID *xid;
 
1237
  int result;
 
1238
};
 
1239
 
 
1240
static my_bool xacommit_handlerton(THD *unused1, plugin_ref plugin,
 
1241
                                   void *arg)
 
1242
{
 
1243
  handlerton *hton= plugin_data(plugin, handlerton *);
 
1244
  if (hton->state == SHOW_OPTION_YES && hton->recover)
 
1245
  {
 
1246
    hton->commit_by_xid(hton, ((struct xahton_st *)arg)->xid);
 
1247
    ((struct xahton_st *)arg)->result= 0;
 
1248
  }
 
1249
  return FALSE;
 
1250
}
 
1251
 
 
1252
static my_bool xarollback_handlerton(THD *unused1, plugin_ref plugin,
 
1253
                                     void *arg)
 
1254
{
 
1255
  handlerton *hton= plugin_data(plugin, handlerton *);
 
1256
  if (hton->state == SHOW_OPTION_YES && hton->recover)
 
1257
  {
 
1258
    hton->rollback_by_xid(hton, ((struct xahton_st *)arg)->xid);
 
1259
    ((struct xahton_st *)arg)->result= 0;
 
1260
  }
 
1261
  return FALSE;
 
1262
}
 
1263
 
 
1264
 
 
1265
int ha_commit_or_rollback_by_xid(XID *xid, bool commit)
 
1266
{
 
1267
  struct xahton_st xaop;
 
1268
  xaop.xid= xid;
 
1269
  xaop.result= 1;
 
1270
 
 
1271
  plugin_foreach(NULL, commit ? xacommit_handlerton : xarollback_handlerton,
 
1272
                 MYSQL_STORAGE_ENGINE_PLUGIN, &xaop);
 
1273
 
 
1274
  return xaop.result;
 
1275
}
 
1276
 
 
1277
 
 
1278
#ifndef DBUG_OFF
 
1279
/**
 
1280
  @note
 
1281
    This does not need to be multi-byte safe or anything
 
1282
*/
 
1283
static char* xid_to_str(char *buf, XID *xid)
 
1284
{
 
1285
  int i;
 
1286
  char *s=buf;
 
1287
  *s++='\'';
 
1288
  for (i=0; i < xid->gtrid_length+xid->bqual_length; i++)
 
1289
  {
 
1290
    uchar c=(uchar)xid->data[i];
 
1291
    /* is_next_dig is set if next character is a number */
 
1292
    bool is_next_dig= FALSE;
 
1293
    if (i < XIDDATASIZE)
 
1294
    {
 
1295
      char ch= xid->data[i+1];
 
1296
      is_next_dig= (ch >= '0' && ch <='9');
 
1297
    }
 
1298
    if (i == xid->gtrid_length)
 
1299
    {
 
1300
      *s++='\'';
 
1301
      if (xid->bqual_length)
 
1302
      {
 
1303
        *s++='.';
 
1304
        *s++='\'';
 
1305
      }
 
1306
    }
 
1307
    if (c < 32 || c > 126)
 
1308
    {
 
1309
      *s++='\\';
 
1310
      /*
 
1311
        If next character is a number, write current character with
 
1312
        3 octal numbers to ensure that the next number is not seen
 
1313
        as part of the octal number
 
1314
      */
 
1315
      if (c > 077 || is_next_dig)
 
1316
        *s++=_dig_vec_lower[c >> 6];
 
1317
      if (c > 007 || is_next_dig)
 
1318
        *s++=_dig_vec_lower[(c >> 3) & 7];
 
1319
      *s++=_dig_vec_lower[c & 7];
774
1320
    }
775
1321
    else
776
1322
    {
777
 
      (void) ha_rollback_trans(session, 0);
778
 
      if (session->transaction_rollback_request)
779
 
        (void) ha_rollback(session);
780
 
    }
781
 
 
782
 
    session->variables.tx_isolation=session->session_tx_isolation;
783
 
  }
784
 
 
785
 
  return error;
786
 
}
787
 
 
788
 
 
789
 
 
 
1323
      if (c == '\'' || c == '\\')
 
1324
        *s++='\\';
 
1325
      *s++=c;
 
1326
    }
 
1327
  }
 
1328
  *s++='\'';
 
1329
  *s=0;
 
1330
  return buf;
 
1331
}
 
1332
#endif
 
1333
 
 
1334
/**
 
1335
  recover() step of xa.
 
1336
 
 
1337
  @note
 
1338
    there are three modes of operation:
 
1339
    - automatic recover after a crash
 
1340
    in this case commit_list != 0, tc_heuristic_recover==0
 
1341
    all xids from commit_list are committed, others are rolled back
 
1342
    - manual (heuristic) recover
 
1343
    in this case commit_list==0, tc_heuristic_recover != 0
 
1344
    DBA has explicitly specified that all prepared transactions should
 
1345
    be committed (or rolled back).
 
1346
    - no recovery (MySQL did not detect a crash)
 
1347
    in this case commit_list==0, tc_heuristic_recover == 0
 
1348
    there should be no prepared transactions in this case.
 
1349
*/
 
1350
struct xarecover_st
 
1351
{
 
1352
  int len, found_foreign_xids, found_my_xids;
 
1353
  XID *list;
 
1354
  HASH *commit_list;
 
1355
  bool dry_run;
 
1356
};
 
1357
 
 
1358
static my_bool xarecover_handlerton(THD *unused, plugin_ref plugin,
 
1359
                                    void *arg)
 
1360
{
 
1361
  handlerton *hton= plugin_data(plugin, handlerton *);
 
1362
  struct xarecover_st *info= (struct xarecover_st *) arg;
 
1363
  int got;
 
1364
 
 
1365
  if (hton->state == SHOW_OPTION_YES && hton->recover)
 
1366
  {
 
1367
    while ((got= hton->recover(hton, info->list, info->len)) > 0 )
 
1368
    {
 
1369
      sql_print_information("Found %d prepared transaction(s) in %s",
 
1370
                            got, ha_resolve_storage_engine_name(hton));
 
1371
      for (int i=0; i < got; i ++)
 
1372
      {
 
1373
        my_xid x=info->list[i].get_my_xid();
 
1374
        if (!x) // not "mine" - that is generated by external TM
 
1375
        {
 
1376
#ifndef DBUG_OFF
 
1377
          char buf[XIDDATASIZE*4+6]; // see xid_to_str
 
1378
          sql_print_information("ignore xid %s", xid_to_str(buf, info->list+i));
 
1379
#endif
 
1380
          xid_cache_insert(info->list+i, XA_PREPARED);
 
1381
          info->found_foreign_xids++;
 
1382
          continue;
 
1383
        }
 
1384
        if (info->dry_run)
 
1385
        {
 
1386
          info->found_my_xids++;
 
1387
          continue;
 
1388
        }
 
1389
        // recovery mode
 
1390
        if (info->commit_list ?
 
1391
            hash_search(info->commit_list, (uchar *)&x, sizeof(x)) != 0 :
 
1392
            tc_heuristic_recover == TC_HEURISTIC_RECOVER_COMMIT)
 
1393
        {
 
1394
#ifndef DBUG_OFF
 
1395
          char buf[XIDDATASIZE*4+6]; // see xid_to_str
 
1396
          sql_print_information("commit xid %s", xid_to_str(buf, info->list+i));
 
1397
#endif
 
1398
          hton->commit_by_xid(hton, info->list+i);
 
1399
        }
 
1400
        else
 
1401
        {
 
1402
#ifndef DBUG_OFF
 
1403
          char buf[XIDDATASIZE*4+6]; // see xid_to_str
 
1404
          sql_print_information("rollback xid %s",
 
1405
                                xid_to_str(buf, info->list+i));
 
1406
#endif
 
1407
          hton->rollback_by_xid(hton, info->list+i);
 
1408
        }
 
1409
      }
 
1410
      if (got < info->len)
 
1411
        break;
 
1412
    }
 
1413
  }
 
1414
  return FALSE;
 
1415
}
 
1416
 
 
1417
int ha_recover(HASH *commit_list)
 
1418
{
 
1419
  struct xarecover_st info;
 
1420
  DBUG_ENTER("ha_recover");
 
1421
  info.found_foreign_xids= info.found_my_xids= 0;
 
1422
  info.commit_list= commit_list;
 
1423
  info.dry_run= (info.commit_list==0 && tc_heuristic_recover==0);
 
1424
  info.list= NULL;
 
1425
 
 
1426
  /* commit_list and tc_heuristic_recover cannot be set both */
 
1427
  DBUG_ASSERT(info.commit_list==0 || tc_heuristic_recover==0);
 
1428
  /* if either is set, total_ha_2pc must be set too */
 
1429
  DBUG_ASSERT(info.dry_run || total_ha_2pc>(ulong)opt_bin_log);
 
1430
 
 
1431
  if (total_ha_2pc <= (ulong)opt_bin_log)
 
1432
    DBUG_RETURN(0);
 
1433
 
 
1434
  if (info.commit_list)
 
1435
    sql_print_information("Starting crash recovery...");
 
1436
 
 
1437
 
 
1438
#ifndef WILL_BE_DELETED_LATER
 
1439
 
 
1440
  /*
 
1441
    for now, only InnoDB supports 2pc. It means we can always safely
 
1442
    rollback all pending transactions, without risking inconsistent data
 
1443
  */
 
1444
 
 
1445
  DBUG_ASSERT(total_ha_2pc == (ulong) opt_bin_log+1); // only InnoDB and binlog
 
1446
  tc_heuristic_recover= TC_HEURISTIC_RECOVER_ROLLBACK; // forcing ROLLBACK
 
1447
  info.dry_run=FALSE;
 
1448
#endif
 
1449
 
 
1450
 
 
1451
  for (info.len= MAX_XID_LIST_SIZE ; 
 
1452
       info.list==0 && info.len > MIN_XID_LIST_SIZE; info.len/=2)
 
1453
  {
 
1454
    info.list=(XID *)my_malloc(info.len*sizeof(XID), MYF(0));
 
1455
  }
 
1456
  if (!info.list)
 
1457
  {
 
1458
    sql_print_error(ER(ER_OUTOFMEMORY), info.len*sizeof(XID));
 
1459
    DBUG_RETURN(1);
 
1460
  }
 
1461
 
 
1462
  plugin_foreach(NULL, xarecover_handlerton, 
 
1463
                 MYSQL_STORAGE_ENGINE_PLUGIN, &info);
 
1464
 
 
1465
  my_free((uchar*)info.list, MYF(0));
 
1466
  if (info.found_foreign_xids)
 
1467
    sql_print_warning("Found %d prepared XA transactions", 
 
1468
                      info.found_foreign_xids);
 
1469
  if (info.dry_run && info.found_my_xids)
 
1470
  {
 
1471
    sql_print_error("Found %d prepared transactions! It means that mysqld was "
 
1472
                    "not shut down properly last time and critical recovery "
 
1473
                    "information (last binlog or %s file) was manually deleted "
 
1474
                    "after a crash. You have to start mysqld with "
 
1475
                    "--tc-heuristic-recover switch to commit or rollback "
 
1476
                    "pending transactions.",
 
1477
                    info.found_my_xids, opt_tc_log_file);
 
1478
    DBUG_RETURN(1);
 
1479
  }
 
1480
  if (info.commit_list)
 
1481
    sql_print_information("Crash recovery finished.");
 
1482
  DBUG_RETURN(0);
 
1483
}
790
1484
 
791
1485
/**
792
1486
  return the list of XID's to a client, the same way SHOW commands do.
796
1490
    so mysql_xa_recover does not filter XID's to ensure uniqueness.
797
1491
    It can be easily fixed later, if necessary.
798
1492
*/
799
 
bool mysql_xa_recover(Session *session)
 
1493
bool mysql_xa_recover(THD *thd)
800
1494
{
801
1495
  List<Item> field_list;
802
 
  Protocol *protocol= session->protocol;
 
1496
  Protocol *protocol= thd->protocol;
803
1497
  int i=0;
804
1498
  XID_STATE *xs;
 
1499
  DBUG_ENTER("mysql_xa_recover");
805
1500
 
806
1501
  field_list.push_back(new Item_int("formatID", 0, MY_INT32_NUM_DECIMAL_DIGITS));
807
1502
  field_list.push_back(new Item_int("gtrid_length", 0, MY_INT32_NUM_DECIMAL_DIGITS));
808
1503
  field_list.push_back(new Item_int("bqual_length", 0, MY_INT32_NUM_DECIMAL_DIGITS));
809
1504
  field_list.push_back(new Item_empty_string("data",XIDDATASIZE));
810
1505
 
811
 
  if (protocol->sendFields(&field_list,
812
 
                           Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
813
 
    return 1;
 
1506
  if (protocol->send_fields(&field_list,
 
1507
                            Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
 
1508
    DBUG_RETURN(1);
814
1509
 
815
1510
  pthread_mutex_lock(&LOCK_xid_cache);
816
1511
  while ((xs= (XID_STATE*)hash_element(&xid_cache, i++)))
817
1512
  {
818
1513
    if (xs->xa_state==XA_PREPARED)
819
1514
    {
820
 
      protocol->prepareForResend();
821
 
      protocol->store((int64_t)xs->xid.formatID);
822
 
      protocol->store((int64_t)xs->xid.gtrid_length);
823
 
      protocol->store((int64_t)xs->xid.bqual_length);
824
 
      protocol->store(xs->xid.data, xs->xid.gtrid_length+xs->xid.bqual_length);
 
1515
      protocol->prepare_for_resend();
 
1516
      protocol->store_longlong((longlong)xs->xid.formatID, FALSE);
 
1517
      protocol->store_longlong((longlong)xs->xid.gtrid_length, FALSE);
 
1518
      protocol->store_longlong((longlong)xs->xid.bqual_length, FALSE);
 
1519
      protocol->store(xs->xid.data, xs->xid.gtrid_length+xs->xid.bqual_length,
 
1520
                      &my_charset_bin);
825
1521
      if (protocol->write())
826
1522
      {
827
1523
        pthread_mutex_unlock(&LOCK_xid_cache);
828
 
        return 1;
 
1524
        DBUG_RETURN(1);
829
1525
      }
830
1526
    }
831
1527
  }
832
1528
 
833
1529
  pthread_mutex_unlock(&LOCK_xid_cache);
834
 
  session->my_eof();
 
1530
  my_eof(thd);
 
1531
  DBUG_RETURN(0);
 
1532
}
 
1533
 
 
1534
/**
 
1535
  @details
 
1536
  This function should be called when MySQL sends rows of a SELECT result set
 
1537
  or the EOF mark to the client. It releases a possible adaptive hash index
 
1538
  S-latch held by thd in InnoDB and also releases a possible InnoDB query
 
1539
  FIFO ticket to enter InnoDB. To save CPU time, InnoDB allows a thd to
 
1540
  keep them over several calls of the InnoDB handler interface when a join
 
1541
  is executed. But when we let the control to pass to the client they have
 
1542
  to be released because if the application program uses mysql_use_result(),
 
1543
  it may deadlock on the S-latch if the application on another connection
 
1544
  performs another SQL query. In MySQL-4.1 this is even more important because
 
1545
  there a connection can have several SELECT queries open at the same time.
 
1546
 
 
1547
  @param thd           the thread handle of the current connection
 
1548
 
 
1549
  @return
 
1550
    always 0
 
1551
*/
 
1552
static my_bool release_temporary_latches(THD *thd, plugin_ref plugin,
 
1553
                                 void *unused)
 
1554
{
 
1555
  handlerton *hton= plugin_data(plugin, handlerton *);
 
1556
 
 
1557
  if (hton->state == SHOW_OPTION_YES && hton->release_temporary_latches)
 
1558
    hton->release_temporary_latches(hton, thd);
 
1559
 
 
1560
  return FALSE;
 
1561
}
 
1562
 
 
1563
 
 
1564
int ha_release_temporary_latches(THD *thd)
 
1565
{
 
1566
  plugin_foreach(thd, release_temporary_latches, MYSQL_STORAGE_ENGINE_PLUGIN, 
 
1567
                 NULL);
 
1568
 
835
1569
  return 0;
836
1570
}
837
1571
 
838
 
 
839
 
int ha_rollback_to_savepoint(Session *session, SAVEPOINT *sv)
 
1572
int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv)
840
1573
{
841
 
  int error= 0;
842
 
  Session_TRANS *trans= &session->transaction.all;
 
1574
  int error=0;
 
1575
  THD_TRANS *trans= (thd->in_sub_stmt ? &thd->transaction.stmt :
 
1576
                                        &thd->transaction.all);
843
1577
  Ha_trx_info *ha_info, *ha_info_next;
844
1578
 
 
1579
  DBUG_ENTER("ha_rollback_to_savepoint");
 
1580
 
845
1581
  trans->no_2pc=0;
846
1582
  /*
847
1583
    rolling back to savepoint in all storage engines that were part of the
850
1586
  for (ha_info= sv->ha_list; ha_info; ha_info= ha_info->next())
851
1587
  {
852
1588
    int err;
853
 
    StorageEngine *engine= ha_info->engine();
854
 
    assert(engine);
855
 
    if ((err= engine->savepoint_rollback(session,
856
 
                                         (void *)(sv+1))))
 
1589
    handlerton *ht= ha_info->ht();
 
1590
    DBUG_ASSERT(ht);
 
1591
    DBUG_ASSERT(ht->savepoint_set != 0);
 
1592
    if ((err= ht->savepoint_rollback(ht, thd,
 
1593
                                     (uchar *)(sv+1)+ht->savepoint_offset)))
857
1594
    { // cannot happen
858
1595
      my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
859
 
      error= 1;
 
1596
      error=1;
860
1597
    }
861
 
    status_var_increment(session->status_var.ha_savepoint_rollback_count);
862
 
    trans->no_2pc|= not engine->has_2pc();
 
1598
    status_var_increment(thd->status_var.ha_savepoint_rollback_count);
 
1599
    trans->no_2pc|= ht->prepare == 0;
863
1600
  }
864
1601
  /*
865
1602
    rolling back the transaction in all storage engines that were not part of
869
1606
       ha_info= ha_info_next)
870
1607
  {
871
1608
    int err;
872
 
    StorageEngine *engine= ha_info->engine();
873
 
    if ((err= engine->rollback(session, !(0))))
 
1609
    handlerton *ht= ha_info->ht();
 
1610
    if ((err= ht->rollback(ht, thd, !thd->in_sub_stmt)))
874
1611
    { // cannot happen
875
1612
      my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
876
 
      error= 1;
 
1613
      error=1;
877
1614
    }
878
 
    status_var_increment(session->status_var.ha_rollback_count);
 
1615
    status_var_increment(thd->status_var.ha_rollback_count);
879
1616
    ha_info_next= ha_info->next();
880
1617
    ha_info->reset(); /* keep it conveniently zero-filled */
881
1618
  }
882
1619
  trans->ha_list= sv->ha_list;
883
 
  return error;
 
1620
  DBUG_RETURN(error);
884
1621
}
885
1622
 
886
1623
/**
889
1626
  section "4.33.4 SQL-statements and transaction states",
890
1627
  SAVEPOINT is *not* transaction-initiating SQL-statement
891
1628
*/
892
 
int ha_savepoint(Session *session, SAVEPOINT *sv)
 
1629
int ha_savepoint(THD *thd, SAVEPOINT *sv)
893
1630
{
894
 
  int error= 0;
895
 
  Session_TRANS *trans= &session->transaction.all;
 
1631
  int error=0;
 
1632
  THD_TRANS *trans= (thd->in_sub_stmt ? &thd->transaction.stmt :
 
1633
                                        &thd->transaction.all);
896
1634
  Ha_trx_info *ha_info= trans->ha_list;
 
1635
  DBUG_ENTER("ha_savepoint");
897
1636
  for (; ha_info; ha_info= ha_info->next())
898
1637
  {
899
1638
    int err;
900
 
    StorageEngine *engine= ha_info->engine();
901
 
    assert(engine);
902
 
#ifdef NOT_IMPLEMENTED /*- TODO (examine this againt the original code base) */
903
 
    if (! engine->savepoint_set)
 
1639
    handlerton *ht= ha_info->ht();
 
1640
    DBUG_ASSERT(ht);
 
1641
    if (! ht->savepoint_set)
904
1642
    {
905
1643
      my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "SAVEPOINT");
906
 
      error= 1;
 
1644
      error=1;
907
1645
      break;
908
 
    } 
909
 
#endif
910
 
    if ((err= engine->savepoint_set(session, (void *)(sv+1))))
 
1646
    }
 
1647
    if ((err= ht->savepoint_set(ht, thd, (uchar *)(sv+1)+ht->savepoint_offset)))
911
1648
    { // cannot happen
912
1649
      my_error(ER_GET_ERRNO, MYF(0), err);
913
 
      error= 1;
 
1650
      error=1;
914
1651
    }
915
 
    status_var_increment(session->status_var.ha_savepoint_count);
 
1652
    status_var_increment(thd->status_var.ha_savepoint_count);
916
1653
  }
917
1654
  /*
918
1655
    Remember the list of registered storage engines. All new
919
1656
    engines are prepended to the beginning of the list.
920
1657
  */
921
1658
  sv->ha_list= trans->ha_list;
922
 
  return error;
 
1659
  DBUG_RETURN(error);
923
1660
}
924
1661
 
925
 
int ha_release_savepoint(Session *session, SAVEPOINT *sv)
 
1662
int ha_release_savepoint(THD *thd, SAVEPOINT *sv)
926
1663
{
927
 
  int error= 0;
 
1664
  int error=0;
928
1665
  Ha_trx_info *ha_info= sv->ha_list;
 
1666
  DBUG_ENTER("ha_release_savepoint");
929
1667
 
930
1668
  for (; ha_info; ha_info= ha_info->next())
931
1669
  {
932
1670
    int err;
933
 
    StorageEngine *engine= ha_info->engine();
 
1671
    handlerton *ht= ha_info->ht();
934
1672
    /* Savepoint life time is enclosed into transaction life time. */
935
 
    assert(engine);
936
 
    if ((err= engine->savepoint_release(session,
937
 
                                        (void *)(sv+1))))
 
1673
    DBUG_ASSERT(ht);
 
1674
    if (!ht->savepoint_release)
 
1675
      continue;
 
1676
    if ((err= ht->savepoint_release(ht, thd,
 
1677
                                    (uchar *)(sv+1) + ht->savepoint_offset)))
938
1678
    { // cannot happen
939
1679
      my_error(ER_GET_ERRNO, MYF(0), err);
940
 
      error= 1;
 
1680
      error=1;
941
1681
    }
942
1682
  }
943
 
  return error;
944
 
}
945
 
 
946
 
 
947
 
 
948
 
 
 
1683
  DBUG_RETURN(error);
 
1684
}
 
1685
 
 
1686
 
 
1687
static my_bool snapshot_handlerton(THD *thd, plugin_ref plugin,
 
1688
                                   void *arg)
 
1689
{
 
1690
  handlerton *hton= plugin_data(plugin, handlerton *);
 
1691
  if (hton->state == SHOW_OPTION_YES &&
 
1692
      hton->start_consistent_snapshot)
 
1693
  {
 
1694
    hton->start_consistent_snapshot(hton, thd);
 
1695
    *((bool *)arg)= false;
 
1696
  }
 
1697
  return FALSE;
 
1698
}
 
1699
 
 
1700
int ha_start_consistent_snapshot(THD *thd)
 
1701
{
 
1702
  bool warn= true;
 
1703
 
 
1704
  plugin_foreach(thd, snapshot_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, &warn);
 
1705
 
 
1706
  /*
 
1707
    Same idea as when one wants to CREATE TABLE in one engine which does not
 
1708
    exist:
 
1709
  */
 
1710
  if (warn)
 
1711
    push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
 
1712
                 "This MySQL server does not support any "
 
1713
                 "consistent-read capable storage engine");
 
1714
  return 0;
 
1715
}
 
1716
 
 
1717
 
 
1718
static my_bool flush_handlerton(THD *thd, plugin_ref plugin,
 
1719
                                void *arg)
 
1720
{
 
1721
  handlerton *hton= plugin_data(plugin, handlerton *);
 
1722
  if (hton->state == SHOW_OPTION_YES && hton->flush_logs && 
 
1723
      hton->flush_logs(hton))
 
1724
    return TRUE;
 
1725
  return FALSE;
 
1726
}
 
1727
 
 
1728
 
 
1729
bool ha_flush_logs(handlerton *db_type)
 
1730
{
 
1731
  if (db_type == NULL)
 
1732
  {
 
1733
    if (plugin_foreach(NULL, flush_handlerton,
 
1734
                          MYSQL_STORAGE_ENGINE_PLUGIN, 0))
 
1735
      return TRUE;
 
1736
  }
 
1737
  else
 
1738
  {
 
1739
    if (db_type->state != SHOW_OPTION_YES ||
 
1740
        (db_type->flush_logs && db_type->flush_logs(db_type)))
 
1741
      return TRUE;
 
1742
  }
 
1743
  return FALSE;
 
1744
}
 
1745
 
 
1746
static const char *check_lowercase_names(handler *file, const char *path,
 
1747
                                         char *tmp_path)
 
1748
{
 
1749
  if (lower_case_table_names != 2 || (file->ha_table_flags() & HA_FILE_BASED))
 
1750
    return path;
 
1751
 
 
1752
  /* Ensure that table handler get path in lower case */
 
1753
  if (tmp_path != path)
 
1754
    strmov(tmp_path, path);
 
1755
 
 
1756
  /*
 
1757
    we only should turn into lowercase database/table part
 
1758
    so start the process after homedirectory
 
1759
  */
 
1760
  my_casedn_str(files_charset_info, tmp_path + mysql_data_home_len);
 
1761
  return tmp_path;
 
1762
}
 
1763
 
 
1764
 
 
1765
/**
 
1766
  An interceptor to hijack the text of the error message without
 
1767
  setting an error in the thread. We need the text to present it
 
1768
  in the form of a warning to the user.
 
1769
*/
 
1770
 
 
1771
struct Ha_delete_table_error_handler: public Internal_error_handler
 
1772
{
 
1773
public:
 
1774
  virtual bool handle_error(uint sql_errno,
 
1775
                            const char *message,
 
1776
                            MYSQL_ERROR::enum_warning_level level,
 
1777
                            THD *thd);
 
1778
  char buff[MYSQL_ERRMSG_SIZE];
 
1779
};
 
1780
 
 
1781
 
 
1782
bool
 
1783
Ha_delete_table_error_handler::
 
1784
handle_error(uint sql_errno,
 
1785
             const char *message,
 
1786
             MYSQL_ERROR::enum_warning_level level,
 
1787
             THD *thd)
 
1788
{
 
1789
  /* Grab the error message */
 
1790
  strmake(buff, message, sizeof(buff)-1);
 
1791
  return TRUE;
 
1792
}
 
1793
 
 
1794
 
 
1795
/**
 
1796
  This should return ENOENT if the file doesn't exists.
 
1797
  The .frm file will be deleted only if we return 0 or ENOENT
 
1798
*/
 
1799
int ha_delete_table(THD *thd, handlerton *table_type, const char *path,
 
1800
                    const char *db, const char *alias, bool generate_warning)
 
1801
{
 
1802
  handler *file;
 
1803
  char tmp_path[FN_REFLEN];
 
1804
  int error;
 
1805
  TABLE dummy_table;
 
1806
  TABLE_SHARE dummy_share;
 
1807
  DBUG_ENTER("ha_delete_table");
 
1808
 
 
1809
  bzero((char*) &dummy_table, sizeof(dummy_table));
 
1810
  bzero((char*) &dummy_share, sizeof(dummy_share));
 
1811
  dummy_table.s= &dummy_share;
 
1812
 
 
1813
  /* DB_TYPE_UNKNOWN is used in ALTER TABLE when renaming only .frm files */
 
1814
  if (table_type == NULL ||
 
1815
      ! (file=get_new_handler((TABLE_SHARE*)0, thd->mem_root, table_type)))
 
1816
    DBUG_RETURN(ENOENT);
 
1817
 
 
1818
  path= check_lowercase_names(file, path, tmp_path);
 
1819
  if ((error= file->ha_delete_table(path)) && generate_warning)
 
1820
  {
 
1821
    /*
 
1822
      Because file->print_error() use my_error() to generate the error message
 
1823
      we use an internal error handler to intercept it and store the text
 
1824
      in a temporary buffer. Later the message will be presented to user
 
1825
      as a warning.
 
1826
    */
 
1827
    Ha_delete_table_error_handler ha_delete_table_error_handler;
 
1828
 
 
1829
    /* Fill up strucutures that print_error may need */
 
1830
    dummy_share.path.str= (char*) path;
 
1831
    dummy_share.path.length= strlen(path);
 
1832
    dummy_share.db.str= (char*) db;
 
1833
    dummy_share.db.length= strlen(db);
 
1834
    dummy_share.table_name.str= (char*) alias;
 
1835
    dummy_share.table_name.length= strlen(alias);
 
1836
    dummy_table.alias= alias;
 
1837
 
 
1838
    file->change_table_ptr(&dummy_table, &dummy_share);
 
1839
 
 
1840
    thd->push_internal_handler(&ha_delete_table_error_handler);
 
1841
    file->print_error(error, 0);
 
1842
 
 
1843
    thd->pop_internal_handler();
 
1844
 
 
1845
    /*
 
1846
      XXX: should we convert *all* errors to warnings here?
 
1847
      What if the error is fatal?
 
1848
    */
 
1849
    push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, error,
 
1850
                ha_delete_table_error_handler.buff);
 
1851
  }
 
1852
  delete file;
 
1853
  DBUG_RETURN(error);
 
1854
}
949
1855
 
950
1856
/****************************************************************************
951
1857
** General handler functions
952
1858
****************************************************************************/
953
 
handler::~handler(void)
954
 
{
955
 
  assert(locked == false);
956
 
  /* TODO: assert(inited == NONE); */
957
 
}
958
 
 
959
 
 
960
1859
handler *handler::clone(MEM_ROOT *mem_root)
961
1860
{
962
1861
  handler *new_handler= get_new_handler(table->s, mem_root, table->s->db_type());
963
1862
  /*
964
1863
    Allocate handler->ref here because otherwise ha_open will allocate it
965
 
    on this->table->mem_root and we will not be able to reclaim that memory
 
1864
    on this->table->mem_root and we will not be able to reclaim that memory 
966
1865
    when the clone handler object is destroyed.
967
1866
  */
968
 
  if (!(new_handler->ref= (unsigned char*) alloc_root(mem_root, ALIGN_SIZE(ref_length)*2)))
 
1867
  if (!(new_handler->ref= (uchar*) alloc_root(mem_root, ALIGN_SIZE(ref_length)*2)))
969
1868
    return NULL;
970
1869
  if (new_handler && !new_handler->ha_open(table,
971
1870
                                           table->s->normalized_path.str,
972
 
                                           table->getDBStat(),
 
1871
                                           table->db_stat,
973
1872
                                           HA_OPEN_IGNORE_IF_LOCKED))
974
1873
    return new_handler;
975
1874
  return NULL;
976
1875
}
977
1876
 
978
 
int handler::ha_index_init(uint32_t idx, bool sorted)
979
 
{
980
 
  int result;
981
 
  assert(inited == NONE);
982
 
  if (!(result= index_init(idx, sorted)))
983
 
    inited=INDEX;
984
 
  end_range= NULL;
985
 
  return result;
986
 
}
987
 
 
988
 
int handler::ha_index_end()
989
 
{
990
 
  assert(inited==INDEX);
991
 
  inited=NONE;
992
 
  end_range= NULL;
993
 
  return(index_end());
994
 
}
995
 
 
996
 
int handler::ha_rnd_init(bool scan)
997
 
{
998
 
  int result;
999
 
  assert(inited==NONE || (inited==RND && scan));
1000
 
  inited= (result= rnd_init(scan)) ? NONE: RND;
1001
 
 
1002
 
  return result;
1003
 
}
1004
 
 
1005
 
int handler::ha_rnd_end()
1006
 
{
1007
 
  assert(inited==RND);
1008
 
  inited=NONE;
1009
 
  return(rnd_end());
1010
 
}
1011
 
 
1012
 
int handler::ha_index_or_rnd_end()
1013
 
{
1014
 
  return inited == INDEX ? ha_index_end() : inited == RND ? ha_rnd_end() : 0;
1015
 
}
1016
 
 
1017
 
handler::Table_flags handler::ha_table_flags() const
1018
 
{
1019
 
  return cached_table_flags;
1020
 
}
1021
 
 
1022
 
void handler::ha_start_bulk_insert(ha_rows rows)
1023
 
{
1024
 
  estimation_rows_to_insert= rows;
1025
 
  start_bulk_insert(rows);
1026
 
}
1027
 
 
1028
 
int handler::ha_end_bulk_insert()
1029
 
{
1030
 
  estimation_rows_to_insert= 0;
1031
 
  return end_bulk_insert();
1032
 
}
1033
 
 
1034
 
void handler::change_table_ptr(Table *table_arg, TableShare *share)
1035
 
{
1036
 
  table= table_arg;
1037
 
  table_share= share;
1038
 
}
1039
 
 
1040
 
const key_map *handler::keys_to_use_for_scanning()
1041
 
{
1042
 
  return &key_map_empty;
1043
 
}
1044
 
 
1045
 
bool handler::has_transactions()
1046
 
{
1047
 
  return (ha_table_flags() & HA_NO_TRANSACTIONS) == 0;
1048
 
}
 
1877
 
1049
1878
 
1050
1879
void handler::ha_statistic_increment(ulong SSV::*offset) const
1051
1880
{
1052
1881
  status_var_increment(table->in_use->status_var.*offset);
1053
1882
}
1054
1883
 
1055
 
void **handler::ha_data(Session *session) const
1056
 
{
1057
 
  return session_ha_data(session, engine);
1058
 
}
1059
 
 
1060
 
Session *handler::ha_session(void) const
1061
 
{
1062
 
  assert(!table || !table->in_use || table->in_use == current_session);
1063
 
  return (table && table->in_use) ? table->in_use : current_session;
1064
 
}
1065
 
 
1066
 
 
1067
 
bool handler::is_fatal_error(int error, uint32_t flags)
1068
 
{
1069
 
  if (!error ||
1070
 
      ((flags & HA_CHECK_DUP_KEY) &&
1071
 
       (error == HA_ERR_FOUND_DUPP_KEY ||
1072
 
        error == HA_ERR_FOUND_DUPP_UNIQUE)))
1073
 
    return false;
1074
 
  return true;
1075
 
}
1076
 
 
1077
 
 
1078
 
ha_rows handler::records() { return stats.records; }
 
1884
void **handler::ha_data(THD *thd) const
 
1885
{
 
1886
  return thd_ha_data(thd, ht);
 
1887
}
 
1888
 
 
1889
THD *handler::ha_thd(void) const
 
1890
{
 
1891
  DBUG_ASSERT(!table || !table->in_use || table->in_use == current_thd);
 
1892
  return (table && table->in_use) ? table->in_use : current_thd;
 
1893
}
 
1894
 
 
1895
 
 
1896
/**
 
1897
   Get tablespace name from handler 
 
1898
   Returns the tablespace name associated
 
1899
   with the table or NULL if not defined
 
1900
*/
 
1901
const 
 
1902
char* handler::get_tablespace_name()
 
1903
{
 
1904
  return table->s->tablespace;
 
1905
}
1079
1906
 
1080
1907
/**
1081
1908
  Open database-handler.
1083
1910
  Try O_RDONLY if cannot open as O_RDWR
1084
1911
  Don't wait for locks if not HA_OPEN_WAIT_IF_LOCKED is set
1085
1912
*/
1086
 
int handler::ha_open(Table *table_arg, const char *name, int mode,
 
1913
int handler::ha_open(TABLE *table_arg, const char *name, int mode,
1087
1914
                     int test_if_locked)
1088
1915
{
1089
1916
  int error;
 
1917
  DBUG_ENTER("handler::ha_open");
 
1918
  DBUG_PRINT("enter",
 
1919
             ("name: %s  db_type: %d  db_stat: %d  mode: %d  lock_test: %d",
 
1920
              name, ht->db_type, table_arg->db_stat, mode,
 
1921
              test_if_locked));
1090
1922
 
1091
1923
  table= table_arg;
1092
 
  assert(table->s == table_share);
1093
 
  assert(alloc_root_inited(&table->mem_root));
 
1924
  DBUG_ASSERT(table->s == table_share);
 
1925
  DBUG_ASSERT(alloc_root_inited(&table->mem_root));
1094
1926
 
1095
1927
  if ((error=open(name,mode,test_if_locked)))
1096
1928
  {
1104
1936
  if (error)
1105
1937
  {
1106
1938
    my_errno= error;                            /* Safeguard */
 
1939
    DBUG_PRINT("error",("error: %d  errno: %d",error,errno));
1107
1940
  }
1108
1941
  else
1109
1942
  {
1112
1945
    (void) extra(HA_EXTRA_NO_READCHECK);        // Not needed in SQL
1113
1946
 
1114
1947
    /* ref is already allocated for us if we're called from handler::clone() */
1115
 
    if (!ref && !(ref= (unsigned char*) alloc_root(&table->mem_root,
 
1948
    if (!ref && !(ref= (uchar*) alloc_root(&table->mem_root, 
1116
1949
                                          ALIGN_SIZE(ref_length)*2)))
1117
1950
    {
1118
1951
      close();
1122
1955
      dup_ref=ref+ALIGN_SIZE(ref_length);
1123
1956
    cached_table_flags= table_flags();
1124
1957
  }
1125
 
  return error;
 
1958
  DBUG_RETURN(error);
1126
1959
}
1127
1960
 
1128
1961
/**
1132
1965
  handlers for random position
1133
1966
*/
1134
1967
 
1135
 
int handler::rnd_pos_by_record(unsigned char *record)
 
1968
int handler::rnd_pos_by_record(uchar *record)
1136
1969
{
1137
1970
  register int error;
 
1971
  DBUG_ENTER("handler::rnd_pos_by_record");
1138
1972
 
1139
1973
  position(record);
1140
1974
  if (inited && (error= ha_index_end()))
1141
 
    return error;
1142
 
  if ((error= ha_rnd_init(false)))
1143
 
    return error;
 
1975
    DBUG_RETURN(error);
 
1976
  if ((error= ha_rnd_init(FALSE)))
 
1977
    DBUG_RETURN(error);
1144
1978
 
1145
 
  return rnd_pos(record, ref);
 
1979
  DBUG_RETURN(rnd_pos(record, ref));
1146
1980
}
1147
1981
 
1148
1982
/**
1151
1985
  This is never called for InnoDB tables, as these table types
1152
1986
  has the HA_STATS_RECORDS_IS_EXACT set.
1153
1987
*/
1154
 
int handler::read_first_row(unsigned char * buf, uint32_t primary_key)
 
1988
int handler::read_first_row(uchar * buf, uint primary_key)
1155
1989
{
1156
1990
  register int error;
 
1991
  DBUG_ENTER("handler::read_first_row");
1157
1992
 
1158
1993
  ha_statistic_increment(&SSV::ha_read_first_count);
1159
1994
 
1176
2011
    error=index_first(buf);
1177
2012
    (void) ha_index_end();
1178
2013
  }
1179
 
  return error;
 
2014
  DBUG_RETURN(error);
1180
2015
}
1181
2016
 
1182
2017
/**
1206
2041
void handler::adjust_next_insert_id_after_explicit_value(uint64_t nr)
1207
2042
{
1208
2043
  /*
1209
 
    If we have set Session::next_insert_id previously and plan to insert an
 
2044
    If we have set THD::next_insert_id previously and plan to insert an
1210
2045
    explicitely-specified value larger than this, we need to increase
1211
 
    Session::next_insert_id to be greater than the explicit value.
 
2046
    THD::next_insert_id to be greater than the explicit value.
1212
2047
  */
1213
2048
  if ((next_insert_id > 0) && (nr >= next_insert_id))
1214
2049
    set_next_insert_id(compute_next_insert_id(nr, &table->in_use->variables));
1240
2075
      the offset is larger than the column's max possible value, i.e. not even
1241
2076
      the first sequence value may be inserted. User will receive warning.
1242
2077
    */
 
2078
    DBUG_PRINT("info",("auto_increment: nr: %lu cannot honour "
 
2079
                       "auto_increment_offset: %lu",
 
2080
                       (ulong) nr, variables->auto_increment_offset));
1243
2081
    return nr;
1244
2082
  }
1245
2083
  if (variables->auto_increment_increment == 1)
1256
2094
 
1257
2095
  Updates columns with type NEXT_NUMBER if:
1258
2096
 
1259
 
  - If column value is set to NULL (in which case auto_increment_field_not_null is false)
 
2097
  - If column value is set to NULL (in which case
 
2098
    auto_increment_field_not_null is 0)
1260
2099
  - If column is set to 0 and (sql_mode & MODE_NO_AUTO_VALUE_ON_ZERO) is not
1261
2100
    set. In the future we will only set NEXT_NUMBER fields if one sets them
1262
2101
    to NULL (or they are not included in the insert list).
1283
2122
    again to reserve a new interval.
1284
2123
 
1285
2124
  - In both cases, the reserved intervals are remembered in
1286
 
    session->auto_inc_intervals_in_cur_stmt_for_binlog if statement-based
 
2125
    thd->auto_inc_intervals_in_cur_stmt_for_binlog if statement-based
1287
2126
    binlogging; the last reserved interval is remembered in
1288
2127
    auto_inc_interval_for_cur_row.
1289
2128
 
1297
2136
    start counting from the inserted value.
1298
2137
 
1299
2138
    This function's "outputs" are: the table's auto_increment field is filled
1300
 
    with a value, session->next_insert_id is filled with the value to use for the
 
2139
    with a value, thd->next_insert_id is filled with the value to use for the
1301
2140
    next row, if a value was autogenerated for the current row it is stored in
1302
 
    session->insert_id_for_cur_row, if get_auto_increment() was called
1303
 
    session->auto_inc_interval_for_cur_row is modified, if that interval is not
1304
 
    present in session->auto_inc_intervals_in_cur_stmt_for_binlog it is added to
 
2141
    thd->insert_id_for_cur_row, if get_auto_increment() was called
 
2142
    thd->auto_inc_interval_for_cur_row is modified, if that interval is not
 
2143
    present in thd->auto_inc_intervals_in_cur_stmt_for_binlog it is added to
1305
2144
    this list.
1306
2145
 
1307
2146
  @todo
1327
2166
int handler::update_auto_increment()
1328
2167
{
1329
2168
  uint64_t nr, nb_reserved_values;
1330
 
  bool append= false;
1331
 
  Session *session= table->in_use;
1332
 
  struct system_variables *variables= &session->variables;
 
2169
  bool append= FALSE;
 
2170
  THD *thd= table->in_use;
 
2171
  struct system_variables *variables= &thd->variables;
 
2172
  DBUG_ENTER("handler::update_auto_increment");
1333
2173
 
1334
2174
  /*
1335
2175
    next_insert_id is a "cursor" into the reserved interval, it may go greater
1336
2176
    than the interval, but not smaller.
1337
2177
  */
1338
 
  assert(next_insert_id >= auto_inc_interval_for_cur_row.minimum());
1339
 
 
1340
 
  /* We check if auto_increment_field_not_null is false
1341
 
     for an auto increment column, not a magic value like NULL is.
1342
 
     same as sql_mode=NO_AUTO_VALUE_ON_ZERO */
1343
 
 
1344
 
  if ((nr= table->next_number_field->val_int()) != 0
1345
 
      || table->auto_increment_field_not_null)
 
2178
  DBUG_ASSERT(next_insert_id >= auto_inc_interval_for_cur_row.minimum());
 
2179
 
 
2180
  if (((nr= table->next_number_field->val_int()) != 0) || 
 
2181
      (table->auto_increment_field_not_null && (thd->variables.sql_mode & MODE_NO_AUTO_VALUE_ON_ZERO)))
1346
2182
  {
1347
2183
    /*
1348
2184
      Update next_insert_id if we had already generated a value in this
1352
2188
    */
1353
2189
    adjust_next_insert_id_after_explicit_value(nr);
1354
2190
    insert_id_for_cur_row= 0; // didn't generate anything
1355
 
 
1356
 
    return 0;
 
2191
    DBUG_RETURN(0);
1357
2192
  }
1358
2193
 
1359
2194
  if ((nr= next_insert_id) >= auto_inc_interval_for_cur_row.maximum())
1360
2195
  {
1361
2196
    /* next_insert_id is beyond what is reserved, so we reserve more. */
1362
2197
    const Discrete_interval *forced=
1363
 
      session->auto_inc_intervals_forced.get_next();
 
2198
      thd->auto_inc_intervals_forced.get_next();
1364
2199
    if (forced != NULL)
1365
2200
    {
1366
2201
      nr= forced->minimum();
1372
2207
        handler::estimation_rows_to_insert was set by
1373
2208
        handler::ha_start_bulk_insert(); if 0 it means "unknown".
1374
2209
      */
1375
 
      uint32_t nb_already_reserved_intervals=
1376
 
        session->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements();
 
2210
      uint nb_already_reserved_intervals=
 
2211
        thd->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements();
1377
2212
      uint64_t nb_desired_values;
1378
2213
      /*
1379
2214
        If an estimation was given to the engine:
1394
2229
        /* avoid overflow in formula, with this if() */
1395
2230
        if (nb_already_reserved_intervals <= AUTO_INC_DEFAULT_NB_MAX_BITS)
1396
2231
        {
1397
 
          nb_desired_values= AUTO_INC_DEFAULT_NB_ROWS *
 
2232
          nb_desired_values= AUTO_INC_DEFAULT_NB_ROWS * 
1398
2233
            (1 << nb_already_reserved_intervals);
1399
 
          set_if_smaller(nb_desired_values, (uint64_t)AUTO_INC_DEFAULT_NB_MAX);
 
2234
          set_if_smaller(nb_desired_values, AUTO_INC_DEFAULT_NB_MAX);
1400
2235
        }
1401
2236
        else
1402
2237
          nb_desired_values= AUTO_INC_DEFAULT_NB_MAX;
1407
2242
                         nb_desired_values, &nr,
1408
2243
                         &nb_reserved_values);
1409
2244
      if (nr == ~(uint64_t) 0)
1410
 
        return HA_ERR_AUTOINC_READ_FAILED;  // Mark failure
1411
 
 
 
2245
        DBUG_RETURN(HA_ERR_AUTOINC_READ_FAILED);  // Mark failure
 
2246
      
1412
2247
      /*
1413
2248
        That rounding below should not be needed when all engines actually
1414
2249
        respect offset and increment in get_auto_increment(). But they don't
1419
2254
      */
1420
2255
      nr= compute_next_insert_id(nr-1, variables);
1421
2256
    }
1422
 
 
 
2257
    
1423
2258
    if (table->s->next_number_keypart == 0)
1424
2259
    {
1425
2260
      /* We must defer the appending until "nr" has been possibly truncated */
1426
 
      append= true;
 
2261
      append= TRUE;
 
2262
    }
 
2263
    else
 
2264
    {
 
2265
      /*
 
2266
        For such auto_increment there is no notion of interval, just a
 
2267
        singleton. The interval is not even stored in
 
2268
        thd->auto_inc_interval_for_cur_row, so we are sure to call the engine
 
2269
        for next row.
 
2270
      */
 
2271
      DBUG_PRINT("info",("auto_increment: special not-first-in-index"));
1427
2272
    }
1428
2273
  }
1429
2274
 
1430
 
  if (unlikely(table->next_number_field->store((int64_t) nr, true)))
 
2275
  DBUG_PRINT("info",("auto_increment: %lu", (ulong) nr));
 
2276
 
 
2277
  if (unlikely(table->next_number_field->store((longlong) nr, TRUE)))
1431
2278
  {
1432
2279
    /*
1433
2280
      first test if the query was aborted due to strict mode constraints
1434
2281
    */
1435
 
    if (session->killed == Session::KILL_BAD_DATA)
1436
 
      return HA_ERR_AUTOINC_ERANGE;
 
2282
    if (thd->killed == THD::KILL_BAD_DATA)
 
2283
      DBUG_RETURN(HA_ERR_AUTOINC_ERANGE);
1437
2284
 
1438
2285
    /*
1439
2286
      field refused this value (overflow) and truncated it, use the result of
1444
2291
      interval will cause a duplicate key).
1445
2292
    */
1446
2293
    nr= prev_insert_id(table->next_number_field->val_int(), variables);
1447
 
    if (unlikely(table->next_number_field->store((int64_t) nr, true)))
 
2294
    if (unlikely(table->next_number_field->store((longlong) nr, TRUE)))
1448
2295
      nr= table->next_number_field->val_int();
1449
2296
  }
1450
2297
  if (append)
1451
2298
  {
1452
2299
    auto_inc_interval_for_cur_row.replace(nr, nb_reserved_values,
1453
2300
                                          variables->auto_increment_increment);
 
2301
    /* Row-based replication does not need to store intervals in binlog */
 
2302
    if (!thd->current_stmt_binlog_row_based)
 
2303
        thd->auto_inc_intervals_in_cur_stmt_for_binlog.append(auto_inc_interval_for_cur_row.minimum(),
 
2304
                                                              auto_inc_interval_for_cur_row.values(),
 
2305
                                                              variables->auto_increment_increment);
1454
2306
  }
1455
2307
 
1456
2308
  /*
1467
2319
  */
1468
2320
  set_next_insert_id(compute_next_insert_id(nr, variables));
1469
2321
 
1470
 
  return 0;
 
2322
  DBUG_RETURN(0);
 
2323
}
 
2324
 
 
2325
 
 
2326
/**
 
2327
  MySQL signal that it changed the column bitmap
 
2328
 
 
2329
  This is for handlers that needs to setup their own column bitmaps.
 
2330
  Normally the handler should set up their own column bitmaps in
 
2331
  index_init() or rnd_init() and in any column_bitmaps_signal() call after
 
2332
  this.
 
2333
 
 
2334
  The handler is allowed to do changes to the bitmap after a index_init or
 
2335
  rnd_init() call is made as after this, MySQL will not use the bitmap
 
2336
  for any program logic checking.
 
2337
*/
 
2338
void handler::column_bitmaps_signal()
 
2339
{
 
2340
  DBUG_ENTER("column_bitmaps_signal");
 
2341
  DBUG_PRINT("info", ("read_set: 0x%lx  write_set: 0x%lx", (long) table->read_set,
 
2342
                      (long) table->write_set));
 
2343
  DBUG_VOID_RETURN;
1471
2344
}
1472
2345
 
1473
2346
 
1477
2350
  offset and increment means that we want values to be of the form
1478
2351
  offset + N * increment, where N>=0 is integer.
1479
2352
  If the function sets *first_value to ~(uint64_t)0 it means an error.
1480
 
  If the function sets *nb_reserved_values to UINT64_MAX it means it has
 
2353
  If the function sets *nb_reserved_values to ULONGLONG_MAX it means it has
1481
2354
  reserved to "positive infinite".
1482
2355
 
1483
2356
  @param offset
1486
2359
  @param first_value         (OUT) the first value reserved by the handler
1487
2360
  @param nb_reserved_values  (OUT) how many values the handler reserved
1488
2361
*/
1489
 
void handler::get_auto_increment(uint64_t ,
1490
 
                                 uint64_t ,
1491
 
                                 uint64_t ,
 
2362
void handler::get_auto_increment(uint64_t offset, uint64_t increment,
 
2363
                                 uint64_t nb_desired_values,
1492
2364
                                 uint64_t *first_value,
1493
2365
                                 uint64_t *nb_reserved_values)
1494
2366
{
1496
2368
  int error;
1497
2369
 
1498
2370
  (void) extra(HA_EXTRA_KEYREAD);
1499
 
  table->mark_columns_used_by_index_no_reset(table->s->next_number_index);
 
2371
  table->mark_columns_used_by_index_no_reset(table->s->next_number_index,
 
2372
                                        table->read_set);
 
2373
  column_bitmaps_signal();
1500
2374
  index_init(table->s->next_number_index, 1);
1501
2375
  if (table->s->next_number_keypart == 0)
1502
2376
  {                                             // Autoincrement at key-start
1506
2380
      use nr+increment without checking again with the handler, in
1507
2381
      handler::update_auto_increment()), so reserves to infinite.
1508
2382
    */
1509
 
    *nb_reserved_values= UINT64_MAX;
 
2383
    *nb_reserved_values= ULONGLONG_MAX;
1510
2384
  }
1511
2385
  else
1512
2386
  {
1513
 
    unsigned char key[MAX_KEY_LENGTH];
 
2387
    uchar key[MAX_KEY_LENGTH];
1514
2388
    key_copy(key, table->record[0],
1515
2389
             table->key_info + table->s->next_number_index,
1516
2390
             table->s->next_number_key_offset);
1554
2428
}
1555
2429
 
1556
2430
 
1557
 
void handler::print_keydup_error(uint32_t key_nr, const char *msg)
 
2431
void handler::print_keydup_error(uint key_nr, const char *msg)
1558
2432
{
1559
2433
  /* Write the duplicated key in the error message */
1560
2434
  char key[MAX_KEY_LENGTH];
1569
2443
  else
1570
2444
  {
1571
2445
    /* Table is opened and defined at this point */
1572
 
    key_unpack(&str,table,(uint32_t) key_nr);
1573
 
    uint32_t max_length=DRIZZLE_ERRMSG_SIZE-(uint32_t) strlen(msg);
 
2446
    key_unpack(&str,table,(uint) key_nr);
 
2447
    uint max_length=MYSQL_ERRMSG_SIZE-(uint) strlen(msg);
1574
2448
    if (str.length() >= max_length)
1575
2449
    {
1576
2450
      str.length(max_length-4);
1593
2467
*/
1594
2468
void handler::print_error(int error, myf errflag)
1595
2469
{
 
2470
  DBUG_ENTER("handler::print_error");
 
2471
  DBUG_PRINT("enter",("error: %d",error));
 
2472
 
1596
2473
  int textno=ER_GET_ERRNO;
1597
2474
  switch (error) {
1598
2475
  case EACCES:
1614
2491
    break;
1615
2492
  case HA_ERR_FOUND_DUPP_KEY:
1616
2493
  {
1617
 
    uint32_t key_nr=get_dup_key(error);
 
2494
    uint key_nr=get_dup_key(error);
1618
2495
    if ((int) key_nr >= 0)
1619
2496
    {
1620
2497
      print_keydup_error(key_nr, ER(ER_DUP_ENTRY_WITH_KEY_NAME));
1621
 
      return;
 
2498
      DBUG_VOID_RETURN;
1622
2499
    }
1623
2500
    textno=ER_DUP_KEY;
1624
2501
    break;
1625
2502
  }
1626
2503
  case HA_ERR_FOREIGN_DUPLICATE_KEY:
1627
2504
  {
1628
 
    uint32_t key_nr= get_dup_key(error);
 
2505
    uint key_nr= get_dup_key(error);
1629
2506
    if ((int) key_nr >= 0)
1630
2507
    {
1631
 
      uint32_t max_length;
 
2508
      uint max_length;
1632
2509
      /* Write the key in the error message */
1633
2510
      char key[MAX_KEY_LENGTH];
1634
2511
      String str(key,sizeof(key),system_charset_info);
1635
2512
      /* Table is opened and defined at this point */
1636
 
      key_unpack(&str,table,(uint32_t) key_nr);
1637
 
      max_length= (DRIZZLE_ERRMSG_SIZE-
1638
 
                   (uint32_t) strlen(ER(ER_FOREIGN_DUPLICATE_KEY)));
 
2513
      key_unpack(&str,table,(uint) key_nr);
 
2514
      max_length= (MYSQL_ERRMSG_SIZE-
 
2515
                   (uint) strlen(ER(ER_FOREIGN_DUPLICATE_KEY)));
1639
2516
      if (str.length() >= max_length)
1640
2517
      {
1641
2518
        str.length(max_length-4);
1643
2520
      }
1644
2521
      my_error(ER_FOREIGN_DUPLICATE_KEY, MYF(0), table_share->table_name.str,
1645
2522
        str.c_ptr(), key_nr+1);
1646
 
      return;
 
2523
      DBUG_VOID_RETURN;
1647
2524
    }
1648
2525
    textno= ER_DUP_KEY;
1649
2526
    break;
1705
2582
    String str;
1706
2583
    get_error_message(error, &str);
1707
2584
    my_error(ER_ROW_IS_REFERENCED_2, MYF(0), str.c_ptr_safe());
1708
 
    return;
 
2585
    DBUG_VOID_RETURN;
1709
2586
  }
1710
2587
  case HA_ERR_NO_REFERENCED_ROW:
1711
2588
  {
1712
2589
    String str;
1713
2590
    get_error_message(error, &str);
1714
2591
    my_error(ER_NO_REFERENCED_ROW_2, MYF(0), str.c_ptr_safe());
1715
 
    return;
 
2592
    DBUG_VOID_RETURN;
1716
2593
  }
1717
2594
  case HA_ERR_TABLE_DEF_CHANGED:
1718
2595
    textno=ER_TABLE_DEF_CHANGED;
1720
2597
  case HA_ERR_NO_SUCH_TABLE:
1721
2598
    my_error(ER_NO_SUCH_TABLE, MYF(0), table_share->db.str,
1722
2599
             table_share->table_name.str);
1723
 
    return;
 
2600
    DBUG_VOID_RETURN;
1724
2601
  case HA_ERR_RBR_LOGGING_FAILED:
1725
2602
    textno= ER_BINLOG_ROW_LOGGING_FAILED;
1726
2603
    break;
1727
2604
  case HA_ERR_DROP_INDEX_FK:
1728
2605
  {
1729
2606
    const char *ptr= "???";
1730
 
    uint32_t key_nr= get_dup_key(error);
 
2607
    uint key_nr= get_dup_key(error);
1731
2608
    if ((int) key_nr >= 0)
1732
2609
      ptr= table->key_info[key_nr].name;
1733
2610
    my_error(ER_DROP_INDEX_FK, MYF(0), ptr);
1734
 
    return;
 
2611
    DBUG_VOID_RETURN;
1735
2612
  }
1736
2613
  case HA_ERR_TABLE_NEEDS_UPGRADE:
1737
2614
    textno=ER_TABLE_NEEDS_UPGRADE;
1748
2625
  case HA_ERR_LOCK_OR_ACTIVE_TRANSACTION:
1749
2626
    my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
1750
2627
               ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
1751
 
    return;
 
2628
    DBUG_VOID_RETURN;
 
2629
    break;
1752
2630
  default:
1753
2631
    {
1754
2632
      /* The error was "unknown" to this function.
1755
2633
         Ask handler if it has got a message for this error */
1756
 
      bool temporary= false;
 
2634
      bool temporary= FALSE;
1757
2635
      String str;
1758
2636
      temporary= get_error_message(error, &str);
1759
2637
      if (!str.is_empty())
1760
2638
      {
1761
 
        const char* engine_name= engine->getName().c_str();
1762
 
        if (temporary)
1763
 
          my_error(ER_GET_TEMPORARY_ERRMSG, MYF(0), error, str.ptr(),
1764
 
                   engine_name);
1765
 
        else
1766
 
          my_error(ER_GET_ERRMSG, MYF(0), error, str.ptr(), engine_name);
 
2639
        const char* engine= table_type();
 
2640
        if (temporary)
 
2641
          my_error(ER_GET_TEMPORARY_ERRMSG, MYF(0), error, str.ptr(), engine);
 
2642
        else
 
2643
          my_error(ER_GET_ERRMSG, MYF(0), error, str.ptr(), engine);
1767
2644
      }
1768
2645
      else
1769
 
      {
1770
 
              my_error(ER_GET_ERRNO,errflag,error);
1771
 
      }
1772
 
      return;
 
2646
        my_error(ER_GET_ERRNO,errflag,error);
 
2647
      DBUG_VOID_RETURN;
1773
2648
    }
1774
2649
  }
1775
2650
  my_error(textno, errflag, table_share->table_name.str, error);
 
2651
  DBUG_VOID_RETURN;
1776
2652
}
1777
2653
 
1778
2654
 
1785
2661
  @return
1786
2662
    Returns true if this is a temporary error
1787
2663
*/
1788
 
bool handler::get_error_message(int , String* )
1789
 
{
1790
 
  return false;
 
2664
bool handler::get_error_message(int error, String* buf)
 
2665
{
 
2666
  return FALSE;
 
2667
}
 
2668
 
 
2669
 
 
2670
int handler::ha_check_for_upgrade(HA_CHECK_OPT *check_opt)
 
2671
{
 
2672
  KEY *keyinfo, *keyend;
 
2673
  KEY_PART_INFO *keypart, *keypartend;
 
2674
 
 
2675
  if (!table->s->mysql_version)
 
2676
  {
 
2677
    /* check for blob-in-key error */
 
2678
    keyinfo= table->key_info;
 
2679
    keyend= table->key_info + table->s->keys;
 
2680
    for (; keyinfo < keyend; keyinfo++)
 
2681
    {
 
2682
      keypart= keyinfo->key_part;
 
2683
      keypartend= keypart + keyinfo->key_parts;
 
2684
      for (; keypart < keypartend; keypart++)
 
2685
      {
 
2686
        if (!keypart->fieldnr)
 
2687
          continue;
 
2688
        Field *field= table->field[keypart->fieldnr-1];
 
2689
        if (field->type() == MYSQL_TYPE_BLOB)
 
2690
        {
 
2691
          if (check_opt->sql_flags & TT_FOR_UPGRADE)
 
2692
            check_opt->flags= T_MEDIUM;
 
2693
          return HA_ADMIN_NEEDS_CHECK;
 
2694
        }
 
2695
      }
 
2696
    }
 
2697
  }
 
2698
  return check_for_upgrade(check_opt);
1791
2699
}
1792
2700
 
1793
2701
 
1797
2705
  return 0;
1798
2706
}
1799
2707
 
 
2708
 
 
2709
static bool update_frm_version(TABLE *table)
 
2710
{
 
2711
  char path[FN_REFLEN];
 
2712
  File file;
 
2713
  int result= 1;
 
2714
  DBUG_ENTER("update_frm_version");
 
2715
 
 
2716
  /*
 
2717
    No need to update frm version in case table was created or checked
 
2718
    by server with the same version. This also ensures that we do not
 
2719
    update frm version for temporary tables as this code doesn't support
 
2720
    temporary tables.
 
2721
  */
 
2722
  if (table->s->mysql_version == MYSQL_VERSION_ID)
 
2723
    DBUG_RETURN(0);
 
2724
 
 
2725
  strxmov(path, table->s->normalized_path.str, reg_ext, NullS);
 
2726
 
 
2727
  if ((file= my_open(path, O_RDWR|O_BINARY, MYF(MY_WME))) >= 0)
 
2728
  {
 
2729
    uchar version[4];
 
2730
    char *key= table->s->table_cache_key.str;
 
2731
    uint key_length= table->s->table_cache_key.length;
 
2732
    TABLE *entry;
 
2733
    HASH_SEARCH_STATE state;
 
2734
 
 
2735
    int4store(version, MYSQL_VERSION_ID);
 
2736
 
 
2737
    if ((result= my_pwrite(file,(uchar*) version,4,51L,MYF_RW)))
 
2738
      goto err;
 
2739
 
 
2740
    for (entry=(TABLE*) hash_first(&open_cache,(uchar*) key,key_length, &state);
 
2741
         entry;
 
2742
         entry= (TABLE*) hash_next(&open_cache,(uchar*) key,key_length, &state))
 
2743
      entry->s->mysql_version= MYSQL_VERSION_ID;
 
2744
  }
 
2745
err:
 
2746
  if (file >= 0)
 
2747
    VOID(my_close(file,MYF(MY_WME)));
 
2748
  DBUG_RETURN(result);
 
2749
}
 
2750
 
 
2751
 
 
2752
 
1800
2753
/**
1801
2754
  @return
1802
2755
    key if error because of duplicated keys
1803
2756
*/
1804
 
uint32_t handler::get_dup_key(int error)
 
2757
uint handler::get_dup_key(int error)
1805
2758
{
1806
 
  table->file->errkey  = (uint32_t) -1;
 
2759
  DBUG_ENTER("handler::get_dup_key");
 
2760
  table->file->errkey  = (uint) -1;
1807
2761
  if (error == HA_ERR_FOUND_DUPP_KEY || error == HA_ERR_FOREIGN_DUPLICATE_KEY ||
1808
2762
      error == HA_ERR_FOUND_DUPP_UNIQUE ||
1809
2763
      error == HA_ERR_DROP_INDEX_FK)
1810
2764
    info(HA_STATUS_ERRKEY | HA_STATUS_NO_LOCK);
1811
 
  return(table->file->errkey);
1812
 
}
 
2765
  DBUG_RETURN(table->file->errkey);
 
2766
}
 
2767
 
 
2768
 
 
2769
/**
 
2770
  Delete all files with extension from bas_ext().
 
2771
 
 
2772
  @param name           Base name of table
 
2773
 
 
2774
  @note
 
2775
    We assume that the handler may return more extensions than
 
2776
    was actually used for the file.
 
2777
 
 
2778
  @retval
 
2779
    0   If we successfully deleted at least one file from base_ext and
 
2780
    didn't get any other errors than ENOENT
 
2781
  @retval
 
2782
    !0  Error
 
2783
*/
 
2784
int handler::delete_table(const char *name)
 
2785
{
 
2786
  int error= 0;
 
2787
  int enoent_or_zero= ENOENT;                   // Error if no file was deleted
 
2788
  char buff[FN_REFLEN];
 
2789
 
 
2790
  for (const char **ext=bas_ext(); *ext ; ext++)
 
2791
  {
 
2792
    fn_format(buff, name, "", *ext, MY_UNPACK_FILENAME|MY_APPEND_EXT);
 
2793
    if (my_delete_with_symlink(buff, MYF(0)))
 
2794
    {
 
2795
      if ((error= my_errno) != ENOENT)
 
2796
        break;
 
2797
    }
 
2798
    else
 
2799
      enoent_or_zero= 0;                        // No error for ENOENT
 
2800
    error= enoent_or_zero;
 
2801
  }
 
2802
  return error;
 
2803
}
 
2804
 
 
2805
 
 
2806
int handler::rename_table(const char * from, const char * to)
 
2807
{
 
2808
  int error= 0;
 
2809
  for (const char **ext= bas_ext(); *ext ; ext++)
 
2810
  {
 
2811
    if (rename_file_ext(from, to, *ext))
 
2812
    {
 
2813
      if ((error=my_errno) != ENOENT)
 
2814
        break;
 
2815
      error= 0;
 
2816
    }
 
2817
  }
 
2818
  return error;
 
2819
}
 
2820
 
1813
2821
 
1814
2822
void handler::drop_table(const char *name)
1815
2823
{
1816
2824
  close();
1817
 
  engine->deleteTable(ha_session(), name);
 
2825
  delete_table(name);
1818
2826
}
1819
2827
 
1820
2828
 
1821
2829
/**
1822
2830
  Performs checks upon the table.
1823
2831
 
1824
 
  @param session                thread doing CHECK Table operation
 
2832
  @param thd                thread doing CHECK TABLE operation
1825
2833
  @param check_opt          options from the parser
1826
2834
 
1827
2835
  @retval
1829
2837
  @retval
1830
2838
    HA_ADMIN_NEEDS_UPGRADE    Table has structures requiring upgrade
1831
2839
  @retval
1832
 
    HA_ADMIN_NEEDS_ALTER      Table has structures requiring ALTER Table
 
2840
    HA_ADMIN_NEEDS_ALTER      Table has structures requiring ALTER TABLE
1833
2841
  @retval
1834
2842
    HA_ADMIN_NOT_IMPLEMENTED
1835
2843
*/
1836
 
int handler::ha_check(Session *, HA_CHECK_OPT *)
 
2844
int handler::ha_check(THD *thd, HA_CHECK_OPT *check_opt)
1837
2845
{
1838
 
  return HA_ADMIN_OK;
 
2846
  int error;
 
2847
 
 
2848
  if ((table->s->mysql_version >= MYSQL_VERSION_ID) &&
 
2849
      (check_opt->sql_flags & TT_FOR_UPGRADE))
 
2850
    return 0;
 
2851
 
 
2852
  if (table->s->mysql_version < MYSQL_VERSION_ID)
 
2853
  {
 
2854
    if ((error= check_old_types()))
 
2855
      return error;
 
2856
    error= ha_check_for_upgrade(check_opt);
 
2857
    if (error && (error != HA_ADMIN_NEEDS_CHECK))
 
2858
      return error;
 
2859
    if (!error && (check_opt->sql_flags & TT_FOR_UPGRADE))
 
2860
      return 0;
 
2861
  }
 
2862
  if ((error= check(thd, check_opt)))
 
2863
    return error;
 
2864
  return update_frm_version(table);
1839
2865
}
1840
2866
 
1841
2867
/**
1847
2873
void
1848
2874
handler::mark_trx_read_write()
1849
2875
{
1850
 
  Ha_trx_info *ha_info= &ha_session()->ha_data[engine->getSlot()].ha_info[0];
 
2876
  Ha_trx_info *ha_info= &ha_thd()->ha_data[ht->slot].ha_info[0];
1851
2877
  /*
1852
2878
    When a storage engine method is called, the transaction must
1853
2879
    have been started, unless it's a DDL call, for which the
1858
2884
  */
1859
2885
  if (ha_info->is_started())
1860
2886
  {
 
2887
    DBUG_ASSERT(has_transactions());
1861
2888
    /*
1862
2889
      table_share can be NULL in ha_delete_table(). See implementation
1863
2890
      of standalone function ha_delete_table() in sql_base.cc.
1864
2891
    */
1865
 
//    if (table_share == NULL || table_share->tmp_table == NO_TMP_TABLE)
 
2892
    if (table_share == NULL || table_share->tmp_table == NO_TMP_TABLE)
1866
2893
      ha_info->set_trx_read_write();
1867
2894
  }
1868
2895
}
1869
2896
 
 
2897
 
 
2898
/**
 
2899
  Repair table: public interface.
 
2900
 
 
2901
  @sa handler::repair()
 
2902
*/
 
2903
 
 
2904
int handler::ha_repair(THD* thd, HA_CHECK_OPT* check_opt)
 
2905
{
 
2906
  int result;
 
2907
 
 
2908
  mark_trx_read_write();
 
2909
 
 
2910
  if ((result= repair(thd, check_opt)))
 
2911
    return result;
 
2912
  return update_frm_version(table);
 
2913
}
 
2914
 
 
2915
 
1870
2916
/**
1871
2917
  Bulk update row: public interface.
1872
2918
 
1874
2920
*/
1875
2921
 
1876
2922
int
1877
 
handler::ha_bulk_update_row(const unsigned char *old_data, unsigned char *new_data,
1878
 
                            uint32_t *dup_key_found)
 
2923
handler::ha_bulk_update_row(const uchar *old_data, uchar *new_data,
 
2924
                            uint *dup_key_found)
1879
2925
{
1880
2926
  mark_trx_read_write();
1881
2927
 
1920
2966
*/
1921
2967
 
1922
2968
int
1923
 
handler::ha_optimize(Session* session, HA_CHECK_OPT* check_opt)
 
2969
handler::ha_optimize(THD* thd, HA_CHECK_OPT* check_opt)
1924
2970
{
1925
2971
  mark_trx_read_write();
1926
2972
 
1927
 
  return optimize(session, check_opt);
 
2973
  return optimize(thd, check_opt);
1928
2974
}
1929
2975
 
1930
2976
 
1935
2981
*/
1936
2982
 
1937
2983
int
1938
 
handler::ha_analyze(Session* session, HA_CHECK_OPT* check_opt)
1939
 
{
1940
 
  mark_trx_read_write();
1941
 
 
1942
 
  return analyze(session, check_opt);
1943
 
}
 
2984
handler::ha_analyze(THD* thd, HA_CHECK_OPT* check_opt)
 
2985
{
 
2986
  mark_trx_read_write();
 
2987
 
 
2988
  return analyze(thd, check_opt);
 
2989
}
 
2990
 
 
2991
 
 
2992
/**
 
2993
  Check and repair table: public interface.
 
2994
 
 
2995
  @sa handler::check_and_repair()
 
2996
*/
 
2997
 
 
2998
bool
 
2999
handler::ha_check_and_repair(THD *thd)
 
3000
{
 
3001
  mark_trx_read_write();
 
3002
 
 
3003
  return check_and_repair(thd);
 
3004
}
 
3005
 
1944
3006
 
1945
3007
/**
1946
3008
  Disable indexes: public interface.
1949
3011
*/
1950
3012
 
1951
3013
int
1952
 
handler::ha_disable_indexes(uint32_t mode)
 
3014
handler::ha_disable_indexes(uint mode)
1953
3015
{
1954
3016
  mark_trx_read_write();
1955
3017
 
1964
3026
*/
1965
3027
 
1966
3028
int
1967
 
handler::ha_enable_indexes(uint32_t mode)
 
3029
handler::ha_enable_indexes(uint mode)
1968
3030
{
1969
3031
  mark_trx_read_write();
1970
3032
 
1979
3041
*/
1980
3042
 
1981
3043
int
1982
 
handler::ha_discard_or_import_tablespace(bool discard)
 
3044
handler::ha_discard_or_import_tablespace(my_bool discard)
1983
3045
{
1984
3046
  mark_trx_read_write();
1985
3047
 
2003
3065
  prepare_for_alter();
2004
3066
}
2005
3067
 
 
3068
 
 
3069
/**
 
3070
  Rename table: public interface.
 
3071
 
 
3072
  @sa handler::rename_table()
 
3073
*/
 
3074
 
 
3075
int
 
3076
handler::ha_rename_table(const char *from, const char *to)
 
3077
{
 
3078
  mark_trx_read_write();
 
3079
 
 
3080
  return rename_table(from, to);
 
3081
}
 
3082
 
 
3083
 
 
3084
/**
 
3085
  Delete table: public interface.
 
3086
 
 
3087
  @sa handler::delete_table()
 
3088
*/
 
3089
 
 
3090
int
 
3091
handler::ha_delete_table(const char *name)
 
3092
{
 
3093
  mark_trx_read_write();
 
3094
 
 
3095
  return delete_table(name);
 
3096
}
 
3097
 
 
3098
 
2006
3099
/**
2007
3100
  Drop table in the engine: public interface.
2008
3101
 
2017
3110
  return drop_table(name);
2018
3111
}
2019
3112
 
 
3113
 
 
3114
/**
 
3115
  Create a table in the engine: public interface.
 
3116
 
 
3117
  @sa handler::create()
 
3118
*/
 
3119
 
 
3120
int
 
3121
handler::ha_create(const char *name, TABLE *form, HA_CREATE_INFO *info)
 
3122
{
 
3123
  mark_trx_read_write();
 
3124
 
 
3125
  return create(name, form, info);
 
3126
}
 
3127
 
 
3128
 
 
3129
/**
 
3130
  Create handler files for CREATE TABLE: public interface.
 
3131
 
 
3132
  @sa handler::create_handler_files()
 
3133
*/
 
3134
 
 
3135
int
 
3136
handler::ha_create_handler_files(const char *name, const char *old_name,
 
3137
                        int action_flag, HA_CREATE_INFO *info)
 
3138
{
 
3139
  mark_trx_read_write();
 
3140
 
 
3141
  return create_handler_files(name, old_name, action_flag, info);
 
3142
}
 
3143
 
 
3144
 
2020
3145
/**
2021
3146
  Tell the storage engine that it is allowed to "disable transaction" in the
2022
3147
  handler. It is a hint that ACID is not required - it is used in NDB for
2023
 
  ALTER Table, for example, when data are copied to temporary table.
 
3148
  ALTER TABLE, for example, when data are copied to temporary table.
2024
3149
  A storage engine may treat this hint any way it likes. NDB for example
2025
3150
  starts to commit every now and then automatically.
2026
3151
  This hint can be safely ignored.
2027
3152
*/
2028
 
int ha_enable_transaction(Session *session, bool on)
 
3153
int ha_enable_transaction(THD *thd, bool on)
2029
3154
{
2030
 
  int error= 0;
 
3155
  int error=0;
 
3156
  DBUG_ENTER("ha_enable_transaction");
 
3157
  DBUG_PRINT("enter", ("on: %d", (int) on));
2031
3158
 
2032
 
  if ((session->transaction.on= on))
 
3159
  if ((thd->transaction.on= on))
2033
3160
  {
2034
3161
    /*
2035
3162
      Now all storage engines should have transaction handling enabled.
2037
3164
      is an optimization hint that storage engine is free to ignore.
2038
3165
      So, let's commit an open transaction (if any) now.
2039
3166
    */
2040
 
    if (!(error= ha_commit_trans(session, 0)))
2041
 
      if (! session->endTransaction(COMMIT))
2042
 
        error= 1;
2043
 
 
 
3167
    if (!(error= ha_commit_trans(thd, 0)))
 
3168
      error= end_trans(thd, COMMIT);
2044
3169
  }
2045
 
  return error;
 
3170
  DBUG_RETURN(error);
2046
3171
}
2047
3172
 
2048
 
int handler::index_next_same(unsigned char *buf, const unsigned char *key, uint32_t keylen)
 
3173
int handler::index_next_same(uchar *buf, const uchar *key, uint keylen)
2049
3174
{
2050
3175
  int error;
 
3176
  DBUG_ENTER("index_next_same");
2051
3177
  if (!(error=index_next(buf)))
2052
3178
  {
2053
3179
    my_ptrdiff_t ptrdiff= buf - table->record[0];
2054
 
    unsigned char *save_record_0= NULL;
 
3180
    uchar *save_record_0= NULL;
2055
3181
    KEY *key_info= NULL;
2056
3182
    KEY_PART_INFO *key_part;
2057
3183
    KEY_PART_INFO *key_part_end= NULL;
2073
3199
      key_part_end= key_part + key_info->key_parts;
2074
3200
      for (; key_part < key_part_end; key_part++)
2075
3201
      {
2076
 
        assert(key_part->field);
 
3202
        DBUG_ASSERT(key_part->field);
2077
3203
        key_part->field->move_field_offset(ptrdiff);
2078
3204
      }
2079
3205
    }
2092
3218
        key_part->field->move_field_offset(-ptrdiff);
2093
3219
    }
2094
3220
  }
2095
 
  return error;
 
3221
  DBUG_RETURN(error);
2096
3222
}
2097
3223
 
2098
3224
 
2100
3226
** Some general functions that isn't in the handler class
2101
3227
****************************************************************************/
2102
3228
 
 
3229
/**
 
3230
  Initiates table-file and calls appropriate database-creator.
 
3231
 
 
3232
  @retval
 
3233
   0  ok
 
3234
  @retval
 
3235
   1  error
 
3236
*/
 
3237
int ha_create_table(THD *thd, const char *path,
 
3238
                    const char *db, const char *table_name,
 
3239
                    HA_CREATE_INFO *create_info,
 
3240
                    bool update_create_info)
 
3241
{
 
3242
  int error= 1;
 
3243
  TABLE table;
 
3244
  char name_buff[FN_REFLEN];
 
3245
  const char *name;
 
3246
  TABLE_SHARE share;
 
3247
  DBUG_ENTER("ha_create_table");
 
3248
  
 
3249
  init_tmp_table_share(thd, &share, db, 0, table_name, path);
 
3250
  if (open_table_def(thd, &share, 0) ||
 
3251
      open_table_from_share(thd, &share, "", 0, (uint) READ_ALL, 0, &table,
 
3252
                            OTM_CREATE))
 
3253
    goto err;
 
3254
 
 
3255
  if (update_create_info)
 
3256
    update_create_info_from_table(create_info, &table);
 
3257
 
 
3258
  name= check_lowercase_names(table.file, share.path.str, name_buff);
 
3259
 
 
3260
  error= table.file->ha_create(name, &table, create_info);
 
3261
  VOID(closefrm(&table, 0));
 
3262
  if (error)
 
3263
  {
 
3264
    strxmov(name_buff, db, ".", table_name, NullS);
 
3265
    my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), name_buff, error);
 
3266
  }
 
3267
err:
 
3268
  free_table_share(&share);
 
3269
  DBUG_RETURN(error != 0);
 
3270
}
 
3271
 
 
3272
/**
 
3273
  Try to discover table from engine.
 
3274
 
 
3275
  @note
 
3276
    If found, write the frm file to disk.
 
3277
 
 
3278
  @retval
 
3279
  -1    Table did not exists
 
3280
  @retval
 
3281
   0    Table created ok
 
3282
  @retval
 
3283
   > 0  Error, table existed but could not be created
 
3284
*/
 
3285
int ha_create_table_from_engine(THD* thd, const char *db, const char *name)
 
3286
{
 
3287
  int error;
 
3288
  uchar *frmblob;
 
3289
  size_t frmlen;
 
3290
  char path[FN_REFLEN];
 
3291
  HA_CREATE_INFO create_info;
 
3292
  TABLE table;
 
3293
  TABLE_SHARE share;
 
3294
  DBUG_ENTER("ha_create_table_from_engine");
 
3295
  DBUG_PRINT("enter", ("name '%s'.'%s'", db, name));
 
3296
 
 
3297
  bzero((uchar*) &create_info,sizeof(create_info));
 
3298
  if ((error= ha_discover(thd, db, name, &frmblob, &frmlen)))
 
3299
  {
 
3300
    /* Table could not be discovered and thus not created */
 
3301
    DBUG_RETURN(error);
 
3302
  }
 
3303
 
 
3304
  /*
 
3305
    Table exists in handler and could be discovered
 
3306
    frmblob and frmlen are set, write the frm to disk
 
3307
  */
 
3308
 
 
3309
  build_table_filename(path, FN_REFLEN-1, db, name, "", 0);
 
3310
  // Save the frm file
 
3311
  error= writefrm(path, frmblob, frmlen);
 
3312
  my_free(frmblob, MYF(0));
 
3313
  if (error)
 
3314
    DBUG_RETURN(2);
 
3315
 
 
3316
  init_tmp_table_share(thd, &share, db, 0, name, path);
 
3317
  if (open_table_def(thd, &share, 0))
 
3318
  {
 
3319
    DBUG_RETURN(3);
 
3320
  }
 
3321
  if (open_table_from_share(thd, &share, "" ,0, 0, 0, &table, OTM_OPEN))
 
3322
  {
 
3323
    free_table_share(&share);
 
3324
    DBUG_RETURN(3);
 
3325
  }
 
3326
 
 
3327
  update_create_info_from_table(&create_info, &table);
 
3328
  create_info.table_options|= HA_OPTION_CREATE_FROM_ENGINE;
 
3329
 
 
3330
  check_lowercase_names(table.file, path, path);
 
3331
  error=table.file->ha_create(path, &table, &create_info);
 
3332
  VOID(closefrm(&table, 1));
 
3333
 
 
3334
  DBUG_RETURN(error != 0);
 
3335
}
2103
3336
 
2104
3337
void st_ha_check_opt::init()
2105
3338
{
2106
 
  flags= 0; 
2107
 
  use_frm= false;
 
3339
  flags= sql_flags= 0;
 
3340
  sort_buffer_size = current_thd->variables.myisam_sort_buff_size;
2108
3341
}
2109
3342
 
2110
3343
 
2121
3354
/**
2122
3355
  Init a key cache if it has not been initied before.
2123
3356
*/
2124
 
int ha_init_key_cache(const char *,
2125
 
                      KEY_CACHE *key_cache)
 
3357
int ha_init_key_cache(const char *name, KEY_CACHE *key_cache)
2126
3358
{
 
3359
  DBUG_ENTER("ha_init_key_cache");
 
3360
 
2127
3361
  if (!key_cache->key_cache_inited)
2128
3362
  {
2129
3363
    pthread_mutex_lock(&LOCK_global_system_variables);
2130
 
    uint32_t tmp_buff_size= (uint32_t) key_cache->param_buff_size;
2131
 
    uint32_t tmp_block_size= (uint32_t) key_cache->param_block_size;
2132
 
    uint32_t division_limit= key_cache->param_division_limit;
2133
 
    uint32_t age_threshold=  key_cache->param_age_threshold;
 
3364
    ulong tmp_buff_size= (ulong) key_cache->param_buff_size;
 
3365
    uint tmp_block_size= (uint) key_cache->param_block_size;
 
3366
    uint division_limit= key_cache->param_division_limit;
 
3367
    uint age_threshold=  key_cache->param_age_threshold;
2134
3368
    pthread_mutex_unlock(&LOCK_global_system_variables);
2135
 
    return(!init_key_cache(key_cache,
 
3369
    DBUG_RETURN(!init_key_cache(key_cache,
2136
3370
                                tmp_block_size,
2137
3371
                                tmp_buff_size,
2138
3372
                                division_limit, age_threshold));
2139
3373
  }
2140
 
  return 0;
 
3374
  DBUG_RETURN(0);
2141
3375
}
2142
3376
 
2143
3377
 
2146
3380
*/
2147
3381
int ha_resize_key_cache(KEY_CACHE *key_cache)
2148
3382
{
 
3383
  DBUG_ENTER("ha_resize_key_cache");
 
3384
 
2149
3385
  if (key_cache->key_cache_inited)
2150
3386
  {
2151
3387
    pthread_mutex_lock(&LOCK_global_system_variables);
2152
3388
    long tmp_buff_size= (long) key_cache->param_buff_size;
2153
3389
    long tmp_block_size= (long) key_cache->param_block_size;
2154
 
    uint32_t division_limit= key_cache->param_division_limit;
2155
 
    uint32_t age_threshold=  key_cache->param_age_threshold;
 
3390
    uint division_limit= key_cache->param_division_limit;
 
3391
    uint age_threshold=  key_cache->param_age_threshold;
2156
3392
    pthread_mutex_unlock(&LOCK_global_system_variables);
2157
 
    return(!resize_key_cache(key_cache, tmp_block_size,
 
3393
    DBUG_RETURN(!resize_key_cache(key_cache, tmp_block_size,
2158
3394
                                  tmp_buff_size,
2159
3395
                                  division_limit, age_threshold));
2160
3396
  }
2161
 
  return 0;
 
3397
  DBUG_RETURN(0);
2162
3398
}
2163
3399
 
2164
3400
 
2170
3406
  if (key_cache->key_cache_inited)
2171
3407
  {
2172
3408
    pthread_mutex_lock(&LOCK_global_system_variables);
2173
 
    uint32_t division_limit= key_cache->param_division_limit;
2174
 
    uint32_t age_threshold=  key_cache->param_age_threshold;
 
3409
    uint division_limit= key_cache->param_division_limit;
 
3410
    uint age_threshold=  key_cache->param_age_threshold;
2175
3411
    pthread_mutex_unlock(&LOCK_global_system_variables);
2176
3412
    change_key_cache_param(key_cache, division_limit, age_threshold);
2177
3413
  }
2199
3435
 
2200
3436
 
2201
3437
/**
 
3438
  Try to discover one table from handler(s).
 
3439
 
 
3440
  @retval
 
3441
    -1   Table did not exists
 
3442
  @retval
 
3443
    0   OK. In this case *frmblob and *frmlen are set
 
3444
  @retval
 
3445
    >0   error.  frmblob and frmlen may not be set
 
3446
*/
 
3447
struct st_discover_args
 
3448
{
 
3449
  const char *db;
 
3450
  const char *name;
 
3451
  uchar **frmblob; 
 
3452
  size_t *frmlen;
 
3453
};
 
3454
 
 
3455
static my_bool discover_handlerton(THD *thd, plugin_ref plugin,
 
3456
                                   void *arg)
 
3457
{
 
3458
  st_discover_args *vargs= (st_discover_args *)arg;
 
3459
  handlerton *hton= plugin_data(plugin, handlerton *);
 
3460
  if (hton->state == SHOW_OPTION_YES && hton->discover &&
 
3461
      (!(hton->discover(hton, thd, vargs->db, vargs->name, 
 
3462
                        vargs->frmblob, 
 
3463
                        vargs->frmlen))))
 
3464
    return TRUE;
 
3465
 
 
3466
  return FALSE;
 
3467
}
 
3468
 
 
3469
int ha_discover(THD *thd, const char *db, const char *name,
 
3470
                uchar **frmblob, size_t *frmlen)
 
3471
{
 
3472
  int error= -1; // Table does not exist in any handler
 
3473
  DBUG_ENTER("ha_discover");
 
3474
  DBUG_PRINT("enter", ("db: %s, name: %s", db, name));
 
3475
  st_discover_args args= {db, name, frmblob, frmlen};
 
3476
 
 
3477
  if (is_prefix(name,tmp_file_prefix)) /* skip temporary tables */
 
3478
    DBUG_RETURN(error);
 
3479
 
 
3480
  if (plugin_foreach(thd, discover_handlerton,
 
3481
                 MYSQL_STORAGE_ENGINE_PLUGIN, &args))
 
3482
    error= 0;
 
3483
 
 
3484
  if (!error)
 
3485
    status_var_increment(thd->status_var.ha_discover_count);
 
3486
  DBUG_RETURN(error);
 
3487
}
 
3488
 
 
3489
 
 
3490
/**
 
3491
  Call this function in order to give the handler the possiblity
 
3492
  to ask engine if there are any new tables that should be written to disk
 
3493
  or any dropped tables that need to be removed from disk
 
3494
*/
 
3495
struct st_find_files_args
 
3496
{
 
3497
  const char *db;
 
3498
  const char *path;
 
3499
  const char *wild;
 
3500
  bool dir;
 
3501
  List<LEX_STRING> *files;
 
3502
};
 
3503
 
 
3504
/**
 
3505
  Ask handler if the table exists in engine.
 
3506
  @retval
 
3507
    HA_ERR_NO_SUCH_TABLE     Table does not exist
 
3508
  @retval
 
3509
    HA_ERR_TABLE_EXIST       Table exists
 
3510
  @retval
 
3511
    \#                  Error code
 
3512
*/
 
3513
struct st_table_exists_in_engine_args
 
3514
{
 
3515
  const char *db;
 
3516
  const char *name;
 
3517
  int err;
 
3518
};
 
3519
 
 
3520
static my_bool table_exists_in_engine_handlerton(THD *thd, plugin_ref plugin,
 
3521
                                   void *arg)
 
3522
{
 
3523
  st_table_exists_in_engine_args *vargs= (st_table_exists_in_engine_args *)arg;
 
3524
  handlerton *hton= plugin_data(plugin, handlerton *);
 
3525
 
 
3526
  int err= HA_ERR_NO_SUCH_TABLE;
 
3527
 
 
3528
  if (hton->state == SHOW_OPTION_YES && hton->table_exists_in_engine)
 
3529
    err = hton->table_exists_in_engine(hton, thd, vargs->db, vargs->name);
 
3530
 
 
3531
  vargs->err = err;
 
3532
  if (vargs->err == HA_ERR_TABLE_EXIST)
 
3533
    return TRUE;
 
3534
 
 
3535
  return FALSE;
 
3536
}
 
3537
 
 
3538
int ha_table_exists_in_engine(THD* thd, const char* db, const char* name)
 
3539
{
 
3540
  DBUG_ENTER("ha_table_exists_in_engine");
 
3541
  DBUG_PRINT("enter", ("db: %s, name: %s", db, name));
 
3542
  st_table_exists_in_engine_args args= {db, name, HA_ERR_NO_SUCH_TABLE};
 
3543
  plugin_foreach(thd, table_exists_in_engine_handlerton,
 
3544
                 MYSQL_STORAGE_ENGINE_PLUGIN, &args);
 
3545
  DBUG_PRINT("exit", ("error: %d", args.err));
 
3546
  DBUG_RETURN(args.err);
 
3547
}
 
3548
 
 
3549
/**
2202
3550
  Calculate cost of 'index only' scan for given index and number of records
2203
3551
 
2204
3552
  @param keynr    Index number
2219
3567
    Estimated cost of 'index only' scan
2220
3568
*/
2221
3569
 
2222
 
double handler::index_only_read_time(uint32_t keynr, double key_records)
 
3570
double handler::index_only_read_time(uint keynr, double records)
2223
3571
{
2224
 
  uint32_t keys_per_block= (stats.block_size/2/
 
3572
  double read_time;
 
3573
  uint keys_per_block= (stats.block_size/2/
2225
3574
                        (table->key_info[keynr].key_length + ref_length) + 1);
2226
 
  return ((double) (key_records + keys_per_block-1) /
2227
 
          (double) keys_per_block);
 
3575
  read_time=((double) (records + keys_per_block-1) /
 
3576
             (double) keys_per_block);
 
3577
  return read_time;
2228
3578
}
2229
3579
 
2230
3580
 
2251
3601
 
2252
3602
  @note
2253
3603
    This method (or an overriding one in a derived class) must check for
2254
 
    session->killed and return HA_POS_ERROR if it is not zero. This is required
 
3604
    thd->killed and return HA_POS_ERROR if it is not zero. This is required
2255
3605
    for a user to be able to interrupt the calculation by killing the
2256
3606
    connection/query.
2257
3607
 
2263
3613
                  contain scan parameters.
2264
3614
*/
2265
3615
 
2266
 
ha_rows
2267
 
handler::multi_range_read_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
2268
 
                                     void *seq_init_param,
2269
 
                                     uint32_t ,
2270
 
                                     uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
 
3616
ha_rows 
 
3617
handler::multi_range_read_info_const(uint keyno, RANGE_SEQ_IF *seq,
 
3618
                                     void *seq_init_param, uint n_ranges_arg,
 
3619
                                     uint *bufsz, uint *flags, COST_VECT *cost)
2271
3620
{
2272
3621
  KEY_MULTI_RANGE range;
2273
3622
  range_seq_t seq_it;
2274
3623
  ha_rows rows, total_rows= 0;
2275
 
  uint32_t n_ranges=0;
2276
 
  Session *session= current_session;
2277
 
 
 
3624
  uint n_ranges=0;
 
3625
  THD *thd= current_thd;
 
3626
  
2278
3627
  /* Default MRR implementation doesn't need buffer */
2279
3628
  *bufsz= 0;
2280
3629
 
2281
3630
  seq_it= seq->init(seq_init_param, n_ranges, *flags);
2282
3631
  while (!seq->next(seq_it, &range))
2283
3632
  {
2284
 
    if (unlikely(session->killed != 0))
 
3633
    if (unlikely(thd->killed != 0))
2285
3634
      return HA_POS_ERROR;
2286
 
 
 
3635
    
2287
3636
    n_ranges++;
2288
3637
    key_range *min_endp, *max_endp;
2289
3638
    {
2294
3643
      rows= 1; /* there can be at most one row */
2295
3644
    else
2296
3645
    {
2297
 
      if (HA_POS_ERROR == (rows= this->records_in_range(keyno, min_endp,
 
3646
      if (HA_POS_ERROR == (rows= this->records_in_range(keyno, min_endp, 
2298
3647
                                                        max_endp)))
2299
3648
      {
2300
3649
        /* Can't scan one range => can't do MRR scan at all */
2304
3653
    }
2305
3654
    total_rows += rows;
2306
3655
  }
2307
 
 
 
3656
  
2308
3657
  if (total_rows != HA_POS_ERROR)
2309
3658
  {
2310
3659
    /* The following calculation is the same as in multi_range_read_info(): */
2312
3661
    cost->zero();
2313
3662
    cost->avg_io_cost= 1; /* assume random seeks */
2314
3663
    if ((*flags & HA_MRR_INDEX_ONLY) && total_rows > 2)
2315
 
      cost->io_count= index_only_read_time(keyno, (uint32_t)total_rows);
 
3664
      cost->io_count= index_only_read_time(keyno, (uint)total_rows);
2316
3665
    else
2317
3666
      cost->io_count= read_time(keyno, n_ranges, total_rows);
2318
3667
    cost->cpu_cost= (double) total_rows / TIME_FOR_COMPARE + 0.01;
2355
3704
    other Error or can't perform the requested scan
2356
3705
*/
2357
3706
 
2358
 
int handler::multi_range_read_info(uint32_t keyno, uint32_t n_ranges, uint32_t n_rows,
2359
 
                                   uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
 
3707
int handler::multi_range_read_info(uint keyno, uint n_ranges, uint n_rows,
 
3708
                                   uint *bufsz, uint *flags, COST_VECT *cost)
2360
3709
{
2361
3710
  *bufsz= 0; /* Default implementation doesn't need a buffer */
2362
3711
 
2377
3726
/**
2378
3727
  Initialize the MRR scan
2379
3728
 
2380
 
  Initialize the MRR scan. This function may do heavyweight scan
 
3729
  Initialize the MRR scan. This function may do heavyweight scan 
2381
3730
  initialization like row prefetching/sorting/etc (NOTE: but better not do
2382
3731
  it here as we may not need it, e.g. if we never satisfy WHERE clause on
2383
3732
  previous tables. For many implementations it would be natural to do such
2384
3733
  initializations in the first multi_read_range_next() call)
2385
3734
 
2386
3735
  mode is a combination of the following flags: HA_MRR_SORTED,
2387
 
  HA_MRR_INDEX_ONLY, HA_MRR_NO_ASSOCIATION
 
3736
  HA_MRR_INDEX_ONLY, HA_MRR_NO_ASSOCIATION 
2388
3737
 
2389
3738
  @param seq             Range sequence to be traversed
2390
3739
  @param seq_init_param  First parameter for seq->init()
2396
3745
    One must have called index_init() before calling this function. Several
2397
3746
    multi_range_read_init() calls may be made in course of one query.
2398
3747
 
2399
 
    Until WL#2623 is done (see its text, section 3.2), the following will
 
3748
    Until WL#2623 is done (see its text, section 3.2), the following will 
2400
3749
    also hold:
2401
3750
    The caller will guarantee that if "seq->init == mrr_ranges_array_init"
2402
3751
    then seq_init_param is an array of n_ranges KEY_MULTI_RANGE structures.
2403
3752
    This property will only be used by NDB handler until WL#2623 is done.
2404
 
 
 
3753
     
2405
3754
    Buffer memory management is done according to the following scenario:
2406
3755
    The caller allocates the buffer and provides it to the callee by filling
2407
3756
    the members of HANDLER_BUFFER structure.
2417
3766
 
2418
3767
int
2419
3768
handler::multi_range_read_init(RANGE_SEQ_IF *seq_funcs, void *seq_init_param,
2420
 
                               uint32_t n_ranges, uint32_t mode,
2421
 
                               HANDLER_BUFFER *)
 
3769
                               uint n_ranges, uint mode, HANDLER_BUFFER *buf)
2422
3770
{
 
3771
  DBUG_ENTER("handler::multi_range_read_init");
2423
3772
  mrr_iter= seq_funcs->init(seq_init_param, n_ranges, mode);
2424
3773
  mrr_funcs= *seq_funcs;
2425
3774
  mrr_is_output_sorted= test(mode & HA_MRR_SORTED);
2426
 
  mrr_have_range= false;
2427
 
  return 0;
 
3775
  mrr_have_range= FALSE;
 
3776
  DBUG_RETURN(0);
2428
3777
}
2429
3778
 
2430
3779
 
2444
3793
int handler::multi_range_read_next(char **range_info)
2445
3794
{
2446
3795
  int result= 0;
2447
 
  int range_res= 0;
 
3796
  int range_res;
 
3797
  DBUG_ENTER("handler::multi_range_read_next");
2448
3798
 
2449
3799
  if (!mrr_have_range)
2450
3800
  {
2451
 
    mrr_have_range= true;
 
3801
    mrr_have_range= TRUE;
2452
3802
    goto start;
2453
3803
  }
2454
3804
 
2491
3841
  while ((result == HA_ERR_END_OF_FILE) && !range_res);
2492
3842
 
2493
3843
  *range_info= mrr_cur_range.ptr;
2494
 
  return result;
 
3844
  DBUG_PRINT("exit",("handler::multi_range_read_next result %d", result));
 
3845
  DBUG_RETURN(result);
2495
3846
}
2496
3847
 
2497
3848
 
2498
3849
/* **************************************************************************
2499
 
 * DS-MRR implementation
 
3850
 * DS-MRR implementation 
2500
3851
 ***************************************************************************/
2501
3852
 
2502
3853
/**
2517
3868
  @retval other Error
2518
3869
*/
2519
3870
 
2520
 
int DsMrr_impl::dsmrr_init(handler *h_in, KEY *key,
 
3871
int DsMrr_impl::dsmrr_init(handler *h, KEY *key,
2521
3872
                           RANGE_SEQ_IF *seq_funcs, void *seq_init_param,
2522
 
                           uint32_t n_ranges, uint32_t mode, HANDLER_BUFFER *buf)
 
3873
                           uint n_ranges, uint mode, HANDLER_BUFFER *buf)
2523
3874
{
2524
 
  uint32_t elem_size;
2525
 
  uint32_t keyno;
 
3875
  uint elem_size;
 
3876
  uint keyno;
2526
3877
  Item *pushed_cond= NULL;
2527
3878
  handler *new_h2;
2528
 
  keyno= h_in->active_index;
2529
 
  assert(h2 == NULL);
 
3879
  DBUG_ENTER("DsMrr_impl::dsmrr_init");
 
3880
  keyno= h->active_index;
 
3881
  DBUG_ASSERT(h2 == NULL);
2530
3882
  if (mode & HA_MRR_USE_DEFAULT_IMPL || mode & HA_MRR_SORTED)
2531
3883
  {
2532
 
    use_default_impl= true;
2533
 
    return(h_in->handler::multi_range_read_init(seq_funcs, seq_init_param,
 
3884
    use_default_impl= TRUE;
 
3885
    DBUG_RETURN(h->handler::multi_range_read_init(seq_funcs, seq_init_param,
2534
3886
                                                  n_ranges, mode, buf));
2535
3887
  }
2536
3888
  rowids_buf= buf->buffer;
2537
3889
  //psergey-todo: don't add key_length as it is not needed anymore
2538
 
  rowids_buf += key->key_length + h_in->ref_length;
 
3890
  rowids_buf += key->key_length + h->ref_length;
2539
3891
 
2540
3892
  is_mrr_assoc= !test(mode & HA_MRR_NO_ASSOCIATION);
2541
3893
  rowids_buf_end= buf->buffer_end;
2542
 
 
2543
 
  elem_size= h_in->ref_length + (int)is_mrr_assoc * sizeof(void*);
2544
 
  rowids_buf_last= rowids_buf +
 
3894
  
 
3895
  elem_size= h->ref_length + (int)is_mrr_assoc * sizeof(void*);
 
3896
  rowids_buf_last= rowids_buf + 
2545
3897
                      ((rowids_buf_end - rowids_buf)/ elem_size)*
2546
3898
                      elem_size;
2547
3899
  rowids_buf_end= rowids_buf_last;
2548
3900
 
2549
3901
  /* Create a separate handler object to do rndpos() calls. */
2550
 
  Session *session= current_session;
2551
 
  if (!(new_h2= h_in->clone(session->mem_root)) ||
2552
 
      new_h2->ha_external_lock(session, F_RDLCK))
 
3902
  THD *thd= current_thd;
 
3903
  if (!(new_h2= h->clone(thd->mem_root)) || 
 
3904
      new_h2->ha_external_lock(thd, F_RDLCK))
2553
3905
  {
2554
3906
    delete new_h2;
2555
 
    return 1;
 
3907
    DBUG_RETURN(1);
2556
3908
  }
2557
3909
 
2558
 
  if (keyno == h_in->pushed_idx_cond_keyno)
2559
 
    pushed_cond= h_in->pushed_idx_cond;
2560
 
  if (h_in->ha_index_end())
 
3910
  if (keyno == h->pushed_idx_cond_keyno)
 
3911
    pushed_cond= h->pushed_idx_cond;
 
3912
  if (h->ha_index_end())
2561
3913
  {
2562
3914
    new_h2= h2;
2563
3915
    goto error;
2567
3919
  table->prepare_for_position();
2568
3920
  new_h2->extra(HA_EXTRA_KEYREAD);
2569
3921
 
2570
 
  if (h2->ha_index_init(keyno, false) ||
 
3922
  if (h2->ha_index_init(keyno, FALSE) || 
2571
3923
      h2->handler::multi_range_read_init(seq_funcs, seq_init_param, n_ranges,
2572
3924
                                         mode, buf))
2573
3925
    goto error;
2574
 
  use_default_impl= false;
2575
 
 
 
3926
  use_default_impl= FALSE;
 
3927
  
2576
3928
  if (pushed_cond)
2577
3929
    h2->idx_cond_push(keyno, pushed_cond);
2578
3930
  if (dsmrr_fill_buffer(new_h2))
2582
3934
    If the above call has scanned through all intervals in *seq, then
2583
3935
    adjust *buf to indicate that the remaining buffer space will not be used.
2584
3936
  */
2585
 
  if (dsmrr_eof)
 
3937
  if (dsmrr_eof) 
2586
3938
    buf->end_of_used_area= rowids_buf_last;
2587
3939
 
2588
 
  if (h_in->ha_rnd_init(false))
 
3940
  if (h->ha_rnd_init(FALSE))
2589
3941
    goto error;
2590
 
 
2591
 
  return 0;
 
3942
  
 
3943
  DBUG_RETURN(0);
2592
3944
error:
2593
3945
  h2->ha_index_or_rnd_end();
2594
 
  h2->ha_external_lock(session, F_UNLCK);
 
3946
  h2->ha_external_lock(thd, F_UNLCK);
2595
3947
  h2->close();
2596
3948
  delete h2;
2597
 
  return 1;
 
3949
  DBUG_RETURN(1);
2598
3950
}
2599
3951
 
2600
3952
 
2601
3953
void DsMrr_impl::dsmrr_close()
2602
3954
{
 
3955
  DBUG_ENTER("DsMrr_impl::dsmrr_close");
2603
3956
  if (h2)
2604
3957
  {
2605
 
    h2->ha_external_lock(current_session, F_UNLCK);
 
3958
    h2->ha_external_lock(current_thd, F_UNLCK);
2606
3959
    h2->close();
2607
3960
    delete h2;
2608
3961
    h2= NULL;
2609
3962
  }
2610
 
  use_default_impl= true;
 
3963
  use_default_impl= TRUE;
 
3964
  DBUG_VOID_RETURN;
2611
3965
}
2612
3966
 
2613
3967
 
2614
 
static int rowid_cmp(void *h, unsigned char *a, unsigned char *b)
 
3968
static int rowid_cmp(void *h, uchar *a, uchar *b)
2615
3969
{
2616
3970
  return ((handler*)h)->cmp_ref(a, b);
2617
3971
}
2621
3975
  DS-MRR: Fill the buffer with rowids and sort it by rowid
2622
3976
 
2623
3977
  {This is an internal function of DiskSweep MRR implementation}
2624
 
  Scan the MRR ranges and collect ROWIDs (or {ROWID, range_id} pairs) into
2625
 
  buffer. When the buffer is full or scan is completed, sort the buffer by
 
3978
  Scan the MRR ranges and collect ROWIDs (or {ROWID, range_id} pairs) into 
 
3979
  buffer. When the buffer is full or scan is completed, sort the buffer by 
2626
3980
  rowid and return.
2627
 
 
2628
 
  The function assumes that rowids buffer is empty when it is invoked.
2629
 
 
 
3981
  
 
3982
  The function assumes that rowids buffer is empty when it is invoked. 
 
3983
  
2630
3984
  @param h  Table handler
2631
3985
 
2632
3986
  @retval 0      OK, the next portion of rowids is in the buffer,
2634
3988
  @retval other  Error
2635
3989
*/
2636
3990
 
2637
 
int DsMrr_impl::dsmrr_fill_buffer(handler *)
 
3991
int DsMrr_impl::dsmrr_fill_buffer(handler *unused)
2638
3992
{
2639
3993
  char *range_info;
2640
 
  int res = 0;
 
3994
  int res;
 
3995
  DBUG_ENTER("DsMrr_impl::dsmrr_fill_buffer");
2641
3996
 
2642
3997
  rowids_buf_cur= rowids_buf;
2643
 
  while ((rowids_buf_cur < rowids_buf_end) &&
 
3998
  while ((rowids_buf_cur < rowids_buf_end) && 
2644
3999
         !(res= h2->handler::multi_range_read_next(&range_info)))
2645
4000
  {
2646
4001
    /* Put rowid, or {rowid, range_id} pair into the buffer */
2656
4011
  }
2657
4012
 
2658
4013
  if (res && res != HA_ERR_END_OF_FILE)
2659
 
    return res;
 
4014
    DBUG_RETURN(res); 
2660
4015
  dsmrr_eof= test(res == HA_ERR_END_OF_FILE);
2661
4016
 
2662
4017
  /* Sort the buffer contents by rowid */
2663
 
  uint32_t elem_size= h->ref_length + (int)is_mrr_assoc * sizeof(void*);
2664
 
  uint32_t n_rowids= (rowids_buf_cur - rowids_buf) / elem_size;
2665
 
 
 
4018
  uint elem_size= h->ref_length + (int)is_mrr_assoc * sizeof(void*);
 
4019
  uint n_rowids= (rowids_buf_cur - rowids_buf) / elem_size;
 
4020
  
2666
4021
  my_qsort2(rowids_buf, n_rowids, elem_size, (qsort2_cmp)rowid_cmp,
2667
4022
            (void*)h);
2668
4023
  rowids_buf_last= rowids_buf_cur;
2669
4024
  rowids_buf_cur=  rowids_buf;
2670
 
  return 0;
 
4025
  DBUG_RETURN(0);
2671
4026
}
2672
4027
 
2673
4028
 
2675
4030
  DS-MRR implementation: multi_range_read_next() function
2676
4031
*/
2677
4032
 
2678
 
int DsMrr_impl::dsmrr_next(handler *h_in, char **range_info)
 
4033
int DsMrr_impl::dsmrr_next(handler *h, char **range_info)
2679
4034
{
2680
4035
  int res;
2681
 
 
 
4036
  
2682
4037
  if (use_default_impl)
2683
 
    return h_in->handler::multi_range_read_next(range_info);
2684
 
 
 
4038
    return h->handler::multi_range_read_next(range_info);
 
4039
    
2685
4040
  if (rowids_buf_cur == rowids_buf_last)
2686
4041
  {
2687
4042
    if (dsmrr_eof)
2693
4048
    if (res)
2694
4049
      goto end;
2695
4050
  }
2696
 
 
 
4051
  
2697
4052
  /* Return EOF if there are no rowids in the buffer after re-fill attempt */
2698
4053
  if (rowids_buf_cur == rowids_buf_last)
2699
4054
  {
2701
4056
    goto end;
2702
4057
  }
2703
4058
 
2704
 
  res= h_in->rnd_pos(table->record[0], rowids_buf_cur);
2705
 
  rowids_buf_cur += h_in->ref_length;
 
4059
  res= h->rnd_pos(table->record[0], rowids_buf_cur);
 
4060
  rowids_buf_cur += h->ref_length;
2706
4061
  if (is_mrr_assoc)
2707
4062
  {
2708
4063
    memcpy(range_info, rowids_buf_cur, sizeof(void*));
2719
4074
/**
2720
4075
  DS-MRR implementation: multi_range_read_info() function
2721
4076
*/
2722
 
int DsMrr_impl::dsmrr_info(uint32_t keyno, uint32_t n_ranges, uint32_t rows, uint32_t *bufsz,
2723
 
                           uint32_t *flags, COST_VECT *cost)
2724
 
{
 
4077
int DsMrr_impl::dsmrr_info(uint keyno, uint n_ranges, uint rows, uint *bufsz,
 
4078
                           uint *flags, COST_VECT *cost)
 
4079
{  
2725
4080
  int res;
2726
 
  uint32_t def_flags= *flags;
2727
 
  uint32_t def_bufsz= *bufsz;
 
4081
  uint def_flags= *flags;
 
4082
  uint def_bufsz= *bufsz;
2728
4083
 
2729
4084
  /* Get cost/flags/mem_usage of default MRR implementation */
2730
4085
  res= h->handler::multi_range_read_info(keyno, n_ranges, rows, &def_bufsz,
2731
4086
                                         &def_flags, cost);
2732
 
  assert(!res);
 
4087
  DBUG_ASSERT(!res);
2733
4088
 
2734
 
  if ((*flags & HA_MRR_USE_DEFAULT_IMPL) ||
 
4089
  if ((*flags & HA_MRR_USE_DEFAULT_IMPL) || 
2735
4090
      choose_mrr_impl(keyno, rows, &def_flags, &def_bufsz, cost))
2736
4091
  {
2737
4092
    /* Default implementation is choosen */
 
4093
    DBUG_PRINT("info", ("Default MRR implementation choosen"));
2738
4094
    *flags= def_flags;
2739
4095
    *bufsz= def_bufsz;
2740
4096
  }
 
4097
  else
 
4098
  {
 
4099
    DBUG_PRINT("info", ("DS-MRR implementation choosen"));
 
4100
  }
2741
4101
  return 0;
2742
4102
}
2743
4103
 
2746
4106
  DS-MRR Implementation: multi_range_read_info_const() function
2747
4107
*/
2748
4108
 
2749
 
ha_rows DsMrr_impl::dsmrr_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
2750
 
                                 void *seq_init_param, uint32_t n_ranges,
2751
 
                                 uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
 
4109
ha_rows DsMrr_impl::dsmrr_info_const(uint keyno, RANGE_SEQ_IF *seq,
 
4110
                                 void *seq_init_param, uint n_ranges, 
 
4111
                                 uint *bufsz, uint *flags, COST_VECT *cost)
2752
4112
{
2753
4113
  ha_rows rows;
2754
 
  uint32_t def_flags= *flags;
2755
 
  uint32_t def_bufsz= *bufsz;
 
4114
  uint def_flags= *flags;
 
4115
  uint def_bufsz= *bufsz;
2756
4116
  /* Get cost/flags/mem_usage of default MRR implementation */
2757
4117
  rows= h->handler::multi_range_read_info_const(keyno, seq, seq_init_param,
2758
 
                                                n_ranges, &def_bufsz,
 
4118
                                                n_ranges, &def_bufsz, 
2759
4119
                                                &def_flags, cost);
2760
4120
  if (rows == HA_POS_ERROR)
2761
4121
  {
2771
4131
  if ((*flags & HA_MRR_USE_DEFAULT_IMPL) ||
2772
4132
      choose_mrr_impl(keyno, rows, flags, bufsz, cost))
2773
4133
  {
 
4134
    DBUG_PRINT("info", ("Default MRR implementation choosen"));
2774
4135
    *flags= def_flags;
2775
4136
    *bufsz= def_bufsz;
2776
4137
  }
2777
4138
  else
2778
4139
  {
2779
4140
    *flags &= ~HA_MRR_USE_DEFAULT_IMPL;
 
4141
    DBUG_PRINT("info", ("DS-MRR implementation choosen"));
2780
4142
  }
2781
4143
  return rows;
2782
4144
}
2796
4158
    Allow use of DS-MRR in cases where the index has partially-covered
2797
4159
    components but they are not used for scanning.
2798
4160
 
2799
 
  @retval true   Yes
2800
 
  @retval false  No
 
4161
  @retval TRUE   Yes
 
4162
  @retval FALSE  No
2801
4163
*/
2802
4164
 
2803
 
bool DsMrr_impl::key_uses_partial_cols(uint32_t keyno)
 
4165
bool DsMrr_impl::key_uses_partial_cols(uint keyno)
2804
4166
{
2805
4167
  KEY_PART_INFO *kp= table->key_info[keyno].key_part;
2806
4168
  KEY_PART_INFO *kp_end= kp + table->key_info[keyno].key_parts;
2807
4169
  for (; kp != kp_end; kp++)
2808
4170
  {
2809
 
    if (!kp->field->part_of_key.test(keyno))
2810
 
      return true;
 
4171
    if (!kp->field->part_of_key.is_set(keyno))
 
4172
      return TRUE;
2811
4173
  }
2812
 
  return false;
 
4174
  return FALSE;
2813
4175
}
2814
4176
 
2815
4177
 
2832
4194
                OUT  If DS-MRR is choosen, cost of DS-MRR scan
2833
4195
                     else the value is not modified
2834
4196
 
2835
 
  @retval true   Default MRR implementation should be used
2836
 
  @retval false  DS-MRR implementation should be used
 
4197
  @retval TRUE   Default MRR implementation should be used
 
4198
  @retval FALSE  DS-MRR implementation should be used
2837
4199
*/
2838
4200
 
2839
 
bool DsMrr_impl::choose_mrr_impl(uint32_t keyno, ha_rows rows, uint32_t *flags,
2840
 
                                 uint32_t *bufsz, COST_VECT *cost)
 
4201
bool DsMrr_impl::choose_mrr_impl(uint keyno, ha_rows rows, uint *flags,
 
4202
                                 uint *bufsz, COST_VECT *cost)
2841
4203
{
2842
4204
  COST_VECT dsmrr_cost;
2843
4205
  bool res;
2844
 
  Session *session= current_session;
2845
 
  if ((session->variables.optimizer_use_mrr == 2) ||
 
4206
  THD *thd= current_thd;
 
4207
  if ((thd->variables.optimizer_use_mrr == 2) || 
2846
4208
      (*flags & HA_MRR_INDEX_ONLY) || (*flags & HA_MRR_SORTED) ||
2847
 
      (keyno == table->s->primary_key &&
2848
 
       h->primary_key_is_clustered()) ||
 
4209
      (keyno == table->s->primary_key && 
 
4210
       h->primary_key_is_clustered()) || 
2849
4211
       key_uses_partial_cols(keyno))
2850
4212
  {
2851
4213
    /* Use the default implementation */
2852
4214
    *flags |= HA_MRR_USE_DEFAULT_IMPL;
2853
 
    return true;
 
4215
    return TRUE;
2854
4216
  }
2855
 
 
2856
 
  uint32_t add_len= table->key_info[keyno].key_length + h->ref_length;
 
4217
  
 
4218
  uint add_len= table->key_info[keyno].key_length + h->ref_length; 
2857
4219
  *bufsz -= add_len;
2858
4220
  if (get_disk_sweep_mrr_cost(keyno, rows, *flags, bufsz, &dsmrr_cost))
2859
 
    return true;
 
4221
    return TRUE;
2860
4222
  *bufsz += add_len;
2861
 
 
 
4223
  
2862
4224
  bool force_dsmrr;
2863
 
  /*
 
4225
  /* 
2864
4226
    If @@optimizer_use_mrr==force, then set cost of DS-MRR to be minimum of
2865
4227
    DS-MRR and Default implementations cost. This allows one to force use of
2866
4228
    DS-MRR whenever it is applicable without affecting other cost-based
2867
4229
    choices.
2868
4230
  */
2869
 
  if ((force_dsmrr= (session->variables.optimizer_use_mrr == 1)) &&
 
4231
  if ((force_dsmrr= (thd->variables.optimizer_use_mrr == 1)) &&
2870
4232
      dsmrr_cost.total_cost() > cost->total_cost())
2871
4233
    dsmrr_cost= *cost;
2872
4234
 
2875
4237
    *flags &= ~HA_MRR_USE_DEFAULT_IMPL;  /* Use the DS-MRR implementation */
2876
4238
    *flags &= ~HA_MRR_SORTED;          /* We will return unordered output */
2877
4239
    *cost= dsmrr_cost;
2878
 
    res= false;
 
4240
    res= FALSE;
2879
4241
  }
2880
4242
  else
2881
4243
  {
2882
4244
    /* Use the default MRR implementation */
2883
 
    res= true;
 
4245
    res= TRUE;
2884
4246
  }
2885
4247
  return res;
2886
4248
}
2887
4249
 
2888
4250
 
2889
 
static void get_sort_and_sweep_cost(Table *table, ha_rows nrows, COST_VECT *cost);
 
4251
static void get_sort_and_sweep_cost(TABLE *table, ha_rows nrows, COST_VECT *cost);
2890
4252
 
2891
4253
 
2892
4254
/**
2898
4260
  @param buffer_size INOUT  Buffer size
2899
4261
  @param cost        OUT    The cost
2900
4262
 
2901
 
  @retval false  OK
2902
 
  @retval true   Error, DS-MRR cannot be used (the buffer is too small
 
4263
  @retval FALSE  OK
 
4264
  @retval TRUE   Error, DS-MRR cannot be used (the buffer is too small
2903
4265
                 for even 1 rowid)
2904
4266
*/
2905
4267
 
2906
 
bool DsMrr_impl::get_disk_sweep_mrr_cost(uint32_t keynr, ha_rows rows, uint32_t flags,
2907
 
                                         uint32_t *buffer_size, COST_VECT *cost)
 
4268
bool DsMrr_impl::get_disk_sweep_mrr_cost(uint keynr, ha_rows rows, uint flags,
 
4269
                                         uint *buffer_size, COST_VECT *cost)
2908
4270
{
2909
 
  uint32_t max_buff_entries, elem_size;
 
4271
  ulong max_buff_entries, elem_size;
2910
4272
  ha_rows rows_in_full_step, rows_in_last_step;
2911
 
  uint32_t n_full_steps;
 
4273
  uint n_full_steps;
2912
4274
  double index_read_cost;
2913
4275
 
2914
4276
  elem_size= h->ref_length + sizeof(void*) * (!test(flags & HA_MRR_NO_ASSOCIATION));
2915
4277
  max_buff_entries = *buffer_size / elem_size;
2916
4278
 
2917
4279
  if (!max_buff_entries)
2918
 
    return true; /* Buffer has not enough space for even 1 rowid */
 
4280
    return TRUE; /* Buffer has not enough space for even 1 rowid */
2919
4281
 
2920
4282
  /* Number of iterations we'll make with full buffer */
2921
 
  n_full_steps= (uint32_t)floor(rows2double(rows) / max_buff_entries);
2922
 
 
2923
 
  /*
2924
 
    Get numbers of rows we'll be processing in
2925
 
     - non-last sweep, with full buffer
 
4283
  n_full_steps= (uint)floor(rows2double(rows) / max_buff_entries);
 
4284
  
 
4285
  /* 
 
4286
    Get numbers of rows we'll be processing in 
 
4287
     - non-last sweep, with full buffer 
2926
4288
     - last iteration, with non-full buffer
2927
4289
  */
2928
4290
  rows_in_full_step= max_buff_entries;
2929
4291
  rows_in_last_step= rows % max_buff_entries;
2930
 
 
 
4292
  
2931
4293
  /* Adjust buffer size if we expect to use only part of the buffer */
2932
4294
  if (n_full_steps)
2933
4295
  {
2937
4299
  else
2938
4300
  {
2939
4301
    cost->zero();
2940
 
    *buffer_size= max(*buffer_size,
2941
 
                      (uint32_t)(1.2*rows_in_last_step) * elem_size +
 
4302
    *buffer_size= max(*buffer_size, 
 
4303
                      (size_t)(1.2*rows_in_last_step) * elem_size + 
2942
4304
                      h->ref_length + table->key_info[keynr].key_length);
2943
4305
  }
2944
 
 
 
4306
  
2945
4307
  COST_VECT last_step_cost;
2946
4308
  get_sort_and_sweep_cost(table, rows_in_last_step, &last_step_cost);
2947
4309
  cost->add(&last_step_cost);
2948
 
 
 
4310
 
2949
4311
  if (n_full_steps != 0)
2950
4312
    cost->mem_cost= *buffer_size;
2951
4313
  else
2952
4314
    cost->mem_cost= (double)rows_in_last_step * elem_size;
2953
 
 
 
4315
  
2954
4316
  /* Total cost of all index accesses */
2955
4317
  index_read_cost= h->index_only_read_time(keynr, (double)rows);
2956
4318
  cost->add_io(index_read_cost, 1 /* Random seeks */);
2957
 
  return false;
 
4319
  return FALSE;
2958
4320
}
2959
4321
 
2960
4322
 
2961
 
/*
 
4323
/* 
2962
4324
  Get cost of one sort-and-sweep step
2963
4325
 
2964
4326
  SYNOPSIS
2973
4335
     - read #nrows records from table in a sweep.
2974
4336
*/
2975
4337
 
2976
 
static
2977
 
void get_sort_and_sweep_cost(Table *table, ha_rows nrows, COST_VECT *cost)
 
4338
static 
 
4339
void get_sort_and_sweep_cost(TABLE *table, ha_rows nrows, COST_VECT *cost)
2978
4340
{
2979
4341
  if (nrows)
2980
4342
  {
2981
 
    get_sweep_read_cost(table, nrows, false, cost);
 
4343
    get_sweep_read_cost(table, nrows, FALSE, cost);
2982
4344
    /* Add cost of qsort call: n * log2(n) * cost(rowid_comparison) */
2983
4345
    double cmp_op= rows2double(nrows) * (1.0 / TIME_FOR_COMPARE_ROWID);
2984
4346
    if (cmp_op < 3)
3007
4369
  Time to move the disk head is proportional to head travel distance.
3008
4370
 
3009
4371
  Time to wait for the plate to rotate depends on whether the disk head
3010
 
  was moved or not.
 
4372
  was moved or not. 
3011
4373
 
3012
4374
  If disk head wasn't moved, the wait time is proportional to distance
3013
4375
  between the previous block and the block we're reading.
3018
4380
 
3019
4381
  Our cost units are "random disk seeks". The cost of random disk seek is
3020
4382
  actually not a constant, it depends one range of cylinders we're going
3021
 
  to access. We make it constant by introducing a fuzzy concept of "typical
 
4383
  to access. We make it constant by introducing a fuzzy concept of "typical 
3022
4384
  datafile length" (it's fuzzy as it's hard to tell whether it should
3023
4385
  include index file, temp.tables etc). Then random seek cost is:
3024
4386
 
3028
4390
 
3029
4391
  @param table             Table to be accessed
3030
4392
  @param nrows             Number of rows to retrieve
3031
 
  @param interrupted       true <=> Assume that the disk sweep will be
3032
 
                           interrupted by other disk IO. false - otherwise.
 
4393
  @param interrupted       TRUE <=> Assume that the disk sweep will be
 
4394
                           interrupted by other disk IO. FALSE - otherwise.
3033
4395
  @param cost         OUT  The cost.
3034
4396
*/
3035
4397
 
3036
 
void get_sweep_read_cost(Table *table, ha_rows nrows, bool interrupted,
 
4398
void get_sweep_read_cost(TABLE *table, ha_rows nrows, bool interrupted, 
3037
4399
                         COST_VECT *cost)
3038
4400
{
 
4401
  DBUG_ENTER("get_sweep_read_cost");
 
4402
 
3039
4403
  cost->zero();
3040
4404
  if (table->file->primary_key_is_clustered())
3041
4405
  {
3042
4406
    cost->io_count= table->file->read_time(table->s->primary_key,
3043
 
                                           (uint32_t) nrows, nrows);
 
4407
                                           (uint) nrows, nrows);
3044
4408
  }
3045
4409
  else
3046
4410
  {
3047
4411
    double n_blocks=
3048
 
      ceil(uint64_t2double(table->file->stats.data_file_length) / IO_SIZE);
 
4412
      ceil(ulonglong2double(table->file->stats.data_file_length) / IO_SIZE);
3049
4413
    double busy_blocks=
3050
4414
      n_blocks * (1.0 - pow(1.0 - 1.0/n_blocks, rows2double(nrows)));
3051
4415
    if (busy_blocks < 1.0)
3052
4416
      busy_blocks= 1.0;
3053
4417
 
 
4418
    DBUG_PRINT("info",("sweep: nblocks=%g, busy_blocks=%g", n_blocks,
 
4419
                       busy_blocks));
3054
4420
    cost->io_count= busy_blocks;
3055
4421
 
3056
4422
    if (!interrupted)
3060
4426
                          DISK_SEEK_PROP_COST*n_blocks/busy_blocks);
3061
4427
    }
3062
4428
  }
 
4429
  DBUG_PRINT("info",("returning cost=%g", cost->total_cost()));
 
4430
  DBUG_VOID_RETURN;
3063
4431
}
3064
4432
 
3065
4433
 
3088
4456
int handler::read_range_first(const key_range *start_key,
3089
4457
                              const key_range *end_key,
3090
4458
                              bool eq_range_arg,
3091
 
                              bool )
 
4459
                              bool sorted /* ignored */)
3092
4460
{
3093
4461
  int result;
 
4462
  DBUG_ENTER("handler::read_range_first");
3094
4463
 
3095
4464
  eq_range= eq_range_arg;
3096
4465
  end_range= 0;
3111
4480
                           start_key->keypart_map,
3112
4481
                           start_key->flag);
3113
4482
  if (result)
3114
 
    return((result == HA_ERR_KEY_NOT_FOUND)
 
4483
    DBUG_RETURN((result == HA_ERR_KEY_NOT_FOUND) 
3115
4484
                ? HA_ERR_END_OF_FILE
3116
4485
                : result);
3117
4486
 
3118
 
  return (compare_key(end_range) <= 0 ? 0 : HA_ERR_END_OF_FILE);
 
4487
  DBUG_RETURN (compare_key(end_range) <= 0 ? 0 : HA_ERR_END_OF_FILE);
3119
4488
}
3120
4489
 
3121
4490
 
3135
4504
int handler::read_range_next()
3136
4505
{
3137
4506
  int result;
 
4507
  DBUG_ENTER("handler::read_range_next");
3138
4508
 
3139
4509
  if (eq_range)
3140
4510
  {
3141
4511
    /* We trust that index_next_same always gives a row in range */
3142
 
    return(index_next_same(table->record[0],
 
4512
    DBUG_RETURN(index_next_same(table->record[0],
3143
4513
                                end_range->key,
3144
4514
                                end_range->length));
3145
4515
  }
3146
4516
  result= index_next(table->record[0]);
3147
4517
  if (result)
3148
 
    return result;
3149
 
  return(compare_key(end_range) <= 0 ? 0 : HA_ERR_END_OF_FILE);
 
4518
    DBUG_RETURN(result);
 
4519
  DBUG_RETURN(compare_key(end_range) <= 0 ? 0 : HA_ERR_END_OF_FILE);
3150
4520
}
3151
4521
 
3152
4522
 
3193
4563
  return cmp;
3194
4564
}
3195
4565
 
3196
 
int handler::index_read_idx_map(unsigned char * buf, uint32_t index,
3197
 
                                const unsigned char * key,
 
4566
int handler::index_read_idx_map(uchar * buf, uint index, const uchar * key,
3198
4567
                                key_part_map keypart_map,
3199
4568
                                enum ha_rkey_function find_flag)
3200
4569
{
3209
4578
}
3210
4579
 
3211
4580
 
3212
 
static bool stat_print(Session *session, const char *type, uint32_t type_len,
3213
 
                       const char *file, uint32_t file_len,
3214
 
                       const char *status, uint32_t status_len)
3215
 
{
3216
 
  Protocol *protocol= session->protocol;
3217
 
  protocol->prepareForResend();
3218
 
  protocol->store(type, type_len);
3219
 
  protocol->store(file, file_len);
3220
 
  protocol->store(status, status_len);
 
4581
/**
 
4582
  Returns a list of all known extensions.
 
4583
 
 
4584
    No mutexes, worst case race is a minor surplus memory allocation
 
4585
    We have to recreate the extension map if mysqld is restarted (for example
 
4586
    within libmysqld)
 
4587
 
 
4588
  @retval
 
4589
    pointer             pointer to TYPELIB structure
 
4590
*/
 
4591
static my_bool exts_handlerton(THD *unused, plugin_ref plugin,
 
4592
                               void *arg)
 
4593
{
 
4594
  List<char> *found_exts= (List<char> *) arg;
 
4595
  handlerton *hton= plugin_data(plugin, handlerton *);
 
4596
  handler *file;
 
4597
  if (hton->state == SHOW_OPTION_YES && hton->create &&
 
4598
      (file= hton->create(hton, (TABLE_SHARE*) 0, current_thd->mem_root)))
 
4599
  {
 
4600
    List_iterator_fast<char> it(*found_exts);
 
4601
    const char **ext, *old_ext;
 
4602
 
 
4603
    for (ext= file->bas_ext(); *ext; ext++)
 
4604
    {
 
4605
      while ((old_ext= it++))
 
4606
      {
 
4607
        if (!strcmp(old_ext, *ext))
 
4608
          break;
 
4609
      }
 
4610
      if (!old_ext)
 
4611
        found_exts->push_back((char *) *ext);
 
4612
 
 
4613
      it.rewind();
 
4614
    }
 
4615
    delete file;
 
4616
  }
 
4617
  return FALSE;
 
4618
}
 
4619
 
 
4620
TYPELIB *ha_known_exts(void)
 
4621
{
 
4622
  if (!known_extensions.type_names || mysys_usage_id != known_extensions_id)
 
4623
  {
 
4624
    List<char> found_exts;
 
4625
    const char **ext, *old_ext;
 
4626
 
 
4627
    known_extensions_id= mysys_usage_id;
 
4628
 
 
4629
    plugin_foreach(NULL, exts_handlerton,
 
4630
                   MYSQL_STORAGE_ENGINE_PLUGIN, &found_exts);
 
4631
 
 
4632
    ext= (const char **) my_once_alloc(sizeof(char *)*
 
4633
                                       (found_exts.elements+1),
 
4634
                                       MYF(MY_WME | MY_FAE));
 
4635
 
 
4636
    DBUG_ASSERT(ext != 0);
 
4637
    known_extensions.count= found_exts.elements;
 
4638
    known_extensions.type_names= ext;
 
4639
 
 
4640
    List_iterator_fast<char> it(found_exts);
 
4641
    while ((old_ext= it++))
 
4642
      *ext++= old_ext;
 
4643
    *ext= 0;
 
4644
  }
 
4645
  return &known_extensions;
 
4646
}
 
4647
 
 
4648
 
 
4649
static bool stat_print(THD *thd, const char *type, uint type_len,
 
4650
                       const char *file, uint file_len,
 
4651
                       const char *status, uint status_len)
 
4652
{
 
4653
  Protocol *protocol= thd->protocol;
 
4654
  protocol->prepare_for_resend();
 
4655
  protocol->store(type, type_len, system_charset_info);
 
4656
  protocol->store(file, file_len, system_charset_info);
 
4657
  protocol->store(status, status_len, system_charset_info);
3221
4658
  if (protocol->write())
3222
 
    return true;
3223
 
  return false;
 
4659
    return TRUE;
 
4660
  return FALSE;
3224
4661
}
3225
4662
 
3226
 
bool ha_show_status(Session *session, StorageEngine *engine, enum ha_stat_type stat)
 
4663
bool ha_show_status(THD *thd, handlerton *db_type, enum ha_stat_type stat)
3227
4664
{
3228
4665
  List<Item> field_list;
3229
 
  Protocol *protocol= session->protocol;
 
4666
  Protocol *protocol= thd->protocol;
3230
4667
  bool result;
3231
4668
 
3232
4669
  field_list.push_back(new Item_empty_string("Type",10));
3233
4670
  field_list.push_back(new Item_empty_string("Name",FN_REFLEN));
3234
4671
  field_list.push_back(new Item_empty_string("Status",10));
3235
4672
 
3236
 
  if (protocol->sendFields(&field_list,
3237
 
                           Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
3238
 
    return true;
 
4673
  if (protocol->send_fields(&field_list,
 
4674
                            Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
 
4675
    return TRUE;
3239
4676
 
3240
 
  result= engine->show_status(session, stat_print, stat) ? 1 : 0;
 
4677
  result= db_type->show_status &&
 
4678
    db_type->show_status(db_type, thd, stat_print, stat) ? 1 : 0;
3241
4679
 
3242
4680
  if (!result)
3243
 
    session->my_eof();
 
4681
    my_eof(thd);
3244
4682
  return result;
3245
4683
}
3246
4684
 
3257
4695
  - table is not mysql.event
3258
4696
*/
3259
4697
 
3260
 
static bool log_row_for_replication(Table* table,
3261
 
                           const unsigned char *before_record,
3262
 
                           const unsigned char *after_record)
3263
 
{
3264
 
  Session *const session= table->in_use;
3265
 
 
3266
 
  switch (session->lex->sql_command)
3267
 
  {
3268
 
  case SQLCOM_REPLACE:
3269
 
  case SQLCOM_INSERT:
3270
 
  case SQLCOM_REPLACE_SELECT:
3271
 
  case SQLCOM_INSERT_SELECT:
3272
 
  case SQLCOM_CREATE_TABLE:
3273
 
    transaction_services.insertRecord(session, table);
3274
 
    break;
3275
 
 
3276
 
  case SQLCOM_UPDATE:
3277
 
  case SQLCOM_UPDATE_MULTI:
3278
 
    transaction_services.updateRecord(session, table, before_record, after_record);
3279
 
    break;
3280
 
 
3281
 
  case SQLCOM_DELETE:
3282
 
  case SQLCOM_DELETE_MULTI:
3283
 
    transaction_services.deleteRecord(session, table);
3284
 
    break;
3285
 
 
 
4698
static bool check_table_binlog_row_based(THD *thd, TABLE *table)
 
4699
{
 
4700
  if (table->s->cached_row_logging_check == -1)
 
4701
  {
 
4702
    int const check(table->s->tmp_table == NO_TMP_TABLE &&
 
4703
                    binlog_filter->db_ok(table->s->db.str));
 
4704
    table->s->cached_row_logging_check= check;
 
4705
  }
 
4706
 
 
4707
  DBUG_ASSERT(table->s->cached_row_logging_check == 0 ||
 
4708
              table->s->cached_row_logging_check == 1);
 
4709
 
 
4710
  return (thd->current_stmt_binlog_row_based &&
 
4711
          table->s->cached_row_logging_check &&
 
4712
          (thd->options & OPTION_BIN_LOG) &&
 
4713
          mysql_bin_log.is_open());
 
4714
}
 
4715
 
 
4716
 
 
4717
/**
 
4718
   Write table maps for all (manually or automatically) locked tables
 
4719
   to the binary log.
 
4720
 
 
4721
   This function will generate and write table maps for all tables
 
4722
   that are locked by the thread 'thd'.  Either manually locked
 
4723
   (stored in THD::locked_tables) and automatically locked (stored
 
4724
   in THD::lock) are considered.
 
4725
 
 
4726
   @param thd     Pointer to THD structure
 
4727
 
 
4728
   @retval 0   All OK
 
4729
   @retval 1   Failed to write all table maps
 
4730
 
 
4731
   @sa
 
4732
       THD::lock
 
4733
       THD::locked_tables
 
4734
*/
 
4735
 
 
4736
static int write_locked_table_maps(THD *thd)
 
4737
{
 
4738
  DBUG_ENTER("write_locked_table_maps");
 
4739
  DBUG_PRINT("enter", ("thd: 0x%lx  thd->lock: 0x%lx  thd->locked_tables: 0x%lx  "
 
4740
                       "thd->extra_lock: 0x%lx",
 
4741
                       (long) thd, (long) thd->lock,
 
4742
                       (long) thd->locked_tables, (long) thd->extra_lock));
 
4743
 
 
4744
  if (thd->get_binlog_table_maps() == 0)
 
4745
  {
 
4746
    MYSQL_LOCK *locks[3];
 
4747
    locks[0]= thd->extra_lock;
 
4748
    locks[1]= thd->lock;
 
4749
    locks[2]= thd->locked_tables;
 
4750
    for (uint i= 0 ; i < sizeof(locks)/sizeof(*locks) ; ++i )
 
4751
    {
 
4752
      MYSQL_LOCK const *const lock= locks[i];
 
4753
      if (lock == NULL)
 
4754
        continue;
 
4755
 
 
4756
      TABLE **const end_ptr= lock->table + lock->table_count;
 
4757
      for (TABLE **table_ptr= lock->table ; 
 
4758
           table_ptr != end_ptr ;
 
4759
           ++table_ptr)
 
4760
      {
 
4761
        TABLE *const table= *table_ptr;
 
4762
        DBUG_PRINT("info", ("Checking table %s", table->s->table_name.str));
 
4763
        if (table->current_lock == F_WRLCK &&
 
4764
            check_table_binlog_row_based(thd, table))
 
4765
        {
 
4766
          int const has_trans= table->file->has_transactions();
 
4767
          int const error= thd->binlog_write_table_map(table, has_trans);
 
4768
          /*
 
4769
            If an error occurs, it is the responsibility of the caller to
 
4770
            roll back the transaction.
 
4771
          */
 
4772
          if (unlikely(error))
 
4773
            DBUG_RETURN(1);
 
4774
        }
 
4775
      }
 
4776
    }
 
4777
  }
 
4778
  DBUG_RETURN(0);
 
4779
}
 
4780
 
 
4781
 
 
4782
typedef bool Log_func(THD*, TABLE*, bool, const uchar*, const uchar*);
 
4783
 
 
4784
static int binlog_log_row(TABLE* table,
 
4785
                          const uchar *before_record,
 
4786
                          const uchar *after_record,
 
4787
                          Log_func *log_func)
 
4788
{
 
4789
  if (table->no_replicate)
 
4790
    return 0;
 
4791
  bool error= 0;
 
4792
  THD *const thd= table->in_use;
 
4793
 
 
4794
  if (check_table_binlog_row_based(thd, table))
 
4795
  {
 
4796
    DBUG_DUMP("read_set 10", (uchar*) table->read_set->bitmap,
 
4797
              (table->s->fields + 7) / 8);
3286
4798
    /*
3287
 
      For everything else we ignore the event (since it just involves a temp table)
 
4799
      If there are no table maps written to the binary log, this is
 
4800
      the first row handled in this statement. In that case, we need
 
4801
      to write table maps for all locked tables to the binary log.
3288
4802
    */
3289
 
  default:
3290
 
    break;
 
4803
    if (likely(!(error= write_locked_table_maps(thd))))
 
4804
    {
 
4805
      bool const has_trans= table->file->has_transactions();
 
4806
      error= (*log_func)(thd, table, has_trans, before_record, after_record);
 
4807
    }
3291
4808
  }
3292
 
 
3293
 
  return false; //error;
 
4809
  return error ? HA_ERR_RBR_LOGGING_FAILED : 0;
3294
4810
}
3295
4811
 
3296
 
int handler::ha_external_lock(Session *session, int lock_type)
 
4812
int handler::ha_external_lock(THD *thd, int lock_type)
3297
4813
{
 
4814
  DBUG_ENTER("handler::ha_external_lock");
3298
4815
  /*
3299
4816
    Whether this is lock or unlock, this should be true, and is to verify that
3300
4817
    if get_auto_increment() was called (thus may have reserved intervals or
3301
4818
    taken a table lock), ha_release_auto_increment() was too.
3302
4819
  */
3303
 
  assert(next_insert_id == 0);
 
4820
  DBUG_ASSERT(next_insert_id == 0);
3304
4821
 
3305
4822
  /*
3306
4823
    We cache the table flags if the locking succeeded. Otherwise, we
3307
4824
    keep them as they were when they were fetched in ha_open().
3308
4825
  */
3309
 
  DRIZZLE_EXTERNAL_LOCK(lock_type);
 
4826
  MYSQL_EXTERNAL_LOCK(lock_type);
3310
4827
 
3311
 
  int error= external_lock(session, lock_type);
 
4828
  int error= external_lock(thd, lock_type);
3312
4829
  if (error == 0)
3313
4830
    cached_table_flags= table_flags();
3314
 
  return error;
 
4831
  DBUG_RETURN(error);
3315
4832
}
3316
4833
 
3317
4834
 
3320
4837
*/
3321
4838
int handler::ha_reset()
3322
4839
{
 
4840
  DBUG_ENTER("ha_reset");
3323
4841
  /* Check that we have called all proper deallocation functions */
3324
 
  assert((unsigned char*) table->def_read_set.bitmap +
 
4842
  DBUG_ASSERT((uchar*) table->def_read_set.bitmap +
3325
4843
              table->s->column_bitmap_size ==
3326
 
              (unsigned char*) table->def_write_set.bitmap);
3327
 
  assert(bitmap_is_set_all(&table->s->all_set));
3328
 
  assert(table->key_read == 0);
 
4844
              (uchar*) table->def_write_set.bitmap);
 
4845
  DBUG_ASSERT(bitmap_is_set_all(&table->s->all_set));
 
4846
  DBUG_ASSERT(table->key_read == 0);
3329
4847
  /* ensure that ha_index_end / ha_rnd_end has been called */
3330
 
  assert(inited == NONE);
 
4848
  DBUG_ASSERT(inited == NONE);
3331
4849
  /* Free cache used by filesort */
3332
4850
  free_io_cache(table);
3333
4851
  /* reset the bitmaps to point to defaults */
3334
4852
  table->default_column_bitmaps();
3335
 
  return(reset());
 
4853
  DBUG_RETURN(reset());
3336
4854
}
3337
4855
 
3338
4856
 
3339
 
int handler::ha_write_row(unsigned char *buf)
 
4857
int handler::ha_write_row(uchar *buf)
3340
4858
{
3341
4859
  int error;
3342
 
  DRIZZLE_INSERT_ROW_START();
3343
 
 
3344
 
  /* 
3345
 
   * If we have a timestamp column, update it to the current time 
3346
 
   * 
3347
 
   * @TODO Technically, the below two lines can be take even further out of the
3348
 
   * handler interface and into the fill_record() method.
3349
 
   */
3350
 
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
3351
 
    table->timestamp_field->set_time();
 
4860
  Log_func *log_func= Write_rows_log_event::binlog_row_logging_function;
 
4861
  DBUG_ENTER("handler::ha_write_row");
 
4862
  MYSQL_INSERT_ROW_START();
3352
4863
 
3353
4864
  mark_trx_read_write();
3354
4865
 
3355
4866
  if (unlikely(error= write_row(buf)))
3356
 
    return error;
3357
 
 
3358
 
  if (unlikely(log_row_for_replication(table, 0, buf)))
3359
 
    return HA_ERR_RBR_LOGGING_FAILED; /* purecov: inspected */
3360
 
 
3361
 
  DRIZZLE_INSERT_ROW_END();
3362
 
  return 0;
 
4867
    DBUG_RETURN(error);
 
4868
  if (unlikely(error= binlog_log_row(table, 0, buf, log_func)))
 
4869
    DBUG_RETURN(error); /* purecov: inspected */
 
4870
  MYSQL_INSERT_ROW_END();
 
4871
  DBUG_RETURN(0);
3363
4872
}
3364
4873
 
3365
4874
 
3366
 
int handler::ha_update_row(const unsigned char *old_data, unsigned char *new_data)
 
4875
int handler::ha_update_row(const uchar *old_data, uchar *new_data)
3367
4876
{
3368
4877
  int error;
 
4878
  Log_func *log_func= Update_rows_log_event::binlog_row_logging_function;
3369
4879
 
3370
4880
  /*
3371
4881
    Some storage engines require that the new record is in record[0]
3372
4882
    (and the old record is in record[1]).
3373
4883
   */
3374
 
  assert(new_data == table->record[0]);
 
4884
  DBUG_ASSERT(new_data == table->record[0]);
3375
4885
 
3376
4886
  mark_trx_read_write();
3377
4887
 
3378
4888
  if (unlikely(error= update_row(old_data, new_data)))
3379
4889
    return error;
3380
 
 
3381
 
  if (unlikely(log_row_for_replication(table, old_data, new_data)))
3382
 
    return HA_ERR_RBR_LOGGING_FAILED;
3383
 
 
 
4890
  if (unlikely(error= binlog_log_row(table, old_data, new_data, log_func)))
 
4891
    return error;
3384
4892
  return 0;
3385
4893
}
3386
4894
 
3387
 
int handler::ha_delete_row(const unsigned char *buf)
 
4895
int handler::ha_delete_row(const uchar *buf)
3388
4896
{
3389
4897
  int error;
 
4898
  Log_func *log_func= Delete_rows_log_event::binlog_row_logging_function;
3390
4899
 
3391
4900
  mark_trx_read_write();
3392
4901
 
3393
4902
  if (unlikely(error= delete_row(buf)))
3394
4903
    return error;
3395
 
 
3396
 
  if (unlikely(log_row_for_replication(table, buf, 0)))
3397
 
    return HA_ERR_RBR_LOGGING_FAILED;
3398
 
 
 
4904
  if (unlikely(error= binlog_log_row(table, buf, 0, log_func)))
 
4905
    return error;
3399
4906
  return 0;
3400
4907
}
 
4908
 
 
4909
 
 
4910
 
 
4911
/**
 
4912
  @details
 
4913
  use_hidden_primary_key() is called in case of an update/delete when
 
4914
  (table_flags() and HA_PRIMARY_KEY_REQUIRED_FOR_DELETE) is defined
 
4915
  but we don't have a primary key
 
4916
*/
 
4917
void handler::use_hidden_primary_key()
 
4918
{
 
4919
  /* fallback to use all columns in the table to identify row */
 
4920
  table->use_all_columns();
 
4921
}