~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/handler.cc

  • Committer: Brian Aker
  • Date: 2009-09-26 04:00:11 UTC
  • mfrom: (1126.12.1 trunk-nodebug)
  • Revision ID: brian@gaz-20090926040011-2qzxdcbpm1ibpkhl
Merge Lee

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
extern drizzled::ReplicationServices replication_services;
 
48
 
 
49
KEY_CREATE_INFO default_key_create_info= { HA_KEY_ALG_UNDEF, 0, {NULL,0} };
 
50
 
 
51
/* number of entries in storage_engines[] */
44
52
uint32_t total_ha= 0;
45
 
/* number of storage engines (from handlertons[]) that support 2pc */
 
53
/* number of storage engines (from storage_engines[]) that support 2pc */
46
54
uint32_t total_ha_2pc= 0;
47
55
/* size of savepoint storage area (see ha_init) */
48
56
uint32_t savepoint_alloc_size= 0;
49
57
 
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
58
const char *ha_row_type[] = {
58
59
  "", "FIXED", "DYNAMIC", "COMPRESSED", "REDUNDANT", "COMPACT", "PAGE", "?","?","?"
59
60
};
61
62
const char *tx_isolation_names[] =
62
63
{ "READ-UNCOMMITTED", "READ-COMMITTED", "REPEATABLE-READ", "SERIALIZABLE",
63
64
  NULL};
 
65
 
64
66
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
 
}
 
67
                               tx_isolation_names, NULL};
221
68
 
222
69
 
223
70
/**
236
83
 
237
84
  /* Allocate a pointer array for the error message strings. */
238
85
  /* Zerofill it to avoid uninitialized gaps. */
239
 
  if (! (errmsgs= (const char**) my_malloc(HA_ERR_ERRORS * sizeof(char*),
240
 
                                           MYF(MY_WME | MY_ZEROFILL))))
 
86
  if (! (errmsgs= (const char**) malloc(HA_ERR_ERRORS * sizeof(char*))))
241
87
    return 1;
 
88
  memset(errmsgs, 0, HA_ERR_ERRORS * sizeof(char *));
242
89
 
243
90
  /* Set the dedicated error messages. */
244
91
  SETMSG(HA_ERR_KEY_NOT_FOUND,          ER(ER_KEY_NOT_FOUND));
307
154
  return 0;
308
155
}
309
156
 
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
157
int ha_init()
424
158
{
425
159
  int error= 0;
430
164
    binary log (which is considered a transaction-capable storage engine in
431
165
    counting total_ha)
432
166
  */
433
 
  opt_using_transactions= total_ha>(uint32_t)opt_bin_log;
434
167
  savepoint_alloc_size+= sizeof(SAVEPOINT);
435
 
  return(error);
 
168
  return error;
436
169
}
437
170
 
438
171
int ha_end()
439
172
{
440
173
  int error= 0;
441
174
 
442
 
  /* 
 
175
  /*
443
176
    This should be eventualy based  on the graceful shutdown flag.
444
177
    So if flag is equal to HA_PANIC_CLOSE, the deallocate
445
178
    the errors.
447
180
  if (ha_finish_errors())
448
181
    error= 1;
449
182
 
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
 
}
 
183
  return error;
 
184
}
 
185
 
 
186
 
493
187
 
494
188
/* ========================================================================
495
189
 ======================= TRANSACTIONS ===================================*/
593
287
  -----------
594
288
 
595
289
  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
 
290
  session->transaction. This structure has two members of type
 
291
  Session_TRANS. These members correspond to the statement and
598
292
  normal transactions respectively:
599
293
 
600
 
  - thd->transaction.stmt contains a list of engines
 
294
  - session->transaction.stmt contains a list of engines
601
295
  that are participating in the given statement
602
 
  - thd->transaction.all contains a list of engines that
 
296
  - session->transaction.all contains a list of engines that
603
297
  have participated in any of the statement transactions started
604
298
  within the context of the normal transaction.
605
299
  Each element of the list contains a pointer to the storage
606
300
  engine, engine-specific transactional data, and engine-specific
607
301
  transaction flags.
608
302
 
609
 
  In autocommit mode thd->transaction.all is empty.
610
 
  Instead, data of thd->transaction.stmt is
 
303
  In autocommit mode session->transaction.all is empty.
 
304
  Instead, data of session->transaction.stmt is
611
305
  used to commit/rollback the normal transaction.
612
306
 
613
307
  The list of registered engines has a few important properties:
618
312
  Transaction life cycle
619
313
  ----------------------
620
314
 
621
 
  When a new connection is established, thd->transaction
 
315
  When a new connection is established, session->transaction
622
316
  members are initialized to an empty state.
623
317
  If a statement uses any tables, all affected engines
624
318
  are registered in the statement engine list. In
634
328
  and emptied again at the next statement's end.
635
329
 
636
330
  The normal transaction is committed in a similar way
637
 
  (by going over all engines in thd->transaction.all list)
 
331
  (by going over all engines in session->transaction.all list)
638
332
  but at different times:
639
333
  - upon COMMIT SQL statement is issued by the user
640
334
  - implicitly, by the server, at the beginning of a DDL statement
644
338
  - if the user has requested so, by issuing ROLLBACK SQL
645
339
  statement
646
340
  - if one of the storage engines requested a rollback
647
 
  by setting thd->transaction_rollback_request. This may
 
341
  by setting session->transaction_rollback_request. This may
648
342
  happen in case, e.g., when the transaction in the engine was
649
343
  chosen a victim of the internal deadlock resolution algorithm
650
344
  and rolled back internally. When such a situation happens, there
664
358
  The remaining rare cases when the server explicitly has
665
359
  to commit the statement transaction prior to committing the normal
666
360
  one cover error-handling scenarios (see for example
667
 
  SQLCOM_LOCK_TABLES).
 
361
  ?).
668
362
 
669
363
  When committing a statement or a normal transaction, the server
670
364
  either uses the two-phase commit protocol, or issues a commit
671
365
  in each engine independently. The two-phase commit protocol
672
366
  is used only if:
673
367
  - all participating engines support two-phase commit (provide
674
 
    handlerton::prepare PSEA API call) and
 
368
    StorageEngine::prepare PSEA API call) and
675
369
  - transactions in at least two engines modify data (i.e. are
676
370
  not read-only).
677
371
 
686
380
  transactions of other participants.
687
381
 
688
382
  After the normal transaction has been committed,
689
 
  thd->transaction.all list is cleared.
 
383
  session->transaction.all list is cleared.
690
384
 
691
385
  When a connection is closed, the current normal transaction, if
692
386
  any, is rolled back.
735
429
 
736
430
  At the end of a statement, server call
737
431
  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().
 
432
  invokes StorageEngine::prepare() for every involved engine.
 
433
  Prepare is followed by a call to StorageEngine::commit_one_phase()
 
434
  If a one-phase commit will suffice, StorageEngine::prepare() is not
 
435
  invoked and the server only calls StorageEngine::commit_one_phase().
742
436
  At statement commit, the statement-related read-write engine
743
437
  flag is propagated to the corresponding flag in the normal
744
438
  transaction.  When the commit is complete, the list of registered
750
444
  ---------------------------------------------------
751
445
 
752
446
  DDLs and operations with non-transactional engines
753
 
  do not "register" in thd->transaction lists, and thus do not
 
447
  do not "register" in session->transaction lists, and thus do not
754
448
  modify the transaction state. Besides, each DDL in
755
449
  MySQL is prefixed with an implicit normal transaction commit
756
 
  (a call to end_active_trans()), and thus leaves nothing
 
450
  (a call to Session::endActiveTransaction()), and thus leaves nothing
757
451
  to modify.
758
452
  However, as it has been pointed out with CREATE TABLE .. SELECT,
759
453
  some DDL statements can start a *new* transaction.
797
491
    times per transaction.
798
492
 
799
493
*/
800
 
void trans_register_ha(THD *thd, bool all, handlerton *ht_arg)
 
494
void trans_register_ha(Session *session, bool all, StorageEngine *engine)
801
495
{
802
 
  THD_TRANS *trans;
 
496
  Session_TRANS *trans;
803
497
  Ha_trx_info *ha_info;
804
498
 
805
499
  if (all)
806
500
  {
807
 
    trans= &thd->transaction.all;
808
 
    thd->server_status|= SERVER_STATUS_IN_TRANS;
 
501
    trans= &session->transaction.all;
 
502
    session->server_status|= SERVER_STATUS_IN_TRANS;
809
503
  }
810
504
  else
811
 
    trans= &thd->transaction.stmt;
 
505
    trans= &session->transaction.stmt;
812
506
 
813
 
  ha_info= thd->ha_data[ht_arg->slot].ha_info + static_cast<unsigned>(all);
 
507
  ha_info= session->ha_data[engine->getSlot()].ha_info + static_cast<unsigned>(all);
814
508
 
815
509
  if (ha_info->is_started())
816
510
    return; /* already registered, return */
817
511
 
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);
 
512
  ha_info->register_ha(trans, engine);
 
513
 
 
514
  trans->no_2pc|= not engine->has_2pc();
 
515
  if (session->transaction.xid_state.xid.is_null())
 
516
    session->transaction.xid_state.xid.set(session->query_id);
864
517
}
865
518
 
866
519
/**
879
532
 
880
533
static
881
534
bool
882
 
ha_check_and_coalesce_trx_read_only(THD *thd, Ha_trx_info *ha_list,
 
535
ha_check_and_coalesce_trx_read_only(Session *session, Ha_trx_info *ha_list,
883
536
                                    bool all)
884
537
{
885
538
  /* The number of storage engines that have actual changes. */
893
546
 
894
547
    if (! all)
895
548
    {
896
 
      Ha_trx_info *ha_info_all= &thd->ha_data[ha_info->ht()->slot].ha_info[1];
 
549
      Ha_trx_info *ha_info_all= &session->ha_data[ha_info->engine()->getSlot()].ha_info[1];
897
550
      assert(ha_info != ha_info_all);
898
551
      /*
899
552
        Merge read-only/read-write information about statement
900
553
        transaction to its enclosing normal transaction. Do this
901
554
        only if in a real transaction -- that is, if we know
902
 
        that ha_info_all is registered in thd->transaction.all.
 
555
        that ha_info_all is registered in session->transaction.all.
903
556
        Since otherwise we only clutter the normal transaction flags.
904
557
      */
905
558
      if (ha_info_all->is_started()) /* false if autocommit. */
933
586
    stored functions or triggers. So we simply do nothing now.
934
587
    TODO: This should be fixed in later ( >= 5.1) releases.
935
588
*/
936
 
int ha_commit_trans(THD *thd, bool all)
 
589
int ha_commit_trans(Session *session, bool all)
937
590
{
938
591
  int error= 0, cookie= 0;
939
592
  /*
940
593
    'all' means that this is either an explicit commit issued by
941
594
    user, or an implicit commit issued by a DDL.
942
595
  */
943
 
  THD_TRANS *trans= all ? &thd->transaction.all : &thd->transaction.stmt;
944
 
  bool is_real_trans= all || thd->transaction.all.ha_list == 0;
 
596
  Session_TRANS *trans= all ? &session->transaction.all : &session->transaction.stmt;
 
597
  bool is_real_trans= all || session->transaction.all.ha_list == 0;
945
598
  Ha_trx_info *ha_info= trans->ha_list;
946
 
  my_xid xid= thd->transaction.xid_state.xid.get_my_xid();
947
599
 
948
600
  /*
949
601
    We must not commit the normal transaction if a statement
951
603
    flags will not get propagated to its normal transaction's
952
604
    counterpart.
953
605
  */
954
 
  assert(thd->transaction.stmt.ha_list == NULL ||
955
 
              trans == &thd->transaction.stmt);
 
606
  assert(session->transaction.stmt.ha_list == NULL ||
 
607
              trans == &session->transaction.stmt);
956
608
 
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
609
  if (ha_info)
978
610
  {
979
611
    bool must_2pc;
980
612
 
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);
 
613
    if (is_real_trans && wait_if_global_read_lock(session, 0, 0))
 
614
    {
 
615
      ha_rollback_trans(session, all);
 
616
      return 1;
 
617
    }
 
618
 
 
619
    must_2pc= ha_check_and_coalesce_trx_read_only(session, ha_info, all);
999
620
 
1000
621
    if (!trans->no_2pc && must_2pc)
1001
622
    {
1002
623
      for (; ha_info && !error; ha_info= ha_info->next())
1003
624
      {
1004
625
        int err;
1005
 
        handlerton *ht= ha_info->ht();
 
626
        StorageEngine *engine= ha_info->engine();
1006
627
        /*
1007
628
          Do not call two-phase commit if this particular
1008
629
          transaction is read-only. This allows for simpler
1014
635
          Sic: we know that prepare() is not NULL since otherwise
1015
636
          trans->no_2pc would have been set.
1016
637
        */
1017
 
        if ((err= ht->prepare(ht, thd, all)))
 
638
        if ((err= engine->prepare(session, all)))
1018
639
        {
1019
640
          my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
1020
641
          error= 1;
1021
642
        }
1022
 
        status_var_increment(thd->status_var.ha_prepare_count);
 
643
        status_var_increment(session->status_var.ha_prepare_count);
1023
644
      }
1024
 
      if (error || (is_real_trans && xid &&
1025
 
                    (error= !(cookie= tc_log->log_xid(thd, xid)))))
 
645
      if (error)
1026
646
      {
1027
 
        ha_rollback_trans(thd, all);
 
647
        ha_rollback_trans(session, all);
1028
648
        error= 1;
1029
649
        goto end;
1030
650
      }
1031
651
    }
1032
 
    error=ha_commit_one_phase(thd, all) ? (cookie ? 2 : 1) : 0;
1033
 
    if (cookie)
1034
 
      tc_log->unlog(cookie, xid);
 
652
    error=ha_commit_one_phase(session, all) ? (cookie ? 2 : 1) : 0;
1035
653
end:
1036
654
    if (is_real_trans)
1037
 
      start_waiting_global_read_lock(thd);
 
655
      start_waiting_global_read_lock(session);
1038
656
  }
1039
 
  return(error);
 
657
  return error;
1040
658
}
1041
659
 
1042
660
/**
1043
661
  @note
1044
662
  This function does not care about global read lock. A caller should.
1045
663
*/
1046
 
int ha_commit_one_phase(THD *thd, bool all)
 
664
int ha_commit_one_phase(Session *session, bool all)
1047
665
{
1048
666
  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;
 
667
  Session_TRANS *trans=all ? &session->transaction.all : &session->transaction.stmt;
 
668
  bool is_real_trans=all || session->transaction.all.ha_list == 0;
1051
669
  Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
1052
670
  if (ha_info)
1053
671
  {
1054
672
    for (; ha_info; ha_info= ha_info_next)
1055
673
    {
1056
674
      int err;
1057
 
      handlerton *ht= ha_info->ht();
1058
 
      if ((err= ht->commit(ht, thd, all)))
 
675
      StorageEngine *engine= ha_info->engine();
 
676
      if ((err= engine->commit(session, all)))
1059
677
      {
1060
678
        my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
1061
679
        error=1;
1062
680
      }
1063
 
      status_var_increment(thd->status_var.ha_commit_count);
 
681
      status_var_increment(session->status_var.ha_commit_count);
1064
682
      ha_info_next= ha_info->next();
1065
683
      ha_info->reset(); /* keep it conveniently zero-filled */
1066
684
    }
1067
685
    trans->ha_list= 0;
1068
686
    trans->no_2pc=0;
1069
687
    if (is_real_trans)
1070
 
      thd->transaction.xid_state.xid.null();
 
688
      session->transaction.xid_state.xid.null();
1071
689
    if (all)
1072
690
    {
1073
 
      thd->variables.tx_isolation=thd->session_tx_isolation;
1074
 
      thd->transaction.cleanup();
 
691
      session->variables.tx_isolation=session->session_tx_isolation;
 
692
      session->transaction.cleanup();
1075
693
    }
1076
694
  }
1077
 
  return(error);
 
695
  return error;
1078
696
}
1079
697
 
1080
698
 
1081
 
int ha_rollback_trans(THD *thd, bool all)
 
699
int ha_rollback_trans(Session *session, bool all)
1082
700
{
1083
701
  int error=0;
1084
 
  THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt;
 
702
  Session_TRANS *trans=all ? &session->transaction.all : &session->transaction.stmt;
1085
703
  Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
1086
 
  bool is_real_trans=all || thd->transaction.all.ha_list == 0;
 
704
  bool is_real_trans=all || session->transaction.all.ha_list == 0;
1087
705
 
1088
706
  /*
1089
707
    We must not rollback the normal transaction if a statement
1090
708
    transaction is pending.
1091
709
  */
1092
 
  assert(thd->transaction.stmt.ha_list == NULL ||
1093
 
              trans == &thd->transaction.stmt);
 
710
  assert(session->transaction.stmt.ha_list == NULL ||
 
711
              trans == &session->transaction.stmt);
1094
712
 
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
713
  if (ha_info)
1109
714
  {
1110
715
    for (; ha_info; ha_info= ha_info_next)
1111
716
    {
1112
717
      int err;
1113
 
      handlerton *ht= ha_info->ht();
1114
 
      if ((err= ht->rollback(ht, thd, all)))
 
718
      StorageEngine *engine= ha_info->engine();
 
719
      if ((err= engine->rollback(session, all)))
1115
720
      { // cannot happen
1116
721
        my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
1117
722
        error=1;
1118
723
      }
1119
 
      status_var_increment(thd->status_var.ha_rollback_count);
 
724
      status_var_increment(session->status_var.ha_rollback_count);
1120
725
      ha_info_next= ha_info->next();
1121
726
      ha_info->reset(); /* keep it conveniently zero-filled */
1122
727
    }
1123
728
    trans->ha_list= 0;
1124
729
    trans->no_2pc=0;
1125
730
    if (is_real_trans)
1126
 
      thd->transaction.xid_state.xid.null();
 
731
      session->transaction.xid_state.xid.null();
1127
732
    if (all)
1128
733
    {
1129
 
      thd->variables.tx_isolation=thd->session_tx_isolation;
1130
 
      thd->transaction.cleanup();
 
734
      session->variables.tx_isolation=session->session_tx_isolation;
 
735
      session->transaction.cleanup();
1131
736
    }
1132
737
  }
1133
738
  if (all)
1134
 
    thd->transaction_rollback_request= false;
 
739
    session->transaction_rollback_request= false;
1135
740
 
1136
741
  /*
1137
742
    If a non-transactional table was updated, warn; don't warn if this is a
1142
747
    the error log; but we don't want users to wonder why they have this
1143
748
    message in the error log, so we don't send it.
1144
749
  */
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,
 
750
  if (is_real_trans && session->transaction.all.modified_non_trans_table && session->killed != Session::KILL_CONNECTION)
 
751
    push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1148
752
                 ER_WARNING_NOT_COMPLETE_ROLLBACK,
1149
753
                 ER(ER_WARNING_NOT_COMPLETE_ROLLBACK));
1150
 
  return(error);
 
754
  return error;
1151
755
}
1152
756
 
1153
757
/**
1161
765
    the user has used LOCK TABLES then that mechanism does not know to do the
1162
766
    commit.
1163
767
*/
1164
 
int ha_autocommit_or_rollback(THD *thd, int error)
 
768
int ha_autocommit_or_rollback(Session *session, int error)
1165
769
{
1166
 
  if (thd->transaction.stmt.ha_list)
 
770
  if (session->transaction.stmt.ha_list)
1167
771
  {
1168
772
    if (!error)
1169
773
    {
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);
 
774
      if (ha_commit_trans(session, 0))
 
775
        error= 1;
 
776
    }
 
777
    else
 
778
    {
 
779
      (void) ha_rollback_trans(session, 0);
 
780
      if (session->transaction_rollback_request)
 
781
        (void) ha_rollback(session);
 
782
    }
 
783
 
 
784
    session->variables.tx_isolation=session->session_tx_isolation;
 
785
  }
 
786
 
 
787
  return error;
1366
788
}
1367
789
 
1368
790
/**
1373
795
    so mysql_xa_recover does not filter XID's to ensure uniqueness.
1374
796
    It can be easily fixed later, if necessary.
1375
797
*/
1376
 
bool mysql_xa_recover(THD *thd)
 
798
bool mysql_xa_recover(Session *session)
1377
799
{
1378
800
  List<Item> field_list;
1379
 
  Protocol *protocol= thd->protocol;
1380
 
  int i=0;
 
801
  int i= 0;
1381
802
  XID_STATE *xs;
1382
803
 
1383
804
  field_list.push_back(new Item_int("formatID", 0, MY_INT32_NUM_DECIMAL_DIGITS));
1385
806
  field_list.push_back(new Item_int("bqual_length", 0, MY_INT32_NUM_DECIMAL_DIGITS));
1386
807
  field_list.push_back(new Item_empty_string("data",XIDDATASIZE));
1387
808
 
1388
 
  if (protocol->send_fields(&field_list,
1389
 
                            Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
1390
 
    return(1);
 
809
  if (session->client->sendFields(&field_list))
 
810
    return 1;
1391
811
 
1392
812
  pthread_mutex_lock(&LOCK_xid_cache);
1393
813
  while ((xs= (XID_STATE*)hash_element(&xid_cache, i++)))
1394
814
  {
1395
815
    if (xs->xa_state==XA_PREPARED)
1396
816
    {
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())
 
817
      session->client->store((int64_t)xs->xid.formatID);
 
818
      session->client->store((int64_t)xs->xid.gtrid_length);
 
819
      session->client->store((int64_t)xs->xid.bqual_length);
 
820
      session->client->store(xs->xid.data,
 
821
                             xs->xid.gtrid_length+xs->xid.bqual_length);
 
822
      if (session->client->flush())
1404
823
      {
1405
824
        pthread_mutex_unlock(&LOCK_xid_cache);
1406
 
        return(1);
 
825
        return 1;
1407
826
      }
1408
827
    }
1409
828
  }
1410
829
 
1411
830
  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
 
 
 
831
  session->my_eof();
1451
832
  return 0;
1452
833
}
1453
834
 
1454
 
int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv)
 
835
 
 
836
int ha_rollback_to_savepoint(Session *session, SAVEPOINT *sv)
1455
837
{
1456
 
  int error=0;
1457
 
  THD_TRANS *trans= (thd->in_sub_stmt ? &thd->transaction.stmt :
1458
 
                                        &thd->transaction.all);
 
838
  int error= 0;
 
839
  Session_TRANS *trans= &session->transaction.all;
1459
840
  Ha_trx_info *ha_info, *ha_info_next;
1460
841
 
1461
842
  trans->no_2pc=0;
1466
847
  for (ha_info= sv->ha_list; ha_info; ha_info= ha_info->next())
1467
848
  {
1468
849
    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)))
 
850
    StorageEngine *engine= ha_info->engine();
 
851
    assert(engine);
 
852
    if ((err= engine->savepoint_rollback(session,
 
853
                                         (void *)(sv+1))))
1474
854
    { // cannot happen
1475
855
      my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
1476
 
      error=1;
 
856
      error= 1;
1477
857
    }
1478
 
    status_var_increment(thd->status_var.ha_savepoint_rollback_count);
1479
 
    trans->no_2pc|= ht->prepare == 0;
 
858
    status_var_increment(session->status_var.ha_savepoint_rollback_count);
 
859
    trans->no_2pc|= not engine->has_2pc();
1480
860
  }
1481
861
  /*
1482
862
    rolling back the transaction in all storage engines that were not part of
1486
866
       ha_info= ha_info_next)
1487
867
  {
1488
868
    int err;
1489
 
    handlerton *ht= ha_info->ht();
1490
 
    if ((err= ht->rollback(ht, thd, !thd->in_sub_stmt)))
 
869
    StorageEngine *engine= ha_info->engine();
 
870
    if ((err= engine->rollback(session, !(0))))
1491
871
    { // cannot happen
1492
872
      my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
1493
 
      error=1;
 
873
      error= 1;
1494
874
    }
1495
 
    status_var_increment(thd->status_var.ha_rollback_count);
 
875
    status_var_increment(session->status_var.ha_rollback_count);
1496
876
    ha_info_next= ha_info->next();
1497
877
    ha_info->reset(); /* keep it conveniently zero-filled */
1498
878
  }
1499
879
  trans->ha_list= sv->ha_list;
1500
 
  return(error);
 
880
  return error;
1501
881
}
1502
882
 
1503
883
/**
1506
886
  section "4.33.4 SQL-statements and transaction states",
1507
887
  SAVEPOINT is *not* transaction-initiating SQL-statement
1508
888
*/
1509
 
int ha_savepoint(THD *thd, SAVEPOINT *sv)
 
889
int ha_savepoint(Session *session, SAVEPOINT *sv)
1510
890
{
1511
 
  int error=0;
1512
 
  THD_TRANS *trans= (thd->in_sub_stmt ? &thd->transaction.stmt :
1513
 
                                        &thd->transaction.all);
 
891
  int error= 0;
 
892
  Session_TRANS *trans= &session->transaction.all;
1514
893
  Ha_trx_info *ha_info= trans->ha_list;
1515
894
  for (; ha_info; ha_info= ha_info->next())
1516
895
  {
1517
896
    int err;
1518
 
    handlerton *ht= ha_info->ht();
1519
 
    assert(ht);
1520
 
    if (! ht->savepoint_set)
 
897
    StorageEngine *engine= ha_info->engine();
 
898
    assert(engine);
 
899
#ifdef NOT_IMPLEMENTED /*- TODO (examine this againt the original code base) */
 
900
    if (! engine->savepoint_set)
1521
901
    {
1522
902
      my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "SAVEPOINT");
1523
 
      error=1;
 
903
      error= 1;
1524
904
      break;
1525
 
    }
1526
 
    if ((err= ht->savepoint_set(ht, thd, (unsigned char *)(sv+1)+ht->savepoint_offset)))
 
905
    } 
 
906
#endif
 
907
    if ((err= engine->savepoint_set(session, (void *)(sv+1))))
1527
908
    { // cannot happen
1528
909
      my_error(ER_GET_ERRNO, MYF(0), err);
1529
 
      error=1;
 
910
      error= 1;
1530
911
    }
1531
 
    status_var_increment(thd->status_var.ha_savepoint_count);
 
912
    status_var_increment(session->status_var.ha_savepoint_count);
1532
913
  }
1533
914
  /*
1534
915
    Remember the list of registered storage engines. All new
1535
916
    engines are prepended to the beginning of the list.
1536
917
  */
1537
918
  sv->ha_list= trans->ha_list;
1538
 
  return(error);
 
919
  return error;
1539
920
}
1540
921
 
1541
 
int ha_release_savepoint(THD *thd, SAVEPOINT *sv)
 
922
int ha_release_savepoint(Session *session, SAVEPOINT *sv)
1542
923
{
1543
 
  int error=0;
 
924
  int error= 0;
1544
925
  Ha_trx_info *ha_info= sv->ha_list;
1545
926
 
1546
927
  for (; ha_info; ha_info= ha_info->next())
1547
928
  {
1548
929
    int err;
1549
 
    handlerton *ht= ha_info->ht();
 
930
    StorageEngine *engine= ha_info->engine();
1550
931
    /* 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)))
 
932
    assert(engine);
 
933
    if ((err= engine->savepoint_release(session,
 
934
                                        (void *)(sv+1))))
1556
935
    { // cannot happen
1557
936
      my_error(ER_GET_ERRNO, MYF(0), err);
1558
 
      error=1;
 
937
      error= 1;
1559
938
    }
1560
939
  }
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
 
}
 
940
  return error;
 
941
}
 
942
 
 
943
 
 
944
 
 
945
 
1732
946
 
1733
947
/****************************************************************************
1734
948
** General handler functions
1735
949
****************************************************************************/
 
950
handler::~handler(void)
 
951
{
 
952
  assert(locked == false);
 
953
  /* TODO: assert(inited == NONE); */
 
954
}
 
955
 
 
956
 
1736
957
handler *handler::clone(MEM_ROOT *mem_root)
1737
958
{
1738
959
  handler *new_handler= get_new_handler(table->s, mem_root, table->s->db_type());
1739
960
  /*
1740
961
    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 
 
962
    on this->table->mem_root and we will not be able to reclaim that memory
1742
963
    when the clone handler object is destroyed.
1743
964
  */
1744
965
  if (!(new_handler->ref= (unsigned char*) alloc_root(mem_root, ALIGN_SIZE(ref_length)*2)))
1751
972
  return NULL;
1752
973
}
1753
974
 
1754
 
 
 
975
int handler::ha_index_init(uint32_t idx, bool sorted)
 
976
{
 
977
  int result;
 
978
  assert(inited == NONE);
 
979
  if (!(result= index_init(idx, sorted)))
 
980
    inited=INDEX;
 
981
  end_range= NULL;
 
982
  return result;
 
983
}
 
984
 
 
985
int handler::ha_index_end()
 
986
{
 
987
  assert(inited==INDEX);
 
988
  inited=NONE;
 
989
  end_range= NULL;
 
990
  return(index_end());
 
991
}
 
992
 
 
993
int handler::ha_rnd_init(bool scan)
 
994
{
 
995
  int result;
 
996
  assert(inited==NONE || (inited==RND && scan));
 
997
  inited= (result= rnd_init(scan)) ? NONE: RND;
 
998
 
 
999
  return result;
 
1000
}
 
1001
 
 
1002
int handler::ha_rnd_end()
 
1003
{
 
1004
  assert(inited==RND);
 
1005
  inited=NONE;
 
1006
  return(rnd_end());
 
1007
}
 
1008
 
 
1009
int handler::ha_index_or_rnd_end()
 
1010
{
 
1011
  return inited == INDEX ? ha_index_end() : inited == RND ? ha_rnd_end() : 0;
 
1012
}
 
1013
 
 
1014
handler::Table_flags handler::ha_table_flags() const
 
1015
{
 
1016
  return cached_table_flags;
 
1017
}
 
1018
 
 
1019
void handler::ha_start_bulk_insert(ha_rows rows)
 
1020
{
 
1021
  estimation_rows_to_insert= rows;
 
1022
  start_bulk_insert(rows);
 
1023
}
 
1024
 
 
1025
int handler::ha_end_bulk_insert()
 
1026
{
 
1027
  estimation_rows_to_insert= 0;
 
1028
  return end_bulk_insert();
 
1029
}
 
1030
 
 
1031
void handler::change_table_ptr(Table *table_arg, TableShare *share)
 
1032
{
 
1033
  table= table_arg;
 
1034
  table_share= share;
 
1035
}
 
1036
 
 
1037
const key_map *handler::keys_to_use_for_scanning()
 
1038
{
 
1039
  return &key_map_empty;
 
1040
}
 
1041
 
 
1042
bool handler::has_transactions()
 
1043
{
 
1044
  return (ha_table_flags() & HA_NO_TRANSACTIONS) == 0;
 
1045
}
1755
1046
 
1756
1047
void handler::ha_statistic_increment(ulong SSV::*offset) const
1757
1048
{
1758
1049
  status_var_increment(table->in_use->status_var.*offset);
1759
1050
}
1760
1051
 
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
 
}
 
1052
void **handler::ha_data(Session *session) const
 
1053
{
 
1054
  return session_ha_data(session, engine);
 
1055
}
 
1056
 
 
1057
Session *handler::ha_session(void) const
 
1058
{
 
1059
  assert(!table || !table->in_use || table->in_use == current_session);
 
1060
  return (table && table->in_use) ? table->in_use : current_session;
 
1061
}
 
1062
 
 
1063
 
 
1064
bool handler::is_fatal_error(int error, uint32_t flags)
 
1065
{
 
1066
  if (!error ||
 
1067
      ((flags & HA_CHECK_DUP_KEY) &&
 
1068
       (error == HA_ERR_FOUND_DUPP_KEY ||
 
1069
        error == HA_ERR_FOUND_DUPP_UNIQUE)))
 
1070
    return false;
 
1071
  return true;
 
1072
}
 
1073
 
 
1074
 
 
1075
ha_rows handler::records() { return stats.records; }
1771
1076
 
1772
1077
/**
1773
1078
  Open database-handler.
1804
1109
    (void) extra(HA_EXTRA_NO_READCHECK);        // Not needed in SQL
1805
1110
 
1806
1111
    /* ref is already allocated for us if we're called from handler::clone() */
1807
 
    if (!ref && !(ref= (unsigned char*) alloc_root(&table->mem_root, 
 
1112
    if (!ref && !(ref= (unsigned char*) alloc_root(&table->mem_root,
1808
1113
                                          ALIGN_SIZE(ref_length)*2)))
1809
1114
    {
1810
1115
      close();
1814
1119
      dup_ref=ref+ALIGN_SIZE(ref_length);
1815
1120
    cached_table_flags= table_flags();
1816
1121
  }
1817
 
  return(error);
 
1122
  return error;
1818
1123
}
1819
1124
 
1820
1125
/**
1830
1135
 
1831
1136
  position(record);
1832
1137
  if (inited && (error= ha_index_end()))
1833
 
    return(error);
 
1138
    return error;
1834
1139
  if ((error= ha_rnd_init(false)))
1835
 
    return(error);
 
1140
    return error;
1836
1141
 
1837
 
  return(rnd_pos(record, ref));
 
1142
  return rnd_pos(record, ref);
1838
1143
}
1839
1144
 
1840
1145
/**
1868
1173
    error=index_first(buf);
1869
1174
    (void) ha_index_end();
1870
1175
  }
1871
 
  return(error);
 
1176
  return error;
1872
1177
}
1873
1178
 
1874
1179
/**
1898
1203
void handler::adjust_next_insert_id_after_explicit_value(uint64_t nr)
1899
1204
{
1900
1205
  /*
1901
 
    If we have set THD::next_insert_id previously and plan to insert an
 
1206
    If we have set Session::next_insert_id previously and plan to insert an
1902
1207
    explicitely-specified value larger than this, we need to increase
1903
 
    THD::next_insert_id to be greater than the explicit value.
 
1208
    Session::next_insert_id to be greater than the explicit value.
1904
1209
  */
1905
1210
  if ((next_insert_id > 0) && (nr >= next_insert_id))
1906
1211
    set_next_insert_id(compute_next_insert_id(nr, &table->in_use->variables));
1948
1253
 
1949
1254
  Updates columns with type NEXT_NUMBER if:
1950
1255
 
1951
 
  - If column value is set to NULL (in which case
1952
 
    auto_increment_field_not_null is 0)
 
1256
  - If column value is set to NULL (in which case auto_increment_field_not_null is false)
1953
1257
  - If column is set to 0 and (sql_mode & MODE_NO_AUTO_VALUE_ON_ZERO) is not
1954
1258
    set. In the future we will only set NEXT_NUMBER fields if one sets them
1955
1259
    to NULL (or they are not included in the insert list).
1976
1280
    again to reserve a new interval.
1977
1281
 
1978
1282
  - In both cases, the reserved intervals are remembered in
1979
 
    thd->auto_inc_intervals_in_cur_stmt_for_binlog if statement-based
 
1283
    session->auto_inc_intervals_in_cur_stmt_for_binlog if statement-based
1980
1284
    binlogging; the last reserved interval is remembered in
1981
1285
    auto_inc_interval_for_cur_row.
1982
1286
 
1990
1294
    start counting from the inserted value.
1991
1295
 
1992
1296
    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
 
1297
    with a value, session->next_insert_id is filled with the value to use for the
1994
1298
    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
 
1299
    session->insert_id_for_cur_row, if get_auto_increment() was called
 
1300
    session->auto_inc_interval_for_cur_row is modified, if that interval is not
 
1301
    present in session->auto_inc_intervals_in_cur_stmt_for_binlog it is added to
1998
1302
    this list.
1999
1303
 
2000
1304
  @todo
2021
1325
{
2022
1326
  uint64_t nr, nb_reserved_values;
2023
1327
  bool append= false;
2024
 
  THD *thd= table->in_use;
2025
 
  struct system_variables *variables= &thd->variables;
 
1328
  Session *session= table->in_use;
 
1329
  struct system_variables *variables= &session->variables;
2026
1330
 
2027
1331
  /*
2028
1332
    next_insert_id is a "cursor" into the reserved interval, it may go greater
2030
1334
  */
2031
1335
  assert(next_insert_id >= auto_inc_interval_for_cur_row.minimum());
2032
1336
 
2033
 
  if ((nr= table->next_number_field->val_int()) != 0)
 
1337
  /* We check if auto_increment_field_not_null is false
 
1338
     for an auto increment column, not a magic value like NULL is.
 
1339
     same as sql_mode=NO_AUTO_VALUE_ON_ZERO */
 
1340
 
 
1341
  if ((nr= table->next_number_field->val_int()) != 0
 
1342
      || table->auto_increment_field_not_null)
2034
1343
  {
2035
1344
    /*
2036
1345
      Update next_insert_id if we had already generated a value in this
2040
1349
    */
2041
1350
    adjust_next_insert_id_after_explicit_value(nr);
2042
1351
    insert_id_for_cur_row= 0; // didn't generate anything
2043
 
    return(0);
 
1352
 
 
1353
    return 0;
2044
1354
  }
2045
1355
 
2046
1356
  if ((nr= next_insert_id) >= auto_inc_interval_for_cur_row.maximum())
2047
1357
  {
2048
1358
    /* next_insert_id is beyond what is reserved, so we reserve more. */
2049
1359
    const Discrete_interval *forced=
2050
 
      thd->auto_inc_intervals_forced.get_next();
 
1360
      session->auto_inc_intervals_forced.get_next();
2051
1361
    if (forced != NULL)
2052
1362
    {
2053
1363
      nr= forced->minimum();
2060
1370
        handler::ha_start_bulk_insert(); if 0 it means "unknown".
2061
1371
      */
2062
1372
      uint32_t nb_already_reserved_intervals=
2063
 
        thd->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements();
 
1373
        session->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements();
2064
1374
      uint64_t nb_desired_values;
2065
1375
      /*
2066
1376
        If an estimation was given to the engine:
2081
1391
        /* avoid overflow in formula, with this if() */
2082
1392
        if (nb_already_reserved_intervals <= AUTO_INC_DEFAULT_NB_MAX_BITS)
2083
1393
        {
2084
 
          nb_desired_values= AUTO_INC_DEFAULT_NB_ROWS * 
 
1394
          nb_desired_values= AUTO_INC_DEFAULT_NB_ROWS *
2085
1395
            (1 << nb_already_reserved_intervals);
2086
 
          set_if_smaller(nb_desired_values, AUTO_INC_DEFAULT_NB_MAX);
 
1396
          set_if_smaller(nb_desired_values, (uint64_t)AUTO_INC_DEFAULT_NB_MAX);
2087
1397
        }
2088
1398
        else
2089
1399
          nb_desired_values= AUTO_INC_DEFAULT_NB_MAX;
2094
1404
                         nb_desired_values, &nr,
2095
1405
                         &nb_reserved_values);
2096
1406
      if (nr == ~(uint64_t) 0)
2097
 
        return(HA_ERR_AUTOINC_READ_FAILED);  // Mark failure
2098
 
      
 
1407
        return HA_ERR_AUTOINC_READ_FAILED;  // Mark failure
 
1408
 
2099
1409
      /*
2100
1410
        That rounding below should not be needed when all engines actually
2101
1411
        respect offset and increment in get_auto_increment(). But they don't
2106
1416
      */
2107
1417
      nr= compute_next_insert_id(nr-1, variables);
2108
1418
    }
2109
 
    
 
1419
 
2110
1420
    if (table->s->next_number_keypart == 0)
2111
1421
    {
2112
1422
      /* We must defer the appending until "nr" has been possibly truncated */
2119
1429
    /*
2120
1430
      first test if the query was aborted due to strict mode constraints
2121
1431
    */
2122
 
    if (thd->killed == THD::KILL_BAD_DATA)
2123
 
      return(HA_ERR_AUTOINC_ERANGE);
 
1432
    if (session->killed == Session::KILL_BAD_DATA)
 
1433
      return HA_ERR_AUTOINC_ERANGE;
2124
1434
 
2125
1435
    /*
2126
1436
      field refused this value (overflow) and truncated it, use the result of
2138
1448
  {
2139
1449
    auto_inc_interval_for_cur_row.replace(nr, nb_reserved_values,
2140
1450
                                          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
1451
  }
2147
1452
 
2148
1453
  /*
2159
1464
  */
2160
1465
  set_next_insert_id(compute_next_insert_id(nr, variables));
2161
1466
 
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;
 
1467
  return 0;
2181
1468
}
2182
1469
 
2183
1470
 
2196
1483
  @param first_value         (OUT) the first value reserved by the handler
2197
1484
  @param nb_reserved_values  (OUT) how many values the handler reserved
2198
1485
*/
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)),
 
1486
void handler::get_auto_increment(uint64_t ,
 
1487
                                 uint64_t ,
 
1488
                                 uint64_t ,
2202
1489
                                 uint64_t *first_value,
2203
1490
                                 uint64_t *nb_reserved_values)
2204
1491
{
2206
1493
  int error;
2207
1494
 
2208
1495
  (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();
 
1496
  table->mark_columns_used_by_index_no_reset(table->s->next_number_index);
2212
1497
  index_init(table->s->next_number_index, 1);
2213
1498
  if (table->s->next_number_keypart == 0)
2214
1499
  {                                             // Autoincrement at key-start
2281
1566
  else
2282
1567
  {
2283
1568
    /* 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);
 
1569
    key_unpack(&str,table,(uint32_t) key_nr);
 
1570
    uint32_t max_length=DRIZZLE_ERRMSG_SIZE-(uint32_t) strlen(msg);
2286
1571
    if (str.length() >= max_length)
2287
1572
    {
2288
1573
      str.length(max_length-4);
2345
1630
      char key[MAX_KEY_LENGTH];
2346
1631
      String str(key,sizeof(key),system_charset_info);
2347
1632
      /* Table is opened and defined at this point */
2348
 
      key_unpack(&str,table,(uint) key_nr);
 
1633
      key_unpack(&str,table,(uint32_t) key_nr);
2349
1634
      max_length= (DRIZZLE_ERRMSG_SIZE-
2350
 
                   (uint) strlen(ER(ER_FOREIGN_DUPLICATE_KEY)));
 
1635
                   (uint32_t) strlen(ER(ER_FOREIGN_DUPLICATE_KEY)));
2351
1636
      if (str.length() >= max_length)
2352
1637
      {
2353
1638
        str.length(max_length-4);
2461
1746
    my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
2462
1747
               ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
2463
1748
    return;
2464
 
    break;
2465
1749
  default:
2466
1750
    {
2467
1751
      /* The error was "unknown" to this function.
2471
1755
      temporary= get_error_message(error, &str);
2472
1756
      if (!str.is_empty())
2473
1757
      {
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);
 
1758
        const char* engine_name= engine->getName().c_str();
 
1759
        if (temporary)
 
1760
          my_error(ER_GET_TEMPORARY_ERRMSG, MYF(0), error, str.ptr(),
 
1761
                   engine_name);
 
1762
        else
 
1763
          my_error(ER_GET_ERRMSG, MYF(0), error, str.ptr(), engine_name);
2479
1764
      }
2480
1765
      else
2481
 
        my_error(ER_GET_ERRNO,errflag,error);
 
1766
      {
 
1767
              my_error(ER_GET_ERRNO,errflag,error);
 
1768
      }
2482
1769
      return;
2483
1770
    }
2484
1771
  }
2485
1772
  my_error(textno, errflag, table_share->table_name.str, error);
2486
 
  return;
2487
1773
}
2488
1774
 
2489
1775
 
2496
1782
  @return
2497
1783
    Returns true if this is a temporary error
2498
1784
*/
2499
 
bool handler::get_error_message(int error __attribute__((unused)),
2500
 
                                String* buf __attribute__((unused)))
 
1785
bool handler::get_error_message(int , String* )
2501
1786
{
2502
1787
  return false;
2503
1788
}
2504
1789
 
2505
1790
 
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
1791
/* Code left, but Drizzle has no legacy yet (while MySQL did) */
2539
1792
int handler::check_old_types()
2540
1793
{
2541
1794
  return 0;
2542
1795
}
2543
1796
 
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
1797
/**
2592
1798
  @return
2593
1799
    key if error because of duplicated keys
2594
1800
*/
2595
1801
uint32_t handler::get_dup_key(int error)
2596
1802
{
2597
 
  table->file->errkey  = (uint) -1;
 
1803
  table->file->errkey  = (uint32_t) -1;
2598
1804
  if (error == HA_ERR_FOUND_DUPP_KEY || error == HA_ERR_FOREIGN_DUPLICATE_KEY ||
2599
1805
      error == HA_ERR_FOUND_DUPP_UNIQUE ||
2600
1806
      error == HA_ERR_DROP_INDEX_FK)
2602
1808
  return(table->file->errkey);
2603
1809
}
2604
1810
 
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
1811
void handler::drop_table(const char *name)
2660
1812
{
2661
1813
  close();
2662
 
  delete_table(name);
 
1814
  engine->deleteTable(ha_session(), name);
2663
1815
}
2664
1816
 
2665
1817
 
2666
1818
/**
2667
1819
  Performs checks upon the table.
2668
1820
 
2669
 
  @param thd                thread doing CHECK Table operation
 
1821
  @param session                thread doing CHECK Table operation
2670
1822
  @param check_opt          options from the parser
2671
1823
 
2672
1824
  @retval
2678
1830
  @retval
2679
1831
    HA_ADMIN_NOT_IMPLEMENTED
2680
1832
*/
2681
 
int handler::ha_check(THD *thd, HA_CHECK_OPT *check_opt)
 
1833
int handler::ha_check(Session *, HA_CHECK_OPT *)
2682
1834
{
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);
 
1835
  return HA_ADMIN_OK;
2702
1836
}
2703
1837
 
2704
1838
/**
2710
1844
void
2711
1845
handler::mark_trx_read_write()
2712
1846
{
2713
 
  Ha_trx_info *ha_info= &ha_thd()->ha_data[ht->slot].ha_info[0];
 
1847
  Ha_trx_info *ha_info= &ha_session()->ha_data[engine->getSlot()].ha_info[0];
2714
1848
  /*
2715
1849
    When a storage engine method is called, the transaction must
2716
1850
    have been started, unless it's a DDL call, for which the
2721
1855
  */
2722
1856
  if (ha_info->is_started())
2723
1857
  {
2724
 
    assert(has_transactions());
2725
1858
    /*
2726
1859
      table_share can be NULL in ha_delete_table(). See implementation
2727
1860
      of standalone function ha_delete_table() in sql_base.cc.
2728
1861
    */
2729
 
    if (table_share == NULL || table_share->tmp_table == NO_TMP_TABLE)
 
1862
//    if (table_share == NULL || table_share->tmp_table == NO_TMP_TABLE)
2730
1863
      ha_info->set_trx_read_write();
2731
1864
  }
2732
1865
}
2733
1866
 
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
1867
/**
2754
1868
  Bulk update row: public interface.
2755
1869
 
2803
1917
*/
2804
1918
 
2805
1919
int
2806
 
handler::ha_optimize(THD* thd, HA_CHECK_OPT* check_opt)
 
1920
handler::ha_optimize(Session* session, HA_CHECK_OPT* check_opt)
2807
1921
{
2808
1922
  mark_trx_read_write();
2809
1923
 
2810
 
  return optimize(thd, check_opt);
 
1924
  return optimize(session, check_opt);
2811
1925
}
2812
1926
 
2813
1927
 
2818
1932
*/
2819
1933
 
2820
1934
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
 
 
 
1935
handler::ha_analyze(Session* session, HA_CHECK_OPT* check_opt)
 
1936
{
 
1937
  mark_trx_read_write();
 
1938
 
 
1939
  return analyze(session, check_opt);
 
1940
}
2843
1941
 
2844
1942
/**
2845
1943
  Disable indexes: public interface.
2885
1983
  return discard_or_import_tablespace(discard);
2886
1984
}
2887
1985
 
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
1986
/**
2937
1987
  Drop table in the engine: public interface.
2938
1988
 
2947
1997
  return drop_table(name);
2948
1998
}
2949
1999
 
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
2000
/**
2983
2001
  Tell the storage engine that it is allowed to "disable transaction" in the
2984
2002
  handler. It is a hint that ACID is not required - it is used in NDB for
2987
2005
  starts to commit every now and then automatically.
2988
2006
  This hint can be safely ignored.
2989
2007
*/
2990
 
int ha_enable_transaction(THD *thd, bool on)
 
2008
int ha_enable_transaction(Session *session, bool on)
2991
2009
{
2992
 
  int error=0;
 
2010
  int error= 0;
2993
2011
 
2994
 
  if ((thd->transaction.on= on))
 
2012
  if ((session->transaction.on= on))
2995
2013
  {
2996
2014
    /*
2997
2015
      Now all storage engines should have transaction handling enabled.
2999
2017
      is an optimization hint that storage engine is free to ignore.
3000
2018
      So, let's commit an open transaction (if any) now.
3001
2019
    */
3002
 
    if (!(error= ha_commit_trans(thd, 0)))
3003
 
      error= end_trans(thd, COMMIT);
 
2020
    if (!(error= ha_commit_trans(session, 0)))
 
2021
      if (! session->endTransaction(COMMIT))
 
2022
        error= 1;
 
2023
 
3004
2024
  }
3005
 
  return(error);
 
2025
  return error;
3006
2026
}
3007
2027
 
3008
2028
int handler::index_next_same(unsigned char *buf, const unsigned char *key, uint32_t keylen)
3052
2072
        key_part->field->move_field_offset(-ptrdiff);
3053
2073
    }
3054
2074
  }
3055
 
  return(error);
 
2075
  return error;
3056
2076
}
3057
2077
 
3058
2078
 
3060
2080
** Some general functions that isn't in the handler class
3061
2081
****************************************************************************/
3062
2082
 
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
2083
 
3168
2084
void st_ha_check_opt::init()
3169
2085
{
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);
 
2086
  flags= 0; 
 
2087
  use_frm= false;
3370
2088
}
3371
2089
 
3372
2090
/**
3390
2108
    Estimated cost of 'index only' scan
3391
2109
*/
3392
2110
 
3393
 
double handler::index_only_read_time(uint32_t keynr, double records)
 
2111
double handler::index_only_read_time(uint32_t keynr, double key_records)
3394
2112
{
3395
 
  double read_time;
3396
2113
  uint32_t keys_per_block= (stats.block_size/2/
3397
2114
                        (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;
 
2115
  return ((double) (key_records + keys_per_block-1) /
 
2116
          (double) keys_per_block);
3401
2117
}
3402
2118
 
3403
2119
 
3424
2140
 
3425
2141
  @note
3426
2142
    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
 
2143
    session->killed and return HA_POS_ERROR if it is not zero. This is required
3428
2144
    for a user to be able to interrupt the calculation by killing the
3429
2145
    connection/query.
3430
2146
 
3439
2155
ha_rows
3440
2156
handler::multi_range_read_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
3441
2157
                                     void *seq_init_param,
3442
 
                                     uint32_t n_ranges_arg __attribute__((unused)),
 
2158
                                     uint32_t ,
3443
2159
                                     uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
3444
2160
{
3445
2161
  KEY_MULTI_RANGE range;
3446
2162
  range_seq_t seq_it;
3447
2163
  ha_rows rows, total_rows= 0;
3448
2164
  uint32_t n_ranges=0;
3449
 
  THD *thd= current_thd;
3450
 
  
 
2165
  Session *session= current_session;
 
2166
 
3451
2167
  /* Default MRR implementation doesn't need buffer */
3452
2168
  *bufsz= 0;
3453
2169
 
3454
2170
  seq_it= seq->init(seq_init_param, n_ranges, *flags);
3455
2171
  while (!seq->next(seq_it, &range))
3456
2172
  {
3457
 
    if (unlikely(thd->killed != 0))
 
2173
    if (unlikely(session->killed != 0))
3458
2174
      return HA_POS_ERROR;
3459
 
    
 
2175
 
3460
2176
    n_ranges++;
3461
2177
    key_range *min_endp, *max_endp;
3462
2178
    {
3467
2183
      rows= 1; /* there can be at most one row */
3468
2184
    else
3469
2185
    {
3470
 
      if (HA_POS_ERROR == (rows= this->records_in_range(keyno, min_endp, 
 
2186
      if (HA_POS_ERROR == (rows= this->records_in_range(keyno, min_endp,
3471
2187
                                                        max_endp)))
3472
2188
      {
3473
2189
        /* Can't scan one range => can't do MRR scan at all */
3477
2193
    }
3478
2194
    total_rows += rows;
3479
2195
  }
3480
 
  
 
2196
 
3481
2197
  if (total_rows != HA_POS_ERROR)
3482
2198
  {
3483
2199
    /* The following calculation is the same as in multi_range_read_info(): */
3485
2201
    cost->zero();
3486
2202
    cost->avg_io_cost= 1; /* assume random seeks */
3487
2203
    if ((*flags & HA_MRR_INDEX_ONLY) && total_rows > 2)
3488
 
      cost->io_count= index_only_read_time(keyno, (uint)total_rows);
 
2204
      cost->io_count= index_only_read_time(keyno, (uint32_t)total_rows);
3489
2205
    else
3490
2206
      cost->io_count= read_time(keyno, n_ranges, total_rows);
3491
2207
    cost->cpu_cost= (double) total_rows / TIME_FOR_COMPARE + 0.01;
3550
2266
/**
3551
2267
  Initialize the MRR scan
3552
2268
 
3553
 
  Initialize the MRR scan. This function may do heavyweight scan 
 
2269
  Initialize the MRR scan. This function may do heavyweight scan
3554
2270
  initialization like row prefetching/sorting/etc (NOTE: but better not do
3555
2271
  it here as we may not need it, e.g. if we never satisfy WHERE clause on
3556
2272
  previous tables. For many implementations it would be natural to do such
3557
2273
  initializations in the first multi_read_range_next() call)
3558
2274
 
3559
2275
  mode is a combination of the following flags: HA_MRR_SORTED,
3560
 
  HA_MRR_INDEX_ONLY, HA_MRR_NO_ASSOCIATION 
 
2276
  HA_MRR_INDEX_ONLY, HA_MRR_NO_ASSOCIATION
3561
2277
 
3562
2278
  @param seq             Range sequence to be traversed
3563
2279
  @param seq_init_param  First parameter for seq->init()
3569
2285
    One must have called index_init() before calling this function. Several
3570
2286
    multi_range_read_init() calls may be made in course of one query.
3571
2287
 
3572
 
    Until WL#2623 is done (see its text, section 3.2), the following will 
 
2288
    Until WL#2623 is done (see its text, section 3.2), the following will
3573
2289
    also hold:
3574
2290
    The caller will guarantee that if "seq->init == mrr_ranges_array_init"
3575
2291
    then seq_init_param is an array of n_ranges KEY_MULTI_RANGE structures.
3576
2292
    This property will only be used by NDB handler until WL#2623 is done.
3577
 
     
 
2293
 
3578
2294
    Buffer memory management is done according to the following scenario:
3579
2295
    The caller allocates the buffer and provides it to the callee by filling
3580
2296
    the members of HANDLER_BUFFER structure.
3591
2307
int
3592
2308
handler::multi_range_read_init(RANGE_SEQ_IF *seq_funcs, void *seq_init_param,
3593
2309
                               uint32_t n_ranges, uint32_t mode,
3594
 
                               HANDLER_BUFFER *buf __attribute__((unused)))
 
2310
                               HANDLER_BUFFER *)
3595
2311
{
3596
2312
  mrr_iter= seq_funcs->init(seq_init_param, n_ranges, mode);
3597
2313
  mrr_funcs= *seq_funcs;
3598
2314
  mrr_is_output_sorted= test(mode & HA_MRR_SORTED);
3599
2315
  mrr_have_range= false;
3600
 
  return(0);
 
2316
  return 0;
3601
2317
}
3602
2318
 
3603
2319
 
3664
2380
  while ((result == HA_ERR_END_OF_FILE) && !range_res);
3665
2381
 
3666
2382
  *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();
 
2383
  return result;
4164
2384
}
4165
2385
 
4166
2386
 
4181
2401
  Time to move the disk head is proportional to head travel distance.
4182
2402
 
4183
2403
  Time to wait for the plate to rotate depends on whether the disk head
4184
 
  was moved or not. 
 
2404
  was moved or not.
4185
2405
 
4186
2406
  If disk head wasn't moved, the wait time is proportional to distance
4187
2407
  between the previous block and the block we're reading.
4192
2412
 
4193
2413
  Our cost units are "random disk seeks". The cost of random disk seek is
4194
2414
  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 
 
2415
  to access. We make it constant by introducing a fuzzy concept of "typical
4196
2416
  datafile length" (it's fuzzy as it's hard to tell whether it should
4197
2417
  include index file, temp.tables etc). Then random seek cost is:
4198
2418
 
4207
2427
  @param cost         OUT  The cost.
4208
2428
*/
4209
2429
 
4210
 
void get_sweep_read_cost(Table *table, ha_rows nrows, bool interrupted, 
 
2430
void get_sweep_read_cost(Table *table, ha_rows nrows, bool interrupted,
4211
2431
                         COST_VECT *cost)
4212
2432
{
4213
2433
  cost->zero();
4214
2434
  if (table->file->primary_key_is_clustered())
4215
2435
  {
4216
2436
    cost->io_count= table->file->read_time(table->s->primary_key,
4217
 
                                           (uint) nrows, nrows);
 
2437
                                           (uint32_t) nrows, nrows);
4218
2438
  }
4219
2439
  else
4220
2440
  {
4234
2454
                          DISK_SEEK_PROP_COST*n_blocks/busy_blocks);
4235
2455
    }
4236
2456
  }
4237
 
  return;
4238
2457
}
4239
2458
 
4240
2459
 
4263
2482
int handler::read_range_first(const key_range *start_key,
4264
2483
                              const key_range *end_key,
4265
2484
                              bool eq_range_arg,
4266
 
                              bool sorted  __attribute__((unused)))
 
2485
                              bool )
4267
2486
{
4268
2487
  int result;
4269
2488
 
4286
2505
                           start_key->keypart_map,
4287
2506
                           start_key->flag);
4288
2507
  if (result)
4289
 
    return((result == HA_ERR_KEY_NOT_FOUND) 
 
2508
    return((result == HA_ERR_KEY_NOT_FOUND)
4290
2509
                ? HA_ERR_END_OF_FILE
4291
2510
                : result);
4292
2511
 
4320
2539
  }
4321
2540
  result= index_next(table->record[0]);
4322
2541
  if (result)
4323
 
    return(result);
 
2542
    return result;
4324
2543
  return(compare_key(end_range) <= 0 ? 0 : HA_ERR_END_OF_FILE);
4325
2544
}
4326
2545
 
4368
2587
  return cmp;
4369
2588
}
4370
2589
 
4371
 
int handler::index_read_idx_map(unsigned char * buf, uint32_t index, const unsigned char * key,
 
2590
int handler::index_read_idx_map(unsigned char * buf, uint32_t index,
 
2591
                                const unsigned char * key,
4372
2592
                                key_part_map keypart_map,
4373
2593
                                enum ha_rkey_function find_flag)
4374
2594
{
4382
2602
  return error ?  error : error1;
4383
2603
}
4384
2604
 
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,
 
2605
static bool stat_print(Session *session, const char *type, uint32_t type_len,
4456
2606
                       const char *file, uint32_t file_len,
4457
2607
                       const char *status, uint32_t status_len)
4458
2608
{
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())
 
2609
  session->client->store(type, type_len);
 
2610
  session->client->store(file, file_len);
 
2611
  session->client->store(status, status_len);
 
2612
  if (session->client->flush())
4465
2613
    return true;
4466
2614
  return false;
4467
2615
}
4468
2616
 
4469
 
bool ha_show_status(THD *thd, handlerton *db_type, enum ha_stat_type stat)
 
2617
bool ha_show_status(Session *session, StorageEngine *engine, enum ha_stat_type stat)
4470
2618
{
4471
2619
  List<Item> field_list;
4472
 
  Protocol *protocol= thd->protocol;
4473
2620
  bool result;
4474
2621
 
4475
2622
  field_list.push_back(new Item_empty_string("Type",10));
4476
2623
  field_list.push_back(new Item_empty_string("Name",FN_REFLEN));
4477
2624
  field_list.push_back(new Item_empty_string("Status",10));
4478
2625
 
4479
 
  if (protocol->send_fields(&field_list,
4480
 
                            Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
 
2626
  if (session->client->sendFields(&field_list))
4481
2627
    return true;
4482
2628
 
4483
 
  result= db_type->show_status &&
4484
 
    db_type->show_status(db_type, thd, stat_print, stat) ? 1 : 0;
 
2629
  result= engine->show_status(session, stat_print, stat) ? 1 : 0;
4485
2630
 
4486
2631
  if (!result)
4487
 
    my_eof(thd);
 
2632
    session->my_eof();
4488
2633
  return result;
4489
2634
}
4490
2635
 
4501
2646
  - table is not mysql.event
4502
2647
*/
4503
2648
 
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
 
  {
 
2649
static bool log_row_for_replication(Table* table,
 
2650
                           const unsigned char *before_record,
 
2651
                           const unsigned char *after_record)
 
2652
{
 
2653
  Session *const session= table->in_use;
 
2654
 
 
2655
  switch (session->lex->sql_command)
 
2656
  {
 
2657
  case SQLCOM_REPLACE:
 
2658
  case SQLCOM_INSERT:
 
2659
  case SQLCOM_REPLACE_SELECT:
 
2660
  case SQLCOM_INSERT_SELECT:
 
2661
  case SQLCOM_CREATE_TABLE:
 
2662
    replication_services.insertRecord(session, table);
 
2663
    break;
 
2664
 
 
2665
  case SQLCOM_UPDATE:
 
2666
    replication_services.updateRecord(session, table, before_record, after_record);
 
2667
    break;
 
2668
 
 
2669
  case SQLCOM_DELETE:
 
2670
    replication_services.deleteRecord(session, table);
 
2671
    break;
 
2672
 
4595
2673
    /*
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.
 
2674
      For everything else we ignore the event (since it just involves a temp table)
4599
2675
    */
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
 
    }
 
2676
  default:
 
2677
    break;
4605
2678
  }
4606
 
  return error ? HA_ERR_RBR_LOGGING_FAILED : 0;
 
2679
 
 
2680
  return false; //error;
4607
2681
}
4608
2682
 
4609
 
int handler::ha_external_lock(THD *thd, int lock_type)
 
2683
int handler::ha_external_lock(Session *session, int lock_type)
4610
2684
{
4611
2685
  /*
4612
2686
    Whether this is lock or unlock, this should be true, and is to verify that
4619
2693
    We cache the table flags if the locking succeeded. Otherwise, we
4620
2694
    keep them as they were when they were fetched in ha_open().
4621
2695
  */
4622
 
  DRIZZLE_EXTERNAL_LOCK(lock_type);
4623
 
 
4624
 
  int error= external_lock(thd, lock_type);
 
2696
 
 
2697
  int error= external_lock(session, lock_type);
 
2698
 
4625
2699
  if (error == 0)
4626
2700
    cached_table_flags= table_flags();
4627
 
  return(error);
 
2701
  return error;
4628
2702
}
4629
2703
 
4630
2704
 
4634
2708
int handler::ha_reset()
4635
2709
{
4636
2710
  /* Check that we have called all proper deallocation functions */
4637
 
  assert((unsigned char*) table->def_read_set.bitmap +
 
2711
  assert((unsigned char*) table->def_read_set.getBitmap() +
4638
2712
              table->s->column_bitmap_size ==
4639
 
              (unsigned char*) table->def_write_set.bitmap);
4640
 
  assert(bitmap_is_set_all(&table->s->all_set));
 
2713
              (unsigned char*) table->def_write_set.getBitmap());
 
2714
  assert(table->s->all_set.isSetAll());
4641
2715
  assert(table->key_read == 0);
4642
2716
  /* ensure that ha_index_end / ha_rnd_end has been called */
4643
2717
  assert(inited == NONE);
4644
2718
  /* Free cache used by filesort */
4645
 
  free_io_cache(table);
 
2719
  table->free_io_cache();
4646
2720
  /* reset the bitmaps to point to defaults */
4647
2721
  table->default_column_bitmaps();
4648
2722
  return(reset());
4652
2726
int handler::ha_write_row(unsigned char *buf)
4653
2727
{
4654
2728
  int error;
4655
 
  Log_func *log_func= Write_rows_log_event::binlog_row_logging_function;
4656
 
  DRIZZLE_INSERT_ROW_START();
 
2729
 
 
2730
  /* 
 
2731
   * If we have a timestamp column, update it to the current time 
 
2732
   * 
 
2733
   * @TODO Technically, the below two lines can be take even further out of the
 
2734
   * handler interface and into the fill_record() method.
 
2735
   */
 
2736
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
 
2737
    table->timestamp_field->set_time();
4657
2738
 
4658
2739
  mark_trx_read_write();
4659
2740
 
4660
2741
  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);
 
2742
  {
 
2743
    return error;
 
2744
  }
 
2745
 
 
2746
  if (unlikely(log_row_for_replication(table, 0, buf)))
 
2747
    return HA_ERR_RBR_LOGGING_FAILED;
 
2748
 
 
2749
  return 0;
4666
2750
}
4667
2751
 
4668
2752
 
4669
2753
int handler::ha_update_row(const unsigned char *old_data, unsigned char *new_data)
4670
2754
{
4671
2755
  int error;
4672
 
  Log_func *log_func= Update_rows_log_event::binlog_row_logging_function;
4673
2756
 
4674
2757
  /*
4675
2758
    Some storage engines require that the new record is in record[0]
4680
2763
  mark_trx_read_write();
4681
2764
 
4682
2765
  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;
 
2766
  {
 
2767
    return error;
 
2768
  }
 
2769
 
 
2770
  if (unlikely(log_row_for_replication(table, old_data, new_data)))
 
2771
    return HA_ERR_RBR_LOGGING_FAILED;
 
2772
 
4686
2773
  return 0;
4687
2774
}
4688
2775
 
4689
2776
int handler::ha_delete_row(const unsigned char *buf)
4690
2777
{
4691
2778
  int error;
4692
 
  Log_func *log_func= Delete_rows_log_event::binlog_row_logging_function;
4693
2779
 
4694
2780
  mark_trx_read_write();
4695
2781
 
4696
2782
  if (unlikely(error= delete_row(buf)))
4697
2783
    return error;
4698
 
  if (unlikely(error= binlog_log_row(table, buf, 0, log_func)))
4699
 
    return error;
 
2784
 
 
2785
  if (unlikely(log_row_for_replication(table, buf, 0)))
 
2786
    return HA_ERR_RBR_LOGGING_FAILED;
 
2787
 
4700
2788
  return 0;
4701
2789
}
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
 
}