~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/handler.cc

  • Committer: Brian Aker
  • Date: 2009-05-15 17:06:35 UTC
  • mto: This revision was merged to the branch mainline in revision 1023.
  • Revision ID: brian@gaz-20090515170635-croy1u63a3gqdn9n
Dead convert functions for character sets.

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)
 
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;
40
47
 
41
48
KEY_CREATE_INFO default_key_create_info= { HA_KEY_ALG_UNDEF, 0, {NULL,0}, {NULL,0} };
42
49
 
43
 
/* number of entries in handlertons[] */
 
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
 
  {NULL, 0}
55
 
};
56
 
 
57
57
const char *ha_row_type[] = {
58
58
  "", "FIXED", "DYNAMIC", "COMPRESSED", "REDUNDANT", "COMPACT", "PAGE", "?","?","?"
59
59
};
61
61
const char *tx_isolation_names[] =
62
62
{ "READ-UNCOMMITTED", "READ-COMMITTED", "REPEATABLE-READ", "SERIALIZABLE",
63
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
 
uint32_t 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_utf8_general_ci.coll->strnncoll(&my_charset_utf8_general_ci,
116
 
                           (const unsigned char *)name->str, name->length,
117
 
                           (const unsigned char *)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_utf8_general_ci,
138
 
                      (const unsigned char *)name->str, name->length,
139
 
                      (const unsigned char *)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
 
  return ha_default_handlerton(thd);
200
 
} /* ha_checktype */
201
 
 
202
 
 
203
 
handler *get_new_handler(TABLE_SHARE *share, MEM_ROOT *alloc,
204
 
                         handlerton *db_type)
205
 
{
206
 
  handler *file;
207
 
 
208
 
  if (db_type && db_type->state == SHOW_OPTION_YES && db_type->create)
209
 
  {
210
 
    if ((file= db_type->create(db_type, share, alloc)))
211
 
      file->init();
212
 
    return(file);
213
 
  }
214
 
  /*
215
 
    Try the default table type
216
 
    Here the call to current_thd() is ok as we call this function a lot of
217
 
    times but we enter this branch very seldom.
218
 
  */
219
 
  return(get_new_handler(share, alloc, ha_default_handlerton(current_thd)));
220
 
}
 
66
                               tx_isolation_names, NULL};
221
67
 
222
68
 
223
69
/**
236
82
 
237
83
  /* Allocate a pointer array for the error message strings. */
238
84
  /* Zerofill it to avoid uninitialized gaps. */
239
 
  if (! (errmsgs= (const char**) my_malloc(HA_ERR_ERRORS * sizeof(char*),
240
 
                                           MYF(MY_WME | MY_ZEROFILL))))
 
85
  if (! (errmsgs= (const char**) malloc(HA_ERR_ERRORS * sizeof(char*))))
241
86
    return 1;
 
87
  memset(errmsgs, 0, HA_ERR_ERRORS * sizeof(char *));
242
88
 
243
89
  /* Set the dedicated error messages. */
244
90
  SETMSG(HA_ERR_KEY_NOT_FOUND,          ER(ER_KEY_NOT_FOUND));
307
153
  return 0;
308
154
}
309
155
 
310
 
 
311
 
int ha_finalize_handlerton(st_plugin_int *plugin)
312
 
{
313
 
  handlerton *hton= (handlerton *)plugin->data;
314
 
 
315
 
  switch (hton->state)
316
 
  {
317
 
  case SHOW_OPTION_NO:
318
 
  case SHOW_OPTION_DISABLED:
319
 
    break;
320
 
  case SHOW_OPTION_YES:
321
 
    if (installed_htons[hton->db_type] == hton)
322
 
      installed_htons[hton->db_type]= NULL;
323
 
    break;
324
 
  };
325
 
 
326
 
  if (hton && plugin->plugin->deinit)
327
 
    (void)plugin->plugin->deinit(hton);
328
 
 
329
 
  free((unsigned char*)hton);
330
 
 
331
 
  return(0);
332
 
}
333
 
 
334
 
 
335
 
int ha_initialize_handlerton(st_plugin_int *plugin)
336
 
{
337
 
  handlerton *hton;
338
 
 
339
 
  hton= (handlerton *)my_malloc(sizeof(handlerton),
340
 
                                MYF(MY_WME | MY_ZEROFILL));
341
 
  /* 
342
 
    FIXME: the MY_ZEROFILL flag above doesn't zero all the bytes.
343
 
    
344
 
    This was detected after adding get_backup_engine member to handlerton
345
 
    structure. Apparently get_backup_engine was not NULL even though it was
346
 
    not initialized.
347
 
   */
348
 
  memset(hton, 0, sizeof(hton));
349
 
  /* Historical Requirement */
350
 
  plugin->data= hton; // shortcut for the future
351
 
  if (plugin->plugin->init)
352
 
  {
353
 
    if (plugin->plugin->init(hton))
354
 
    {
355
 
      sql_print_error(_("Plugin '%s' init function returned error."),
356
 
                      plugin->name.str);
357
 
      goto err;
358
 
    }
359
 
  }
360
 
 
361
 
  /*
362
 
    the switch below and hton->state should be removed when
363
 
    command-line options for plugins will be implemented
364
 
  */
365
 
  switch (hton->state) {
366
 
  case SHOW_OPTION_NO:
367
 
    break;
368
 
  case SHOW_OPTION_YES:
369
 
    {
370
 
      uint32_t tmp;
371
 
      /* now check the db_type for conflict */
372
 
      if (hton->db_type <= DB_TYPE_UNKNOWN ||
373
 
          hton->db_type >= DB_TYPE_DEFAULT ||
374
 
          installed_htons[hton->db_type])
375
 
      {
376
 
        int idx= (int) DB_TYPE_FIRST_DYNAMIC;
377
 
 
378
 
        while (idx < (int) DB_TYPE_DEFAULT && installed_htons[idx])
379
 
          idx++;
380
 
 
381
 
        if (idx == (int) DB_TYPE_DEFAULT)
382
 
        {
383
 
          sql_print_warning(_("Too many storage engines!"));
384
 
          return(1);
385
 
        }
386
 
        if (hton->db_type != DB_TYPE_UNKNOWN)
387
 
          sql_print_warning(_("Storage engine '%s' has conflicting typecode. "
388
 
                            "Assigning value %d."), plugin->plugin->name, idx);
389
 
        hton->db_type= (enum legacy_db_type) idx;
390
 
      }
391
 
      installed_htons[hton->db_type]= hton;
392
 
      tmp= hton->savepoint_offset;
393
 
      hton->savepoint_offset= savepoint_alloc_size;
394
 
      savepoint_alloc_size+= tmp;
395
 
      hton->slot= total_ha++;
396
 
      hton2plugin[hton->slot]=plugin;
397
 
      if (hton->prepare)
398
 
        total_ha_2pc++;
399
 
      break;
400
 
    }
401
 
    /* fall through */
402
 
  default:
403
 
    hton->state= SHOW_OPTION_DISABLED;
404
 
    break;
405
 
  }
406
 
  
407
 
  /* 
408
 
    This is entirely for legacy. We will create a new "disk based" hton and a 
409
 
    "memory" hton which will be configurable longterm. We should be able to 
410
 
    remove partition and myisammrg.
411
 
  */
412
 
  if (strcmp(plugin->plugin->name, "MEMORY") == 0)
413
 
    heap_hton= hton;
414
 
 
415
 
  if (strcmp(plugin->plugin->name, "MyISAM") == 0)
416
 
    myisam_hton= hton;
417
 
 
418
 
  return(0);
419
 
err:
420
 
  return(1);
421
 
}
422
 
 
423
156
int ha_init()
424
157
{
425
158
  int error= 0;
430
163
    binary log (which is considered a transaction-capable storage engine in
431
164
    counting total_ha)
432
165
  */
433
 
  opt_using_transactions= total_ha>(uint32_t)opt_bin_log;
434
166
  savepoint_alloc_size+= sizeof(SAVEPOINT);
435
167
  return(error);
436
168
}
439
171
{
440
172
  int error= 0;
441
173
 
442
 
  /* 
 
174
  /*
443
175
    This should be eventualy based  on the graceful shutdown flag.
444
176
    So if flag is equal to HA_PANIC_CLOSE, the deallocate
445
177
    the errors.
450
182
  return(error);
451
183
}
452
184
 
453
 
static bool dropdb_handlerton(THD *unused1 __attribute__((unused)),
454
 
                              plugin_ref plugin,
455
 
                              void *path)
456
 
{
457
 
  handlerton *hton= plugin_data(plugin, handlerton *);
458
 
  if (hton->state == SHOW_OPTION_YES && hton->drop_database)
459
 
    hton->drop_database(hton, (char *)path);
460
 
  return false;
461
 
}
462
 
 
463
 
 
464
 
void ha_drop_database(char* path)
465
 
{
466
 
  plugin_foreach(NULL, dropdb_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN, path);
467
 
}
468
 
 
469
 
 
470
 
static bool closecon_handlerton(THD *thd, plugin_ref plugin,
471
 
                                void *unused __attribute__((unused)))
472
 
{
473
 
  handlerton *hton= plugin_data(plugin, handlerton *);
474
 
  /*
475
 
    there's no need to rollback here as all transactions must
476
 
    be rolled back already
477
 
  */
478
 
  if (hton->state == SHOW_OPTION_YES && hton->close_connection &&
479
 
      thd_get_ha_data(thd, hton))
480
 
    hton->close_connection(hton, thd);
481
 
  return false;
482
 
}
483
 
 
484
 
 
485
 
/**
486
 
  @note
487
 
    don't bother to rollback here, it's done already
488
 
*/
489
 
void ha_close_connection(THD* thd)
490
 
{
491
 
  plugin_foreach(thd, closecon_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN, 0);
492
 
}
 
185
 
493
186
 
494
187
/* ========================================================================
495
188
 ======================= TRANSACTIONS ===================================*/
593
286
  -----------
594
287
 
595
288
  The server stores its transaction-related data in
596
 
  thd->transaction. This structure has two members of type
597
 
  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
598
291
  normal transactions respectively:
599
292
 
600
 
  - thd->transaction.stmt contains a list of engines
 
293
  - session->transaction.stmt contains a list of engines
601
294
  that are participating in the given statement
602
 
  - thd->transaction.all contains a list of engines that
 
295
  - session->transaction.all contains a list of engines that
603
296
  have participated in any of the statement transactions started
604
297
  within the context of the normal transaction.
605
298
  Each element of the list contains a pointer to the storage
606
299
  engine, engine-specific transactional data, and engine-specific
607
300
  transaction flags.
608
301
 
609
 
  In autocommit mode thd->transaction.all is empty.
610
 
  Instead, data of thd->transaction.stmt is
 
302
  In autocommit mode session->transaction.all is empty.
 
303
  Instead, data of session->transaction.stmt is
611
304
  used to commit/rollback the normal transaction.
612
305
 
613
306
  The list of registered engines has a few important properties:
618
311
  Transaction life cycle
619
312
  ----------------------
620
313
 
621
 
  When a new connection is established, thd->transaction
 
314
  When a new connection is established, session->transaction
622
315
  members are initialized to an empty state.
623
316
  If a statement uses any tables, all affected engines
624
317
  are registered in the statement engine list. In
634
327
  and emptied again at the next statement's end.
635
328
 
636
329
  The normal transaction is committed in a similar way
637
 
  (by going over all engines in thd->transaction.all list)
 
330
  (by going over all engines in session->transaction.all list)
638
331
  but at different times:
639
332
  - upon COMMIT SQL statement is issued by the user
640
333
  - implicitly, by the server, at the beginning of a DDL statement
644
337
  - if the user has requested so, by issuing ROLLBACK SQL
645
338
  statement
646
339
  - if one of the storage engines requested a rollback
647
 
  by setting thd->transaction_rollback_request. This may
 
340
  by setting session->transaction_rollback_request. This may
648
341
  happen in case, e.g., when the transaction in the engine was
649
342
  chosen a victim of the internal deadlock resolution algorithm
650
343
  and rolled back internally. When such a situation happens, there
671
364
  in each engine independently. The two-phase commit protocol
672
365
  is used only if:
673
366
  - all participating engines support two-phase commit (provide
674
 
    handlerton::prepare PSEA API call) and
 
367
    StorageEngine::prepare PSEA API call) and
675
368
  - transactions in at least two engines modify data (i.e. are
676
369
  not read-only).
677
370
 
686
379
  transactions of other participants.
687
380
 
688
381
  After the normal transaction has been committed,
689
 
  thd->transaction.all list is cleared.
 
382
  session->transaction.all list is cleared.
690
383
 
691
384
  When a connection is closed, the current normal transaction, if
692
385
  any, is rolled back.
735
428
 
736
429
  At the end of a statement, server call
737
430
  ha_autocommit_or_rollback() is invoked. This call in turn
738
 
  invokes handlerton::prepare() for every involved engine.
739
 
  Prepare is followed by a call to handlerton::commit_one_phase()
740
 
  If a one-phase commit will suffice, handlerton::prepare() is not
741
 
  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().
742
435
  At statement commit, the statement-related read-write engine
743
436
  flag is propagated to the corresponding flag in the normal
744
437
  transaction.  When the commit is complete, the list of registered
750
443
  ---------------------------------------------------
751
444
 
752
445
  DDLs and operations with non-transactional engines
753
 
  do not "register" in thd->transaction lists, and thus do not
 
446
  do not "register" in session->transaction lists, and thus do not
754
447
  modify the transaction state. Besides, each DDL in
755
448
  MySQL is prefixed with an implicit normal transaction commit
756
 
  (a call to end_active_trans()), and thus leaves nothing
 
449
  (a call to Session::endActiveTransaction()), and thus leaves nothing
757
450
  to modify.
758
451
  However, as it has been pointed out with CREATE TABLE .. SELECT,
759
452
  some DDL statements can start a *new* transaction.
797
490
    times per transaction.
798
491
 
799
492
*/
800
 
void trans_register_ha(THD *thd, bool all, handlerton *ht_arg)
 
493
void trans_register_ha(Session *session, bool all, StorageEngine *engine)
801
494
{
802
 
  THD_TRANS *trans;
 
495
  Session_TRANS *trans;
803
496
  Ha_trx_info *ha_info;
804
497
 
805
498
  if (all)
806
499
  {
807
 
    trans= &thd->transaction.all;
808
 
    thd->server_status|= SERVER_STATUS_IN_TRANS;
 
500
    trans= &session->transaction.all;
 
501
    session->server_status|= SERVER_STATUS_IN_TRANS;
809
502
  }
810
503
  else
811
 
    trans= &thd->transaction.stmt;
 
504
    trans= &session->transaction.stmt;
812
505
 
813
 
  ha_info= thd->ha_data[ht_arg->slot].ha_info + static_cast<unsigned>(all);
 
506
  ha_info= session->ha_data[engine->slot].ha_info + static_cast<unsigned>(all);
814
507
 
815
508
  if (ha_info->is_started())
816
509
    return; /* already registered, return */
817
510
 
818
 
  ha_info->register_ha(trans, ht_arg);
 
511
  ha_info->register_ha(trans, engine);
819
512
 
820
 
  trans->no_2pc|=(ht_arg->prepare==0);
821
 
  if (thd->transaction.xid_state.xid.is_null())
822
 
    thd->transaction.xid_state.xid.set(thd->query_id);
 
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);
823
516
 
824
517
  return;
825
518
}
830
523
  @retval
831
524
    1   error, transaction was rolled back
832
525
*/
833
 
int ha_prepare(THD *thd)
 
526
int ha_prepare(Session *session)
834
527
{
835
528
  int error=0, all=1;
836
 
  THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt;
 
529
  Session_TRANS *trans=all ? &session->transaction.all : &session->transaction.stmt;
837
530
  Ha_trx_info *ha_info= trans->ha_list;
838
531
  if (ha_info)
839
532
  {
840
533
    for (; ha_info; ha_info= ha_info->next())
841
534
    {
842
535
      int err;
843
 
      handlerton *ht= ha_info->ht();
844
 
      status_var_increment(thd->status_var.ha_prepare_count);
845
 
      if (ht->prepare)
 
536
      StorageEngine *engine= ha_info->engine();
 
537
      status_var_increment(session->status_var.ha_prepare_count);
 
538
      if ((err= engine->prepare(session, all)))
846
539
      {
847
 
        if ((err= ht->prepare(ht, thd, all)))
848
 
        {
849
 
          my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
850
 
          ha_rollback_trans(thd, all);
851
 
          error=1;
852
 
          break;
853
 
        }
 
540
        my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
 
541
        ha_rollback_trans(session, all);
 
542
        error=1;
 
543
        break;
854
544
      }
855
545
      else
856
546
      {
857
 
        push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
547
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
858
548
                            ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
859
 
                            ha_resolve_storage_engine_name(ht));
 
549
                            engine->getName().c_str());
860
550
      }
861
551
    }
862
552
  }
879
569
 
880
570
static
881
571
bool
882
 
ha_check_and_coalesce_trx_read_only(THD *thd, Ha_trx_info *ha_list,
 
572
ha_check_and_coalesce_trx_read_only(Session *session, Ha_trx_info *ha_list,
883
573
                                    bool all)
884
574
{
885
575
  /* The number of storage engines that have actual changes. */
893
583
 
894
584
    if (! all)
895
585
    {
896
 
      Ha_trx_info *ha_info_all= &thd->ha_data[ha_info->ht()->slot].ha_info[1];
 
586
      Ha_trx_info *ha_info_all= &session->ha_data[ha_info->engine()->slot].ha_info[1];
897
587
      assert(ha_info != ha_info_all);
898
588
      /*
899
589
        Merge read-only/read-write information about statement
900
590
        transaction to its enclosing normal transaction. Do this
901
591
        only if in a real transaction -- that is, if we know
902
 
        that ha_info_all is registered in thd->transaction.all.
 
592
        that ha_info_all is registered in session->transaction.all.
903
593
        Since otherwise we only clutter the normal transaction flags.
904
594
      */
905
595
      if (ha_info_all->is_started()) /* false if autocommit. */
933
623
    stored functions or triggers. So we simply do nothing now.
934
624
    TODO: This should be fixed in later ( >= 5.1) releases.
935
625
*/
936
 
int ha_commit_trans(THD *thd, bool all)
 
626
int ha_commit_trans(Session *session, bool all)
937
627
{
938
628
  int error= 0, cookie= 0;
939
629
  /*
940
630
    'all' means that this is either an explicit commit issued by
941
631
    user, or an implicit commit issued by a DDL.
942
632
  */
943
 
  THD_TRANS *trans= all ? &thd->transaction.all : &thd->transaction.stmt;
944
 
  bool is_real_trans= all || thd->transaction.all.ha_list == 0;
 
633
  Session_TRANS *trans= all ? &session->transaction.all : &session->transaction.stmt;
 
634
  bool is_real_trans= all || session->transaction.all.ha_list == 0;
945
635
  Ha_trx_info *ha_info= trans->ha_list;
946
 
  my_xid xid= thd->transaction.xid_state.xid.get_my_xid();
947
636
 
948
637
  /*
949
638
    We must not commit the normal transaction if a statement
951
640
    flags will not get propagated to its normal transaction's
952
641
    counterpart.
953
642
  */
954
 
  assert(thd->transaction.stmt.ha_list == NULL ||
955
 
              trans == &thd->transaction.stmt);
 
643
  assert(session->transaction.stmt.ha_list == NULL ||
 
644
              trans == &session->transaction.stmt);
956
645
 
957
 
  if (thd->in_sub_stmt)
958
 
  {
959
 
    /*
960
 
      Since we don't support nested statement transactions in 5.0,
961
 
      we can't commit or rollback stmt transactions while we are inside
962
 
      stored functions or triggers. So we simply do nothing now.
963
 
      TODO: This should be fixed in later ( >= 5.1) releases.
964
 
    */
965
 
    if (!all)
966
 
      return(0);
967
 
    /*
968
 
      We assume that all statements which commit or rollback main transaction
969
 
      are prohibited inside of stored functions or triggers. So they should
970
 
      bail out with error even before ha_commit_trans() call. To be 100% safe
971
 
      let us throw error in non-debug builds.
972
 
    */
973
 
    assert(0);
974
 
    my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
975
 
    return(2);
976
 
  }
977
646
  if (ha_info)
978
647
  {
979
648
    bool must_2pc;
980
649
 
981
 
    if (is_real_trans && wait_if_global_read_lock(thd, 0, 0))
 
650
    if (is_real_trans && wait_if_global_read_lock(session, 0, 0))
982
651
    {
983
 
      ha_rollback_trans(thd, all);
 
652
      ha_rollback_trans(session, all);
984
653
      return(1);
985
654
    }
986
655
 
987
 
    if (   is_real_trans
988
 
        && opt_readonly
989
 
        && ! thd->slave_thread
990
 
       )
991
 
    {
992
 
      my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only");
993
 
      ha_rollback_trans(thd, all);
994
 
      error= 1;
995
 
      goto end;
996
 
    }
997
 
 
998
 
    must_2pc= ha_check_and_coalesce_trx_read_only(thd, ha_info, all);
 
656
    must_2pc= ha_check_and_coalesce_trx_read_only(session, ha_info, all);
999
657
 
1000
658
    if (!trans->no_2pc && must_2pc)
1001
659
    {
1002
660
      for (; ha_info && !error; ha_info= ha_info->next())
1003
661
      {
1004
662
        int err;
1005
 
        handlerton *ht= ha_info->ht();
 
663
        StorageEngine *engine= ha_info->engine();
1006
664
        /*
1007
665
          Do not call two-phase commit if this particular
1008
666
          transaction is read-only. This allows for simpler
1014
672
          Sic: we know that prepare() is not NULL since otherwise
1015
673
          trans->no_2pc would have been set.
1016
674
        */
1017
 
        if ((err= ht->prepare(ht, thd, all)))
 
675
        if ((err= engine->prepare(session, all)))
1018
676
        {
1019
677
          my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
1020
678
          error= 1;
1021
679
        }
1022
 
        status_var_increment(thd->status_var.ha_prepare_count);
 
680
        status_var_increment(session->status_var.ha_prepare_count);
1023
681
      }
1024
 
      if (error || (is_real_trans && xid &&
1025
 
                    (error= !(cookie= tc_log->log_xid(thd, xid)))))
 
682
      if (error)
1026
683
      {
1027
 
        ha_rollback_trans(thd, all);
 
684
        ha_rollback_trans(session, all);
1028
685
        error= 1;
1029
686
        goto end;
1030
687
      }
1031
688
    }
1032
 
    error=ha_commit_one_phase(thd, all) ? (cookie ? 2 : 1) : 0;
1033
 
    if (cookie)
1034
 
      tc_log->unlog(cookie, xid);
 
689
    error=ha_commit_one_phase(session, all) ? (cookie ? 2 : 1) : 0;
1035
690
end:
1036
691
    if (is_real_trans)
1037
 
      start_waiting_global_read_lock(thd);
 
692
      start_waiting_global_read_lock(session);
1038
693
  }
1039
694
  return(error);
1040
695
}
1043
698
  @note
1044
699
  This function does not care about global read lock. A caller should.
1045
700
*/
1046
 
int ha_commit_one_phase(THD *thd, bool all)
 
701
int ha_commit_one_phase(Session *session, bool all)
1047
702
{
1048
703
  int error=0;
1049
 
  THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt;
1050
 
  bool is_real_trans=all || thd->transaction.all.ha_list == 0;
 
704
  Session_TRANS *trans=all ? &session->transaction.all : &session->transaction.stmt;
 
705
  bool is_real_trans=all || session->transaction.all.ha_list == 0;
1051
706
  Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
1052
707
  if (ha_info)
1053
708
  {
1054
709
    for (; ha_info; ha_info= ha_info_next)
1055
710
    {
1056
711
      int err;
1057
 
      handlerton *ht= ha_info->ht();
1058
 
      if ((err= ht->commit(ht, thd, all)))
 
712
      StorageEngine *engine= ha_info->engine();
 
713
      if ((err= engine->commit(session, all)))
1059
714
      {
1060
715
        my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
1061
716
        error=1;
1062
717
      }
1063
 
      status_var_increment(thd->status_var.ha_commit_count);
 
718
      status_var_increment(session->status_var.ha_commit_count);
1064
719
      ha_info_next= ha_info->next();
1065
720
      ha_info->reset(); /* keep it conveniently zero-filled */
1066
721
    }
1067
722
    trans->ha_list= 0;
1068
723
    trans->no_2pc=0;
1069
724
    if (is_real_trans)
1070
 
      thd->transaction.xid_state.xid.null();
 
725
      session->transaction.xid_state.xid.null();
1071
726
    if (all)
1072
727
    {
1073
 
      thd->variables.tx_isolation=thd->session_tx_isolation;
1074
 
      thd->transaction.cleanup();
 
728
      session->variables.tx_isolation=session->session_tx_isolation;
 
729
      session->transaction.cleanup();
1075
730
    }
1076
731
  }
1077
732
  return(error);
1078
733
}
1079
734
 
1080
735
 
1081
 
int ha_rollback_trans(THD *thd, bool all)
 
736
int ha_rollback_trans(Session *session, bool all)
1082
737
{
1083
738
  int error=0;
1084
 
  THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt;
 
739
  Session_TRANS *trans=all ? &session->transaction.all : &session->transaction.stmt;
1085
740
  Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
1086
 
  bool is_real_trans=all || thd->transaction.all.ha_list == 0;
 
741
  bool is_real_trans=all || session->transaction.all.ha_list == 0;
1087
742
 
1088
743
  /*
1089
744
    We must not rollback the normal transaction if a statement
1090
745
    transaction is pending.
1091
746
  */
1092
 
  assert(thd->transaction.stmt.ha_list == NULL ||
1093
 
              trans == &thd->transaction.stmt);
 
747
  assert(session->transaction.stmt.ha_list == NULL ||
 
748
              trans == &session->transaction.stmt);
1094
749
 
1095
 
  if (thd->in_sub_stmt)
1096
 
  {
1097
 
    /*
1098
 
      If we are inside stored function or trigger we should not commit or
1099
 
      rollback current statement transaction. See comment in ha_commit_trans()
1100
 
      call for more information.
1101
 
    */
1102
 
    if (!all)
1103
 
      return(0);
1104
 
    assert(0);
1105
 
    my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
1106
 
    return(1);
1107
 
  }
1108
750
  if (ha_info)
1109
751
  {
1110
752
    for (; ha_info; ha_info= ha_info_next)
1111
753
    {
1112
754
      int err;
1113
 
      handlerton *ht= ha_info->ht();
1114
 
      if ((err= ht->rollback(ht, thd, all)))
 
755
      StorageEngine *engine= ha_info->engine();
 
756
      if ((err= engine->rollback(session, all)))
1115
757
      { // cannot happen
1116
758
        my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
1117
759
        error=1;
1118
760
      }
1119
 
      status_var_increment(thd->status_var.ha_rollback_count);
 
761
      status_var_increment(session->status_var.ha_rollback_count);
1120
762
      ha_info_next= ha_info->next();
1121
763
      ha_info->reset(); /* keep it conveniently zero-filled */
1122
764
    }
1123
765
    trans->ha_list= 0;
1124
766
    trans->no_2pc=0;
1125
767
    if (is_real_trans)
1126
 
      thd->transaction.xid_state.xid.null();
 
768
      session->transaction.xid_state.xid.null();
1127
769
    if (all)
1128
770
    {
1129
 
      thd->variables.tx_isolation=thd->session_tx_isolation;
1130
 
      thd->transaction.cleanup();
 
771
      session->variables.tx_isolation=session->session_tx_isolation;
 
772
      session->transaction.cleanup();
1131
773
    }
1132
774
  }
1133
775
  if (all)
1134
 
    thd->transaction_rollback_request= false;
 
776
    session->transaction_rollback_request= false;
1135
777
 
1136
778
  /*
1137
779
    If a non-transactional table was updated, warn; don't warn if this is a
1142
784
    the error log; but we don't want users to wonder why they have this
1143
785
    message in the error log, so we don't send it.
1144
786
  */
1145
 
  if (is_real_trans && thd->transaction.all.modified_non_trans_table &&
1146
 
      !thd->slave_thread && thd->killed != THD::KILL_CONNECTION)
1147
 
    push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
787
  if (is_real_trans && session->transaction.all.modified_non_trans_table && session->killed != Session::KILL_CONNECTION)
 
788
    push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1148
789
                 ER_WARNING_NOT_COMPLETE_ROLLBACK,
1149
790
                 ER(ER_WARNING_NOT_COMPLETE_ROLLBACK));
1150
791
  return(error);
1161
802
    the user has used LOCK TABLES then that mechanism does not know to do the
1162
803
    commit.
1163
804
*/
1164
 
int ha_autocommit_or_rollback(THD *thd, int error)
 
805
int ha_autocommit_or_rollback(Session *session, int error)
1165
806
{
1166
 
  if (thd->transaction.stmt.ha_list)
 
807
  if (session->transaction.stmt.ha_list)
1167
808
  {
1168
809
    if (!error)
1169
810
    {
1170
 
      if (ha_commit_trans(thd, 0))
1171
 
        error=1;
 
811
      if (ha_commit_trans(session, 0))
 
812
        error=1;
1172
813
    }
1173
 
    else 
 
814
    else
1174
815
    {
1175
 
      (void) ha_rollback_trans(thd, 0);
1176
 
      if (thd->transaction_rollback_request && !thd->in_sub_stmt)
1177
 
        (void) ha_rollback(thd);
 
816
      (void) ha_rollback_trans(session, 0);
 
817
      if (session->transaction_rollback_request)
 
818
        (void) ha_rollback(session);
1178
819
    }
1179
820
 
1180
 
    thd->variables.tx_isolation=thd->session_tx_isolation;
 
821
    session->variables.tx_isolation=session->session_tx_isolation;
1181
822
  }
1182
823
  return(error);
1183
824
}
1184
825
 
1185
826
 
1186
 
struct xahton_st {
1187
 
  XID *xid;
1188
 
  int result;
1189
 
};
1190
 
 
1191
 
static bool xacommit_handlerton(THD *unused1 __attribute__((unused)),
1192
 
                                plugin_ref plugin,
1193
 
                                void *arg)
1194
 
{
1195
 
  handlerton *hton= plugin_data(plugin, handlerton *);
1196
 
  if (hton->state == SHOW_OPTION_YES && hton->recover)
1197
 
  {
1198
 
    hton->commit_by_xid(hton, ((struct xahton_st *)arg)->xid);
1199
 
    ((struct xahton_st *)arg)->result= 0;
1200
 
  }
1201
 
  return false;
1202
 
}
1203
 
 
1204
 
static bool xarollback_handlerton(THD *unused1 __attribute__((unused)),
1205
 
                                  plugin_ref plugin,
1206
 
                                  void *arg)
1207
 
{
1208
 
  handlerton *hton= plugin_data(plugin, handlerton *);
1209
 
  if (hton->state == SHOW_OPTION_YES && hton->recover)
1210
 
  {
1211
 
    hton->rollback_by_xid(hton, ((struct xahton_st *)arg)->xid);
1212
 
    ((struct xahton_st *)arg)->result= 0;
1213
 
  }
1214
 
  return false;
1215
 
}
1216
 
 
1217
 
 
1218
 
int ha_commit_or_rollback_by_xid(XID *xid, bool commit)
1219
 
{
1220
 
  struct xahton_st xaop;
1221
 
  xaop.xid= xid;
1222
 
  xaop.result= 1;
1223
 
 
1224
 
  plugin_foreach(NULL, commit ? xacommit_handlerton : xarollback_handlerton,
1225
 
                 DRIZZLE_STORAGE_ENGINE_PLUGIN, &xaop);
1226
 
 
1227
 
  return xaop.result;
1228
 
}
1229
 
 
1230
 
/**
1231
 
  recover() step of xa.
1232
 
 
1233
 
  @note
1234
 
    there are three modes of operation:
1235
 
    - automatic recover after a crash
1236
 
    in this case commit_list != 0, tc_heuristic_recover==0
1237
 
    all xids from commit_list are committed, others are rolled back
1238
 
    - manual (heuristic) recover
1239
 
    in this case commit_list==0, tc_heuristic_recover != 0
1240
 
    DBA has explicitly specified that all prepared transactions should
1241
 
    be committed (or rolled back).
1242
 
    - no recovery (MySQL did not detect a crash)
1243
 
    in this case commit_list==0, tc_heuristic_recover == 0
1244
 
    there should be no prepared transactions in this case.
1245
 
*/
1246
 
struct xarecover_st
1247
 
{
1248
 
  int len, found_foreign_xids, found_my_xids;
1249
 
  XID *list;
1250
 
  HASH *commit_list;
1251
 
  bool dry_run;
1252
 
};
1253
 
 
1254
 
static bool xarecover_handlerton(THD *unused __attribute__((unused)),
1255
 
                                 plugin_ref plugin,
1256
 
                                 void *arg)
1257
 
{
1258
 
  handlerton *hton= plugin_data(plugin, handlerton *);
1259
 
  struct xarecover_st *info= (struct xarecover_st *) arg;
1260
 
  int got;
1261
 
 
1262
 
  if (hton->state == SHOW_OPTION_YES && hton->recover)
1263
 
  {
1264
 
    while ((got= hton->recover(hton, info->list, info->len)) > 0 )
1265
 
    {
1266
 
      sql_print_information(_("Found %d prepared transaction(s) in %s"),
1267
 
                            got, ha_resolve_storage_engine_name(hton));
1268
 
      for (int i=0; i < got; i ++)
1269
 
      {
1270
 
        my_xid x=info->list[i].get_my_xid();
1271
 
        if (!x) // not "mine" - that is generated by external TM
1272
 
        {
1273
 
          xid_cache_insert(info->list+i, XA_PREPARED);
1274
 
          info->found_foreign_xids++;
1275
 
          continue;
1276
 
        }
1277
 
        if (info->dry_run)
1278
 
        {
1279
 
          info->found_my_xids++;
1280
 
          continue;
1281
 
        }
1282
 
        // recovery mode
1283
 
        if (info->commit_list ?
1284
 
            hash_search(info->commit_list, (unsigned char *)&x, sizeof(x)) != 0 :
1285
 
            tc_heuristic_recover == TC_HEURISTIC_RECOVER_COMMIT)
1286
 
        {
1287
 
          hton->commit_by_xid(hton, info->list+i);
1288
 
        }
1289
 
        else
1290
 
        {
1291
 
          hton->rollback_by_xid(hton, info->list+i);
1292
 
        }
1293
 
      }
1294
 
      if (got < info->len)
1295
 
        break;
1296
 
    }
1297
 
  }
1298
 
  return false;
1299
 
}
1300
 
 
1301
 
int ha_recover(HASH *commit_list)
1302
 
{
1303
 
  struct xarecover_st info;
1304
 
  info.found_foreign_xids= info.found_my_xids= 0;
1305
 
  info.commit_list= commit_list;
1306
 
  info.dry_run= (info.commit_list==0 && tc_heuristic_recover==0);
1307
 
  info.list= NULL;
1308
 
 
1309
 
  /* commit_list and tc_heuristic_recover cannot be set both */
1310
 
  assert(info.commit_list==0 || tc_heuristic_recover==0);
1311
 
  /* if either is set, total_ha_2pc must be set too */
1312
 
  assert(info.dry_run || total_ha_2pc>(uint32_t)opt_bin_log);
1313
 
 
1314
 
  if (total_ha_2pc <= (uint32_t)opt_bin_log)
1315
 
    return(0);
1316
 
 
1317
 
  if (info.commit_list)
1318
 
    sql_print_information(_("Starting crash recovery..."));
1319
 
 
1320
 
 
1321
 
#ifndef WILL_BE_DELETED_LATER
1322
 
 
1323
 
  /*
1324
 
    for now, only InnoDB supports 2pc. It means we can always safely
1325
 
    rollback all pending transactions, without risking inconsistent data
1326
 
  */
1327
 
 
1328
 
  assert(total_ha_2pc == (uint32_t) opt_bin_log+1); // only InnoDB and binlog
1329
 
  tc_heuristic_recover= TC_HEURISTIC_RECOVER_ROLLBACK; // forcing ROLLBACK
1330
 
  info.dry_run=false;
1331
 
#endif
1332
 
 
1333
 
 
1334
 
  for (info.len= MAX_XID_LIST_SIZE ; 
1335
 
       info.list==0 && info.len > MIN_XID_LIST_SIZE; info.len/=2)
1336
 
  {
1337
 
    info.list=(XID *)my_malloc(info.len*sizeof(XID), MYF(0));
1338
 
  }
1339
 
  if (!info.list)
1340
 
  {
1341
 
    sql_print_error(ER(ER_OUTOFMEMORY), info.len*sizeof(XID));
1342
 
    return(1);
1343
 
  }
1344
 
 
1345
 
  plugin_foreach(NULL, xarecover_handlerton, 
1346
 
                 DRIZZLE_STORAGE_ENGINE_PLUGIN, &info);
1347
 
 
1348
 
  free((unsigned char*)info.list);
1349
 
  if (info.found_foreign_xids)
1350
 
    sql_print_warning(_("Found %d prepared XA transactions"), 
1351
 
                      info.found_foreign_xids);
1352
 
  if (info.dry_run && info.found_my_xids)
1353
 
  {
1354
 
    sql_print_error(_("Found %d prepared transactions! It means that drizzled "
1355
 
                    "was not shut down properly last time and critical "
1356
 
                    "recovery information (last binlog or %s file) was "
1357
 
                    "manually deleted after a crash. You have to start "
1358
 
                    "drizzled with the --tc-heuristic-recover switch to "
1359
 
                    "commit or rollback pending transactions."),
1360
 
                    info.found_my_xids, opt_tc_log_file);
1361
 
    return(1);
1362
 
  }
1363
 
  if (info.commit_list)
1364
 
    sql_print_information(_("Crash recovery finished."));
1365
 
  return(0);
1366
 
}
 
827
 
1367
828
 
1368
829
/**
1369
830
  return the list of XID's to a client, the same way SHOW commands do.
1373
834
    so mysql_xa_recover does not filter XID's to ensure uniqueness.
1374
835
    It can be easily fixed later, if necessary.
1375
836
*/
1376
 
bool mysql_xa_recover(THD *thd)
 
837
bool mysql_xa_recover(Session *session)
1377
838
{
1378
839
  List<Item> field_list;
1379
 
  Protocol *protocol= thd->protocol;
 
840
  Protocol *protocol= session->protocol;
1380
841
  int i=0;
1381
842
  XID_STATE *xs;
1382
843
 
1385
846
  field_list.push_back(new Item_int("bqual_length", 0, MY_INT32_NUM_DECIMAL_DIGITS));
1386
847
  field_list.push_back(new Item_empty_string("data",XIDDATASIZE));
1387
848
 
1388
 
  if (protocol->send_fields(&field_list,
1389
 
                            Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
 
849
  if (protocol->sendFields(&field_list,
 
850
                           Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
1390
851
    return(1);
1391
852
 
1392
853
  pthread_mutex_lock(&LOCK_xid_cache);
1394
855
  {
1395
856
    if (xs->xa_state==XA_PREPARED)
1396
857
    {
1397
 
      protocol->prepare_for_resend();
1398
 
      protocol->store_int64_t((int64_t)xs->xid.formatID, false);
1399
 
      protocol->store_int64_t((int64_t)xs->xid.gtrid_length, false);
1400
 
      protocol->store_int64_t((int64_t)xs->xid.bqual_length, false);
 
858
      protocol->prepareForResend();
 
859
      protocol->store((int64_t)xs->xid.formatID);
 
860
      protocol->store((int64_t)xs->xid.gtrid_length);
 
861
      protocol->store((int64_t)xs->xid.bqual_length);
1401
862
      protocol->store(xs->xid.data, xs->xid.gtrid_length+xs->xid.bqual_length,
1402
863
                      &my_charset_bin);
1403
864
      if (protocol->write())
1409
870
  }
1410
871
 
1411
872
  pthread_mutex_unlock(&LOCK_xid_cache);
1412
 
  my_eof(thd);
 
873
  session->my_eof();
1413
874
  return(0);
1414
875
}
1415
876
 
1416
 
/**
1417
 
  @details
1418
 
  This function should be called when MySQL sends rows of a SELECT result set
1419
 
  or the EOF mark to the client. It releases a possible adaptive hash index
1420
 
  S-latch held by thd in InnoDB and also releases a possible InnoDB query
1421
 
  FIFO ticket to enter InnoDB. To save CPU time, InnoDB allows a thd to
1422
 
  keep them over several calls of the InnoDB handler interface when a join
1423
 
  is executed. But when we let the control to pass to the client they have
1424
 
  to be released because if the application program uses mysql_use_result(),
1425
 
  it may deadlock on the S-latch if the application on another connection
1426
 
  performs another SQL query. In MySQL-4.1 this is even more important because
1427
 
  there a connection can have several SELECT queries open at the same time.
1428
 
 
1429
 
  @param thd           the thread handle of the current connection
1430
 
 
1431
 
  @return
1432
 
    always 0
1433
 
*/
1434
 
static bool release_temporary_latches(THD *thd, plugin_ref plugin,
1435
 
                                      void *unused __attribute__((unused)))
1436
 
{
1437
 
  handlerton *hton= plugin_data(plugin, handlerton *);
1438
 
 
1439
 
  if (hton->state == SHOW_OPTION_YES && hton->release_temporary_latches)
1440
 
    hton->release_temporary_latches(hton, thd);
1441
 
 
1442
 
  return false;
1443
 
}
1444
 
 
1445
 
 
1446
 
int ha_release_temporary_latches(THD *thd)
1447
 
{
1448
 
  plugin_foreach(thd, release_temporary_latches, DRIZZLE_STORAGE_ENGINE_PLUGIN, 
1449
 
                 NULL);
1450
 
 
1451
 
  return 0;
1452
 
}
1453
 
 
1454
 
int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv)
 
877
 
 
878
int ha_rollback_to_savepoint(Session *session, SAVEPOINT *sv)
1455
879
{
1456
880
  int error=0;
1457
 
  THD_TRANS *trans= (thd->in_sub_stmt ? &thd->transaction.stmt :
1458
 
                                        &thd->transaction.all);
 
881
  Session_TRANS *trans= &session->transaction.all;
1459
882
  Ha_trx_info *ha_info, *ha_info_next;
1460
883
 
1461
884
  trans->no_2pc=0;
1466
889
  for (ha_info= sv->ha_list; ha_info; ha_info= ha_info->next())
1467
890
  {
1468
891
    int err;
1469
 
    handlerton *ht= ha_info->ht();
1470
 
    assert(ht);
1471
 
    assert(ht->savepoint_set != 0);
1472
 
    if ((err= ht->savepoint_rollback(ht, thd,
1473
 
                                     (unsigned char *)(sv+1)+ht->savepoint_offset)))
 
892
    StorageEngine *engine= ha_info->engine();
 
893
    assert(engine);
 
894
    if ((err= engine->savepoint_rollback(session,
 
895
                                         (void *)(sv+1))))
1474
896
    { // cannot happen
1475
897
      my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
1476
898
      error=1;
1477
899
    }
1478
 
    status_var_increment(thd->status_var.ha_savepoint_rollback_count);
1479
 
    trans->no_2pc|= ht->prepare == 0;
 
900
    status_var_increment(session->status_var.ha_savepoint_rollback_count);
 
901
    trans->no_2pc|= not engine->has_2pc();
1480
902
  }
1481
903
  /*
1482
904
    rolling back the transaction in all storage engines that were not part of
1486
908
       ha_info= ha_info_next)
1487
909
  {
1488
910
    int err;
1489
 
    handlerton *ht= ha_info->ht();
1490
 
    if ((err= ht->rollback(ht, thd, !thd->in_sub_stmt)))
 
911
    StorageEngine *engine= ha_info->engine();
 
912
    if ((err= engine->rollback(session, !(0))))
1491
913
    { // cannot happen
1492
914
      my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
1493
915
      error=1;
1494
916
    }
1495
 
    status_var_increment(thd->status_var.ha_rollback_count);
 
917
    status_var_increment(session->status_var.ha_rollback_count);
1496
918
    ha_info_next= ha_info->next();
1497
919
    ha_info->reset(); /* keep it conveniently zero-filled */
1498
920
  }
1506
928
  section "4.33.4 SQL-statements and transaction states",
1507
929
  SAVEPOINT is *not* transaction-initiating SQL-statement
1508
930
*/
1509
 
int ha_savepoint(THD *thd, SAVEPOINT *sv)
 
931
int ha_savepoint(Session *session, SAVEPOINT *sv)
1510
932
{
1511
933
  int error=0;
1512
 
  THD_TRANS *trans= (thd->in_sub_stmt ? &thd->transaction.stmt :
1513
 
                                        &thd->transaction.all);
 
934
  Session_TRANS *trans= &session->transaction.all;
1514
935
  Ha_trx_info *ha_info= trans->ha_list;
1515
936
  for (; ha_info; ha_info= ha_info->next())
1516
937
  {
1517
938
    int err;
1518
 
    handlerton *ht= ha_info->ht();
1519
 
    assert(ht);
1520
 
    if (! ht->savepoint_set)
 
939
    StorageEngine *engine= ha_info->engine();
 
940
    assert(engine);
 
941
/*    if (! engine->savepoint_set)
1521
942
    {
1522
943
      my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "SAVEPOINT");
1523
944
      error=1;
1524
945
      break;
1525
 
    }
1526
 
    if ((err= ht->savepoint_set(ht, thd, (unsigned char *)(sv+1)+ht->savepoint_offset)))
 
946
    } */
 
947
    if ((err= engine->savepoint_set(session, (void *)(sv+1))))
1527
948
    { // cannot happen
1528
949
      my_error(ER_GET_ERRNO, MYF(0), err);
1529
950
      error=1;
1530
951
    }
1531
 
    status_var_increment(thd->status_var.ha_savepoint_count);
 
952
    status_var_increment(session->status_var.ha_savepoint_count);
1532
953
  }
1533
954
  /*
1534
955
    Remember the list of registered storage engines. All new
1538
959
  return(error);
1539
960
}
1540
961
 
1541
 
int ha_release_savepoint(THD *thd, SAVEPOINT *sv)
 
962
int ha_release_savepoint(Session *session, SAVEPOINT *sv)
1542
963
{
1543
964
  int error=0;
1544
965
  Ha_trx_info *ha_info= sv->ha_list;
1546
967
  for (; ha_info; ha_info= ha_info->next())
1547
968
  {
1548
969
    int err;
1549
 
    handlerton *ht= ha_info->ht();
 
970
    StorageEngine *engine= ha_info->engine();
1550
971
    /* Savepoint life time is enclosed into transaction life time. */
1551
 
    assert(ht);
1552
 
    if (!ht->savepoint_release)
1553
 
      continue;
1554
 
    if ((err= ht->savepoint_release(ht, thd,
1555
 
                                    (unsigned char *)(sv+1) + ht->savepoint_offset)))
 
972
    assert(engine);
 
973
    if ((err= engine->savepoint_release(session,
 
974
                                        (void *)(sv+1))))
1556
975
    { // cannot happen
1557
976
      my_error(ER_GET_ERRNO, MYF(0), err);
1558
977
      error=1;
1562
981
}
1563
982
 
1564
983
 
1565
 
static bool snapshot_handlerton(THD *thd, plugin_ref plugin, void *arg)
1566
 
{
1567
 
  handlerton *hton= plugin_data(plugin, handlerton *);
1568
 
  if (hton->state == SHOW_OPTION_YES &&
1569
 
      hton->start_consistent_snapshot)
1570
 
  {
1571
 
    hton->start_consistent_snapshot(hton, thd);
1572
 
    *((bool *)arg)= false;
1573
 
  }
1574
 
  return false;
1575
 
}
1576
 
 
1577
 
int ha_start_consistent_snapshot(THD *thd)
1578
 
{
1579
 
  bool warn= true;
1580
 
 
1581
 
  plugin_foreach(thd, snapshot_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN, &warn);
1582
 
 
1583
 
  /*
1584
 
    Same idea as when one wants to CREATE TABLE in one engine which does not
1585
 
    exist:
1586
 
  */
1587
 
  if (warn)
1588
 
    push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
1589
 
                 "This MySQL server does not support any "
1590
 
                 "consistent-read capable storage engine");
1591
 
  return 0;
1592
 
}
1593
 
 
1594
 
 
1595
 
static bool flush_handlerton(THD *thd __attribute__((unused)),
1596
 
                             plugin_ref plugin,
1597
 
                             void *arg __attribute__((unused)))
1598
 
{
1599
 
  handlerton *hton= plugin_data(plugin, handlerton *);
1600
 
  if (hton->state == SHOW_OPTION_YES && hton->flush_logs && 
1601
 
      hton->flush_logs(hton))
1602
 
    return true;
1603
 
  return false;
1604
 
}
1605
 
 
1606
 
 
1607
 
bool ha_flush_logs(handlerton *db_type)
1608
 
{
1609
 
  if (db_type == NULL)
1610
 
  {
1611
 
    if (plugin_foreach(NULL, flush_handlerton,
1612
 
                          DRIZZLE_STORAGE_ENGINE_PLUGIN, 0))
1613
 
      return true;
1614
 
  }
1615
 
  else
1616
 
  {
1617
 
    if (db_type->state != SHOW_OPTION_YES ||
1618
 
        (db_type->flush_logs && db_type->flush_logs(db_type)))
1619
 
      return true;
1620
 
  }
1621
 
  return false;
1622
 
}
1623
 
 
1624
 
static const char *check_lowercase_names(handler *file, const char *path,
1625
 
                                         char *tmp_path)
1626
 
{
1627
 
  if (lower_case_table_names != 2 || (file->ha_table_flags() & HA_FILE_BASED))
1628
 
    return path;
1629
 
 
1630
 
  /* Ensure that table handler get path in lower case */
1631
 
  if (tmp_path != path)
1632
 
    my_stpcpy(tmp_path, path);
1633
 
 
1634
 
  /*
1635
 
    we only should turn into lowercase database/table part
1636
 
    so start the process after homedirectory
1637
 
  */
1638
 
  my_casedn_str(files_charset_info, tmp_path + mysql_data_home_len);
1639
 
  return tmp_path;
1640
 
}
1641
 
 
1642
 
 
1643
 
/**
1644
 
  An interceptor to hijack the text of the error message without
1645
 
  setting an error in the thread. We need the text to present it
1646
 
  in the form of a warning to the user.
1647
 
*/
1648
 
 
1649
 
struct Ha_delete_table_error_handler: public Internal_error_handler
1650
 
{
1651
 
public:
1652
 
  virtual bool handle_error(uint32_t sql_errno,
1653
 
                            const char *message,
1654
 
                            DRIZZLE_ERROR::enum_warning_level level,
1655
 
                            THD *thd);
1656
 
  char buff[DRIZZLE_ERRMSG_SIZE];
1657
 
};
1658
 
 
1659
 
 
1660
 
bool
1661
 
Ha_delete_table_error_handler::
1662
 
handle_error(uint32_t sql_errno  __attribute__((unused)),
1663
 
             const char *message,
1664
 
             DRIZZLE_ERROR::enum_warning_level level __attribute__((unused)),
1665
 
             THD *thd __attribute__((unused)))
1666
 
{
1667
 
  /* Grab the error message */
1668
 
  strmake(buff, message, sizeof(buff)-1);
1669
 
  return true;
1670
 
}
1671
 
 
1672
 
 
1673
 
/**
1674
 
  This should return ENOENT if the file doesn't exists.
1675
 
  The .frm file will be deleted only if we return 0 or ENOENT
1676
 
*/
1677
 
int ha_delete_table(THD *thd, handlerton *table_type, const char *path,
1678
 
                    const char *db, const char *alias, bool generate_warning)
1679
 
{
1680
 
  handler *file;
1681
 
  char tmp_path[FN_REFLEN];
1682
 
  int error;
1683
 
  Table dummy_table;
1684
 
  TABLE_SHARE dummy_share;
1685
 
 
1686
 
  memset(&dummy_table, 0, sizeof(dummy_table));
1687
 
  memset(&dummy_share, 0, sizeof(dummy_share));
1688
 
  dummy_table.s= &dummy_share;
1689
 
 
1690
 
  /* DB_TYPE_UNKNOWN is used in ALTER Table when renaming only .frm files */
1691
 
  if (table_type == NULL ||
1692
 
      ! (file=get_new_handler((TABLE_SHARE*)0, thd->mem_root, table_type)))
1693
 
    return(ENOENT);
1694
 
 
1695
 
  path= check_lowercase_names(file, path, tmp_path);
1696
 
  if ((error= file->ha_delete_table(path)) && generate_warning)
1697
 
  {
1698
 
    /*
1699
 
      Because file->print_error() use my_error() to generate the error message
1700
 
      we use an internal error handler to intercept it and store the text
1701
 
      in a temporary buffer. Later the message will be presented to user
1702
 
      as a warning.
1703
 
    */
1704
 
    Ha_delete_table_error_handler ha_delete_table_error_handler;
1705
 
 
1706
 
    /* Fill up strucutures that print_error may need */
1707
 
    dummy_share.path.str= (char*) path;
1708
 
    dummy_share.path.length= strlen(path);
1709
 
    dummy_share.db.str= (char*) db;
1710
 
    dummy_share.db.length= strlen(db);
1711
 
    dummy_share.table_name.str= (char*) alias;
1712
 
    dummy_share.table_name.length= strlen(alias);
1713
 
    dummy_table.alias= alias;
1714
 
 
1715
 
    file->change_table_ptr(&dummy_table, &dummy_share);
1716
 
 
1717
 
    thd->push_internal_handler(&ha_delete_table_error_handler);
1718
 
    file->print_error(error, 0);
1719
 
 
1720
 
    thd->pop_internal_handler();
1721
 
 
1722
 
    /*
1723
 
      XXX: should we convert *all* errors to warnings here?
1724
 
      What if the error is fatal?
1725
 
    */
1726
 
    push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_ERROR, error,
1727
 
                ha_delete_table_error_handler.buff);
1728
 
  }
1729
 
  delete file;
1730
 
  return(error);
1731
 
}
 
984
 
 
985
 
1732
986
 
1733
987
/****************************************************************************
1734
988
** General handler functions
1738
992
  handler *new_handler= get_new_handler(table->s, mem_root, table->s->db_type());
1739
993
  /*
1740
994
    Allocate handler->ref here because otherwise ha_open will allocate it
1741
 
    on this->table->mem_root and we will not be able to reclaim that memory 
 
995
    on this->table->mem_root and we will not be able to reclaim that memory
1742
996
    when the clone handler object is destroyed.
1743
997
  */
1744
998
  if (!(new_handler->ref= (unsigned char*) alloc_root(mem_root, ALIGN_SIZE(ref_length)*2)))
1751
1005
  return NULL;
1752
1006
}
1753
1007
 
1754
 
 
 
1008
int handler::ha_index_init(uint32_t idx, bool sorted)
 
1009
{
 
1010
  int result;
 
1011
  assert(inited==NONE);
 
1012
  if (!(result= index_init(idx, sorted)))
 
1013
    inited=INDEX;
 
1014
  end_range= NULL;
 
1015
  return(result);
 
1016
}
 
1017
 
 
1018
int handler::ha_index_end()
 
1019
{
 
1020
  assert(inited==INDEX);
 
1021
  inited=NONE;
 
1022
  end_range= NULL;
 
1023
  return(index_end());
 
1024
}
 
1025
 
 
1026
int handler::ha_rnd_init(bool scan)
 
1027
{
 
1028
  int result;
 
1029
  assert(inited==NONE || (inited==RND && scan));
 
1030
  inited= (result= rnd_init(scan)) ? NONE: RND;
 
1031
  return(result);
 
1032
}
 
1033
 
 
1034
int handler::ha_rnd_end()
 
1035
{
 
1036
  assert(inited==RND);
 
1037
  inited=NONE;
 
1038
  return(rnd_end());
 
1039
}
 
1040
 
 
1041
int handler::ha_index_or_rnd_end()
 
1042
{
 
1043
  return inited == INDEX ? ha_index_end() : inited == RND ? ha_rnd_end() : 0;
 
1044
}
 
1045
 
 
1046
handler::Table_flags handler::ha_table_flags() const
 
1047
{
 
1048
  return cached_table_flags;
 
1049
}
 
1050
 
 
1051
void handler::ha_start_bulk_insert(ha_rows rows)
 
1052
{
 
1053
  estimation_rows_to_insert= rows;
 
1054
  start_bulk_insert(rows);
 
1055
}
 
1056
 
 
1057
int handler::ha_end_bulk_insert()
 
1058
{
 
1059
  estimation_rows_to_insert= 0;
 
1060
  return end_bulk_insert();
 
1061
}
 
1062
 
 
1063
void handler::change_table_ptr(Table *table_arg, TableShare *share)
 
1064
{
 
1065
  table= table_arg;
 
1066
  table_share= share;
 
1067
}
 
1068
 
 
1069
const key_map *handler::keys_to_use_for_scanning()
 
1070
{
 
1071
  return &key_map_empty;
 
1072
}
 
1073
 
 
1074
bool handler::has_transactions()
 
1075
{
 
1076
  return (ha_table_flags() & HA_NO_TRANSACTIONS) == 0;
 
1077
}
1755
1078
 
1756
1079
void handler::ha_statistic_increment(ulong SSV::*offset) const
1757
1080
{
1758
1081
  status_var_increment(table->in_use->status_var.*offset);
1759
1082
}
1760
1083
 
1761
 
void **handler::ha_data(THD *thd) const
1762
 
{
1763
 
  return thd_ha_data(thd, ht);
1764
 
}
1765
 
 
1766
 
THD *handler::ha_thd(void) const
1767
 
{
1768
 
  assert(!table || !table->in_use || table->in_use == current_thd);
1769
 
  return (table && table->in_use) ? table->in_use : current_thd;
1770
 
}
 
1084
void **handler::ha_data(Session *session) const
 
1085
{
 
1086
  return session_ha_data(session, engine);
 
1087
}
 
1088
 
 
1089
Session *handler::ha_session(void) const
 
1090
{
 
1091
  assert(!table || !table->in_use || table->in_use == current_session);
 
1092
  return (table && table->in_use) ? table->in_use : current_session;
 
1093
}
 
1094
 
 
1095
 
 
1096
bool handler::is_fatal_error(int error, uint32_t flags)
 
1097
{
 
1098
  if (!error ||
 
1099
      ((flags & HA_CHECK_DUP_KEY) &&
 
1100
       (error == HA_ERR_FOUND_DUPP_KEY ||
 
1101
        error == HA_ERR_FOUND_DUPP_UNIQUE)))
 
1102
    return false;
 
1103
  return true;
 
1104
}
 
1105
 
 
1106
 
 
1107
ha_rows handler::records() { return stats.records; }
1771
1108
 
1772
1109
/**
1773
1110
  Open database-handler.
1804
1141
    (void) extra(HA_EXTRA_NO_READCHECK);        // Not needed in SQL
1805
1142
 
1806
1143
    /* ref is already allocated for us if we're called from handler::clone() */
1807
 
    if (!ref && !(ref= (unsigned char*) alloc_root(&table->mem_root, 
 
1144
    if (!ref && !(ref= (unsigned char*) alloc_root(&table->mem_root,
1808
1145
                                          ALIGN_SIZE(ref_length)*2)))
1809
1146
    {
1810
1147
      close();
1898
1235
void handler::adjust_next_insert_id_after_explicit_value(uint64_t nr)
1899
1236
{
1900
1237
  /*
1901
 
    If we have set THD::next_insert_id previously and plan to insert an
 
1238
    If we have set Session::next_insert_id previously and plan to insert an
1902
1239
    explicitely-specified value larger than this, we need to increase
1903
 
    THD::next_insert_id to be greater than the explicit value.
 
1240
    Session::next_insert_id to be greater than the explicit value.
1904
1241
  */
1905
1242
  if ((next_insert_id > 0) && (nr >= next_insert_id))
1906
1243
    set_next_insert_id(compute_next_insert_id(nr, &table->in_use->variables));
1976
1313
    again to reserve a new interval.
1977
1314
 
1978
1315
  - In both cases, the reserved intervals are remembered in
1979
 
    thd->auto_inc_intervals_in_cur_stmt_for_binlog if statement-based
 
1316
    session->auto_inc_intervals_in_cur_stmt_for_binlog if statement-based
1980
1317
    binlogging; the last reserved interval is remembered in
1981
1318
    auto_inc_interval_for_cur_row.
1982
1319
 
1990
1327
    start counting from the inserted value.
1991
1328
 
1992
1329
    This function's "outputs" are: the table's auto_increment field is filled
1993
 
    with a value, thd->next_insert_id is filled with the value to use for the
 
1330
    with a value, session->next_insert_id is filled with the value to use for the
1994
1331
    next row, if a value was autogenerated for the current row it is stored in
1995
 
    thd->insert_id_for_cur_row, if get_auto_increment() was called
1996
 
    thd->auto_inc_interval_for_cur_row is modified, if that interval is not
1997
 
    present in thd->auto_inc_intervals_in_cur_stmt_for_binlog it is added to
 
1332
    session->insert_id_for_cur_row, if get_auto_increment() was called
 
1333
    session->auto_inc_interval_for_cur_row is modified, if that interval is not
 
1334
    present in session->auto_inc_intervals_in_cur_stmt_for_binlog it is added to
1998
1335
    this list.
1999
1336
 
2000
1337
  @todo
2021
1358
{
2022
1359
  uint64_t nr, nb_reserved_values;
2023
1360
  bool append= false;
2024
 
  THD *thd= table->in_use;
2025
 
  struct system_variables *variables= &thd->variables;
 
1361
  Session *session= table->in_use;
 
1362
  struct system_variables *variables= &session->variables;
2026
1363
 
2027
1364
  /*
2028
1365
    next_insert_id is a "cursor" into the reserved interval, it may go greater
2030
1367
  */
2031
1368
  assert(next_insert_id >= auto_inc_interval_for_cur_row.minimum());
2032
1369
 
2033
 
  if ((nr= table->next_number_field->val_int()) != 0)
 
1370
  /* We check for auto_increment_field_not_null as 0 is an explicit value
 
1371
     for an auto increment column, not a magic value like NULL is.
 
1372
     same as sql_mode=NO_AUTO_VALUE_ON_ZERO */
 
1373
 
 
1374
  if ((nr= table->next_number_field->val_int()) != 0
 
1375
      || table->auto_increment_field_not_null)
2034
1376
  {
2035
1377
    /*
2036
1378
      Update next_insert_id if we had already generated a value in this
2047
1389
  {
2048
1390
    /* next_insert_id is beyond what is reserved, so we reserve more. */
2049
1391
    const Discrete_interval *forced=
2050
 
      thd->auto_inc_intervals_forced.get_next();
 
1392
      session->auto_inc_intervals_forced.get_next();
2051
1393
    if (forced != NULL)
2052
1394
    {
2053
1395
      nr= forced->minimum();
2060
1402
        handler::ha_start_bulk_insert(); if 0 it means "unknown".
2061
1403
      */
2062
1404
      uint32_t nb_already_reserved_intervals=
2063
 
        thd->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements();
 
1405
        session->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements();
2064
1406
      uint64_t nb_desired_values;
2065
1407
      /*
2066
1408
        If an estimation was given to the engine:
2081
1423
        /* avoid overflow in formula, with this if() */
2082
1424
        if (nb_already_reserved_intervals <= AUTO_INC_DEFAULT_NB_MAX_BITS)
2083
1425
        {
2084
 
          nb_desired_values= AUTO_INC_DEFAULT_NB_ROWS * 
 
1426
          nb_desired_values= AUTO_INC_DEFAULT_NB_ROWS *
2085
1427
            (1 << nb_already_reserved_intervals);
2086
 
          set_if_smaller(nb_desired_values, AUTO_INC_DEFAULT_NB_MAX);
 
1428
          set_if_smaller(nb_desired_values, (uint64_t)AUTO_INC_DEFAULT_NB_MAX);
2087
1429
        }
2088
1430
        else
2089
1431
          nb_desired_values= AUTO_INC_DEFAULT_NB_MAX;
2095
1437
                         &nb_reserved_values);
2096
1438
      if (nr == ~(uint64_t) 0)
2097
1439
        return(HA_ERR_AUTOINC_READ_FAILED);  // Mark failure
2098
 
      
 
1440
 
2099
1441
      /*
2100
1442
        That rounding below should not be needed when all engines actually
2101
1443
        respect offset and increment in get_auto_increment(). But they don't
2106
1448
      */
2107
1449
      nr= compute_next_insert_id(nr-1, variables);
2108
1450
    }
2109
 
    
 
1451
 
2110
1452
    if (table->s->next_number_keypart == 0)
2111
1453
    {
2112
1454
      /* We must defer the appending until "nr" has been possibly truncated */
2119
1461
    /*
2120
1462
      first test if the query was aborted due to strict mode constraints
2121
1463
    */
2122
 
    if (thd->killed == THD::KILL_BAD_DATA)
 
1464
    if (session->killed == Session::KILL_BAD_DATA)
2123
1465
      return(HA_ERR_AUTOINC_ERANGE);
2124
1466
 
2125
1467
    /*
2138
1480
  {
2139
1481
    auto_inc_interval_for_cur_row.replace(nr, nb_reserved_values,
2140
1482
                                          variables->auto_increment_increment);
2141
 
    /* Row-based replication does not need to store intervals in binlog */
2142
 
    if (!thd->current_stmt_binlog_row_based)
2143
 
        thd->auto_inc_intervals_in_cur_stmt_for_binlog.append(auto_inc_interval_for_cur_row.minimum(),
2144
 
                                                              auto_inc_interval_for_cur_row.values(),
2145
 
                                                              variables->auto_increment_increment);
2146
1483
  }
2147
1484
 
2148
1485
  /*
2164
1501
 
2165
1502
 
2166
1503
/**
2167
 
  MySQL signal that it changed the column bitmap
2168
 
 
2169
 
  This is for handlers that needs to setup their own column bitmaps.
2170
 
  Normally the handler should set up their own column bitmaps in
2171
 
  index_init() or rnd_init() and in any column_bitmaps_signal() call after
2172
 
  this.
2173
 
 
2174
 
  The handler is allowed to do changes to the bitmap after a index_init or
2175
 
  rnd_init() call is made as after this, MySQL will not use the bitmap
2176
 
  for any program logic checking.
2177
 
*/
2178
 
void handler::column_bitmaps_signal()
2179
 
{
2180
 
  return;
2181
 
}
2182
 
 
2183
 
 
2184
 
/**
2185
1504
  Reserves an interval of auto_increment values from the handler.
2186
1505
 
2187
1506
  offset and increment means that we want values to be of the form
2196
1515
  @param first_value         (OUT) the first value reserved by the handler
2197
1516
  @param nb_reserved_values  (OUT) how many values the handler reserved
2198
1517
*/
2199
 
void handler::get_auto_increment(uint64_t offset __attribute__((unused)),
2200
 
                                 uint64_t increment __attribute__((unused)),
2201
 
                                 uint64_t nb_desired_values __attribute__((unused)),
 
1518
void handler::get_auto_increment(uint64_t ,
 
1519
                                 uint64_t ,
 
1520
                                 uint64_t ,
2202
1521
                                 uint64_t *first_value,
2203
1522
                                 uint64_t *nb_reserved_values)
2204
1523
{
2206
1525
  int error;
2207
1526
 
2208
1527
  (void) extra(HA_EXTRA_KEYREAD);
2209
 
  table->mark_columns_used_by_index_no_reset(table->s->next_number_index,
2210
 
                                        table->read_set);
2211
 
  column_bitmaps_signal();
 
1528
  table->mark_columns_used_by_index_no_reset(table->s->next_number_index);
2212
1529
  index_init(table->s->next_number_index, 1);
2213
1530
  if (table->s->next_number_keypart == 0)
2214
1531
  {                                             // Autoincrement at key-start
2281
1598
  else
2282
1599
  {
2283
1600
    /* Table is opened and defined at this point */
2284
 
    key_unpack(&str,table,(uint) key_nr);
2285
 
    uint32_t max_length=DRIZZLE_ERRMSG_SIZE-(uint) strlen(msg);
 
1601
    key_unpack(&str,table,(uint32_t) key_nr);
 
1602
    uint32_t max_length=DRIZZLE_ERRMSG_SIZE-(uint32_t) strlen(msg);
2286
1603
    if (str.length() >= max_length)
2287
1604
    {
2288
1605
      str.length(max_length-4);
2345
1662
      char key[MAX_KEY_LENGTH];
2346
1663
      String str(key,sizeof(key),system_charset_info);
2347
1664
      /* Table is opened and defined at this point */
2348
 
      key_unpack(&str,table,(uint) key_nr);
 
1665
      key_unpack(&str,table,(uint32_t) key_nr);
2349
1666
      max_length= (DRIZZLE_ERRMSG_SIZE-
2350
 
                   (uint) strlen(ER(ER_FOREIGN_DUPLICATE_KEY)));
 
1667
                   (uint32_t) strlen(ER(ER_FOREIGN_DUPLICATE_KEY)));
2351
1668
      if (str.length() >= max_length)
2352
1669
      {
2353
1670
        str.length(max_length-4);
2461
1778
    my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
2462
1779
               ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
2463
1780
    return;
2464
 
    break;
2465
1781
  default:
2466
1782
    {
2467
1783
      /* The error was "unknown" to this function.
2471
1787
      temporary= get_error_message(error, &str);
2472
1788
      if (!str.is_empty())
2473
1789
      {
2474
 
        const char* engine= table_type();
2475
 
        if (temporary)
2476
 
          my_error(ER_GET_TEMPORARY_ERRMSG, MYF(0), error, str.ptr(), engine);
2477
 
        else
2478
 
          my_error(ER_GET_ERRMSG, MYF(0), error, str.ptr(), engine);
 
1790
              const char* engine_name= table_type();
 
1791
              if (temporary)
 
1792
                my_error(ER_GET_TEMPORARY_ERRMSG, MYF(0), error, str.ptr(),
 
1793
                   engine_name);
 
1794
              else
 
1795
                my_error(ER_GET_ERRMSG, MYF(0), error, str.ptr(), engine_name);
2479
1796
      }
2480
1797
      else
2481
 
        my_error(ER_GET_ERRNO,errflag,error);
 
1798
      {
 
1799
              my_error(ER_GET_ERRNO,errflag,error);
 
1800
      }
2482
1801
      return;
2483
1802
    }
2484
1803
  }
2496
1815
  @return
2497
1816
    Returns true if this is a temporary error
2498
1817
*/
2499
 
bool handler::get_error_message(int error __attribute__((unused)),
2500
 
                                String* buf __attribute__((unused)))
 
1818
bool handler::get_error_message(int ,
 
1819
                                String* )
2501
1820
{
2502
1821
  return false;
2503
1822
}
2524
1843
        Field *field= table->field[keypart->fieldnr-1];
2525
1844
        if (field->type() == DRIZZLE_TYPE_BLOB)
2526
1845
        {
2527
 
          if (check_opt->sql_flags & TT_FOR_UPGRADE)
2528
 
            check_opt->flags= T_MEDIUM;
2529
1846
          return HA_ADMIN_NEEDS_CHECK;
2530
1847
        }
2531
1848
      }
2541
1858
  return 0;
2542
1859
}
2543
1860
 
2544
 
 
2545
 
static bool update_frm_version(Table *table)
2546
 
{
2547
 
  char path[FN_REFLEN];
2548
 
  File file;
2549
 
  bool result= true;
2550
 
 
2551
 
  /*
2552
 
    No need to update frm version in case table was created or checked
2553
 
    by server with the same version. This also ensures that we do not
2554
 
    update frm version for temporary tables as this code doesn't support
2555
 
    temporary tables.
2556
 
  */
2557
 
  if (table->s->mysql_version == DRIZZLE_VERSION_ID)
2558
 
    return(0);
2559
 
 
2560
 
  strxmov(path, table->s->normalized_path.str, reg_ext, NULL);
2561
 
 
2562
 
  if ((file= my_open(path, O_RDWR|O_BINARY, MYF(MY_WME))) >= 0)
2563
 
  {
2564
 
    unsigned char version[4];
2565
 
    char *key= table->s->table_cache_key.str;
2566
 
    uint32_t key_length= table->s->table_cache_key.length;
2567
 
    Table *entry;
2568
 
    HASH_SEARCH_STATE state;
2569
 
 
2570
 
    int4store(version, DRIZZLE_VERSION_ID);
2571
 
 
2572
 
    if (pwrite(file, (unsigned char*)version, 4, 51L) == 0)
2573
 
    {
2574
 
      result= false;
2575
 
      goto err;
2576
 
    }
2577
 
 
2578
 
    for (entry=(Table*) hash_first(&open_cache,(unsigned char*) key,key_length, &state);
2579
 
         entry;
2580
 
         entry= (Table*) hash_next(&open_cache,(unsigned char*) key,key_length, &state))
2581
 
      entry->s->mysql_version= DRIZZLE_VERSION_ID;
2582
 
  }
2583
 
err:
2584
 
  if (file >= 0)
2585
 
    my_close(file,MYF(MY_WME));
2586
 
  return(result);
2587
 
}
2588
 
 
2589
 
 
2590
 
 
2591
1861
/**
2592
1862
  @return
2593
1863
    key if error because of duplicated keys
2594
1864
*/
2595
1865
uint32_t handler::get_dup_key(int error)
2596
1866
{
2597
 
  table->file->errkey  = (uint) -1;
 
1867
  table->file->errkey  = (uint32_t) -1;
2598
1868
  if (error == HA_ERR_FOUND_DUPP_KEY || error == HA_ERR_FOREIGN_DUPLICATE_KEY ||
2599
1869
      error == HA_ERR_FOUND_DUPP_UNIQUE ||
2600
1870
      error == HA_ERR_DROP_INDEX_FK)
2666
1936
/**
2667
1937
  Performs checks upon the table.
2668
1938
 
2669
 
  @param thd                thread doing CHECK Table operation
 
1939
  @param session                thread doing CHECK Table operation
2670
1940
  @param check_opt          options from the parser
2671
1941
 
2672
1942
  @retval
2678
1948
  @retval
2679
1949
    HA_ADMIN_NOT_IMPLEMENTED
2680
1950
*/
2681
 
int handler::ha_check(THD *thd, HA_CHECK_OPT *check_opt)
 
1951
int handler::ha_check(Session *session, HA_CHECK_OPT *check_opt)
2682
1952
{
2683
1953
  int error;
2684
1954
 
2685
 
  if ((table->s->mysql_version >= DRIZZLE_VERSION_ID) &&
2686
 
      (check_opt->sql_flags & TT_FOR_UPGRADE))
2687
 
    return 0;
2688
 
 
2689
1955
  if (table->s->mysql_version < DRIZZLE_VERSION_ID)
2690
1956
  {
2691
1957
    if ((error= check_old_types()))
2693
1959
    error= ha_check_for_upgrade(check_opt);
2694
1960
    if (error && (error != HA_ADMIN_NEEDS_CHECK))
2695
1961
      return error;
2696
 
    if (!error && (check_opt->sql_flags & TT_FOR_UPGRADE))
2697
 
      return 0;
2698
1962
  }
2699
 
  if ((error= check(thd, check_opt)))
 
1963
  if ((error= check(session, check_opt)))
2700
1964
    return error;
2701
 
  return update_frm_version(table);
 
1965
  return HA_ADMIN_OK;
2702
1966
}
2703
1967
 
2704
1968
/**
2710
1974
void
2711
1975
handler::mark_trx_read_write()
2712
1976
{
2713
 
  Ha_trx_info *ha_info= &ha_thd()->ha_data[ht->slot].ha_info[0];
 
1977
  Ha_trx_info *ha_info= &ha_session()->ha_data[engine->slot].ha_info[0];
2714
1978
  /*
2715
1979
    When a storage engine method is called, the transaction must
2716
1980
    have been started, unless it's a DDL call, for which the
2721
1985
  */
2722
1986
  if (ha_info->is_started())
2723
1987
  {
2724
 
    assert(has_transactions());
2725
1988
    /*
2726
1989
      table_share can be NULL in ha_delete_table(). See implementation
2727
1990
      of standalone function ha_delete_table() in sql_base.cc.
2738
2001
  @sa handler::repair()
2739
2002
*/
2740
2003
 
2741
 
int handler::ha_repair(THD* thd, HA_CHECK_OPT* check_opt)
 
2004
int handler::ha_repair(Session* session, HA_CHECK_OPT* check_opt)
2742
2005
{
2743
2006
  int result;
2744
2007
 
2745
2008
  mark_trx_read_write();
2746
2009
 
2747
 
  if ((result= repair(thd, check_opt)))
 
2010
  if ((result= repair(session, check_opt)))
2748
2011
    return result;
2749
 
  return update_frm_version(table);
 
2012
  return HA_ADMIN_OK;
2750
2013
}
2751
2014
 
2752
2015
 
2803
2066
*/
2804
2067
 
2805
2068
int
2806
 
handler::ha_optimize(THD* thd, HA_CHECK_OPT* check_opt)
 
2069
handler::ha_optimize(Session* session, HA_CHECK_OPT* check_opt)
2807
2070
{
2808
2071
  mark_trx_read_write();
2809
2072
 
2810
 
  return optimize(thd, check_opt);
 
2073
  return optimize(session, check_opt);
2811
2074
}
2812
2075
 
2813
2076
 
2818
2081
*/
2819
2082
 
2820
2083
int
2821
 
handler::ha_analyze(THD* thd, HA_CHECK_OPT* check_opt)
 
2084
handler::ha_analyze(Session* session, HA_CHECK_OPT* check_opt)
2822
2085
{
2823
2086
  mark_trx_read_write();
2824
2087
 
2825
 
  return analyze(thd, check_opt);
 
2088
  return analyze(session, check_opt);
2826
2089
}
2827
2090
 
2828
2091
 
2833
2096
*/
2834
2097
 
2835
2098
bool
2836
 
handler::ha_check_and_repair(THD *thd)
 
2099
handler::ha_check_and_repair(Session *session)
2837
2100
{
2838
2101
  mark_trx_read_write();
2839
2102
 
2840
 
  return check_and_repair(thd);
 
2103
  return check_and_repair(session);
2841
2104
}
2842
2105
 
2843
2106
 
2955
2218
*/
2956
2219
 
2957
2220
int
2958
 
handler::ha_create(const char *name, Table *form, HA_CREATE_INFO *info)
 
2221
handler::ha_create(const char *name, Table *form, HA_CREATE_INFO *create_info)
2959
2222
{
2960
2223
  mark_trx_read_write();
2961
2224
 
2962
 
  return create(name, form, info);
 
2225
  return create(name, form, create_info);
2963
2226
}
2964
2227
 
2965
2228
 
2971
2234
 
2972
2235
int
2973
2236
handler::ha_create_handler_files(const char *name, const char *old_name,
2974
 
                        int action_flag, HA_CREATE_INFO *info)
 
2237
                                 int action_flag, HA_CREATE_INFO *create_info)
2975
2238
{
2976
2239
  mark_trx_read_write();
2977
2240
 
2978
 
  return create_handler_files(name, old_name, action_flag, info);
 
2241
  return create_handler_files(name, old_name, action_flag, create_info);
2979
2242
}
2980
2243
 
2981
2244
 
2987
2250
  starts to commit every now and then automatically.
2988
2251
  This hint can be safely ignored.
2989
2252
*/
2990
 
int ha_enable_transaction(THD *thd, bool on)
 
2253
int ha_enable_transaction(Session *session, bool on)
2991
2254
{
2992
2255
  int error=0;
2993
2256
 
2994
 
  if ((thd->transaction.on= on))
 
2257
  if ((session->transaction.on= on))
2995
2258
  {
2996
2259
    /*
2997
2260
      Now all storage engines should have transaction handling enabled.
2999
2262
      is an optimization hint that storage engine is free to ignore.
3000
2263
      So, let's commit an open transaction (if any) now.
3001
2264
    */
3002
 
    if (!(error= ha_commit_trans(thd, 0)))
3003
 
      error= end_trans(thd, COMMIT);
 
2265
    if (!(error= ha_commit_trans(session, 0)))
 
2266
      if (! session->endTransaction(COMMIT))
 
2267
        error= 1;
 
2268
 
3004
2269
  }
3005
2270
  return(error);
3006
2271
}
3060
2325
** Some general functions that isn't in the handler class
3061
2326
****************************************************************************/
3062
2327
 
3063
 
/**
3064
 
  Initiates table-file and calls appropriate database-creator.
3065
 
 
3066
 
  @retval
3067
 
   0  ok
3068
 
  @retval
3069
 
   1  error
3070
 
*/
3071
 
int ha_create_table(THD *thd, const char *path,
3072
 
                    const char *db, const char *table_name,
3073
 
                    HA_CREATE_INFO *create_info,
3074
 
                    bool update_create_info)
3075
 
{
3076
 
  int error= 1;
3077
 
  Table table;
3078
 
  char name_buff[FN_REFLEN];
3079
 
  const char *name;
3080
 
  TABLE_SHARE share;
3081
 
  
3082
 
  init_tmp_table_share(thd, &share, db, 0, table_name, path);
3083
 
  if (open_table_def(thd, &share, 0) ||
3084
 
      open_table_from_share(thd, &share, "", 0, (uint) READ_ALL, 0, &table,
3085
 
                            OTM_CREATE))
3086
 
    goto err;
3087
 
 
3088
 
  if (update_create_info)
3089
 
    table.updateCreateInfo(create_info);
3090
 
 
3091
 
  name= check_lowercase_names(table.file, share.path.str, name_buff);
3092
 
 
3093
 
  error= table.file->ha_create(name, &table, create_info);
3094
 
  closefrm(&table, 0);
3095
 
  if (error)
3096
 
  {
3097
 
    strxmov(name_buff, db, ".", table_name, NULL);
3098
 
    my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), name_buff, error);
3099
 
  }
3100
 
err:
3101
 
  free_table_share(&share);
3102
 
  return(error != 0);
3103
 
}
3104
 
 
3105
 
/**
3106
 
  Try to discover table from engine.
3107
 
 
3108
 
  @note
3109
 
    If found, write the frm file to disk.
3110
 
 
3111
 
  @retval
3112
 
  -1    Table did not exists
3113
 
  @retval
3114
 
   0    Table created ok
3115
 
  @retval
3116
 
   > 0  Error, table existed but could not be created
3117
 
*/
3118
 
int ha_create_table_from_engine(THD* thd, const char *db, const char *name)
3119
 
{
3120
 
  int error;
3121
 
  unsigned char *frmblob;
3122
 
  size_t frmlen;
3123
 
  char path[FN_REFLEN];
3124
 
  HA_CREATE_INFO create_info;
3125
 
  Table table;
3126
 
  TABLE_SHARE share;
3127
 
 
3128
 
  memset(&create_info, 0, sizeof(create_info));
3129
 
  if ((error= ha_discover(thd, db, name, &frmblob, &frmlen)))
3130
 
  {
3131
 
    /* Table could not be discovered and thus not created */
3132
 
    return(error);
3133
 
  }
3134
 
 
3135
 
  /*
3136
 
    Table exists in handler and could be discovered
3137
 
    frmblob and frmlen are set, write the frm to disk
3138
 
  */
3139
 
 
3140
 
  build_table_filename(path, FN_REFLEN-1, db, name, "", 0);
3141
 
  // Save the frm file
3142
 
  error= writefrm(path, frmblob, frmlen);
3143
 
  free(frmblob);
3144
 
  if (error)
3145
 
    return(2);
3146
 
 
3147
 
  init_tmp_table_share(thd, &share, db, 0, name, path);
3148
 
  if (open_table_def(thd, &share, 0))
3149
 
  {
3150
 
    return(3);
3151
 
  }
3152
 
  if (open_table_from_share(thd, &share, "" ,0, 0, 0, &table, OTM_OPEN))
3153
 
  {
3154
 
    free_table_share(&share);
3155
 
    return(3);
3156
 
  }
3157
 
 
3158
 
  table.updateCreateInfo(&create_info);
3159
 
  create_info.table_options|= HA_OPTION_CREATE_FROM_ENGINE;
3160
 
 
3161
 
  check_lowercase_names(table.file, path, path);
3162
 
  error=table.file->ha_create(path, &table, &create_info);
3163
 
  closefrm(&table, 1);
3164
 
 
3165
 
  return(error != 0);
3166
 
}
3167
2328
 
3168
2329
void st_ha_check_opt::init()
3169
2330
{
3170
 
  flags= sql_flags= 0;
3171
 
  sort_buffer_size = current_thd->variables.myisam_sort_buff_size;
 
2331
  flags= 0; 
 
2332
  use_frm= false;
3172
2333
}
3173
2334
 
3174
2335
 
3185
2346
/**
3186
2347
  Init a key cache if it has not been initied before.
3187
2348
*/
3188
 
int ha_init_key_cache(const char *name __attribute__((unused)),
 
2349
int ha_init_key_cache(const char *,
3189
2350
                      KEY_CACHE *key_cache)
3190
2351
{
3191
2352
  if (!key_cache->key_cache_inited)
3192
2353
  {
3193
2354
    pthread_mutex_lock(&LOCK_global_system_variables);
3194
2355
    uint32_t tmp_buff_size= (uint32_t) key_cache->param_buff_size;
3195
 
    uint32_t tmp_block_size= (uint) key_cache->param_block_size;
 
2356
    uint32_t tmp_block_size= (uint32_t) key_cache->param_block_size;
3196
2357
    uint32_t division_limit= key_cache->param_division_limit;
3197
2358
    uint32_t age_threshold=  key_cache->param_age_threshold;
3198
2359
    pthread_mutex_unlock(&LOCK_global_system_variables);
3263
2424
 
3264
2425
 
3265
2426
/**
3266
 
  Try to discover one table from handler(s).
3267
 
 
3268
 
  @retval
3269
 
    -1   Table did not exists
3270
 
  @retval
3271
 
    0   OK. In this case *frmblob and *frmlen are set
3272
 
  @retval
3273
 
    >0   error.  frmblob and frmlen may not be set
3274
 
*/
3275
 
struct st_discover_args
3276
 
{
3277
 
  const char *db;
3278
 
  const char *name;
3279
 
  unsigned char **frmblob; 
3280
 
  size_t *frmlen;
3281
 
};
3282
 
 
3283
 
static bool discover_handlerton(THD *thd, plugin_ref plugin,
3284
 
                                void *arg)
3285
 
{
3286
 
  st_discover_args *vargs= (st_discover_args *)arg;
3287
 
  handlerton *hton= plugin_data(plugin, handlerton *);
3288
 
  if (hton->state == SHOW_OPTION_YES && hton->discover &&
3289
 
      (!(hton->discover(hton, thd, vargs->db, vargs->name, 
3290
 
                        vargs->frmblob, 
3291
 
                        vargs->frmlen))))
3292
 
    return true;
3293
 
 
3294
 
  return false;
3295
 
}
3296
 
 
3297
 
int ha_discover(THD *thd, const char *db, const char *name,
3298
 
                unsigned char **frmblob, size_t *frmlen)
3299
 
{
3300
 
  int error= -1; // Table does not exist in any handler
3301
 
  st_discover_args args= {db, name, frmblob, frmlen};
3302
 
 
3303
 
  if (is_prefix(name,tmp_file_prefix)) /* skip temporary tables */
3304
 
    return(error);
3305
 
 
3306
 
  if (plugin_foreach(thd, discover_handlerton,
3307
 
                 DRIZZLE_STORAGE_ENGINE_PLUGIN, &args))
3308
 
    error= 0;
3309
 
 
3310
 
  if (!error)
3311
 
    status_var_increment(thd->status_var.ha_discover_count);
3312
 
  return(error);
3313
 
}
3314
 
 
3315
 
 
3316
 
/**
3317
 
  Call this function in order to give the handler the possiblity
3318
 
  to ask engine if there are any new tables that should be written to disk
3319
 
  or any dropped tables that need to be removed from disk
3320
 
*/
3321
 
struct st_find_files_args
3322
 
{
3323
 
  const char *db;
3324
 
  const char *path;
3325
 
  const char *wild;
3326
 
  bool dir;
3327
 
  List<LEX_STRING> *files;
3328
 
};
3329
 
 
3330
 
/**
3331
 
  Ask handler if the table exists in engine.
3332
 
  @retval
3333
 
    HA_ERR_NO_SUCH_TABLE     Table does not exist
3334
 
  @retval
3335
 
    HA_ERR_TABLE_EXIST       Table exists
3336
 
  @retval
3337
 
    \#                  Error code
3338
 
*/
3339
 
struct st_table_exists_in_engine_args
3340
 
{
3341
 
  const char *db;
3342
 
  const char *name;
3343
 
  int err;
3344
 
};
3345
 
 
3346
 
static bool table_exists_in_engine_handlerton(THD *thd, plugin_ref plugin,
3347
 
                                              void *arg)
3348
 
{
3349
 
  st_table_exists_in_engine_args *vargs= (st_table_exists_in_engine_args *)arg;
3350
 
  handlerton *hton= plugin_data(plugin, handlerton *);
3351
 
 
3352
 
  int err= HA_ERR_NO_SUCH_TABLE;
3353
 
 
3354
 
  if (hton->state == SHOW_OPTION_YES && hton->table_exists_in_engine)
3355
 
    err = hton->table_exists_in_engine(hton, thd, vargs->db, vargs->name);
3356
 
 
3357
 
  vargs->err = err;
3358
 
  if (vargs->err == HA_ERR_TABLE_EXIST)
3359
 
    return true;
3360
 
 
3361
 
  return false;
3362
 
}
3363
 
 
3364
 
int ha_table_exists_in_engine(THD* thd, const char* db, const char* name)
3365
 
{
3366
 
  st_table_exists_in_engine_args args= {db, name, HA_ERR_NO_SUCH_TABLE};
3367
 
  plugin_foreach(thd, table_exists_in_engine_handlerton,
3368
 
                 DRIZZLE_STORAGE_ENGINE_PLUGIN, &args);
3369
 
  return(args.err);
3370
 
}
3371
 
 
3372
 
/**
3373
2427
  Calculate cost of 'index only' scan for given index and number of records
3374
2428
 
3375
2429
  @param keynr    Index number
3390
2444
    Estimated cost of 'index only' scan
3391
2445
*/
3392
2446
 
3393
 
double handler::index_only_read_time(uint32_t keynr, double records)
 
2447
double handler::index_only_read_time(uint32_t keynr, double key_records)
3394
2448
{
3395
 
  double read_time;
3396
2449
  uint32_t keys_per_block= (stats.block_size/2/
3397
2450
                        (table->key_info[keynr].key_length + ref_length) + 1);
3398
 
  read_time=((double) (records + keys_per_block-1) /
3399
 
             (double) keys_per_block);
3400
 
  return read_time;
 
2451
  return ((double) (key_records + keys_per_block-1) /
 
2452
          (double) keys_per_block);
3401
2453
}
3402
2454
 
3403
2455
 
3424
2476
 
3425
2477
  @note
3426
2478
    This method (or an overriding one in a derived class) must check for
3427
 
    thd->killed and return HA_POS_ERROR if it is not zero. This is required
 
2479
    session->killed and return HA_POS_ERROR if it is not zero. This is required
3428
2480
    for a user to be able to interrupt the calculation by killing the
3429
2481
    connection/query.
3430
2482
 
3439
2491
ha_rows
3440
2492
handler::multi_range_read_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
3441
2493
                                     void *seq_init_param,
3442
 
                                     uint32_t n_ranges_arg __attribute__((unused)),
 
2494
                                     uint32_t ,
3443
2495
                                     uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
3444
2496
{
3445
2497
  KEY_MULTI_RANGE range;
3446
2498
  range_seq_t seq_it;
3447
2499
  ha_rows rows, total_rows= 0;
3448
2500
  uint32_t n_ranges=0;
3449
 
  THD *thd= current_thd;
3450
 
  
 
2501
  Session *session= current_session;
 
2502
 
3451
2503
  /* Default MRR implementation doesn't need buffer */
3452
2504
  *bufsz= 0;
3453
2505
 
3454
2506
  seq_it= seq->init(seq_init_param, n_ranges, *flags);
3455
2507
  while (!seq->next(seq_it, &range))
3456
2508
  {
3457
 
    if (unlikely(thd->killed != 0))
 
2509
    if (unlikely(session->killed != 0))
3458
2510
      return HA_POS_ERROR;
3459
 
    
 
2511
 
3460
2512
    n_ranges++;
3461
2513
    key_range *min_endp, *max_endp;
3462
2514
    {
3467
2519
      rows= 1; /* there can be at most one row */
3468
2520
    else
3469
2521
    {
3470
 
      if (HA_POS_ERROR == (rows= this->records_in_range(keyno, min_endp, 
 
2522
      if (HA_POS_ERROR == (rows= this->records_in_range(keyno, min_endp,
3471
2523
                                                        max_endp)))
3472
2524
      {
3473
2525
        /* Can't scan one range => can't do MRR scan at all */
3477
2529
    }
3478
2530
    total_rows += rows;
3479
2531
  }
3480
 
  
 
2532
 
3481
2533
  if (total_rows != HA_POS_ERROR)
3482
2534
  {
3483
2535
    /* The following calculation is the same as in multi_range_read_info(): */
3485
2537
    cost->zero();
3486
2538
    cost->avg_io_cost= 1; /* assume random seeks */
3487
2539
    if ((*flags & HA_MRR_INDEX_ONLY) && total_rows > 2)
3488
 
      cost->io_count= index_only_read_time(keyno, (uint)total_rows);
 
2540
      cost->io_count= index_only_read_time(keyno, (uint32_t)total_rows);
3489
2541
    else
3490
2542
      cost->io_count= read_time(keyno, n_ranges, total_rows);
3491
2543
    cost->cpu_cost= (double) total_rows / TIME_FOR_COMPARE + 0.01;
3550
2602
/**
3551
2603
  Initialize the MRR scan
3552
2604
 
3553
 
  Initialize the MRR scan. This function may do heavyweight scan 
 
2605
  Initialize the MRR scan. This function may do heavyweight scan
3554
2606
  initialization like row prefetching/sorting/etc (NOTE: but better not do
3555
2607
  it here as we may not need it, e.g. if we never satisfy WHERE clause on
3556
2608
  previous tables. For many implementations it would be natural to do such
3557
2609
  initializations in the first multi_read_range_next() call)
3558
2610
 
3559
2611
  mode is a combination of the following flags: HA_MRR_SORTED,
3560
 
  HA_MRR_INDEX_ONLY, HA_MRR_NO_ASSOCIATION 
 
2612
  HA_MRR_INDEX_ONLY, HA_MRR_NO_ASSOCIATION
3561
2613
 
3562
2614
  @param seq             Range sequence to be traversed
3563
2615
  @param seq_init_param  First parameter for seq->init()
3569
2621
    One must have called index_init() before calling this function. Several
3570
2622
    multi_range_read_init() calls may be made in course of one query.
3571
2623
 
3572
 
    Until WL#2623 is done (see its text, section 3.2), the following will 
 
2624
    Until WL#2623 is done (see its text, section 3.2), the following will
3573
2625
    also hold:
3574
2626
    The caller will guarantee that if "seq->init == mrr_ranges_array_init"
3575
2627
    then seq_init_param is an array of n_ranges KEY_MULTI_RANGE structures.
3576
2628
    This property will only be used by NDB handler until WL#2623 is done.
3577
 
     
 
2629
 
3578
2630
    Buffer memory management is done according to the following scenario:
3579
2631
    The caller allocates the buffer and provides it to the callee by filling
3580
2632
    the members of HANDLER_BUFFER structure.
3591
2643
int
3592
2644
handler::multi_range_read_init(RANGE_SEQ_IF *seq_funcs, void *seq_init_param,
3593
2645
                               uint32_t n_ranges, uint32_t mode,
3594
 
                               HANDLER_BUFFER *buf __attribute__((unused)))
 
2646
                               HANDLER_BUFFER *)
3595
2647
{
3596
2648
  mrr_iter= seq_funcs->init(seq_init_param, n_ranges, mode);
3597
2649
  mrr_funcs= *seq_funcs;
3669
2721
 
3670
2722
 
3671
2723
/* **************************************************************************
3672
 
 * DS-MRR implementation 
 
2724
 * DS-MRR implementation
3673
2725
 ***************************************************************************/
3674
2726
 
3675
2727
/**
3690
2742
  @retval other Error
3691
2743
*/
3692
2744
 
3693
 
int DsMrr_impl::dsmrr_init(handler *h, KEY *key,
 
2745
int DsMrr_impl::dsmrr_init(handler *h_in, KEY *key,
3694
2746
                           RANGE_SEQ_IF *seq_funcs, void *seq_init_param,
3695
2747
                           uint32_t n_ranges, uint32_t mode, HANDLER_BUFFER *buf)
3696
2748
{
3698
2750
  uint32_t keyno;
3699
2751
  Item *pushed_cond= NULL;
3700
2752
  handler *new_h2;
3701
 
  keyno= h->active_index;
 
2753
  keyno= h_in->active_index;
3702
2754
  assert(h2 == NULL);
3703
2755
  if (mode & HA_MRR_USE_DEFAULT_IMPL || mode & HA_MRR_SORTED)
3704
2756
  {
3705
2757
    use_default_impl= true;
3706
 
    return(h->handler::multi_range_read_init(seq_funcs, seq_init_param,
 
2758
    return(h_in->handler::multi_range_read_init(seq_funcs, seq_init_param,
3707
2759
                                                  n_ranges, mode, buf));
3708
2760
  }
3709
2761
  rowids_buf= buf->buffer;
3710
2762
  //psergey-todo: don't add key_length as it is not needed anymore
3711
 
  rowids_buf += key->key_length + h->ref_length;
 
2763
  rowids_buf += key->key_length + h_in->ref_length;
3712
2764
 
3713
2765
  is_mrr_assoc= !test(mode & HA_MRR_NO_ASSOCIATION);
3714
2766
  rowids_buf_end= buf->buffer_end;
3715
 
  
3716
 
  elem_size= h->ref_length + (int)is_mrr_assoc * sizeof(void*);
3717
 
  rowids_buf_last= rowids_buf + 
 
2767
 
 
2768
  elem_size= h_in->ref_length + (int)is_mrr_assoc * sizeof(void*);
 
2769
  rowids_buf_last= rowids_buf +
3718
2770
                      ((rowids_buf_end - rowids_buf)/ elem_size)*
3719
2771
                      elem_size;
3720
2772
  rowids_buf_end= rowids_buf_last;
3721
2773
 
3722
2774
  /* Create a separate handler object to do rndpos() calls. */
3723
 
  THD *thd= current_thd;
3724
 
  if (!(new_h2= h->clone(thd->mem_root)) || 
3725
 
      new_h2->ha_external_lock(thd, F_RDLCK))
 
2775
  Session *session= current_session;
 
2776
  if (!(new_h2= h_in->clone(session->mem_root)) ||
 
2777
      new_h2->ha_external_lock(session, F_RDLCK))
3726
2778
  {
3727
2779
    delete new_h2;
3728
2780
    return(1);
3729
2781
  }
3730
2782
 
3731
 
  if (keyno == h->pushed_idx_cond_keyno)
3732
 
    pushed_cond= h->pushed_idx_cond;
3733
 
  if (h->ha_index_end())
 
2783
  if (keyno == h_in->pushed_idx_cond_keyno)
 
2784
    pushed_cond= h_in->pushed_idx_cond;
 
2785
  if (h_in->ha_index_end())
3734
2786
  {
3735
2787
    new_h2= h2;
3736
2788
    goto error;
3740
2792
  table->prepare_for_position();
3741
2793
  new_h2->extra(HA_EXTRA_KEYREAD);
3742
2794
 
3743
 
  if (h2->ha_index_init(keyno, false) || 
 
2795
  if (h2->ha_index_init(keyno, false) ||
3744
2796
      h2->handler::multi_range_read_init(seq_funcs, seq_init_param, n_ranges,
3745
2797
                                         mode, buf))
3746
2798
    goto error;
3747
2799
  use_default_impl= false;
3748
 
  
 
2800
 
3749
2801
  if (pushed_cond)
3750
2802
    h2->idx_cond_push(keyno, pushed_cond);
3751
2803
  if (dsmrr_fill_buffer(new_h2))
3755
2807
    If the above call has scanned through all intervals in *seq, then
3756
2808
    adjust *buf to indicate that the remaining buffer space will not be used.
3757
2809
  */
3758
 
  if (dsmrr_eof) 
 
2810
  if (dsmrr_eof)
3759
2811
    buf->end_of_used_area= rowids_buf_last;
3760
2812
 
3761
 
  if (h->ha_rnd_init(false))
 
2813
  if (h_in->ha_rnd_init(false))
3762
2814
    goto error;
3763
 
  
 
2815
 
3764
2816
  return(0);
3765
2817
error:
3766
2818
  h2->ha_index_or_rnd_end();
3767
 
  h2->ha_external_lock(thd, F_UNLCK);
 
2819
  h2->ha_external_lock(session, F_UNLCK);
3768
2820
  h2->close();
3769
2821
  delete h2;
3770
2822
  return(1);
3775
2827
{
3776
2828
  if (h2)
3777
2829
  {
3778
 
    h2->ha_external_lock(current_thd, F_UNLCK);
 
2830
    h2->ha_external_lock(current_session, F_UNLCK);
3779
2831
    h2->close();
3780
2832
    delete h2;
3781
2833
    h2= NULL;
3795
2847
  DS-MRR: Fill the buffer with rowids and sort it by rowid
3796
2848
 
3797
2849
  {This is an internal function of DiskSweep MRR implementation}
3798
 
  Scan the MRR ranges and collect ROWIDs (or {ROWID, range_id} pairs) into 
3799
 
  buffer. When the buffer is full or scan is completed, sort the buffer by 
 
2850
  Scan the MRR ranges and collect ROWIDs (or {ROWID, range_id} pairs) into
 
2851
  buffer. When the buffer is full or scan is completed, sort the buffer by
3800
2852
  rowid and return.
3801
 
  
3802
 
  The function assumes that rowids buffer is empty when it is invoked. 
3803
 
  
 
2853
 
 
2854
  The function assumes that rowids buffer is empty when it is invoked.
 
2855
 
3804
2856
  @param h  Table handler
3805
2857
 
3806
2858
  @retval 0      OK, the next portion of rowids is in the buffer,
3808
2860
  @retval other  Error
3809
2861
*/
3810
2862
 
3811
 
int DsMrr_impl::dsmrr_fill_buffer(handler *unused __attribute__((unused)))
 
2863
int DsMrr_impl::dsmrr_fill_buffer(handler *)
3812
2864
{
3813
2865
  char *range_info;
3814
2866
  int res = 0;
3815
2867
 
3816
2868
  rowids_buf_cur= rowids_buf;
3817
 
  while ((rowids_buf_cur < rowids_buf_end) && 
 
2869
  while ((rowids_buf_cur < rowids_buf_end) &&
3818
2870
         !(res= h2->handler::multi_range_read_next(&range_info)))
3819
2871
  {
3820
2872
    /* Put rowid, or {rowid, range_id} pair into the buffer */
3830
2882
  }
3831
2883
 
3832
2884
  if (res && res != HA_ERR_END_OF_FILE)
3833
 
    return(res); 
 
2885
    return(res);
3834
2886
  dsmrr_eof= test(res == HA_ERR_END_OF_FILE);
3835
2887
 
3836
2888
  /* Sort the buffer contents by rowid */
3837
2889
  uint32_t elem_size= h->ref_length + (int)is_mrr_assoc * sizeof(void*);
3838
2890
  uint32_t n_rowids= (rowids_buf_cur - rowids_buf) / elem_size;
3839
 
  
 
2891
 
3840
2892
  my_qsort2(rowids_buf, n_rowids, elem_size, (qsort2_cmp)rowid_cmp,
3841
2893
            (void*)h);
3842
2894
  rowids_buf_last= rowids_buf_cur;
3849
2901
  DS-MRR implementation: multi_range_read_next() function
3850
2902
*/
3851
2903
 
3852
 
int DsMrr_impl::dsmrr_next(handler *h, char **range_info)
 
2904
int DsMrr_impl::dsmrr_next(handler *h_in, char **range_info)
3853
2905
{
3854
2906
  int res;
3855
 
  
 
2907
 
3856
2908
  if (use_default_impl)
3857
 
    return h->handler::multi_range_read_next(range_info);
3858
 
    
 
2909
    return h_in->handler::multi_range_read_next(range_info);
 
2910
 
3859
2911
  if (rowids_buf_cur == rowids_buf_last)
3860
2912
  {
3861
2913
    if (dsmrr_eof)
3867
2919
    if (res)
3868
2920
      goto end;
3869
2921
  }
3870
 
  
 
2922
 
3871
2923
  /* Return EOF if there are no rowids in the buffer after re-fill attempt */
3872
2924
  if (rowids_buf_cur == rowids_buf_last)
3873
2925
  {
3875
2927
    goto end;
3876
2928
  }
3877
2929
 
3878
 
  res= h->rnd_pos(table->record[0], rowids_buf_cur);
3879
 
  rowids_buf_cur += h->ref_length;
 
2930
  res= h_in->rnd_pos(table->record[0], rowids_buf_cur);
 
2931
  rowids_buf_cur += h_in->ref_length;
3880
2932
  if (is_mrr_assoc)
3881
2933
  {
3882
2934
    memcpy(range_info, rowids_buf_cur, sizeof(void*));
3895
2947
*/
3896
2948
int DsMrr_impl::dsmrr_info(uint32_t keyno, uint32_t n_ranges, uint32_t rows, uint32_t *bufsz,
3897
2949
                           uint32_t *flags, COST_VECT *cost)
3898
 
{  
 
2950
{
3899
2951
  int res;
3900
2952
  uint32_t def_flags= *flags;
3901
2953
  uint32_t def_bufsz= *bufsz;
3905
2957
                                         &def_flags, cost);
3906
2958
  assert(!res);
3907
2959
 
3908
 
  if ((*flags & HA_MRR_USE_DEFAULT_IMPL) || 
 
2960
  if ((*flags & HA_MRR_USE_DEFAULT_IMPL) ||
3909
2961
      choose_mrr_impl(keyno, rows, &def_flags, &def_bufsz, cost))
3910
2962
  {
3911
2963
    /* Default implementation is choosen */
3921
2973
*/
3922
2974
 
3923
2975
ha_rows DsMrr_impl::dsmrr_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
3924
 
                                 void *seq_init_param, uint32_t n_ranges, 
 
2976
                                 void *seq_init_param, uint32_t n_ranges,
3925
2977
                                 uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
3926
2978
{
3927
2979
  ha_rows rows;
3929
2981
  uint32_t def_bufsz= *bufsz;
3930
2982
  /* Get cost/flags/mem_usage of default MRR implementation */
3931
2983
  rows= h->handler::multi_range_read_info_const(keyno, seq, seq_init_param,
3932
 
                                                n_ranges, &def_bufsz, 
 
2984
                                                n_ranges, &def_bufsz,
3933
2985
                                                &def_flags, cost);
3934
2986
  if (rows == HA_POS_ERROR)
3935
2987
  {
3980
3032
  KEY_PART_INFO *kp_end= kp + table->key_info[keyno].key_parts;
3981
3033
  for (; kp != kp_end; kp++)
3982
3034
  {
3983
 
    if (!kp->field->part_of_key.is_set(keyno))
 
3035
    if (!kp->field->part_of_key.test(keyno))
3984
3036
      return true;
3985
3037
  }
3986
3038
  return false;
4015
3067
{
4016
3068
  COST_VECT dsmrr_cost;
4017
3069
  bool res;
4018
 
  THD *thd= current_thd;
4019
 
  if ((thd->variables.optimizer_use_mrr == 2) || 
 
3070
  Session *session= current_session;
 
3071
  if ((session->variables.optimizer_use_mrr == 2) ||
4020
3072
      (*flags & HA_MRR_INDEX_ONLY) || (*flags & HA_MRR_SORTED) ||
4021
 
      (keyno == table->s->primary_key && 
4022
 
       h->primary_key_is_clustered()) || 
 
3073
      (keyno == table->s->primary_key &&
 
3074
       h->primary_key_is_clustered()) ||
4023
3075
       key_uses_partial_cols(keyno))
4024
3076
  {
4025
3077
    /* Use the default implementation */
4026
3078
    *flags |= HA_MRR_USE_DEFAULT_IMPL;
4027
3079
    return true;
4028
3080
  }
4029
 
  
4030
 
  uint32_t add_len= table->key_info[keyno].key_length + h->ref_length; 
 
3081
 
 
3082
  uint32_t add_len= table->key_info[keyno].key_length + h->ref_length;
4031
3083
  *bufsz -= add_len;
4032
3084
  if (get_disk_sweep_mrr_cost(keyno, rows, *flags, bufsz, &dsmrr_cost))
4033
3085
    return true;
4034
3086
  *bufsz += add_len;
4035
 
  
 
3087
 
4036
3088
  bool force_dsmrr;
4037
 
  /* 
 
3089
  /*
4038
3090
    If @@optimizer_use_mrr==force, then set cost of DS-MRR to be minimum of
4039
3091
    DS-MRR and Default implementations cost. This allows one to force use of
4040
3092
    DS-MRR whenever it is applicable without affecting other cost-based
4041
3093
    choices.
4042
3094
  */
4043
 
  if ((force_dsmrr= (thd->variables.optimizer_use_mrr == 1)) &&
 
3095
  if ((force_dsmrr= (session->variables.optimizer_use_mrr == 1)) &&
4044
3096
      dsmrr_cost.total_cost() > cost->total_cost())
4045
3097
    dsmrr_cost= *cost;
4046
3098
 
4092
3144
    return true; /* Buffer has not enough space for even 1 rowid */
4093
3145
 
4094
3146
  /* Number of iterations we'll make with full buffer */
4095
 
  n_full_steps= (uint)floor(rows2double(rows) / max_buff_entries);
4096
 
  
4097
 
  /* 
4098
 
    Get numbers of rows we'll be processing in 
4099
 
     - non-last sweep, with full buffer 
 
3147
  n_full_steps= (uint32_t)floor(rows2double(rows) / max_buff_entries);
 
3148
 
 
3149
  /*
 
3150
    Get numbers of rows we'll be processing in
 
3151
     - non-last sweep, with full buffer
4100
3152
     - last iteration, with non-full buffer
4101
3153
  */
4102
3154
  rows_in_full_step= max_buff_entries;
4103
3155
  rows_in_last_step= rows % max_buff_entries;
4104
 
  
 
3156
 
4105
3157
  /* Adjust buffer size if we expect to use only part of the buffer */
4106
3158
  if (n_full_steps)
4107
3159
  {
4111
3163
  else
4112
3164
  {
4113
3165
    cost->zero();
4114
 
    *buffer_size= cmax((ulong)*buffer_size, 
4115
 
                      (size_t)(1.2*rows_in_last_step) * elem_size + 
 
3166
    *buffer_size= cmax((ulong)*buffer_size,
 
3167
                      (size_t)(1.2*rows_in_last_step) * elem_size +
4116
3168
                      h->ref_length + table->key_info[keynr].key_length);
4117
3169
  }
4118
 
  
 
3170
 
4119
3171
  COST_VECT last_step_cost;
4120
3172
  get_sort_and_sweep_cost(table, rows_in_last_step, &last_step_cost);
4121
3173
  cost->add(&last_step_cost);
4122
 
 
 
3174
 
4123
3175
  if (n_full_steps != 0)
4124
3176
    cost->mem_cost= *buffer_size;
4125
3177
  else
4126
3178
    cost->mem_cost= (double)rows_in_last_step * elem_size;
4127
 
  
 
3179
 
4128
3180
  /* Total cost of all index accesses */
4129
3181
  index_read_cost= h->index_only_read_time(keynr, (double)rows);
4130
3182
  cost->add_io(index_read_cost, 1 /* Random seeks */);
4132
3184
}
4133
3185
 
4134
3186
 
4135
 
/* 
 
3187
/*
4136
3188
  Get cost of one sort-and-sweep step
4137
3189
 
4138
3190
  SYNOPSIS
4147
3199
     - read #nrows records from table in a sweep.
4148
3200
*/
4149
3201
 
4150
 
static 
 
3202
static
4151
3203
void get_sort_and_sweep_cost(Table *table, ha_rows nrows, COST_VECT *cost)
4152
3204
{
4153
3205
  if (nrows)
4181
3233
  Time to move the disk head is proportional to head travel distance.
4182
3234
 
4183
3235
  Time to wait for the plate to rotate depends on whether the disk head
4184
 
  was moved or not. 
 
3236
  was moved or not.
4185
3237
 
4186
3238
  If disk head wasn't moved, the wait time is proportional to distance
4187
3239
  between the previous block and the block we're reading.
4192
3244
 
4193
3245
  Our cost units are "random disk seeks". The cost of random disk seek is
4194
3246
  actually not a constant, it depends one range of cylinders we're going
4195
 
  to access. We make it constant by introducing a fuzzy concept of "typical 
 
3247
  to access. We make it constant by introducing a fuzzy concept of "typical
4196
3248
  datafile length" (it's fuzzy as it's hard to tell whether it should
4197
3249
  include index file, temp.tables etc). Then random seek cost is:
4198
3250
 
4207
3259
  @param cost         OUT  The cost.
4208
3260
*/
4209
3261
 
4210
 
void get_sweep_read_cost(Table *table, ha_rows nrows, bool interrupted, 
 
3262
void get_sweep_read_cost(Table *table, ha_rows nrows, bool interrupted,
4211
3263
                         COST_VECT *cost)
4212
3264
{
4213
3265
  cost->zero();
4214
3266
  if (table->file->primary_key_is_clustered())
4215
3267
  {
4216
3268
    cost->io_count= table->file->read_time(table->s->primary_key,
4217
 
                                           (uint) nrows, nrows);
 
3269
                                           (uint32_t) nrows, nrows);
4218
3270
  }
4219
3271
  else
4220
3272
  {
4263
3315
int handler::read_range_first(const key_range *start_key,
4264
3316
                              const key_range *end_key,
4265
3317
                              bool eq_range_arg,
4266
 
                              bool sorted  __attribute__((unused)))
 
3318
                              bool )
4267
3319
{
4268
3320
  int result;
4269
3321
 
4286
3338
                           start_key->keypart_map,
4287
3339
                           start_key->flag);
4288
3340
  if (result)
4289
 
    return((result == HA_ERR_KEY_NOT_FOUND) 
 
3341
    return((result == HA_ERR_KEY_NOT_FOUND)
4290
3342
                ? HA_ERR_END_OF_FILE
4291
3343
                : result);
4292
3344
 
4368
3420
  return cmp;
4369
3421
}
4370
3422
 
4371
 
int handler::index_read_idx_map(unsigned char * buf, uint32_t index, const unsigned char * key,
 
3423
int handler::index_read_idx_map(unsigned char * buf, uint32_t index,
 
3424
                                const unsigned char * key,
4372
3425
                                key_part_map keypart_map,
4373
3426
                                enum ha_rkey_function find_flag)
4374
3427
{
4383
3436
}
4384
3437
 
4385
3438
 
4386
 
/**
4387
 
  Returns a list of all known extensions.
4388
 
 
4389
 
    No mutexes, worst case race is a minor surplus memory allocation
4390
 
    We have to recreate the extension map if mysqld is restarted (for example
4391
 
    within libmysqld)
4392
 
 
4393
 
  @retval
4394
 
    pointer             pointer to TYPELIB structure
4395
 
*/
4396
 
static bool exts_handlerton(THD *unused __attribute__((unused)),
4397
 
                            plugin_ref plugin,
4398
 
                            void *arg)
4399
 
{
4400
 
  List<char> *found_exts= (List<char> *) arg;
4401
 
  handlerton *hton= plugin_data(plugin, handlerton *);
4402
 
  handler *file;
4403
 
  if (hton->state == SHOW_OPTION_YES && hton->create &&
4404
 
      (file= hton->create(hton, (TABLE_SHARE*) 0, current_thd->mem_root)))
4405
 
  {
4406
 
    List_iterator_fast<char> it(*found_exts);
4407
 
    const char **ext, *old_ext;
4408
 
 
4409
 
    for (ext= file->bas_ext(); *ext; ext++)
4410
 
    {
4411
 
      while ((old_ext= it++))
4412
 
      {
4413
 
        if (!strcmp(old_ext, *ext))
4414
 
          break;
4415
 
      }
4416
 
      if (!old_ext)
4417
 
        found_exts->push_back((char *) *ext);
4418
 
 
4419
 
      it.rewind();
4420
 
    }
4421
 
    delete file;
4422
 
  }
4423
 
  return false;
4424
 
}
4425
 
 
4426
 
TYPELIB *ha_known_exts(void)
4427
 
{
4428
 
  if (!known_extensions.type_names || mysys_usage_id != known_extensions_id)
4429
 
  {
4430
 
    List<char> found_exts;
4431
 
    const char **ext, *old_ext;
4432
 
 
4433
 
    known_extensions_id= mysys_usage_id;
4434
 
 
4435
 
    plugin_foreach(NULL, exts_handlerton,
4436
 
                   DRIZZLE_STORAGE_ENGINE_PLUGIN, &found_exts);
4437
 
 
4438
 
    ext= (const char **) my_once_alloc(sizeof(char *)*
4439
 
                                       (found_exts.elements+1),
4440
 
                                       MYF(MY_WME | MY_FAE));
4441
 
 
4442
 
    assert(ext != 0);
4443
 
    known_extensions.count= found_exts.elements;
4444
 
    known_extensions.type_names= ext;
4445
 
 
4446
 
    List_iterator_fast<char> it(found_exts);
4447
 
    while ((old_ext= it++))
4448
 
      *ext++= old_ext;
4449
 
    *ext= 0;
4450
 
  }
4451
 
  return &known_extensions;
4452
 
}
4453
 
 
4454
 
 
4455
 
static bool stat_print(THD *thd, const char *type, uint32_t type_len,
 
3439
static bool stat_print(Session *session, const char *type, uint32_t type_len,
4456
3440
                       const char *file, uint32_t file_len,
4457
3441
                       const char *status, uint32_t status_len)
4458
3442
{
4459
 
  Protocol *protocol= thd->protocol;
4460
 
  protocol->prepare_for_resend();
 
3443
  Protocol *protocol= session->protocol;
 
3444
  protocol->prepareForResend();
4461
3445
  protocol->store(type, type_len, system_charset_info);
4462
3446
  protocol->store(file, file_len, system_charset_info);
4463
3447
  protocol->store(status, status_len, system_charset_info);
4466
3450
  return false;
4467
3451
}
4468
3452
 
4469
 
bool ha_show_status(THD *thd, handlerton *db_type, enum ha_stat_type stat)
 
3453
bool ha_show_status(Session *session, StorageEngine *engine, enum ha_stat_type stat)
4470
3454
{
4471
3455
  List<Item> field_list;
4472
 
  Protocol *protocol= thd->protocol;
 
3456
  Protocol *protocol= session->protocol;
4473
3457
  bool result;
4474
3458
 
4475
3459
  field_list.push_back(new Item_empty_string("Type",10));
4476
3460
  field_list.push_back(new Item_empty_string("Name",FN_REFLEN));
4477
3461
  field_list.push_back(new Item_empty_string("Status",10));
4478
3462
 
4479
 
  if (protocol->send_fields(&field_list,
4480
 
                            Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
 
3463
  if (protocol->sendFields(&field_list,
 
3464
                           Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
4481
3465
    return true;
4482
3466
 
4483
 
  result= db_type->show_status &&
4484
 
    db_type->show_status(db_type, thd, stat_print, stat) ? 1 : 0;
 
3467
  result= engine->show_status(session, stat_print, stat) ? 1 : 0;
4485
3468
 
4486
3469
  if (!result)
4487
 
    my_eof(thd);
 
3470
    session->my_eof();
4488
3471
  return result;
4489
3472
}
4490
3473
 
4501
3484
  - table is not mysql.event
4502
3485
*/
4503
3486
 
4504
 
static bool check_table_binlog_row_based(THD *thd, Table *table)
4505
 
{
4506
 
  if (table->s->cached_row_logging_check == -1)
4507
 
  {
4508
 
    int const check(table->s->tmp_table == NO_TMP_TABLE &&
4509
 
                    binlog_filter->db_ok(table->s->db.str));
4510
 
    table->s->cached_row_logging_check= check;
4511
 
  }
4512
 
 
4513
 
  assert(table->s->cached_row_logging_check == 0 ||
4514
 
              table->s->cached_row_logging_check == 1);
4515
 
 
4516
 
  return (thd->current_stmt_binlog_row_based &&
4517
 
          table->s->cached_row_logging_check &&
4518
 
          (thd->options & OPTION_BIN_LOG) &&
4519
 
          mysql_bin_log.is_open());
4520
 
}
4521
 
 
4522
 
 
4523
 
/**
4524
 
   Write table maps for all (manually or automatically) locked tables
4525
 
   to the binary log.
4526
 
 
4527
 
   This function will generate and write table maps for all tables
4528
 
   that are locked by the thread 'thd'.  Either manually locked
4529
 
   (stored in THD::locked_tables) and automatically locked (stored
4530
 
   in THD::lock) are considered.
4531
 
 
4532
 
   @param thd     Pointer to THD structure
4533
 
 
4534
 
   @retval 0   All OK
4535
 
   @retval 1   Failed to write all table maps
4536
 
 
4537
 
   @sa
4538
 
       THD::lock
4539
 
       THD::locked_tables
4540
 
*/
4541
 
 
4542
 
static int write_locked_table_maps(THD *thd)
4543
 
{
4544
 
  if (thd->get_binlog_table_maps() == 0)
4545
 
  {
4546
 
    DRIZZLE_LOCK *locks[3];
4547
 
    locks[0]= thd->extra_lock;
4548
 
    locks[1]= thd->lock;
4549
 
    locks[2]= thd->locked_tables;
4550
 
    for (uint32_t i= 0 ; i < sizeof(locks)/sizeof(*locks) ; ++i )
4551
 
    {
4552
 
      DRIZZLE_LOCK const *const lock= locks[i];
4553
 
      if (lock == NULL)
4554
 
        continue;
4555
 
 
4556
 
      Table **const end_ptr= lock->table + lock->table_count;
4557
 
      for (Table **table_ptr= lock->table ; 
4558
 
           table_ptr != end_ptr ;
4559
 
           ++table_ptr)
4560
 
      {
4561
 
        Table *const table= *table_ptr;
4562
 
        if (table->current_lock == F_WRLCK &&
4563
 
            check_table_binlog_row_based(thd, table))
4564
 
        {
4565
 
          int const has_trans= table->file->has_transactions();
4566
 
          int const error= thd->binlog_write_table_map(table, has_trans);
4567
 
          /*
4568
 
            If an error occurs, it is the responsibility of the caller to
4569
 
            roll back the transaction.
4570
 
          */
4571
 
          if (unlikely(error))
4572
 
            return(1);
4573
 
        }
4574
 
      }
4575
 
    }
4576
 
  }
4577
 
  return(0);
4578
 
}
4579
 
 
4580
 
 
4581
 
typedef bool Log_func(THD*, Table*, bool, const unsigned char*, const unsigned char*);
4582
 
 
4583
 
static int binlog_log_row(Table* table,
4584
 
                          const unsigned char *before_record,
4585
 
                          const unsigned char *after_record,
4586
 
                          Log_func *log_func)
4587
 
{
4588
 
  if (table->no_replicate)
4589
 
    return 0;
4590
 
  bool error= 0;
4591
 
  THD *const thd= table->in_use;
4592
 
 
4593
 
  if (check_table_binlog_row_based(thd, table))
4594
 
  {
 
3487
static bool binlog_log_row(Table* table,
 
3488
                           const unsigned char *before_record,
 
3489
                           const unsigned char *after_record)
 
3490
{
 
3491
  Session *const session= table->in_use;
 
3492
 
 
3493
  switch (session->lex->sql_command)
 
3494
  {
 
3495
  case SQLCOM_REPLACE:
 
3496
  case SQLCOM_INSERT:
 
3497
  case SQLCOM_REPLACE_SELECT:
 
3498
  case SQLCOM_INSERT_SELECT:
 
3499
  case SQLCOM_CREATE_TABLE:
 
3500
    transaction_services.insertRecord(session, table);
 
3501
    break;
 
3502
 
 
3503
  case SQLCOM_UPDATE:
 
3504
  case SQLCOM_UPDATE_MULTI:
 
3505
    transaction_services.updateRecord(session, table, before_record, after_record);
 
3506
    break;
 
3507
 
 
3508
  case SQLCOM_DELETE:
 
3509
  case SQLCOM_DELETE_MULTI:
 
3510
    transaction_services.deleteRecord(session, table);
 
3511
    break;
 
3512
 
4595
3513
    /*
4596
 
      If there are no table maps written to the binary log, this is
4597
 
      the first row handled in this statement. In that case, we need
4598
 
      to write table maps for all locked tables to the binary log.
 
3514
      For everything else we ignore the event (since it just involves a temp table)
4599
3515
    */
4600
 
    if (likely(!(error= write_locked_table_maps(thd))))
4601
 
    {
4602
 
      bool const has_trans= table->file->has_transactions();
4603
 
      error= (*log_func)(thd, table, has_trans, before_record, after_record);
4604
 
    }
 
3516
  default:
 
3517
    break;
4605
3518
  }
4606
 
  return error ? HA_ERR_RBR_LOGGING_FAILED : 0;
 
3519
 
 
3520
  return false; //error;
4607
3521
}
4608
3522
 
4609
 
int handler::ha_external_lock(THD *thd, int lock_type)
 
3523
int handler::ha_external_lock(Session *session, int lock_type)
4610
3524
{
4611
3525
  /*
4612
3526
    Whether this is lock or unlock, this should be true, and is to verify that
4621
3535
  */
4622
3536
  DRIZZLE_EXTERNAL_LOCK(lock_type);
4623
3537
 
4624
 
  int error= external_lock(thd, lock_type);
 
3538
  int error= external_lock(session, lock_type);
4625
3539
  if (error == 0)
4626
3540
    cached_table_flags= table_flags();
4627
3541
  return(error);
4652
3566
int handler::ha_write_row(unsigned char *buf)
4653
3567
{
4654
3568
  int error;
4655
 
  Log_func *log_func= Write_rows_log_event::binlog_row_logging_function;
4656
3569
  DRIZZLE_INSERT_ROW_START();
4657
3570
 
 
3571
  /* 
 
3572
   * If we have a timestamp column, update it to the current time 
 
3573
   * 
 
3574
   * @TODO Technically, the below two lines can be take even further out of the
 
3575
   * handler interface and into the fill_record() method.
 
3576
   */
 
3577
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
 
3578
    table->timestamp_field->set_time();
 
3579
 
4658
3580
  mark_trx_read_write();
4659
3581
 
4660
3582
  if (unlikely(error= write_row(buf)))
4661
3583
    return(error);
4662
 
  if (unlikely(error= binlog_log_row(table, 0, buf, log_func)))
4663
 
    return(error); /* purecov: inspected */
 
3584
 
 
3585
  if (unlikely(binlog_log_row(table, 0, buf)))
 
3586
    return HA_ERR_RBR_LOGGING_FAILED; /* purecov: inspected */
 
3587
 
4664
3588
  DRIZZLE_INSERT_ROW_END();
4665
3589
  return(0);
4666
3590
}
4669
3593
int handler::ha_update_row(const unsigned char *old_data, unsigned char *new_data)
4670
3594
{
4671
3595
  int error;
4672
 
  Log_func *log_func= Update_rows_log_event::binlog_row_logging_function;
4673
3596
 
4674
3597
  /*
4675
3598
    Some storage engines require that the new record is in record[0]
4681
3604
 
4682
3605
  if (unlikely(error= update_row(old_data, new_data)))
4683
3606
    return error;
4684
 
  if (unlikely(error= binlog_log_row(table, old_data, new_data, log_func)))
4685
 
    return error;
 
3607
 
 
3608
  if (unlikely(binlog_log_row(table, old_data, new_data)))
 
3609
    return HA_ERR_RBR_LOGGING_FAILED;
 
3610
 
4686
3611
  return 0;
4687
3612
}
4688
3613
 
4689
3614
int handler::ha_delete_row(const unsigned char *buf)
4690
3615
{
4691
3616
  int error;
4692
 
  Log_func *log_func= Delete_rows_log_event::binlog_row_logging_function;
4693
3617
 
4694
3618
  mark_trx_read_write();
4695
3619
 
4696
3620
  if (unlikely(error= delete_row(buf)))
4697
3621
    return error;
4698
 
  if (unlikely(error= binlog_log_row(table, buf, 0, log_func)))
4699
 
    return error;
 
3622
 
 
3623
  if (unlikely(binlog_log_row(table, buf, 0)))
 
3624
    return HA_ERR_RBR_LOGGING_FAILED;
 
3625
 
4700
3626
  return 0;
4701
3627
}
4702
3628
 
4703
 
 
4704
 
 
4705
 
/**
4706
 
  @details
4707
 
  use_hidden_primary_key() is called in case of an update/delete when
4708
 
  (table_flags() and HA_PRIMARY_KEY_REQUIRED_FOR_DELETE) is defined
4709
 
  but we don't have a primary key
4710
 
*/
4711
 
void handler::use_hidden_primary_key()
4712
 
{
4713
 
  /* fallback to use all columns in the table to identify row */
4714
 
  table->use_all_columns();
 
3629
void table_case_convert(char * name, uint32_t length)
 
3630
{
 
3631
  if (lower_case_table_names)
 
3632
    files_charset_info->cset->casedn(files_charset_info,
 
3633
                                     name, length, name, length);
 
3634
}
 
3635
 
 
3636
const char *table_case_name(HA_CREATE_INFO *info, const char *name)
 
3637
{
 
3638
  return ((lower_case_table_names == 2 && info->alias) ? info->alias : name);
4715
3639
}