~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/handler.cc

  • Committer: Padraig O'Sullivan
  • Date: 2009-06-29 17:24:02 UTC
  • mto: This revision was merged to the branch mainline in revision 1081.
  • Revision ID: osullivan.padraig@gmail.com-20090629172402-9c5n1kr7ry7xgau7
Removed the dependency on knowing the position of an I_S table in the
schema_tables array defined in show.cc. This issue crops up in
prepare_schema_table. An issue with my design is that it increases the time
complexity from O(1) to O(n) in numerous places to determine an I_S table to
work on since we don't have an explicit index into the array and instead
need to search by name. However, as n is the number of I_S tables and this
number is quite small (at the moment n is < 30), we don't see this causing
any issue. This design makes the code much more maintainable and easier to
understand. Previously, modifying anything to do with the I_S tables meant
having to tip-toe around the issue of hard-coded indexes into the
schema_tables array.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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 */
 
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
 */
15
19
 
16
20
/**
17
21
  @file handler.cc
19
23
  Handler-calling-functions
20
24
*/
21
25
 
22
 
#ifdef USE_PRAGMA_IMPLEMENTATION
23
 
#pragma implementation                          // gcc: Class implementation
24
 
#endif
25
 
 
26
 
#include <drizzled/server_includes.h>
27
 
#include "rpl_filter.h"
28
 
#include <drizzled/drizzled_error_messages.h>
29
 
 
30
 
/*
31
 
  While we have legacy_db_type, we have this array to
32
 
  check for dups and to find handlerton from legacy_db_type.
33
 
  Remove when legacy_db_type is finally gone
34
 
*/
35
 
st_plugin_int *hton2plugin[MAX_HA];
36
 
 
37
 
static handlerton *installed_htons[128];
38
 
 
39
 
#define BITMAP_STACKBUF_SIZE (128/8)
40
 
 
41
 
KEY_CREATE_INFO default_key_create_info= { HA_KEY_ALG_UNDEF, 0, {NullS,0}, {NullS,0} };
42
 
 
43
 
/* number of entries in handlertons[] */
 
26
#include "drizzled/server_includes.h"
 
27
#include "mysys/hash.h"
 
28
#include "drizzled/error.h"
 
29
#include "drizzled/gettext.h"
 
30
#include "drizzled/data_home.h"
 
31
#include "drizzled/probes.h"
 
32
#include "drizzled/sql_parse.h"
 
33
#include "drizzled/cost_vect.h"
 
34
#include "drizzled/session.h"
 
35
#include "drizzled/sql_base.h"
 
36
#include "drizzled/transaction_services.h"
 
37
#include "drizzled/lock.h"
 
38
#include "drizzled/item/int.h"
 
39
#include "drizzled/item/empty_string.h"
 
40
#include "drizzled/unireg.h" // for mysql_frm_type
 
41
#include "drizzled/field/timestamp.h"
 
42
#include "drizzled/message/table.pb.h"
 
43
 
 
44
using namespace std;
 
45
 
 
46
extern drizzled::TransactionServices transaction_services;
 
47
 
 
48
KEY_CREATE_INFO default_key_create_info= { HA_KEY_ALG_UNDEF, 0, {NULL,0}, {NULL,0} };
 
49
 
 
50
/* number of entries in storage_engines[] */
44
51
uint32_t total_ha= 0;
45
 
/* number of storage engines (from handlertons[]) that support 2pc */
 
52
/* number of storage engines (from storage_engines[]) that support 2pc */
46
53
uint32_t total_ha_2pc= 0;
47
54
/* size of savepoint storage area (see ha_init) */
48
55
uint32_t savepoint_alloc_size= 0;
49
56
 
50
 
static const LEX_STRING sys_table_aliases[]=
51
 
{
52
 
  { C_STRING_WITH_LEN("INNOBASE") },  { C_STRING_WITH_LEN("INNODB") },
53
 
  { C_STRING_WITH_LEN("HEAP") },      { C_STRING_WITH_LEN("MEMORY") },
54
 
  {NullS, 0}
55
 
};
56
 
 
57
57
const char *ha_row_type[] = {
58
58
  "", "FIXED", "DYNAMIC", "COMPRESSED", "REDUNDANT", "COMPACT", "PAGE", "?","?","?"
59
59
};
60
60
 
61
61
const char *tx_isolation_names[] =
62
62
{ "READ-UNCOMMITTED", "READ-COMMITTED", "REPEATABLE-READ", "SERIALIZABLE",
63
 
  NullS};
 
63
  NULL};
 
64
 
64
65
TYPELIB tx_isolation_typelib= {array_elements(tx_isolation_names)-1,"",
65
 
                               tx_isolation_names, NULL};
66
 
 
67
 
static TYPELIB known_extensions= {0,"known_exts", NULL, NULL};
68
 
uint known_extensions_id= 0;
69
 
 
70
 
 
71
 
 
72
 
static plugin_ref ha_default_plugin(THD *thd)
73
 
{
74
 
  if (thd->variables.table_plugin)
75
 
    return thd->variables.table_plugin;
76
 
  return my_plugin_lock(thd, &global_system_variables.table_plugin);
77
 
}
78
 
 
79
 
 
80
 
/**
81
 
  Return the default storage engine handlerton for thread
82
 
 
83
 
  @param ha_default_handlerton(thd)
84
 
  @param thd         current thread
85
 
 
86
 
  @return
87
 
    pointer to handlerton
88
 
*/
89
 
handlerton *ha_default_handlerton(THD *thd)
90
 
{
91
 
  plugin_ref plugin= ha_default_plugin(thd);
92
 
  assert(plugin);
93
 
  handlerton *hton= plugin_data(plugin, handlerton*);
94
 
  assert(hton);
95
 
  return hton;
96
 
}
97
 
 
98
 
 
99
 
/**
100
 
  Return the storage engine handlerton for the supplied name
101
 
  
102
 
  @param thd         current thread
103
 
  @param name        name of storage engine
104
 
  
105
 
  @return
106
 
    pointer to storage engine plugin handle
107
 
*/
108
 
plugin_ref ha_resolve_by_name(THD *thd, const LEX_STRING *name)
109
 
{
110
 
  const LEX_STRING *table_alias;
111
 
  plugin_ref plugin;
112
 
 
113
 
redo:
114
 
  /* my_strnncoll is a macro and gcc doesn't do early expansion of macro */
115
 
  if (thd && !my_charset_latin1.coll->strnncoll(&my_charset_latin1,
116
 
                           (const uchar *)name->str, name->length,
117
 
                           (const uchar *)STRING_WITH_LEN("DEFAULT"), 0))
118
 
    return ha_default_plugin(thd);
119
 
 
120
 
  if ((plugin= my_plugin_lock_by_name(thd, name, DRIZZLE_STORAGE_ENGINE_PLUGIN)))
121
 
  {
122
 
    handlerton *hton= plugin_data(plugin, handlerton *);
123
 
    if (!(hton->flags & HTON_NOT_USER_SELECTABLE))
124
 
      return plugin;
125
 
      
126
 
    /*
127
 
      unlocking plugin immediately after locking is relatively low cost.
128
 
    */
129
 
    plugin_unlock(thd, plugin);
130
 
  }
131
 
 
132
 
  /*
133
 
    We check for the historical aliases.
134
 
  */
135
 
  for (table_alias= sys_table_aliases; table_alias->str; table_alias+= 2)
136
 
  {
137
 
    if (!my_strnncoll(&my_charset_latin1,
138
 
                      (const uchar *)name->str, name->length,
139
 
                      (const uchar *)table_alias->str, table_alias->length))
140
 
    {
141
 
      name= table_alias + 1;
142
 
      goto redo;
143
 
    }
144
 
  }
145
 
 
146
 
  return NULL;
147
 
}
148
 
 
149
 
 
150
 
plugin_ref ha_lock_engine(THD *thd, handlerton *hton)
151
 
{
152
 
  if (hton)
153
 
  {
154
 
    st_plugin_int **plugin= hton2plugin + hton->slot;
155
 
    
156
 
    return my_plugin_lock(thd, &plugin);
157
 
  }
158
 
  return NULL;
159
 
}
160
 
 
161
 
 
162
 
handlerton *ha_resolve_by_legacy_type(THD *thd, enum legacy_db_type db_type)
163
 
{
164
 
  plugin_ref plugin;
165
 
  switch (db_type) {
166
 
  case DB_TYPE_DEFAULT:
167
 
    return ha_default_handlerton(thd);
168
 
  default:
169
 
    if (db_type > DB_TYPE_UNKNOWN && db_type < DB_TYPE_DEFAULT &&
170
 
        (plugin= ha_lock_engine(thd, installed_htons[db_type])))
171
 
      return plugin_data(plugin, handlerton*);
172
 
    /* fall through */
173
 
  case DB_TYPE_UNKNOWN:
174
 
    return NULL;
175
 
  }
176
 
}
177
 
 
178
 
 
179
 
/**
180
 
  Use other database handler if databasehandler is not compiled in.
181
 
*/
182
 
handlerton *ha_checktype(THD *thd, enum legacy_db_type database_type,
183
 
                          bool no_substitute, bool report_error)
184
 
{
185
 
  handlerton *hton= ha_resolve_by_legacy_type(thd, database_type);
186
 
  if (ha_storage_engine_is_enabled(hton))
187
 
    return hton;
188
 
 
189
 
  if (no_substitute)
190
 
  {
191
 
    if (report_error)
192
 
    {
193
 
      const char *engine_name= ha_resolve_storage_engine_name(hton);
194
 
      my_error(ER_FEATURE_DISABLED,MYF(0),engine_name,engine_name);
195
 
    }
196
 
    return NULL;
197
 
  }
198
 
 
199
 
  switch (database_type) {
200
 
  case DB_TYPE_HASH:
201
 
    return ha_resolve_by_legacy_type(thd, DB_TYPE_HASH);
202
 
  default:
203
 
    break;
204
 
  }
205
 
 
206
 
  return ha_default_handlerton(thd);
207
 
} /* ha_checktype */
208
 
 
209
 
 
210
 
handler *get_new_handler(TABLE_SHARE *share, MEM_ROOT *alloc,
211
 
                         handlerton *db_type)
212
 
{
213
 
  handler *file;
214
 
 
215
 
  if (db_type && db_type->state == SHOW_OPTION_YES && db_type->create)
216
 
  {
217
 
    if ((file= db_type->create(db_type, share, alloc)))
218
 
      file->init();
219
 
    return(file);
220
 
  }
221
 
  /*
222
 
    Try the default table type
223
 
    Here the call to current_thd() is ok as we call this function a lot of
224
 
    times but we enter this branch very seldom.
225
 
  */
226
 
  return(get_new_handler(share, alloc, ha_default_handlerton(current_thd)));
227
 
}
 
66
                               tx_isolation_names, NULL};
228
67
 
229
68
 
230
69
/**
243
82
 
244
83
  /* Allocate a pointer array for the error message strings. */
245
84
  /* Zerofill it to avoid uninitialized gaps. */
246
 
  if (! (errmsgs= (const char**) my_malloc(HA_ERR_ERRORS * sizeof(char*),
247
 
                                           MYF(MY_WME | MY_ZEROFILL))))
 
85
  if (! (errmsgs= (const char**) malloc(HA_ERR_ERRORS * sizeof(char*))))
248
86
    return 1;
 
87
  memset(errmsgs, 0, HA_ERR_ERRORS * sizeof(char *));
249
88
 
250
89
  /* Set the dedicated error messages. */
251
90
  SETMSG(HA_ERR_KEY_NOT_FOUND,          ER(ER_KEY_NOT_FOUND));
310
149
  /* Allocate a pointer array for the error message strings. */
311
150
  if (! (errmsgs= my_error_unregister(HA_ERR_FIRST, HA_ERR_LAST)))
312
151
    return 1;
313
 
  my_free((uchar*) errmsgs, MYF(0));
 
152
  free((unsigned char*) errmsgs);
314
153
  return 0;
315
154
}
316
155
 
317
 
 
318
 
int ha_finalize_handlerton(st_plugin_int *plugin)
319
 
{
320
 
  handlerton *hton= (handlerton *)plugin->data;
321
 
 
322
 
  switch (hton->state)
323
 
  {
324
 
  case SHOW_OPTION_NO:
325
 
  case SHOW_OPTION_DISABLED:
326
 
    break;
327
 
  case SHOW_OPTION_YES:
328
 
    if (installed_htons[hton->db_type] == hton)
329
 
      installed_htons[hton->db_type]= NULL;
330
 
    break;
331
 
  };
332
 
 
333
 
  if (hton && plugin->plugin->deinit)
334
 
    (void)plugin->plugin->deinit(hton);
335
 
 
336
 
  my_free((uchar*)hton, MYF(0));
337
 
 
338
 
  return(0);
339
 
}
340
 
 
341
 
 
342
 
int ha_initialize_handlerton(st_plugin_int *plugin)
343
 
{
344
 
  handlerton *hton;
345
 
 
346
 
  hton= (handlerton *)my_malloc(sizeof(handlerton),
347
 
                                MYF(MY_WME | MY_ZEROFILL));
348
 
  /* 
349
 
    FIXME: the MY_ZEROFILL flag above doesn't zero all the bytes.
350
 
    
351
 
    This was detected after adding get_backup_engine member to handlerton
352
 
    structure. Apparently get_backup_engine was not NULL even though it was
353
 
    not initialized.
354
 
   */
355
 
  memset(hton, 0, sizeof(hton));
356
 
  /* Historical Requirement */
357
 
  plugin->data= hton; // shortcut for the future
358
 
  if (plugin->plugin->init)
359
 
  {
360
 
    if (plugin->plugin->init(hton))
361
 
    {
362
 
      sql_print_error("Plugin '%s' init function returned error.",
363
 
                      plugin->name.str);
364
 
      goto err;
365
 
    }
366
 
  }
367
 
 
368
 
  /*
369
 
    the switch below and hton->state should be removed when
370
 
    command-line options for plugins will be implemented
371
 
  */
372
 
  switch (hton->state) {
373
 
  case SHOW_OPTION_NO:
374
 
    break;
375
 
  case SHOW_OPTION_YES:
376
 
    {
377
 
      uint tmp;
378
 
      /* now check the db_type for conflict */
379
 
      if (hton->db_type <= DB_TYPE_UNKNOWN ||
380
 
          hton->db_type >= DB_TYPE_DEFAULT ||
381
 
          installed_htons[hton->db_type])
382
 
      {
383
 
        int idx= (int) DB_TYPE_FIRST_DYNAMIC;
384
 
 
385
 
        while (idx < (int) DB_TYPE_DEFAULT && installed_htons[idx])
386
 
          idx++;
387
 
 
388
 
        if (idx == (int) DB_TYPE_DEFAULT)
389
 
        {
390
 
          sql_print_warning("Too many storage engines!");
391
 
          return(1);
392
 
        }
393
 
        if (hton->db_type != DB_TYPE_UNKNOWN)
394
 
          sql_print_warning("Storage engine '%s' has conflicting typecode. "
395
 
                            "Assigning value %d.", plugin->plugin->name, idx);
396
 
        hton->db_type= (enum legacy_db_type) idx;
397
 
      }
398
 
      installed_htons[hton->db_type]= hton;
399
 
      tmp= hton->savepoint_offset;
400
 
      hton->savepoint_offset= savepoint_alloc_size;
401
 
      savepoint_alloc_size+= tmp;
402
 
      hton->slot= total_ha++;
403
 
      hton2plugin[hton->slot]=plugin;
404
 
      if (hton->prepare)
405
 
        total_ha_2pc++;
406
 
      break;
407
 
    }
408
 
    /* fall through */
409
 
  default:
410
 
    hton->state= SHOW_OPTION_DISABLED;
411
 
    break;
412
 
  }
413
 
  
414
 
  /* 
415
 
    This is entirely for legacy. We will create a new "disk based" hton and a 
416
 
    "memory" hton which will be configurable longterm. We should be able to 
417
 
    remove partition and myisammrg.
418
 
  */
419
 
  switch (hton->db_type) {
420
 
  case DB_TYPE_HEAP:
421
 
    heap_hton= hton;
422
 
    break;
423
 
  case DB_TYPE_MYISAM:
424
 
    myisam_hton= hton;
425
 
    break;
426
 
  default:
427
 
    break;
428
 
  };
429
 
 
430
 
  return(0);
431
 
err:
432
 
  return(1);
433
 
}
434
 
 
435
156
int ha_init()
436
157
{
437
158
  int error= 0;
442
163
    binary log (which is considered a transaction-capable storage engine in
443
164
    counting total_ha)
444
165
  */
445
 
  opt_using_transactions= total_ha>(uint32_t)opt_bin_log;
446
166
  savepoint_alloc_size+= sizeof(SAVEPOINT);
447
 
  return(error);
 
167
  return error;
448
168
}
449
169
 
450
170
int ha_end()
451
171
{
452
172
  int error= 0;
453
173
 
454
 
  /* 
 
174
  /*
455
175
    This should be eventualy based  on the graceful shutdown flag.
456
176
    So if flag is equal to HA_PANIC_CLOSE, the deallocate
457
177
    the errors.
459
179
  if (ha_finish_errors())
460
180
    error= 1;
461
181
 
462
 
  return(error);
463
 
}
464
 
 
465
 
static bool dropdb_handlerton(THD *unused1 __attribute__((unused)),
466
 
                              plugin_ref plugin,
467
 
                              void *path)
468
 
{
469
 
  handlerton *hton= plugin_data(plugin, handlerton *);
470
 
  if (hton->state == SHOW_OPTION_YES && hton->drop_database)
471
 
    hton->drop_database(hton, (char *)path);
472
 
  return false;
473
 
}
474
 
 
475
 
 
476
 
void ha_drop_database(char* path)
477
 
{
478
 
  plugin_foreach(NULL, dropdb_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN, path);
479
 
}
480
 
 
481
 
 
482
 
static bool closecon_handlerton(THD *thd, plugin_ref plugin,
483
 
                                void *unused __attribute__((unused)))
484
 
{
485
 
  handlerton *hton= plugin_data(plugin, handlerton *);
486
 
  /*
487
 
    there's no need to rollback here as all transactions must
488
 
    be rolled back already
489
 
  */
490
 
  if (hton->state == SHOW_OPTION_YES && hton->close_connection &&
491
 
      thd_get_ha_data(thd, hton))
492
 
    hton->close_connection(hton, thd);
493
 
  return false;
494
 
}
495
 
 
496
 
 
497
 
/**
498
 
  @note
499
 
    don't bother to rollback here, it's done already
500
 
*/
501
 
void ha_close_connection(THD* thd)
502
 
{
503
 
  plugin_foreach(thd, closecon_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN, 0);
504
 
}
 
182
  return error;
 
183
}
 
184
 
 
185
 
505
186
 
506
187
/* ========================================================================
507
188
 ======================= TRANSACTIONS ===================================*/
605
286
  -----------
606
287
 
607
288
  The server stores its transaction-related data in
608
 
  thd->transaction. This structure has two members of type
609
 
  THD_TRANS. These members correspond to the statement and
 
289
  session->transaction. This structure has two members of type
 
290
  Session_TRANS. These members correspond to the statement and
610
291
  normal transactions respectively:
611
292
 
612
 
  - thd->transaction.stmt contains a list of engines
 
293
  - session->transaction.stmt contains a list of engines
613
294
  that are participating in the given statement
614
 
  - thd->transaction.all contains a list of engines that
 
295
  - session->transaction.all contains a list of engines that
615
296
  have participated in any of the statement transactions started
616
297
  within the context of the normal transaction.
617
298
  Each element of the list contains a pointer to the storage
618
299
  engine, engine-specific transactional data, and engine-specific
619
300
  transaction flags.
620
301
 
621
 
  In autocommit mode thd->transaction.all is empty.
622
 
  Instead, data of thd->transaction.stmt is
 
302
  In autocommit mode session->transaction.all is empty.
 
303
  Instead, data of session->transaction.stmt is
623
304
  used to commit/rollback the normal transaction.
624
305
 
625
306
  The list of registered engines has a few important properties:
630
311
  Transaction life cycle
631
312
  ----------------------
632
313
 
633
 
  When a new connection is established, thd->transaction
 
314
  When a new connection is established, session->transaction
634
315
  members are initialized to an empty state.
635
316
  If a statement uses any tables, all affected engines
636
317
  are registered in the statement engine list. In
646
327
  and emptied again at the next statement's end.
647
328
 
648
329
  The normal transaction is committed in a similar way
649
 
  (by going over all engines in thd->transaction.all list)
 
330
  (by going over all engines in session->transaction.all list)
650
331
  but at different times:
651
332
  - upon COMMIT SQL statement is issued by the user
652
333
  - implicitly, by the server, at the beginning of a DDL statement
656
337
  - if the user has requested so, by issuing ROLLBACK SQL
657
338
  statement
658
339
  - if one of the storage engines requested a rollback
659
 
  by setting thd->transaction_rollback_request. This may
 
340
  by setting session->transaction_rollback_request. This may
660
341
  happen in case, e.g., when the transaction in the engine was
661
342
  chosen a victim of the internal deadlock resolution algorithm
662
343
  and rolled back internally. When such a situation happens, there
676
357
  The remaining rare cases when the server explicitly has
677
358
  to commit the statement transaction prior to committing the normal
678
359
  one cover error-handling scenarios (see for example
679
 
  SQLCOM_LOCK_TABLES).
 
360
  ?).
680
361
 
681
362
  When committing a statement or a normal transaction, the server
682
363
  either uses the two-phase commit protocol, or issues a commit
683
364
  in each engine independently. The two-phase commit protocol
684
365
  is used only if:
685
366
  - all participating engines support two-phase commit (provide
686
 
    handlerton::prepare PSEA API call) and
 
367
    StorageEngine::prepare PSEA API call) and
687
368
  - transactions in at least two engines modify data (i.e. are
688
369
  not read-only).
689
370
 
698
379
  transactions of other participants.
699
380
 
700
381
  After the normal transaction has been committed,
701
 
  thd->transaction.all list is cleared.
 
382
  session->transaction.all list is cleared.
702
383
 
703
384
  When a connection is closed, the current normal transaction, if
704
385
  any, is rolled back.
747
428
 
748
429
  At the end of a statement, server call
749
430
  ha_autocommit_or_rollback() is invoked. This call in turn
750
 
  invokes handlerton::prepare() for every involved engine.
751
 
  Prepare is followed by a call to handlerton::commit_one_phase()
752
 
  If a one-phase commit will suffice, handlerton::prepare() is not
753
 
  invoked and the server only calls handlerton::commit_one_phase().
 
431
  invokes StorageEngine::prepare() for every involved engine.
 
432
  Prepare is followed by a call to StorageEngine::commit_one_phase()
 
433
  If a one-phase commit will suffice, StorageEngine::prepare() is not
 
434
  invoked and the server only calls StorageEngine::commit_one_phase().
754
435
  At statement commit, the statement-related read-write engine
755
436
  flag is propagated to the corresponding flag in the normal
756
437
  transaction.  When the commit is complete, the list of registered
762
443
  ---------------------------------------------------
763
444
 
764
445
  DDLs and operations with non-transactional engines
765
 
  do not "register" in thd->transaction lists, and thus do not
 
446
  do not "register" in session->transaction lists, and thus do not
766
447
  modify the transaction state. Besides, each DDL in
767
448
  MySQL is prefixed with an implicit normal transaction commit
768
 
  (a call to end_active_trans()), and thus leaves nothing
 
449
  (a call to Session::endActiveTransaction()), and thus leaves nothing
769
450
  to modify.
770
451
  However, as it has been pointed out with CREATE TABLE .. SELECT,
771
452
  some DDL statements can start a *new* transaction.
776
457
  to maintain atomicity: if CREATE TABLE .. SELECT failed,
777
458
  the newly created table is deleted.
778
459
  In addition, some DDL statements issue interim transaction
779
 
  commits: e.g. ALTER TABLE issues a commit after data is copied
 
460
  commits: e.g. ALTER Table issues a commit after data is copied
780
461
  from the original table to the internal temporary table. Other
781
462
  statements, e.g. CREATE TABLE ... SELECT do not always commit
782
463
  after itself.
783
464
  And finally there is a group of DDL statements such as
784
 
  RENAME/DROP TABLE that doesn't start a new transaction
 
465
  RENAME/DROP Table that doesn't start a new transaction
785
466
  and doesn't commit.
786
467
 
787
468
  This diversity makes it hard to say what will happen if
809
490
    times per transaction.
810
491
 
811
492
*/
812
 
void trans_register_ha(THD *thd, bool all, handlerton *ht_arg)
 
493
void trans_register_ha(Session *session, bool all, StorageEngine *engine)
813
494
{
814
 
  THD_TRANS *trans;
 
495
  Session_TRANS *trans;
815
496
  Ha_trx_info *ha_info;
816
497
 
817
498
  if (all)
818
499
  {
819
 
    trans= &thd->transaction.all;
820
 
    thd->server_status|= SERVER_STATUS_IN_TRANS;
 
500
    trans= &session->transaction.all;
 
501
    session->server_status|= SERVER_STATUS_IN_TRANS;
821
502
  }
822
503
  else
823
 
    trans= &thd->transaction.stmt;
 
504
    trans= &session->transaction.stmt;
824
505
 
825
 
  ha_info= thd->ha_data[ht_arg->slot].ha_info + static_cast<unsigned>(all);
 
506
  ha_info= session->ha_data[engine->getSlot()].ha_info + static_cast<unsigned>(all);
826
507
 
827
508
  if (ha_info->is_started())
828
509
    return; /* already registered, return */
829
510
 
830
 
  ha_info->register_ha(trans, ht_arg);
831
 
 
832
 
  trans->no_2pc|=(ht_arg->prepare==0);
833
 
  if (thd->transaction.xid_state.xid.is_null())
834
 
    thd->transaction.xid_state.xid.set(thd->query_id);
835
 
 
836
 
  return;
837
 
}
838
 
 
839
 
/**
840
 
  @retval
841
 
    0   ok
842
 
  @retval
843
 
    1   error, transaction was rolled back
844
 
*/
845
 
int ha_prepare(THD *thd)
846
 
{
847
 
  int error=0, all=1;
848
 
  THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt;
849
 
  Ha_trx_info *ha_info= trans->ha_list;
850
 
  if (ha_info)
851
 
  {
852
 
    for (; ha_info; ha_info= ha_info->next())
853
 
    {
854
 
      int err;
855
 
      handlerton *ht= ha_info->ht();
856
 
      status_var_increment(thd->status_var.ha_prepare_count);
857
 
      if (ht->prepare)
858
 
      {
859
 
        if ((err= ht->prepare(ht, thd, all)))
860
 
        {
861
 
          my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
862
 
          ha_rollback_trans(thd, all);
863
 
          error=1;
864
 
          break;
865
 
        }
866
 
      }
867
 
      else
868
 
      {
869
 
        push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
870
 
                            ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
871
 
                            ha_resolve_storage_engine_name(ht));
872
 
      }
873
 
    }
874
 
  }
875
 
  return(error);
 
511
  ha_info->register_ha(trans, engine);
 
512
 
 
513
  trans->no_2pc|= not engine->has_2pc();
 
514
  if (session->transaction.xid_state.xid.is_null())
 
515
    session->transaction.xid_state.xid.set(session->query_id);
876
516
}
877
517
 
878
518
/**
891
531
 
892
532
static
893
533
bool
894
 
ha_check_and_coalesce_trx_read_only(THD *thd, Ha_trx_info *ha_list,
 
534
ha_check_and_coalesce_trx_read_only(Session *session, Ha_trx_info *ha_list,
895
535
                                    bool all)
896
536
{
897
537
  /* The number of storage engines that have actual changes. */
905
545
 
906
546
    if (! all)
907
547
    {
908
 
      Ha_trx_info *ha_info_all= &thd->ha_data[ha_info->ht()->slot].ha_info[1];
 
548
      Ha_trx_info *ha_info_all= &session->ha_data[ha_info->engine()->getSlot()].ha_info[1];
909
549
      assert(ha_info != ha_info_all);
910
550
      /*
911
551
        Merge read-only/read-write information about statement
912
552
        transaction to its enclosing normal transaction. Do this
913
553
        only if in a real transaction -- that is, if we know
914
 
        that ha_info_all is registered in thd->transaction.all.
 
554
        that ha_info_all is registered in session->transaction.all.
915
555
        Since otherwise we only clutter the normal transaction flags.
916
556
      */
917
557
      if (ha_info_all->is_started()) /* false if autocommit. */
945
585
    stored functions or triggers. So we simply do nothing now.
946
586
    TODO: This should be fixed in later ( >= 5.1) releases.
947
587
*/
948
 
int ha_commit_trans(THD *thd, bool all)
 
588
int ha_commit_trans(Session *session, bool all)
949
589
{
950
590
  int error= 0, cookie= 0;
951
591
  /*
952
592
    'all' means that this is either an explicit commit issued by
953
593
    user, or an implicit commit issued by a DDL.
954
594
  */
955
 
  THD_TRANS *trans= all ? &thd->transaction.all : &thd->transaction.stmt;
956
 
  bool is_real_trans= all || thd->transaction.all.ha_list == 0;
 
595
  Session_TRANS *trans= all ? &session->transaction.all : &session->transaction.stmt;
 
596
  bool is_real_trans= all || session->transaction.all.ha_list == 0;
957
597
  Ha_trx_info *ha_info= trans->ha_list;
958
 
  my_xid xid= thd->transaction.xid_state.xid.get_my_xid();
959
598
 
960
599
  /*
961
600
    We must not commit the normal transaction if a statement
963
602
    flags will not get propagated to its normal transaction's
964
603
    counterpart.
965
604
  */
966
 
  assert(thd->transaction.stmt.ha_list == NULL ||
967
 
              trans == &thd->transaction.stmt);
 
605
  assert(session->transaction.stmt.ha_list == NULL ||
 
606
              trans == &session->transaction.stmt);
968
607
 
969
 
  if (thd->in_sub_stmt)
970
 
  {
971
 
    /*
972
 
      Since we don't support nested statement transactions in 5.0,
973
 
      we can't commit or rollback stmt transactions while we are inside
974
 
      stored functions or triggers. So we simply do nothing now.
975
 
      TODO: This should be fixed in later ( >= 5.1) releases.
976
 
    */
977
 
    if (!all)
978
 
      return(0);
979
 
    /*
980
 
      We assume that all statements which commit or rollback main transaction
981
 
      are prohibited inside of stored functions or triggers. So they should
982
 
      bail out with error even before ha_commit_trans() call. To be 100% safe
983
 
      let us throw error in non-debug builds.
984
 
    */
985
 
    assert(0);
986
 
    my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
987
 
    return(2);
988
 
  }
989
608
  if (ha_info)
990
609
  {
991
610
    bool must_2pc;
992
611
 
993
 
    if (is_real_trans && wait_if_global_read_lock(thd, 0, 0))
994
 
    {
995
 
      ha_rollback_trans(thd, all);
996
 
      return(1);
997
 
    }
998
 
 
999
 
    if (   is_real_trans
1000
 
        && opt_readonly
1001
 
        && ! thd->slave_thread
1002
 
       )
1003
 
    {
1004
 
      my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only");
1005
 
      ha_rollback_trans(thd, all);
1006
 
      error= 1;
1007
 
      goto end;
1008
 
    }
1009
 
 
1010
 
    must_2pc= ha_check_and_coalesce_trx_read_only(thd, ha_info, all);
 
612
    if (is_real_trans && wait_if_global_read_lock(session, 0, 0))
 
613
    {
 
614
      ha_rollback_trans(session, all);
 
615
      return 1;
 
616
    }
 
617
 
 
618
    must_2pc= ha_check_and_coalesce_trx_read_only(session, ha_info, all);
1011
619
 
1012
620
    if (!trans->no_2pc && must_2pc)
1013
621
    {
1014
622
      for (; ha_info && !error; ha_info= ha_info->next())
1015
623
      {
1016
624
        int err;
1017
 
        handlerton *ht= ha_info->ht();
 
625
        StorageEngine *engine= ha_info->engine();
1018
626
        /*
1019
627
          Do not call two-phase commit if this particular
1020
628
          transaction is read-only. This allows for simpler
1026
634
          Sic: we know that prepare() is not NULL since otherwise
1027
635
          trans->no_2pc would have been set.
1028
636
        */
1029
 
        if ((err= ht->prepare(ht, thd, all)))
 
637
        if ((err= engine->prepare(session, all)))
1030
638
        {
1031
639
          my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
1032
640
          error= 1;
1033
641
        }
1034
 
        status_var_increment(thd->status_var.ha_prepare_count);
 
642
        status_var_increment(session->status_var.ha_prepare_count);
1035
643
      }
1036
 
      if (error || (is_real_trans && xid &&
1037
 
                    (error= !(cookie= tc_log->log_xid(thd, xid)))))
 
644
      if (error)
1038
645
      {
1039
 
        ha_rollback_trans(thd, all);
 
646
        ha_rollback_trans(session, all);
1040
647
        error= 1;
1041
648
        goto end;
1042
649
      }
1043
650
    }
1044
 
    error=ha_commit_one_phase(thd, all) ? (cookie ? 2 : 1) : 0;
1045
 
    if (cookie)
1046
 
      tc_log->unlog(cookie, xid);
 
651
    error=ha_commit_one_phase(session, all) ? (cookie ? 2 : 1) : 0;
1047
652
end:
1048
653
    if (is_real_trans)
1049
 
      start_waiting_global_read_lock(thd);
 
654
      start_waiting_global_read_lock(session);
1050
655
  }
1051
 
  return(error);
 
656
  return error;
1052
657
}
1053
658
 
1054
659
/**
1055
660
  @note
1056
661
  This function does not care about global read lock. A caller should.
1057
662
*/
1058
 
int ha_commit_one_phase(THD *thd, bool all)
 
663
int ha_commit_one_phase(Session *session, bool all)
1059
664
{
1060
665
  int error=0;
1061
 
  THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt;
1062
 
  bool is_real_trans=all || thd->transaction.all.ha_list == 0;
 
666
  Session_TRANS *trans=all ? &session->transaction.all : &session->transaction.stmt;
 
667
  bool is_real_trans=all || session->transaction.all.ha_list == 0;
1063
668
  Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
1064
669
  if (ha_info)
1065
670
  {
1066
671
    for (; ha_info; ha_info= ha_info_next)
1067
672
    {
1068
673
      int err;
1069
 
      handlerton *ht= ha_info->ht();
1070
 
      if ((err= ht->commit(ht, thd, all)))
 
674
      StorageEngine *engine= ha_info->engine();
 
675
      if ((err= engine->commit(session, all)))
1071
676
      {
1072
677
        my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
1073
678
        error=1;
1074
679
      }
1075
 
      status_var_increment(thd->status_var.ha_commit_count);
 
680
      status_var_increment(session->status_var.ha_commit_count);
1076
681
      ha_info_next= ha_info->next();
1077
682
      ha_info->reset(); /* keep it conveniently zero-filled */
1078
683
    }
1079
684
    trans->ha_list= 0;
1080
685
    trans->no_2pc=0;
1081
686
    if (is_real_trans)
1082
 
      thd->transaction.xid_state.xid.null();
 
687
      session->transaction.xid_state.xid.null();
1083
688
    if (all)
1084
689
    {
1085
 
      thd->variables.tx_isolation=thd->session_tx_isolation;
1086
 
      thd->transaction.cleanup();
 
690
      session->variables.tx_isolation=session->session_tx_isolation;
 
691
      session->transaction.cleanup();
1087
692
    }
1088
693
  }
1089
 
  return(error);
 
694
  return error;
1090
695
}
1091
696
 
1092
697
 
1093
 
int ha_rollback_trans(THD *thd, bool all)
 
698
int ha_rollback_trans(Session *session, bool all)
1094
699
{
1095
700
  int error=0;
1096
 
  THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt;
 
701
  Session_TRANS *trans=all ? &session->transaction.all : &session->transaction.stmt;
1097
702
  Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
1098
 
  bool is_real_trans=all || thd->transaction.all.ha_list == 0;
 
703
  bool is_real_trans=all || session->transaction.all.ha_list == 0;
1099
704
 
1100
705
  /*
1101
706
    We must not rollback the normal transaction if a statement
1102
707
    transaction is pending.
1103
708
  */
1104
 
  assert(thd->transaction.stmt.ha_list == NULL ||
1105
 
              trans == &thd->transaction.stmt);
 
709
  assert(session->transaction.stmt.ha_list == NULL ||
 
710
              trans == &session->transaction.stmt);
1106
711
 
1107
 
  if (thd->in_sub_stmt)
1108
 
  {
1109
 
    /*
1110
 
      If we are inside stored function or trigger we should not commit or
1111
 
      rollback current statement transaction. See comment in ha_commit_trans()
1112
 
      call for more information.
1113
 
    */
1114
 
    if (!all)
1115
 
      return(0);
1116
 
    assert(0);
1117
 
    my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
1118
 
    return(1);
1119
 
  }
1120
712
  if (ha_info)
1121
713
  {
1122
714
    for (; ha_info; ha_info= ha_info_next)
1123
715
    {
1124
716
      int err;
1125
 
      handlerton *ht= ha_info->ht();
1126
 
      if ((err= ht->rollback(ht, thd, all)))
 
717
      StorageEngine *engine= ha_info->engine();
 
718
      if ((err= engine->rollback(session, all)))
1127
719
      { // cannot happen
1128
720
        my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
1129
721
        error=1;
1130
722
      }
1131
 
      status_var_increment(thd->status_var.ha_rollback_count);
 
723
      status_var_increment(session->status_var.ha_rollback_count);
1132
724
      ha_info_next= ha_info->next();
1133
725
      ha_info->reset(); /* keep it conveniently zero-filled */
1134
726
    }
1135
727
    trans->ha_list= 0;
1136
728
    trans->no_2pc=0;
1137
729
    if (is_real_trans)
1138
 
      thd->transaction.xid_state.xid.null();
 
730
      session->transaction.xid_state.xid.null();
1139
731
    if (all)
1140
732
    {
1141
 
      thd->variables.tx_isolation=thd->session_tx_isolation;
1142
 
      thd->transaction.cleanup();
 
733
      session->variables.tx_isolation=session->session_tx_isolation;
 
734
      session->transaction.cleanup();
1143
735
    }
1144
736
  }
1145
737
  if (all)
1146
 
    thd->transaction_rollback_request= false;
 
738
    session->transaction_rollback_request= false;
1147
739
 
1148
740
  /*
1149
741
    If a non-transactional table was updated, warn; don't warn if this is a
1154
746
    the error log; but we don't want users to wonder why they have this
1155
747
    message in the error log, so we don't send it.
1156
748
  */
1157
 
  if (is_real_trans && thd->transaction.all.modified_non_trans_table &&
1158
 
      !thd->slave_thread && thd->killed != THD::KILL_CONNECTION)
1159
 
    push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
749
  if (is_real_trans && session->transaction.all.modified_non_trans_table && session->killed != Session::KILL_CONNECTION)
 
750
    push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1160
751
                 ER_WARNING_NOT_COMPLETE_ROLLBACK,
1161
752
                 ER(ER_WARNING_NOT_COMPLETE_ROLLBACK));
1162
 
  return(error);
 
753
  return error;
1163
754
}
1164
755
 
1165
756
/**
1173
764
    the user has used LOCK TABLES then that mechanism does not know to do the
1174
765
    commit.
1175
766
*/
1176
 
int ha_autocommit_or_rollback(THD *thd, int error)
 
767
int ha_autocommit_or_rollback(Session *session, int error)
1177
768
{
1178
 
  if (thd->transaction.stmt.ha_list)
 
769
  if (session->transaction.stmt.ha_list)
1179
770
  {
1180
771
    if (!error)
1181
772
    {
1182
 
      if (ha_commit_trans(thd, 0))
1183
 
        error=1;
1184
 
    }
1185
 
    else 
1186
 
    {
1187
 
      (void) ha_rollback_trans(thd, 0);
1188
 
      if (thd->transaction_rollback_request && !thd->in_sub_stmt)
1189
 
        (void) ha_rollback(thd);
1190
 
    }
1191
 
 
1192
 
    thd->variables.tx_isolation=thd->session_tx_isolation;
1193
 
  }
1194
 
  return(error);
1195
 
}
1196
 
 
1197
 
 
1198
 
struct xahton_st {
1199
 
  XID *xid;
1200
 
  int result;
1201
 
};
1202
 
 
1203
 
static bool xacommit_handlerton(THD *unused1 __attribute__((unused)),
1204
 
                                plugin_ref plugin,
1205
 
                                void *arg)
1206
 
{
1207
 
  handlerton *hton= plugin_data(plugin, handlerton *);
1208
 
  if (hton->state == SHOW_OPTION_YES && hton->recover)
1209
 
  {
1210
 
    hton->commit_by_xid(hton, ((struct xahton_st *)arg)->xid);
1211
 
    ((struct xahton_st *)arg)->result= 0;
1212
 
  }
1213
 
  return false;
1214
 
}
1215
 
 
1216
 
static bool xarollback_handlerton(THD *unused1 __attribute__((unused)),
1217
 
                                  plugin_ref plugin,
1218
 
                                  void *arg)
1219
 
{
1220
 
  handlerton *hton= plugin_data(plugin, handlerton *);
1221
 
  if (hton->state == SHOW_OPTION_YES && hton->recover)
1222
 
  {
1223
 
    hton->rollback_by_xid(hton, ((struct xahton_st *)arg)->xid);
1224
 
    ((struct xahton_st *)arg)->result= 0;
1225
 
  }
1226
 
  return false;
1227
 
}
1228
 
 
1229
 
 
1230
 
int ha_commit_or_rollback_by_xid(XID *xid, bool commit)
1231
 
{
1232
 
  struct xahton_st xaop;
1233
 
  xaop.xid= xid;
1234
 
  xaop.result= 1;
1235
 
 
1236
 
  plugin_foreach(NULL, commit ? xacommit_handlerton : xarollback_handlerton,
1237
 
                 DRIZZLE_STORAGE_ENGINE_PLUGIN, &xaop);
1238
 
 
1239
 
  return xaop.result;
1240
 
}
1241
 
 
1242
 
/**
1243
 
  recover() step of xa.
1244
 
 
1245
 
  @note
1246
 
    there are three modes of operation:
1247
 
    - automatic recover after a crash
1248
 
    in this case commit_list != 0, tc_heuristic_recover==0
1249
 
    all xids from commit_list are committed, others are rolled back
1250
 
    - manual (heuristic) recover
1251
 
    in this case commit_list==0, tc_heuristic_recover != 0
1252
 
    DBA has explicitly specified that all prepared transactions should
1253
 
    be committed (or rolled back).
1254
 
    - no recovery (MySQL did not detect a crash)
1255
 
    in this case commit_list==0, tc_heuristic_recover == 0
1256
 
    there should be no prepared transactions in this case.
1257
 
*/
1258
 
struct xarecover_st
1259
 
{
1260
 
  int len, found_foreign_xids, found_my_xids;
1261
 
  XID *list;
1262
 
  HASH *commit_list;
1263
 
  bool dry_run;
1264
 
};
1265
 
 
1266
 
static bool xarecover_handlerton(THD *unused __attribute__((unused)),
1267
 
                                 plugin_ref plugin,
1268
 
                                 void *arg)
1269
 
{
1270
 
  handlerton *hton= plugin_data(plugin, handlerton *);
1271
 
  struct xarecover_st *info= (struct xarecover_st *) arg;
1272
 
  int got;
1273
 
 
1274
 
  if (hton->state == SHOW_OPTION_YES && hton->recover)
1275
 
  {
1276
 
    while ((got= hton->recover(hton, info->list, info->len)) > 0 )
1277
 
    {
1278
 
      sql_print_information("Found %d prepared transaction(s) in %s",
1279
 
                            got, ha_resolve_storage_engine_name(hton));
1280
 
      for (int i=0; i < got; i ++)
1281
 
      {
1282
 
        my_xid x=info->list[i].get_my_xid();
1283
 
        if (!x) // not "mine" - that is generated by external TM
1284
 
        {
1285
 
          xid_cache_insert(info->list+i, XA_PREPARED);
1286
 
          info->found_foreign_xids++;
1287
 
          continue;
1288
 
        }
1289
 
        if (info->dry_run)
1290
 
        {
1291
 
          info->found_my_xids++;
1292
 
          continue;
1293
 
        }
1294
 
        // recovery mode
1295
 
        if (info->commit_list ?
1296
 
            hash_search(info->commit_list, (uchar *)&x, sizeof(x)) != 0 :
1297
 
            tc_heuristic_recover == TC_HEURISTIC_RECOVER_COMMIT)
1298
 
        {
1299
 
          hton->commit_by_xid(hton, info->list+i);
1300
 
        }
1301
 
        else
1302
 
        {
1303
 
          hton->rollback_by_xid(hton, info->list+i);
1304
 
        }
1305
 
      }
1306
 
      if (got < info->len)
1307
 
        break;
1308
 
    }
1309
 
  }
1310
 
  return false;
1311
 
}
1312
 
 
1313
 
int ha_recover(HASH *commit_list)
1314
 
{
1315
 
  struct xarecover_st info;
1316
 
  info.found_foreign_xids= info.found_my_xids= 0;
1317
 
  info.commit_list= commit_list;
1318
 
  info.dry_run= (info.commit_list==0 && tc_heuristic_recover==0);
1319
 
  info.list= NULL;
1320
 
 
1321
 
  /* commit_list and tc_heuristic_recover cannot be set both */
1322
 
  assert(info.commit_list==0 || tc_heuristic_recover==0);
1323
 
  /* if either is set, total_ha_2pc must be set too */
1324
 
  assert(info.dry_run || total_ha_2pc>(uint32_t)opt_bin_log);
1325
 
 
1326
 
  if (total_ha_2pc <= (uint32_t)opt_bin_log)
1327
 
    return(0);
1328
 
 
1329
 
  if (info.commit_list)
1330
 
    sql_print_information("Starting crash recovery...");
1331
 
 
1332
 
 
1333
 
#ifndef WILL_BE_DELETED_LATER
1334
 
 
1335
 
  /*
1336
 
    for now, only InnoDB supports 2pc. It means we can always safely
1337
 
    rollback all pending transactions, without risking inconsistent data
1338
 
  */
1339
 
 
1340
 
  assert(total_ha_2pc == (uint32_t) opt_bin_log+1); // only InnoDB and binlog
1341
 
  tc_heuristic_recover= TC_HEURISTIC_RECOVER_ROLLBACK; // forcing ROLLBACK
1342
 
  info.dry_run=false;
1343
 
#endif
1344
 
 
1345
 
 
1346
 
  for (info.len= MAX_XID_LIST_SIZE ; 
1347
 
       info.list==0 && info.len > MIN_XID_LIST_SIZE; info.len/=2)
1348
 
  {
1349
 
    info.list=(XID *)my_malloc(info.len*sizeof(XID), MYF(0));
1350
 
  }
1351
 
  if (!info.list)
1352
 
  {
1353
 
    sql_print_error(ER(ER_OUTOFMEMORY), info.len*sizeof(XID));
1354
 
    return(1);
1355
 
  }
1356
 
 
1357
 
  plugin_foreach(NULL, xarecover_handlerton, 
1358
 
                 DRIZZLE_STORAGE_ENGINE_PLUGIN, &info);
1359
 
 
1360
 
  my_free((uchar*)info.list, MYF(0));
1361
 
  if (info.found_foreign_xids)
1362
 
    sql_print_warning("Found %d prepared XA transactions", 
1363
 
                      info.found_foreign_xids);
1364
 
  if (info.dry_run && info.found_my_xids)
1365
 
  {
1366
 
    sql_print_error("Found %d prepared transactions! It means that mysqld was "
1367
 
                    "not shut down properly last time and critical recovery "
1368
 
                    "information (last binlog or %s file) was manually deleted "
1369
 
                    "after a crash. You have to start mysqld with "
1370
 
                    "--tc-heuristic-recover switch to commit or rollback "
1371
 
                    "pending transactions.",
1372
 
                    info.found_my_xids, opt_tc_log_file);
1373
 
    return(1);
1374
 
  }
1375
 
  if (info.commit_list)
1376
 
    sql_print_information("Crash recovery finished.");
1377
 
  return(0);
1378
 
}
 
773
      if (ha_commit_trans(session, 0))
 
774
        error= 1;
 
775
    }
 
776
    else
 
777
    {
 
778
      (void) ha_rollback_trans(session, 0);
 
779
      if (session->transaction_rollback_request)
 
780
        (void) ha_rollback(session);
 
781
    }
 
782
 
 
783
    session->variables.tx_isolation=session->session_tx_isolation;
 
784
  }
 
785
 
 
786
  return error;
 
787
}
 
788
 
 
789
 
 
790
 
1379
791
 
1380
792
/**
1381
793
  return the list of XID's to a client, the same way SHOW commands do.
1385
797
    so mysql_xa_recover does not filter XID's to ensure uniqueness.
1386
798
    It can be easily fixed later, if necessary.
1387
799
*/
1388
 
bool mysql_xa_recover(THD *thd)
 
800
bool mysql_xa_recover(Session *session)
1389
801
{
1390
802
  List<Item> field_list;
1391
 
  Protocol *protocol= thd->protocol;
 
803
  Protocol *protocol= session->protocol;
1392
804
  int i=0;
1393
805
  XID_STATE *xs;
1394
806
 
1397
809
  field_list.push_back(new Item_int("bqual_length", 0, MY_INT32_NUM_DECIMAL_DIGITS));
1398
810
  field_list.push_back(new Item_empty_string("data",XIDDATASIZE));
1399
811
 
1400
 
  if (protocol->send_fields(&field_list,
1401
 
                            Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
1402
 
    return(1);
 
812
  if (protocol->sendFields(&field_list,
 
813
                           Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
 
814
    return 1;
1403
815
 
1404
816
  pthread_mutex_lock(&LOCK_xid_cache);
1405
817
  while ((xs= (XID_STATE*)hash_element(&xid_cache, i++)))
1406
818
  {
1407
819
    if (xs->xa_state==XA_PREPARED)
1408
820
    {
1409
 
      protocol->prepare_for_resend();
1410
 
      protocol->store_int64_t((int64_t)xs->xid.formatID, false);
1411
 
      protocol->store_int64_t((int64_t)xs->xid.gtrid_length, false);
1412
 
      protocol->store_int64_t((int64_t)xs->xid.bqual_length, false);
1413
 
      protocol->store(xs->xid.data, xs->xid.gtrid_length+xs->xid.bqual_length,
1414
 
                      &my_charset_bin);
 
821
      protocol->prepareForResend();
 
822
      protocol->store((int64_t)xs->xid.formatID);
 
823
      protocol->store((int64_t)xs->xid.gtrid_length);
 
824
      protocol->store((int64_t)xs->xid.bqual_length);
 
825
      protocol->store(xs->xid.data, xs->xid.gtrid_length+xs->xid.bqual_length);
1415
826
      if (protocol->write())
1416
827
      {
1417
828
        pthread_mutex_unlock(&LOCK_xid_cache);
1418
 
        return(1);
 
829
        return 1;
1419
830
      }
1420
831
    }
1421
832
  }
1422
833
 
1423
834
  pthread_mutex_unlock(&LOCK_xid_cache);
1424
 
  my_eof(thd);
1425
 
  return(0);
1426
 
}
1427
 
 
1428
 
/**
1429
 
  @details
1430
 
  This function should be called when MySQL sends rows of a SELECT result set
1431
 
  or the EOF mark to the client. It releases a possible adaptive hash index
1432
 
  S-latch held by thd in InnoDB and also releases a possible InnoDB query
1433
 
  FIFO ticket to enter InnoDB. To save CPU time, InnoDB allows a thd to
1434
 
  keep them over several calls of the InnoDB handler interface when a join
1435
 
  is executed. But when we let the control to pass to the client they have
1436
 
  to be released because if the application program uses mysql_use_result(),
1437
 
  it may deadlock on the S-latch if the application on another connection
1438
 
  performs another SQL query. In MySQL-4.1 this is even more important because
1439
 
  there a connection can have several SELECT queries open at the same time.
1440
 
 
1441
 
  @param thd           the thread handle of the current connection
1442
 
 
1443
 
  @return
1444
 
    always 0
1445
 
*/
1446
 
static bool release_temporary_latches(THD *thd, plugin_ref plugin,
1447
 
                                      void *unused __attribute__((unused)))
1448
 
{
1449
 
  handlerton *hton= plugin_data(plugin, handlerton *);
1450
 
 
1451
 
  if (hton->state == SHOW_OPTION_YES && hton->release_temporary_latches)
1452
 
    hton->release_temporary_latches(hton, thd);
1453
 
 
1454
 
  return false;
1455
 
}
1456
 
 
1457
 
 
1458
 
int ha_release_temporary_latches(THD *thd)
1459
 
{
1460
 
  plugin_foreach(thd, release_temporary_latches, DRIZZLE_STORAGE_ENGINE_PLUGIN, 
1461
 
                 NULL);
1462
 
 
 
835
  session->my_eof();
1463
836
  return 0;
1464
837
}
1465
838
 
1466
 
int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv)
 
839
 
 
840
int ha_rollback_to_savepoint(Session *session, SAVEPOINT *sv)
1467
841
{
1468
 
  int error=0;
1469
 
  THD_TRANS *trans= (thd->in_sub_stmt ? &thd->transaction.stmt :
1470
 
                                        &thd->transaction.all);
 
842
  int error= 0;
 
843
  Session_TRANS *trans= &session->transaction.all;
1471
844
  Ha_trx_info *ha_info, *ha_info_next;
1472
845
 
1473
846
  trans->no_2pc=0;
1478
851
  for (ha_info= sv->ha_list; ha_info; ha_info= ha_info->next())
1479
852
  {
1480
853
    int err;
1481
 
    handlerton *ht= ha_info->ht();
1482
 
    assert(ht);
1483
 
    assert(ht->savepoint_set != 0);
1484
 
    if ((err= ht->savepoint_rollback(ht, thd,
1485
 
                                     (uchar *)(sv+1)+ht->savepoint_offset)))
 
854
    StorageEngine *engine= ha_info->engine();
 
855
    assert(engine);
 
856
    if ((err= engine->savepoint_rollback(session,
 
857
                                         (void *)(sv+1))))
1486
858
    { // cannot happen
1487
859
      my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
1488
 
      error=1;
 
860
      error= 1;
1489
861
    }
1490
 
    status_var_increment(thd->status_var.ha_savepoint_rollback_count);
1491
 
    trans->no_2pc|= ht->prepare == 0;
 
862
    status_var_increment(session->status_var.ha_savepoint_rollback_count);
 
863
    trans->no_2pc|= not engine->has_2pc();
1492
864
  }
1493
865
  /*
1494
866
    rolling back the transaction in all storage engines that were not part of
1498
870
       ha_info= ha_info_next)
1499
871
  {
1500
872
    int err;
1501
 
    handlerton *ht= ha_info->ht();
1502
 
    if ((err= ht->rollback(ht, thd, !thd->in_sub_stmt)))
 
873
    StorageEngine *engine= ha_info->engine();
 
874
    if ((err= engine->rollback(session, !(0))))
1503
875
    { // cannot happen
1504
876
      my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
1505
 
      error=1;
 
877
      error= 1;
1506
878
    }
1507
 
    status_var_increment(thd->status_var.ha_rollback_count);
 
879
    status_var_increment(session->status_var.ha_rollback_count);
1508
880
    ha_info_next= ha_info->next();
1509
881
    ha_info->reset(); /* keep it conveniently zero-filled */
1510
882
  }
1511
883
  trans->ha_list= sv->ha_list;
1512
 
  return(error);
 
884
  return error;
1513
885
}
1514
886
 
1515
887
/**
1518
890
  section "4.33.4 SQL-statements and transaction states",
1519
891
  SAVEPOINT is *not* transaction-initiating SQL-statement
1520
892
*/
1521
 
int ha_savepoint(THD *thd, SAVEPOINT *sv)
 
893
int ha_savepoint(Session *session, SAVEPOINT *sv)
1522
894
{
1523
 
  int error=0;
1524
 
  THD_TRANS *trans= (thd->in_sub_stmt ? &thd->transaction.stmt :
1525
 
                                        &thd->transaction.all);
 
895
  int error= 0;
 
896
  Session_TRANS *trans= &session->transaction.all;
1526
897
  Ha_trx_info *ha_info= trans->ha_list;
1527
898
  for (; ha_info; ha_info= ha_info->next())
1528
899
  {
1529
900
    int err;
1530
 
    handlerton *ht= ha_info->ht();
1531
 
    assert(ht);
1532
 
    if (! ht->savepoint_set)
 
901
    StorageEngine *engine= ha_info->engine();
 
902
    assert(engine);
 
903
#ifdef NOT_IMPLEMENTED /*- TODO (examine this againt the original code base) */
 
904
    if (! engine->savepoint_set)
1533
905
    {
1534
906
      my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "SAVEPOINT");
1535
 
      error=1;
 
907
      error= 1;
1536
908
      break;
1537
 
    }
1538
 
    if ((err= ht->savepoint_set(ht, thd, (uchar *)(sv+1)+ht->savepoint_offset)))
 
909
    } 
 
910
#endif
 
911
    if ((err= engine->savepoint_set(session, (void *)(sv+1))))
1539
912
    { // cannot happen
1540
913
      my_error(ER_GET_ERRNO, MYF(0), err);
1541
 
      error=1;
 
914
      error= 1;
1542
915
    }
1543
 
    status_var_increment(thd->status_var.ha_savepoint_count);
 
916
    status_var_increment(session->status_var.ha_savepoint_count);
1544
917
  }
1545
918
  /*
1546
919
    Remember the list of registered storage engines. All new
1547
920
    engines are prepended to the beginning of the list.
1548
921
  */
1549
922
  sv->ha_list= trans->ha_list;
1550
 
  return(error);
 
923
  return error;
1551
924
}
1552
925
 
1553
 
int ha_release_savepoint(THD *thd, SAVEPOINT *sv)
 
926
int ha_release_savepoint(Session *session, SAVEPOINT *sv)
1554
927
{
1555
 
  int error=0;
 
928
  int error= 0;
1556
929
  Ha_trx_info *ha_info= sv->ha_list;
1557
930
 
1558
931
  for (; ha_info; ha_info= ha_info->next())
1559
932
  {
1560
933
    int err;
1561
 
    handlerton *ht= ha_info->ht();
 
934
    StorageEngine *engine= ha_info->engine();
1562
935
    /* Savepoint life time is enclosed into transaction life time. */
1563
 
    assert(ht);
1564
 
    if (!ht->savepoint_release)
1565
 
      continue;
1566
 
    if ((err= ht->savepoint_release(ht, thd,
1567
 
                                    (uchar *)(sv+1) + ht->savepoint_offset)))
 
936
    assert(engine);
 
937
    if ((err= engine->savepoint_release(session,
 
938
                                        (void *)(sv+1))))
1568
939
    { // cannot happen
1569
940
      my_error(ER_GET_ERRNO, MYF(0), err);
1570
 
      error=1;
 
941
      error= 1;
1571
942
    }
1572
943
  }
1573
 
  return(error);
1574
 
}
1575
 
 
1576
 
 
1577
 
static bool snapshot_handlerton(THD *thd, plugin_ref plugin, void *arg)
1578
 
{
1579
 
  handlerton *hton= plugin_data(plugin, handlerton *);
1580
 
  if (hton->state == SHOW_OPTION_YES &&
1581
 
      hton->start_consistent_snapshot)
1582
 
  {
1583
 
    hton->start_consistent_snapshot(hton, thd);
1584
 
    *((bool *)arg)= false;
1585
 
  }
1586
 
  return false;
1587
 
}
1588
 
 
1589
 
int ha_start_consistent_snapshot(THD *thd)
1590
 
{
1591
 
  bool warn= true;
1592
 
 
1593
 
  plugin_foreach(thd, snapshot_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN, &warn);
1594
 
 
1595
 
  /*
1596
 
    Same idea as when one wants to CREATE TABLE in one engine which does not
1597
 
    exist:
1598
 
  */
1599
 
  if (warn)
1600
 
    push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
1601
 
                 "This MySQL server does not support any "
1602
 
                 "consistent-read capable storage engine");
1603
 
  return 0;
1604
 
}
1605
 
 
1606
 
 
1607
 
static bool flush_handlerton(THD *thd __attribute__((unused)),
1608
 
                             plugin_ref plugin,
1609
 
                             void *arg __attribute__((unused)))
1610
 
{
1611
 
  handlerton *hton= plugin_data(plugin, handlerton *);
1612
 
  if (hton->state == SHOW_OPTION_YES && hton->flush_logs && 
1613
 
      hton->flush_logs(hton))
1614
 
    return true;
1615
 
  return false;
1616
 
}
1617
 
 
1618
 
 
1619
 
bool ha_flush_logs(handlerton *db_type)
1620
 
{
1621
 
  if (db_type == NULL)
1622
 
  {
1623
 
    if (plugin_foreach(NULL, flush_handlerton,
1624
 
                          DRIZZLE_STORAGE_ENGINE_PLUGIN, 0))
1625
 
      return true;
1626
 
  }
1627
 
  else
1628
 
  {
1629
 
    if (db_type->state != SHOW_OPTION_YES ||
1630
 
        (db_type->flush_logs && db_type->flush_logs(db_type)))
1631
 
      return true;
1632
 
  }
1633
 
  return false;
1634
 
}
1635
 
 
1636
 
static const char *check_lowercase_names(handler *file, const char *path,
1637
 
                                         char *tmp_path)
1638
 
{
1639
 
  if (lower_case_table_names != 2 || (file->ha_table_flags() & HA_FILE_BASED))
1640
 
    return path;
1641
 
 
1642
 
  /* Ensure that table handler get path in lower case */
1643
 
  if (tmp_path != path)
1644
 
    stpcpy(tmp_path, path);
1645
 
 
1646
 
  /*
1647
 
    we only should turn into lowercase database/table part
1648
 
    so start the process after homedirectory
1649
 
  */
1650
 
  my_casedn_str(files_charset_info, tmp_path + mysql_data_home_len);
1651
 
  return tmp_path;
1652
 
}
1653
 
 
1654
 
 
1655
 
/**
1656
 
  An interceptor to hijack the text of the error message without
1657
 
  setting an error in the thread. We need the text to present it
1658
 
  in the form of a warning to the user.
1659
 
*/
1660
 
 
1661
 
struct Ha_delete_table_error_handler: public Internal_error_handler
1662
 
{
1663
 
public:
1664
 
  virtual bool handle_error(uint sql_errno,
1665
 
                            const char *message,
1666
 
                            DRIZZLE_ERROR::enum_warning_level level,
1667
 
                            THD *thd);
1668
 
  char buff[DRIZZLE_ERRMSG_SIZE];
1669
 
};
1670
 
 
1671
 
 
1672
 
bool
1673
 
Ha_delete_table_error_handler::
1674
 
handle_error(uint sql_errno  __attribute__((unused)),
1675
 
             const char *message,
1676
 
             DRIZZLE_ERROR::enum_warning_level level __attribute__((unused)),
1677
 
             THD *thd __attribute__((unused)))
1678
 
{
1679
 
  /* Grab the error message */
1680
 
  strmake(buff, message, sizeof(buff)-1);
1681
 
  return true;
1682
 
}
1683
 
 
1684
 
 
1685
 
/**
1686
 
  This should return ENOENT if the file doesn't exists.
1687
 
  The .frm file will be deleted only if we return 0 or ENOENT
1688
 
*/
1689
 
int ha_delete_table(THD *thd, handlerton *table_type, const char *path,
1690
 
                    const char *db, const char *alias, bool generate_warning)
1691
 
{
1692
 
  handler *file;
1693
 
  char tmp_path[FN_REFLEN];
1694
 
  int error;
1695
 
  TABLE dummy_table;
1696
 
  TABLE_SHARE dummy_share;
1697
 
 
1698
 
  memset(&dummy_table, 0, sizeof(dummy_table));
1699
 
  memset(&dummy_share, 0, sizeof(dummy_share));
1700
 
  dummy_table.s= &dummy_share;
1701
 
 
1702
 
  /* DB_TYPE_UNKNOWN is used in ALTER TABLE when renaming only .frm files */
1703
 
  if (table_type == NULL ||
1704
 
      ! (file=get_new_handler((TABLE_SHARE*)0, thd->mem_root, table_type)))
1705
 
    return(ENOENT);
1706
 
 
1707
 
  path= check_lowercase_names(file, path, tmp_path);
1708
 
  if ((error= file->ha_delete_table(path)) && generate_warning)
1709
 
  {
1710
 
    /*
1711
 
      Because file->print_error() use my_error() to generate the error message
1712
 
      we use an internal error handler to intercept it and store the text
1713
 
      in a temporary buffer. Later the message will be presented to user
1714
 
      as a warning.
1715
 
    */
1716
 
    Ha_delete_table_error_handler ha_delete_table_error_handler;
1717
 
 
1718
 
    /* Fill up strucutures that print_error may need */
1719
 
    dummy_share.path.str= (char*) path;
1720
 
    dummy_share.path.length= strlen(path);
1721
 
    dummy_share.db.str= (char*) db;
1722
 
    dummy_share.db.length= strlen(db);
1723
 
    dummy_share.table_name.str= (char*) alias;
1724
 
    dummy_share.table_name.length= strlen(alias);
1725
 
    dummy_table.alias= alias;
1726
 
 
1727
 
    file->change_table_ptr(&dummy_table, &dummy_share);
1728
 
 
1729
 
    thd->push_internal_handler(&ha_delete_table_error_handler);
1730
 
    file->print_error(error, 0);
1731
 
 
1732
 
    thd->pop_internal_handler();
1733
 
 
1734
 
    /*
1735
 
      XXX: should we convert *all* errors to warnings here?
1736
 
      What if the error is fatal?
1737
 
    */
1738
 
    push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_ERROR, error,
1739
 
                ha_delete_table_error_handler.buff);
1740
 
  }
1741
 
  delete file;
1742
 
  return(error);
1743
 
}
 
944
  return error;
 
945
}
 
946
 
 
947
 
 
948
 
 
949
 
1744
950
 
1745
951
/****************************************************************************
1746
952
** General handler functions
1747
953
****************************************************************************/
 
954
handler::~handler(void)
 
955
{
 
956
  assert(locked == false);
 
957
  /* TODO: assert(inited == NONE); */
 
958
}
 
959
 
 
960
 
1748
961
handler *handler::clone(MEM_ROOT *mem_root)
1749
962
{
1750
963
  handler *new_handler= get_new_handler(table->s, mem_root, table->s->db_type());
1751
964
  /*
1752
965
    Allocate handler->ref here because otherwise ha_open will allocate it
1753
 
    on this->table->mem_root and we will not be able to reclaim that memory 
 
966
    on this->table->mem_root and we will not be able to reclaim that memory
1754
967
    when the clone handler object is destroyed.
1755
968
  */
1756
 
  if (!(new_handler->ref= (uchar*) alloc_root(mem_root, ALIGN_SIZE(ref_length)*2)))
 
969
  if (!(new_handler->ref= (unsigned char*) alloc_root(mem_root, ALIGN_SIZE(ref_length)*2)))
1757
970
    return NULL;
1758
971
  if (new_handler && !new_handler->ha_open(table,
1759
972
                                           table->s->normalized_path.str,
1760
 
                                           table->db_stat,
 
973
                                           table->getDBStat(),
1761
974
                                           HA_OPEN_IGNORE_IF_LOCKED))
1762
975
    return new_handler;
1763
976
  return NULL;
1764
977
}
1765
978
 
1766
 
 
 
979
int handler::ha_index_init(uint32_t idx, bool sorted)
 
980
{
 
981
  int result;
 
982
  assert(inited == NONE);
 
983
  if (!(result= index_init(idx, sorted)))
 
984
    inited=INDEX;
 
985
  end_range= NULL;
 
986
  return result;
 
987
}
 
988
 
 
989
int handler::ha_index_end()
 
990
{
 
991
  assert(inited==INDEX);
 
992
  inited=NONE;
 
993
  end_range= NULL;
 
994
  return(index_end());
 
995
}
 
996
 
 
997
int handler::ha_rnd_init(bool scan)
 
998
{
 
999
  int result;
 
1000
  assert(inited==NONE || (inited==RND && scan));
 
1001
  inited= (result= rnd_init(scan)) ? NONE: RND;
 
1002
 
 
1003
  return result;
 
1004
}
 
1005
 
 
1006
int handler::ha_rnd_end()
 
1007
{
 
1008
  assert(inited==RND);
 
1009
  inited=NONE;
 
1010
  return(rnd_end());
 
1011
}
 
1012
 
 
1013
int handler::ha_index_or_rnd_end()
 
1014
{
 
1015
  return inited == INDEX ? ha_index_end() : inited == RND ? ha_rnd_end() : 0;
 
1016
}
 
1017
 
 
1018
handler::Table_flags handler::ha_table_flags() const
 
1019
{
 
1020
  return cached_table_flags;
 
1021
}
 
1022
 
 
1023
void handler::ha_start_bulk_insert(ha_rows rows)
 
1024
{
 
1025
  estimation_rows_to_insert= rows;
 
1026
  start_bulk_insert(rows);
 
1027
}
 
1028
 
 
1029
int handler::ha_end_bulk_insert()
 
1030
{
 
1031
  estimation_rows_to_insert= 0;
 
1032
  return end_bulk_insert();
 
1033
}
 
1034
 
 
1035
void handler::change_table_ptr(Table *table_arg, TableShare *share)
 
1036
{
 
1037
  table= table_arg;
 
1038
  table_share= share;
 
1039
}
 
1040
 
 
1041
const key_map *handler::keys_to_use_for_scanning()
 
1042
{
 
1043
  return &key_map_empty;
 
1044
}
 
1045
 
 
1046
bool handler::has_transactions()
 
1047
{
 
1048
  return (ha_table_flags() & HA_NO_TRANSACTIONS) == 0;
 
1049
}
1767
1050
 
1768
1051
void handler::ha_statistic_increment(ulong SSV::*offset) const
1769
1052
{
1770
1053
  status_var_increment(table->in_use->status_var.*offset);
1771
1054
}
1772
1055
 
1773
 
void **handler::ha_data(THD *thd) const
1774
 
{
1775
 
  return thd_ha_data(thd, ht);
1776
 
}
1777
 
 
1778
 
THD *handler::ha_thd(void) const
1779
 
{
1780
 
  assert(!table || !table->in_use || table->in_use == current_thd);
1781
 
  return (table && table->in_use) ? table->in_use : current_thd;
1782
 
}
 
1056
void **handler::ha_data(Session *session) const
 
1057
{
 
1058
  return session_ha_data(session, engine);
 
1059
}
 
1060
 
 
1061
Session *handler::ha_session(void) const
 
1062
{
 
1063
  assert(!table || !table->in_use || table->in_use == current_session);
 
1064
  return (table && table->in_use) ? table->in_use : current_session;
 
1065
}
 
1066
 
 
1067
 
 
1068
bool handler::is_fatal_error(int error, uint32_t flags)
 
1069
{
 
1070
  if (!error ||
 
1071
      ((flags & HA_CHECK_DUP_KEY) &&
 
1072
       (error == HA_ERR_FOUND_DUPP_KEY ||
 
1073
        error == HA_ERR_FOUND_DUPP_UNIQUE)))
 
1074
    return false;
 
1075
  return true;
 
1076
}
 
1077
 
 
1078
 
 
1079
ha_rows handler::records() { return stats.records; }
1783
1080
 
1784
1081
/**
1785
1082
  Open database-handler.
1787
1084
  Try O_RDONLY if cannot open as O_RDWR
1788
1085
  Don't wait for locks if not HA_OPEN_WAIT_IF_LOCKED is set
1789
1086
*/
1790
 
int handler::ha_open(TABLE *table_arg, const char *name, int mode,
 
1087
int handler::ha_open(Table *table_arg, const char *name, int mode,
1791
1088
                     int test_if_locked)
1792
1089
{
1793
1090
  int error;
1816
1113
    (void) extra(HA_EXTRA_NO_READCHECK);        // Not needed in SQL
1817
1114
 
1818
1115
    /* ref is already allocated for us if we're called from handler::clone() */
1819
 
    if (!ref && !(ref= (uchar*) alloc_root(&table->mem_root, 
 
1116
    if (!ref && !(ref= (unsigned char*) alloc_root(&table->mem_root,
1820
1117
                                          ALIGN_SIZE(ref_length)*2)))
1821
1118
    {
1822
1119
      close();
1826
1123
      dup_ref=ref+ALIGN_SIZE(ref_length);
1827
1124
    cached_table_flags= table_flags();
1828
1125
  }
1829
 
  return(error);
 
1126
  return error;
1830
1127
}
1831
1128
 
1832
1129
/**
1836
1133
  handlers for random position
1837
1134
*/
1838
1135
 
1839
 
int handler::rnd_pos_by_record(uchar *record)
 
1136
int handler::rnd_pos_by_record(unsigned char *record)
1840
1137
{
1841
1138
  register int error;
1842
1139
 
1843
1140
  position(record);
1844
1141
  if (inited && (error= ha_index_end()))
1845
 
    return(error);
 
1142
    return error;
1846
1143
  if ((error= ha_rnd_init(false)))
1847
 
    return(error);
 
1144
    return error;
1848
1145
 
1849
 
  return(rnd_pos(record, ref));
 
1146
  return rnd_pos(record, ref);
1850
1147
}
1851
1148
 
1852
1149
/**
1855
1152
  This is never called for InnoDB tables, as these table types
1856
1153
  has the HA_STATS_RECORDS_IS_EXACT set.
1857
1154
*/
1858
 
int handler::read_first_row(uchar * buf, uint primary_key)
 
1155
int handler::read_first_row(unsigned char * buf, uint32_t primary_key)
1859
1156
{
1860
1157
  register int error;
1861
1158
 
1880
1177
    error=index_first(buf);
1881
1178
    (void) ha_index_end();
1882
1179
  }
1883
 
  return(error);
 
1180
  return error;
1884
1181
}
1885
1182
 
1886
1183
/**
1910
1207
void handler::adjust_next_insert_id_after_explicit_value(uint64_t nr)
1911
1208
{
1912
1209
  /*
1913
 
    If we have set THD::next_insert_id previously and plan to insert an
 
1210
    If we have set Session::next_insert_id previously and plan to insert an
1914
1211
    explicitely-specified value larger than this, we need to increase
1915
 
    THD::next_insert_id to be greater than the explicit value.
 
1212
    Session::next_insert_id to be greater than the explicit value.
1916
1213
  */
1917
1214
  if ((next_insert_id > 0) && (nr >= next_insert_id))
1918
1215
    set_next_insert_id(compute_next_insert_id(nr, &table->in_use->variables));
1960
1257
 
1961
1258
  Updates columns with type NEXT_NUMBER if:
1962
1259
 
1963
 
  - If column value is set to NULL (in which case
1964
 
    auto_increment_field_not_null is 0)
 
1260
  - If column value is set to NULL (in which case auto_increment_field_not_null is false)
1965
1261
  - If column is set to 0 and (sql_mode & MODE_NO_AUTO_VALUE_ON_ZERO) is not
1966
1262
    set. In the future we will only set NEXT_NUMBER fields if one sets them
1967
1263
    to NULL (or they are not included in the insert list).
1988
1284
    again to reserve a new interval.
1989
1285
 
1990
1286
  - In both cases, the reserved intervals are remembered in
1991
 
    thd->auto_inc_intervals_in_cur_stmt_for_binlog if statement-based
 
1287
    session->auto_inc_intervals_in_cur_stmt_for_binlog if statement-based
1992
1288
    binlogging; the last reserved interval is remembered in
1993
1289
    auto_inc_interval_for_cur_row.
1994
1290
 
2002
1298
    start counting from the inserted value.
2003
1299
 
2004
1300
    This function's "outputs" are: the table's auto_increment field is filled
2005
 
    with a value, thd->next_insert_id is filled with the value to use for the
 
1301
    with a value, session->next_insert_id is filled with the value to use for the
2006
1302
    next row, if a value was autogenerated for the current row it is stored in
2007
 
    thd->insert_id_for_cur_row, if get_auto_increment() was called
2008
 
    thd->auto_inc_interval_for_cur_row is modified, if that interval is not
2009
 
    present in thd->auto_inc_intervals_in_cur_stmt_for_binlog it is added to
 
1303
    session->insert_id_for_cur_row, if get_auto_increment() was called
 
1304
    session->auto_inc_interval_for_cur_row is modified, if that interval is not
 
1305
    present in session->auto_inc_intervals_in_cur_stmt_for_binlog it is added to
2010
1306
    this list.
2011
1307
 
2012
1308
  @todo
2033
1329
{
2034
1330
  uint64_t nr, nb_reserved_values;
2035
1331
  bool append= false;
2036
 
  THD *thd= table->in_use;
2037
 
  struct system_variables *variables= &thd->variables;
 
1332
  Session *session= table->in_use;
 
1333
  struct system_variables *variables= &session->variables;
2038
1334
 
2039
1335
  /*
2040
1336
    next_insert_id is a "cursor" into the reserved interval, it may go greater
2042
1338
  */
2043
1339
  assert(next_insert_id >= auto_inc_interval_for_cur_row.minimum());
2044
1340
 
2045
 
  if (((nr= table->next_number_field->val_int()) != 0) || 
2046
 
      (table->auto_increment_field_not_null && (thd->variables.sql_mode & MODE_NO_AUTO_VALUE_ON_ZERO)))
 
1341
  /* We check if auto_increment_field_not_null is false
 
1342
     for an auto increment column, not a magic value like NULL is.
 
1343
     same as sql_mode=NO_AUTO_VALUE_ON_ZERO */
 
1344
 
 
1345
  if ((nr= table->next_number_field->val_int()) != 0
 
1346
      || table->auto_increment_field_not_null)
2047
1347
  {
2048
1348
    /*
2049
1349
      Update next_insert_id if we had already generated a value in this
2053
1353
    */
2054
1354
    adjust_next_insert_id_after_explicit_value(nr);
2055
1355
    insert_id_for_cur_row= 0; // didn't generate anything
2056
 
    return(0);
 
1356
 
 
1357
    return 0;
2057
1358
  }
2058
1359
 
2059
1360
  if ((nr= next_insert_id) >= auto_inc_interval_for_cur_row.maximum())
2060
1361
  {
2061
1362
    /* next_insert_id is beyond what is reserved, so we reserve more. */
2062
1363
    const Discrete_interval *forced=
2063
 
      thd->auto_inc_intervals_forced.get_next();
 
1364
      session->auto_inc_intervals_forced.get_next();
2064
1365
    if (forced != NULL)
2065
1366
    {
2066
1367
      nr= forced->minimum();
2072
1373
        handler::estimation_rows_to_insert was set by
2073
1374
        handler::ha_start_bulk_insert(); if 0 it means "unknown".
2074
1375
      */
2075
 
      uint nb_already_reserved_intervals=
2076
 
        thd->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements();
 
1376
      uint32_t nb_already_reserved_intervals=
 
1377
        session->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements();
2077
1378
      uint64_t nb_desired_values;
2078
1379
      /*
2079
1380
        If an estimation was given to the engine:
2094
1395
        /* avoid overflow in formula, with this if() */
2095
1396
        if (nb_already_reserved_intervals <= AUTO_INC_DEFAULT_NB_MAX_BITS)
2096
1397
        {
2097
 
          nb_desired_values= AUTO_INC_DEFAULT_NB_ROWS * 
 
1398
          nb_desired_values= AUTO_INC_DEFAULT_NB_ROWS *
2098
1399
            (1 << nb_already_reserved_intervals);
2099
 
          set_if_smaller(nb_desired_values, AUTO_INC_DEFAULT_NB_MAX);
 
1400
          set_if_smaller(nb_desired_values, (uint64_t)AUTO_INC_DEFAULT_NB_MAX);
2100
1401
        }
2101
1402
        else
2102
1403
          nb_desired_values= AUTO_INC_DEFAULT_NB_MAX;
2107
1408
                         nb_desired_values, &nr,
2108
1409
                         &nb_reserved_values);
2109
1410
      if (nr == ~(uint64_t) 0)
2110
 
        return(HA_ERR_AUTOINC_READ_FAILED);  // Mark failure
2111
 
      
 
1411
        return HA_ERR_AUTOINC_READ_FAILED;  // Mark failure
 
1412
 
2112
1413
      /*
2113
1414
        That rounding below should not be needed when all engines actually
2114
1415
        respect offset and increment in get_auto_increment(). But they don't
2119
1420
      */
2120
1421
      nr= compute_next_insert_id(nr-1, variables);
2121
1422
    }
2122
 
    
 
1423
 
2123
1424
    if (table->s->next_number_keypart == 0)
2124
1425
    {
2125
1426
      /* We must defer the appending until "nr" has been possibly truncated */
2132
1433
    /*
2133
1434
      first test if the query was aborted due to strict mode constraints
2134
1435
    */
2135
 
    if (thd->killed == THD::KILL_BAD_DATA)
2136
 
      return(HA_ERR_AUTOINC_ERANGE);
 
1436
    if (session->killed == Session::KILL_BAD_DATA)
 
1437
      return HA_ERR_AUTOINC_ERANGE;
2137
1438
 
2138
1439
    /*
2139
1440
      field refused this value (overflow) and truncated it, use the result of
2151
1452
  {
2152
1453
    auto_inc_interval_for_cur_row.replace(nr, nb_reserved_values,
2153
1454
                                          variables->auto_increment_increment);
2154
 
    /* Row-based replication does not need to store intervals in binlog */
2155
 
    if (!thd->current_stmt_binlog_row_based)
2156
 
        thd->auto_inc_intervals_in_cur_stmt_for_binlog.append(auto_inc_interval_for_cur_row.minimum(),
2157
 
                                                              auto_inc_interval_for_cur_row.values(),
2158
 
                                                              variables->auto_increment_increment);
2159
1455
  }
2160
1456
 
2161
1457
  /*
2172
1468
  */
2173
1469
  set_next_insert_id(compute_next_insert_id(nr, variables));
2174
1470
 
2175
 
  return(0);
2176
 
}
2177
 
 
2178
 
 
2179
 
/**
2180
 
  MySQL signal that it changed the column bitmap
2181
 
 
2182
 
  This is for handlers that needs to setup their own column bitmaps.
2183
 
  Normally the handler should set up their own column bitmaps in
2184
 
  index_init() or rnd_init() and in any column_bitmaps_signal() call after
2185
 
  this.
2186
 
 
2187
 
  The handler is allowed to do changes to the bitmap after a index_init or
2188
 
  rnd_init() call is made as after this, MySQL will not use the bitmap
2189
 
  for any program logic checking.
2190
 
*/
2191
 
void handler::column_bitmaps_signal()
2192
 
{
2193
 
  return;
 
1471
  return 0;
2194
1472
}
2195
1473
 
2196
1474
 
2209
1487
  @param first_value         (OUT) the first value reserved by the handler
2210
1488
  @param nb_reserved_values  (OUT) how many values the handler reserved
2211
1489
*/
2212
 
void handler::get_auto_increment(uint64_t offset __attribute__((unused)),
2213
 
                                 uint64_t increment __attribute__((unused)),
2214
 
                                 uint64_t nb_desired_values __attribute__((unused)),
 
1490
void handler::get_auto_increment(uint64_t ,
 
1491
                                 uint64_t ,
 
1492
                                 uint64_t ,
2215
1493
                                 uint64_t *first_value,
2216
1494
                                 uint64_t *nb_reserved_values)
2217
1495
{
2219
1497
  int error;
2220
1498
 
2221
1499
  (void) extra(HA_EXTRA_KEYREAD);
2222
 
  table->mark_columns_used_by_index_no_reset(table->s->next_number_index,
2223
 
                                        table->read_set);
2224
 
  column_bitmaps_signal();
 
1500
  table->mark_columns_used_by_index_no_reset(table->s->next_number_index);
2225
1501
  index_init(table->s->next_number_index, 1);
2226
1502
  if (table->s->next_number_keypart == 0)
2227
1503
  {                                             // Autoincrement at key-start
2235
1511
  }
2236
1512
  else
2237
1513
  {
2238
 
    uchar key[MAX_KEY_LENGTH];
 
1514
    unsigned char key[MAX_KEY_LENGTH];
2239
1515
    key_copy(key, table->record[0],
2240
1516
             table->key_info + table->s->next_number_index,
2241
1517
             table->s->next_number_key_offset);
2279
1555
}
2280
1556
 
2281
1557
 
2282
 
void handler::print_keydup_error(uint key_nr, const char *msg)
 
1558
void handler::print_keydup_error(uint32_t key_nr, const char *msg)
2283
1559
{
2284
1560
  /* Write the duplicated key in the error message */
2285
1561
  char key[MAX_KEY_LENGTH];
2294
1570
  else
2295
1571
  {
2296
1572
    /* Table is opened and defined at this point */
2297
 
    key_unpack(&str,table,(uint) key_nr);
2298
 
    uint max_length=DRIZZLE_ERRMSG_SIZE-(uint) strlen(msg);
 
1573
    key_unpack(&str,table,(uint32_t) key_nr);
 
1574
    uint32_t max_length=DRIZZLE_ERRMSG_SIZE-(uint32_t) strlen(msg);
2299
1575
    if (str.length() >= max_length)
2300
1576
    {
2301
1577
      str.length(max_length-4);
2339
1615
    break;
2340
1616
  case HA_ERR_FOUND_DUPP_KEY:
2341
1617
  {
2342
 
    uint key_nr=get_dup_key(error);
 
1618
    uint32_t key_nr=get_dup_key(error);
2343
1619
    if ((int) key_nr >= 0)
2344
1620
    {
2345
1621
      print_keydup_error(key_nr, ER(ER_DUP_ENTRY_WITH_KEY_NAME));
2350
1626
  }
2351
1627
  case HA_ERR_FOREIGN_DUPLICATE_KEY:
2352
1628
  {
2353
 
    uint key_nr= get_dup_key(error);
 
1629
    uint32_t key_nr= get_dup_key(error);
2354
1630
    if ((int) key_nr >= 0)
2355
1631
    {
2356
 
      uint max_length;
 
1632
      uint32_t max_length;
2357
1633
      /* Write the key in the error message */
2358
1634
      char key[MAX_KEY_LENGTH];
2359
1635
      String str(key,sizeof(key),system_charset_info);
2360
1636
      /* Table is opened and defined at this point */
2361
 
      key_unpack(&str,table,(uint) key_nr);
 
1637
      key_unpack(&str,table,(uint32_t) key_nr);
2362
1638
      max_length= (DRIZZLE_ERRMSG_SIZE-
2363
 
                   (uint) strlen(ER(ER_FOREIGN_DUPLICATE_KEY)));
 
1639
                   (uint32_t) strlen(ER(ER_FOREIGN_DUPLICATE_KEY)));
2364
1640
      if (str.length() >= max_length)
2365
1641
      {
2366
1642
        str.length(max_length-4);
2452
1728
  case HA_ERR_DROP_INDEX_FK:
2453
1729
  {
2454
1730
    const char *ptr= "???";
2455
 
    uint key_nr= get_dup_key(error);
 
1731
    uint32_t key_nr= get_dup_key(error);
2456
1732
    if ((int) key_nr >= 0)
2457
1733
      ptr= table->key_info[key_nr].name;
2458
1734
    my_error(ER_DROP_INDEX_FK, MYF(0), ptr);
2474
1750
    my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
2475
1751
               ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
2476
1752
    return;
2477
 
    break;
2478
1753
  default:
2479
1754
    {
2480
1755
      /* The error was "unknown" to this function.
2484
1759
      temporary= get_error_message(error, &str);
2485
1760
      if (!str.is_empty())
2486
1761
      {
2487
 
        const char* engine= table_type();
2488
 
        if (temporary)
2489
 
          my_error(ER_GET_TEMPORARY_ERRMSG, MYF(0), error, str.ptr(), engine);
2490
 
        else
2491
 
          my_error(ER_GET_ERRMSG, MYF(0), error, str.ptr(), engine);
 
1762
        const char* engine_name= engine->getName().c_str();
 
1763
        if (temporary)
 
1764
          my_error(ER_GET_TEMPORARY_ERRMSG, MYF(0), error, str.ptr(),
 
1765
                   engine_name);
 
1766
        else
 
1767
          my_error(ER_GET_ERRMSG, MYF(0), error, str.ptr(), engine_name);
2492
1768
      }
2493
1769
      else
2494
 
        my_error(ER_GET_ERRNO,errflag,error);
 
1770
      {
 
1771
              my_error(ER_GET_ERRNO,errflag,error);
 
1772
      }
2495
1773
      return;
2496
1774
    }
2497
1775
  }
2498
1776
  my_error(textno, errflag, table_share->table_name.str, error);
2499
 
  return;
2500
1777
}
2501
1778
 
2502
1779
 
2509
1786
  @return
2510
1787
    Returns true if this is a temporary error
2511
1788
*/
2512
 
bool handler::get_error_message(int error __attribute__((unused)),
2513
 
                                String* buf __attribute__((unused)))
 
1789
bool handler::get_error_message(int , String* )
2514
1790
{
2515
1791
  return false;
2516
1792
}
2517
1793
 
2518
1794
 
2519
 
int handler::ha_check_for_upgrade(HA_CHECK_OPT *check_opt)
2520
 
{
2521
 
  KEY *keyinfo, *keyend;
2522
 
  KEY_PART_INFO *keypart, *keypartend;
2523
 
 
2524
 
  if (!table->s->mysql_version)
2525
 
  {
2526
 
    /* check for blob-in-key error */
2527
 
    keyinfo= table->key_info;
2528
 
    keyend= table->key_info + table->s->keys;
2529
 
    for (; keyinfo < keyend; keyinfo++)
2530
 
    {
2531
 
      keypart= keyinfo->key_part;
2532
 
      keypartend= keypart + keyinfo->key_parts;
2533
 
      for (; keypart < keypartend; keypart++)
2534
 
      {
2535
 
        if (!keypart->fieldnr)
2536
 
          continue;
2537
 
        Field *field= table->field[keypart->fieldnr-1];
2538
 
        if (field->type() == DRIZZLE_TYPE_BLOB)
2539
 
        {
2540
 
          if (check_opt->sql_flags & TT_FOR_UPGRADE)
2541
 
            check_opt->flags= T_MEDIUM;
2542
 
          return HA_ADMIN_NEEDS_CHECK;
2543
 
        }
2544
 
      }
2545
 
    }
2546
 
  }
2547
 
  return check_for_upgrade(check_opt);
2548
 
}
2549
 
 
2550
 
 
2551
1795
/* Code left, but Drizzle has no legacy yet (while MySQL did) */
2552
1796
int handler::check_old_types()
2553
1797
{
2554
1798
  return 0;
2555
1799
}
2556
1800
 
2557
 
 
2558
 
static bool update_frm_version(TABLE *table)
2559
 
{
2560
 
  char path[FN_REFLEN];
2561
 
  File file;
2562
 
  bool result= true;
2563
 
 
2564
 
  /*
2565
 
    No need to update frm version in case table was created or checked
2566
 
    by server with the same version. This also ensures that we do not
2567
 
    update frm version for temporary tables as this code doesn't support
2568
 
    temporary tables.
2569
 
  */
2570
 
  if (table->s->mysql_version == DRIZZLE_VERSION_ID)
2571
 
    return(0);
2572
 
 
2573
 
  strxmov(path, table->s->normalized_path.str, reg_ext, NullS);
2574
 
 
2575
 
  if ((file= my_open(path, O_RDWR|O_BINARY, MYF(MY_WME))) >= 0)
2576
 
  {
2577
 
    uchar version[4];
2578
 
    char *key= table->s->table_cache_key.str;
2579
 
    uint key_length= table->s->table_cache_key.length;
2580
 
    TABLE *entry;
2581
 
    HASH_SEARCH_STATE state;
2582
 
 
2583
 
    int4store(version, DRIZZLE_VERSION_ID);
2584
 
 
2585
 
    if (pwrite(file, (uchar*)version, 4, 51L) == 0)
2586
 
    {
2587
 
      result= false;
2588
 
      goto err;
2589
 
    }
2590
 
 
2591
 
    for (entry=(TABLE*) hash_first(&open_cache,(uchar*) key,key_length, &state);
2592
 
         entry;
2593
 
         entry= (TABLE*) hash_next(&open_cache,(uchar*) key,key_length, &state))
2594
 
      entry->s->mysql_version= DRIZZLE_VERSION_ID;
2595
 
  }
2596
 
err:
2597
 
  if (file >= 0)
2598
 
    VOID(my_close(file,MYF(MY_WME)));
2599
 
  return(result);
2600
 
}
2601
 
 
2602
 
 
2603
 
 
2604
1801
/**
2605
1802
  @return
2606
1803
    key if error because of duplicated keys
2607
1804
*/
2608
 
uint handler::get_dup_key(int error)
 
1805
uint32_t handler::get_dup_key(int error)
2609
1806
{
2610
 
  table->file->errkey  = (uint) -1;
 
1807
  table->file->errkey  = (uint32_t) -1;
2611
1808
  if (error == HA_ERR_FOUND_DUPP_KEY || error == HA_ERR_FOREIGN_DUPLICATE_KEY ||
2612
1809
      error == HA_ERR_FOUND_DUPP_UNIQUE ||
2613
1810
      error == HA_ERR_DROP_INDEX_FK)
2615
1812
  return(table->file->errkey);
2616
1813
}
2617
1814
 
2618
 
 
2619
 
/**
2620
 
  Delete all files with extension from bas_ext().
2621
 
 
2622
 
  @param name           Base name of table
2623
 
 
2624
 
  @note
2625
 
    We assume that the handler may return more extensions than
2626
 
    was actually used for the file.
2627
 
 
2628
 
  @retval
2629
 
    0   If we successfully deleted at least one file from base_ext and
2630
 
    didn't get any other errors than ENOENT
2631
 
  @retval
2632
 
    !0  Error
2633
 
*/
2634
 
int handler::delete_table(const char *name)
2635
 
{
2636
 
  int error= 0;
2637
 
  int enoent_or_zero= ENOENT;                   // Error if no file was deleted
2638
 
  char buff[FN_REFLEN];
2639
 
 
2640
 
  for (const char **ext=bas_ext(); *ext ; ext++)
2641
 
  {
2642
 
    fn_format(buff, name, "", *ext, MY_UNPACK_FILENAME|MY_APPEND_EXT);
2643
 
    if (my_delete_with_symlink(buff, MYF(0)))
2644
 
    {
2645
 
      if ((error= my_errno) != ENOENT)
2646
 
        break;
2647
 
    }
2648
 
    else
2649
 
      enoent_or_zero= 0;                        // No error for ENOENT
2650
 
    error= enoent_or_zero;
2651
 
  }
2652
 
  return error;
2653
 
}
2654
 
 
2655
 
 
2656
 
int handler::rename_table(const char * from, const char * to)
2657
 
{
2658
 
  int error= 0;
2659
 
  for (const char **ext= bas_ext(); *ext ; ext++)
2660
 
  {
2661
 
    if (rename_file_ext(from, to, *ext))
2662
 
    {
2663
 
      if ((error=my_errno) != ENOENT)
2664
 
        break;
2665
 
      error= 0;
2666
 
    }
2667
 
  }
2668
 
  return error;
2669
 
}
2670
 
 
2671
 
 
2672
1815
void handler::drop_table(const char *name)
2673
1816
{
2674
1817
  close();
2675
 
  delete_table(name);
 
1818
  engine->deleteTable(ha_session(), name);
2676
1819
}
2677
1820
 
2678
1821
 
2679
1822
/**
2680
1823
  Performs checks upon the table.
2681
1824
 
2682
 
  @param thd                thread doing CHECK TABLE operation
 
1825
  @param session                thread doing CHECK Table operation
2683
1826
  @param check_opt          options from the parser
2684
1827
 
2685
1828
  @retval
2687
1830
  @retval
2688
1831
    HA_ADMIN_NEEDS_UPGRADE    Table has structures requiring upgrade
2689
1832
  @retval
2690
 
    HA_ADMIN_NEEDS_ALTER      Table has structures requiring ALTER TABLE
 
1833
    HA_ADMIN_NEEDS_ALTER      Table has structures requiring ALTER Table
2691
1834
  @retval
2692
1835
    HA_ADMIN_NOT_IMPLEMENTED
2693
1836
*/
2694
 
int handler::ha_check(THD *thd, HA_CHECK_OPT *check_opt)
 
1837
int handler::ha_check(Session *, HA_CHECK_OPT *)
2695
1838
{
2696
 
  int error;
2697
 
 
2698
 
  if ((table->s->mysql_version >= DRIZZLE_VERSION_ID) &&
2699
 
      (check_opt->sql_flags & TT_FOR_UPGRADE))
2700
 
    return 0;
2701
 
 
2702
 
  if (table->s->mysql_version < DRIZZLE_VERSION_ID)
2703
 
  {
2704
 
    if ((error= check_old_types()))
2705
 
      return error;
2706
 
    error= ha_check_for_upgrade(check_opt);
2707
 
    if (error && (error != HA_ADMIN_NEEDS_CHECK))
2708
 
      return error;
2709
 
    if (!error && (check_opt->sql_flags & TT_FOR_UPGRADE))
2710
 
      return 0;
2711
 
  }
2712
 
  if ((error= check(thd, check_opt)))
2713
 
    return error;
2714
 
  return update_frm_version(table);
 
1839
  return HA_ADMIN_OK;
2715
1840
}
2716
1841
 
2717
1842
/**
2723
1848
void
2724
1849
handler::mark_trx_read_write()
2725
1850
{
2726
 
  Ha_trx_info *ha_info= &ha_thd()->ha_data[ht->slot].ha_info[0];
 
1851
  Ha_trx_info *ha_info= &ha_session()->ha_data[engine->getSlot()].ha_info[0];
2727
1852
  /*
2728
1853
    When a storage engine method is called, the transaction must
2729
1854
    have been started, unless it's a DDL call, for which the
2734
1859
  */
2735
1860
  if (ha_info->is_started())
2736
1861
  {
2737
 
    assert(has_transactions());
2738
1862
    /*
2739
1863
      table_share can be NULL in ha_delete_table(). See implementation
2740
1864
      of standalone function ha_delete_table() in sql_base.cc.
2741
1865
    */
2742
 
    if (table_share == NULL || table_share->tmp_table == NO_TMP_TABLE)
 
1866
//    if (table_share == NULL || table_share->tmp_table == NO_TMP_TABLE)
2743
1867
      ha_info->set_trx_read_write();
2744
1868
  }
2745
1869
}
2746
1870
 
2747
 
 
2748
 
/**
2749
 
  Repair table: public interface.
2750
 
 
2751
 
  @sa handler::repair()
2752
 
*/
2753
 
 
2754
 
int handler::ha_repair(THD* thd, HA_CHECK_OPT* check_opt)
2755
 
{
2756
 
  int result;
2757
 
 
2758
 
  mark_trx_read_write();
2759
 
 
2760
 
  if ((result= repair(thd, check_opt)))
2761
 
    return result;
2762
 
  return update_frm_version(table);
2763
 
}
2764
 
 
2765
 
 
2766
1871
/**
2767
1872
  Bulk update row: public interface.
2768
1873
 
2770
1875
*/
2771
1876
 
2772
1877
int
2773
 
handler::ha_bulk_update_row(const uchar *old_data, uchar *new_data,
2774
 
                            uint *dup_key_found)
 
1878
handler::ha_bulk_update_row(const unsigned char *old_data, unsigned char *new_data,
 
1879
                            uint32_t *dup_key_found)
2775
1880
{
2776
1881
  mark_trx_read_write();
2777
1882
 
2816
1921
*/
2817
1922
 
2818
1923
int
2819
 
handler::ha_optimize(THD* thd, HA_CHECK_OPT* check_opt)
 
1924
handler::ha_optimize(Session* session, HA_CHECK_OPT* check_opt)
2820
1925
{
2821
1926
  mark_trx_read_write();
2822
1927
 
2823
 
  return optimize(thd, check_opt);
 
1928
  return optimize(session, check_opt);
2824
1929
}
2825
1930
 
2826
1931
 
2831
1936
*/
2832
1937
 
2833
1938
int
2834
 
handler::ha_analyze(THD* thd, HA_CHECK_OPT* check_opt)
2835
 
{
2836
 
  mark_trx_read_write();
2837
 
 
2838
 
  return analyze(thd, check_opt);
2839
 
}
2840
 
 
2841
 
 
2842
 
/**
2843
 
  Check and repair table: public interface.
2844
 
 
2845
 
  @sa handler::check_and_repair()
2846
 
*/
2847
 
 
2848
 
bool
2849
 
handler::ha_check_and_repair(THD *thd)
2850
 
{
2851
 
  mark_trx_read_write();
2852
 
 
2853
 
  return check_and_repair(thd);
2854
 
}
2855
 
 
 
1939
handler::ha_analyze(Session* session, HA_CHECK_OPT* check_opt)
 
1940
{
 
1941
  mark_trx_read_write();
 
1942
 
 
1943
  return analyze(session, check_opt);
 
1944
}
2856
1945
 
2857
1946
/**
2858
1947
  Disable indexes: public interface.
2861
1950
*/
2862
1951
 
2863
1952
int
2864
 
handler::ha_disable_indexes(uint mode)
 
1953
handler::ha_disable_indexes(uint32_t mode)
2865
1954
{
2866
1955
  mark_trx_read_write();
2867
1956
 
2876
1965
*/
2877
1966
 
2878
1967
int
2879
 
handler::ha_enable_indexes(uint mode)
 
1968
handler::ha_enable_indexes(uint32_t mode)
2880
1969
{
2881
1970
  mark_trx_read_write();
2882
1971
 
2915
2004
  prepare_for_alter();
2916
2005
}
2917
2006
 
2918
 
 
2919
 
/**
2920
 
  Rename table: public interface.
2921
 
 
2922
 
  @sa handler::rename_table()
2923
 
*/
2924
 
 
2925
 
int
2926
 
handler::ha_rename_table(const char *from, const char *to)
2927
 
{
2928
 
  mark_trx_read_write();
2929
 
 
2930
 
  return rename_table(from, to);
2931
 
}
2932
 
 
2933
 
 
2934
 
/**
2935
 
  Delete table: public interface.
2936
 
 
2937
 
  @sa handler::delete_table()
2938
 
*/
2939
 
 
2940
 
int
2941
 
handler::ha_delete_table(const char *name)
2942
 
{
2943
 
  mark_trx_read_write();
2944
 
 
2945
 
  return delete_table(name);
2946
 
}
2947
 
 
2948
 
 
2949
2007
/**
2950
2008
  Drop table in the engine: public interface.
2951
2009
 
2960
2018
  return drop_table(name);
2961
2019
}
2962
2020
 
2963
 
 
2964
 
/**
2965
 
  Create a table in the engine: public interface.
2966
 
 
2967
 
  @sa handler::create()
2968
 
*/
2969
 
 
2970
 
int
2971
 
handler::ha_create(const char *name, TABLE *form, HA_CREATE_INFO *info)
2972
 
{
2973
 
  mark_trx_read_write();
2974
 
 
2975
 
  return create(name, form, info);
2976
 
}
2977
 
 
2978
 
 
2979
 
/**
2980
 
  Create handler files for CREATE TABLE: public interface.
2981
 
 
2982
 
  @sa handler::create_handler_files()
2983
 
*/
2984
 
 
2985
 
int
2986
 
handler::ha_create_handler_files(const char *name, const char *old_name,
2987
 
                        int action_flag, HA_CREATE_INFO *info)
2988
 
{
2989
 
  mark_trx_read_write();
2990
 
 
2991
 
  return create_handler_files(name, old_name, action_flag, info);
2992
 
}
2993
 
 
2994
 
 
2995
2021
/**
2996
2022
  Tell the storage engine that it is allowed to "disable transaction" in the
2997
2023
  handler. It is a hint that ACID is not required - it is used in NDB for
2998
 
  ALTER TABLE, for example, when data are copied to temporary table.
 
2024
  ALTER Table, for example, when data are copied to temporary table.
2999
2025
  A storage engine may treat this hint any way it likes. NDB for example
3000
2026
  starts to commit every now and then automatically.
3001
2027
  This hint can be safely ignored.
3002
2028
*/
3003
 
int ha_enable_transaction(THD *thd, bool on)
 
2029
int ha_enable_transaction(Session *session, bool on)
3004
2030
{
3005
 
  int error=0;
 
2031
  int error= 0;
3006
2032
 
3007
 
  if ((thd->transaction.on= on))
 
2033
  if ((session->transaction.on= on))
3008
2034
  {
3009
2035
    /*
3010
2036
      Now all storage engines should have transaction handling enabled.
3012
2038
      is an optimization hint that storage engine is free to ignore.
3013
2039
      So, let's commit an open transaction (if any) now.
3014
2040
    */
3015
 
    if (!(error= ha_commit_trans(thd, 0)))
3016
 
      error= end_trans(thd, COMMIT);
 
2041
    if (!(error= ha_commit_trans(session, 0)))
 
2042
      if (! session->endTransaction(COMMIT))
 
2043
        error= 1;
 
2044
 
3017
2045
  }
3018
 
  return(error);
 
2046
  return error;
3019
2047
}
3020
2048
 
3021
 
int handler::index_next_same(uchar *buf, const uchar *key, uint keylen)
 
2049
int handler::index_next_same(unsigned char *buf, const unsigned char *key, uint32_t keylen)
3022
2050
{
3023
2051
  int error;
3024
2052
  if (!(error=index_next(buf)))
3025
2053
  {
3026
2054
    my_ptrdiff_t ptrdiff= buf - table->record[0];
3027
 
    uchar *save_record_0= NULL;
 
2055
    unsigned char *save_record_0= NULL;
3028
2056
    KEY *key_info= NULL;
3029
2057
    KEY_PART_INFO *key_part;
3030
2058
    KEY_PART_INFO *key_part_end= NULL;
3065
2093
        key_part->field->move_field_offset(-ptrdiff);
3066
2094
    }
3067
2095
  }
3068
 
  return(error);
 
2096
  return error;
3069
2097
}
3070
2098
 
3071
2099
 
3073
2101
** Some general functions that isn't in the handler class
3074
2102
****************************************************************************/
3075
2103
 
3076
 
/**
3077
 
  Initiates table-file and calls appropriate database-creator.
3078
 
 
3079
 
  @retval
3080
 
   0  ok
3081
 
  @retval
3082
 
   1  error
3083
 
*/
3084
 
int ha_create_table(THD *thd, const char *path,
3085
 
                    const char *db, const char *table_name,
3086
 
                    HA_CREATE_INFO *create_info,
3087
 
                    bool update_create_info)
3088
 
{
3089
 
  int error= 1;
3090
 
  TABLE table;
3091
 
  char name_buff[FN_REFLEN];
3092
 
  const char *name;
3093
 
  TABLE_SHARE share;
3094
 
  
3095
 
  init_tmp_table_share(thd, &share, db, 0, table_name, path);
3096
 
  if (open_table_def(thd, &share, 0) ||
3097
 
      open_table_from_share(thd, &share, "", 0, (uint) READ_ALL, 0, &table,
3098
 
                            OTM_CREATE))
3099
 
    goto err;
3100
 
 
3101
 
  if (update_create_info)
3102
 
    update_create_info_from_table(create_info, &table);
3103
 
 
3104
 
  name= check_lowercase_names(table.file, share.path.str, name_buff);
3105
 
 
3106
 
  error= table.file->ha_create(name, &table, create_info);
3107
 
  VOID(closefrm(&table, 0));
3108
 
  if (error)
3109
 
  {
3110
 
    strxmov(name_buff, db, ".", table_name, NullS);
3111
 
    my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), name_buff, error);
3112
 
  }
3113
 
err:
3114
 
  free_table_share(&share);
3115
 
  return(error != 0);
3116
 
}
3117
 
 
3118
 
/**
3119
 
  Try to discover table from engine.
3120
 
 
3121
 
  @note
3122
 
    If found, write the frm file to disk.
3123
 
 
3124
 
  @retval
3125
 
  -1    Table did not exists
3126
 
  @retval
3127
 
   0    Table created ok
3128
 
  @retval
3129
 
   > 0  Error, table existed but could not be created
3130
 
*/
3131
 
int ha_create_table_from_engine(THD* thd, const char *db, const char *name)
3132
 
{
3133
 
  int error;
3134
 
  uchar *frmblob;
3135
 
  size_t frmlen;
3136
 
  char path[FN_REFLEN];
3137
 
  HA_CREATE_INFO create_info;
3138
 
  TABLE table;
3139
 
  TABLE_SHARE share;
3140
 
 
3141
 
  memset(&create_info, 0, sizeof(create_info));
3142
 
  if ((error= ha_discover(thd, db, name, &frmblob, &frmlen)))
3143
 
  {
3144
 
    /* Table could not be discovered and thus not created */
3145
 
    return(error);
3146
 
  }
3147
 
 
3148
 
  /*
3149
 
    Table exists in handler and could be discovered
3150
 
    frmblob and frmlen are set, write the frm to disk
3151
 
  */
3152
 
 
3153
 
  build_table_filename(path, FN_REFLEN-1, db, name, "", 0);
3154
 
  // Save the frm file
3155
 
  error= writefrm(path, frmblob, frmlen);
3156
 
  my_free(frmblob, MYF(0));
3157
 
  if (error)
3158
 
    return(2);
3159
 
 
3160
 
  init_tmp_table_share(thd, &share, db, 0, name, path);
3161
 
  if (open_table_def(thd, &share, 0))
3162
 
  {
3163
 
    return(3);
3164
 
  }
3165
 
  if (open_table_from_share(thd, &share, "" ,0, 0, 0, &table, OTM_OPEN))
3166
 
  {
3167
 
    free_table_share(&share);
3168
 
    return(3);
3169
 
  }
3170
 
 
3171
 
  update_create_info_from_table(&create_info, &table);
3172
 
  create_info.table_options|= HA_OPTION_CREATE_FROM_ENGINE;
3173
 
 
3174
 
  check_lowercase_names(table.file, path, path);
3175
 
  error=table.file->ha_create(path, &table, &create_info);
3176
 
  VOID(closefrm(&table, 1));
3177
 
 
3178
 
  return(error != 0);
3179
 
}
3180
2104
 
3181
2105
void st_ha_check_opt::init()
3182
2106
{
3183
 
  flags= sql_flags= 0;
3184
 
  sort_buffer_size = current_thd->variables.myisam_sort_buff_size;
 
2107
  flags= 0; 
 
2108
  use_frm= false;
3185
2109
}
3186
2110
 
3187
2111
 
3198
2122
/**
3199
2123
  Init a key cache if it has not been initied before.
3200
2124
*/
3201
 
int ha_init_key_cache(const char *name __attribute__((unused)),
 
2125
int ha_init_key_cache(const char *,
3202
2126
                      KEY_CACHE *key_cache)
3203
2127
{
3204
2128
  if (!key_cache->key_cache_inited)
3205
2129
  {
3206
2130
    pthread_mutex_lock(&LOCK_global_system_variables);
3207
2131
    uint32_t tmp_buff_size= (uint32_t) key_cache->param_buff_size;
3208
 
    uint tmp_block_size= (uint) key_cache->param_block_size;
3209
 
    uint division_limit= key_cache->param_division_limit;
3210
 
    uint age_threshold=  key_cache->param_age_threshold;
 
2132
    uint32_t tmp_block_size= (uint32_t) key_cache->param_block_size;
 
2133
    uint32_t division_limit= key_cache->param_division_limit;
 
2134
    uint32_t age_threshold=  key_cache->param_age_threshold;
3211
2135
    pthread_mutex_unlock(&LOCK_global_system_variables);
3212
2136
    return(!init_key_cache(key_cache,
3213
2137
                                tmp_block_size,
3214
2138
                                tmp_buff_size,
3215
2139
                                division_limit, age_threshold));
3216
2140
  }
3217
 
  return(0);
 
2141
  return 0;
3218
2142
}
3219
2143
 
3220
2144
 
3228
2152
    pthread_mutex_lock(&LOCK_global_system_variables);
3229
2153
    long tmp_buff_size= (long) key_cache->param_buff_size;
3230
2154
    long tmp_block_size= (long) key_cache->param_block_size;
3231
 
    uint division_limit= key_cache->param_division_limit;
3232
 
    uint age_threshold=  key_cache->param_age_threshold;
 
2155
    uint32_t division_limit= key_cache->param_division_limit;
 
2156
    uint32_t age_threshold=  key_cache->param_age_threshold;
3233
2157
    pthread_mutex_unlock(&LOCK_global_system_variables);
3234
2158
    return(!resize_key_cache(key_cache, tmp_block_size,
3235
2159
                                  tmp_buff_size,
3236
2160
                                  division_limit, age_threshold));
3237
2161
  }
3238
 
  return(0);
 
2162
  return 0;
3239
2163
}
3240
2164
 
3241
2165
 
3247
2171
  if (key_cache->key_cache_inited)
3248
2172
  {
3249
2173
    pthread_mutex_lock(&LOCK_global_system_variables);
3250
 
    uint division_limit= key_cache->param_division_limit;
3251
 
    uint age_threshold=  key_cache->param_age_threshold;
 
2174
    uint32_t division_limit= key_cache->param_division_limit;
 
2175
    uint32_t age_threshold=  key_cache->param_age_threshold;
3252
2176
    pthread_mutex_unlock(&LOCK_global_system_variables);
3253
2177
    change_key_cache_param(key_cache, division_limit, age_threshold);
3254
2178
  }
3276
2200
 
3277
2201
 
3278
2202
/**
3279
 
  Try to discover one table from handler(s).
3280
 
 
3281
 
  @retval
3282
 
    -1   Table did not exists
3283
 
  @retval
3284
 
    0   OK. In this case *frmblob and *frmlen are set
3285
 
  @retval
3286
 
    >0   error.  frmblob and frmlen may not be set
3287
 
*/
3288
 
struct st_discover_args
3289
 
{
3290
 
  const char *db;
3291
 
  const char *name;
3292
 
  uchar **frmblob; 
3293
 
  size_t *frmlen;
3294
 
};
3295
 
 
3296
 
static bool discover_handlerton(THD *thd, plugin_ref plugin,
3297
 
                                void *arg)
3298
 
{
3299
 
  st_discover_args *vargs= (st_discover_args *)arg;
3300
 
  handlerton *hton= plugin_data(plugin, handlerton *);
3301
 
  if (hton->state == SHOW_OPTION_YES && hton->discover &&
3302
 
      (!(hton->discover(hton, thd, vargs->db, vargs->name, 
3303
 
                        vargs->frmblob, 
3304
 
                        vargs->frmlen))))
3305
 
    return true;
3306
 
 
3307
 
  return false;
3308
 
}
3309
 
 
3310
 
int ha_discover(THD *thd, const char *db, const char *name,
3311
 
                uchar **frmblob, size_t *frmlen)
3312
 
{
3313
 
  int error= -1; // Table does not exist in any handler
3314
 
  st_discover_args args= {db, name, frmblob, frmlen};
3315
 
 
3316
 
  if (is_prefix(name,tmp_file_prefix)) /* skip temporary tables */
3317
 
    return(error);
3318
 
 
3319
 
  if (plugin_foreach(thd, discover_handlerton,
3320
 
                 DRIZZLE_STORAGE_ENGINE_PLUGIN, &args))
3321
 
    error= 0;
3322
 
 
3323
 
  if (!error)
3324
 
    status_var_increment(thd->status_var.ha_discover_count);
3325
 
  return(error);
3326
 
}
3327
 
 
3328
 
 
3329
 
/**
3330
 
  Call this function in order to give the handler the possiblity
3331
 
  to ask engine if there are any new tables that should be written to disk
3332
 
  or any dropped tables that need to be removed from disk
3333
 
*/
3334
 
struct st_find_files_args
3335
 
{
3336
 
  const char *db;
3337
 
  const char *path;
3338
 
  const char *wild;
3339
 
  bool dir;
3340
 
  List<LEX_STRING> *files;
3341
 
};
3342
 
 
3343
 
/**
3344
 
  Ask handler if the table exists in engine.
3345
 
  @retval
3346
 
    HA_ERR_NO_SUCH_TABLE     Table does not exist
3347
 
  @retval
3348
 
    HA_ERR_TABLE_EXIST       Table exists
3349
 
  @retval
3350
 
    \#                  Error code
3351
 
*/
3352
 
struct st_table_exists_in_engine_args
3353
 
{
3354
 
  const char *db;
3355
 
  const char *name;
3356
 
  int err;
3357
 
};
3358
 
 
3359
 
static bool table_exists_in_engine_handlerton(THD *thd, plugin_ref plugin,
3360
 
                                              void *arg)
3361
 
{
3362
 
  st_table_exists_in_engine_args *vargs= (st_table_exists_in_engine_args *)arg;
3363
 
  handlerton *hton= plugin_data(plugin, handlerton *);
3364
 
 
3365
 
  int err= HA_ERR_NO_SUCH_TABLE;
3366
 
 
3367
 
  if (hton->state == SHOW_OPTION_YES && hton->table_exists_in_engine)
3368
 
    err = hton->table_exists_in_engine(hton, thd, vargs->db, vargs->name);
3369
 
 
3370
 
  vargs->err = err;
3371
 
  if (vargs->err == HA_ERR_TABLE_EXIST)
3372
 
    return true;
3373
 
 
3374
 
  return false;
3375
 
}
3376
 
 
3377
 
int ha_table_exists_in_engine(THD* thd, const char* db, const char* name)
3378
 
{
3379
 
  st_table_exists_in_engine_args args= {db, name, HA_ERR_NO_SUCH_TABLE};
3380
 
  plugin_foreach(thd, table_exists_in_engine_handlerton,
3381
 
                 DRIZZLE_STORAGE_ENGINE_PLUGIN, &args);
3382
 
  return(args.err);
3383
 
}
3384
 
 
3385
 
/**
3386
2203
  Calculate cost of 'index only' scan for given index and number of records
3387
2204
 
3388
2205
  @param keynr    Index number
3403
2220
    Estimated cost of 'index only' scan
3404
2221
*/
3405
2222
 
3406
 
double handler::index_only_read_time(uint keynr, double records)
 
2223
double handler::index_only_read_time(uint32_t keynr, double key_records)
3407
2224
{
3408
 
  double read_time;
3409
 
  uint keys_per_block= (stats.block_size/2/
 
2225
  uint32_t keys_per_block= (stats.block_size/2/
3410
2226
                        (table->key_info[keynr].key_length + ref_length) + 1);
3411
 
  read_time=((double) (records + keys_per_block-1) /
3412
 
             (double) keys_per_block);
3413
 
  return read_time;
 
2227
  return ((double) (key_records + keys_per_block-1) /
 
2228
          (double) keys_per_block);
3414
2229
}
3415
2230
 
3416
2231
 
3437
2252
 
3438
2253
  @note
3439
2254
    This method (or an overriding one in a derived class) must check for
3440
 
    thd->killed and return HA_POS_ERROR if it is not zero. This is required
 
2255
    session->killed and return HA_POS_ERROR if it is not zero. This is required
3441
2256
    for a user to be able to interrupt the calculation by killing the
3442
2257
    connection/query.
3443
2258
 
3450
2265
*/
3451
2266
 
3452
2267
ha_rows
3453
 
handler::multi_range_read_info_const(uint keyno, RANGE_SEQ_IF *seq,
 
2268
handler::multi_range_read_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
3454
2269
                                     void *seq_init_param,
3455
 
                                     uint n_ranges_arg __attribute__((unused)),
3456
 
                                     uint *bufsz, uint *flags, COST_VECT *cost)
 
2270
                                     uint32_t ,
 
2271
                                     uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
3457
2272
{
3458
2273
  KEY_MULTI_RANGE range;
3459
2274
  range_seq_t seq_it;
3460
2275
  ha_rows rows, total_rows= 0;
3461
 
  uint n_ranges=0;
3462
 
  THD *thd= current_thd;
3463
 
  
 
2276
  uint32_t n_ranges=0;
 
2277
  Session *session= current_session;
 
2278
 
3464
2279
  /* Default MRR implementation doesn't need buffer */
3465
2280
  *bufsz= 0;
3466
2281
 
3467
2282
  seq_it= seq->init(seq_init_param, n_ranges, *flags);
3468
2283
  while (!seq->next(seq_it, &range))
3469
2284
  {
3470
 
    if (unlikely(thd->killed != 0))
 
2285
    if (unlikely(session->killed != 0))
3471
2286
      return HA_POS_ERROR;
3472
 
    
 
2287
 
3473
2288
    n_ranges++;
3474
2289
    key_range *min_endp, *max_endp;
3475
2290
    {
3480
2295
      rows= 1; /* there can be at most one row */
3481
2296
    else
3482
2297
    {
3483
 
      if (HA_POS_ERROR == (rows= this->records_in_range(keyno, min_endp, 
 
2298
      if (HA_POS_ERROR == (rows= this->records_in_range(keyno, min_endp,
3484
2299
                                                        max_endp)))
3485
2300
      {
3486
2301
        /* Can't scan one range => can't do MRR scan at all */
3490
2305
    }
3491
2306
    total_rows += rows;
3492
2307
  }
3493
 
  
 
2308
 
3494
2309
  if (total_rows != HA_POS_ERROR)
3495
2310
  {
3496
2311
    /* The following calculation is the same as in multi_range_read_info(): */
3498
2313
    cost->zero();
3499
2314
    cost->avg_io_cost= 1; /* assume random seeks */
3500
2315
    if ((*flags & HA_MRR_INDEX_ONLY) && total_rows > 2)
3501
 
      cost->io_count= index_only_read_time(keyno, (uint)total_rows);
 
2316
      cost->io_count= index_only_read_time(keyno, (uint32_t)total_rows);
3502
2317
    else
3503
2318
      cost->io_count= read_time(keyno, n_ranges, total_rows);
3504
2319
    cost->cpu_cost= (double) total_rows / TIME_FOR_COMPARE + 0.01;
3541
2356
    other Error or can't perform the requested scan
3542
2357
*/
3543
2358
 
3544
 
int handler::multi_range_read_info(uint keyno, uint n_ranges, uint n_rows,
3545
 
                                   uint *bufsz, uint *flags, COST_VECT *cost)
 
2359
int handler::multi_range_read_info(uint32_t keyno, uint32_t n_ranges, uint32_t n_rows,
 
2360
                                   uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
3546
2361
{
3547
2362
  *bufsz= 0; /* Default implementation doesn't need a buffer */
3548
2363
 
3563
2378
/**
3564
2379
  Initialize the MRR scan
3565
2380
 
3566
 
  Initialize the MRR scan. This function may do heavyweight scan 
 
2381
  Initialize the MRR scan. This function may do heavyweight scan
3567
2382
  initialization like row prefetching/sorting/etc (NOTE: but better not do
3568
2383
  it here as we may not need it, e.g. if we never satisfy WHERE clause on
3569
2384
  previous tables. For many implementations it would be natural to do such
3570
2385
  initializations in the first multi_read_range_next() call)
3571
2386
 
3572
2387
  mode is a combination of the following flags: HA_MRR_SORTED,
3573
 
  HA_MRR_INDEX_ONLY, HA_MRR_NO_ASSOCIATION 
 
2388
  HA_MRR_INDEX_ONLY, HA_MRR_NO_ASSOCIATION
3574
2389
 
3575
2390
  @param seq             Range sequence to be traversed
3576
2391
  @param seq_init_param  First parameter for seq->init()
3582
2397
    One must have called index_init() before calling this function. Several
3583
2398
    multi_range_read_init() calls may be made in course of one query.
3584
2399
 
3585
 
    Until WL#2623 is done (see its text, section 3.2), the following will 
 
2400
    Until WL#2623 is done (see its text, section 3.2), the following will
3586
2401
    also hold:
3587
2402
    The caller will guarantee that if "seq->init == mrr_ranges_array_init"
3588
2403
    then seq_init_param is an array of n_ranges KEY_MULTI_RANGE structures.
3589
2404
    This property will only be used by NDB handler until WL#2623 is done.
3590
 
     
 
2405
 
3591
2406
    Buffer memory management is done according to the following scenario:
3592
2407
    The caller allocates the buffer and provides it to the callee by filling
3593
2408
    the members of HANDLER_BUFFER structure.
3603
2418
 
3604
2419
int
3605
2420
handler::multi_range_read_init(RANGE_SEQ_IF *seq_funcs, void *seq_init_param,
3606
 
                               uint n_ranges, uint mode,
3607
 
                               HANDLER_BUFFER *buf __attribute__((unused)))
 
2421
                               uint32_t n_ranges, uint32_t mode,
 
2422
                               HANDLER_BUFFER *)
3608
2423
{
3609
2424
  mrr_iter= seq_funcs->init(seq_init_param, n_ranges, mode);
3610
2425
  mrr_funcs= *seq_funcs;
3611
2426
  mrr_is_output_sorted= test(mode & HA_MRR_SORTED);
3612
2427
  mrr_have_range= false;
3613
 
  return(0);
 
2428
  return 0;
3614
2429
}
3615
2430
 
3616
2431
 
3677
2492
  while ((result == HA_ERR_END_OF_FILE) && !range_res);
3678
2493
 
3679
2494
  *range_info= mrr_cur_range.ptr;
3680
 
  return(result);
 
2495
  return result;
3681
2496
}
3682
2497
 
3683
2498
 
3684
2499
/* **************************************************************************
3685
 
 * DS-MRR implementation 
 
2500
 * DS-MRR implementation
3686
2501
 ***************************************************************************/
3687
2502
 
3688
2503
/**
3703
2518
  @retval other Error
3704
2519
*/
3705
2520
 
3706
 
int DsMrr_impl::dsmrr_init(handler *h, KEY *key,
 
2521
int DsMrr_impl::dsmrr_init(handler *h_in, KEY *key,
3707
2522
                           RANGE_SEQ_IF *seq_funcs, void *seq_init_param,
3708
 
                           uint n_ranges, uint mode, HANDLER_BUFFER *buf)
 
2523
                           uint32_t n_ranges, uint32_t mode, HANDLER_BUFFER *buf)
3709
2524
{
3710
 
  uint elem_size;
3711
 
  uint keyno;
 
2525
  uint32_t elem_size;
 
2526
  uint32_t keyno;
3712
2527
  Item *pushed_cond= NULL;
3713
2528
  handler *new_h2;
3714
 
  keyno= h->active_index;
 
2529
  keyno= h_in->active_index;
3715
2530
  assert(h2 == NULL);
3716
2531
  if (mode & HA_MRR_USE_DEFAULT_IMPL || mode & HA_MRR_SORTED)
3717
2532
  {
3718
2533
    use_default_impl= true;
3719
 
    return(h->handler::multi_range_read_init(seq_funcs, seq_init_param,
 
2534
    return(h_in->handler::multi_range_read_init(seq_funcs, seq_init_param,
3720
2535
                                                  n_ranges, mode, buf));
3721
2536
  }
3722
2537
  rowids_buf= buf->buffer;
3723
2538
  //psergey-todo: don't add key_length as it is not needed anymore
3724
 
  rowids_buf += key->key_length + h->ref_length;
 
2539
  rowids_buf += key->key_length + h_in->ref_length;
3725
2540
 
3726
2541
  is_mrr_assoc= !test(mode & HA_MRR_NO_ASSOCIATION);
3727
2542
  rowids_buf_end= buf->buffer_end;
3728
 
  
3729
 
  elem_size= h->ref_length + (int)is_mrr_assoc * sizeof(void*);
3730
 
  rowids_buf_last= rowids_buf + 
 
2543
 
 
2544
  elem_size= h_in->ref_length + (int)is_mrr_assoc * sizeof(void*);
 
2545
  rowids_buf_last= rowids_buf +
3731
2546
                      ((rowids_buf_end - rowids_buf)/ elem_size)*
3732
2547
                      elem_size;
3733
2548
  rowids_buf_end= rowids_buf_last;
3734
2549
 
3735
2550
  /* Create a separate handler object to do rndpos() calls. */
3736
 
  THD *thd= current_thd;
3737
 
  if (!(new_h2= h->clone(thd->mem_root)) || 
3738
 
      new_h2->ha_external_lock(thd, F_RDLCK))
 
2551
  Session *session= current_session;
 
2552
  if (!(new_h2= h_in->clone(session->mem_root)) ||
 
2553
      new_h2->ha_external_lock(session, F_RDLCK))
3739
2554
  {
3740
2555
    delete new_h2;
3741
 
    return(1);
 
2556
    return 1;
3742
2557
  }
3743
2558
 
3744
 
  if (keyno == h->pushed_idx_cond_keyno)
3745
 
    pushed_cond= h->pushed_idx_cond;
3746
 
  if (h->ha_index_end())
 
2559
  if (keyno == h_in->pushed_idx_cond_keyno)
 
2560
    pushed_cond= h_in->pushed_idx_cond;
 
2561
  if (h_in->ha_index_end())
3747
2562
  {
3748
2563
    new_h2= h2;
3749
2564
    goto error;
3753
2568
  table->prepare_for_position();
3754
2569
  new_h2->extra(HA_EXTRA_KEYREAD);
3755
2570
 
3756
 
  if (h2->ha_index_init(keyno, false) || 
 
2571
  if (h2->ha_index_init(keyno, false) ||
3757
2572
      h2->handler::multi_range_read_init(seq_funcs, seq_init_param, n_ranges,
3758
2573
                                         mode, buf))
3759
2574
    goto error;
3760
2575
  use_default_impl= false;
3761
 
  
 
2576
 
3762
2577
  if (pushed_cond)
3763
2578
    h2->idx_cond_push(keyno, pushed_cond);
3764
2579
  if (dsmrr_fill_buffer(new_h2))
3768
2583
    If the above call has scanned through all intervals in *seq, then
3769
2584
    adjust *buf to indicate that the remaining buffer space will not be used.
3770
2585
  */
3771
 
  if (dsmrr_eof) 
 
2586
  if (dsmrr_eof)
3772
2587
    buf->end_of_used_area= rowids_buf_last;
3773
2588
 
3774
 
  if (h->ha_rnd_init(false))
 
2589
  if (h_in->ha_rnd_init(false))
3775
2590
    goto error;
3776
 
  
3777
 
  return(0);
 
2591
 
 
2592
  return 0;
3778
2593
error:
3779
2594
  h2->ha_index_or_rnd_end();
3780
 
  h2->ha_external_lock(thd, F_UNLCK);
 
2595
  h2->ha_external_lock(session, F_UNLCK);
3781
2596
  h2->close();
3782
2597
  delete h2;
3783
 
  return(1);
 
2598
  return 1;
3784
2599
}
3785
2600
 
3786
2601
 
3788
2603
{
3789
2604
  if (h2)
3790
2605
  {
3791
 
    h2->ha_external_lock(current_thd, F_UNLCK);
 
2606
    h2->ha_external_lock(current_session, F_UNLCK);
3792
2607
    h2->close();
3793
2608
    delete h2;
3794
2609
    h2= NULL;
3795
2610
  }
3796
2611
  use_default_impl= true;
3797
 
  return;
3798
2612
}
3799
2613
 
3800
2614
 
3801
 
static int rowid_cmp(void *h, uchar *a, uchar *b)
 
2615
static int rowid_cmp(void *h, unsigned char *a, unsigned char *b)
3802
2616
{
3803
2617
  return ((handler*)h)->cmp_ref(a, b);
3804
2618
}
3808
2622
  DS-MRR: Fill the buffer with rowids and sort it by rowid
3809
2623
 
3810
2624
  {This is an internal function of DiskSweep MRR implementation}
3811
 
  Scan the MRR ranges and collect ROWIDs (or {ROWID, range_id} pairs) into 
3812
 
  buffer. When the buffer is full or scan is completed, sort the buffer by 
 
2625
  Scan the MRR ranges and collect ROWIDs (or {ROWID, range_id} pairs) into
 
2626
  buffer. When the buffer is full or scan is completed, sort the buffer by
3813
2627
  rowid and return.
3814
 
  
3815
 
  The function assumes that rowids buffer is empty when it is invoked. 
3816
 
  
 
2628
 
 
2629
  The function assumes that rowids buffer is empty when it is invoked.
 
2630
 
3817
2631
  @param h  Table handler
3818
2632
 
3819
2633
  @retval 0      OK, the next portion of rowids is in the buffer,
3821
2635
  @retval other  Error
3822
2636
*/
3823
2637
 
3824
 
int DsMrr_impl::dsmrr_fill_buffer(handler *unused __attribute__((unused)))
 
2638
int DsMrr_impl::dsmrr_fill_buffer(handler *)
3825
2639
{
3826
2640
  char *range_info;
3827
2641
  int res = 0;
3828
2642
 
3829
2643
  rowids_buf_cur= rowids_buf;
3830
 
  while ((rowids_buf_cur < rowids_buf_end) && 
 
2644
  while ((rowids_buf_cur < rowids_buf_end) &&
3831
2645
         !(res= h2->handler::multi_range_read_next(&range_info)))
3832
2646
  {
3833
2647
    /* Put rowid, or {rowid, range_id} pair into the buffer */
3843
2657
  }
3844
2658
 
3845
2659
  if (res && res != HA_ERR_END_OF_FILE)
3846
 
    return(res); 
 
2660
    return res;
3847
2661
  dsmrr_eof= test(res == HA_ERR_END_OF_FILE);
3848
2662
 
3849
2663
  /* Sort the buffer contents by rowid */
3850
 
  uint elem_size= h->ref_length + (int)is_mrr_assoc * sizeof(void*);
3851
 
  uint n_rowids= (rowids_buf_cur - rowids_buf) / elem_size;
3852
 
  
 
2664
  uint32_t elem_size= h->ref_length + (int)is_mrr_assoc * sizeof(void*);
 
2665
  uint32_t n_rowids= (rowids_buf_cur - rowids_buf) / elem_size;
 
2666
 
3853
2667
  my_qsort2(rowids_buf, n_rowids, elem_size, (qsort2_cmp)rowid_cmp,
3854
2668
            (void*)h);
3855
2669
  rowids_buf_last= rowids_buf_cur;
3856
2670
  rowids_buf_cur=  rowids_buf;
3857
 
  return(0);
 
2671
  return 0;
3858
2672
}
3859
2673
 
3860
2674
 
3862
2676
  DS-MRR implementation: multi_range_read_next() function
3863
2677
*/
3864
2678
 
3865
 
int DsMrr_impl::dsmrr_next(handler *h, char **range_info)
 
2679
int DsMrr_impl::dsmrr_next(handler *h_in, char **range_info)
3866
2680
{
3867
2681
  int res;
3868
 
  
 
2682
 
3869
2683
  if (use_default_impl)
3870
 
    return h->handler::multi_range_read_next(range_info);
3871
 
    
 
2684
    return h_in->handler::multi_range_read_next(range_info);
 
2685
 
3872
2686
  if (rowids_buf_cur == rowids_buf_last)
3873
2687
  {
3874
2688
    if (dsmrr_eof)
3880
2694
    if (res)
3881
2695
      goto end;
3882
2696
  }
3883
 
  
 
2697
 
3884
2698
  /* Return EOF if there are no rowids in the buffer after re-fill attempt */
3885
2699
  if (rowids_buf_cur == rowids_buf_last)
3886
2700
  {
3888
2702
    goto end;
3889
2703
  }
3890
2704
 
3891
 
  res= h->rnd_pos(table->record[0], rowids_buf_cur);
3892
 
  rowids_buf_cur += h->ref_length;
 
2705
  res= h_in->rnd_pos(table->record[0], rowids_buf_cur);
 
2706
  rowids_buf_cur += h_in->ref_length;
3893
2707
  if (is_mrr_assoc)
3894
2708
  {
3895
2709
    memcpy(range_info, rowids_buf_cur, sizeof(void*));
3906
2720
/**
3907
2721
  DS-MRR implementation: multi_range_read_info() function
3908
2722
*/
3909
 
int DsMrr_impl::dsmrr_info(uint keyno, uint n_ranges, uint rows, uint *bufsz,
3910
 
                           uint *flags, COST_VECT *cost)
3911
 
{  
 
2723
int DsMrr_impl::dsmrr_info(uint32_t keyno, uint32_t n_ranges, uint32_t rows, uint32_t *bufsz,
 
2724
                           uint32_t *flags, COST_VECT *cost)
 
2725
{
3912
2726
  int res;
3913
 
  uint def_flags= *flags;
3914
 
  uint def_bufsz= *bufsz;
 
2727
  uint32_t def_flags= *flags;
 
2728
  uint32_t def_bufsz= *bufsz;
3915
2729
 
3916
2730
  /* Get cost/flags/mem_usage of default MRR implementation */
3917
2731
  res= h->handler::multi_range_read_info(keyno, n_ranges, rows, &def_bufsz,
3918
2732
                                         &def_flags, cost);
3919
2733
  assert(!res);
3920
2734
 
3921
 
  if ((*flags & HA_MRR_USE_DEFAULT_IMPL) || 
 
2735
  if ((*flags & HA_MRR_USE_DEFAULT_IMPL) ||
3922
2736
      choose_mrr_impl(keyno, rows, &def_flags, &def_bufsz, cost))
3923
2737
  {
3924
2738
    /* Default implementation is choosen */
3933
2747
  DS-MRR Implementation: multi_range_read_info_const() function
3934
2748
*/
3935
2749
 
3936
 
ha_rows DsMrr_impl::dsmrr_info_const(uint keyno, RANGE_SEQ_IF *seq,
3937
 
                                 void *seq_init_param, uint n_ranges, 
3938
 
                                 uint *bufsz, uint *flags, COST_VECT *cost)
 
2750
ha_rows DsMrr_impl::dsmrr_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
 
2751
                                 void *seq_init_param, uint32_t n_ranges,
 
2752
                                 uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
3939
2753
{
3940
2754
  ha_rows rows;
3941
 
  uint def_flags= *flags;
3942
 
  uint def_bufsz= *bufsz;
 
2755
  uint32_t def_flags= *flags;
 
2756
  uint32_t def_bufsz= *bufsz;
3943
2757
  /* Get cost/flags/mem_usage of default MRR implementation */
3944
2758
  rows= h->handler::multi_range_read_info_const(keyno, seq, seq_init_param,
3945
 
                                                n_ranges, &def_bufsz, 
 
2759
                                                n_ranges, &def_bufsz,
3946
2760
                                                &def_flags, cost);
3947
2761
  if (rows == HA_POS_ERROR)
3948
2762
  {
3987
2801
  @retval false  No
3988
2802
*/
3989
2803
 
3990
 
bool DsMrr_impl::key_uses_partial_cols(uint keyno)
 
2804
bool DsMrr_impl::key_uses_partial_cols(uint32_t keyno)
3991
2805
{
3992
2806
  KEY_PART_INFO *kp= table->key_info[keyno].key_part;
3993
2807
  KEY_PART_INFO *kp_end= kp + table->key_info[keyno].key_parts;
3994
2808
  for (; kp != kp_end; kp++)
3995
2809
  {
3996
 
    if (!kp->field->part_of_key.is_set(keyno))
 
2810
    if (!kp->field->part_of_key.test(keyno))
3997
2811
      return true;
3998
2812
  }
3999
2813
  return false;
4023
2837
  @retval false  DS-MRR implementation should be used
4024
2838
*/
4025
2839
 
4026
 
bool DsMrr_impl::choose_mrr_impl(uint keyno, ha_rows rows, uint *flags,
4027
 
                                 uint *bufsz, COST_VECT *cost)
 
2840
bool DsMrr_impl::choose_mrr_impl(uint32_t keyno, ha_rows rows, uint32_t *flags,
 
2841
                                 uint32_t *bufsz, COST_VECT *cost)
4028
2842
{
4029
2843
  COST_VECT dsmrr_cost;
4030
2844
  bool res;
4031
 
  THD *thd= current_thd;
4032
 
  if ((thd->variables.optimizer_use_mrr == 2) || 
 
2845
  Session *session= current_session;
 
2846
  if ((session->variables.optimizer_use_mrr == 2) ||
4033
2847
      (*flags & HA_MRR_INDEX_ONLY) || (*flags & HA_MRR_SORTED) ||
4034
 
      (keyno == table->s->primary_key && 
4035
 
       h->primary_key_is_clustered()) || 
 
2848
      (keyno == table->s->primary_key &&
 
2849
       h->primary_key_is_clustered()) ||
4036
2850
       key_uses_partial_cols(keyno))
4037
2851
  {
4038
2852
    /* Use the default implementation */
4039
2853
    *flags |= HA_MRR_USE_DEFAULT_IMPL;
4040
2854
    return true;
4041
2855
  }
4042
 
  
4043
 
  uint add_len= table->key_info[keyno].key_length + h->ref_length; 
 
2856
 
 
2857
  uint32_t add_len= table->key_info[keyno].key_length + h->ref_length;
4044
2858
  *bufsz -= add_len;
4045
2859
  if (get_disk_sweep_mrr_cost(keyno, rows, *flags, bufsz, &dsmrr_cost))
4046
2860
    return true;
4047
2861
  *bufsz += add_len;
4048
 
  
 
2862
 
4049
2863
  bool force_dsmrr;
4050
 
  /* 
 
2864
  /*
4051
2865
    If @@optimizer_use_mrr==force, then set cost of DS-MRR to be minimum of
4052
2866
    DS-MRR and Default implementations cost. This allows one to force use of
4053
2867
    DS-MRR whenever it is applicable without affecting other cost-based
4054
2868
    choices.
4055
2869
  */
4056
 
  if ((force_dsmrr= (thd->variables.optimizer_use_mrr == 1)) &&
 
2870
  if ((force_dsmrr= (session->variables.optimizer_use_mrr == 1)) &&
4057
2871
      dsmrr_cost.total_cost() > cost->total_cost())
4058
2872
    dsmrr_cost= *cost;
4059
2873
 
4073
2887
}
4074
2888
 
4075
2889
 
4076
 
static void get_sort_and_sweep_cost(TABLE *table, ha_rows nrows, COST_VECT *cost);
 
2890
static void get_sort_and_sweep_cost(Table *table, ha_rows nrows, COST_VECT *cost);
4077
2891
 
4078
2892
 
4079
2893
/**
4090
2904
                 for even 1 rowid)
4091
2905
*/
4092
2906
 
4093
 
bool DsMrr_impl::get_disk_sweep_mrr_cost(uint keynr, ha_rows rows, uint flags,
4094
 
                                         uint *buffer_size, COST_VECT *cost)
 
2907
bool DsMrr_impl::get_disk_sweep_mrr_cost(uint32_t keynr, ha_rows rows, uint32_t flags,
 
2908
                                         uint32_t *buffer_size, COST_VECT *cost)
4095
2909
{
4096
2910
  uint32_t max_buff_entries, elem_size;
4097
2911
  ha_rows rows_in_full_step, rows_in_last_step;
4098
 
  uint n_full_steps;
 
2912
  uint32_t n_full_steps;
4099
2913
  double index_read_cost;
4100
2914
 
4101
2915
  elem_size= h->ref_length + sizeof(void*) * (!test(flags & HA_MRR_NO_ASSOCIATION));
4105
2919
    return true; /* Buffer has not enough space for even 1 rowid */
4106
2920
 
4107
2921
  /* Number of iterations we'll make with full buffer */
4108
 
  n_full_steps= (uint)floor(rows2double(rows) / max_buff_entries);
4109
 
  
4110
 
  /* 
4111
 
    Get numbers of rows we'll be processing in 
4112
 
     - non-last sweep, with full buffer 
 
2922
  n_full_steps= (uint32_t)floor(rows2double(rows) / max_buff_entries);
 
2923
 
 
2924
  /*
 
2925
    Get numbers of rows we'll be processing in
 
2926
     - non-last sweep, with full buffer
4113
2927
     - last iteration, with non-full buffer
4114
2928
  */
4115
2929
  rows_in_full_step= max_buff_entries;
4116
2930
  rows_in_last_step= rows % max_buff_entries;
4117
 
  
 
2931
 
4118
2932
  /* Adjust buffer size if we expect to use only part of the buffer */
4119
2933
  if (n_full_steps)
4120
2934
  {
4124
2938
  else
4125
2939
  {
4126
2940
    cost->zero();
4127
 
    *buffer_size= max((ulong)*buffer_size, 
4128
 
                      (size_t)(1.2*rows_in_last_step) * elem_size + 
 
2941
    *buffer_size= cmax((ulong)*buffer_size,
 
2942
                      (size_t)(1.2*rows_in_last_step) * elem_size +
4129
2943
                      h->ref_length + table->key_info[keynr].key_length);
4130
2944
  }
4131
 
  
 
2945
 
4132
2946
  COST_VECT last_step_cost;
4133
2947
  get_sort_and_sweep_cost(table, rows_in_last_step, &last_step_cost);
4134
2948
  cost->add(&last_step_cost);
4135
 
 
 
2949
 
4136
2950
  if (n_full_steps != 0)
4137
2951
    cost->mem_cost= *buffer_size;
4138
2952
  else
4139
2953
    cost->mem_cost= (double)rows_in_last_step * elem_size;
4140
 
  
 
2954
 
4141
2955
  /* Total cost of all index accesses */
4142
2956
  index_read_cost= h->index_only_read_time(keynr, (double)rows);
4143
2957
  cost->add_io(index_read_cost, 1 /* Random seeks */);
4145
2959
}
4146
2960
 
4147
2961
 
4148
 
/* 
 
2962
/*
4149
2963
  Get cost of one sort-and-sweep step
4150
2964
 
4151
2965
  SYNOPSIS
4160
2974
     - read #nrows records from table in a sweep.
4161
2975
*/
4162
2976
 
4163
 
static 
4164
 
void get_sort_and_sweep_cost(TABLE *table, ha_rows nrows, COST_VECT *cost)
 
2977
static
 
2978
void get_sort_and_sweep_cost(Table *table, ha_rows nrows, COST_VECT *cost)
4165
2979
{
4166
2980
  if (nrows)
4167
2981
  {
4194
3008
  Time to move the disk head is proportional to head travel distance.
4195
3009
 
4196
3010
  Time to wait for the plate to rotate depends on whether the disk head
4197
 
  was moved or not. 
 
3011
  was moved or not.
4198
3012
 
4199
3013
  If disk head wasn't moved, the wait time is proportional to distance
4200
3014
  between the previous block and the block we're reading.
4205
3019
 
4206
3020
  Our cost units are "random disk seeks". The cost of random disk seek is
4207
3021
  actually not a constant, it depends one range of cylinders we're going
4208
 
  to access. We make it constant by introducing a fuzzy concept of "typical 
 
3022
  to access. We make it constant by introducing a fuzzy concept of "typical
4209
3023
  datafile length" (it's fuzzy as it's hard to tell whether it should
4210
3024
  include index file, temp.tables etc). Then random seek cost is:
4211
3025
 
4220
3034
  @param cost         OUT  The cost.
4221
3035
*/
4222
3036
 
4223
 
void get_sweep_read_cost(TABLE *table, ha_rows nrows, bool interrupted, 
 
3037
void get_sweep_read_cost(Table *table, ha_rows nrows, bool interrupted,
4224
3038
                         COST_VECT *cost)
4225
3039
{
4226
3040
  cost->zero();
4227
3041
  if (table->file->primary_key_is_clustered())
4228
3042
  {
4229
3043
    cost->io_count= table->file->read_time(table->s->primary_key,
4230
 
                                           (uint) nrows, nrows);
 
3044
                                           (uint32_t) nrows, nrows);
4231
3045
  }
4232
3046
  else
4233
3047
  {
4247
3061
                          DISK_SEEK_PROP_COST*n_blocks/busy_blocks);
4248
3062
    }
4249
3063
  }
4250
 
  return;
4251
3064
}
4252
3065
 
4253
3066
 
4276
3089
int handler::read_range_first(const key_range *start_key,
4277
3090
                              const key_range *end_key,
4278
3091
                              bool eq_range_arg,
4279
 
                              bool sorted  __attribute__((unused)))
 
3092
                              bool )
4280
3093
{
4281
3094
  int result;
4282
3095
 
4299
3112
                           start_key->keypart_map,
4300
3113
                           start_key->flag);
4301
3114
  if (result)
4302
 
    return((result == HA_ERR_KEY_NOT_FOUND) 
 
3115
    return((result == HA_ERR_KEY_NOT_FOUND)
4303
3116
                ? HA_ERR_END_OF_FILE
4304
3117
                : result);
4305
3118
 
4333
3146
  }
4334
3147
  result= index_next(table->record[0]);
4335
3148
  if (result)
4336
 
    return(result);
 
3149
    return result;
4337
3150
  return(compare_key(end_range) <= 0 ? 0 : HA_ERR_END_OF_FILE);
4338
3151
}
4339
3152
 
4381
3194
  return cmp;
4382
3195
}
4383
3196
 
4384
 
int handler::index_read_idx_map(uchar * buf, uint index, const uchar * key,
 
3197
int handler::index_read_idx_map(unsigned char * buf, uint32_t index,
 
3198
                                const unsigned char * key,
4385
3199
                                key_part_map keypart_map,
4386
3200
                                enum ha_rkey_function find_flag)
4387
3201
{
4396
3210
}
4397
3211
 
4398
3212
 
4399
 
/**
4400
 
  Returns a list of all known extensions.
4401
 
 
4402
 
    No mutexes, worst case race is a minor surplus memory allocation
4403
 
    We have to recreate the extension map if mysqld is restarted (for example
4404
 
    within libmysqld)
4405
 
 
4406
 
  @retval
4407
 
    pointer             pointer to TYPELIB structure
4408
 
*/
4409
 
static bool exts_handlerton(THD *unused __attribute__((unused)),
4410
 
                            plugin_ref plugin,
4411
 
                            void *arg)
4412
 
{
4413
 
  List<char> *found_exts= (List<char> *) arg;
4414
 
  handlerton *hton= plugin_data(plugin, handlerton *);
4415
 
  handler *file;
4416
 
  if (hton->state == SHOW_OPTION_YES && hton->create &&
4417
 
      (file= hton->create(hton, (TABLE_SHARE*) 0, current_thd->mem_root)))
4418
 
  {
4419
 
    List_iterator_fast<char> it(*found_exts);
4420
 
    const char **ext, *old_ext;
4421
 
 
4422
 
    for (ext= file->bas_ext(); *ext; ext++)
4423
 
    {
4424
 
      while ((old_ext= it++))
4425
 
      {
4426
 
        if (!strcmp(old_ext, *ext))
4427
 
          break;
4428
 
      }
4429
 
      if (!old_ext)
4430
 
        found_exts->push_back((char *) *ext);
4431
 
 
4432
 
      it.rewind();
4433
 
    }
4434
 
    delete file;
4435
 
  }
4436
 
  return false;
4437
 
}
4438
 
 
4439
 
TYPELIB *ha_known_exts(void)
4440
 
{
4441
 
  if (!known_extensions.type_names || mysys_usage_id != known_extensions_id)
4442
 
  {
4443
 
    List<char> found_exts;
4444
 
    const char **ext, *old_ext;
4445
 
 
4446
 
    known_extensions_id= mysys_usage_id;
4447
 
 
4448
 
    plugin_foreach(NULL, exts_handlerton,
4449
 
                   DRIZZLE_STORAGE_ENGINE_PLUGIN, &found_exts);
4450
 
 
4451
 
    ext= (const char **) my_once_alloc(sizeof(char *)*
4452
 
                                       (found_exts.elements+1),
4453
 
                                       MYF(MY_WME | MY_FAE));
4454
 
 
4455
 
    assert(ext != 0);
4456
 
    known_extensions.count= found_exts.elements;
4457
 
    known_extensions.type_names= ext;
4458
 
 
4459
 
    List_iterator_fast<char> it(found_exts);
4460
 
    while ((old_ext= it++))
4461
 
      *ext++= old_ext;
4462
 
    *ext= 0;
4463
 
  }
4464
 
  return &known_extensions;
4465
 
}
4466
 
 
4467
 
 
4468
 
static bool stat_print(THD *thd, const char *type, uint type_len,
4469
 
                       const char *file, uint file_len,
4470
 
                       const char *status, uint status_len)
4471
 
{
4472
 
  Protocol *protocol= thd->protocol;
4473
 
  protocol->prepare_for_resend();
4474
 
  protocol->store(type, type_len, system_charset_info);
4475
 
  protocol->store(file, file_len, system_charset_info);
4476
 
  protocol->store(status, status_len, system_charset_info);
 
3213
static bool stat_print(Session *session, const char *type, uint32_t type_len,
 
3214
                       const char *file, uint32_t file_len,
 
3215
                       const char *status, uint32_t status_len)
 
3216
{
 
3217
  Protocol *protocol= session->protocol;
 
3218
  protocol->prepareForResend();
 
3219
  protocol->store(type, type_len);
 
3220
  protocol->store(file, file_len);
 
3221
  protocol->store(status, status_len);
4477
3222
  if (protocol->write())
4478
3223
    return true;
4479
3224
  return false;
4480
3225
}
4481
3226
 
4482
 
bool ha_show_status(THD *thd, handlerton *db_type, enum ha_stat_type stat)
 
3227
bool ha_show_status(Session *session, StorageEngine *engine, enum ha_stat_type stat)
4483
3228
{
4484
3229
  List<Item> field_list;
4485
 
  Protocol *protocol= thd->protocol;
 
3230
  Protocol *protocol= session->protocol;
4486
3231
  bool result;
4487
3232
 
4488
3233
  field_list.push_back(new Item_empty_string("Type",10));
4489
3234
  field_list.push_back(new Item_empty_string("Name",FN_REFLEN));
4490
3235
  field_list.push_back(new Item_empty_string("Status",10));
4491
3236
 
4492
 
  if (protocol->send_fields(&field_list,
4493
 
                            Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
 
3237
  if (protocol->sendFields(&field_list,
 
3238
                           Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
4494
3239
    return true;
4495
3240
 
4496
 
  result= db_type->show_status &&
4497
 
    db_type->show_status(db_type, thd, stat_print, stat) ? 1 : 0;
 
3241
  result= engine->show_status(session, stat_print, stat) ? 1 : 0;
4498
3242
 
4499
3243
  if (!result)
4500
 
    my_eof(thd);
 
3244
    session->my_eof();
4501
3245
  return result;
4502
3246
}
4503
3247
 
4514
3258
  - table is not mysql.event
4515
3259
*/
4516
3260
 
4517
 
static bool check_table_binlog_row_based(THD *thd, TABLE *table)
4518
 
{
4519
 
  if (table->s->cached_row_logging_check == -1)
4520
 
  {
4521
 
    int const check(table->s->tmp_table == NO_TMP_TABLE &&
4522
 
                    binlog_filter->db_ok(table->s->db.str));
4523
 
    table->s->cached_row_logging_check= check;
4524
 
  }
4525
 
 
4526
 
  assert(table->s->cached_row_logging_check == 0 ||
4527
 
              table->s->cached_row_logging_check == 1);
4528
 
 
4529
 
  return (thd->current_stmt_binlog_row_based &&
4530
 
          table->s->cached_row_logging_check &&
4531
 
          (thd->options & OPTION_BIN_LOG) &&
4532
 
          mysql_bin_log.is_open());
4533
 
}
4534
 
 
4535
 
 
4536
 
/**
4537
 
   Write table maps for all (manually or automatically) locked tables
4538
 
   to the binary log.
4539
 
 
4540
 
   This function will generate and write table maps for all tables
4541
 
   that are locked by the thread 'thd'.  Either manually locked
4542
 
   (stored in THD::locked_tables) and automatically locked (stored
4543
 
   in THD::lock) are considered.
4544
 
 
4545
 
   @param thd     Pointer to THD structure
4546
 
 
4547
 
   @retval 0   All OK
4548
 
   @retval 1   Failed to write all table maps
4549
 
 
4550
 
   @sa
4551
 
       THD::lock
4552
 
       THD::locked_tables
4553
 
*/
4554
 
 
4555
 
static int write_locked_table_maps(THD *thd)
4556
 
{
4557
 
  if (thd->get_binlog_table_maps() == 0)
4558
 
  {
4559
 
    DRIZZLE_LOCK *locks[3];
4560
 
    locks[0]= thd->extra_lock;
4561
 
    locks[1]= thd->lock;
4562
 
    locks[2]= thd->locked_tables;
4563
 
    for (uint i= 0 ; i < sizeof(locks)/sizeof(*locks) ; ++i )
4564
 
    {
4565
 
      DRIZZLE_LOCK const *const lock= locks[i];
4566
 
      if (lock == NULL)
4567
 
        continue;
4568
 
 
4569
 
      TABLE **const end_ptr= lock->table + lock->table_count;
4570
 
      for (TABLE **table_ptr= lock->table ; 
4571
 
           table_ptr != end_ptr ;
4572
 
           ++table_ptr)
4573
 
      {
4574
 
        TABLE *const table= *table_ptr;
4575
 
        if (table->current_lock == F_WRLCK &&
4576
 
            check_table_binlog_row_based(thd, table))
4577
 
        {
4578
 
          int const has_trans= table->file->has_transactions();
4579
 
          int const error= thd->binlog_write_table_map(table, has_trans);
4580
 
          /*
4581
 
            If an error occurs, it is the responsibility of the caller to
4582
 
            roll back the transaction.
4583
 
          */
4584
 
          if (unlikely(error))
4585
 
            return(1);
4586
 
        }
4587
 
      }
4588
 
    }
4589
 
  }
4590
 
  return(0);
4591
 
}
4592
 
 
4593
 
 
4594
 
typedef bool Log_func(THD*, TABLE*, bool, const uchar*, const uchar*);
4595
 
 
4596
 
static int binlog_log_row(TABLE* table,
4597
 
                          const uchar *before_record,
4598
 
                          const uchar *after_record,
4599
 
                          Log_func *log_func)
4600
 
{
4601
 
  if (table->no_replicate)
4602
 
    return 0;
4603
 
  bool error= 0;
4604
 
  THD *const thd= table->in_use;
4605
 
 
4606
 
  if (check_table_binlog_row_based(thd, table))
4607
 
  {
 
3261
static bool log_row_for_replication(Table* table,
 
3262
                           const unsigned char *before_record,
 
3263
                           const unsigned char *after_record)
 
3264
{
 
3265
  Session *const session= table->in_use;
 
3266
 
 
3267
  switch (session->lex->sql_command)
 
3268
  {
 
3269
  case SQLCOM_REPLACE:
 
3270
  case SQLCOM_INSERT:
 
3271
  case SQLCOM_REPLACE_SELECT:
 
3272
  case SQLCOM_INSERT_SELECT:
 
3273
  case SQLCOM_CREATE_TABLE:
 
3274
    transaction_services.insertRecord(session, table);
 
3275
    break;
 
3276
 
 
3277
  case SQLCOM_UPDATE:
 
3278
  case SQLCOM_UPDATE_MULTI:
 
3279
    transaction_services.updateRecord(session, table, before_record, after_record);
 
3280
    break;
 
3281
 
 
3282
  case SQLCOM_DELETE:
 
3283
  case SQLCOM_DELETE_MULTI:
 
3284
    transaction_services.deleteRecord(session, table);
 
3285
    break;
 
3286
 
4608
3287
    /*
4609
 
      If there are no table maps written to the binary log, this is
4610
 
      the first row handled in this statement. In that case, we need
4611
 
      to write table maps for all locked tables to the binary log.
 
3288
      For everything else we ignore the event (since it just involves a temp table)
4612
3289
    */
4613
 
    if (likely(!(error= write_locked_table_maps(thd))))
4614
 
    {
4615
 
      bool const has_trans= table->file->has_transactions();
4616
 
      error= (*log_func)(thd, table, has_trans, before_record, after_record);
4617
 
    }
 
3290
  default:
 
3291
    break;
4618
3292
  }
4619
 
  return error ? HA_ERR_RBR_LOGGING_FAILED : 0;
 
3293
 
 
3294
  return false; //error;
4620
3295
}
4621
3296
 
4622
 
int handler::ha_external_lock(THD *thd, int lock_type)
 
3297
int handler::ha_external_lock(Session *session, int lock_type)
4623
3298
{
4624
3299
  /*
4625
3300
    Whether this is lock or unlock, this should be true, and is to verify that
4634
3309
  */
4635
3310
  DRIZZLE_EXTERNAL_LOCK(lock_type);
4636
3311
 
4637
 
  int error= external_lock(thd, lock_type);
 
3312
  int error= external_lock(session, lock_type);
4638
3313
  if (error == 0)
4639
3314
    cached_table_flags= table_flags();
4640
 
  return(error);
 
3315
  return error;
4641
3316
}
4642
3317
 
4643
3318
 
4647
3322
int handler::ha_reset()
4648
3323
{
4649
3324
  /* Check that we have called all proper deallocation functions */
4650
 
  assert((uchar*) table->def_read_set.bitmap +
 
3325
  assert((unsigned char*) table->def_read_set.bitmap +
4651
3326
              table->s->column_bitmap_size ==
4652
 
              (uchar*) table->def_write_set.bitmap);
 
3327
              (unsigned char*) table->def_write_set.bitmap);
4653
3328
  assert(bitmap_is_set_all(&table->s->all_set));
4654
3329
  assert(table->key_read == 0);
4655
3330
  /* ensure that ha_index_end / ha_rnd_end has been called */
4662
3337
}
4663
3338
 
4664
3339
 
4665
 
int handler::ha_write_row(uchar *buf)
 
3340
int handler::ha_write_row(unsigned char *buf)
4666
3341
{
4667
3342
  int error;
4668
 
  Log_func *log_func= Write_rows_log_event::binlog_row_logging_function;
4669
3343
  DRIZZLE_INSERT_ROW_START();
4670
3344
 
 
3345
  /* 
 
3346
   * If we have a timestamp column, update it to the current time 
 
3347
   * 
 
3348
   * @TODO Technically, the below two lines can be take even further out of the
 
3349
   * handler interface and into the fill_record() method.
 
3350
   */
 
3351
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
 
3352
    table->timestamp_field->set_time();
 
3353
 
4671
3354
  mark_trx_read_write();
4672
3355
 
4673
3356
  if (unlikely(error= write_row(buf)))
4674
 
    return(error);
4675
 
  if (unlikely(error= binlog_log_row(table, 0, buf, log_func)))
4676
 
    return(error); /* purecov: inspected */
 
3357
    return error;
 
3358
 
 
3359
  if (unlikely(log_row_for_replication(table, 0, buf)))
 
3360
    return HA_ERR_RBR_LOGGING_FAILED; /* purecov: inspected */
 
3361
 
4677
3362
  DRIZZLE_INSERT_ROW_END();
4678
 
  return(0);
 
3363
  return 0;
4679
3364
}
4680
3365
 
4681
3366
 
4682
 
int handler::ha_update_row(const uchar *old_data, uchar *new_data)
 
3367
int handler::ha_update_row(const unsigned char *old_data, unsigned char *new_data)
4683
3368
{
4684
3369
  int error;
4685
 
  Log_func *log_func= Update_rows_log_event::binlog_row_logging_function;
4686
3370
 
4687
3371
  /*
4688
3372
    Some storage engines require that the new record is in record[0]
4694
3378
 
4695
3379
  if (unlikely(error= update_row(old_data, new_data)))
4696
3380
    return error;
4697
 
  if (unlikely(error= binlog_log_row(table, old_data, new_data, log_func)))
4698
 
    return error;
 
3381
 
 
3382
  if (unlikely(log_row_for_replication(table, old_data, new_data)))
 
3383
    return HA_ERR_RBR_LOGGING_FAILED;
 
3384
 
4699
3385
  return 0;
4700
3386
}
4701
3387
 
4702
 
int handler::ha_delete_row(const uchar *buf)
 
3388
int handler::ha_delete_row(const unsigned char *buf)
4703
3389
{
4704
3390
  int error;
4705
 
  Log_func *log_func= Delete_rows_log_event::binlog_row_logging_function;
4706
3391
 
4707
3392
  mark_trx_read_write();
4708
3393
 
4709
3394
  if (unlikely(error= delete_row(buf)))
4710
3395
    return error;
4711
 
  if (unlikely(error= binlog_log_row(table, buf, 0, log_func)))
4712
 
    return error;
 
3396
 
 
3397
  if (unlikely(log_row_for_replication(table, buf, 0)))
 
3398
    return HA_ERR_RBR_LOGGING_FAILED;
 
3399
 
4713
3400
  return 0;
4714
3401
}
4715
 
 
4716
 
 
4717
 
 
4718
 
/**
4719
 
  @details
4720
 
  use_hidden_primary_key() is called in case of an update/delete when
4721
 
  (table_flags() and HA_PRIMARY_KEY_REQUIRED_FOR_DELETE) is defined
4722
 
  but we don't have a primary key
4723
 
*/
4724
 
void handler::use_hidden_primary_key()
4725
 
{
4726
 
  /* fallback to use all columns in the table to identify row */
4727
 
  table->use_all_columns();
4728
 
}