~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/handler.cc

MergedĀ inĀ trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2000-2006 MySQL AB
2
 
 
3
 
   This program is free software; you can redistribute it and/or modify
4
 
   it under the terms of the GNU General Public License as published by
5
 
   the Free Software Foundation; version 2 of the License.
6
 
 
7
 
   This program is distributed in the hope that it will be useful,
8
 
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
 
   GNU General Public License for more details.
11
 
 
12
 
   You should have received a copy of the GNU General Public License
13
 
   along with this program; if not, write to the Free Software
14
 
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
 
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
 
3
 *
 
4
 *  Copyright (C) 2008 Sun Microsystems
 
5
 *
 
6
 *  This program is free software; you can redistribute it and/or modify
 
7
 *  it under the terms of the GNU General Public License as published by
 
8
 *  the Free Software Foundation; version 2 of the License.
 
9
 *
 
10
 *  This program is distributed in the hope that it will be useful,
 
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 *  GNU General Public License for more details.
 
14
 *
 
15
 *  You should have received a copy of the GNU General Public License
 
16
 *  along with this program; if not, write to the Free Software
 
17
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
18
 */
15
19
 
16
20
/**
17
21
  @file handler.cc
19
23
  Handler-calling-functions
20
24
*/
21
25
 
22
 
#ifdef USE_PRAGMA_IMPLEMENTATION
23
 
#pragma implementation                          // gcc: Class implementation
24
 
#endif
25
 
 
26
 
#include <drizzled/server_includes.h>
27
 
#include "rpl_filter.h"
28
 
#include <drizzled/drizzled_error_messages.h>
29
 
 
30
 
/*
31
 
  While we have legacy_db_type, we have this array to
32
 
  check for dups and to find handlerton from legacy_db_type.
33
 
  Remove when legacy_db_type is finally gone
34
 
*/
35
 
st_plugin_int *hton2plugin[MAX_HA];
36
 
 
37
 
static handlerton *installed_htons[128];
38
 
 
39
 
#define BITMAP_STACKBUF_SIZE (128/8)
40
 
 
41
 
KEY_CREATE_INFO default_key_create_info= { HA_KEY_ALG_UNDEF, 0, {NULL,0}, {NULL,0} };
42
 
 
43
 
/* number of entries in handlertons[] */
 
26
#include "drizzled/server_includes.h"
 
27
#include "mysys/hash.h"
 
28
#include "drizzled/error.h"
 
29
#include "drizzled/gettext.h"
 
30
#include "drizzled/probes.h"
 
31
#include "drizzled/sql_parse.h"
 
32
#include "drizzled/cost_vect.h"
 
33
#include "drizzled/session.h"
 
34
#include "drizzled/sql_base.h"
 
35
#include "drizzled/replication_services.h"
 
36
#include "drizzled/lock.h"
 
37
#include "drizzled/item/int.h"
 
38
#include "drizzled/item/empty_string.h"
 
39
#include "drizzled/unireg.h" // for mysql_frm_type
 
40
#include "drizzled/field/timestamp.h"
 
41
#include "drizzled/message/table.pb.h"
 
42
#include "drizzled/plugin/client.h"
 
43
 
 
44
using namespace std;
 
45
using namespace drizzled;
 
46
 
 
47
KEY_CREATE_INFO default_key_create_info= { HA_KEY_ALG_UNDEF, 0, {NULL,0} };
 
48
 
 
49
/* number of entries in storage_engines[] */
44
50
uint32_t total_ha= 0;
45
 
/* number of storage engines (from handlertons[]) that support 2pc */
 
51
/* number of storage engines (from storage_engines[]) that support 2pc */
46
52
uint32_t total_ha_2pc= 0;
47
53
/* size of savepoint storage area (see ha_init) */
48
54
uint32_t savepoint_alloc_size= 0;
49
55
 
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
56
const char *ha_row_type[] = {
58
57
  "", "FIXED", "DYNAMIC", "COMPRESSED", "REDUNDANT", "COMPACT", "PAGE", "?","?","?"
59
58
};
61
60
const char *tx_isolation_names[] =
62
61
{ "READ-UNCOMMITTED", "READ-COMMITTED", "REPEATABLE-READ", "SERIALIZABLE",
63
62
  NULL};
 
63
 
64
64
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
 
}
 
65
                               tx_isolation_names, NULL};
221
66
 
222
67
 
223
68
/**
236
81
 
237
82
  /* Allocate a pointer array for the error message strings. */
238
83
  /* Zerofill it to avoid uninitialized gaps. */
239
 
  if (! (errmsgs= (const char**) my_malloc(HA_ERR_ERRORS * sizeof(char*),
240
 
                                           MYF(MY_WME | MY_ZEROFILL))))
 
84
  if (! (errmsgs= (const char**) malloc(HA_ERR_ERRORS * sizeof(char*))))
241
85
    return 1;
 
86
  memset(errmsgs, 0, HA_ERR_ERRORS * sizeof(char *));
242
87
 
243
88
  /* Set the dedicated error messages. */
244
89
  SETMSG(HA_ERR_KEY_NOT_FOUND,          ER(ER_KEY_NOT_FOUND));
307
152
  return 0;
308
153
}
309
154
 
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
155
int ha_init()
424
156
{
425
157
  int error= 0;
430
162
    binary log (which is considered a transaction-capable storage engine in
431
163
    counting total_ha)
432
164
  */
433
 
  opt_using_transactions= total_ha>(uint32_t)opt_bin_log;
434
165
  savepoint_alloc_size+= sizeof(SAVEPOINT);
435
 
  return(error);
 
166
  return error;
436
167
}
437
168
 
438
169
int ha_end()
439
170
{
440
171
  int error= 0;
441
172
 
442
 
  /* 
 
173
  /*
443
174
    This should be eventualy based  on the graceful shutdown flag.
444
175
    So if flag is equal to HA_PANIC_CLOSE, the deallocate
445
176
    the errors.
447
178
  if (ha_finish_errors())
448
179
    error= 1;
449
180
 
450
 
  return(error);
451
 
}
452
 
 
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
 
}
 
181
  return error;
 
182
}
 
183
 
 
184
 
493
185
 
494
186
/* ========================================================================
495
187
 ======================= TRANSACTIONS ===================================*/
593
285
  -----------
594
286
 
595
287
  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
 
288
  session->transaction. This structure has two members of type
 
289
  Session_TRANS. These members correspond to the statement and
598
290
  normal transactions respectively:
599
291
 
600
 
  - thd->transaction.stmt contains a list of engines
 
292
  - session->transaction.stmt contains a list of engines
601
293
  that are participating in the given statement
602
 
  - thd->transaction.all contains a list of engines that
 
294
  - session->transaction.all contains a list of engines that
603
295
  have participated in any of the statement transactions started
604
296
  within the context of the normal transaction.
605
297
  Each element of the list contains a pointer to the storage
606
298
  engine, engine-specific transactional data, and engine-specific
607
299
  transaction flags.
608
300
 
609
 
  In autocommit mode thd->transaction.all is empty.
610
 
  Instead, data of thd->transaction.stmt is
 
301
  In autocommit mode session->transaction.all is empty.
 
302
  Instead, data of session->transaction.stmt is
611
303
  used to commit/rollback the normal transaction.
612
304
 
613
305
  The list of registered engines has a few important properties:
618
310
  Transaction life cycle
619
311
  ----------------------
620
312
 
621
 
  When a new connection is established, thd->transaction
 
313
  When a new connection is established, session->transaction
622
314
  members are initialized to an empty state.
623
315
  If a statement uses any tables, all affected engines
624
316
  are registered in the statement engine list. In
634
326
  and emptied again at the next statement's end.
635
327
 
636
328
  The normal transaction is committed in a similar way
637
 
  (by going over all engines in thd->transaction.all list)
 
329
  (by going over all engines in session->transaction.all list)
638
330
  but at different times:
639
331
  - upon COMMIT SQL statement is issued by the user
640
332
  - implicitly, by the server, at the beginning of a DDL statement
644
336
  - if the user has requested so, by issuing ROLLBACK SQL
645
337
  statement
646
338
  - if one of the storage engines requested a rollback
647
 
  by setting thd->transaction_rollback_request. This may
 
339
  by setting session->transaction_rollback_request. This may
648
340
  happen in case, e.g., when the transaction in the engine was
649
341
  chosen a victim of the internal deadlock resolution algorithm
650
342
  and rolled back internally. When such a situation happens, there
664
356
  The remaining rare cases when the server explicitly has
665
357
  to commit the statement transaction prior to committing the normal
666
358
  one cover error-handling scenarios (see for example
667
 
  SQLCOM_LOCK_TABLES).
 
359
  ?).
668
360
 
669
361
  When committing a statement or a normal transaction, the server
670
362
  either uses the two-phase commit protocol, or issues a commit
671
363
  in each engine independently. The two-phase commit protocol
672
364
  is used only if:
673
365
  - all participating engines support two-phase commit (provide
674
 
    handlerton::prepare PSEA API call) and
 
366
    plugin::StorageEngine::prepare PSEA API call) and
675
367
  - transactions in at least two engines modify data (i.e. are
676
368
  not read-only).
677
369
 
686
378
  transactions of other participants.
687
379
 
688
380
  After the normal transaction has been committed,
689
 
  thd->transaction.all list is cleared.
 
381
  session->transaction.all list is cleared.
690
382
 
691
383
  When a connection is closed, the current normal transaction, if
692
384
  any, is rolled back.
735
427
 
736
428
  At the end of a statement, server call
737
429
  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().
 
430
  invokes plugin::StorageEngine::prepare() for every involved engine.
 
431
  Prepare is followed by a call to plugin::StorageEngine::commit_one_phase()
 
432
  If a one-phase commit will suffice, plugin::StorageEngine::prepare() is not
 
433
  invoked and the server only calls plugin::StorageEngine::commit_one_phase().
742
434
  At statement commit, the statement-related read-write engine
743
435
  flag is propagated to the corresponding flag in the normal
744
436
  transaction.  When the commit is complete, the list of registered
750
442
  ---------------------------------------------------
751
443
 
752
444
  DDLs and operations with non-transactional engines
753
 
  do not "register" in thd->transaction lists, and thus do not
 
445
  do not "register" in session->transaction lists, and thus do not
754
446
  modify the transaction state. Besides, each DDL in
755
447
  MySQL is prefixed with an implicit normal transaction commit
756
 
  (a call to end_active_trans()), and thus leaves nothing
 
448
  (a call to Session::endActiveTransaction()), and thus leaves nothing
757
449
  to modify.
758
450
  However, as it has been pointed out with CREATE TABLE .. SELECT,
759
451
  some DDL statements can start a *new* transaction.
797
489
    times per transaction.
798
490
 
799
491
*/
800
 
void trans_register_ha(THD *thd, bool all, handlerton *ht_arg)
 
492
void trans_register_ha(Session *session, bool all, plugin::StorageEngine *engine)
801
493
{
802
 
  THD_TRANS *trans;
 
494
  Session_TRANS *trans;
803
495
  Ha_trx_info *ha_info;
804
496
 
805
497
  if (all)
806
498
  {
807
 
    trans= &thd->transaction.all;
808
 
    thd->server_status|= SERVER_STATUS_IN_TRANS;
 
499
    trans= &session->transaction.all;
 
500
    session->server_status|= SERVER_STATUS_IN_TRANS;
809
501
  }
810
502
  else
811
 
    trans= &thd->transaction.stmt;
 
503
    trans= &session->transaction.stmt;
812
504
 
813
 
  ha_info= thd->ha_data[ht_arg->slot].ha_info + static_cast<unsigned>(all);
 
505
  ha_info= session->ha_data[engine->getSlot()].ha_info + static_cast<unsigned>(all);
814
506
 
815
507
  if (ha_info->is_started())
816
508
    return; /* already registered, return */
817
509
 
818
 
  ha_info->register_ha(trans, ht_arg);
819
 
 
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);
823
 
 
824
 
  return;
825
 
}
826
 
 
827
 
/**
828
 
  @retval
829
 
    0   ok
830
 
  @retval
831
 
    1   error, transaction was rolled back
832
 
*/
833
 
int ha_prepare(THD *thd)
834
 
{
835
 
  int error=0, all=1;
836
 
  THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt;
837
 
  Ha_trx_info *ha_info= trans->ha_list;
838
 
  if (ha_info)
839
 
  {
840
 
    for (; ha_info; ha_info= ha_info->next())
841
 
    {
842
 
      int err;
843
 
      handlerton *ht= ha_info->ht();
844
 
      status_var_increment(thd->status_var.ha_prepare_count);
845
 
      if (ht->prepare)
846
 
      {
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
 
        }
854
 
      }
855
 
      else
856
 
      {
857
 
        push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
858
 
                            ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
859
 
                            ha_resolve_storage_engine_name(ht));
860
 
      }
861
 
    }
862
 
  }
863
 
  return(error);
 
510
  ha_info->register_ha(trans, engine);
 
511
 
 
512
  trans->no_2pc|= not engine->has_2pc();
 
513
  if (session->transaction.xid_state.xid.is_null())
 
514
    session->transaction.xid_state.xid.set(session->query_id);
864
515
}
865
516
 
866
517
/**
879
530
 
880
531
static
881
532
bool
882
 
ha_check_and_coalesce_trx_read_only(THD *thd, Ha_trx_info *ha_list,
 
533
ha_check_and_coalesce_trx_read_only(Session *session, Ha_trx_info *ha_list,
883
534
                                    bool all)
884
535
{
885
536
  /* The number of storage engines that have actual changes. */
893
544
 
894
545
    if (! all)
895
546
    {
896
 
      Ha_trx_info *ha_info_all= &thd->ha_data[ha_info->ht()->slot].ha_info[1];
 
547
      Ha_trx_info *ha_info_all= &session->ha_data[ha_info->engine()->getSlot()].ha_info[1];
897
548
      assert(ha_info != ha_info_all);
898
549
      /*
899
550
        Merge read-only/read-write information about statement
900
551
        transaction to its enclosing normal transaction. Do this
901
552
        only if in a real transaction -- that is, if we know
902
 
        that ha_info_all is registered in thd->transaction.all.
 
553
        that ha_info_all is registered in session->transaction.all.
903
554
        Since otherwise we only clutter the normal transaction flags.
904
555
      */
905
556
      if (ha_info_all->is_started()) /* false if autocommit. */
933
584
    stored functions or triggers. So we simply do nothing now.
934
585
    TODO: This should be fixed in later ( >= 5.1) releases.
935
586
*/
936
 
int ha_commit_trans(THD *thd, bool all)
 
587
int ha_commit_trans(Session *session, bool all)
937
588
{
938
589
  int error= 0, cookie= 0;
939
590
  /*
940
591
    'all' means that this is either an explicit commit issued by
941
592
    user, or an implicit commit issued by a DDL.
942
593
  */
943
 
  THD_TRANS *trans= all ? &thd->transaction.all : &thd->transaction.stmt;
944
 
  bool is_real_trans= all || thd->transaction.all.ha_list == 0;
 
594
  Session_TRANS *trans= all ? &session->transaction.all : &session->transaction.stmt;
 
595
  bool is_real_trans= all || session->transaction.all.ha_list == 0;
945
596
  Ha_trx_info *ha_info= trans->ha_list;
946
 
  my_xid xid= thd->transaction.xid_state.xid.get_my_xid();
947
597
 
948
598
  /*
949
599
    We must not commit the normal transaction if a statement
951
601
    flags will not get propagated to its normal transaction's
952
602
    counterpart.
953
603
  */
954
 
  assert(thd->transaction.stmt.ha_list == NULL ||
955
 
              trans == &thd->transaction.stmt);
 
604
  assert(session->transaction.stmt.ha_list == NULL ||
 
605
              trans == &session->transaction.stmt);
956
606
 
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
607
  if (ha_info)
978
608
  {
979
609
    bool must_2pc;
980
610
 
981
 
    if (is_real_trans && wait_if_global_read_lock(thd, 0, 0))
982
 
    {
983
 
      ha_rollback_trans(thd, all);
984
 
      return(1);
985
 
    }
986
 
 
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);
 
611
    if (is_real_trans && wait_if_global_read_lock(session, 0, 0))
 
612
    {
 
613
      ha_rollback_trans(session, all);
 
614
      return 1;
 
615
    }
 
616
 
 
617
    must_2pc= ha_check_and_coalesce_trx_read_only(session, ha_info, all);
999
618
 
1000
619
    if (!trans->no_2pc && must_2pc)
1001
620
    {
1002
621
      for (; ha_info && !error; ha_info= ha_info->next())
1003
622
      {
1004
623
        int err;
1005
 
        handlerton *ht= ha_info->ht();
 
624
        plugin::StorageEngine *engine= ha_info->engine();
1006
625
        /*
1007
626
          Do not call two-phase commit if this particular
1008
627
          transaction is read-only. This allows for simpler
1014
633
          Sic: we know that prepare() is not NULL since otherwise
1015
634
          trans->no_2pc would have been set.
1016
635
        */
1017
 
        if ((err= ht->prepare(ht, thd, all)))
 
636
        if ((err= engine->prepare(session, all)))
1018
637
        {
1019
638
          my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
1020
639
          error= 1;
1021
640
        }
1022
 
        status_var_increment(thd->status_var.ha_prepare_count);
 
641
        status_var_increment(session->status_var.ha_prepare_count);
1023
642
      }
1024
 
      if (error || (is_real_trans && xid &&
1025
 
                    (error= !(cookie= tc_log->log_xid(thd, xid)))))
 
643
      if (error)
1026
644
      {
1027
 
        ha_rollback_trans(thd, all);
 
645
        ha_rollback_trans(session, all);
1028
646
        error= 1;
1029
647
        goto end;
1030
648
      }
1031
649
    }
1032
 
    error=ha_commit_one_phase(thd, all) ? (cookie ? 2 : 1) : 0;
1033
 
    if (cookie)
1034
 
      tc_log->unlog(cookie, xid);
 
650
    error=ha_commit_one_phase(session, all) ? (cookie ? 2 : 1) : 0;
1035
651
end:
1036
652
    if (is_real_trans)
1037
 
      start_waiting_global_read_lock(thd);
 
653
      start_waiting_global_read_lock(session);
1038
654
  }
1039
 
  return(error);
 
655
  return error;
1040
656
}
1041
657
 
1042
658
/**
1043
659
  @note
1044
660
  This function does not care about global read lock. A caller should.
1045
661
*/
1046
 
int ha_commit_one_phase(THD *thd, bool all)
 
662
int ha_commit_one_phase(Session *session, bool all)
1047
663
{
1048
664
  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;
 
665
  Session_TRANS *trans=all ? &session->transaction.all : &session->transaction.stmt;
 
666
  bool is_real_trans=all || session->transaction.all.ha_list == 0;
1051
667
  Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
1052
668
  if (ha_info)
1053
669
  {
1054
670
    for (; ha_info; ha_info= ha_info_next)
1055
671
    {
1056
672
      int err;
1057
 
      handlerton *ht= ha_info->ht();
1058
 
      if ((err= ht->commit(ht, thd, all)))
 
673
      plugin::StorageEngine *engine= ha_info->engine();
 
674
      if ((err= engine->commit(session, all)))
1059
675
      {
1060
676
        my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
1061
677
        error=1;
1062
678
      }
1063
 
      status_var_increment(thd->status_var.ha_commit_count);
 
679
      status_var_increment(session->status_var.ha_commit_count);
1064
680
      ha_info_next= ha_info->next();
1065
681
      ha_info->reset(); /* keep it conveniently zero-filled */
1066
682
    }
1067
683
    trans->ha_list= 0;
1068
684
    trans->no_2pc=0;
1069
685
    if (is_real_trans)
1070
 
      thd->transaction.xid_state.xid.null();
 
686
      session->transaction.xid_state.xid.null();
1071
687
    if (all)
1072
688
    {
1073
 
      thd->variables.tx_isolation=thd->session_tx_isolation;
1074
 
      thd->transaction.cleanup();
 
689
      session->variables.tx_isolation=session->session_tx_isolation;
 
690
      session->transaction.cleanup();
1075
691
    }
1076
692
  }
1077
 
  return(error);
 
693
  return error;
1078
694
}
1079
695
 
1080
696
 
1081
 
int ha_rollback_trans(THD *thd, bool all)
 
697
int ha_rollback_trans(Session *session, bool all)
1082
698
{
1083
699
  int error=0;
1084
 
  THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt;
 
700
  Session_TRANS *trans=all ? &session->transaction.all : &session->transaction.stmt;
1085
701
  Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
1086
 
  bool is_real_trans=all || thd->transaction.all.ha_list == 0;
 
702
  bool is_real_trans=all || session->transaction.all.ha_list == 0;
1087
703
 
1088
704
  /*
1089
705
    We must not rollback the normal transaction if a statement
1090
706
    transaction is pending.
1091
707
  */
1092
 
  assert(thd->transaction.stmt.ha_list == NULL ||
1093
 
              trans == &thd->transaction.stmt);
 
708
  assert(session->transaction.stmt.ha_list == NULL ||
 
709
              trans == &session->transaction.stmt);
1094
710
 
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
711
  if (ha_info)
1109
712
  {
1110
713
    for (; ha_info; ha_info= ha_info_next)
1111
714
    {
1112
715
      int err;
1113
 
      handlerton *ht= ha_info->ht();
1114
 
      if ((err= ht->rollback(ht, thd, all)))
 
716
      plugin::StorageEngine *engine= ha_info->engine();
 
717
      if ((err= engine->rollback(session, all)))
1115
718
      { // cannot happen
1116
719
        my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
1117
720
        error=1;
1118
721
      }
1119
 
      status_var_increment(thd->status_var.ha_rollback_count);
 
722
      status_var_increment(session->status_var.ha_rollback_count);
1120
723
      ha_info_next= ha_info->next();
1121
724
      ha_info->reset(); /* keep it conveniently zero-filled */
1122
725
    }
1123
726
    trans->ha_list= 0;
1124
727
    trans->no_2pc=0;
1125
728
    if (is_real_trans)
1126
 
      thd->transaction.xid_state.xid.null();
 
729
      session->transaction.xid_state.xid.null();
1127
730
    if (all)
1128
731
    {
1129
 
      thd->variables.tx_isolation=thd->session_tx_isolation;
1130
 
      thd->transaction.cleanup();
 
732
      session->variables.tx_isolation=session->session_tx_isolation;
 
733
      session->transaction.cleanup();
1131
734
    }
1132
735
  }
1133
736
  if (all)
1134
 
    thd->transaction_rollback_request= false;
 
737
    session->transaction_rollback_request= false;
1135
738
 
1136
739
  /*
1137
740
    If a non-transactional table was updated, warn; don't warn if this is a
1142
745
    the error log; but we don't want users to wonder why they have this
1143
746
    message in the error log, so we don't send it.
1144
747
  */
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,
 
748
  if (is_real_trans && session->transaction.all.modified_non_trans_table && session->killed != Session::KILL_CONNECTION)
 
749
    push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1148
750
                 ER_WARNING_NOT_COMPLETE_ROLLBACK,
1149
751
                 ER(ER_WARNING_NOT_COMPLETE_ROLLBACK));
1150
 
  return(error);
 
752
  return error;
1151
753
}
1152
754
 
1153
755
/**
1161
763
    the user has used LOCK TABLES then that mechanism does not know to do the
1162
764
    commit.
1163
765
*/
1164
 
int ha_autocommit_or_rollback(THD *thd, int error)
 
766
int ha_autocommit_or_rollback(Session *session, int error)
1165
767
{
1166
 
  if (thd->transaction.stmt.ha_list)
 
768
  if (session->transaction.stmt.ha_list)
1167
769
  {
1168
770
    if (!error)
1169
771
    {
1170
 
      if (ha_commit_trans(thd, 0))
1171
 
        error=1;
1172
 
    }
1173
 
    else 
1174
 
    {
1175
 
      (void) ha_rollback_trans(thd, 0);
1176
 
      if (thd->transaction_rollback_request && !thd->in_sub_stmt)
1177
 
        (void) ha_rollback(thd);
1178
 
    }
1179
 
 
1180
 
    thd->variables.tx_isolation=thd->session_tx_isolation;
1181
 
  }
1182
 
  return(error);
1183
 
}
1184
 
 
1185
 
 
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);
 
772
      if (ha_commit_trans(session, 0))
 
773
        error= 1;
 
774
    }
 
775
    else
 
776
    {
 
777
      (void) ha_rollback_trans(session, 0);
 
778
      if (session->transaction_rollback_request)
 
779
        (void) ha_rollback(session);
 
780
    }
 
781
 
 
782
    session->variables.tx_isolation=session->session_tx_isolation;
 
783
  }
 
784
 
 
785
  return error;
1366
786
}
1367
787
 
1368
788
/**
1373
793
    so mysql_xa_recover does not filter XID's to ensure uniqueness.
1374
794
    It can be easily fixed later, if necessary.
1375
795
*/
1376
 
bool mysql_xa_recover(THD *thd)
 
796
bool mysql_xa_recover(Session *session)
1377
797
{
1378
798
  List<Item> field_list;
1379
 
  Protocol *protocol= thd->protocol;
1380
 
  int i=0;
 
799
  int i= 0;
1381
800
  XID_STATE *xs;
1382
801
 
1383
802
  field_list.push_back(new Item_int("formatID", 0, MY_INT32_NUM_DECIMAL_DIGITS));
1385
804
  field_list.push_back(new Item_int("bqual_length", 0, MY_INT32_NUM_DECIMAL_DIGITS));
1386
805
  field_list.push_back(new Item_empty_string("data",XIDDATASIZE));
1387
806
 
1388
 
  if (protocol->send_fields(&field_list,
1389
 
                            Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
1390
 
    return(1);
 
807
  if (session->client->sendFields(&field_list))
 
808
    return 1;
1391
809
 
1392
810
  pthread_mutex_lock(&LOCK_xid_cache);
1393
811
  while ((xs= (XID_STATE*)hash_element(&xid_cache, i++)))
1394
812
  {
1395
813
    if (xs->xa_state==XA_PREPARED)
1396
814
    {
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);
1401
 
      protocol->store(xs->xid.data, xs->xid.gtrid_length+xs->xid.bqual_length,
1402
 
                      &my_charset_bin);
1403
 
      if (protocol->write())
 
815
      session->client->store((int64_t)xs->xid.formatID);
 
816
      session->client->store((int64_t)xs->xid.gtrid_length);
 
817
      session->client->store((int64_t)xs->xid.bqual_length);
 
818
      session->client->store(xs->xid.data,
 
819
                             xs->xid.gtrid_length+xs->xid.bqual_length);
 
820
      if (session->client->flush())
1404
821
      {
1405
822
        pthread_mutex_unlock(&LOCK_xid_cache);
1406
 
        return(1);
 
823
        return 1;
1407
824
      }
1408
825
    }
1409
826
  }
1410
827
 
1411
828
  pthread_mutex_unlock(&LOCK_xid_cache);
1412
 
  my_eof(thd);
1413
 
  return(0);
1414
 
}
1415
 
 
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
 
 
 
829
  session->my_eof();
1451
830
  return 0;
1452
831
}
1453
832
 
1454
 
int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv)
 
833
 
 
834
int ha_rollback_to_savepoint(Session *session, SAVEPOINT *sv)
1455
835
{
1456
 
  int error=0;
1457
 
  THD_TRANS *trans= (thd->in_sub_stmt ? &thd->transaction.stmt :
1458
 
                                        &thd->transaction.all);
 
836
  int error= 0;
 
837
  Session_TRANS *trans= &session->transaction.all;
1459
838
  Ha_trx_info *ha_info, *ha_info_next;
1460
839
 
1461
840
  trans->no_2pc=0;
1466
845
  for (ha_info= sv->ha_list; ha_info; ha_info= ha_info->next())
1467
846
  {
1468
847
    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)))
 
848
    plugin::StorageEngine *engine= ha_info->engine();
 
849
    assert(engine);
 
850
    if ((err= engine->savepoint_rollback(session,
 
851
                                         (void *)(sv+1))))
1474
852
    { // cannot happen
1475
853
      my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
1476
 
      error=1;
 
854
      error= 1;
1477
855
    }
1478
 
    status_var_increment(thd->status_var.ha_savepoint_rollback_count);
1479
 
    trans->no_2pc|= ht->prepare == 0;
 
856
    status_var_increment(session->status_var.ha_savepoint_rollback_count);
 
857
    trans->no_2pc|= not engine->has_2pc();
1480
858
  }
1481
859
  /*
1482
860
    rolling back the transaction in all storage engines that were not part of
1486
864
       ha_info= ha_info_next)
1487
865
  {
1488
866
    int err;
1489
 
    handlerton *ht= ha_info->ht();
1490
 
    if ((err= ht->rollback(ht, thd, !thd->in_sub_stmt)))
 
867
    plugin::StorageEngine *engine= ha_info->engine();
 
868
    if ((err= engine->rollback(session, !(0))))
1491
869
    { // cannot happen
1492
870
      my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
1493
 
      error=1;
 
871
      error= 1;
1494
872
    }
1495
 
    status_var_increment(thd->status_var.ha_rollback_count);
 
873
    status_var_increment(session->status_var.ha_rollback_count);
1496
874
    ha_info_next= ha_info->next();
1497
875
    ha_info->reset(); /* keep it conveniently zero-filled */
1498
876
  }
1499
877
  trans->ha_list= sv->ha_list;
1500
 
  return(error);
 
878
  return error;
1501
879
}
1502
880
 
1503
881
/**
1506
884
  section "4.33.4 SQL-statements and transaction states",
1507
885
  SAVEPOINT is *not* transaction-initiating SQL-statement
1508
886
*/
1509
 
int ha_savepoint(THD *thd, SAVEPOINT *sv)
 
887
int ha_savepoint(Session *session, SAVEPOINT *sv)
1510
888
{
1511
 
  int error=0;
1512
 
  THD_TRANS *trans= (thd->in_sub_stmt ? &thd->transaction.stmt :
1513
 
                                        &thd->transaction.all);
 
889
  int error= 0;
 
890
  Session_TRANS *trans= &session->transaction.all;
1514
891
  Ha_trx_info *ha_info= trans->ha_list;
1515
892
  for (; ha_info; ha_info= ha_info->next())
1516
893
  {
1517
894
    int err;
1518
 
    handlerton *ht= ha_info->ht();
1519
 
    assert(ht);
1520
 
    if (! ht->savepoint_set)
 
895
    plugin::StorageEngine *engine= ha_info->engine();
 
896
    assert(engine);
 
897
#ifdef NOT_IMPLEMENTED /*- TODO (examine this againt the original code base) */
 
898
    if (! engine->savepoint_set)
1521
899
    {
1522
900
      my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "SAVEPOINT");
1523
 
      error=1;
 
901
      error= 1;
1524
902
      break;
1525
 
    }
1526
 
    if ((err= ht->savepoint_set(ht, thd, (unsigned char *)(sv+1)+ht->savepoint_offset)))
 
903
    } 
 
904
#endif
 
905
    if ((err= engine->savepoint_set(session, (void *)(sv+1))))
1527
906
    { // cannot happen
1528
907
      my_error(ER_GET_ERRNO, MYF(0), err);
1529
 
      error=1;
 
908
      error= 1;
1530
909
    }
1531
 
    status_var_increment(thd->status_var.ha_savepoint_count);
 
910
    status_var_increment(session->status_var.ha_savepoint_count);
1532
911
  }
1533
912
  /*
1534
913
    Remember the list of registered storage engines. All new
1535
914
    engines are prepended to the beginning of the list.
1536
915
  */
1537
916
  sv->ha_list= trans->ha_list;
1538
 
  return(error);
 
917
  return error;
1539
918
}
1540
919
 
1541
 
int ha_release_savepoint(THD *thd, SAVEPOINT *sv)
 
920
int ha_release_savepoint(Session *session, SAVEPOINT *sv)
1542
921
{
1543
 
  int error=0;
 
922
  int error= 0;
1544
923
  Ha_trx_info *ha_info= sv->ha_list;
1545
924
 
1546
925
  for (; ha_info; ha_info= ha_info->next())
1547
926
  {
1548
927
    int err;
1549
 
    handlerton *ht= ha_info->ht();
 
928
    plugin::StorageEngine *engine= ha_info->engine();
1550
929
    /* 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)))
 
930
    assert(engine);
 
931
    if ((err= engine->savepoint_release(session,
 
932
                                        (void *)(sv+1))))
1556
933
    { // cannot happen
1557
934
      my_error(ER_GET_ERRNO, MYF(0), err);
1558
 
      error=1;
 
935
      error= 1;
1559
936
    }
1560
937
  }
1561
 
  return(error);
1562
 
}
1563
 
 
1564
 
 
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
 
}
 
938
  return error;
 
939
}
 
940
 
 
941
 
 
942
 
 
943
 
1732
944
 
1733
945
/****************************************************************************
1734
946
** General handler functions
1735
947
****************************************************************************/
 
948
handler::~handler(void)
 
949
{
 
950
  assert(locked == false);
 
951
  /* TODO: assert(inited == NONE); */
 
952
}
 
953
 
 
954
 
1736
955
handler *handler::clone(MEM_ROOT *mem_root)
1737
956
{
1738
957
  handler *new_handler= get_new_handler(table->s, mem_root, table->s->db_type());
1739
958
  /*
1740
959
    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 
 
960
    on this->table->mem_root and we will not be able to reclaim that memory
1742
961
    when the clone handler object is destroyed.
1743
962
  */
1744
963
  if (!(new_handler->ref= (unsigned char*) alloc_root(mem_root, ALIGN_SIZE(ref_length)*2)))
1751
970
  return NULL;
1752
971
}
1753
972
 
1754
 
 
 
973
int handler::ha_index_init(uint32_t idx, bool sorted)
 
974
{
 
975
  int result;
 
976
  assert(inited == NONE);
 
977
  if (!(result= index_init(idx, sorted)))
 
978
    inited=INDEX;
 
979
  end_range= NULL;
 
980
  return result;
 
981
}
 
982
 
 
983
int handler::ha_index_end()
 
984
{
 
985
  assert(inited==INDEX);
 
986
  inited=NONE;
 
987
  end_range= NULL;
 
988
  return(index_end());
 
989
}
 
990
 
 
991
int handler::ha_rnd_init(bool scan)
 
992
{
 
993
  int result;
 
994
  assert(inited==NONE || (inited==RND && scan));
 
995
  inited= (result= rnd_init(scan)) ? NONE: RND;
 
996
 
 
997
  return result;
 
998
}
 
999
 
 
1000
int handler::ha_rnd_end()
 
1001
{
 
1002
  assert(inited==RND);
 
1003
  inited=NONE;
 
1004
  return(rnd_end());
 
1005
}
 
1006
 
 
1007
int handler::ha_index_or_rnd_end()
 
1008
{
 
1009
  return inited == INDEX ? ha_index_end() : inited == RND ? ha_rnd_end() : 0;
 
1010
}
 
1011
 
 
1012
handler::Table_flags handler::ha_table_flags() const
 
1013
{
 
1014
  return cached_table_flags;
 
1015
}
 
1016
 
 
1017
void handler::ha_start_bulk_insert(ha_rows rows)
 
1018
{
 
1019
  estimation_rows_to_insert= rows;
 
1020
  start_bulk_insert(rows);
 
1021
}
 
1022
 
 
1023
int handler::ha_end_bulk_insert()
 
1024
{
 
1025
  estimation_rows_to_insert= 0;
 
1026
  return end_bulk_insert();
 
1027
}
 
1028
 
 
1029
void handler::change_table_ptr(Table *table_arg, TableShare *share)
 
1030
{
 
1031
  table= table_arg;
 
1032
  table_share= share;
 
1033
}
 
1034
 
 
1035
const key_map *handler::keys_to_use_for_scanning()
 
1036
{
 
1037
  return &key_map_empty;
 
1038
}
 
1039
 
 
1040
bool handler::has_transactions()
 
1041
{
 
1042
  return (ha_table_flags() & HA_NO_TRANSACTIONS) == 0;
 
1043
}
1755
1044
 
1756
1045
void handler::ha_statistic_increment(ulong SSV::*offset) const
1757
1046
{
1758
1047
  status_var_increment(table->in_use->status_var.*offset);
1759
1048
}
1760
1049
 
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
 
}
 
1050
void **handler::ha_data(Session *session) const
 
1051
{
 
1052
  return session_ha_data(session, engine);
 
1053
}
 
1054
 
 
1055
Session *handler::ha_session(void) const
 
1056
{
 
1057
  assert(!table || !table->in_use || table->in_use == current_session);
 
1058
  return (table && table->in_use) ? table->in_use : current_session;
 
1059
}
 
1060
 
 
1061
 
 
1062
bool handler::is_fatal_error(int error, uint32_t flags)
 
1063
{
 
1064
  if (!error ||
 
1065
      ((flags & HA_CHECK_DUP_KEY) &&
 
1066
       (error == HA_ERR_FOUND_DUPP_KEY ||
 
1067
        error == HA_ERR_FOUND_DUPP_UNIQUE)))
 
1068
    return false;
 
1069
  return true;
 
1070
}
 
1071
 
 
1072
 
 
1073
ha_rows handler::records() { return stats.records; }
1771
1074
 
1772
1075
/**
1773
1076
  Open database-handler.
1804
1107
    (void) extra(HA_EXTRA_NO_READCHECK);        // Not needed in SQL
1805
1108
 
1806
1109
    /* ref is already allocated for us if we're called from handler::clone() */
1807
 
    if (!ref && !(ref= (unsigned char*) alloc_root(&table->mem_root, 
 
1110
    if (!ref && !(ref= (unsigned char*) alloc_root(&table->mem_root,
1808
1111
                                          ALIGN_SIZE(ref_length)*2)))
1809
1112
    {
1810
1113
      close();
1814
1117
      dup_ref=ref+ALIGN_SIZE(ref_length);
1815
1118
    cached_table_flags= table_flags();
1816
1119
  }
1817
 
  return(error);
 
1120
  return error;
1818
1121
}
1819
1122
 
1820
1123
/**
1830
1133
 
1831
1134
  position(record);
1832
1135
  if (inited && (error= ha_index_end()))
1833
 
    return(error);
 
1136
    return error;
1834
1137
  if ((error= ha_rnd_init(false)))
1835
 
    return(error);
 
1138
    return error;
1836
1139
 
1837
 
  return(rnd_pos(record, ref));
 
1140
  return rnd_pos(record, ref);
1838
1141
}
1839
1142
 
1840
1143
/**
1868
1171
    error=index_first(buf);
1869
1172
    (void) ha_index_end();
1870
1173
  }
1871
 
  return(error);
 
1174
  return error;
1872
1175
}
1873
1176
 
1874
1177
/**
1898
1201
void handler::adjust_next_insert_id_after_explicit_value(uint64_t nr)
1899
1202
{
1900
1203
  /*
1901
 
    If we have set THD::next_insert_id previously and plan to insert an
 
1204
    If we have set Session::next_insert_id previously and plan to insert an
1902
1205
    explicitely-specified value larger than this, we need to increase
1903
 
    THD::next_insert_id to be greater than the explicit value.
 
1206
    Session::next_insert_id to be greater than the explicit value.
1904
1207
  */
1905
1208
  if ((next_insert_id > 0) && (nr >= next_insert_id))
1906
1209
    set_next_insert_id(compute_next_insert_id(nr, &table->in_use->variables));
1948
1251
 
1949
1252
  Updates columns with type NEXT_NUMBER if:
1950
1253
 
1951
 
  - If column value is set to NULL (in which case
1952
 
    auto_increment_field_not_null is 0)
 
1254
  - If column value is set to NULL (in which case auto_increment_field_not_null is false)
1953
1255
  - If column is set to 0 and (sql_mode & MODE_NO_AUTO_VALUE_ON_ZERO) is not
1954
1256
    set. In the future we will only set NEXT_NUMBER fields if one sets them
1955
1257
    to NULL (or they are not included in the insert list).
1976
1278
    again to reserve a new interval.
1977
1279
 
1978
1280
  - In both cases, the reserved intervals are remembered in
1979
 
    thd->auto_inc_intervals_in_cur_stmt_for_binlog if statement-based
 
1281
    session->auto_inc_intervals_in_cur_stmt_for_binlog if statement-based
1980
1282
    binlogging; the last reserved interval is remembered in
1981
1283
    auto_inc_interval_for_cur_row.
1982
1284
 
1990
1292
    start counting from the inserted value.
1991
1293
 
1992
1294
    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
 
1295
    with a value, session->next_insert_id is filled with the value to use for the
1994
1296
    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
 
1297
    session->insert_id_for_cur_row, if get_auto_increment() was called
 
1298
    session->auto_inc_interval_for_cur_row is modified, if that interval is not
 
1299
    present in session->auto_inc_intervals_in_cur_stmt_for_binlog it is added to
1998
1300
    this list.
1999
1301
 
2000
1302
  @todo
2021
1323
{
2022
1324
  uint64_t nr, nb_reserved_values;
2023
1325
  bool append= false;
2024
 
  THD *thd= table->in_use;
2025
 
  struct system_variables *variables= &thd->variables;
 
1326
  Session *session= table->in_use;
 
1327
  struct system_variables *variables= &session->variables;
2026
1328
 
2027
1329
  /*
2028
1330
    next_insert_id is a "cursor" into the reserved interval, it may go greater
2030
1332
  */
2031
1333
  assert(next_insert_id >= auto_inc_interval_for_cur_row.minimum());
2032
1334
 
2033
 
  if ((nr= table->next_number_field->val_int()) != 0)
 
1335
  /* We check if auto_increment_field_not_null is false
 
1336
     for an auto increment column, not a magic value like NULL is.
 
1337
     same as sql_mode=NO_AUTO_VALUE_ON_ZERO */
 
1338
 
 
1339
  if ((nr= table->next_number_field->val_int()) != 0
 
1340
      || table->auto_increment_field_not_null)
2034
1341
  {
2035
1342
    /*
2036
1343
      Update next_insert_id if we had already generated a value in this
2040
1347
    */
2041
1348
    adjust_next_insert_id_after_explicit_value(nr);
2042
1349
    insert_id_for_cur_row= 0; // didn't generate anything
2043
 
    return(0);
 
1350
 
 
1351
    return 0;
2044
1352
  }
2045
1353
 
2046
1354
  if ((nr= next_insert_id) >= auto_inc_interval_for_cur_row.maximum())
2047
1355
  {
2048
1356
    /* next_insert_id is beyond what is reserved, so we reserve more. */
2049
1357
    const Discrete_interval *forced=
2050
 
      thd->auto_inc_intervals_forced.get_next();
 
1358
      session->auto_inc_intervals_forced.get_next();
2051
1359
    if (forced != NULL)
2052
1360
    {
2053
1361
      nr= forced->minimum();
2060
1368
        handler::ha_start_bulk_insert(); if 0 it means "unknown".
2061
1369
      */
2062
1370
      uint32_t nb_already_reserved_intervals=
2063
 
        thd->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements();
 
1371
        session->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements();
2064
1372
      uint64_t nb_desired_values;
2065
1373
      /*
2066
1374
        If an estimation was given to the engine:
2081
1389
        /* avoid overflow in formula, with this if() */
2082
1390
        if (nb_already_reserved_intervals <= AUTO_INC_DEFAULT_NB_MAX_BITS)
2083
1391
        {
2084
 
          nb_desired_values= AUTO_INC_DEFAULT_NB_ROWS * 
 
1392
          nb_desired_values= AUTO_INC_DEFAULT_NB_ROWS *
2085
1393
            (1 << nb_already_reserved_intervals);
2086
 
          set_if_smaller(nb_desired_values, AUTO_INC_DEFAULT_NB_MAX);
 
1394
          set_if_smaller(nb_desired_values, (uint64_t)AUTO_INC_DEFAULT_NB_MAX);
2087
1395
        }
2088
1396
        else
2089
1397
          nb_desired_values= AUTO_INC_DEFAULT_NB_MAX;
2094
1402
                         nb_desired_values, &nr,
2095
1403
                         &nb_reserved_values);
2096
1404
      if (nr == ~(uint64_t) 0)
2097
 
        return(HA_ERR_AUTOINC_READ_FAILED);  // Mark failure
2098
 
      
 
1405
        return HA_ERR_AUTOINC_READ_FAILED;  // Mark failure
 
1406
 
2099
1407
      /*
2100
1408
        That rounding below should not be needed when all engines actually
2101
1409
        respect offset and increment in get_auto_increment(). But they don't
2106
1414
      */
2107
1415
      nr= compute_next_insert_id(nr-1, variables);
2108
1416
    }
2109
 
    
 
1417
 
2110
1418
    if (table->s->next_number_keypart == 0)
2111
1419
    {
2112
1420
      /* We must defer the appending until "nr" has been possibly truncated */
2119
1427
    /*
2120
1428
      first test if the query was aborted due to strict mode constraints
2121
1429
    */
2122
 
    if (thd->killed == THD::KILL_BAD_DATA)
2123
 
      return(HA_ERR_AUTOINC_ERANGE);
 
1430
    if (session->killed == Session::KILL_BAD_DATA)
 
1431
      return HA_ERR_AUTOINC_ERANGE;
2124
1432
 
2125
1433
    /*
2126
1434
      field refused this value (overflow) and truncated it, use the result of
2138
1446
  {
2139
1447
    auto_inc_interval_for_cur_row.replace(nr, nb_reserved_values,
2140
1448
                                          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
1449
  }
2147
1450
 
2148
1451
  /*
2159
1462
  */
2160
1463
  set_next_insert_id(compute_next_insert_id(nr, variables));
2161
1464
 
2162
 
  return(0);
2163
 
}
2164
 
 
2165
 
 
2166
 
/**
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;
 
1465
  return 0;
2181
1466
}
2182
1467
 
2183
1468
 
2196
1481
  @param first_value         (OUT) the first value reserved by the handler
2197
1482
  @param nb_reserved_values  (OUT) how many values the handler reserved
2198
1483
*/
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)),
 
1484
void handler::get_auto_increment(uint64_t ,
 
1485
                                 uint64_t ,
 
1486
                                 uint64_t ,
2202
1487
                                 uint64_t *first_value,
2203
1488
                                 uint64_t *nb_reserved_values)
2204
1489
{
2206
1491
  int error;
2207
1492
 
2208
1493
  (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();
 
1494
  table->mark_columns_used_by_index_no_reset(table->s->next_number_index);
2212
1495
  index_init(table->s->next_number_index, 1);
2213
1496
  if (table->s->next_number_keypart == 0)
2214
1497
  {                                             // Autoincrement at key-start
2281
1564
  else
2282
1565
  {
2283
1566
    /* 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);
 
1567
    key_unpack(&str,table,(uint32_t) key_nr);
 
1568
    uint32_t max_length=DRIZZLE_ERRMSG_SIZE-(uint32_t) strlen(msg);
2286
1569
    if (str.length() >= max_length)
2287
1570
    {
2288
1571
      str.length(max_length-4);
2345
1628
      char key[MAX_KEY_LENGTH];
2346
1629
      String str(key,sizeof(key),system_charset_info);
2347
1630
      /* Table is opened and defined at this point */
2348
 
      key_unpack(&str,table,(uint) key_nr);
 
1631
      key_unpack(&str,table,(uint32_t) key_nr);
2349
1632
      max_length= (DRIZZLE_ERRMSG_SIZE-
2350
 
                   (uint) strlen(ER(ER_FOREIGN_DUPLICATE_KEY)));
 
1633
                   (uint32_t) strlen(ER(ER_FOREIGN_DUPLICATE_KEY)));
2351
1634
      if (str.length() >= max_length)
2352
1635
      {
2353
1636
        str.length(max_length-4);
2461
1744
    my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
2462
1745
               ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
2463
1746
    return;
2464
 
    break;
2465
1747
  default:
2466
1748
    {
2467
1749
      /* The error was "unknown" to this function.
2471
1753
      temporary= get_error_message(error, &str);
2472
1754
      if (!str.is_empty())
2473
1755
      {
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);
 
1756
        const char* engine_name= engine->getName().c_str();
 
1757
        if (temporary)
 
1758
          my_error(ER_GET_TEMPORARY_ERRMSG, MYF(0), error, str.ptr(),
 
1759
                   engine_name);
 
1760
        else
 
1761
          my_error(ER_GET_ERRMSG, MYF(0), error, str.ptr(), engine_name);
2479
1762
      }
2480
1763
      else
2481
 
        my_error(ER_GET_ERRNO,errflag,error);
 
1764
      {
 
1765
              my_error(ER_GET_ERRNO,errflag,error);
 
1766
      }
2482
1767
      return;
2483
1768
    }
2484
1769
  }
2485
1770
  my_error(textno, errflag, table_share->table_name.str, error);
2486
 
  return;
2487
1771
}
2488
1772
 
2489
1773
 
2496
1780
  @return
2497
1781
    Returns true if this is a temporary error
2498
1782
*/
2499
 
bool handler::get_error_message(int error __attribute__((unused)),
2500
 
                                String* buf __attribute__((unused)))
 
1783
bool handler::get_error_message(int , String* )
2501
1784
{
2502
1785
  return false;
2503
1786
}
2504
1787
 
2505
1788
 
2506
 
int handler::ha_check_for_upgrade(HA_CHECK_OPT *check_opt)
2507
 
{
2508
 
  KEY *keyinfo, *keyend;
2509
 
  KEY_PART_INFO *keypart, *keypartend;
2510
 
 
2511
 
  if (!table->s->mysql_version)
2512
 
  {
2513
 
    /* check for blob-in-key error */
2514
 
    keyinfo= table->key_info;
2515
 
    keyend= table->key_info + table->s->keys;
2516
 
    for (; keyinfo < keyend; keyinfo++)
2517
 
    {
2518
 
      keypart= keyinfo->key_part;
2519
 
      keypartend= keypart + keyinfo->key_parts;
2520
 
      for (; keypart < keypartend; keypart++)
2521
 
      {
2522
 
        if (!keypart->fieldnr)
2523
 
          continue;
2524
 
        Field *field= table->field[keypart->fieldnr-1];
2525
 
        if (field->type() == DRIZZLE_TYPE_BLOB)
2526
 
        {
2527
 
          if (check_opt->sql_flags & TT_FOR_UPGRADE)
2528
 
            check_opt->flags= T_MEDIUM;
2529
 
          return HA_ADMIN_NEEDS_CHECK;
2530
 
        }
2531
 
      }
2532
 
    }
2533
 
  }
2534
 
  return check_for_upgrade(check_opt);
2535
 
}
2536
 
 
2537
 
 
2538
1789
/* Code left, but Drizzle has no legacy yet (while MySQL did) */
2539
1790
int handler::check_old_types()
2540
1791
{
2541
1792
  return 0;
2542
1793
}
2543
1794
 
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
1795
/**
2592
1796
  @return
2593
1797
    key if error because of duplicated keys
2594
1798
*/
2595
1799
uint32_t handler::get_dup_key(int error)
2596
1800
{
2597
 
  table->file->errkey  = (uint) -1;
 
1801
  table->file->errkey  = (uint32_t) -1;
2598
1802
  if (error == HA_ERR_FOUND_DUPP_KEY || error == HA_ERR_FOREIGN_DUPLICATE_KEY ||
2599
1803
      error == HA_ERR_FOUND_DUPP_UNIQUE ||
2600
1804
      error == HA_ERR_DROP_INDEX_FK)
2602
1806
  return(table->file->errkey);
2603
1807
}
2604
1808
 
2605
 
 
2606
 
/**
2607
 
  Delete all files with extension from bas_ext().
2608
 
 
2609
 
  @param name           Base name of table
2610
 
 
2611
 
  @note
2612
 
    We assume that the handler may return more extensions than
2613
 
    was actually used for the file.
2614
 
 
2615
 
  @retval
2616
 
    0   If we successfully deleted at least one file from base_ext and
2617
 
    didn't get any other errors than ENOENT
2618
 
  @retval
2619
 
    !0  Error
2620
 
*/
2621
 
int handler::delete_table(const char *name)
2622
 
{
2623
 
  int error= 0;
2624
 
  int enoent_or_zero= ENOENT;                   // Error if no file was deleted
2625
 
  char buff[FN_REFLEN];
2626
 
 
2627
 
  for (const char **ext=bas_ext(); *ext ; ext++)
2628
 
  {
2629
 
    fn_format(buff, name, "", *ext, MY_UNPACK_FILENAME|MY_APPEND_EXT);
2630
 
    if (my_delete_with_symlink(buff, MYF(0)))
2631
 
    {
2632
 
      if ((error= my_errno) != ENOENT)
2633
 
        break;
2634
 
    }
2635
 
    else
2636
 
      enoent_or_zero= 0;                        // No error for ENOENT
2637
 
    error= enoent_or_zero;
2638
 
  }
2639
 
  return error;
2640
 
}
2641
 
 
2642
 
 
2643
 
int handler::rename_table(const char * from, const char * to)
2644
 
{
2645
 
  int error= 0;
2646
 
  for (const char **ext= bas_ext(); *ext ; ext++)
2647
 
  {
2648
 
    if (rename_file_ext(from, to, *ext))
2649
 
    {
2650
 
      if ((error=my_errno) != ENOENT)
2651
 
        break;
2652
 
      error= 0;
2653
 
    }
2654
 
  }
2655
 
  return error;
2656
 
}
2657
 
 
2658
 
 
2659
1809
void handler::drop_table(const char *name)
2660
1810
{
2661
1811
  close();
2662
 
  delete_table(name);
 
1812
  engine->deleteTable(ha_session(), name);
2663
1813
}
2664
1814
 
2665
1815
 
2666
1816
/**
2667
1817
  Performs checks upon the table.
2668
1818
 
2669
 
  @param thd                thread doing CHECK Table operation
 
1819
  @param session                thread doing CHECK Table operation
2670
1820
  @param check_opt          options from the parser
2671
1821
 
2672
1822
  @retval
2678
1828
  @retval
2679
1829
    HA_ADMIN_NOT_IMPLEMENTED
2680
1830
*/
2681
 
int handler::ha_check(THD *thd, HA_CHECK_OPT *check_opt)
 
1831
int handler::ha_check(Session *, HA_CHECK_OPT *)
2682
1832
{
2683
 
  int error;
2684
 
 
2685
 
  if ((table->s->mysql_version >= DRIZZLE_VERSION_ID) &&
2686
 
      (check_opt->sql_flags & TT_FOR_UPGRADE))
2687
 
    return 0;
2688
 
 
2689
 
  if (table->s->mysql_version < DRIZZLE_VERSION_ID)
2690
 
  {
2691
 
    if ((error= check_old_types()))
2692
 
      return error;
2693
 
    error= ha_check_for_upgrade(check_opt);
2694
 
    if (error && (error != HA_ADMIN_NEEDS_CHECK))
2695
 
      return error;
2696
 
    if (!error && (check_opt->sql_flags & TT_FOR_UPGRADE))
2697
 
      return 0;
2698
 
  }
2699
 
  if ((error= check(thd, check_opt)))
2700
 
    return error;
2701
 
  return update_frm_version(table);
 
1833
  return HA_ADMIN_OK;
2702
1834
}
2703
1835
 
2704
1836
/**
2710
1842
void
2711
1843
handler::mark_trx_read_write()
2712
1844
{
2713
 
  Ha_trx_info *ha_info= &ha_thd()->ha_data[ht->slot].ha_info[0];
 
1845
  Ha_trx_info *ha_info= &ha_session()->ha_data[engine->getSlot()].ha_info[0];
2714
1846
  /*
2715
1847
    When a storage engine method is called, the transaction must
2716
1848
    have been started, unless it's a DDL call, for which the
2721
1853
  */
2722
1854
  if (ha_info->is_started())
2723
1855
  {
2724
 
    assert(has_transactions());
2725
1856
    /*
2726
1857
      table_share can be NULL in ha_delete_table(). See implementation
2727
1858
      of standalone function ha_delete_table() in sql_base.cc.
2728
1859
    */
2729
 
    if (table_share == NULL || table_share->tmp_table == NO_TMP_TABLE)
 
1860
//    if (table_share == NULL || table_share->tmp_table == NO_TMP_TABLE)
2730
1861
      ha_info->set_trx_read_write();
2731
1862
  }
2732
1863
}
2733
1864
 
2734
 
 
2735
 
/**
2736
 
  Repair table: public interface.
2737
 
 
2738
 
  @sa handler::repair()
2739
 
*/
2740
 
 
2741
 
int handler::ha_repair(THD* thd, HA_CHECK_OPT* check_opt)
2742
 
{
2743
 
  int result;
2744
 
 
2745
 
  mark_trx_read_write();
2746
 
 
2747
 
  if ((result= repair(thd, check_opt)))
2748
 
    return result;
2749
 
  return update_frm_version(table);
2750
 
}
2751
 
 
2752
 
 
2753
1865
/**
2754
1866
  Bulk update row: public interface.
2755
1867
 
2803
1915
*/
2804
1916
 
2805
1917
int
2806
 
handler::ha_optimize(THD* thd, HA_CHECK_OPT* check_opt)
 
1918
handler::ha_optimize(Session* session, HA_CHECK_OPT* check_opt)
2807
1919
{
2808
1920
  mark_trx_read_write();
2809
1921
 
2810
 
  return optimize(thd, check_opt);
 
1922
  return optimize(session, check_opt);
2811
1923
}
2812
1924
 
2813
1925
 
2818
1930
*/
2819
1931
 
2820
1932
int
2821
 
handler::ha_analyze(THD* thd, HA_CHECK_OPT* check_opt)
2822
 
{
2823
 
  mark_trx_read_write();
2824
 
 
2825
 
  return analyze(thd, check_opt);
2826
 
}
2827
 
 
2828
 
 
2829
 
/**
2830
 
  Check and repair table: public interface.
2831
 
 
2832
 
  @sa handler::check_and_repair()
2833
 
*/
2834
 
 
2835
 
bool
2836
 
handler::ha_check_and_repair(THD *thd)
2837
 
{
2838
 
  mark_trx_read_write();
2839
 
 
2840
 
  return check_and_repair(thd);
2841
 
}
2842
 
 
 
1933
handler::ha_analyze(Session* session, HA_CHECK_OPT* check_opt)
 
1934
{
 
1935
  mark_trx_read_write();
 
1936
 
 
1937
  return analyze(session, check_opt);
 
1938
}
2843
1939
 
2844
1940
/**
2845
1941
  Disable indexes: public interface.
2885
1981
  return discard_or_import_tablespace(discard);
2886
1982
}
2887
1983
 
2888
 
 
2889
 
/**
2890
 
  Prepare for alter: public interface.
2891
 
 
2892
 
  Called to prepare an *online* ALTER.
2893
 
 
2894
 
  @sa handler::prepare_for_alter()
2895
 
*/
2896
 
 
2897
 
void
2898
 
handler::ha_prepare_for_alter()
2899
 
{
2900
 
  mark_trx_read_write();
2901
 
 
2902
 
  prepare_for_alter();
2903
 
}
2904
 
 
2905
 
 
2906
 
/**
2907
 
  Rename table: public interface.
2908
 
 
2909
 
  @sa handler::rename_table()
2910
 
*/
2911
 
 
2912
 
int
2913
 
handler::ha_rename_table(const char *from, const char *to)
2914
 
{
2915
 
  mark_trx_read_write();
2916
 
 
2917
 
  return rename_table(from, to);
2918
 
}
2919
 
 
2920
 
 
2921
 
/**
2922
 
  Delete table: public interface.
2923
 
 
2924
 
  @sa handler::delete_table()
2925
 
*/
2926
 
 
2927
 
int
2928
 
handler::ha_delete_table(const char *name)
2929
 
{
2930
 
  mark_trx_read_write();
2931
 
 
2932
 
  return delete_table(name);
2933
 
}
2934
 
 
2935
 
 
2936
1984
/**
2937
1985
  Drop table in the engine: public interface.
2938
1986
 
2947
1995
  return drop_table(name);
2948
1996
}
2949
1997
 
2950
 
 
2951
 
/**
2952
 
  Create a table in the engine: public interface.
2953
 
 
2954
 
  @sa handler::create()
2955
 
*/
2956
 
 
2957
 
int
2958
 
handler::ha_create(const char *name, Table *form, HA_CREATE_INFO *info)
2959
 
{
2960
 
  mark_trx_read_write();
2961
 
 
2962
 
  return create(name, form, info);
2963
 
}
2964
 
 
2965
 
 
2966
 
/**
2967
 
  Create handler files for CREATE TABLE: public interface.
2968
 
 
2969
 
  @sa handler::create_handler_files()
2970
 
*/
2971
 
 
2972
 
int
2973
 
handler::ha_create_handler_files(const char *name, const char *old_name,
2974
 
                        int action_flag, HA_CREATE_INFO *info)
2975
 
{
2976
 
  mark_trx_read_write();
2977
 
 
2978
 
  return create_handler_files(name, old_name, action_flag, info);
2979
 
}
2980
 
 
2981
 
 
2982
1998
/**
2983
1999
  Tell the storage engine that it is allowed to "disable transaction" in the
2984
2000
  handler. It is a hint that ACID is not required - it is used in NDB for
2987
2003
  starts to commit every now and then automatically.
2988
2004
  This hint can be safely ignored.
2989
2005
*/
2990
 
int ha_enable_transaction(THD *thd, bool on)
 
2006
int ha_enable_transaction(Session *session, bool on)
2991
2007
{
2992
 
  int error=0;
 
2008
  int error= 0;
2993
2009
 
2994
 
  if ((thd->transaction.on= on))
 
2010
  if ((session->transaction.on= on))
2995
2011
  {
2996
2012
    /*
2997
2013
      Now all storage engines should have transaction handling enabled.
2999
2015
      is an optimization hint that storage engine is free to ignore.
3000
2016
      So, let's commit an open transaction (if any) now.
3001
2017
    */
3002
 
    if (!(error= ha_commit_trans(thd, 0)))
3003
 
      error= end_trans(thd, COMMIT);
 
2018
    if (!(error= ha_commit_trans(session, 0)))
 
2019
      if (! session->endTransaction(COMMIT))
 
2020
        error= 1;
 
2021
 
3004
2022
  }
3005
 
  return(error);
 
2023
  return error;
3006
2024
}
3007
2025
 
3008
2026
int handler::index_next_same(unsigned char *buf, const unsigned char *key, uint32_t keylen)
3052
2070
        key_part->field->move_field_offset(-ptrdiff);
3053
2071
    }
3054
2072
  }
3055
 
  return(error);
 
2073
  return error;
3056
2074
}
3057
2075
 
3058
2076
 
3060
2078
** Some general functions that isn't in the handler class
3061
2079
****************************************************************************/
3062
2080
 
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
2081
 
3168
2082
void st_ha_check_opt::init()
3169
2083
{
3170
 
  flags= sql_flags= 0;
3171
 
  sort_buffer_size = current_thd->variables.myisam_sort_buff_size;
3172
 
}
3173
 
 
3174
 
 
3175
 
/*****************************************************************************
3176
 
  Key cache handling.
3177
 
 
3178
 
  This code is only relevant for ISAM/MyISAM tables
3179
 
 
3180
 
  key_cache->cache may be 0 only in the case where a key cache is not
3181
 
  initialized or when we where not able to init the key cache in a previous
3182
 
  call to ha_init_key_cache() (probably out of memory)
3183
 
*****************************************************************************/
3184
 
 
3185
 
/**
3186
 
  Init a key cache if it has not been initied before.
3187
 
*/
3188
 
int ha_init_key_cache(const char *name __attribute__((unused)),
3189
 
                      KEY_CACHE *key_cache)
3190
 
{
3191
 
  if (!key_cache->key_cache_inited)
3192
 
  {
3193
 
    pthread_mutex_lock(&LOCK_global_system_variables);
3194
 
    uint32_t tmp_buff_size= (uint32_t) key_cache->param_buff_size;
3195
 
    uint32_t tmp_block_size= (uint) key_cache->param_block_size;
3196
 
    uint32_t division_limit= key_cache->param_division_limit;
3197
 
    uint32_t age_threshold=  key_cache->param_age_threshold;
3198
 
    pthread_mutex_unlock(&LOCK_global_system_variables);
3199
 
    return(!init_key_cache(key_cache,
3200
 
                                tmp_block_size,
3201
 
                                tmp_buff_size,
3202
 
                                division_limit, age_threshold));
3203
 
  }
3204
 
  return(0);
3205
 
}
3206
 
 
3207
 
 
3208
 
/**
3209
 
  Resize key cache.
3210
 
*/
3211
 
int ha_resize_key_cache(KEY_CACHE *key_cache)
3212
 
{
3213
 
  if (key_cache->key_cache_inited)
3214
 
  {
3215
 
    pthread_mutex_lock(&LOCK_global_system_variables);
3216
 
    long tmp_buff_size= (long) key_cache->param_buff_size;
3217
 
    long tmp_block_size= (long) key_cache->param_block_size;
3218
 
    uint32_t division_limit= key_cache->param_division_limit;
3219
 
    uint32_t age_threshold=  key_cache->param_age_threshold;
3220
 
    pthread_mutex_unlock(&LOCK_global_system_variables);
3221
 
    return(!resize_key_cache(key_cache, tmp_block_size,
3222
 
                                  tmp_buff_size,
3223
 
                                  division_limit, age_threshold));
3224
 
  }
3225
 
  return(0);
3226
 
}
3227
 
 
3228
 
 
3229
 
/**
3230
 
  Change parameters for key cache (like size)
3231
 
*/
3232
 
int ha_change_key_cache_param(KEY_CACHE *key_cache)
3233
 
{
3234
 
  if (key_cache->key_cache_inited)
3235
 
  {
3236
 
    pthread_mutex_lock(&LOCK_global_system_variables);
3237
 
    uint32_t division_limit= key_cache->param_division_limit;
3238
 
    uint32_t age_threshold=  key_cache->param_age_threshold;
3239
 
    pthread_mutex_unlock(&LOCK_global_system_variables);
3240
 
    change_key_cache_param(key_cache, division_limit, age_threshold);
3241
 
  }
3242
 
  return 0;
3243
 
}
3244
 
 
3245
 
/**
3246
 
  Free memory allocated by a key cache.
3247
 
*/
3248
 
int ha_end_key_cache(KEY_CACHE *key_cache)
3249
 
{
3250
 
  end_key_cache(key_cache, 1);          // Can never fail
3251
 
  return 0;
3252
 
}
3253
 
 
3254
 
/**
3255
 
  Move all tables from one key cache to another one.
3256
 
*/
3257
 
int ha_change_key_cache(KEY_CACHE *old_key_cache,
3258
 
                        KEY_CACHE *new_key_cache)
3259
 
{
3260
 
  mi_change_key_cache(old_key_cache, new_key_cache);
3261
 
  return 0;
3262
 
}
3263
 
 
3264
 
 
3265
 
/**
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);
 
2084
  flags= 0; 
 
2085
  use_frm= false;
3370
2086
}
3371
2087
 
3372
2088
/**
3390
2106
    Estimated cost of 'index only' scan
3391
2107
*/
3392
2108
 
3393
 
double handler::index_only_read_time(uint32_t keynr, double records)
 
2109
double handler::index_only_read_time(uint32_t keynr, double key_records)
3394
2110
{
3395
 
  double read_time;
3396
2111
  uint32_t keys_per_block= (stats.block_size/2/
3397
2112
                        (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;
 
2113
  return ((double) (key_records + keys_per_block-1) /
 
2114
          (double) keys_per_block);
3401
2115
}
3402
2116
 
3403
2117
 
3424
2138
 
3425
2139
  @note
3426
2140
    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
 
2141
    session->killed and return HA_POS_ERROR if it is not zero. This is required
3428
2142
    for a user to be able to interrupt the calculation by killing the
3429
2143
    connection/query.
3430
2144
 
3439
2153
ha_rows
3440
2154
handler::multi_range_read_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
3441
2155
                                     void *seq_init_param,
3442
 
                                     uint32_t n_ranges_arg __attribute__((unused)),
 
2156
                                     uint32_t ,
3443
2157
                                     uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
3444
2158
{
3445
2159
  KEY_MULTI_RANGE range;
3446
2160
  range_seq_t seq_it;
3447
2161
  ha_rows rows, total_rows= 0;
3448
2162
  uint32_t n_ranges=0;
3449
 
  THD *thd= current_thd;
3450
 
  
 
2163
  Session *session= current_session;
 
2164
 
3451
2165
  /* Default MRR implementation doesn't need buffer */
3452
2166
  *bufsz= 0;
3453
2167
 
3454
2168
  seq_it= seq->init(seq_init_param, n_ranges, *flags);
3455
2169
  while (!seq->next(seq_it, &range))
3456
2170
  {
3457
 
    if (unlikely(thd->killed != 0))
 
2171
    if (unlikely(session->killed != 0))
3458
2172
      return HA_POS_ERROR;
3459
 
    
 
2173
 
3460
2174
    n_ranges++;
3461
2175
    key_range *min_endp, *max_endp;
3462
2176
    {
3467
2181
      rows= 1; /* there can be at most one row */
3468
2182
    else
3469
2183
    {
3470
 
      if (HA_POS_ERROR == (rows= this->records_in_range(keyno, min_endp, 
 
2184
      if (HA_POS_ERROR == (rows= this->records_in_range(keyno, min_endp,
3471
2185
                                                        max_endp)))
3472
2186
      {
3473
2187
        /* Can't scan one range => can't do MRR scan at all */
3477
2191
    }
3478
2192
    total_rows += rows;
3479
2193
  }
3480
 
  
 
2194
 
3481
2195
  if (total_rows != HA_POS_ERROR)
3482
2196
  {
3483
2197
    /* The following calculation is the same as in multi_range_read_info(): */
3485
2199
    cost->zero();
3486
2200
    cost->avg_io_cost= 1; /* assume random seeks */
3487
2201
    if ((*flags & HA_MRR_INDEX_ONLY) && total_rows > 2)
3488
 
      cost->io_count= index_only_read_time(keyno, (uint)total_rows);
 
2202
      cost->io_count= index_only_read_time(keyno, (uint32_t)total_rows);
3489
2203
    else
3490
2204
      cost->io_count= read_time(keyno, n_ranges, total_rows);
3491
2205
    cost->cpu_cost= (double) total_rows / TIME_FOR_COMPARE + 0.01;
3550
2264
/**
3551
2265
  Initialize the MRR scan
3552
2266
 
3553
 
  Initialize the MRR scan. This function may do heavyweight scan 
 
2267
  Initialize the MRR scan. This function may do heavyweight scan
3554
2268
  initialization like row prefetching/sorting/etc (NOTE: but better not do
3555
2269
  it here as we may not need it, e.g. if we never satisfy WHERE clause on
3556
2270
  previous tables. For many implementations it would be natural to do such
3557
2271
  initializations in the first multi_read_range_next() call)
3558
2272
 
3559
2273
  mode is a combination of the following flags: HA_MRR_SORTED,
3560
 
  HA_MRR_INDEX_ONLY, HA_MRR_NO_ASSOCIATION 
 
2274
  HA_MRR_INDEX_ONLY, HA_MRR_NO_ASSOCIATION
3561
2275
 
3562
2276
  @param seq             Range sequence to be traversed
3563
2277
  @param seq_init_param  First parameter for seq->init()
3569
2283
    One must have called index_init() before calling this function. Several
3570
2284
    multi_range_read_init() calls may be made in course of one query.
3571
2285
 
3572
 
    Until WL#2623 is done (see its text, section 3.2), the following will 
 
2286
    Until WL#2623 is done (see its text, section 3.2), the following will
3573
2287
    also hold:
3574
2288
    The caller will guarantee that if "seq->init == mrr_ranges_array_init"
3575
2289
    then seq_init_param is an array of n_ranges KEY_MULTI_RANGE structures.
3576
2290
    This property will only be used by NDB handler until WL#2623 is done.
3577
 
     
 
2291
 
3578
2292
    Buffer memory management is done according to the following scenario:
3579
2293
    The caller allocates the buffer and provides it to the callee by filling
3580
2294
    the members of HANDLER_BUFFER structure.
3591
2305
int
3592
2306
handler::multi_range_read_init(RANGE_SEQ_IF *seq_funcs, void *seq_init_param,
3593
2307
                               uint32_t n_ranges, uint32_t mode,
3594
 
                               HANDLER_BUFFER *buf __attribute__((unused)))
 
2308
                               HANDLER_BUFFER *)
3595
2309
{
3596
2310
  mrr_iter= seq_funcs->init(seq_init_param, n_ranges, mode);
3597
2311
  mrr_funcs= *seq_funcs;
3598
2312
  mrr_is_output_sorted= test(mode & HA_MRR_SORTED);
3599
2313
  mrr_have_range= false;
3600
 
  return(0);
 
2314
  return 0;
3601
2315
}
3602
2316
 
3603
2317
 
3664
2378
  while ((result == HA_ERR_END_OF_FILE) && !range_res);
3665
2379
 
3666
2380
  *range_info= mrr_cur_range.ptr;
3667
 
  return(result);
3668
 
}
3669
 
 
3670
 
 
3671
 
/* **************************************************************************
3672
 
 * DS-MRR implementation 
3673
 
 ***************************************************************************/
3674
 
 
3675
 
/**
3676
 
  DS-MRR: Initialize and start MRR scan
3677
 
 
3678
 
  Initialize and start the MRR scan. Depending on the mode parameter, this
3679
 
  may use default or DS-MRR implementation.
3680
 
 
3681
 
  @param h               Table handler to be used
3682
 
  @param key             Index to be used
3683
 
  @param seq_funcs       Interval sequence enumeration functions
3684
 
  @param seq_init_param  Interval sequence enumeration parameter
3685
 
  @param n_ranges        Number of ranges in the sequence.
3686
 
  @param mode            HA_MRR_* modes to use
3687
 
  @param buf             INOUT Buffer to use
3688
 
 
3689
 
  @retval 0     Ok, Scan started.
3690
 
  @retval other Error
3691
 
*/
3692
 
 
3693
 
int DsMrr_impl::dsmrr_init(handler *h, KEY *key,
3694
 
                           RANGE_SEQ_IF *seq_funcs, void *seq_init_param,
3695
 
                           uint32_t n_ranges, uint32_t mode, HANDLER_BUFFER *buf)
3696
 
{
3697
 
  uint32_t elem_size;
3698
 
  uint32_t keyno;
3699
 
  Item *pushed_cond= NULL;
3700
 
  handler *new_h2;
3701
 
  keyno= h->active_index;
3702
 
  assert(h2 == NULL);
3703
 
  if (mode & HA_MRR_USE_DEFAULT_IMPL || mode & HA_MRR_SORTED)
3704
 
  {
3705
 
    use_default_impl= true;
3706
 
    return(h->handler::multi_range_read_init(seq_funcs, seq_init_param,
3707
 
                                                  n_ranges, mode, buf));
3708
 
  }
3709
 
  rowids_buf= buf->buffer;
3710
 
  //psergey-todo: don't add key_length as it is not needed anymore
3711
 
  rowids_buf += key->key_length + h->ref_length;
3712
 
 
3713
 
  is_mrr_assoc= !test(mode & HA_MRR_NO_ASSOCIATION);
3714
 
  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 + 
3718
 
                      ((rowids_buf_end - rowids_buf)/ elem_size)*
3719
 
                      elem_size;
3720
 
  rowids_buf_end= rowids_buf_last;
3721
 
 
3722
 
  /* 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))
3726
 
  {
3727
 
    delete new_h2;
3728
 
    return(1);
3729
 
  }
3730
 
 
3731
 
  if (keyno == h->pushed_idx_cond_keyno)
3732
 
    pushed_cond= h->pushed_idx_cond;
3733
 
  if (h->ha_index_end())
3734
 
  {
3735
 
    new_h2= h2;
3736
 
    goto error;
3737
 
  }
3738
 
 
3739
 
  h2= new_h2;
3740
 
  table->prepare_for_position();
3741
 
  new_h2->extra(HA_EXTRA_KEYREAD);
3742
 
 
3743
 
  if (h2->ha_index_init(keyno, false) || 
3744
 
      h2->handler::multi_range_read_init(seq_funcs, seq_init_param, n_ranges,
3745
 
                                         mode, buf))
3746
 
    goto error;
3747
 
  use_default_impl= false;
3748
 
  
3749
 
  if (pushed_cond)
3750
 
    h2->idx_cond_push(keyno, pushed_cond);
3751
 
  if (dsmrr_fill_buffer(new_h2))
3752
 
    goto error;
3753
 
 
3754
 
  /*
3755
 
    If the above call has scanned through all intervals in *seq, then
3756
 
    adjust *buf to indicate that the remaining buffer space will not be used.
3757
 
  */
3758
 
  if (dsmrr_eof) 
3759
 
    buf->end_of_used_area= rowids_buf_last;
3760
 
 
3761
 
  if (h->ha_rnd_init(false))
3762
 
    goto error;
3763
 
  
3764
 
  return(0);
3765
 
error:
3766
 
  h2->ha_index_or_rnd_end();
3767
 
  h2->ha_external_lock(thd, F_UNLCK);
3768
 
  h2->close();
3769
 
  delete h2;
3770
 
  return(1);
3771
 
}
3772
 
 
3773
 
 
3774
 
void DsMrr_impl::dsmrr_close()
3775
 
{
3776
 
  if (h2)
3777
 
  {
3778
 
    h2->ha_external_lock(current_thd, F_UNLCK);
3779
 
    h2->close();
3780
 
    delete h2;
3781
 
    h2= NULL;
3782
 
  }
3783
 
  use_default_impl= true;
3784
 
  return;
3785
 
}
3786
 
 
3787
 
 
3788
 
static int rowid_cmp(void *h, unsigned char *a, unsigned char *b)
3789
 
{
3790
 
  return ((handler*)h)->cmp_ref(a, b);
3791
 
}
3792
 
 
3793
 
 
3794
 
/**
3795
 
  DS-MRR: Fill the buffer with rowids and sort it by rowid
3796
 
 
3797
 
  {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 
3800
 
  rowid and return.
3801
 
  
3802
 
  The function assumes that rowids buffer is empty when it is invoked. 
3803
 
  
3804
 
  @param h  Table handler
3805
 
 
3806
 
  @retval 0      OK, the next portion of rowids is in the buffer,
3807
 
                 properly ordered
3808
 
  @retval other  Error
3809
 
*/
3810
 
 
3811
 
int DsMrr_impl::dsmrr_fill_buffer(handler *unused __attribute__((unused)))
3812
 
{
3813
 
  char *range_info;
3814
 
  int res = 0;
3815
 
 
3816
 
  rowids_buf_cur= rowids_buf;
3817
 
  while ((rowids_buf_cur < rowids_buf_end) && 
3818
 
         !(res= h2->handler::multi_range_read_next(&range_info)))
3819
 
  {
3820
 
    /* Put rowid, or {rowid, range_id} pair into the buffer */
3821
 
    h2->position(table->record[0]);
3822
 
    memcpy(rowids_buf_cur, h2->ref, h2->ref_length);
3823
 
    rowids_buf_cur += h->ref_length;
3824
 
 
3825
 
    if (is_mrr_assoc)
3826
 
    {
3827
 
      memcpy(rowids_buf_cur, &range_info, sizeof(void*));
3828
 
      rowids_buf_cur += sizeof(void*);
3829
 
    }
3830
 
  }
3831
 
 
3832
 
  if (res && res != HA_ERR_END_OF_FILE)
3833
 
    return(res); 
3834
 
  dsmrr_eof= test(res == HA_ERR_END_OF_FILE);
3835
 
 
3836
 
  /* Sort the buffer contents by rowid */
3837
 
  uint32_t elem_size= h->ref_length + (int)is_mrr_assoc * sizeof(void*);
3838
 
  uint32_t n_rowids= (rowids_buf_cur - rowids_buf) / elem_size;
3839
 
  
3840
 
  my_qsort2(rowids_buf, n_rowids, elem_size, (qsort2_cmp)rowid_cmp,
3841
 
            (void*)h);
3842
 
  rowids_buf_last= rowids_buf_cur;
3843
 
  rowids_buf_cur=  rowids_buf;
3844
 
  return(0);
3845
 
}
3846
 
 
3847
 
 
3848
 
/**
3849
 
  DS-MRR implementation: multi_range_read_next() function
3850
 
*/
3851
 
 
3852
 
int DsMrr_impl::dsmrr_next(handler *h, char **range_info)
3853
 
{
3854
 
  int res;
3855
 
  
3856
 
  if (use_default_impl)
3857
 
    return h->handler::multi_range_read_next(range_info);
3858
 
    
3859
 
  if (rowids_buf_cur == rowids_buf_last)
3860
 
  {
3861
 
    if (dsmrr_eof)
3862
 
    {
3863
 
      res= HA_ERR_END_OF_FILE;
3864
 
      goto end;
3865
 
    }
3866
 
    res= dsmrr_fill_buffer(h);
3867
 
    if (res)
3868
 
      goto end;
3869
 
  }
3870
 
  
3871
 
  /* Return EOF if there are no rowids in the buffer after re-fill attempt */
3872
 
  if (rowids_buf_cur == rowids_buf_last)
3873
 
  {
3874
 
    res= HA_ERR_END_OF_FILE;
3875
 
    goto end;
3876
 
  }
3877
 
 
3878
 
  res= h->rnd_pos(table->record[0], rowids_buf_cur);
3879
 
  rowids_buf_cur += h->ref_length;
3880
 
  if (is_mrr_assoc)
3881
 
  {
3882
 
    memcpy(range_info, rowids_buf_cur, sizeof(void*));
3883
 
    rowids_buf_cur += sizeof(void*);
3884
 
  }
3885
 
 
3886
 
end:
3887
 
  if (res)
3888
 
    dsmrr_close();
3889
 
  return res;
3890
 
}
3891
 
 
3892
 
 
3893
 
/**
3894
 
  DS-MRR implementation: multi_range_read_info() function
3895
 
*/
3896
 
int DsMrr_impl::dsmrr_info(uint32_t keyno, uint32_t n_ranges, uint32_t rows, uint32_t *bufsz,
3897
 
                           uint32_t *flags, COST_VECT *cost)
3898
 
{  
3899
 
  int res;
3900
 
  uint32_t def_flags= *flags;
3901
 
  uint32_t def_bufsz= *bufsz;
3902
 
 
3903
 
  /* Get cost/flags/mem_usage of default MRR implementation */
3904
 
  res= h->handler::multi_range_read_info(keyno, n_ranges, rows, &def_bufsz,
3905
 
                                         &def_flags, cost);
3906
 
  assert(!res);
3907
 
 
3908
 
  if ((*flags & HA_MRR_USE_DEFAULT_IMPL) || 
3909
 
      choose_mrr_impl(keyno, rows, &def_flags, &def_bufsz, cost))
3910
 
  {
3911
 
    /* Default implementation is choosen */
3912
 
    *flags= def_flags;
3913
 
    *bufsz= def_bufsz;
3914
 
  }
3915
 
  return 0;
3916
 
}
3917
 
 
3918
 
 
3919
 
/**
3920
 
  DS-MRR Implementation: multi_range_read_info_const() function
3921
 
*/
3922
 
 
3923
 
ha_rows DsMrr_impl::dsmrr_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
3924
 
                                 void *seq_init_param, uint32_t n_ranges, 
3925
 
                                 uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
3926
 
{
3927
 
  ha_rows rows;
3928
 
  uint32_t def_flags= *flags;
3929
 
  uint32_t def_bufsz= *bufsz;
3930
 
  /* Get cost/flags/mem_usage of default MRR implementation */
3931
 
  rows= h->handler::multi_range_read_info_const(keyno, seq, seq_init_param,
3932
 
                                                n_ranges, &def_bufsz, 
3933
 
                                                &def_flags, cost);
3934
 
  if (rows == HA_POS_ERROR)
3935
 
  {
3936
 
    /* Default implementation can't perform MRR scan => we can't either */
3937
 
    return rows;
3938
 
  }
3939
 
 
3940
 
  /*
3941
 
    If HA_MRR_USE_DEFAULT_IMPL has been passed to us, that is an order to
3942
 
    use the default MRR implementation (we need it for UPDATE/DELETE).
3943
 
    Otherwise, make a choice based on cost and @@optimizer_use_mrr.
3944
 
  */
3945
 
  if ((*flags & HA_MRR_USE_DEFAULT_IMPL) ||
3946
 
      choose_mrr_impl(keyno, rows, flags, bufsz, cost))
3947
 
  {
3948
 
    *flags= def_flags;
3949
 
    *bufsz= def_bufsz;
3950
 
  }
3951
 
  else
3952
 
  {
3953
 
    *flags &= ~HA_MRR_USE_DEFAULT_IMPL;
3954
 
  }
3955
 
  return rows;
3956
 
}
3957
 
 
3958
 
 
3959
 
/**
3960
 
  Check if key has partially-covered columns
3961
 
 
3962
 
  We can't use DS-MRR to perform range scans when the ranges are over
3963
 
  partially-covered keys, because we'll not have full key part values
3964
 
  (we'll have their prefixes from the index) and will not be able to check
3965
 
  if we've reached the end the range.
3966
 
 
3967
 
  @param keyno  Key to check
3968
 
 
3969
 
  @todo
3970
 
    Allow use of DS-MRR in cases where the index has partially-covered
3971
 
    components but they are not used for scanning.
3972
 
 
3973
 
  @retval true   Yes
3974
 
  @retval false  No
3975
 
*/
3976
 
 
3977
 
bool DsMrr_impl::key_uses_partial_cols(uint32_t keyno)
3978
 
{
3979
 
  KEY_PART_INFO *kp= table->key_info[keyno].key_part;
3980
 
  KEY_PART_INFO *kp_end= kp + table->key_info[keyno].key_parts;
3981
 
  for (; kp != kp_end; kp++)
3982
 
  {
3983
 
    if (!kp->field->part_of_key.is_set(keyno))
3984
 
      return true;
3985
 
  }
3986
 
  return false;
3987
 
}
3988
 
 
3989
 
 
3990
 
/**
3991
 
  DS-MRR Internals: Choose between Default MRR implementation and DS-MRR
3992
 
 
3993
 
  Make the choice between using Default MRR implementation and DS-MRR.
3994
 
  This function contains common functionality factored out of dsmrr_info()
3995
 
  and dsmrr_info_const(). The function assumes that the default MRR
3996
 
  implementation's applicability requirements are satisfied.
3997
 
 
3998
 
  @param keyno       Index number
3999
 
  @param rows        E(full rows to be retrieved)
4000
 
  @param flags  IN   MRR flags provided by the MRR user
4001
 
                OUT  If DS-MRR is choosen, flags of DS-MRR implementation
4002
 
                     else the value is not modified
4003
 
  @param bufsz  IN   If DS-MRR is choosen, buffer use of DS-MRR implementation
4004
 
                     else the value is not modified
4005
 
  @param cost   IN   Cost of default MRR implementation
4006
 
                OUT  If DS-MRR is choosen, cost of DS-MRR scan
4007
 
                     else the value is not modified
4008
 
 
4009
 
  @retval true   Default MRR implementation should be used
4010
 
  @retval false  DS-MRR implementation should be used
4011
 
*/
4012
 
 
4013
 
bool DsMrr_impl::choose_mrr_impl(uint32_t keyno, ha_rows rows, uint32_t *flags,
4014
 
                                 uint32_t *bufsz, COST_VECT *cost)
4015
 
{
4016
 
  COST_VECT dsmrr_cost;
4017
 
  bool res;
4018
 
  THD *thd= current_thd;
4019
 
  if ((thd->variables.optimizer_use_mrr == 2) || 
4020
 
      (*flags & HA_MRR_INDEX_ONLY) || (*flags & HA_MRR_SORTED) ||
4021
 
      (keyno == table->s->primary_key && 
4022
 
       h->primary_key_is_clustered()) || 
4023
 
       key_uses_partial_cols(keyno))
4024
 
  {
4025
 
    /* Use the default implementation */
4026
 
    *flags |= HA_MRR_USE_DEFAULT_IMPL;
4027
 
    return true;
4028
 
  }
4029
 
  
4030
 
  uint32_t add_len= table->key_info[keyno].key_length + h->ref_length; 
4031
 
  *bufsz -= add_len;
4032
 
  if (get_disk_sweep_mrr_cost(keyno, rows, *flags, bufsz, &dsmrr_cost))
4033
 
    return true;
4034
 
  *bufsz += add_len;
4035
 
  
4036
 
  bool force_dsmrr;
4037
 
  /* 
4038
 
    If @@optimizer_use_mrr==force, then set cost of DS-MRR to be minimum of
4039
 
    DS-MRR and Default implementations cost. This allows one to force use of
4040
 
    DS-MRR whenever it is applicable without affecting other cost-based
4041
 
    choices.
4042
 
  */
4043
 
  if ((force_dsmrr= (thd->variables.optimizer_use_mrr == 1)) &&
4044
 
      dsmrr_cost.total_cost() > cost->total_cost())
4045
 
    dsmrr_cost= *cost;
4046
 
 
4047
 
  if (force_dsmrr || dsmrr_cost.total_cost() <= cost->total_cost())
4048
 
  {
4049
 
    *flags &= ~HA_MRR_USE_DEFAULT_IMPL;  /* Use the DS-MRR implementation */
4050
 
    *flags &= ~HA_MRR_SORTED;          /* We will return unordered output */
4051
 
    *cost= dsmrr_cost;
4052
 
    res= false;
4053
 
  }
4054
 
  else
4055
 
  {
4056
 
    /* Use the default MRR implementation */
4057
 
    res= true;
4058
 
  }
4059
 
  return res;
4060
 
}
4061
 
 
4062
 
 
4063
 
static void get_sort_and_sweep_cost(Table *table, ha_rows nrows, COST_VECT *cost);
4064
 
 
4065
 
 
4066
 
/**
4067
 
  Get cost of DS-MRR scan
4068
 
 
4069
 
  @param keynr              Index to be used
4070
 
  @param rows               E(Number of rows to be scanned)
4071
 
  @param flags              Scan parameters (HA_MRR_* flags)
4072
 
  @param buffer_size INOUT  Buffer size
4073
 
  @param cost        OUT    The cost
4074
 
 
4075
 
  @retval false  OK
4076
 
  @retval true   Error, DS-MRR cannot be used (the buffer is too small
4077
 
                 for even 1 rowid)
4078
 
*/
4079
 
 
4080
 
bool DsMrr_impl::get_disk_sweep_mrr_cost(uint32_t keynr, ha_rows rows, uint32_t flags,
4081
 
                                         uint32_t *buffer_size, COST_VECT *cost)
4082
 
{
4083
 
  uint32_t max_buff_entries, elem_size;
4084
 
  ha_rows rows_in_full_step, rows_in_last_step;
4085
 
  uint32_t n_full_steps;
4086
 
  double index_read_cost;
4087
 
 
4088
 
  elem_size= h->ref_length + sizeof(void*) * (!test(flags & HA_MRR_NO_ASSOCIATION));
4089
 
  max_buff_entries = *buffer_size / elem_size;
4090
 
 
4091
 
  if (!max_buff_entries)
4092
 
    return true; /* Buffer has not enough space for even 1 rowid */
4093
 
 
4094
 
  /* 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 
4100
 
     - last iteration, with non-full buffer
4101
 
  */
4102
 
  rows_in_full_step= max_buff_entries;
4103
 
  rows_in_last_step= rows % max_buff_entries;
4104
 
  
4105
 
  /* Adjust buffer size if we expect to use only part of the buffer */
4106
 
  if (n_full_steps)
4107
 
  {
4108
 
    get_sort_and_sweep_cost(table, rows, cost);
4109
 
    cost->multiply(n_full_steps);
4110
 
  }
4111
 
  else
4112
 
  {
4113
 
    cost->zero();
4114
 
    *buffer_size= cmax((ulong)*buffer_size, 
4115
 
                      (size_t)(1.2*rows_in_last_step) * elem_size + 
4116
 
                      h->ref_length + table->key_info[keynr].key_length);
4117
 
  }
4118
 
  
4119
 
  COST_VECT last_step_cost;
4120
 
  get_sort_and_sweep_cost(table, rows_in_last_step, &last_step_cost);
4121
 
  cost->add(&last_step_cost);
4122
 
 
4123
 
  if (n_full_steps != 0)
4124
 
    cost->mem_cost= *buffer_size;
4125
 
  else
4126
 
    cost->mem_cost= (double)rows_in_last_step * elem_size;
4127
 
  
4128
 
  /* Total cost of all index accesses */
4129
 
  index_read_cost= h->index_only_read_time(keynr, (double)rows);
4130
 
  cost->add_io(index_read_cost, 1 /* Random seeks */);
4131
 
  return false;
4132
 
}
4133
 
 
4134
 
 
4135
 
/* 
4136
 
  Get cost of one sort-and-sweep step
4137
 
 
4138
 
  SYNOPSIS
4139
 
    get_sort_and_sweep_cost()
4140
 
      table       Table being accessed
4141
 
      nrows       Number of rows to be sorted and retrieved
4142
 
      cost   OUT  The cost
4143
 
 
4144
 
  DESCRIPTION
4145
 
    Get cost of these operations:
4146
 
     - sort an array of #nrows ROWIDs using qsort
4147
 
     - read #nrows records from table in a sweep.
4148
 
*/
4149
 
 
4150
 
static 
4151
 
void get_sort_and_sweep_cost(Table *table, ha_rows nrows, COST_VECT *cost)
4152
 
{
4153
 
  if (nrows)
4154
 
  {
4155
 
    get_sweep_read_cost(table, nrows, false, cost);
4156
 
    /* Add cost of qsort call: n * log2(n) * cost(rowid_comparison) */
4157
 
    double cmp_op= rows2double(nrows) * (1.0 / TIME_FOR_COMPARE_ROWID);
4158
 
    if (cmp_op < 3)
4159
 
      cmp_op= 3;
4160
 
    cost->cpu_cost += cmp_op * log2(cmp_op);
4161
 
  }
4162
 
  else
4163
 
    cost->zero();
 
2381
  return result;
4164
2382
}
4165
2383
 
4166
2384
 
4181
2399
  Time to move the disk head is proportional to head travel distance.
4182
2400
 
4183
2401
  Time to wait for the plate to rotate depends on whether the disk head
4184
 
  was moved or not. 
 
2402
  was moved or not.
4185
2403
 
4186
2404
  If disk head wasn't moved, the wait time is proportional to distance
4187
2405
  between the previous block and the block we're reading.
4192
2410
 
4193
2411
  Our cost units are "random disk seeks". The cost of random disk seek is
4194
2412
  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 
 
2413
  to access. We make it constant by introducing a fuzzy concept of "typical
4196
2414
  datafile length" (it's fuzzy as it's hard to tell whether it should
4197
2415
  include index file, temp.tables etc). Then random seek cost is:
4198
2416
 
4207
2425
  @param cost         OUT  The cost.
4208
2426
*/
4209
2427
 
4210
 
void get_sweep_read_cost(Table *table, ha_rows nrows, bool interrupted, 
 
2428
void get_sweep_read_cost(Table *table, ha_rows nrows, bool interrupted,
4211
2429
                         COST_VECT *cost)
4212
2430
{
4213
2431
  cost->zero();
4214
2432
  if (table->file->primary_key_is_clustered())
4215
2433
  {
4216
2434
    cost->io_count= table->file->read_time(table->s->primary_key,
4217
 
                                           (uint) nrows, nrows);
 
2435
                                           (uint32_t) nrows, nrows);
4218
2436
  }
4219
2437
  else
4220
2438
  {
4234
2452
                          DISK_SEEK_PROP_COST*n_blocks/busy_blocks);
4235
2453
    }
4236
2454
  }
4237
 
  return;
4238
2455
}
4239
2456
 
4240
2457
 
4263
2480
int handler::read_range_first(const key_range *start_key,
4264
2481
                              const key_range *end_key,
4265
2482
                              bool eq_range_arg,
4266
 
                              bool sorted  __attribute__((unused)))
 
2483
                              bool )
4267
2484
{
4268
2485
  int result;
4269
2486
 
4286
2503
                           start_key->keypart_map,
4287
2504
                           start_key->flag);
4288
2505
  if (result)
4289
 
    return((result == HA_ERR_KEY_NOT_FOUND) 
 
2506
    return((result == HA_ERR_KEY_NOT_FOUND)
4290
2507
                ? HA_ERR_END_OF_FILE
4291
2508
                : result);
4292
2509
 
4320
2537
  }
4321
2538
  result= index_next(table->record[0]);
4322
2539
  if (result)
4323
 
    return(result);
 
2540
    return result;
4324
2541
  return(compare_key(end_range) <= 0 ? 0 : HA_ERR_END_OF_FILE);
4325
2542
}
4326
2543
 
4368
2585
  return cmp;
4369
2586
}
4370
2587
 
4371
 
int handler::index_read_idx_map(unsigned char * buf, uint32_t index, const unsigned char * key,
 
2588
int handler::index_read_idx_map(unsigned char * buf, uint32_t index,
 
2589
                                const unsigned char * key,
4372
2590
                                key_part_map keypart_map,
4373
2591
                                enum ha_rkey_function find_flag)
4374
2592
{
4382
2600
  return error ?  error : error1;
4383
2601
}
4384
2602
 
4385
 
 
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,
 
2603
static bool stat_print(Session *session, const char *type, uint32_t type_len,
4456
2604
                       const char *file, uint32_t file_len,
4457
2605
                       const char *status, uint32_t status_len)
4458
2606
{
4459
 
  Protocol *protocol= thd->protocol;
4460
 
  protocol->prepare_for_resend();
4461
 
  protocol->store(type, type_len, system_charset_info);
4462
 
  protocol->store(file, file_len, system_charset_info);
4463
 
  protocol->store(status, status_len, system_charset_info);
4464
 
  if (protocol->write())
 
2607
  session->client->store(type, type_len);
 
2608
  session->client->store(file, file_len);
 
2609
  session->client->store(status, status_len);
 
2610
  if (session->client->flush())
4465
2611
    return true;
4466
2612
  return false;
4467
2613
}
4468
2614
 
4469
 
bool ha_show_status(THD *thd, handlerton *db_type, enum ha_stat_type stat)
 
2615
bool ha_show_status(Session *session, plugin::StorageEngine *engine, enum ha_stat_type stat)
4470
2616
{
4471
2617
  List<Item> field_list;
4472
 
  Protocol *protocol= thd->protocol;
4473
2618
  bool result;
4474
2619
 
4475
2620
  field_list.push_back(new Item_empty_string("Type",10));
4476
2621
  field_list.push_back(new Item_empty_string("Name",FN_REFLEN));
4477
2622
  field_list.push_back(new Item_empty_string("Status",10));
4478
2623
 
4479
 
  if (protocol->send_fields(&field_list,
4480
 
                            Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
 
2624
  if (session->client->sendFields(&field_list))
4481
2625
    return true;
4482
2626
 
4483
 
  result= db_type->show_status &&
4484
 
    db_type->show_status(db_type, thd, stat_print, stat) ? 1 : 0;
 
2627
  result= engine->show_status(session, stat_print, stat) ? 1 : 0;
4485
2628
 
4486
2629
  if (!result)
4487
 
    my_eof(thd);
 
2630
    session->my_eof();
4488
2631
  return result;
4489
2632
}
4490
2633
 
4501
2644
  - table is not mysql.event
4502
2645
*/
4503
2646
 
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
 
  {
 
2647
static bool log_row_for_replication(Table* table,
 
2648
                           const unsigned char *before_record,
 
2649
                           const unsigned char *after_record)
 
2650
{
 
2651
  ReplicationServices &replication_services= ReplicationServices::singleton();
 
2652
  Session *const session= table->in_use;
 
2653
 
 
2654
  switch (session->lex->sql_command)
 
2655
  {
 
2656
  case SQLCOM_REPLACE:
 
2657
  case SQLCOM_INSERT:
 
2658
  case SQLCOM_REPLACE_SELECT:
 
2659
  case SQLCOM_INSERT_SELECT:
 
2660
  case SQLCOM_CREATE_TABLE:
 
2661
    replication_services.insertRecord(session, table);
 
2662
    break;
 
2663
 
 
2664
  case SQLCOM_UPDATE:
 
2665
    replication_services.updateRecord(session, table, before_record, after_record);
 
2666
    break;
 
2667
 
 
2668
  case SQLCOM_DELETE:
 
2669
    replication_services.deleteRecord(session, table);
 
2670
    break;
 
2671
 
4595
2672
    /*
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.
 
2673
      For everything else we ignore the event (since it just involves a temp table)
4599
2674
    */
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
 
    }
 
2675
  default:
 
2676
    break;
4605
2677
  }
4606
 
  return error ? HA_ERR_RBR_LOGGING_FAILED : 0;
 
2678
 
 
2679
  return false; //error;
4607
2680
}
4608
2681
 
4609
 
int handler::ha_external_lock(THD *thd, int lock_type)
 
2682
int handler::ha_external_lock(Session *session, int lock_type)
4610
2683
{
4611
2684
  /*
4612
2685
    Whether this is lock or unlock, this should be true, and is to verify that
4619
2692
    We cache the table flags if the locking succeeded. Otherwise, we
4620
2693
    keep them as they were when they were fetched in ha_open().
4621
2694
  */
4622
 
  DRIZZLE_EXTERNAL_LOCK(lock_type);
4623
 
 
4624
 
  int error= external_lock(thd, lock_type);
 
2695
 
 
2696
  int error= external_lock(session, lock_type);
 
2697
 
4625
2698
  if (error == 0)
4626
2699
    cached_table_flags= table_flags();
4627
 
  return(error);
 
2700
  return error;
4628
2701
}
4629
2702
 
4630
2703
 
4634
2707
int handler::ha_reset()
4635
2708
{
4636
2709
  /* Check that we have called all proper deallocation functions */
4637
 
  assert((unsigned char*) table->def_read_set.bitmap +
 
2710
  assert((unsigned char*) table->def_read_set.getBitmap() +
4638
2711
              table->s->column_bitmap_size ==
4639
 
              (unsigned char*) table->def_write_set.bitmap);
4640
 
  assert(bitmap_is_set_all(&table->s->all_set));
 
2712
              (unsigned char*) table->def_write_set.getBitmap());
 
2713
  assert(table->s->all_set.isSetAll());
4641
2714
  assert(table->key_read == 0);
4642
2715
  /* ensure that ha_index_end / ha_rnd_end has been called */
4643
2716
  assert(inited == NONE);
4644
2717
  /* Free cache used by filesort */
4645
 
  free_io_cache(table);
 
2718
  table->free_io_cache();
4646
2719
  /* reset the bitmaps to point to defaults */
4647
2720
  table->default_column_bitmaps();
4648
2721
  return(reset());
4652
2725
int handler::ha_write_row(unsigned char *buf)
4653
2726
{
4654
2727
  int error;
4655
 
  Log_func *log_func= Write_rows_log_event::binlog_row_logging_function;
4656
 
  DRIZZLE_INSERT_ROW_START();
 
2728
 
 
2729
  /* 
 
2730
   * If we have a timestamp column, update it to the current time 
 
2731
   * 
 
2732
   * @TODO Technically, the below two lines can be take even further out of the
 
2733
   * handler interface and into the fill_record() method.
 
2734
   */
 
2735
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
 
2736
    table->timestamp_field->set_time();
4657
2737
 
4658
2738
  mark_trx_read_write();
4659
2739
 
4660
2740
  if (unlikely(error= write_row(buf)))
4661
 
    return(error);
4662
 
  if (unlikely(error= binlog_log_row(table, 0, buf, log_func)))
4663
 
    return(error); /* purecov: inspected */
4664
 
  DRIZZLE_INSERT_ROW_END();
4665
 
  return(0);
 
2741
  {
 
2742
    return error;
 
2743
  }
 
2744
 
 
2745
  if (unlikely(log_row_for_replication(table, 0, buf)))
 
2746
    return HA_ERR_RBR_LOGGING_FAILED;
 
2747
 
 
2748
  return 0;
4666
2749
}
4667
2750
 
4668
2751
 
4669
2752
int handler::ha_update_row(const unsigned char *old_data, unsigned char *new_data)
4670
2753
{
4671
2754
  int error;
4672
 
  Log_func *log_func= Update_rows_log_event::binlog_row_logging_function;
4673
2755
 
4674
2756
  /*
4675
2757
    Some storage engines require that the new record is in record[0]
4680
2762
  mark_trx_read_write();
4681
2763
 
4682
2764
  if (unlikely(error= update_row(old_data, new_data)))
4683
 
    return error;
4684
 
  if (unlikely(error= binlog_log_row(table, old_data, new_data, log_func)))
4685
 
    return error;
 
2765
  {
 
2766
    return error;
 
2767
  }
 
2768
 
 
2769
  if (unlikely(log_row_for_replication(table, old_data, new_data)))
 
2770
    return HA_ERR_RBR_LOGGING_FAILED;
 
2771
 
4686
2772
  return 0;
4687
2773
}
4688
2774
 
4689
2775
int handler::ha_delete_row(const unsigned char *buf)
4690
2776
{
4691
2777
  int error;
4692
 
  Log_func *log_func= Delete_rows_log_event::binlog_row_logging_function;
4693
2778
 
4694
2779
  mark_trx_read_write();
4695
2780
 
4696
2781
  if (unlikely(error= delete_row(buf)))
4697
2782
    return error;
4698
 
  if (unlikely(error= binlog_log_row(table, buf, 0, log_func)))
4699
 
    return error;
 
2783
 
 
2784
  if (unlikely(log_row_for_replication(table, buf, 0)))
 
2785
    return HA_ERR_RBR_LOGGING_FAILED;
 
2786
 
4700
2787
  return 0;
4701
2788
}
4702
 
 
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();
4715
 
}