~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/handler.cc

  • Committer: Monty Taylor
  • Date: 2008-09-16 00:00:48 UTC
  • mto: This revision was merged to the branch mainline in revision 391.
  • Revision ID: monty@inaugust.com-20080916000048-3rvrv3gv9l0ad3gs
Fixed copyright headers in drizzled/

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 
 *
4
 
 *  Copyright (C) 2008 Sun Microsystems, Inc.
5
 
 *
6
 
 *  This program is free software; you can redistribute it and/or modify
7
 
 *  it under the terms of the GNU General Public License as published by
8
 
 *  the Free Software Foundation; version 2 of the License.
9
 
 *
10
 
 *  This program is distributed in the hope that it will be useful,
11
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
 *  GNU General Public License for more details.
14
 
 *
15
 
 *  You should have received a copy of the GNU General Public License
16
 
 *  along with this program; if not, write to the Free Software
17
 
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
 
 */
 
1
/* Copyright (C) 2000-2006 MySQL AB
 
2
 
 
3
   This program is free software; you can redistribute it and/or modify
 
4
   it under the terms of the GNU General Public License as published by
 
5
   the Free Software Foundation; version 2 of the License.
 
6
 
 
7
   This program is distributed in the hope that it will be useful,
 
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
10
   GNU General Public License for more details.
 
11
 
 
12
   You should have received a copy of the GNU General Public License
 
13
   along with this program; if not, write to the Free Software
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
19
15
 
20
16
/**
21
 
  @file Cursor.cc
 
17
  @file handler.cc
22
18
 
23
19
  Handler-calling-functions
24
20
*/
25
21
 
26
 
#include "config.h"
27
 
 
28
 
#include <fcntl.h>
29
 
 
30
 
#include "drizzled/error.h"
31
 
#include "drizzled/field/epoch.h"
32
 
#include "drizzled/gettext.h"
33
 
#include "drizzled/internal/my_sys.h"
34
 
#include "drizzled/item/empty_string.h"
35
 
#include "drizzled/item/int.h"
36
 
#include "drizzled/lock.h"
37
 
#include "drizzled/message/table.h"
38
 
#include "drizzled/my_hash.h"
39
 
#include "drizzled/optimizer/cost_vector.h"
40
 
#include "drizzled/plugin/client.h"
41
 
#include "drizzled/plugin/event_observer.h"
42
 
#include "drizzled/plugin/storage_engine.h"
43
 
#include "drizzled/probes.h"
44
 
#include "drizzled/session.h"
45
 
#include "drizzled/sql_base.h"
46
 
#include "drizzled/sql_parse.h"
47
 
#include "drizzled/transaction_services.h"
48
 
 
49
 
using namespace std;
50
 
 
51
 
namespace drizzled
52
 
{
 
22
#ifdef USE_PRAGMA_IMPLEMENTATION
 
23
#pragma implementation                          // gcc: Class implementation
 
24
#endif
 
25
 
 
26
#include <drizzled/server_includes.h>
 
27
#include "rpl_filter.h"
 
28
#include <drizzled/drizzled_error_messages.h>
 
29
 
 
30
/*
 
31
  While we have legacy_db_type, we have this array to
 
32
  check for dups and to find handlerton from legacy_db_type.
 
33
  Remove when legacy_db_type is finally gone
 
34
*/
 
35
st_plugin_int *hton2plugin[MAX_HA];
 
36
 
 
37
static handlerton *installed_htons[128];
 
38
 
 
39
#define BITMAP_STACKBUF_SIZE (128/8)
 
40
 
 
41
KEY_CREATE_INFO default_key_create_info= { HA_KEY_ALG_UNDEF, 0, {NullS,0}, {NullS,0} };
 
42
 
 
43
/* number of entries in handlertons[] */
 
44
uint32_t total_ha= 0;
 
45
/* number of storage engines (from handlertons[]) that support 2pc */
 
46
uint32_t total_ha_2pc= 0;
 
47
/* size of savepoint storage area (see ha_init) */
 
48
uint32_t savepoint_alloc_size= 0;
 
49
 
 
50
static const LEX_STRING sys_table_aliases[]=
 
51
{
 
52
  { C_STRING_WITH_LEN("INNOBASE") },  { C_STRING_WITH_LEN("INNODB") },
 
53
  { C_STRING_WITH_LEN("HEAP") },      { C_STRING_WITH_LEN("MEMORY") },
 
54
  {NullS, 0}
 
55
};
 
56
 
 
57
const char *ha_row_type[] = {
 
58
  "", "FIXED", "DYNAMIC", "COMPRESSED", "REDUNDANT", "COMPACT", "PAGE", "?","?","?"
 
59
};
 
60
 
 
61
const char *tx_isolation_names[] =
 
62
{ "READ-UNCOMMITTED", "READ-COMMITTED", "REPEATABLE-READ", "SERIALIZABLE",
 
63
  NullS};
 
64
TYPELIB tx_isolation_typelib= {array_elements(tx_isolation_names)-1,"",
 
65
                               tx_isolation_names, NULL};
 
66
 
 
67
static TYPELIB known_extensions= {0,"known_exts", NULL, NULL};
 
68
uint known_extensions_id= 0;
 
69
 
 
70
 
 
71
 
 
72
static plugin_ref ha_default_plugin(THD *thd)
 
73
{
 
74
  if (thd->variables.table_plugin)
 
75
    return thd->variables.table_plugin;
 
76
  return my_plugin_lock(thd, &global_system_variables.table_plugin);
 
77
}
 
78
 
 
79
 
 
80
/**
 
81
  Return the default storage engine handlerton for thread
 
82
 
 
83
  @param ha_default_handlerton(thd)
 
84
  @param thd         current thread
 
85
 
 
86
  @return
 
87
    pointer to handlerton
 
88
*/
 
89
handlerton *ha_default_handlerton(THD *thd)
 
90
{
 
91
  plugin_ref plugin= ha_default_plugin(thd);
 
92
  assert(plugin);
 
93
  handlerton *hton= plugin_data(plugin, handlerton*);
 
94
  assert(hton);
 
95
  return hton;
 
96
}
 
97
 
 
98
 
 
99
/**
 
100
  Return the storage engine handlerton for the supplied name
 
101
  
 
102
  @param thd         current thread
 
103
  @param name        name of storage engine
 
104
  
 
105
  @return
 
106
    pointer to storage engine plugin handle
 
107
*/
 
108
plugin_ref ha_resolve_by_name(THD *thd, const LEX_STRING *name)
 
109
{
 
110
  const LEX_STRING *table_alias;
 
111
  plugin_ref plugin;
 
112
 
 
113
redo:
 
114
  /* my_strnncoll is a macro and gcc doesn't do early expansion of macro */
 
115
  if (thd && !my_charset_utf8_general_ci.coll->strnncoll(&my_charset_utf8_general_ci,
 
116
                           (const uchar *)name->str, name->length,
 
117
                           (const uchar *)STRING_WITH_LEN("DEFAULT"), 0))
 
118
    return ha_default_plugin(thd);
 
119
 
 
120
  if ((plugin= my_plugin_lock_by_name(thd, name, DRIZZLE_STORAGE_ENGINE_PLUGIN)))
 
121
  {
 
122
    handlerton *hton= plugin_data(plugin, handlerton *);
 
123
    if (!(hton->flags & HTON_NOT_USER_SELECTABLE))
 
124
      return plugin;
 
125
      
 
126
    /*
 
127
      unlocking plugin immediately after locking is relatively low cost.
 
128
    */
 
129
    plugin_unlock(thd, plugin);
 
130
  }
 
131
 
 
132
  /*
 
133
    We check for the historical aliases.
 
134
  */
 
135
  for (table_alias= sys_table_aliases; table_alias->str; table_alias+= 2)
 
136
  {
 
137
    if (!my_strnncoll(&my_charset_utf8_general_ci,
 
138
                      (const uchar *)name->str, name->length,
 
139
                      (const uchar *)table_alias->str, table_alias->length))
 
140
    {
 
141
      name= table_alias + 1;
 
142
      goto redo;
 
143
    }
 
144
  }
 
145
 
 
146
  return NULL;
 
147
}
 
148
 
 
149
 
 
150
plugin_ref ha_lock_engine(THD *thd, handlerton *hton)
 
151
{
 
152
  if (hton)
 
153
  {
 
154
    st_plugin_int **plugin= hton2plugin + hton->slot;
 
155
    
 
156
    return my_plugin_lock(thd, &plugin);
 
157
  }
 
158
  return NULL;
 
159
}
 
160
 
 
161
 
 
162
handlerton *ha_resolve_by_legacy_type(THD *thd, enum legacy_db_type db_type)
 
163
{
 
164
  plugin_ref plugin;
 
165
  switch (db_type) {
 
166
  case DB_TYPE_DEFAULT:
 
167
    return ha_default_handlerton(thd);
 
168
  default:
 
169
    if (db_type > DB_TYPE_UNKNOWN && db_type < DB_TYPE_DEFAULT &&
 
170
        (plugin= ha_lock_engine(thd, installed_htons[db_type])))
 
171
      return plugin_data(plugin, handlerton*);
 
172
    /* fall through */
 
173
  case DB_TYPE_UNKNOWN:
 
174
    return NULL;
 
175
  }
 
176
}
 
177
 
 
178
 
 
179
/**
 
180
  Use other database handler if databasehandler is not compiled in.
 
181
*/
 
182
handlerton *ha_checktype(THD *thd, enum legacy_db_type database_type,
 
183
                          bool no_substitute, bool report_error)
 
184
{
 
185
  handlerton *hton= ha_resolve_by_legacy_type(thd, database_type);
 
186
  if (ha_storage_engine_is_enabled(hton))
 
187
    return hton;
 
188
 
 
189
  if (no_substitute)
 
190
  {
 
191
    if (report_error)
 
192
    {
 
193
      const char *engine_name= ha_resolve_storage_engine_name(hton);
 
194
      my_error(ER_FEATURE_DISABLED,MYF(0),engine_name,engine_name);
 
195
    }
 
196
    return NULL;
 
197
  }
 
198
 
 
199
  switch (database_type) {
 
200
  case DB_TYPE_HASH:
 
201
    return ha_resolve_by_legacy_type(thd, DB_TYPE_HASH);
 
202
  default:
 
203
    break;
 
204
  }
 
205
 
 
206
  return ha_default_handlerton(thd);
 
207
} /* ha_checktype */
 
208
 
 
209
 
 
210
handler *get_new_handler(TABLE_SHARE *share, MEM_ROOT *alloc,
 
211
                         handlerton *db_type)
 
212
{
 
213
  handler *file;
 
214
 
 
215
  if (db_type && db_type->state == SHOW_OPTION_YES && db_type->create)
 
216
  {
 
217
    if ((file= db_type->create(db_type, share, alloc)))
 
218
      file->init();
 
219
    return(file);
 
220
  }
 
221
  /*
 
222
    Try the default table type
 
223
    Here the call to current_thd() is ok as we call this function a lot of
 
224
    times but we enter this branch very seldom.
 
225
  */
 
226
  return(get_new_handler(share, alloc, ha_default_handlerton(current_thd)));
 
227
}
 
228
 
 
229
 
 
230
/**
 
231
  Register handler error messages for use with my_error().
 
232
 
 
233
  @retval
 
234
    0           OK
 
235
  @retval
 
236
    !=0         Error
 
237
*/
 
238
 
 
239
int ha_init_errors(void)
 
240
{
 
241
#define SETMSG(nr, msg) errmsgs[(nr) - HA_ERR_FIRST]= (msg)
 
242
  const char    **errmsgs;
 
243
 
 
244
  /* Allocate a pointer array for the error message strings. */
 
245
  /* Zerofill it to avoid uninitialized gaps. */
 
246
  if (! (errmsgs= (const char**) my_malloc(HA_ERR_ERRORS * sizeof(char*),
 
247
                                           MYF(MY_WME | MY_ZEROFILL))))
 
248
    return 1;
 
249
 
 
250
  /* Set the dedicated error messages. */
 
251
  SETMSG(HA_ERR_KEY_NOT_FOUND,          ER(ER_KEY_NOT_FOUND));
 
252
  SETMSG(HA_ERR_FOUND_DUPP_KEY,         ER(ER_DUP_KEY));
 
253
  SETMSG(HA_ERR_RECORD_CHANGED,         "Update wich is recoverable");
 
254
  SETMSG(HA_ERR_WRONG_INDEX,            "Wrong index given to function");
 
255
  SETMSG(HA_ERR_CRASHED,                ER(ER_NOT_KEYFILE));
 
256
  SETMSG(HA_ERR_WRONG_IN_RECORD,        ER(ER_CRASHED_ON_USAGE));
 
257
  SETMSG(HA_ERR_OUT_OF_MEM,             "Table handler out of memory");
 
258
  SETMSG(HA_ERR_NOT_A_TABLE,            "Incorrect file format '%.64s'");
 
259
  SETMSG(HA_ERR_WRONG_COMMAND,          "Command not supported");
 
260
  SETMSG(HA_ERR_OLD_FILE,               ER(ER_OLD_KEYFILE));
 
261
  SETMSG(HA_ERR_NO_ACTIVE_RECORD,       "No record read in update");
 
262
  SETMSG(HA_ERR_RECORD_DELETED,         "Intern record deleted");
 
263
  SETMSG(HA_ERR_RECORD_FILE_FULL,       ER(ER_RECORD_FILE_FULL));
 
264
  SETMSG(HA_ERR_INDEX_FILE_FULL,        "No more room in index file '%.64s'");
 
265
  SETMSG(HA_ERR_END_OF_FILE,            "End in next/prev/first/last");
 
266
  SETMSG(HA_ERR_UNSUPPORTED,            ER(ER_ILLEGAL_HA));
 
267
  SETMSG(HA_ERR_TO_BIG_ROW,             "Too big row");
 
268
  SETMSG(HA_WRONG_CREATE_OPTION,        "Wrong create option");
 
269
  SETMSG(HA_ERR_FOUND_DUPP_UNIQUE,      ER(ER_DUP_UNIQUE));
 
270
  SETMSG(HA_ERR_UNKNOWN_CHARSET,        "Can't open charset");
 
271
  SETMSG(HA_ERR_WRONG_MRG_TABLE_DEF,    ER(ER_WRONG_MRG_TABLE));
 
272
  SETMSG(HA_ERR_CRASHED_ON_REPAIR,      ER(ER_CRASHED_ON_REPAIR));
 
273
  SETMSG(HA_ERR_CRASHED_ON_USAGE,       ER(ER_CRASHED_ON_USAGE));
 
274
  SETMSG(HA_ERR_LOCK_WAIT_TIMEOUT,      ER(ER_LOCK_WAIT_TIMEOUT));
 
275
  SETMSG(HA_ERR_LOCK_TABLE_FULL,        ER(ER_LOCK_TABLE_FULL));
 
276
  SETMSG(HA_ERR_READ_ONLY_TRANSACTION,  ER(ER_READ_ONLY_TRANSACTION));
 
277
  SETMSG(HA_ERR_LOCK_DEADLOCK,          ER(ER_LOCK_DEADLOCK));
 
278
  SETMSG(HA_ERR_CANNOT_ADD_FOREIGN,     ER(ER_CANNOT_ADD_FOREIGN));
 
279
  SETMSG(HA_ERR_NO_REFERENCED_ROW,      ER(ER_NO_REFERENCED_ROW_2));
 
280
  SETMSG(HA_ERR_ROW_IS_REFERENCED,      ER(ER_ROW_IS_REFERENCED_2));
 
281
  SETMSG(HA_ERR_NO_SAVEPOINT,           "No savepoint with that name");
 
282
  SETMSG(HA_ERR_NON_UNIQUE_BLOCK_SIZE,  "Non unique key block size");
 
283
  SETMSG(HA_ERR_NO_SUCH_TABLE,          "No such table: '%.64s'");
 
284
  SETMSG(HA_ERR_TABLE_EXIST,            ER(ER_TABLE_EXISTS_ERROR));
 
285
  SETMSG(HA_ERR_NO_CONNECTION,          "Could not connect to storage engine");
 
286
  SETMSG(HA_ERR_TABLE_DEF_CHANGED,      ER(ER_TABLE_DEF_CHANGED));
 
287
  SETMSG(HA_ERR_FOREIGN_DUPLICATE_KEY,  "FK constraint would lead to duplicate key");
 
288
  SETMSG(HA_ERR_TABLE_NEEDS_UPGRADE,    ER(ER_TABLE_NEEDS_UPGRADE));
 
289
  SETMSG(HA_ERR_TABLE_READONLY,         ER(ER_OPEN_AS_READONLY));
 
290
  SETMSG(HA_ERR_AUTOINC_READ_FAILED,    ER(ER_AUTOINC_READ_FAILED));
 
291
  SETMSG(HA_ERR_AUTOINC_ERANGE,         ER(ER_WARN_DATA_OUT_OF_RANGE));
 
292
 
 
293
  /* Register the error messages for use with my_error(). */
 
294
  return my_error_register(errmsgs, HA_ERR_FIRST, HA_ERR_LAST);
 
295
}
 
296
 
 
297
 
 
298
/**
 
299
  Unregister handler error messages.
 
300
 
 
301
  @retval
 
302
    0           OK
 
303
  @retval
 
304
    !=0         Error
 
305
*/
 
306
static int ha_finish_errors(void)
 
307
{
 
308
  const char    **errmsgs;
 
309
 
 
310
  /* Allocate a pointer array for the error message strings. */
 
311
  if (! (errmsgs= my_error_unregister(HA_ERR_FIRST, HA_ERR_LAST)))
 
312
    return 1;
 
313
  my_free((uchar*) errmsgs, MYF(0));
 
314
  return 0;
 
315
}
 
316
 
 
317
 
 
318
int ha_finalize_handlerton(st_plugin_int *plugin)
 
319
{
 
320
  handlerton *hton= (handlerton *)plugin->data;
 
321
 
 
322
  switch (hton->state)
 
323
  {
 
324
  case SHOW_OPTION_NO:
 
325
  case SHOW_OPTION_DISABLED:
 
326
    break;
 
327
  case SHOW_OPTION_YES:
 
328
    if (installed_htons[hton->db_type] == hton)
 
329
      installed_htons[hton->db_type]= NULL;
 
330
    break;
 
331
  };
 
332
 
 
333
  if (hton && plugin->plugin->deinit)
 
334
    (void)plugin->plugin->deinit(hton);
 
335
 
 
336
  my_free((uchar*)hton, MYF(0));
 
337
 
 
338
  return(0);
 
339
}
 
340
 
 
341
 
 
342
int ha_initialize_handlerton(st_plugin_int *plugin)
 
343
{
 
344
  handlerton *hton;
 
345
 
 
346
  hton= (handlerton *)my_malloc(sizeof(handlerton),
 
347
                                MYF(MY_WME | MY_ZEROFILL));
 
348
  /* 
 
349
    FIXME: the MY_ZEROFILL flag above doesn't zero all the bytes.
 
350
    
 
351
    This was detected after adding get_backup_engine member to handlerton
 
352
    structure. Apparently get_backup_engine was not NULL even though it was
 
353
    not initialized.
 
354
   */
 
355
  memset(hton, 0, sizeof(hton));
 
356
  /* Historical Requirement */
 
357
  plugin->data= hton; // shortcut for the future
 
358
  if (plugin->plugin->init)
 
359
  {
 
360
    if (plugin->plugin->init(hton))
 
361
    {
 
362
      sql_print_error(_("Plugin '%s' init function returned error."),
 
363
                      plugin->name.str);
 
364
      goto err;
 
365
    }
 
366
  }
 
367
 
 
368
  /*
 
369
    the switch below and hton->state should be removed when
 
370
    command-line options for plugins will be implemented
 
371
  */
 
372
  switch (hton->state) {
 
373
  case SHOW_OPTION_NO:
 
374
    break;
 
375
  case SHOW_OPTION_YES:
 
376
    {
 
377
      uint tmp;
 
378
      /* now check the db_type for conflict */
 
379
      if (hton->db_type <= DB_TYPE_UNKNOWN ||
 
380
          hton->db_type >= DB_TYPE_DEFAULT ||
 
381
          installed_htons[hton->db_type])
 
382
      {
 
383
        int idx= (int) DB_TYPE_FIRST_DYNAMIC;
 
384
 
 
385
        while (idx < (int) DB_TYPE_DEFAULT && installed_htons[idx])
 
386
          idx++;
 
387
 
 
388
        if (idx == (int) DB_TYPE_DEFAULT)
 
389
        {
 
390
          sql_print_warning(_("Too many storage engines!"));
 
391
          return(1);
 
392
        }
 
393
        if (hton->db_type != DB_TYPE_UNKNOWN)
 
394
          sql_print_warning(_("Storage engine '%s' has conflicting typecode. "
 
395
                            "Assigning value %d."), plugin->plugin->name, idx);
 
396
        hton->db_type= (enum legacy_db_type) idx;
 
397
      }
 
398
      installed_htons[hton->db_type]= hton;
 
399
      tmp= hton->savepoint_offset;
 
400
      hton->savepoint_offset= savepoint_alloc_size;
 
401
      savepoint_alloc_size+= tmp;
 
402
      hton->slot= total_ha++;
 
403
      hton2plugin[hton->slot]=plugin;
 
404
      if (hton->prepare)
 
405
        total_ha_2pc++;
 
406
      break;
 
407
    }
 
408
    /* fall through */
 
409
  default:
 
410
    hton->state= SHOW_OPTION_DISABLED;
 
411
    break;
 
412
  }
 
413
  
 
414
  /* 
 
415
    This is entirely for legacy. We will create a new "disk based" hton and a 
 
416
    "memory" hton which will be configurable longterm. We should be able to 
 
417
    remove partition and myisammrg.
 
418
  */
 
419
  switch (hton->db_type) {
 
420
  case DB_TYPE_HEAP:
 
421
    heap_hton= hton;
 
422
    break;
 
423
  case DB_TYPE_MYISAM:
 
424
    myisam_hton= hton;
 
425
    break;
 
426
  default:
 
427
    break;
 
428
  };
 
429
 
 
430
  return(0);
 
431
err:
 
432
  return(1);
 
433
}
 
434
 
 
435
int ha_init()
 
436
{
 
437
  int error= 0;
 
438
 
 
439
  assert(total_ha < MAX_HA);
 
440
  /*
 
441
    Check if there is a transaction-capable storage engine besides the
 
442
    binary log (which is considered a transaction-capable storage engine in
 
443
    counting total_ha)
 
444
  */
 
445
  opt_using_transactions= total_ha>(uint32_t)opt_bin_log;
 
446
  savepoint_alloc_size+= sizeof(SAVEPOINT);
 
447
  return(error);
 
448
}
 
449
 
 
450
int ha_end()
 
451
{
 
452
  int error= 0;
 
453
 
 
454
  /* 
 
455
    This should be eventualy based  on the graceful shutdown flag.
 
456
    So if flag is equal to HA_PANIC_CLOSE, the deallocate
 
457
    the errors.
 
458
  */
 
459
  if (ha_finish_errors())
 
460
    error= 1;
 
461
 
 
462
  return(error);
 
463
}
 
464
 
 
465
static bool dropdb_handlerton(THD *unused1 __attribute__((unused)),
 
466
                              plugin_ref plugin,
 
467
                              void *path)
 
468
{
 
469
  handlerton *hton= plugin_data(plugin, handlerton *);
 
470
  if (hton->state == SHOW_OPTION_YES && hton->drop_database)
 
471
    hton->drop_database(hton, (char *)path);
 
472
  return false;
 
473
}
 
474
 
 
475
 
 
476
void ha_drop_database(char* path)
 
477
{
 
478
  plugin_foreach(NULL, dropdb_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN, path);
 
479
}
 
480
 
 
481
 
 
482
static bool closecon_handlerton(THD *thd, plugin_ref plugin,
 
483
                                void *unused __attribute__((unused)))
 
484
{
 
485
  handlerton *hton= plugin_data(plugin, handlerton *);
 
486
  /*
 
487
    there's no need to rollback here as all transactions must
 
488
    be rolled back already
 
489
  */
 
490
  if (hton->state == SHOW_OPTION_YES && hton->close_connection &&
 
491
      thd_get_ha_data(thd, hton))
 
492
    hton->close_connection(hton, thd);
 
493
  return false;
 
494
}
 
495
 
 
496
 
 
497
/**
 
498
  @note
 
499
    don't bother to rollback here, it's done already
 
500
*/
 
501
void ha_close_connection(THD* thd)
 
502
{
 
503
  plugin_foreach(thd, closecon_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN, 0);
 
504
}
 
505
 
 
506
/* ========================================================================
 
507
 ======================= TRANSACTIONS ===================================*/
 
508
 
 
509
/**
 
510
  Transaction handling in the server
 
511
  ==================================
 
512
 
 
513
  In each client connection, MySQL maintains two transactional
 
514
  states:
 
515
  - a statement transaction,
 
516
  - a standard, also called normal transaction.
 
517
 
 
518
  Historical note
 
519
  ---------------
 
520
  "Statement transaction" is a non-standard term that comes
 
521
  from the times when MySQL supported BerkeleyDB storage engine.
 
522
 
 
523
  First of all, it should be said that in BerkeleyDB auto-commit
 
524
  mode auto-commits operations that are atomic to the storage
 
525
  engine itself, such as a write of a record, and are too
 
526
  high-granular to be atomic from the application perspective
 
527
  (MySQL). One SQL statement could involve many BerkeleyDB
 
528
  auto-committed operations and thus BerkeleyDB auto-commit was of
 
529
  little use to MySQL.
 
530
 
 
531
  Secondly, instead of SQL standard savepoints, BerkeleyDB
 
532
  provided the concept of "nested transactions". In a nutshell,
 
533
  transactions could be arbitrarily nested, but when the parent
 
534
  transaction was committed or aborted, all its child (nested)
 
535
  transactions were handled committed or aborted as well.
 
536
  Commit of a nested transaction, in turn, made its changes
 
537
  visible, but not durable: it destroyed the nested transaction,
 
538
  all its changes would become available to the parent and
 
539
  currently active nested transactions of this parent.
 
540
 
 
541
  So the mechanism of nested transactions was employed to
 
542
  provide "all or nothing" guarantee of SQL statements
 
543
  required by the standard.
 
544
  A nested transaction would be created at start of each SQL
 
545
  statement, and destroyed (committed or aborted) at statement
 
546
  end. Such nested transaction was internally referred to as
 
547
  a "statement transaction" and gave birth to the term.
 
548
 
 
549
  <Historical note ends>
 
550
 
 
551
  Since then a statement transaction is started for each statement
 
552
  that accesses transactional tables or uses the binary log.  If
 
553
  the statement succeeds, the statement transaction is committed.
 
554
  If the statement fails, the transaction is rolled back. Commits
 
555
  of statement transactions are not durable -- each such
 
556
  transaction is nested in the normal transaction, and if the
 
557
  normal transaction is rolled back, the effects of all enclosed
 
558
  statement transactions are undone as well.  Technically,
 
559
  a statement transaction can be viewed as a savepoint which is
 
560
  maintained automatically in order to make effects of one
 
561
  statement atomic.
 
562
 
 
563
  The normal transaction is started by the user and is ended
 
564
  usually upon a user request as well. The normal transaction
 
565
  encloses transactions of all statements issued between
 
566
  its beginning and its end.
 
567
  In autocommit mode, the normal transaction is equivalent
 
568
  to the statement transaction.
 
569
 
 
570
  Since MySQL supports PSEA (pluggable storage engine
 
571
  architecture), more than one transactional engine can be
 
572
  active at a time. Hence transactions, from the server
 
573
  point of view, are always distributed. In particular,
 
574
  transactional state is maintained independently for each
 
575
  engine. In order to commit a transaction the two phase
 
576
  commit protocol is employed.
 
577
 
 
578
  Not all statements are executed in context of a transaction.
 
579
  Administrative and status information statements do not modify
 
580
  engine data, and thus do not start a statement transaction and
 
581
  also have no effect on the normal transaction. Examples of such
 
582
  statements are SHOW STATUS and RESET SLAVE.
 
583
 
 
584
  Similarly DDL statements are not transactional,
 
585
  and therefore a transaction is [almost] never started for a DDL
 
586
  statement. The difference between a DDL statement and a purely
 
587
  administrative statement though is that a DDL statement always
 
588
  commits the current transaction before proceeding, if there is
 
589
  any.
 
590
 
 
591
  At last, SQL statements that work with non-transactional
 
592
  engines also have no effect on the transaction state of the
 
593
  connection. Even though they are written to the binary log,
 
594
  and the binary log is, overall, transactional, the writes
 
595
  are done in "write-through" mode, directly to the binlog
 
596
  file, followed with a OS cache sync, in other words,
 
597
  bypassing the binlog undo log (translog).
 
598
  They do not commit the current normal transaction.
 
599
  A failure of a statement that uses non-transactional tables
 
600
  would cause a rollback of the statement transaction, but
 
601
  in case there no non-transactional tables are used,
 
602
  no statement transaction is started.
 
603
 
 
604
  Data layout
 
605
  -----------
 
606
 
 
607
  The server stores its transaction-related data in
 
608
  thd->transaction. This structure has two members of type
 
609
  THD_TRANS. These members correspond to the statement and
 
610
  normal transactions respectively:
 
611
 
 
612
  - thd->transaction.stmt contains a list of engines
 
613
  that are participating in the given statement
 
614
  - thd->transaction.all contains a list of engines that
 
615
  have participated in any of the statement transactions started
 
616
  within the context of the normal transaction.
 
617
  Each element of the list contains a pointer to the storage
 
618
  engine, engine-specific transactional data, and engine-specific
 
619
  transaction flags.
 
620
 
 
621
  In autocommit mode thd->transaction.all is empty.
 
622
  Instead, data of thd->transaction.stmt is
 
623
  used to commit/rollback the normal transaction.
 
624
 
 
625
  The list of registered engines has a few important properties:
 
626
  - no engine is registered in the list twice
 
627
  - engines are present in the list a reverse temporal order --
 
628
  new participants are always added to the beginning of the list.
 
629
 
 
630
  Transaction life cycle
 
631
  ----------------------
 
632
 
 
633
  When a new connection is established, thd->transaction
 
634
  members are initialized to an empty state.
 
635
  If a statement uses any tables, all affected engines
 
636
  are registered in the statement engine list. In
 
637
  non-autocommit mode, the same engines are registered in
 
638
  the normal transaction list.
 
639
  At the end of the statement, the server issues a commit
 
640
  or a roll back for all engines in the statement list.
 
641
  At this point transaction flags of an engine, if any, are
 
642
  propagated from the statement list to the list of the normal
 
643
  transaction.
 
644
  When commit/rollback is finished, the statement list is
 
645
  cleared. It will be filled in again by the next statement,
 
646
  and emptied again at the next statement's end.
 
647
 
 
648
  The normal transaction is committed in a similar way
 
649
  (by going over all engines in thd->transaction.all list)
 
650
  but at different times:
 
651
  - upon COMMIT SQL statement is issued by the user
 
652
  - implicitly, by the server, at the beginning of a DDL statement
 
653
  or SET AUTOCOMMIT={0|1} statement.
 
654
 
 
655
  The normal transaction can be rolled back as well:
 
656
  - if the user has requested so, by issuing ROLLBACK SQL
 
657
  statement
 
658
  - if one of the storage engines requested a rollback
 
659
  by setting thd->transaction_rollback_request. This may
 
660
  happen in case, e.g., when the transaction in the engine was
 
661
  chosen a victim of the internal deadlock resolution algorithm
 
662
  and rolled back internally. When such a situation happens, there
 
663
  is little the server can do and the only option is to rollback
 
664
  transactions in all other participating engines.  In this case
 
665
  the rollback is accompanied by an error sent to the user.
 
666
 
 
667
  As follows from the use cases above, the normal transaction
 
668
  is never committed when there is an outstanding statement
 
669
  transaction. In most cases there is no conflict, since
 
670
  commits of the normal transaction are issued by a stand-alone
 
671
  administrative or DDL statement, thus no outstanding statement
 
672
  transaction of the previous statement exists. Besides,
 
673
  all statements that manipulate with the normal transaction
 
674
  are prohibited in stored functions and triggers, therefore
 
675
  no conflicting situation can occur in a sub-statement either.
 
676
  The remaining rare cases when the server explicitly has
 
677
  to commit the statement transaction prior to committing the normal
 
678
  one cover error-handling scenarios (see for example
 
679
  SQLCOM_LOCK_TABLES).
 
680
 
 
681
  When committing a statement or a normal transaction, the server
 
682
  either uses the two-phase commit protocol, or issues a commit
 
683
  in each engine independently. The two-phase commit protocol
 
684
  is used only if:
 
685
  - all participating engines support two-phase commit (provide
 
686
    handlerton::prepare PSEA API call) and
 
687
  - transactions in at least two engines modify data (i.e. are
 
688
  not read-only).
 
689
 
 
690
  Note that the two phase commit is used for
 
691
  statement transactions, even though they are not durable anyway.
 
692
  This is done to ensure logical consistency of data in a multiple-
 
693
  engine transaction.
 
694
  For example, imagine that some day MySQL supports unique
 
695
  constraint checks deferred till the end of statement. In such
 
696
  case a commit in one of the engines may yield ER_DUP_KEY,
 
697
  and MySQL should be able to gracefully abort statement
 
698
  transactions of other participants.
 
699
 
 
700
  After the normal transaction has been committed,
 
701
  thd->transaction.all list is cleared.
 
702
 
 
703
  When a connection is closed, the current normal transaction, if
 
704
  any, is rolled back.
 
705
 
 
706
  Roles and responsibilities
 
707
  --------------------------
 
708
 
 
709
  The server has no way to know that an engine participates in
 
710
  the statement and a transaction has been started
 
711
  in it unless the engine says so. Thus, in order to be
 
712
  a part of a transaction, the engine must "register" itself.
 
713
  This is done by invoking trans_register_ha() server call.
 
714
  Normally the engine registers itself whenever handler::external_lock()
 
715
  is called. trans_register_ha() can be invoked many times: if
 
716
  an engine is already registered, the call does nothing.
 
717
  In case autocommit is not set, the engine must register itself
 
718
  twice -- both in the statement list and in the normal transaction
 
719
  list.
 
720
  In which list to register is a parameter of trans_register_ha().
 
721
 
 
722
  Note, that although the registration interface in itself is
 
723
  fairly clear, the current usage practice often leads to undesired
 
724
  effects. E.g. since a call to trans_register_ha() in most engines
 
725
  is embedded into implementation of handler::external_lock(), some
 
726
  DDL statements start a transaction (at least from the server
 
727
  point of view) even though they are not expected to. E.g.
 
728
  CREATE TABLE does not start a transaction, since
 
729
  handler::external_lock() is never called during CREATE TABLE. But
 
730
  CREATE TABLE ... SELECT does, since handler::external_lock() is
 
731
  called for the table that is being selected from. This has no
 
732
  practical effects currently, but must be kept in mind
 
733
  nevertheless.
 
734
 
 
735
  Once an engine is registered, the server will do the rest
 
736
  of the work.
 
737
 
 
738
  During statement execution, whenever any of data-modifying
 
739
  PSEA API methods is used, e.g. handler::write_row() or
 
740
  handler::update_row(), the read-write flag is raised in the
 
741
  statement transaction for the involved engine.
 
742
  Currently All PSEA calls are "traced", and the data can not be
 
743
  changed in a way other than issuing a PSEA call. Important:
 
744
  unless this invariant is preserved the server will not know that
 
745
  a transaction in a given engine is read-write and will not
 
746
  involve the two-phase commit protocol!
 
747
 
 
748
  At the end of a statement, server call
 
749
  ha_autocommit_or_rollback() is invoked. This call in turn
 
750
  invokes handlerton::prepare() for every involved engine.
 
751
  Prepare is followed by a call to handlerton::commit_one_phase()
 
752
  If a one-phase commit will suffice, handlerton::prepare() is not
 
753
  invoked and the server only calls handlerton::commit_one_phase().
 
754
  At statement commit, the statement-related read-write engine
 
755
  flag is propagated to the corresponding flag in the normal
 
756
  transaction.  When the commit is complete, the list of registered
 
757
  engines is cleared.
 
758
 
 
759
  Rollback is handled in a similar fashion.
 
760
 
 
761
  Additional notes on DDL and the normal transaction.
 
762
  ---------------------------------------------------
 
763
 
 
764
  DDLs and operations with non-transactional engines
 
765
  do not "register" in thd->transaction lists, and thus do not
 
766
  modify the transaction state. Besides, each DDL in
 
767
  MySQL is prefixed with an implicit normal transaction commit
 
768
  (a call to end_active_trans()), and thus leaves nothing
 
769
  to modify.
 
770
  However, as it has been pointed out with CREATE TABLE .. SELECT,
 
771
  some DDL statements can start a *new* transaction.
 
772
 
 
773
  Behaviour of the server in this case is currently badly
 
774
  defined.
 
775
  DDL statements use a form of "semantic" logging
 
776
  to maintain atomicity: if CREATE TABLE .. SELECT failed,
 
777
  the newly created table is deleted.
 
778
  In addition, some DDL statements issue interim transaction
 
779
  commits: e.g. ALTER Table issues a commit after data is copied
 
780
  from the original table to the internal temporary table. Other
 
781
  statements, e.g. CREATE TABLE ... SELECT do not always commit
 
782
  after itself.
 
783
  And finally there is a group of DDL statements such as
 
784
  RENAME/DROP Table that doesn't start a new transaction
 
785
  and doesn't commit.
 
786
 
 
787
  This diversity makes it hard to say what will happen if
 
788
  by chance a stored function is invoked during a DDL --
 
789
  whether any modifications it makes will be committed or not
 
790
  is not clear. Fortunately, SQL grammar of few DDLs allows
 
791
  invocation of a stored function.
 
792
 
 
793
  A consistent behaviour is perhaps to always commit the normal
 
794
  transaction after all DDLs, just like the statement transaction
 
795
  is always committed at the end of all statements.
 
796
*/
 
797
 
 
798
/**
 
799
  Register a storage engine for a transaction.
 
800
 
 
801
  Every storage engine MUST call this function when it starts
 
802
  a transaction or a statement (that is it must be called both for the
 
803
  "beginning of transaction" and "beginning of statement").
 
804
  Only storage engines registered for the transaction/statement
 
805
  will know when to commit/rollback it.
 
806
 
 
807
  @note
 
808
    trans_register_ha is idempotent - storage engine may register many
 
809
    times per transaction.
 
810
 
 
811
*/
 
812
void trans_register_ha(THD *thd, bool all, handlerton *ht_arg)
 
813
{
 
814
  THD_TRANS *trans;
 
815
  Ha_trx_info *ha_info;
 
816
 
 
817
  if (all)
 
818
  {
 
819
    trans= &thd->transaction.all;
 
820
    thd->server_status|= SERVER_STATUS_IN_TRANS;
 
821
  }
 
822
  else
 
823
    trans= &thd->transaction.stmt;
 
824
 
 
825
  ha_info= thd->ha_data[ht_arg->slot].ha_info + static_cast<unsigned>(all);
 
826
 
 
827
  if (ha_info->is_started())
 
828
    return; /* already registered, return */
 
829
 
 
830
  ha_info->register_ha(trans, ht_arg);
 
831
 
 
832
  trans->no_2pc|=(ht_arg->prepare==0);
 
833
  if (thd->transaction.xid_state.xid.is_null())
 
834
    thd->transaction.xid_state.xid.set(thd->query_id);
 
835
 
 
836
  return;
 
837
}
 
838
 
 
839
/**
 
840
  @retval
 
841
    0   ok
 
842
  @retval
 
843
    1   error, transaction was rolled back
 
844
*/
 
845
int ha_prepare(THD *thd)
 
846
{
 
847
  int error=0, all=1;
 
848
  THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt;
 
849
  Ha_trx_info *ha_info= trans->ha_list;
 
850
  if (ha_info)
 
851
  {
 
852
    for (; ha_info; ha_info= ha_info->next())
 
853
    {
 
854
      int err;
 
855
      handlerton *ht= ha_info->ht();
 
856
      status_var_increment(thd->status_var.ha_prepare_count);
 
857
      if (ht->prepare)
 
858
      {
 
859
        if ((err= ht->prepare(ht, thd, all)))
 
860
        {
 
861
          my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
 
862
          ha_rollback_trans(thd, all);
 
863
          error=1;
 
864
          break;
 
865
        }
 
866
      }
 
867
      else
 
868
      {
 
869
        push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
870
                            ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
 
871
                            ha_resolve_storage_engine_name(ht));
 
872
      }
 
873
    }
 
874
  }
 
875
  return(error);
 
876
}
 
877
 
 
878
/**
 
879
  Check if we can skip the two-phase commit.
 
880
 
 
881
  A helper function to evaluate if two-phase commit is mandatory.
 
882
  As a side effect, propagates the read-only/read-write flags
 
883
  of the statement transaction to its enclosing normal transaction.
 
884
 
 
885
  @retval true   we must run a two-phase commit. Returned
 
886
                 if we have at least two engines with read-write changes.
 
887
  @retval false  Don't need two-phase commit. Even if we have two
 
888
                 transactional engines, we can run two independent
 
889
                 commits if changes in one of the engines are read-only.
 
890
*/
 
891
 
 
892
static
 
893
bool
 
894
ha_check_and_coalesce_trx_read_only(THD *thd, Ha_trx_info *ha_list,
 
895
                                    bool all)
 
896
{
 
897
  /* The number of storage engines that have actual changes. */
 
898
  unsigned rw_ha_count= 0;
 
899
  Ha_trx_info *ha_info;
 
900
 
 
901
  for (ha_info= ha_list; ha_info; ha_info= ha_info->next())
 
902
  {
 
903
    if (ha_info->is_trx_read_write())
 
904
      ++rw_ha_count;
 
905
 
 
906
    if (! all)
 
907
    {
 
908
      Ha_trx_info *ha_info_all= &thd->ha_data[ha_info->ht()->slot].ha_info[1];
 
909
      assert(ha_info != ha_info_all);
 
910
      /*
 
911
        Merge read-only/read-write information about statement
 
912
        transaction to its enclosing normal transaction. Do this
 
913
        only if in a real transaction -- that is, if we know
 
914
        that ha_info_all is registered in thd->transaction.all.
 
915
        Since otherwise we only clutter the normal transaction flags.
 
916
      */
 
917
      if (ha_info_all->is_started()) /* false if autocommit. */
 
918
        ha_info_all->coalesce_trx_with(ha_info);
 
919
    }
 
920
    else if (rw_ha_count > 1)
 
921
    {
 
922
      /*
 
923
        It is a normal transaction, so we don't need to merge read/write
 
924
        information up, and the need for two-phase commit has been
 
925
        already established. Break the loop prematurely.
 
926
      */
 
927
      break;
 
928
    }
 
929
  }
 
930
  return rw_ha_count > 1;
 
931
}
 
932
 
 
933
 
 
934
/**
 
935
  @retval
 
936
    0   ok
 
937
  @retval
 
938
    1   transaction was rolled back
 
939
  @retval
 
940
    2   error during commit, data may be inconsistent
 
941
 
 
942
  @todo
 
943
    Since we don't support nested statement transactions in 5.0,
 
944
    we can't commit or rollback stmt transactions while we are inside
 
945
    stored functions or triggers. So we simply do nothing now.
 
946
    TODO: This should be fixed in later ( >= 5.1) releases.
 
947
*/
 
948
int ha_commit_trans(THD *thd, bool all)
 
949
{
 
950
  int error= 0, cookie= 0;
 
951
  /*
 
952
    'all' means that this is either an explicit commit issued by
 
953
    user, or an implicit commit issued by a DDL.
 
954
  */
 
955
  THD_TRANS *trans= all ? &thd->transaction.all : &thd->transaction.stmt;
 
956
  bool is_real_trans= all || thd->transaction.all.ha_list == 0;
 
957
  Ha_trx_info *ha_info= trans->ha_list;
 
958
  my_xid xid= thd->transaction.xid_state.xid.get_my_xid();
 
959
 
 
960
  /*
 
961
    We must not commit the normal transaction if a statement
 
962
    transaction is pending. Otherwise statement transaction
 
963
    flags will not get propagated to its normal transaction's
 
964
    counterpart.
 
965
  */
 
966
  assert(thd->transaction.stmt.ha_list == NULL ||
 
967
              trans == &thd->transaction.stmt);
 
968
 
 
969
  if (thd->in_sub_stmt)
 
970
  {
 
971
    /*
 
972
      Since we don't support nested statement transactions in 5.0,
 
973
      we can't commit or rollback stmt transactions while we are inside
 
974
      stored functions or triggers. So we simply do nothing now.
 
975
      TODO: This should be fixed in later ( >= 5.1) releases.
 
976
    */
 
977
    if (!all)
 
978
      return(0);
 
979
    /*
 
980
      We assume that all statements which commit or rollback main transaction
 
981
      are prohibited inside of stored functions or triggers. So they should
 
982
      bail out with error even before ha_commit_trans() call. To be 100% safe
 
983
      let us throw error in non-debug builds.
 
984
    */
 
985
    assert(0);
 
986
    my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
 
987
    return(2);
 
988
  }
 
989
  if (ha_info)
 
990
  {
 
991
    bool must_2pc;
 
992
 
 
993
    if (is_real_trans && wait_if_global_read_lock(thd, 0, 0))
 
994
    {
 
995
      ha_rollback_trans(thd, all);
 
996
      return(1);
 
997
    }
 
998
 
 
999
    if (   is_real_trans
 
1000
        && opt_readonly
 
1001
        && ! thd->slave_thread
 
1002
       )
 
1003
    {
 
1004
      my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only");
 
1005
      ha_rollback_trans(thd, all);
 
1006
      error= 1;
 
1007
      goto end;
 
1008
    }
 
1009
 
 
1010
    must_2pc= ha_check_and_coalesce_trx_read_only(thd, ha_info, all);
 
1011
 
 
1012
    if (!trans->no_2pc && must_2pc)
 
1013
    {
 
1014
      for (; ha_info && !error; ha_info= ha_info->next())
 
1015
      {
 
1016
        int err;
 
1017
        handlerton *ht= ha_info->ht();
 
1018
        /*
 
1019
          Do not call two-phase commit if this particular
 
1020
          transaction is read-only. This allows for simpler
 
1021
          implementation in engines that are always read-only.
 
1022
        */
 
1023
        if (! ha_info->is_trx_read_write())
 
1024
          continue;
 
1025
        /*
 
1026
          Sic: we know that prepare() is not NULL since otherwise
 
1027
          trans->no_2pc would have been set.
 
1028
        */
 
1029
        if ((err= ht->prepare(ht, thd, all)))
 
1030
        {
 
1031
          my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
 
1032
          error= 1;
 
1033
        }
 
1034
        status_var_increment(thd->status_var.ha_prepare_count);
 
1035
      }
 
1036
      if (error || (is_real_trans && xid &&
 
1037
                    (error= !(cookie= tc_log->log_xid(thd, xid)))))
 
1038
      {
 
1039
        ha_rollback_trans(thd, all);
 
1040
        error= 1;
 
1041
        goto end;
 
1042
      }
 
1043
    }
 
1044
    error=ha_commit_one_phase(thd, all) ? (cookie ? 2 : 1) : 0;
 
1045
    if (cookie)
 
1046
      tc_log->unlog(cookie, xid);
 
1047
end:
 
1048
    if (is_real_trans)
 
1049
      start_waiting_global_read_lock(thd);
 
1050
  }
 
1051
  return(error);
 
1052
}
 
1053
 
 
1054
/**
 
1055
  @note
 
1056
  This function does not care about global read lock. A caller should.
 
1057
*/
 
1058
int ha_commit_one_phase(THD *thd, bool all)
 
1059
{
 
1060
  int error=0;
 
1061
  THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt;
 
1062
  bool is_real_trans=all || thd->transaction.all.ha_list == 0;
 
1063
  Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
 
1064
  if (ha_info)
 
1065
  {
 
1066
    for (; ha_info; ha_info= ha_info_next)
 
1067
    {
 
1068
      int err;
 
1069
      handlerton *ht= ha_info->ht();
 
1070
      if ((err= ht->commit(ht, thd, all)))
 
1071
      {
 
1072
        my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
 
1073
        error=1;
 
1074
      }
 
1075
      status_var_increment(thd->status_var.ha_commit_count);
 
1076
      ha_info_next= ha_info->next();
 
1077
      ha_info->reset(); /* keep it conveniently zero-filled */
 
1078
    }
 
1079
    trans->ha_list= 0;
 
1080
    trans->no_2pc=0;
 
1081
    if (is_real_trans)
 
1082
      thd->transaction.xid_state.xid.null();
 
1083
    if (all)
 
1084
    {
 
1085
      thd->variables.tx_isolation=thd->session_tx_isolation;
 
1086
      thd->transaction.cleanup();
 
1087
    }
 
1088
  }
 
1089
  return(error);
 
1090
}
 
1091
 
 
1092
 
 
1093
int ha_rollback_trans(THD *thd, bool all)
 
1094
{
 
1095
  int error=0;
 
1096
  THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt;
 
1097
  Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
 
1098
  bool is_real_trans=all || thd->transaction.all.ha_list == 0;
 
1099
 
 
1100
  /*
 
1101
    We must not rollback the normal transaction if a statement
 
1102
    transaction is pending.
 
1103
  */
 
1104
  assert(thd->transaction.stmt.ha_list == NULL ||
 
1105
              trans == &thd->transaction.stmt);
 
1106
 
 
1107
  if (thd->in_sub_stmt)
 
1108
  {
 
1109
    /*
 
1110
      If we are inside stored function or trigger we should not commit or
 
1111
      rollback current statement transaction. See comment in ha_commit_trans()
 
1112
      call for more information.
 
1113
    */
 
1114
    if (!all)
 
1115
      return(0);
 
1116
    assert(0);
 
1117
    my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
 
1118
    return(1);
 
1119
  }
 
1120
  if (ha_info)
 
1121
  {
 
1122
    for (; ha_info; ha_info= ha_info_next)
 
1123
    {
 
1124
      int err;
 
1125
      handlerton *ht= ha_info->ht();
 
1126
      if ((err= ht->rollback(ht, thd, all)))
 
1127
      { // cannot happen
 
1128
        my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
 
1129
        error=1;
 
1130
      }
 
1131
      status_var_increment(thd->status_var.ha_rollback_count);
 
1132
      ha_info_next= ha_info->next();
 
1133
      ha_info->reset(); /* keep it conveniently zero-filled */
 
1134
    }
 
1135
    trans->ha_list= 0;
 
1136
    trans->no_2pc=0;
 
1137
    if (is_real_trans)
 
1138
      thd->transaction.xid_state.xid.null();
 
1139
    if (all)
 
1140
    {
 
1141
      thd->variables.tx_isolation=thd->session_tx_isolation;
 
1142
      thd->transaction.cleanup();
 
1143
    }
 
1144
  }
 
1145
  if (all)
 
1146
    thd->transaction_rollback_request= false;
 
1147
 
 
1148
  /*
 
1149
    If a non-transactional table was updated, warn; don't warn if this is a
 
1150
    slave thread (because when a slave thread executes a ROLLBACK, it has
 
1151
    been read from the binary log, so it's 100% sure and normal to produce
 
1152
    error ER_WARNING_NOT_COMPLETE_ROLLBACK. If we sent the warning to the
 
1153
    slave SQL thread, it would not stop the thread but just be printed in
 
1154
    the error log; but we don't want users to wonder why they have this
 
1155
    message in the error log, so we don't send it.
 
1156
  */
 
1157
  if (is_real_trans && thd->transaction.all.modified_non_trans_table &&
 
1158
      !thd->slave_thread && thd->killed != THD::KILL_CONNECTION)
 
1159
    push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
1160
                 ER_WARNING_NOT_COMPLETE_ROLLBACK,
 
1161
                 ER(ER_WARNING_NOT_COMPLETE_ROLLBACK));
 
1162
  return(error);
 
1163
}
 
1164
 
 
1165
/**
 
1166
  This is used to commit or rollback a single statement depending on
 
1167
  the value of error.
 
1168
 
 
1169
  @note
 
1170
    Note that if the autocommit is on, then the following call inside
 
1171
    InnoDB will commit or rollback the whole transaction (= the statement). The
 
1172
    autocommit mechanism built into InnoDB is based on counting locks, but if
 
1173
    the user has used LOCK TABLES then that mechanism does not know to do the
 
1174
    commit.
 
1175
*/
 
1176
int ha_autocommit_or_rollback(THD *thd, int error)
 
1177
{
 
1178
  if (thd->transaction.stmt.ha_list)
 
1179
  {
 
1180
    if (!error)
 
1181
    {
 
1182
      if (ha_commit_trans(thd, 0))
 
1183
        error=1;
 
1184
    }
 
1185
    else 
 
1186
    {
 
1187
      (void) ha_rollback_trans(thd, 0);
 
1188
      if (thd->transaction_rollback_request && !thd->in_sub_stmt)
 
1189
        (void) ha_rollback(thd);
 
1190
    }
 
1191
 
 
1192
    thd->variables.tx_isolation=thd->session_tx_isolation;
 
1193
  }
 
1194
  return(error);
 
1195
}
 
1196
 
 
1197
 
 
1198
struct xahton_st {
 
1199
  XID *xid;
 
1200
  int result;
 
1201
};
 
1202
 
 
1203
static bool xacommit_handlerton(THD *unused1 __attribute__((unused)),
 
1204
                                plugin_ref plugin,
 
1205
                                void *arg)
 
1206
{
 
1207
  handlerton *hton= plugin_data(plugin, handlerton *);
 
1208
  if (hton->state == SHOW_OPTION_YES && hton->recover)
 
1209
  {
 
1210
    hton->commit_by_xid(hton, ((struct xahton_st *)arg)->xid);
 
1211
    ((struct xahton_st *)arg)->result= 0;
 
1212
  }
 
1213
  return false;
 
1214
}
 
1215
 
 
1216
static bool xarollback_handlerton(THD *unused1 __attribute__((unused)),
 
1217
                                  plugin_ref plugin,
 
1218
                                  void *arg)
 
1219
{
 
1220
  handlerton *hton= plugin_data(plugin, handlerton *);
 
1221
  if (hton->state == SHOW_OPTION_YES && hton->recover)
 
1222
  {
 
1223
    hton->rollback_by_xid(hton, ((struct xahton_st *)arg)->xid);
 
1224
    ((struct xahton_st *)arg)->result= 0;
 
1225
  }
 
1226
  return false;
 
1227
}
 
1228
 
 
1229
 
 
1230
int ha_commit_or_rollback_by_xid(XID *xid, bool commit)
 
1231
{
 
1232
  struct xahton_st xaop;
 
1233
  xaop.xid= xid;
 
1234
  xaop.result= 1;
 
1235
 
 
1236
  plugin_foreach(NULL, commit ? xacommit_handlerton : xarollback_handlerton,
 
1237
                 DRIZZLE_STORAGE_ENGINE_PLUGIN, &xaop);
 
1238
 
 
1239
  return xaop.result;
 
1240
}
 
1241
 
 
1242
/**
 
1243
  recover() step of xa.
 
1244
 
 
1245
  @note
 
1246
    there are three modes of operation:
 
1247
    - automatic recover after a crash
 
1248
    in this case commit_list != 0, tc_heuristic_recover==0
 
1249
    all xids from commit_list are committed, others are rolled back
 
1250
    - manual (heuristic) recover
 
1251
    in this case commit_list==0, tc_heuristic_recover != 0
 
1252
    DBA has explicitly specified that all prepared transactions should
 
1253
    be committed (or rolled back).
 
1254
    - no recovery (MySQL did not detect a crash)
 
1255
    in this case commit_list==0, tc_heuristic_recover == 0
 
1256
    there should be no prepared transactions in this case.
 
1257
*/
 
1258
struct xarecover_st
 
1259
{
 
1260
  int len, found_foreign_xids, found_my_xids;
 
1261
  XID *list;
 
1262
  HASH *commit_list;
 
1263
  bool dry_run;
 
1264
};
 
1265
 
 
1266
static bool xarecover_handlerton(THD *unused __attribute__((unused)),
 
1267
                                 plugin_ref plugin,
 
1268
                                 void *arg)
 
1269
{
 
1270
  handlerton *hton= plugin_data(plugin, handlerton *);
 
1271
  struct xarecover_st *info= (struct xarecover_st *) arg;
 
1272
  int got;
 
1273
 
 
1274
  if (hton->state == SHOW_OPTION_YES && hton->recover)
 
1275
  {
 
1276
    while ((got= hton->recover(hton, info->list, info->len)) > 0 )
 
1277
    {
 
1278
      sql_print_information(_("Found %d prepared transaction(s) in %s"),
 
1279
                            got, ha_resolve_storage_engine_name(hton));
 
1280
      for (int i=0; i < got; i ++)
 
1281
      {
 
1282
        my_xid x=info->list[i].get_my_xid();
 
1283
        if (!x) // not "mine" - that is generated by external TM
 
1284
        {
 
1285
          xid_cache_insert(info->list+i, XA_PREPARED);
 
1286
          info->found_foreign_xids++;
 
1287
          continue;
 
1288
        }
 
1289
        if (info->dry_run)
 
1290
        {
 
1291
          info->found_my_xids++;
 
1292
          continue;
 
1293
        }
 
1294
        // recovery mode
 
1295
        if (info->commit_list ?
 
1296
            hash_search(info->commit_list, (uchar *)&x, sizeof(x)) != 0 :
 
1297
            tc_heuristic_recover == TC_HEURISTIC_RECOVER_COMMIT)
 
1298
        {
 
1299
          hton->commit_by_xid(hton, info->list+i);
 
1300
        }
 
1301
        else
 
1302
        {
 
1303
          hton->rollback_by_xid(hton, info->list+i);
 
1304
        }
 
1305
      }
 
1306
      if (got < info->len)
 
1307
        break;
 
1308
    }
 
1309
  }
 
1310
  return false;
 
1311
}
 
1312
 
 
1313
int ha_recover(HASH *commit_list)
 
1314
{
 
1315
  struct xarecover_st info;
 
1316
  info.found_foreign_xids= info.found_my_xids= 0;
 
1317
  info.commit_list= commit_list;
 
1318
  info.dry_run= (info.commit_list==0 && tc_heuristic_recover==0);
 
1319
  info.list= NULL;
 
1320
 
 
1321
  /* commit_list and tc_heuristic_recover cannot be set both */
 
1322
  assert(info.commit_list==0 || tc_heuristic_recover==0);
 
1323
  /* if either is set, total_ha_2pc must be set too */
 
1324
  assert(info.dry_run || total_ha_2pc>(uint32_t)opt_bin_log);
 
1325
 
 
1326
  if (total_ha_2pc <= (uint32_t)opt_bin_log)
 
1327
    return(0);
 
1328
 
 
1329
  if (info.commit_list)
 
1330
    sql_print_information(_("Starting crash recovery..."));
 
1331
 
 
1332
 
 
1333
#ifndef WILL_BE_DELETED_LATER
 
1334
 
 
1335
  /*
 
1336
    for now, only InnoDB supports 2pc. It means we can always safely
 
1337
    rollback all pending transactions, without risking inconsistent data
 
1338
  */
 
1339
 
 
1340
  assert(total_ha_2pc == (uint32_t) opt_bin_log+1); // only InnoDB and binlog
 
1341
  tc_heuristic_recover= TC_HEURISTIC_RECOVER_ROLLBACK; // forcing ROLLBACK
 
1342
  info.dry_run=false;
 
1343
#endif
 
1344
 
 
1345
 
 
1346
  for (info.len= MAX_XID_LIST_SIZE ; 
 
1347
       info.list==0 && info.len > MIN_XID_LIST_SIZE; info.len/=2)
 
1348
  {
 
1349
    info.list=(XID *)my_malloc(info.len*sizeof(XID), MYF(0));
 
1350
  }
 
1351
  if (!info.list)
 
1352
  {
 
1353
    sql_print_error(ER(ER_OUTOFMEMORY), info.len*sizeof(XID));
 
1354
    return(1);
 
1355
  }
 
1356
 
 
1357
  plugin_foreach(NULL, xarecover_handlerton, 
 
1358
                 DRIZZLE_STORAGE_ENGINE_PLUGIN, &info);
 
1359
 
 
1360
  my_free((uchar*)info.list, MYF(0));
 
1361
  if (info.found_foreign_xids)
 
1362
    sql_print_warning(_("Found %d prepared XA transactions"), 
 
1363
                      info.found_foreign_xids);
 
1364
  if (info.dry_run && info.found_my_xids)
 
1365
  {
 
1366
    sql_print_error(_("Found %d prepared transactions! It means that drizzled "
 
1367
                    "was not shut down properly last time and critical "
 
1368
                    "recovery information (last binlog or %s file) was "
 
1369
                    "manually deleted after a crash. You have to start "
 
1370
                    "drizzled with the --tc-heuristic-recover switch to "
 
1371
                    "commit or rollback pending transactions."),
 
1372
                    info.found_my_xids, opt_tc_log_file);
 
1373
    return(1);
 
1374
  }
 
1375
  if (info.commit_list)
 
1376
    sql_print_information(_("Crash recovery finished."));
 
1377
  return(0);
 
1378
}
 
1379
 
 
1380
/**
 
1381
  return the list of XID's to a client, the same way SHOW commands do.
 
1382
 
 
1383
  @note
 
1384
    I didn't find in XA specs that an RM cannot return the same XID twice,
 
1385
    so mysql_xa_recover does not filter XID's to ensure uniqueness.
 
1386
    It can be easily fixed later, if necessary.
 
1387
*/
 
1388
bool mysql_xa_recover(THD *thd)
 
1389
{
 
1390
  List<Item> field_list;
 
1391
  Protocol *protocol= thd->protocol;
 
1392
  int i=0;
 
1393
  XID_STATE *xs;
 
1394
 
 
1395
  field_list.push_back(new Item_int("formatID", 0, MY_INT32_NUM_DECIMAL_DIGITS));
 
1396
  field_list.push_back(new Item_int("gtrid_length", 0, MY_INT32_NUM_DECIMAL_DIGITS));
 
1397
  field_list.push_back(new Item_int("bqual_length", 0, MY_INT32_NUM_DECIMAL_DIGITS));
 
1398
  field_list.push_back(new Item_empty_string("data",XIDDATASIZE));
 
1399
 
 
1400
  if (protocol->send_fields(&field_list,
 
1401
                            Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
 
1402
    return(1);
 
1403
 
 
1404
  pthread_mutex_lock(&LOCK_xid_cache);
 
1405
  while ((xs= (XID_STATE*)hash_element(&xid_cache, i++)))
 
1406
  {
 
1407
    if (xs->xa_state==XA_PREPARED)
 
1408
    {
 
1409
      protocol->prepare_for_resend();
 
1410
      protocol->store_int64_t((int64_t)xs->xid.formatID, false);
 
1411
      protocol->store_int64_t((int64_t)xs->xid.gtrid_length, false);
 
1412
      protocol->store_int64_t((int64_t)xs->xid.bqual_length, false);
 
1413
      protocol->store(xs->xid.data, xs->xid.gtrid_length+xs->xid.bqual_length,
 
1414
                      &my_charset_bin);
 
1415
      if (protocol->write())
 
1416
      {
 
1417
        pthread_mutex_unlock(&LOCK_xid_cache);
 
1418
        return(1);
 
1419
      }
 
1420
    }
 
1421
  }
 
1422
 
 
1423
  pthread_mutex_unlock(&LOCK_xid_cache);
 
1424
  my_eof(thd);
 
1425
  return(0);
 
1426
}
 
1427
 
 
1428
/**
 
1429
  @details
 
1430
  This function should be called when MySQL sends rows of a SELECT result set
 
1431
  or the EOF mark to the client. It releases a possible adaptive hash index
 
1432
  S-latch held by thd in InnoDB and also releases a possible InnoDB query
 
1433
  FIFO ticket to enter InnoDB. To save CPU time, InnoDB allows a thd to
 
1434
  keep them over several calls of the InnoDB handler interface when a join
 
1435
  is executed. But when we let the control to pass to the client they have
 
1436
  to be released because if the application program uses mysql_use_result(),
 
1437
  it may deadlock on the S-latch if the application on another connection
 
1438
  performs another SQL query. In MySQL-4.1 this is even more important because
 
1439
  there a connection can have several SELECT queries open at the same time.
 
1440
 
 
1441
  @param thd           the thread handle of the current connection
 
1442
 
 
1443
  @return
 
1444
    always 0
 
1445
*/
 
1446
static bool release_temporary_latches(THD *thd, plugin_ref plugin,
 
1447
                                      void *unused __attribute__((unused)))
 
1448
{
 
1449
  handlerton *hton= plugin_data(plugin, handlerton *);
 
1450
 
 
1451
  if (hton->state == SHOW_OPTION_YES && hton->release_temporary_latches)
 
1452
    hton->release_temporary_latches(hton, thd);
 
1453
 
 
1454
  return false;
 
1455
}
 
1456
 
 
1457
 
 
1458
int ha_release_temporary_latches(THD *thd)
 
1459
{
 
1460
  plugin_foreach(thd, release_temporary_latches, DRIZZLE_STORAGE_ENGINE_PLUGIN, 
 
1461
                 NULL);
 
1462
 
 
1463
  return 0;
 
1464
}
 
1465
 
 
1466
int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv)
 
1467
{
 
1468
  int error=0;
 
1469
  THD_TRANS *trans= (thd->in_sub_stmt ? &thd->transaction.stmt :
 
1470
                                        &thd->transaction.all);
 
1471
  Ha_trx_info *ha_info, *ha_info_next;
 
1472
 
 
1473
  trans->no_2pc=0;
 
1474
  /*
 
1475
    rolling back to savepoint in all storage engines that were part of the
 
1476
    transaction when the savepoint was set
 
1477
  */
 
1478
  for (ha_info= sv->ha_list; ha_info; ha_info= ha_info->next())
 
1479
  {
 
1480
    int err;
 
1481
    handlerton *ht= ha_info->ht();
 
1482
    assert(ht);
 
1483
    assert(ht->savepoint_set != 0);
 
1484
    if ((err= ht->savepoint_rollback(ht, thd,
 
1485
                                     (uchar *)(sv+1)+ht->savepoint_offset)))
 
1486
    { // cannot happen
 
1487
      my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
 
1488
      error=1;
 
1489
    }
 
1490
    status_var_increment(thd->status_var.ha_savepoint_rollback_count);
 
1491
    trans->no_2pc|= ht->prepare == 0;
 
1492
  }
 
1493
  /*
 
1494
    rolling back the transaction in all storage engines that were not part of
 
1495
    the transaction when the savepoint was set
 
1496
  */
 
1497
  for (ha_info= trans->ha_list; ha_info != sv->ha_list;
 
1498
       ha_info= ha_info_next)
 
1499
  {
 
1500
    int err;
 
1501
    handlerton *ht= ha_info->ht();
 
1502
    if ((err= ht->rollback(ht, thd, !thd->in_sub_stmt)))
 
1503
    { // cannot happen
 
1504
      my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
 
1505
      error=1;
 
1506
    }
 
1507
    status_var_increment(thd->status_var.ha_rollback_count);
 
1508
    ha_info_next= ha_info->next();
 
1509
    ha_info->reset(); /* keep it conveniently zero-filled */
 
1510
  }
 
1511
  trans->ha_list= sv->ha_list;
 
1512
  return(error);
 
1513
}
 
1514
 
 
1515
/**
 
1516
  @note
 
1517
  according to the sql standard (ISO/IEC 9075-2:2003)
 
1518
  section "4.33.4 SQL-statements and transaction states",
 
1519
  SAVEPOINT is *not* transaction-initiating SQL-statement
 
1520
*/
 
1521
int ha_savepoint(THD *thd, SAVEPOINT *sv)
 
1522
{
 
1523
  int error=0;
 
1524
  THD_TRANS *trans= (thd->in_sub_stmt ? &thd->transaction.stmt :
 
1525
                                        &thd->transaction.all);
 
1526
  Ha_trx_info *ha_info= trans->ha_list;
 
1527
  for (; ha_info; ha_info= ha_info->next())
 
1528
  {
 
1529
    int err;
 
1530
    handlerton *ht= ha_info->ht();
 
1531
    assert(ht);
 
1532
    if (! ht->savepoint_set)
 
1533
    {
 
1534
      my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "SAVEPOINT");
 
1535
      error=1;
 
1536
      break;
 
1537
    }
 
1538
    if ((err= ht->savepoint_set(ht, thd, (uchar *)(sv+1)+ht->savepoint_offset)))
 
1539
    { // cannot happen
 
1540
      my_error(ER_GET_ERRNO, MYF(0), err);
 
1541
      error=1;
 
1542
    }
 
1543
    status_var_increment(thd->status_var.ha_savepoint_count);
 
1544
  }
 
1545
  /*
 
1546
    Remember the list of registered storage engines. All new
 
1547
    engines are prepended to the beginning of the list.
 
1548
  */
 
1549
  sv->ha_list= trans->ha_list;
 
1550
  return(error);
 
1551
}
 
1552
 
 
1553
int ha_release_savepoint(THD *thd, SAVEPOINT *sv)
 
1554
{
 
1555
  int error=0;
 
1556
  Ha_trx_info *ha_info= sv->ha_list;
 
1557
 
 
1558
  for (; ha_info; ha_info= ha_info->next())
 
1559
  {
 
1560
    int err;
 
1561
    handlerton *ht= ha_info->ht();
 
1562
    /* Savepoint life time is enclosed into transaction life time. */
 
1563
    assert(ht);
 
1564
    if (!ht->savepoint_release)
 
1565
      continue;
 
1566
    if ((err= ht->savepoint_release(ht, thd,
 
1567
                                    (uchar *)(sv+1) + ht->savepoint_offset)))
 
1568
    { // cannot happen
 
1569
      my_error(ER_GET_ERRNO, MYF(0), err);
 
1570
      error=1;
 
1571
    }
 
1572
  }
 
1573
  return(error);
 
1574
}
 
1575
 
 
1576
 
 
1577
static bool snapshot_handlerton(THD *thd, plugin_ref plugin, void *arg)
 
1578
{
 
1579
  handlerton *hton= plugin_data(plugin, handlerton *);
 
1580
  if (hton->state == SHOW_OPTION_YES &&
 
1581
      hton->start_consistent_snapshot)
 
1582
  {
 
1583
    hton->start_consistent_snapshot(hton, thd);
 
1584
    *((bool *)arg)= false;
 
1585
  }
 
1586
  return false;
 
1587
}
 
1588
 
 
1589
int ha_start_consistent_snapshot(THD *thd)
 
1590
{
 
1591
  bool warn= true;
 
1592
 
 
1593
  plugin_foreach(thd, snapshot_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN, &warn);
 
1594
 
 
1595
  /*
 
1596
    Same idea as when one wants to CREATE TABLE in one engine which does not
 
1597
    exist:
 
1598
  */
 
1599
  if (warn)
 
1600
    push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
 
1601
                 "This MySQL server does not support any "
 
1602
                 "consistent-read capable storage engine");
 
1603
  return 0;
 
1604
}
 
1605
 
 
1606
 
 
1607
static bool flush_handlerton(THD *thd __attribute__((unused)),
 
1608
                             plugin_ref plugin,
 
1609
                             void *arg __attribute__((unused)))
 
1610
{
 
1611
  handlerton *hton= plugin_data(plugin, handlerton *);
 
1612
  if (hton->state == SHOW_OPTION_YES && hton->flush_logs && 
 
1613
      hton->flush_logs(hton))
 
1614
    return true;
 
1615
  return false;
 
1616
}
 
1617
 
 
1618
 
 
1619
bool ha_flush_logs(handlerton *db_type)
 
1620
{
 
1621
  if (db_type == NULL)
 
1622
  {
 
1623
    if (plugin_foreach(NULL, flush_handlerton,
 
1624
                          DRIZZLE_STORAGE_ENGINE_PLUGIN, 0))
 
1625
      return true;
 
1626
  }
 
1627
  else
 
1628
  {
 
1629
    if (db_type->state != SHOW_OPTION_YES ||
 
1630
        (db_type->flush_logs && db_type->flush_logs(db_type)))
 
1631
      return true;
 
1632
  }
 
1633
  return false;
 
1634
}
 
1635
 
 
1636
static const char *check_lowercase_names(handler *file, const char *path,
 
1637
                                         char *tmp_path)
 
1638
{
 
1639
  if (lower_case_table_names != 2 || (file->ha_table_flags() & HA_FILE_BASED))
 
1640
    return path;
 
1641
 
 
1642
  /* Ensure that table handler get path in lower case */
 
1643
  if (tmp_path != path)
 
1644
    stpcpy(tmp_path, path);
 
1645
 
 
1646
  /*
 
1647
    we only should turn into lowercase database/table part
 
1648
    so start the process after homedirectory
 
1649
  */
 
1650
  my_casedn_str(files_charset_info, tmp_path + mysql_data_home_len);
 
1651
  return tmp_path;
 
1652
}
 
1653
 
 
1654
 
 
1655
/**
 
1656
  An interceptor to hijack the text of the error message without
 
1657
  setting an error in the thread. We need the text to present it
 
1658
  in the form of a warning to the user.
 
1659
*/
 
1660
 
 
1661
struct Ha_delete_table_error_handler: public Internal_error_handler
 
1662
{
 
1663
public:
 
1664
  virtual bool handle_error(uint sql_errno,
 
1665
                            const char *message,
 
1666
                            DRIZZLE_ERROR::enum_warning_level level,
 
1667
                            THD *thd);
 
1668
  char buff[DRIZZLE_ERRMSG_SIZE];
 
1669
};
 
1670
 
 
1671
 
 
1672
bool
 
1673
Ha_delete_table_error_handler::
 
1674
handle_error(uint sql_errno  __attribute__((unused)),
 
1675
             const char *message,
 
1676
             DRIZZLE_ERROR::enum_warning_level level __attribute__((unused)),
 
1677
             THD *thd __attribute__((unused)))
 
1678
{
 
1679
  /* Grab the error message */
 
1680
  strmake(buff, message, sizeof(buff)-1);
 
1681
  return true;
 
1682
}
 
1683
 
 
1684
 
 
1685
/**
 
1686
  This should return ENOENT if the file doesn't exists.
 
1687
  The .frm file will be deleted only if we return 0 or ENOENT
 
1688
*/
 
1689
int ha_delete_table(THD *thd, handlerton *table_type, const char *path,
 
1690
                    const char *db, const char *alias, bool generate_warning)
 
1691
{
 
1692
  handler *file;
 
1693
  char tmp_path[FN_REFLEN];
 
1694
  int error;
 
1695
  Table dummy_table;
 
1696
  TABLE_SHARE dummy_share;
 
1697
 
 
1698
  memset(&dummy_table, 0, sizeof(dummy_table));
 
1699
  memset(&dummy_share, 0, sizeof(dummy_share));
 
1700
  dummy_table.s= &dummy_share;
 
1701
 
 
1702
  /* DB_TYPE_UNKNOWN is used in ALTER Table when renaming only .frm files */
 
1703
  if (table_type == NULL ||
 
1704
      ! (file=get_new_handler((TABLE_SHARE*)0, thd->mem_root, table_type)))
 
1705
    return(ENOENT);
 
1706
 
 
1707
  path= check_lowercase_names(file, path, tmp_path);
 
1708
  if ((error= file->ha_delete_table(path)) && generate_warning)
 
1709
  {
 
1710
    /*
 
1711
      Because file->print_error() use my_error() to generate the error message
 
1712
      we use an internal error handler to intercept it and store the text
 
1713
      in a temporary buffer. Later the message will be presented to user
 
1714
      as a warning.
 
1715
    */
 
1716
    Ha_delete_table_error_handler ha_delete_table_error_handler;
 
1717
 
 
1718
    /* Fill up strucutures that print_error may need */
 
1719
    dummy_share.path.str= (char*) path;
 
1720
    dummy_share.path.length= strlen(path);
 
1721
    dummy_share.db.str= (char*) db;
 
1722
    dummy_share.db.length= strlen(db);
 
1723
    dummy_share.table_name.str= (char*) alias;
 
1724
    dummy_share.table_name.length= strlen(alias);
 
1725
    dummy_table.alias= alias;
 
1726
 
 
1727
    file->change_table_ptr(&dummy_table, &dummy_share);
 
1728
 
 
1729
    thd->push_internal_handler(&ha_delete_table_error_handler);
 
1730
    file->print_error(error, 0);
 
1731
 
 
1732
    thd->pop_internal_handler();
 
1733
 
 
1734
    /*
 
1735
      XXX: should we convert *all* errors to warnings here?
 
1736
      What if the error is fatal?
 
1737
    */
 
1738
    push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_ERROR, error,
 
1739
                ha_delete_table_error_handler.buff);
 
1740
  }
 
1741
  delete file;
 
1742
  return(error);
 
1743
}
53
1744
 
54
1745
/****************************************************************************
55
 
** General Cursor functions
 
1746
** General handler functions
56
1747
****************************************************************************/
57
 
Cursor::Cursor(plugin::StorageEngine &engine_arg,
58
 
               Table &arg)
59
 
  : table(arg),
60
 
    engine(engine_arg),
61
 
    estimation_rows_to_insert(0),
62
 
    ref(0),
63
 
    key_used_on_scan(MAX_KEY), active_index(MAX_KEY),
64
 
    ref_length(sizeof(internal::my_off_t)),
65
 
    inited(NONE),
66
 
    locked(false),
67
 
    next_insert_id(0), insert_id_for_cur_row(0)
68
 
{ }
69
 
 
70
 
Cursor::~Cursor(void)
71
 
{
72
 
  assert(locked == false);
73
 
  /* TODO: assert(inited == NONE); */
74
 
}
75
 
 
76
 
 
77
 
/*
78
 
 * @note this only used in
79
 
 * optimizer::QuickRangeSelect::init_ror_merged_scan(bool reuse_handler) as
80
 
 * of the writing of this comment. -Brian
81
 
 */
82
 
Cursor *Cursor::clone(memory::Root *mem_root)
83
 
{
84
 
  Cursor *new_handler= getTable()->getMutableShare()->db_type()->getCursor(*getTable());
85
 
 
 
1748
handler *handler::clone(MEM_ROOT *mem_root)
 
1749
{
 
1750
  handler *new_handler= get_new_handler(table->s, mem_root, table->s->db_type());
86
1751
  /*
87
 
    Allocate Cursor->ref here because otherwise ha_open will allocate it
88
 
    on this->table->mem_root and we will not be able to reclaim that memory
89
 
    when the clone Cursor object is destroyed.
 
1752
    Allocate handler->ref here because otherwise ha_open will allocate it
 
1753
    on this->table->mem_root and we will not be able to reclaim that memory 
 
1754
    when the clone handler object is destroyed.
90
1755
  */
91
 
  if (!(new_handler->ref= (unsigned char*) mem_root->alloc_root(ALIGN_SIZE(ref_length)*2)))
 
1756
  if (!(new_handler->ref= (uchar*) alloc_root(mem_root, ALIGN_SIZE(ref_length)*2)))
92
1757
    return NULL;
93
 
 
94
 
  identifier::Table identifier(getTable()->getShare()->getSchemaName(),
95
 
                             getTable()->getShare()->getTableName(),
96
 
                             getTable()->getShare()->getType());
97
 
 
98
 
  if (new_handler && !new_handler->ha_open(identifier,
99
 
                                           getTable()->getDBStat(),
 
1758
  if (new_handler && !new_handler->ha_open(table,
 
1759
                                           table->s->normalized_path.str,
 
1760
                                           table->getDBStat(),
100
1761
                                           HA_OPEN_IGNORE_IF_LOCKED))
101
1762
    return new_handler;
102
1763
  return NULL;
103
1764
}
104
1765
 
105
 
/*
106
 
  DESCRIPTION
107
 
    given a buffer with a key value, and a map of keyparts
108
 
    that are present in this value, returns the length of the value
109
 
*/
110
 
uint32_t Cursor::calculate_key_len(uint32_t key_position, key_part_map keypart_map_arg)
111
 
{
112
 
  /* works only with key prefixes */
113
 
  assert(((keypart_map_arg + 1) & keypart_map_arg) == 0);
114
 
 
115
 
  const KeyPartInfo *key_part_found= getTable()->getShare()->getKeyInfo(key_position).key_part;
116
 
  const KeyPartInfo *end_key_part_found= key_part_found + getTable()->getShare()->getKeyInfo(key_position).key_parts;
117
 
  uint32_t length= 0;
118
 
 
119
 
  while (key_part_found < end_key_part_found && keypart_map_arg)
120
 
  {
121
 
    length+= key_part_found->store_length;
122
 
    keypart_map_arg >>= 1;
123
 
    key_part_found++;
124
 
  }
125
 
  return length;
126
 
}
127
 
 
128
 
int Cursor::startIndexScan(uint32_t idx, bool sorted)
129
 
{
130
 
  int result;
131
 
  assert(inited == NONE);
132
 
  if (!(result= doStartIndexScan(idx, sorted)))
133
 
    inited=INDEX;
134
 
  end_range= NULL;
135
 
  return result;
136
 
}
137
 
 
138
 
int Cursor::endIndexScan()
139
 
{
140
 
  assert(inited==INDEX);
141
 
  inited=NONE;
142
 
  end_range= NULL;
143
 
  return(doEndIndexScan());
144
 
}
145
 
 
146
 
int Cursor::startTableScan(bool scan)
147
 
{
148
 
  int result;
149
 
  assert(inited==NONE || (inited==RND && scan));
150
 
  inited= (result= doStartTableScan(scan)) ? NONE: RND;
151
 
 
152
 
  return result;
153
 
}
154
 
 
155
 
int Cursor::endTableScan()
156
 
{
157
 
  assert(inited==RND);
158
 
  inited=NONE;
159
 
  return(doEndTableScan());
160
 
}
161
 
 
162
 
int Cursor::ha_index_or_rnd_end()
163
 
{
164
 
  return inited == INDEX ? endIndexScan() : inited == RND ? endTableScan() : 0;
165
 
}
166
 
 
167
 
void Cursor::ha_start_bulk_insert(ha_rows rows)
168
 
{
169
 
  estimation_rows_to_insert= rows;
170
 
  start_bulk_insert(rows);
171
 
}
172
 
 
173
 
int Cursor::ha_end_bulk_insert()
174
 
{
175
 
  estimation_rows_to_insert= 0;
176
 
  return end_bulk_insert();
177
 
}
178
 
 
179
 
const key_map *Cursor::keys_to_use_for_scanning()
180
 
{
181
 
  return &key_map_empty;
182
 
}
183
 
 
184
 
bool Cursor::has_transactions()
185
 
{
186
 
  return (getTable()->getShare()->db_type()->check_flag(HTON_BIT_DOES_TRANSACTIONS));
187
 
}
188
 
 
189
 
void Cursor::ha_statistic_increment(uint64_t system_status_var::*offset) const
190
 
{
191
 
  (getTable()->in_use->status_var.*offset)++;
192
 
}
193
 
 
194
 
void **Cursor::ha_data(Session *session) const
195
 
{
196
 
  return session->getEngineData(getEngine());
197
 
}
198
 
 
199
 
bool Cursor::is_fatal_error(int error, uint32_t flags)
200
 
{
201
 
  if (!error ||
202
 
      ((flags & HA_CHECK_DUP_KEY) &&
203
 
       (error == HA_ERR_FOUND_DUPP_KEY ||
204
 
        error == HA_ERR_FOUND_DUPP_UNIQUE)))
205
 
    return false;
206
 
  return true;
207
 
}
208
 
 
209
 
 
210
 
ha_rows Cursor::records() { return stats.records; }
211
 
uint64_t Cursor::tableSize() { return stats.index_file_length + stats.data_file_length; }
212
 
uint64_t Cursor::rowSize() { return getTable()->getRecordLength() + getTable()->sizeFields(); }
213
 
 
214
 
int Cursor::doOpen(const identifier::Table &identifier, int mode, uint32_t test_if_locked)
215
 
{
216
 
  return open(identifier.getPath().c_str(), mode, test_if_locked);
 
1766
 
 
1767
 
 
1768
void handler::ha_statistic_increment(ulong SSV::*offset) const
 
1769
{
 
1770
  status_var_increment(table->in_use->status_var.*offset);
 
1771
}
 
1772
 
 
1773
void **handler::ha_data(THD *thd) const
 
1774
{
 
1775
  return thd_ha_data(thd, ht);
 
1776
}
 
1777
 
 
1778
THD *handler::ha_thd(void) const
 
1779
{
 
1780
  assert(!table || !table->in_use || table->in_use == current_thd);
 
1781
  return (table && table->in_use) ? table->in_use : current_thd;
217
1782
}
218
1783
 
219
1784
/**
220
 
  Open database-Cursor.
 
1785
  Open database-handler.
221
1786
 
222
1787
  Try O_RDONLY if cannot open as O_RDWR
223
1788
  Don't wait for locks if not HA_OPEN_WAIT_IF_LOCKED is set
224
1789
*/
225
 
int Cursor::ha_open(const identifier::Table &identifier,
226
 
                    int mode,
227
 
                    int test_if_locked)
 
1790
int handler::ha_open(Table *table_arg, const char *name, int mode,
 
1791
                     int test_if_locked)
228
1792
{
229
1793
  int error;
230
1794
 
231
 
  if ((error= doOpen(identifier, mode, test_if_locked)))
 
1795
  table= table_arg;
 
1796
  assert(table->s == table_share);
 
1797
  assert(alloc_root_inited(&table->mem_root));
 
1798
 
 
1799
  if ((error=open(name,mode,test_if_locked)))
232
1800
  {
233
1801
    if ((error == EACCES || error == EROFS) && mode == O_RDWR &&
234
 
        (getTable()->db_stat & HA_TRY_READ_ONLY))
 
1802
        (table->db_stat & HA_TRY_READ_ONLY))
235
1803
    {
236
 
      getTable()->db_stat|=HA_READ_ONLY;
237
 
      error= doOpen(identifier, O_RDONLY,test_if_locked);
 
1804
      table->db_stat|=HA_READ_ONLY;
 
1805
      error=open(name,O_RDONLY,test_if_locked);
238
1806
    }
239
1807
  }
240
1808
  if (error)
241
1809
  {
242
 
    errno= error;                            /* Safeguard */
 
1810
    my_errno= error;                            /* Safeguard */
243
1811
  }
244
1812
  else
245
1813
  {
246
 
    if (getTable()->getShare()->db_options_in_use & HA_OPTION_READ_ONLY_DATA)
247
 
      getTable()->db_stat|=HA_READ_ONLY;
 
1814
    if (table->s->db_options_in_use & HA_OPTION_READ_ONLY_DATA)
 
1815
      table->db_stat|=HA_READ_ONLY;
248
1816
    (void) extra(HA_EXTRA_NO_READCHECK);        // Not needed in SQL
249
1817
 
250
 
    /* ref is already allocated for us if we're called from Cursor::clone() */
251
 
    if (!ref && !(ref= (unsigned char*) getTable()->alloc_root(ALIGN_SIZE(ref_length)*2)))
 
1818
    /* ref is already allocated for us if we're called from handler::clone() */
 
1819
    if (!ref && !(ref= (uchar*) alloc_root(&table->mem_root, 
 
1820
                                          ALIGN_SIZE(ref_length)*2)))
252
1821
    {
253
1822
      close();
254
1823
      error=HA_ERR_OUT_OF_MEM;
255
1824
    }
256
1825
    else
257
1826
      dup_ref=ref+ALIGN_SIZE(ref_length);
 
1827
    cached_table_flags= table_flags();
258
1828
  }
259
 
  return error;
 
1829
  return(error);
 
1830
}
 
1831
 
 
1832
/**
 
1833
  one has to use this method when to find
 
1834
  random position by record as the plain
 
1835
  position() call doesn't work for some
 
1836
  handlers for random position
 
1837
*/
 
1838
 
 
1839
int handler::rnd_pos_by_record(uchar *record)
 
1840
{
 
1841
  register int error;
 
1842
 
 
1843
  position(record);
 
1844
  if (inited && (error= ha_index_end()))
 
1845
    return(error);
 
1846
  if ((error= ha_rnd_init(false)))
 
1847
    return(error);
 
1848
 
 
1849
  return(rnd_pos(record, ref));
260
1850
}
261
1851
 
262
1852
/**
265
1855
  This is never called for InnoDB tables, as these table types
266
1856
  has the HA_STATS_RECORDS_IS_EXACT set.
267
1857
*/
268
 
int Cursor::read_first_row(unsigned char * buf, uint32_t primary_key)
 
1858
int handler::read_first_row(uchar * buf, uint primary_key)
269
1859
{
270
1860
  register int error;
271
1861
 
272
 
  ha_statistic_increment(&system_status_var::ha_read_first_count);
 
1862
  ha_statistic_increment(&SSV::ha_read_first_count);
273
1863
 
274
1864
  /*
275
1865
    If there is very few deleted rows in the table, find the first row by
277
1867
    TODO remove the test for HA_READ_ORDER
278
1868
  */
279
1869
  if (stats.deleted < 10 || primary_key >= MAX_KEY ||
280
 
      !(getTable()->index_flags(primary_key) & HA_READ_ORDER))
 
1870
      !(index_flags(primary_key, 0, 0) & HA_READ_ORDER))
281
1871
  {
282
 
    error= startTableScan(1);
283
 
    if (error == 0)
284
 
    {
285
 
      while ((error= rnd_next(buf)) == HA_ERR_RECORD_DELETED) ;
286
 
      (void) endTableScan();
287
 
    }
 
1872
    (void) ha_rnd_init(1);
 
1873
    while ((error= rnd_next(buf)) == HA_ERR_RECORD_DELETED) ;
 
1874
    (void) ha_rnd_end();
288
1875
  }
289
1876
  else
290
1877
  {
291
1878
    /* Find the first row through the primary key */
292
 
    error= startIndexScan(primary_key, 0);
293
 
    if (error == 0)
294
 
    {
295
 
      error=index_first(buf);
296
 
      (void) endIndexScan();
297
 
    }
 
1879
    (void) ha_index_init(primary_key, 0);
 
1880
    error=index_first(buf);
 
1881
    (void) ha_index_end();
298
1882
  }
299
 
  return error;
 
1883
  return(error);
300
1884
}
301
1885
 
302
1886
/**
311
1895
  @verbatim 1,5,15,25,35,... @endverbatim
312
1896
*/
313
1897
inline uint64_t
314
 
compute_next_insert_id(uint64_t nr, drizzle_system_variables *variables)
 
1898
compute_next_insert_id(uint64_t nr,struct system_variables *variables)
315
1899
{
316
1900
  if (variables->auto_increment_increment == 1)
317
1901
    return (nr+1); // optimization of the formula below
323
1907
}
324
1908
 
325
1909
 
326
 
void Cursor::adjust_next_insert_id_after_explicit_value(uint64_t nr)
 
1910
void handler::adjust_next_insert_id_after_explicit_value(uint64_t nr)
327
1911
{
328
1912
  /*
329
 
    If we have set Session::next_insert_id previously and plan to insert an
 
1913
    If we have set THD::next_insert_id previously and plan to insert an
330
1914
    explicitely-specified value larger than this, we need to increase
331
 
    Session::next_insert_id to be greater than the explicit value.
 
1915
    THD::next_insert_id to be greater than the explicit value.
332
1916
  */
333
1917
  if ((next_insert_id > 0) && (nr >= next_insert_id))
334
 
    set_next_insert_id(compute_next_insert_id(nr, &getTable()->in_use->variables));
 
1918
    set_next_insert_id(compute_next_insert_id(nr, &table->in_use->variables));
335
1919
}
336
1920
 
337
1921
 
351
1935
    The number X if it exists, "nr" otherwise.
352
1936
*/
353
1937
inline uint64_t
354
 
prev_insert_id(uint64_t nr, drizzle_system_variables *variables)
 
1938
prev_insert_id(uint64_t nr, struct system_variables *variables)
355
1939
{
356
1940
  if (unlikely(nr < variables->auto_increment_offset))
357
1941
  {
376
1960
 
377
1961
  Updates columns with type NEXT_NUMBER if:
378
1962
 
379
 
  - If column value is set to NULL (in which case auto_increment_field_not_null is false)
 
1963
  - If column value is set to NULL (in which case
 
1964
    auto_increment_field_not_null is 0)
380
1965
  - If column is set to 0 and (sql_mode & MODE_NO_AUTO_VALUE_ON_ZERO) is not
381
1966
    set. In the future we will only set NEXT_NUMBER fields if one sets them
382
1967
    to NULL (or they are not included in the insert list).
397
1982
    reserved for us.
398
1983
 
399
1984
  - In both cases, for the following rows we use those reserved values without
400
 
    calling the Cursor again (we just progress in the interval, computing
 
1985
    calling the handler again (we just progress in the interval, computing
401
1986
    each new value from the previous one). Until we have exhausted them, then
402
1987
    we either take the next provided interval or call get_auto_increment()
403
1988
    again to reserve a new interval.
404
1989
 
405
1990
  - In both cases, the reserved intervals are remembered in
406
 
    session->auto_inc_intervals_in_cur_stmt_for_binlog if statement-based
 
1991
    thd->auto_inc_intervals_in_cur_stmt_for_binlog if statement-based
407
1992
    binlogging; the last reserved interval is remembered in
408
1993
    auto_inc_interval_for_cur_row.
409
1994
 
417
2002
    start counting from the inserted value.
418
2003
 
419
2004
    This function's "outputs" are: the table's auto_increment field is filled
420
 
    with a value, session->next_insert_id is filled with the value to use for the
 
2005
    with a value, thd->next_insert_id is filled with the value to use for the
421
2006
    next row, if a value was autogenerated for the current row it is stored in
422
 
    session->insert_id_for_cur_row, if get_auto_increment() was called
423
 
    session->auto_inc_interval_for_cur_row is modified, if that interval is not
424
 
    present in session->auto_inc_intervals_in_cur_stmt_for_binlog it is added to
 
2007
    thd->insert_id_for_cur_row, if get_auto_increment() was called
 
2008
    thd->auto_inc_interval_for_cur_row is modified, if that interval is not
 
2009
    present in thd->auto_inc_intervals_in_cur_stmt_for_binlog it is added to
425
2010
    this list.
426
2011
 
427
2012
  @todo
444
2029
#define AUTO_INC_DEFAULT_NB_MAX_BITS 16
445
2030
#define AUTO_INC_DEFAULT_NB_MAX ((1 << AUTO_INC_DEFAULT_NB_MAX_BITS) - 1)
446
2031
 
447
 
int Cursor::update_auto_increment()
 
2032
int handler::update_auto_increment()
448
2033
{
449
2034
  uint64_t nr, nb_reserved_values;
450
2035
  bool append= false;
451
 
  Session *session= getTable()->in_use;
452
 
  drizzle_system_variables *variables= &session->variables;
 
2036
  THD *thd= table->in_use;
 
2037
  struct system_variables *variables= &thd->variables;
453
2038
 
454
2039
  /*
455
2040
    next_insert_id is a "cursor" into the reserved interval, it may go greater
457
2042
  */
458
2043
  assert(next_insert_id >= auto_inc_interval_for_cur_row.minimum());
459
2044
 
460
 
  /* We check if auto_increment_field_not_null is false
461
 
     for an auto increment column, not a magic value like NULL is.
462
 
     same as sql_mode=NO_AUTO_VALUE_ON_ZERO */
463
 
 
464
 
  if ((nr= getTable()->next_number_field->val_int()) != 0
465
 
      || getTable()->auto_increment_field_not_null)
 
2045
  if ((nr= table->next_number_field->val_int()) != 0)
466
2046
  {
467
2047
    /*
468
2048
      Update next_insert_id if we had already generated a value in this
472
2052
    */
473
2053
    adjust_next_insert_id_after_explicit_value(nr);
474
2054
    insert_id_for_cur_row= 0; // didn't generate anything
475
 
 
476
 
    return 0;
 
2055
    return(0);
477
2056
  }
478
2057
 
479
2058
  if ((nr= next_insert_id) >= auto_inc_interval_for_cur_row.maximum())
480
2059
  {
481
2060
    /* next_insert_id is beyond what is reserved, so we reserve more. */
482
2061
    const Discrete_interval *forced=
483
 
      session->auto_inc_intervals_forced.get_next();
 
2062
      thd->auto_inc_intervals_forced.get_next();
484
2063
    if (forced != NULL)
485
2064
    {
486
2065
      nr= forced->minimum();
489
2068
    else
490
2069
    {
491
2070
      /*
492
 
        Cursor::estimation_rows_to_insert was set by
493
 
        Cursor::ha_start_bulk_insert(); if 0 it means "unknown".
 
2071
        handler::estimation_rows_to_insert was set by
 
2072
        handler::ha_start_bulk_insert(); if 0 it means "unknown".
494
2073
      */
495
 
      uint32_t nb_already_reserved_intervals=
496
 
        session->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements();
 
2074
      uint nb_already_reserved_intervals=
 
2075
        thd->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements();
497
2076
      uint64_t nb_desired_values;
498
2077
      /*
499
2078
        If an estimation was given to the engine:
514
2093
        /* avoid overflow in formula, with this if() */
515
2094
        if (nb_already_reserved_intervals <= AUTO_INC_DEFAULT_NB_MAX_BITS)
516
2095
        {
517
 
          nb_desired_values= AUTO_INC_DEFAULT_NB_ROWS *
 
2096
          nb_desired_values= AUTO_INC_DEFAULT_NB_ROWS * 
518
2097
            (1 << nb_already_reserved_intervals);
519
 
          set_if_smaller(nb_desired_values, (uint64_t)AUTO_INC_DEFAULT_NB_MAX);
 
2098
          set_if_smaller(nb_desired_values, AUTO_INC_DEFAULT_NB_MAX);
520
2099
        }
521
2100
        else
522
2101
          nb_desired_values= AUTO_INC_DEFAULT_NB_MAX;
527
2106
                         nb_desired_values, &nr,
528
2107
                         &nb_reserved_values);
529
2108
      if (nr == ~(uint64_t) 0)
530
 
        return HA_ERR_AUTOINC_READ_FAILED;  // Mark failure
531
 
 
 
2109
        return(HA_ERR_AUTOINC_READ_FAILED);  // Mark failure
 
2110
      
532
2111
      /*
533
2112
        That rounding below should not be needed when all engines actually
534
2113
        respect offset and increment in get_auto_increment(). But they don't
539
2118
      */
540
2119
      nr= compute_next_insert_id(nr-1, variables);
541
2120
    }
542
 
 
543
 
    if (getTable()->getShare()->next_number_keypart == 0)
 
2121
    
 
2122
    if (table->s->next_number_keypart == 0)
544
2123
    {
545
2124
      /* We must defer the appending until "nr" has been possibly truncated */
546
2125
      append= true;
547
2126
    }
548
2127
  }
549
2128
 
550
 
  if (unlikely(getTable()->next_number_field->store((int64_t) nr, true)))
 
2129
  if (unlikely(table->next_number_field->store((int64_t) nr, true)))
551
2130
  {
552
2131
    /*
553
2132
      first test if the query was aborted due to strict mode constraints
554
2133
    */
555
 
    if (session->getKilled() == Session::KILL_BAD_DATA)
556
 
      return HA_ERR_AUTOINC_ERANGE;
 
2134
    if (thd->killed == THD::KILL_BAD_DATA)
 
2135
      return(HA_ERR_AUTOINC_ERANGE);
557
2136
 
558
2137
    /*
559
2138
      field refused this value (overflow) and truncated it, use the result of
563
2142
      bother shifting the right bound (anyway any other value from this
564
2143
      interval will cause a duplicate key).
565
2144
    */
566
 
    nr= prev_insert_id(getTable()->next_number_field->val_int(), variables);
567
 
    if (unlikely(getTable()->next_number_field->store((int64_t) nr, true)))
568
 
      nr= getTable()->next_number_field->val_int();
 
2145
    nr= prev_insert_id(table->next_number_field->val_int(), variables);
 
2146
    if (unlikely(table->next_number_field->store((int64_t) nr, true)))
 
2147
      nr= table->next_number_field->val_int();
569
2148
  }
570
2149
  if (append)
571
2150
  {
572
2151
    auto_inc_interval_for_cur_row.replace(nr, nb_reserved_values,
573
2152
                                          variables->auto_increment_increment);
 
2153
    /* Row-based replication does not need to store intervals in binlog */
 
2154
    if (!thd->current_stmt_binlog_row_based)
 
2155
        thd->auto_inc_intervals_in_cur_stmt_for_binlog.append(auto_inc_interval_for_cur_row.minimum(),
 
2156
                                                              auto_inc_interval_for_cur_row.values(),
 
2157
                                                              variables->auto_increment_increment);
574
2158
  }
575
2159
 
576
2160
  /*
587
2171
  */
588
2172
  set_next_insert_id(compute_next_insert_id(nr, variables));
589
2173
 
590
 
  return 0;
591
 
}
592
 
 
593
 
 
594
 
/**
595
 
  Reserves an interval of auto_increment values from the Cursor.
 
2174
  return(0);
 
2175
}
 
2176
 
 
2177
 
 
2178
/**
 
2179
  MySQL signal that it changed the column bitmap
 
2180
 
 
2181
  This is for handlers that needs to setup their own column bitmaps.
 
2182
  Normally the handler should set up their own column bitmaps in
 
2183
  index_init() or rnd_init() and in any column_bitmaps_signal() call after
 
2184
  this.
 
2185
 
 
2186
  The handler is allowed to do changes to the bitmap after a index_init or
 
2187
  rnd_init() call is made as after this, MySQL will not use the bitmap
 
2188
  for any program logic checking.
 
2189
*/
 
2190
void handler::column_bitmaps_signal()
 
2191
{
 
2192
  return;
 
2193
}
 
2194
 
 
2195
 
 
2196
/**
 
2197
  Reserves an interval of auto_increment values from the handler.
596
2198
 
597
2199
  offset and increment means that we want values to be of the form
598
2200
  offset + N * increment, where N>=0 is integer.
603
2205
  @param offset
604
2206
  @param increment
605
2207
  @param nb_desired_values   how many values we want
606
 
  @param first_value         (OUT) the first value reserved by the Cursor
607
 
  @param nb_reserved_values  (OUT) how many values the Cursor reserved
 
2208
  @param first_value         (OUT) the first value reserved by the handler
 
2209
  @param nb_reserved_values  (OUT) how many values the handler reserved
608
2210
*/
609
 
 
610
 
void Cursor::ha_release_auto_increment()
 
2211
void handler::get_auto_increment(uint64_t offset __attribute__((unused)),
 
2212
                                 uint64_t increment __attribute__((unused)),
 
2213
                                 uint64_t nb_desired_values __attribute__((unused)),
 
2214
                                 uint64_t *first_value,
 
2215
                                 uint64_t *nb_reserved_values)
 
2216
{
 
2217
  uint64_t nr;
 
2218
  int error;
 
2219
 
 
2220
  (void) extra(HA_EXTRA_KEYREAD);
 
2221
  table->mark_columns_used_by_index_no_reset(table->s->next_number_index,
 
2222
                                        table->read_set);
 
2223
  column_bitmaps_signal();
 
2224
  index_init(table->s->next_number_index, 1);
 
2225
  if (table->s->next_number_keypart == 0)
 
2226
  {                                             // Autoincrement at key-start
 
2227
    error=index_last(table->record[1]);
 
2228
    /*
 
2229
      MySQL implicitely assumes such method does locking (as MySQL decides to
 
2230
      use nr+increment without checking again with the handler, in
 
2231
      handler::update_auto_increment()), so reserves to infinite.
 
2232
    */
 
2233
    *nb_reserved_values= UINT64_MAX;
 
2234
  }
 
2235
  else
 
2236
  {
 
2237
    uchar key[MAX_KEY_LENGTH];
 
2238
    key_copy(key, table->record[0],
 
2239
             table->key_info + table->s->next_number_index,
 
2240
             table->s->next_number_key_offset);
 
2241
    error= index_read_map(table->record[1], key,
 
2242
                          make_prev_keypart_map(table->s->next_number_keypart),
 
2243
                          HA_READ_PREFIX_LAST);
 
2244
    /*
 
2245
      MySQL needs to call us for next row: assume we are inserting ("a",null)
 
2246
      here, we return 3, and next this statement will want to insert
 
2247
      ("b",null): there is no reason why ("b",3+1) would be the good row to
 
2248
      insert: maybe it already exists, maybe 3+1 is too large...
 
2249
    */
 
2250
    *nb_reserved_values= 1;
 
2251
  }
 
2252
 
 
2253
  if (error)
 
2254
    nr=1;
 
2255
  else
 
2256
    nr= ((uint64_t) table->next_number_field->
 
2257
         val_int_offset(table->s->rec_buff_length)+1);
 
2258
  index_end();
 
2259
  (void) extra(HA_EXTRA_NO_KEYREAD);
 
2260
  *first_value= nr;
 
2261
}
 
2262
 
 
2263
 
 
2264
void handler::ha_release_auto_increment()
611
2265
{
612
2266
  release_auto_increment();
613
2267
  insert_id_for_cur_row= 0;
619
2273
      this statement used forced auto_increment values if there were some,
620
2274
      wipe them away for other statements.
621
2275
    */
622
 
    getTable()->in_use->auto_inc_intervals_forced.empty();
623
 
  }
624
 
}
625
 
 
626
 
void Cursor::drop_table(const char *)
 
2276
    table->in_use->auto_inc_intervals_forced.empty();
 
2277
  }
 
2278
}
 
2279
 
 
2280
 
 
2281
void handler::print_keydup_error(uint key_nr, const char *msg)
 
2282
{
 
2283
  /* Write the duplicated key in the error message */
 
2284
  char key[MAX_KEY_LENGTH];
 
2285
  String str(key,sizeof(key),system_charset_info);
 
2286
 
 
2287
  if (key_nr == MAX_KEY)
 
2288
  {
 
2289
    /* Key is unknown */
 
2290
    str.copy("", 0, system_charset_info);
 
2291
    my_printf_error(ER_DUP_ENTRY, msg, MYF(0), str.c_ptr(), "*UNKNOWN*");
 
2292
  }
 
2293
  else
 
2294
  {
 
2295
    /* Table is opened and defined at this point */
 
2296
    key_unpack(&str,table,(uint) key_nr);
 
2297
    uint max_length=DRIZZLE_ERRMSG_SIZE-(uint) strlen(msg);
 
2298
    if (str.length() >= max_length)
 
2299
    {
 
2300
      str.length(max_length-4);
 
2301
      str.append(STRING_WITH_LEN("..."));
 
2302
    }
 
2303
    my_printf_error(ER_DUP_ENTRY, msg,
 
2304
                    MYF(0), str.c_ptr(), table->key_info[key_nr].name);
 
2305
  }
 
2306
}
 
2307
 
 
2308
 
 
2309
/**
 
2310
  Print error that we got from handler function.
 
2311
 
 
2312
  @note
 
2313
    In case of delete table it's only safe to use the following parts of
 
2314
    the 'table' structure:
 
2315
    - table->s->path
 
2316
    - table->alias
 
2317
*/
 
2318
void handler::print_error(int error, myf errflag)
 
2319
{
 
2320
  int textno=ER_GET_ERRNO;
 
2321
  switch (error) {
 
2322
  case EACCES:
 
2323
    textno=ER_OPEN_AS_READONLY;
 
2324
    break;
 
2325
  case EAGAIN:
 
2326
    textno=ER_FILE_USED;
 
2327
    break;
 
2328
  case ENOENT:
 
2329
    textno=ER_FILE_NOT_FOUND;
 
2330
    break;
 
2331
  case HA_ERR_KEY_NOT_FOUND:
 
2332
  case HA_ERR_NO_ACTIVE_RECORD:
 
2333
  case HA_ERR_END_OF_FILE:
 
2334
    textno=ER_KEY_NOT_FOUND;
 
2335
    break;
 
2336
  case HA_ERR_WRONG_MRG_TABLE_DEF:
 
2337
    textno=ER_WRONG_MRG_TABLE;
 
2338
    break;
 
2339
  case HA_ERR_FOUND_DUPP_KEY:
 
2340
  {
 
2341
    uint key_nr=get_dup_key(error);
 
2342
    if ((int) key_nr >= 0)
 
2343
    {
 
2344
      print_keydup_error(key_nr, ER(ER_DUP_ENTRY_WITH_KEY_NAME));
 
2345
      return;
 
2346
    }
 
2347
    textno=ER_DUP_KEY;
 
2348
    break;
 
2349
  }
 
2350
  case HA_ERR_FOREIGN_DUPLICATE_KEY:
 
2351
  {
 
2352
    uint key_nr= get_dup_key(error);
 
2353
    if ((int) key_nr >= 0)
 
2354
    {
 
2355
      uint max_length;
 
2356
      /* Write the key in the error message */
 
2357
      char key[MAX_KEY_LENGTH];
 
2358
      String str(key,sizeof(key),system_charset_info);
 
2359
      /* Table is opened and defined at this point */
 
2360
      key_unpack(&str,table,(uint) key_nr);
 
2361
      max_length= (DRIZZLE_ERRMSG_SIZE-
 
2362
                   (uint) strlen(ER(ER_FOREIGN_DUPLICATE_KEY)));
 
2363
      if (str.length() >= max_length)
 
2364
      {
 
2365
        str.length(max_length-4);
 
2366
        str.append(STRING_WITH_LEN("..."));
 
2367
      }
 
2368
      my_error(ER_FOREIGN_DUPLICATE_KEY, MYF(0), table_share->table_name.str,
 
2369
        str.c_ptr(), key_nr+1);
 
2370
      return;
 
2371
    }
 
2372
    textno= ER_DUP_KEY;
 
2373
    break;
 
2374
  }
 
2375
  case HA_ERR_FOUND_DUPP_UNIQUE:
 
2376
    textno=ER_DUP_UNIQUE;
 
2377
    break;
 
2378
  case HA_ERR_RECORD_CHANGED:
 
2379
    textno=ER_CHECKREAD;
 
2380
    break;
 
2381
  case HA_ERR_CRASHED:
 
2382
    textno=ER_NOT_KEYFILE;
 
2383
    break;
 
2384
  case HA_ERR_WRONG_IN_RECORD:
 
2385
    textno= ER_CRASHED_ON_USAGE;
 
2386
    break;
 
2387
  case HA_ERR_CRASHED_ON_USAGE:
 
2388
    textno=ER_CRASHED_ON_USAGE;
 
2389
    break;
 
2390
  case HA_ERR_NOT_A_TABLE:
 
2391
    textno= error;
 
2392
    break;
 
2393
  case HA_ERR_CRASHED_ON_REPAIR:
 
2394
    textno=ER_CRASHED_ON_REPAIR;
 
2395
    break;
 
2396
  case HA_ERR_OUT_OF_MEM:
 
2397
    textno=ER_OUT_OF_RESOURCES;
 
2398
    break;
 
2399
  case HA_ERR_WRONG_COMMAND:
 
2400
    textno=ER_ILLEGAL_HA;
 
2401
    break;
 
2402
  case HA_ERR_OLD_FILE:
 
2403
    textno=ER_OLD_KEYFILE;
 
2404
    break;
 
2405
  case HA_ERR_UNSUPPORTED:
 
2406
    textno=ER_UNSUPPORTED_EXTENSION;
 
2407
    break;
 
2408
  case HA_ERR_RECORD_FILE_FULL:
 
2409
  case HA_ERR_INDEX_FILE_FULL:
 
2410
    textno=ER_RECORD_FILE_FULL;
 
2411
    break;
 
2412
  case HA_ERR_LOCK_WAIT_TIMEOUT:
 
2413
    textno=ER_LOCK_WAIT_TIMEOUT;
 
2414
    break;
 
2415
  case HA_ERR_LOCK_TABLE_FULL:
 
2416
    textno=ER_LOCK_TABLE_FULL;
 
2417
    break;
 
2418
  case HA_ERR_LOCK_DEADLOCK:
 
2419
    textno=ER_LOCK_DEADLOCK;
 
2420
    break;
 
2421
  case HA_ERR_READ_ONLY_TRANSACTION:
 
2422
    textno=ER_READ_ONLY_TRANSACTION;
 
2423
    break;
 
2424
  case HA_ERR_CANNOT_ADD_FOREIGN:
 
2425
    textno=ER_CANNOT_ADD_FOREIGN;
 
2426
    break;
 
2427
  case HA_ERR_ROW_IS_REFERENCED:
 
2428
  {
 
2429
    String str;
 
2430
    get_error_message(error, &str);
 
2431
    my_error(ER_ROW_IS_REFERENCED_2, MYF(0), str.c_ptr_safe());
 
2432
    return;
 
2433
  }
 
2434
  case HA_ERR_NO_REFERENCED_ROW:
 
2435
  {
 
2436
    String str;
 
2437
    get_error_message(error, &str);
 
2438
    my_error(ER_NO_REFERENCED_ROW_2, MYF(0), str.c_ptr_safe());
 
2439
    return;
 
2440
  }
 
2441
  case HA_ERR_TABLE_DEF_CHANGED:
 
2442
    textno=ER_TABLE_DEF_CHANGED;
 
2443
    break;
 
2444
  case HA_ERR_NO_SUCH_TABLE:
 
2445
    my_error(ER_NO_SUCH_TABLE, MYF(0), table_share->db.str,
 
2446
             table_share->table_name.str);
 
2447
    return;
 
2448
  case HA_ERR_RBR_LOGGING_FAILED:
 
2449
    textno= ER_BINLOG_ROW_LOGGING_FAILED;
 
2450
    break;
 
2451
  case HA_ERR_DROP_INDEX_FK:
 
2452
  {
 
2453
    const char *ptr= "???";
 
2454
    uint key_nr= get_dup_key(error);
 
2455
    if ((int) key_nr >= 0)
 
2456
      ptr= table->key_info[key_nr].name;
 
2457
    my_error(ER_DROP_INDEX_FK, MYF(0), ptr);
 
2458
    return;
 
2459
  }
 
2460
  case HA_ERR_TABLE_NEEDS_UPGRADE:
 
2461
    textno=ER_TABLE_NEEDS_UPGRADE;
 
2462
    break;
 
2463
  case HA_ERR_TABLE_READONLY:
 
2464
    textno= ER_OPEN_AS_READONLY;
 
2465
    break;
 
2466
  case HA_ERR_AUTOINC_READ_FAILED:
 
2467
    textno= ER_AUTOINC_READ_FAILED;
 
2468
    break;
 
2469
  case HA_ERR_AUTOINC_ERANGE:
 
2470
    textno= ER_WARN_DATA_OUT_OF_RANGE;
 
2471
    break;
 
2472
  case HA_ERR_LOCK_OR_ACTIVE_TRANSACTION:
 
2473
    my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
 
2474
               ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
 
2475
    return;
 
2476
    break;
 
2477
  default:
 
2478
    {
 
2479
      /* The error was "unknown" to this function.
 
2480
         Ask handler if it has got a message for this error */
 
2481
      bool temporary= false;
 
2482
      String str;
 
2483
      temporary= get_error_message(error, &str);
 
2484
      if (!str.is_empty())
 
2485
      {
 
2486
        const char* engine= table_type();
 
2487
        if (temporary)
 
2488
          my_error(ER_GET_TEMPORARY_ERRMSG, MYF(0), error, str.ptr(), engine);
 
2489
        else
 
2490
          my_error(ER_GET_ERRMSG, MYF(0), error, str.ptr(), engine);
 
2491
      }
 
2492
      else
 
2493
        my_error(ER_GET_ERRNO,errflag,error);
 
2494
      return;
 
2495
    }
 
2496
  }
 
2497
  my_error(textno, errflag, table_share->table_name.str, error);
 
2498
  return;
 
2499
}
 
2500
 
 
2501
 
 
2502
/**
 
2503
  Return an error message specific to this handler.
 
2504
 
 
2505
  @param error  error code previously returned by handler
 
2506
  @param buf    pointer to String where to add error message
 
2507
 
 
2508
  @return
 
2509
    Returns true if this is a temporary error
 
2510
*/
 
2511
bool handler::get_error_message(int error __attribute__((unused)),
 
2512
                                String* buf __attribute__((unused)))
 
2513
{
 
2514
  return false;
 
2515
}
 
2516
 
 
2517
 
 
2518
int handler::ha_check_for_upgrade(HA_CHECK_OPT *check_opt)
 
2519
{
 
2520
  KEY *keyinfo, *keyend;
 
2521
  KEY_PART_INFO *keypart, *keypartend;
 
2522
 
 
2523
  if (!table->s->mysql_version)
 
2524
  {
 
2525
    /* check for blob-in-key error */
 
2526
    keyinfo= table->key_info;
 
2527
    keyend= table->key_info + table->s->keys;
 
2528
    for (; keyinfo < keyend; keyinfo++)
 
2529
    {
 
2530
      keypart= keyinfo->key_part;
 
2531
      keypartend= keypart + keyinfo->key_parts;
 
2532
      for (; keypart < keypartend; keypart++)
 
2533
      {
 
2534
        if (!keypart->fieldnr)
 
2535
          continue;
 
2536
        Field *field= table->field[keypart->fieldnr-1];
 
2537
        if (field->type() == DRIZZLE_TYPE_BLOB)
 
2538
        {
 
2539
          if (check_opt->sql_flags & TT_FOR_UPGRADE)
 
2540
            check_opt->flags= T_MEDIUM;
 
2541
          return HA_ADMIN_NEEDS_CHECK;
 
2542
        }
 
2543
      }
 
2544
    }
 
2545
  }
 
2546
  return check_for_upgrade(check_opt);
 
2547
}
 
2548
 
 
2549
 
 
2550
/* Code left, but Drizzle has no legacy yet (while MySQL did) */
 
2551
int handler::check_old_types()
 
2552
{
 
2553
  return 0;
 
2554
}
 
2555
 
 
2556
 
 
2557
static bool update_frm_version(Table *table)
 
2558
{
 
2559
  char path[FN_REFLEN];
 
2560
  File file;
 
2561
  bool result= true;
 
2562
 
 
2563
  /*
 
2564
    No need to update frm version in case table was created or checked
 
2565
    by server with the same version. This also ensures that we do not
 
2566
    update frm version for temporary tables as this code doesn't support
 
2567
    temporary tables.
 
2568
  */
 
2569
  if (table->s->mysql_version == DRIZZLE_VERSION_ID)
 
2570
    return(0);
 
2571
 
 
2572
  strxmov(path, table->s->normalized_path.str, reg_ext, NullS);
 
2573
 
 
2574
  if ((file= my_open(path, O_RDWR|O_BINARY, MYF(MY_WME))) >= 0)
 
2575
  {
 
2576
    uchar version[4];
 
2577
    char *key= table->s->table_cache_key.str;
 
2578
    uint key_length= table->s->table_cache_key.length;
 
2579
    Table *entry;
 
2580
    HASH_SEARCH_STATE state;
 
2581
 
 
2582
    int4store(version, DRIZZLE_VERSION_ID);
 
2583
 
 
2584
    if (pwrite(file, (uchar*)version, 4, 51L) == 0)
 
2585
    {
 
2586
      result= false;
 
2587
      goto err;
 
2588
    }
 
2589
 
 
2590
    for (entry=(Table*) hash_first(&open_cache,(uchar*) key,key_length, &state);
 
2591
         entry;
 
2592
         entry= (Table*) hash_next(&open_cache,(uchar*) key,key_length, &state))
 
2593
      entry->s->mysql_version= DRIZZLE_VERSION_ID;
 
2594
  }
 
2595
err:
 
2596
  if (file >= 0)
 
2597
    VOID(my_close(file,MYF(MY_WME)));
 
2598
  return(result);
 
2599
}
 
2600
 
 
2601
 
 
2602
 
 
2603
/**
 
2604
  @return
 
2605
    key if error because of duplicated keys
 
2606
*/
 
2607
uint handler::get_dup_key(int error)
 
2608
{
 
2609
  table->file->errkey  = (uint) -1;
 
2610
  if (error == HA_ERR_FOUND_DUPP_KEY || error == HA_ERR_FOREIGN_DUPLICATE_KEY ||
 
2611
      error == HA_ERR_FOUND_DUPP_UNIQUE ||
 
2612
      error == HA_ERR_DROP_INDEX_FK)
 
2613
    info(HA_STATUS_ERRKEY | HA_STATUS_NO_LOCK);
 
2614
  return(table->file->errkey);
 
2615
}
 
2616
 
 
2617
 
 
2618
/**
 
2619
  Delete all files with extension from bas_ext().
 
2620
 
 
2621
  @param name           Base name of table
 
2622
 
 
2623
  @note
 
2624
    We assume that the handler may return more extensions than
 
2625
    was actually used for the file.
 
2626
 
 
2627
  @retval
 
2628
    0   If we successfully deleted at least one file from base_ext and
 
2629
    didn't get any other errors than ENOENT
 
2630
  @retval
 
2631
    !0  Error
 
2632
*/
 
2633
int handler::delete_table(const char *name)
 
2634
{
 
2635
  int error= 0;
 
2636
  int enoent_or_zero= ENOENT;                   // Error if no file was deleted
 
2637
  char buff[FN_REFLEN];
 
2638
 
 
2639
  for (const char **ext=bas_ext(); *ext ; ext++)
 
2640
  {
 
2641
    fn_format(buff, name, "", *ext, MY_UNPACK_FILENAME|MY_APPEND_EXT);
 
2642
    if (my_delete_with_symlink(buff, MYF(0)))
 
2643
    {
 
2644
      if ((error= my_errno) != ENOENT)
 
2645
        break;
 
2646
    }
 
2647
    else
 
2648
      enoent_or_zero= 0;                        // No error for ENOENT
 
2649
    error= enoent_or_zero;
 
2650
  }
 
2651
  return error;
 
2652
}
 
2653
 
 
2654
 
 
2655
int handler::rename_table(const char * from, const char * to)
 
2656
{
 
2657
  int error= 0;
 
2658
  for (const char **ext= bas_ext(); *ext ; ext++)
 
2659
  {
 
2660
    if (rename_file_ext(from, to, *ext))
 
2661
    {
 
2662
      if ((error=my_errno) != ENOENT)
 
2663
        break;
 
2664
      error= 0;
 
2665
    }
 
2666
  }
 
2667
  return error;
 
2668
}
 
2669
 
 
2670
 
 
2671
void handler::drop_table(const char *name)
627
2672
{
628
2673
  close();
 
2674
  delete_table(name);
629
2675
}
630
2676
 
631
2677
 
632
2678
/**
633
2679
  Performs checks upon the table.
634
2680
 
635
 
  @param session                thread doing CHECK Table operation
 
2681
  @param thd                thread doing CHECK Table operation
636
2682
  @param check_opt          options from the parser
637
2683
 
638
2684
  @retval
644
2690
  @retval
645
2691
    HA_ADMIN_NOT_IMPLEMENTED
646
2692
*/
647
 
int Cursor::ha_check(Session *, HA_CHECK_OPT *)
 
2693
int handler::ha_check(THD *thd, HA_CHECK_OPT *check_opt)
648
2694
{
649
 
  return HA_ADMIN_OK;
 
2695
  int error;
 
2696
 
 
2697
  if ((table->s->mysql_version >= DRIZZLE_VERSION_ID) &&
 
2698
      (check_opt->sql_flags & TT_FOR_UPGRADE))
 
2699
    return 0;
 
2700
 
 
2701
  if (table->s->mysql_version < DRIZZLE_VERSION_ID)
 
2702
  {
 
2703
    if ((error= check_old_types()))
 
2704
      return error;
 
2705
    error= ha_check_for_upgrade(check_opt);
 
2706
    if (error && (error != HA_ADMIN_NEEDS_CHECK))
 
2707
      return error;
 
2708
    if (!error && (check_opt->sql_flags & TT_FOR_UPGRADE))
 
2709
      return 0;
 
2710
  }
 
2711
  if ((error= check(thd, check_opt)))
 
2712
    return error;
 
2713
  return update_frm_version(table);
650
2714
}
651
2715
 
652
2716
/**
656
2720
 
657
2721
inline
658
2722
void
659
 
Cursor::setTransactionReadWrite()
 
2723
handler::mark_trx_read_write()
660
2724
{
661
 
  ResourceContext *resource_context;
662
 
 
663
 
  /*
664
 
   * If the cursor has not context for execution then there should be no
665
 
   * possible resource to gain (and if there is... then there is a bug such
666
 
   * that in_use should have been set.
667
 
 */
668
 
  if (not getTable()->in_use)
669
 
    return;
670
 
 
671
 
  resource_context= getTable()->in_use->getResourceContext(getEngine());
 
2725
  Ha_trx_info *ha_info= &ha_thd()->ha_data[ht->slot].ha_info[0];
672
2726
  /*
673
2727
    When a storage engine method is called, the transaction must
674
2728
    have been started, unless it's a DDL call, for which the
677
2731
    Unfortunately here we can't know know for sure if the engine
678
2732
    has registered the transaction or not, so we must check.
679
2733
  */
680
 
  if (resource_context->isStarted())
 
2734
  if (ha_info->is_started())
681
2735
  {
682
 
    resource_context->markModifiedData();
 
2736
    assert(has_transactions());
 
2737
    /*
 
2738
      table_share can be NULL in ha_delete_table(). See implementation
 
2739
      of standalone function ha_delete_table() in sql_base.cc.
 
2740
    */
 
2741
    if (table_share == NULL || table_share->tmp_table == NO_TMP_TABLE)
 
2742
      ha_info->set_trx_read_write();
683
2743
  }
684
2744
}
685
2745
 
686
2746
 
687
2747
/**
 
2748
  Repair table: public interface.
 
2749
 
 
2750
  @sa handler::repair()
 
2751
*/
 
2752
 
 
2753
int handler::ha_repair(THD* thd, HA_CHECK_OPT* check_opt)
 
2754
{
 
2755
  int result;
 
2756
 
 
2757
  mark_trx_read_write();
 
2758
 
 
2759
  if ((result= repair(thd, check_opt)))
 
2760
    return result;
 
2761
  return update_frm_version(table);
 
2762
}
 
2763
 
 
2764
 
 
2765
/**
 
2766
  Bulk update row: public interface.
 
2767
 
 
2768
  @sa handler::bulk_update_row()
 
2769
*/
 
2770
 
 
2771
int
 
2772
handler::ha_bulk_update_row(const uchar *old_data, uchar *new_data,
 
2773
                            uint *dup_key_found)
 
2774
{
 
2775
  mark_trx_read_write();
 
2776
 
 
2777
  return bulk_update_row(old_data, new_data, dup_key_found);
 
2778
}
 
2779
 
 
2780
 
 
2781
/**
688
2782
  Delete all rows: public interface.
689
2783
 
690
 
  @sa Cursor::delete_all_rows()
691
 
 
692
 
  @note
693
 
 
694
 
  This is now equalivalent to TRUNCATE TABLE.
 
2784
  @sa handler::delete_all_rows()
695
2785
*/
696
2786
 
697
2787
int
698
 
Cursor::ha_delete_all_rows()
 
2788
handler::ha_delete_all_rows()
699
2789
{
700
 
  setTransactionReadWrite();
701
 
 
702
 
  int result= delete_all_rows();
703
 
 
704
 
  if (result == 0)
705
 
  {
706
 
    /** 
707
 
     * Trigger post-truncate notification to plugins... 
708
 
     *
709
 
     * @todo Make TransactionServices generic to AfterTriggerServices
710
 
     * or similar...
711
 
     */
712
 
    Session *const session= getTable()->in_use;
713
 
    TransactionServices &transaction_services= TransactionServices::singleton();
714
 
    transaction_services.truncateTable(*session, *getTable());
715
 
  }
716
 
 
717
 
  return result;
 
2790
  mark_trx_read_write();
 
2791
 
 
2792
  return delete_all_rows();
718
2793
}
719
2794
 
720
2795
 
721
2796
/**
722
2797
  Reset auto increment: public interface.
723
2798
 
724
 
  @sa Cursor::reset_auto_increment()
 
2799
  @sa handler::reset_auto_increment()
725
2800
*/
726
2801
 
727
2802
int
728
 
Cursor::ha_reset_auto_increment(uint64_t value)
 
2803
handler::ha_reset_auto_increment(uint64_t value)
729
2804
{
730
 
  setTransactionReadWrite();
 
2805
  mark_trx_read_write();
731
2806
 
732
2807
  return reset_auto_increment(value);
733
2808
}
734
2809
 
735
2810
 
736
2811
/**
 
2812
  Optimize table: public interface.
 
2813
 
 
2814
  @sa handler::optimize()
 
2815
*/
 
2816
 
 
2817
int
 
2818
handler::ha_optimize(THD* thd, HA_CHECK_OPT* check_opt)
 
2819
{
 
2820
  mark_trx_read_write();
 
2821
 
 
2822
  return optimize(thd, check_opt);
 
2823
}
 
2824
 
 
2825
 
 
2826
/**
737
2827
  Analyze table: public interface.
738
2828
 
739
 
  @sa Cursor::analyze()
 
2829
  @sa handler::analyze()
740
2830
*/
741
2831
 
742
2832
int
743
 
Cursor::ha_analyze(Session* session, HA_CHECK_OPT*)
744
 
{
745
 
  setTransactionReadWrite();
746
 
 
747
 
  return analyze(session);
748
 
}
 
2833
handler::ha_analyze(THD* thd, HA_CHECK_OPT* check_opt)
 
2834
{
 
2835
  mark_trx_read_write();
 
2836
 
 
2837
  return analyze(thd, check_opt);
 
2838
}
 
2839
 
 
2840
 
 
2841
/**
 
2842
  Check and repair table: public interface.
 
2843
 
 
2844
  @sa handler::check_and_repair()
 
2845
*/
 
2846
 
 
2847
bool
 
2848
handler::ha_check_and_repair(THD *thd)
 
2849
{
 
2850
  mark_trx_read_write();
 
2851
 
 
2852
  return check_and_repair(thd);
 
2853
}
 
2854
 
749
2855
 
750
2856
/**
751
2857
  Disable indexes: public interface.
752
2858
 
753
 
  @sa Cursor::disable_indexes()
 
2859
  @sa handler::disable_indexes()
754
2860
*/
755
2861
 
756
2862
int
757
 
Cursor::ha_disable_indexes(uint32_t mode)
 
2863
handler::ha_disable_indexes(uint mode)
758
2864
{
759
 
  setTransactionReadWrite();
 
2865
  mark_trx_read_write();
760
2866
 
761
2867
  return disable_indexes(mode);
762
2868
}
765
2871
/**
766
2872
  Enable indexes: public interface.
767
2873
 
768
 
  @sa Cursor::enable_indexes()
 
2874
  @sa handler::enable_indexes()
769
2875
*/
770
2876
 
771
2877
int
772
 
Cursor::ha_enable_indexes(uint32_t mode)
 
2878
handler::ha_enable_indexes(uint mode)
773
2879
{
774
 
  setTransactionReadWrite();
 
2880
  mark_trx_read_write();
775
2881
 
776
2882
  return enable_indexes(mode);
777
2883
}
780
2886
/**
781
2887
  Discard or import tablespace: public interface.
782
2888
 
783
 
  @sa Cursor::discard_or_import_tablespace()
 
2889
  @sa handler::discard_or_import_tablespace()
784
2890
*/
785
2891
 
786
2892
int
787
 
Cursor::ha_discard_or_import_tablespace(bool discard)
 
2893
handler::ha_discard_or_import_tablespace(bool discard)
788
2894
{
789
 
  setTransactionReadWrite();
 
2895
  mark_trx_read_write();
790
2896
 
791
2897
  return discard_or_import_tablespace(discard);
792
2898
}
793
2899
 
 
2900
 
 
2901
/**
 
2902
  Prepare for alter: public interface.
 
2903
 
 
2904
  Called to prepare an *online* ALTER.
 
2905
 
 
2906
  @sa handler::prepare_for_alter()
 
2907
*/
 
2908
 
 
2909
void
 
2910
handler::ha_prepare_for_alter()
 
2911
{
 
2912
  mark_trx_read_write();
 
2913
 
 
2914
  prepare_for_alter();
 
2915
}
 
2916
 
 
2917
 
 
2918
/**
 
2919
  Rename table: public interface.
 
2920
 
 
2921
  @sa handler::rename_table()
 
2922
*/
 
2923
 
 
2924
int
 
2925
handler::ha_rename_table(const char *from, const char *to)
 
2926
{
 
2927
  mark_trx_read_write();
 
2928
 
 
2929
  return rename_table(from, to);
 
2930
}
 
2931
 
 
2932
 
 
2933
/**
 
2934
  Delete table: public interface.
 
2935
 
 
2936
  @sa handler::delete_table()
 
2937
*/
 
2938
 
 
2939
int
 
2940
handler::ha_delete_table(const char *name)
 
2941
{
 
2942
  mark_trx_read_write();
 
2943
 
 
2944
  return delete_table(name);
 
2945
}
 
2946
 
 
2947
 
794
2948
/**
795
2949
  Drop table in the engine: public interface.
796
2950
 
797
 
  @sa Cursor::drop_table()
 
2951
  @sa handler::drop_table()
798
2952
*/
799
2953
 
800
2954
void
801
 
Cursor::closeMarkForDelete(const char *name)
 
2955
handler::ha_drop_table(const char *name)
802
2956
{
803
 
  setTransactionReadWrite();
 
2957
  mark_trx_read_write();
804
2958
 
805
2959
  return drop_table(name);
806
2960
}
807
2961
 
808
 
int Cursor::index_next_same(unsigned char *buf, const unsigned char *key, uint32_t keylen)
 
2962
 
 
2963
/**
 
2964
  Create a table in the engine: public interface.
 
2965
 
 
2966
  @sa handler::create()
 
2967
*/
 
2968
 
 
2969
int
 
2970
handler::ha_create(const char *name, Table *form, HA_CREATE_INFO *info)
 
2971
{
 
2972
  mark_trx_read_write();
 
2973
 
 
2974
  return create(name, form, info);
 
2975
}
 
2976
 
 
2977
 
 
2978
/**
 
2979
  Create handler files for CREATE TABLE: public interface.
 
2980
 
 
2981
  @sa handler::create_handler_files()
 
2982
*/
 
2983
 
 
2984
int
 
2985
handler::ha_create_handler_files(const char *name, const char *old_name,
 
2986
                        int action_flag, HA_CREATE_INFO *info)
 
2987
{
 
2988
  mark_trx_read_write();
 
2989
 
 
2990
  return create_handler_files(name, old_name, action_flag, info);
 
2991
}
 
2992
 
 
2993
 
 
2994
/**
 
2995
  Tell the storage engine that it is allowed to "disable transaction" in the
 
2996
  handler. It is a hint that ACID is not required - it is used in NDB for
 
2997
  ALTER Table, for example, when data are copied to temporary table.
 
2998
  A storage engine may treat this hint any way it likes. NDB for example
 
2999
  starts to commit every now and then automatically.
 
3000
  This hint can be safely ignored.
 
3001
*/
 
3002
int ha_enable_transaction(THD *thd, bool on)
 
3003
{
 
3004
  int error=0;
 
3005
 
 
3006
  if ((thd->transaction.on= on))
 
3007
  {
 
3008
    /*
 
3009
      Now all storage engines should have transaction handling enabled.
 
3010
      But some may have it enabled all the time - "disabling" transactions
 
3011
      is an optimization hint that storage engine is free to ignore.
 
3012
      So, let's commit an open transaction (if any) now.
 
3013
    */
 
3014
    if (!(error= ha_commit_trans(thd, 0)))
 
3015
      error= end_trans(thd, COMMIT);
 
3016
  }
 
3017
  return(error);
 
3018
}
 
3019
 
 
3020
int handler::index_next_same(uchar *buf, const uchar *key, uint keylen)
809
3021
{
810
3022
  int error;
811
3023
  if (!(error=index_next(buf)))
812
3024
  {
813
 
    ptrdiff_t ptrdiff= buf - getTable()->getInsertRecord();
814
 
    unsigned char *save_record_0= NULL;
815
 
    KeyInfo *key_info= NULL;
816
 
    KeyPartInfo *key_part;
817
 
    KeyPartInfo *key_part_end= NULL;
 
3025
    my_ptrdiff_t ptrdiff= buf - table->record[0];
 
3026
    uchar *save_record_0= NULL;
 
3027
    KEY *key_info= NULL;
 
3028
    KEY_PART_INFO *key_part;
 
3029
    KEY_PART_INFO *key_part_end= NULL;
818
3030
 
819
3031
    /*
820
 
      key_cmp_if_same() compares table->getInsertRecord() against 'key'.
821
 
      In parts it uses table->getInsertRecord() directly, in parts it uses
822
 
      field objects with their local pointers into table->getInsertRecord().
823
 
      If 'buf' is distinct from table->getInsertRecord(), we need to move
824
 
      all record references. This is table->getInsertRecord() itself and
 
3032
      key_cmp_if_same() compares table->record[0] against 'key'.
 
3033
      In parts it uses table->record[0] directly, in parts it uses
 
3034
      field objects with their local pointers into table->record[0].
 
3035
      If 'buf' is distinct from table->record[0], we need to move
 
3036
      all record references. This is table->record[0] itself and
825
3037
      the field pointers of the fields used in this key.
826
3038
    */
827
3039
    if (ptrdiff)
828
3040
    {
829
 
      save_record_0= getTable()->getInsertRecord();
830
 
      getTable()->record[0]= buf;
831
 
      key_info= getTable()->key_info + active_index;
 
3041
      save_record_0= table->record[0];
 
3042
      table->record[0]= buf;
 
3043
      key_info= table->key_info + active_index;
832
3044
      key_part= key_info->key_part;
833
3045
      key_part_end= key_part + key_info->key_parts;
834
3046
      for (; key_part < key_part_end; key_part++)
838
3050
      }
839
3051
    }
840
3052
 
841
 
    if (key_cmp_if_same(getTable(), key, active_index, keylen))
 
3053
    if (key_cmp_if_same(table, key, active_index, keylen))
842
3054
    {
843
 
      getTable()->status=STATUS_NOT_FOUND;
 
3055
      table->status=STATUS_NOT_FOUND;
844
3056
      error=HA_ERR_END_OF_FILE;
845
3057
    }
846
3058
 
847
3059
    /* Move back if necessary. */
848
3060
    if (ptrdiff)
849
3061
    {
850
 
      getTable()->record[0]= save_record_0;
 
3062
      table->record[0]= save_record_0;
851
3063
      for (key_part= key_info->key_part; key_part < key_part_end; key_part++)
852
3064
        key_part->field->move_field_offset(-ptrdiff);
853
3065
    }
854
3066
  }
855
 
  return error;
 
3067
  return(error);
856
3068
}
857
3069
 
858
3070
 
859
3071
/****************************************************************************
860
 
** Some general functions that isn't in the Cursor class
 
3072
** Some general functions that isn't in the handler class
861
3073
****************************************************************************/
862
3074
 
863
3075
/**
 
3076
  Initiates table-file and calls appropriate database-creator.
 
3077
 
 
3078
  @retval
 
3079
   0  ok
 
3080
  @retval
 
3081
   1  error
 
3082
*/
 
3083
int ha_create_table(THD *thd, const char *path,
 
3084
                    const char *db, const char *table_name,
 
3085
                    HA_CREATE_INFO *create_info,
 
3086
                    bool update_create_info)
 
3087
{
 
3088
  int error= 1;
 
3089
  Table table;
 
3090
  char name_buff[FN_REFLEN];
 
3091
  const char *name;
 
3092
  TABLE_SHARE share;
 
3093
  
 
3094
  init_tmp_table_share(thd, &share, db, 0, table_name, path);
 
3095
  if (open_table_def(thd, &share, 0) ||
 
3096
      open_table_from_share(thd, &share, "", 0, (uint) READ_ALL, 0, &table,
 
3097
                            OTM_CREATE))
 
3098
    goto err;
 
3099
 
 
3100
  if (update_create_info)
 
3101
    table.updateCreateInfo(create_info);
 
3102
 
 
3103
  name= check_lowercase_names(table.file, share.path.str, name_buff);
 
3104
 
 
3105
  error= table.file->ha_create(name, &table, create_info);
 
3106
  VOID(closefrm(&table, 0));
 
3107
  if (error)
 
3108
  {
 
3109
    strxmov(name_buff, db, ".", table_name, NullS);
 
3110
    my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), name_buff, error);
 
3111
  }
 
3112
err:
 
3113
  free_table_share(&share);
 
3114
  return(error != 0);
 
3115
}
 
3116
 
 
3117
/**
 
3118
  Try to discover table from engine.
 
3119
 
 
3120
  @note
 
3121
    If found, write the frm file to disk.
 
3122
 
 
3123
  @retval
 
3124
  -1    Table did not exists
 
3125
  @retval
 
3126
   0    Table created ok
 
3127
  @retval
 
3128
   > 0  Error, table existed but could not be created
 
3129
*/
 
3130
int ha_create_table_from_engine(THD* thd, const char *db, const char *name)
 
3131
{
 
3132
  int error;
 
3133
  uchar *frmblob;
 
3134
  size_t frmlen;
 
3135
  char path[FN_REFLEN];
 
3136
  HA_CREATE_INFO create_info;
 
3137
  Table table;
 
3138
  TABLE_SHARE share;
 
3139
 
 
3140
  memset(&create_info, 0, sizeof(create_info));
 
3141
  if ((error= ha_discover(thd, db, name, &frmblob, &frmlen)))
 
3142
  {
 
3143
    /* Table could not be discovered and thus not created */
 
3144
    return(error);
 
3145
  }
 
3146
 
 
3147
  /*
 
3148
    Table exists in handler and could be discovered
 
3149
    frmblob and frmlen are set, write the frm to disk
 
3150
  */
 
3151
 
 
3152
  build_table_filename(path, FN_REFLEN-1, db, name, "", 0);
 
3153
  // Save the frm file
 
3154
  error= writefrm(path, frmblob, frmlen);
 
3155
  my_free(frmblob, MYF(0));
 
3156
  if (error)
 
3157
    return(2);
 
3158
 
 
3159
  init_tmp_table_share(thd, &share, db, 0, name, path);
 
3160
  if (open_table_def(thd, &share, 0))
 
3161
  {
 
3162
    return(3);
 
3163
  }
 
3164
  if (open_table_from_share(thd, &share, "" ,0, 0, 0, &table, OTM_OPEN))
 
3165
  {
 
3166
    free_table_share(&share);
 
3167
    return(3);
 
3168
  }
 
3169
 
 
3170
  table.updateCreateInfo(&create_info);
 
3171
  create_info.table_options|= HA_OPTION_CREATE_FROM_ENGINE;
 
3172
 
 
3173
  check_lowercase_names(table.file, path, path);
 
3174
  error=table.file->ha_create(path, &table, &create_info);
 
3175
  VOID(closefrm(&table, 1));
 
3176
 
 
3177
  return(error != 0);
 
3178
}
 
3179
 
 
3180
void st_ha_check_opt::init()
 
3181
{
 
3182
  flags= sql_flags= 0;
 
3183
  sort_buffer_size = current_thd->variables.myisam_sort_buff_size;
 
3184
}
 
3185
 
 
3186
 
 
3187
/*****************************************************************************
 
3188
  Key cache handling.
 
3189
 
 
3190
  This code is only relevant for ISAM/MyISAM tables
 
3191
 
 
3192
  key_cache->cache may be 0 only in the case where a key cache is not
 
3193
  initialized or when we where not able to init the key cache in a previous
 
3194
  call to ha_init_key_cache() (probably out of memory)
 
3195
*****************************************************************************/
 
3196
 
 
3197
/**
 
3198
  Init a key cache if it has not been initied before.
 
3199
*/
 
3200
int ha_init_key_cache(const char *name __attribute__((unused)),
 
3201
                      KEY_CACHE *key_cache)
 
3202
{
 
3203
  if (!key_cache->key_cache_inited)
 
3204
  {
 
3205
    pthread_mutex_lock(&LOCK_global_system_variables);
 
3206
    uint32_t tmp_buff_size= (uint32_t) key_cache->param_buff_size;
 
3207
    uint tmp_block_size= (uint) key_cache->param_block_size;
 
3208
    uint division_limit= key_cache->param_division_limit;
 
3209
    uint age_threshold=  key_cache->param_age_threshold;
 
3210
    pthread_mutex_unlock(&LOCK_global_system_variables);
 
3211
    return(!init_key_cache(key_cache,
 
3212
                                tmp_block_size,
 
3213
                                tmp_buff_size,
 
3214
                                division_limit, age_threshold));
 
3215
  }
 
3216
  return(0);
 
3217
}
 
3218
 
 
3219
 
 
3220
/**
 
3221
  Resize key cache.
 
3222
*/
 
3223
int ha_resize_key_cache(KEY_CACHE *key_cache)
 
3224
{
 
3225
  if (key_cache->key_cache_inited)
 
3226
  {
 
3227
    pthread_mutex_lock(&LOCK_global_system_variables);
 
3228
    long tmp_buff_size= (long) key_cache->param_buff_size;
 
3229
    long tmp_block_size= (long) key_cache->param_block_size;
 
3230
    uint division_limit= key_cache->param_division_limit;
 
3231
    uint age_threshold=  key_cache->param_age_threshold;
 
3232
    pthread_mutex_unlock(&LOCK_global_system_variables);
 
3233
    return(!resize_key_cache(key_cache, tmp_block_size,
 
3234
                                  tmp_buff_size,
 
3235
                                  division_limit, age_threshold));
 
3236
  }
 
3237
  return(0);
 
3238
}
 
3239
 
 
3240
 
 
3241
/**
 
3242
  Change parameters for key cache (like size)
 
3243
*/
 
3244
int ha_change_key_cache_param(KEY_CACHE *key_cache)
 
3245
{
 
3246
  if (key_cache->key_cache_inited)
 
3247
  {
 
3248
    pthread_mutex_lock(&LOCK_global_system_variables);
 
3249
    uint division_limit= key_cache->param_division_limit;
 
3250
    uint age_threshold=  key_cache->param_age_threshold;
 
3251
    pthread_mutex_unlock(&LOCK_global_system_variables);
 
3252
    change_key_cache_param(key_cache, division_limit, age_threshold);
 
3253
  }
 
3254
  return 0;
 
3255
}
 
3256
 
 
3257
/**
 
3258
  Free memory allocated by a key cache.
 
3259
*/
 
3260
int ha_end_key_cache(KEY_CACHE *key_cache)
 
3261
{
 
3262
  end_key_cache(key_cache, 1);          // Can never fail
 
3263
  return 0;
 
3264
}
 
3265
 
 
3266
/**
 
3267
  Move all tables from one key cache to another one.
 
3268
*/
 
3269
int ha_change_key_cache(KEY_CACHE *old_key_cache,
 
3270
                        KEY_CACHE *new_key_cache)
 
3271
{
 
3272
  mi_change_key_cache(old_key_cache, new_key_cache);
 
3273
  return 0;
 
3274
}
 
3275
 
 
3276
 
 
3277
/**
 
3278
  Try to discover one table from handler(s).
 
3279
 
 
3280
  @retval
 
3281
    -1   Table did not exists
 
3282
  @retval
 
3283
    0   OK. In this case *frmblob and *frmlen are set
 
3284
  @retval
 
3285
    >0   error.  frmblob and frmlen may not be set
 
3286
*/
 
3287
struct st_discover_args
 
3288
{
 
3289
  const char *db;
 
3290
  const char *name;
 
3291
  uchar **frmblob; 
 
3292
  size_t *frmlen;
 
3293
};
 
3294
 
 
3295
static bool discover_handlerton(THD *thd, plugin_ref plugin,
 
3296
                                void *arg)
 
3297
{
 
3298
  st_discover_args *vargs= (st_discover_args *)arg;
 
3299
  handlerton *hton= plugin_data(plugin, handlerton *);
 
3300
  if (hton->state == SHOW_OPTION_YES && hton->discover &&
 
3301
      (!(hton->discover(hton, thd, vargs->db, vargs->name, 
 
3302
                        vargs->frmblob, 
 
3303
                        vargs->frmlen))))
 
3304
    return true;
 
3305
 
 
3306
  return false;
 
3307
}
 
3308
 
 
3309
int ha_discover(THD *thd, const char *db, const char *name,
 
3310
                uchar **frmblob, size_t *frmlen)
 
3311
{
 
3312
  int error= -1; // Table does not exist in any handler
 
3313
  st_discover_args args= {db, name, frmblob, frmlen};
 
3314
 
 
3315
  if (is_prefix(name,tmp_file_prefix)) /* skip temporary tables */
 
3316
    return(error);
 
3317
 
 
3318
  if (plugin_foreach(thd, discover_handlerton,
 
3319
                 DRIZZLE_STORAGE_ENGINE_PLUGIN, &args))
 
3320
    error= 0;
 
3321
 
 
3322
  if (!error)
 
3323
    status_var_increment(thd->status_var.ha_discover_count);
 
3324
  return(error);
 
3325
}
 
3326
 
 
3327
 
 
3328
/**
 
3329
  Call this function in order to give the handler the possiblity
 
3330
  to ask engine if there are any new tables that should be written to disk
 
3331
  or any dropped tables that need to be removed from disk
 
3332
*/
 
3333
struct st_find_files_args
 
3334
{
 
3335
  const char *db;
 
3336
  const char *path;
 
3337
  const char *wild;
 
3338
  bool dir;
 
3339
  List<LEX_STRING> *files;
 
3340
};
 
3341
 
 
3342
/**
 
3343
  Ask handler if the table exists in engine.
 
3344
  @retval
 
3345
    HA_ERR_NO_SUCH_TABLE     Table does not exist
 
3346
  @retval
 
3347
    HA_ERR_TABLE_EXIST       Table exists
 
3348
  @retval
 
3349
    \#                  Error code
 
3350
*/
 
3351
struct st_table_exists_in_engine_args
 
3352
{
 
3353
  const char *db;
 
3354
  const char *name;
 
3355
  int err;
 
3356
};
 
3357
 
 
3358
static bool table_exists_in_engine_handlerton(THD *thd, plugin_ref plugin,
 
3359
                                              void *arg)
 
3360
{
 
3361
  st_table_exists_in_engine_args *vargs= (st_table_exists_in_engine_args *)arg;
 
3362
  handlerton *hton= plugin_data(plugin, handlerton *);
 
3363
 
 
3364
  int err= HA_ERR_NO_SUCH_TABLE;
 
3365
 
 
3366
  if (hton->state == SHOW_OPTION_YES && hton->table_exists_in_engine)
 
3367
    err = hton->table_exists_in_engine(hton, thd, vargs->db, vargs->name);
 
3368
 
 
3369
  vargs->err = err;
 
3370
  if (vargs->err == HA_ERR_TABLE_EXIST)
 
3371
    return true;
 
3372
 
 
3373
  return false;
 
3374
}
 
3375
 
 
3376
int ha_table_exists_in_engine(THD* thd, const char* db, const char* name)
 
3377
{
 
3378
  st_table_exists_in_engine_args args= {db, name, HA_ERR_NO_SUCH_TABLE};
 
3379
  plugin_foreach(thd, table_exists_in_engine_handlerton,
 
3380
                 DRIZZLE_STORAGE_ENGINE_PLUGIN, &args);
 
3381
  return(args.err);
 
3382
}
 
3383
 
 
3384
/**
864
3385
  Calculate cost of 'index only' scan for given index and number of records
865
3386
 
866
3387
  @param keynr    Index number
869
3390
  @note
870
3391
    It is assumed that we will read trough the whole key range and that all
871
3392
    key blocks are half full (normally things are much better). It is also
872
 
    assumed that each time we read the next key from the index, the Cursor
 
3393
    assumed that each time we read the next key from the index, the handler
873
3394
    performs a random seek, thus the cost is proportional to the number of
874
3395
    blocks read.
875
3396
 
876
3397
  @todo
877
 
    Consider joining this function and Cursor::read_time() into one
878
 
    Cursor::read_time(keynr, records, ranges, bool index_only) function.
 
3398
    Consider joining this function and handler::read_time() into one
 
3399
    handler::read_time(keynr, records, ranges, bool index_only) function.
879
3400
 
880
3401
  @return
881
3402
    Estimated cost of 'index only' scan
882
3403
*/
883
3404
 
884
 
double Cursor::index_only_read_time(uint32_t keynr, double key_records)
 
3405
double handler::index_only_read_time(uint keynr, double records)
885
3406
{
886
 
  uint32_t keys_per_block= (stats.block_size/2/
887
 
                        (getTable()->key_info[keynr].key_length + ref_length) + 1);
888
 
  return ((double) (key_records + keys_per_block-1) /
889
 
          (double) keys_per_block);
 
3407
  double read_time;
 
3408
  uint keys_per_block= (stats.block_size/2/
 
3409
                        (table->key_info[keynr].key_length + ref_length) + 1);
 
3410
  read_time=((double) (records + keys_per_block-1) /
 
3411
             (double) keys_per_block);
 
3412
  return read_time;
890
3413
}
891
3414
 
892
3415
 
913
3436
 
914
3437
  @note
915
3438
    This method (or an overriding one in a derived class) must check for
916
 
    session->getKilled() and return HA_POS_ERROR if it is not zero. This is required
 
3439
    thd->killed and return HA_POS_ERROR if it is not zero. This is required
917
3440
    for a user to be able to interrupt the calculation by killing the
918
3441
    connection/query.
919
3442
 
926
3449
*/
927
3450
 
928
3451
ha_rows
929
 
Cursor::multi_range_read_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
 
3452
handler::multi_range_read_info_const(uint keyno, RANGE_SEQ_IF *seq,
930
3453
                                     void *seq_init_param,
931
 
                                     uint32_t ,
932
 
                                     uint32_t *bufsz, uint32_t *flags, optimizer::CostVector *cost)
 
3454
                                     uint n_ranges_arg __attribute__((unused)),
 
3455
                                     uint *bufsz, uint *flags, COST_VECT *cost)
933
3456
{
934
3457
  KEY_MULTI_RANGE range;
935
3458
  range_seq_t seq_it;
936
3459
  ha_rows rows, total_rows= 0;
937
 
  uint32_t n_ranges=0;
938
 
 
 
3460
  uint n_ranges=0;
 
3461
  THD *thd= current_thd;
 
3462
  
939
3463
  /* Default MRR implementation doesn't need buffer */
940
3464
  *bufsz= 0;
941
3465
 
942
3466
  seq_it= seq->init(seq_init_param, n_ranges, *flags);
943
3467
  while (!seq->next(seq_it, &range))
944
3468
  {
 
3469
    if (unlikely(thd->killed != 0))
 
3470
      return HA_POS_ERROR;
 
3471
    
945
3472
    n_ranges++;
946
3473
    key_range *min_endp, *max_endp;
947
3474
    {
952
3479
      rows= 1; /* there can be at most one row */
953
3480
    else
954
3481
    {
955
 
      if (HA_POS_ERROR == (rows= this->records_in_range(keyno, min_endp,
 
3482
      if (HA_POS_ERROR == (rows= this->records_in_range(keyno, min_endp, 
956
3483
                                                        max_endp)))
957
3484
      {
958
3485
        /* Can't scan one range => can't do MRR scan at all */
962
3489
    }
963
3490
    total_rows += rows;
964
3491
  }
965
 
 
 
3492
  
966
3493
  if (total_rows != HA_POS_ERROR)
967
3494
  {
968
3495
    /* The following calculation is the same as in multi_range_read_info(): */
969
3496
    *flags |= HA_MRR_USE_DEFAULT_IMPL;
970
3497
    cost->zero();
971
 
    cost->setAvgIOCost(1); /* assume random seeks */
 
3498
    cost->avg_io_cost= 1; /* assume random seeks */
972
3499
    if ((*flags & HA_MRR_INDEX_ONLY) && total_rows > 2)
973
 
      cost->setIOCount(index_only_read_time(keyno, (uint32_t)total_rows));
 
3500
      cost->io_count= index_only_read_time(keyno, (uint)total_rows);
974
3501
    else
975
 
      cost->setIOCount(read_time(keyno, n_ranges, total_rows));
976
 
    cost->setCpuCost((double) total_rows / TIME_FOR_COMPARE + 0.01);
 
3502
      cost->io_count= read_time(keyno, n_ranges, total_rows);
 
3503
    cost->cpu_cost= (double) total_rows / TIME_FOR_COMPARE + 0.01;
977
3504
  }
978
3505
  return total_rows;
979
3506
}
1013
3540
    other Error or can't perform the requested scan
1014
3541
*/
1015
3542
 
1016
 
int Cursor::multi_range_read_info(uint32_t keyno, uint32_t n_ranges, uint32_t n_rows,
1017
 
                                   uint32_t *bufsz, uint32_t *flags, optimizer::CostVector *cost)
 
3543
int handler::multi_range_read_info(uint keyno, uint n_ranges, uint n_rows,
 
3544
                                   uint *bufsz, uint *flags, COST_VECT *cost)
1018
3545
{
1019
3546
  *bufsz= 0; /* Default implementation doesn't need a buffer */
1020
3547
 
1021
3548
  *flags |= HA_MRR_USE_DEFAULT_IMPL;
1022
3549
 
1023
3550
  cost->zero();
1024
 
  cost->setAvgIOCost(1); /* assume random seeks */
 
3551
  cost->avg_io_cost= 1; /* assume random seeks */
1025
3552
 
1026
3553
  /* Produce the same cost as non-MRR code does */
1027
3554
  if (*flags & HA_MRR_INDEX_ONLY)
1028
 
    cost->setIOCount(index_only_read_time(keyno, n_rows));
 
3555
    cost->io_count= index_only_read_time(keyno, n_rows);
1029
3556
  else
1030
 
    cost->setIOCount(read_time(keyno, n_ranges, n_rows));
 
3557
    cost->io_count= read_time(keyno, n_ranges, n_rows);
1031
3558
  return 0;
1032
3559
}
1033
3560
 
1035
3562
/**
1036
3563
  Initialize the MRR scan
1037
3564
 
1038
 
  Initialize the MRR scan. This function may do heavyweight scan
 
3565
  Initialize the MRR scan. This function may do heavyweight scan 
1039
3566
  initialization like row prefetching/sorting/etc (NOTE: but better not do
1040
3567
  it here as we may not need it, e.g. if we never satisfy WHERE clause on
1041
3568
  previous tables. For many implementations it would be natural to do such
1042
3569
  initializations in the first multi_read_range_next() call)
1043
3570
 
1044
3571
  mode is a combination of the following flags: HA_MRR_SORTED,
1045
 
  HA_MRR_INDEX_ONLY, HA_MRR_NO_ASSOCIATION
 
3572
  HA_MRR_INDEX_ONLY, HA_MRR_NO_ASSOCIATION 
1046
3573
 
1047
3574
  @param seq             Range sequence to be traversed
1048
3575
  @param seq_init_param  First parameter for seq->init()
1051
3578
  @param buf             INOUT: memory buffer to be used
1052
3579
 
1053
3580
  @note
1054
 
    One must have called doStartIndexScan() before calling this function. Several
 
3581
    One must have called index_init() before calling this function. Several
1055
3582
    multi_range_read_init() calls may be made in course of one query.
1056
3583
 
1057
 
    Until WL#2623 is done (see its text, section 3.2), the following will
 
3584
    Until WL#2623 is done (see its text, section 3.2), the following will 
1058
3585
    also hold:
1059
3586
    The caller will guarantee that if "seq->init == mrr_ranges_array_init"
1060
3587
    then seq_init_param is an array of n_ranges KEY_MULTI_RANGE structures.
1061
 
    This property will only be used by NDB Cursor until WL#2623 is done.
1062
 
 
 
3588
    This property will only be used by NDB handler until WL#2623 is done.
 
3589
     
1063
3590
    Buffer memory management is done according to the following scenario:
1064
3591
    The caller allocates the buffer and provides it to the callee by filling
1065
3592
    the members of HANDLER_BUFFER structure.
1066
3593
    The callee consumes all or some fraction of the provided buffer space, and
1067
3594
    sets the HANDLER_BUFFER members accordingly.
1068
3595
    The callee may use the buffer memory until the next multi_range_read_init()
1069
 
    call is made, all records have been read, or until doEndIndexScan() call is
 
3596
    call is made, all records have been read, or until index_end() call is
1070
3597
    made, whichever comes first.
1071
3598
 
1072
3599
  @retval 0  OK
1074
3601
*/
1075
3602
 
1076
3603
int
1077
 
Cursor::multi_range_read_init(RANGE_SEQ_IF *seq_funcs, void *seq_init_param,
1078
 
                               uint32_t n_ranges, uint32_t mode)
 
3604
handler::multi_range_read_init(RANGE_SEQ_IF *seq_funcs, void *seq_init_param,
 
3605
                               uint n_ranges, uint mode,
 
3606
                               HANDLER_BUFFER *buf __attribute__((unused)))
1079
3607
{
1080
3608
  mrr_iter= seq_funcs->init(seq_init_param, n_ranges, mode);
1081
3609
  mrr_funcs= *seq_funcs;
1082
3610
  mrr_is_output_sorted= test(mode & HA_MRR_SORTED);
1083
3611
  mrr_have_range= false;
1084
 
 
1085
 
  return 0;
 
3612
  return(0);
1086
3613
}
1087
3614
 
1088
3615
 
1099
3626
  @retval other  Error code
1100
3627
*/
1101
3628
 
1102
 
int Cursor::multi_range_read_next(char **range_info)
 
3629
int handler::multi_range_read_next(char **range_info)
1103
3630
{
1104
3631
  int result= 0;
1105
3632
  int range_res= 0;
1106
3633
 
1107
 
  if (not mrr_have_range)
 
3634
  if (!mrr_have_range)
1108
3635
  {
1109
3636
    mrr_have_range= true;
1110
3637
    goto start;
1149
3676
  while ((result == HA_ERR_END_OF_FILE) && !range_res);
1150
3677
 
1151
3678
  *range_info= mrr_cur_range.ptr;
1152
 
  return result;
 
3679
  return(result);
 
3680
}
 
3681
 
 
3682
 
 
3683
/* **************************************************************************
 
3684
 * DS-MRR implementation 
 
3685
 ***************************************************************************/
 
3686
 
 
3687
/**
 
3688
  DS-MRR: Initialize and start MRR scan
 
3689
 
 
3690
  Initialize and start the MRR scan. Depending on the mode parameter, this
 
3691
  may use default or DS-MRR implementation.
 
3692
 
 
3693
  @param h               Table handler to be used
 
3694
  @param key             Index to be used
 
3695
  @param seq_funcs       Interval sequence enumeration functions
 
3696
  @param seq_init_param  Interval sequence enumeration parameter
 
3697
  @param n_ranges        Number of ranges in the sequence.
 
3698
  @param mode            HA_MRR_* modes to use
 
3699
  @param buf             INOUT Buffer to use
 
3700
 
 
3701
  @retval 0     Ok, Scan started.
 
3702
  @retval other Error
 
3703
*/
 
3704
 
 
3705
int DsMrr_impl::dsmrr_init(handler *h, KEY *key,
 
3706
                           RANGE_SEQ_IF *seq_funcs, void *seq_init_param,
 
3707
                           uint n_ranges, uint mode, HANDLER_BUFFER *buf)
 
3708
{
 
3709
  uint elem_size;
 
3710
  uint keyno;
 
3711
  Item *pushed_cond= NULL;
 
3712
  handler *new_h2;
 
3713
  keyno= h->active_index;
 
3714
  assert(h2 == NULL);
 
3715
  if (mode & HA_MRR_USE_DEFAULT_IMPL || mode & HA_MRR_SORTED)
 
3716
  {
 
3717
    use_default_impl= true;
 
3718
    return(h->handler::multi_range_read_init(seq_funcs, seq_init_param,
 
3719
                                                  n_ranges, mode, buf));
 
3720
  }
 
3721
  rowids_buf= buf->buffer;
 
3722
  //psergey-todo: don't add key_length as it is not needed anymore
 
3723
  rowids_buf += key->key_length + h->ref_length;
 
3724
 
 
3725
  is_mrr_assoc= !test(mode & HA_MRR_NO_ASSOCIATION);
 
3726
  rowids_buf_end= buf->buffer_end;
 
3727
  
 
3728
  elem_size= h->ref_length + (int)is_mrr_assoc * sizeof(void*);
 
3729
  rowids_buf_last= rowids_buf + 
 
3730
                      ((rowids_buf_end - rowids_buf)/ elem_size)*
 
3731
                      elem_size;
 
3732
  rowids_buf_end= rowids_buf_last;
 
3733
 
 
3734
  /* Create a separate handler object to do rndpos() calls. */
 
3735
  THD *thd= current_thd;
 
3736
  if (!(new_h2= h->clone(thd->mem_root)) || 
 
3737
      new_h2->ha_external_lock(thd, F_RDLCK))
 
3738
  {
 
3739
    delete new_h2;
 
3740
    return(1);
 
3741
  }
 
3742
 
 
3743
  if (keyno == h->pushed_idx_cond_keyno)
 
3744
    pushed_cond= h->pushed_idx_cond;
 
3745
  if (h->ha_index_end())
 
3746
  {
 
3747
    new_h2= h2;
 
3748
    goto error;
 
3749
  }
 
3750
 
 
3751
  h2= new_h2;
 
3752
  table->prepare_for_position();
 
3753
  new_h2->extra(HA_EXTRA_KEYREAD);
 
3754
 
 
3755
  if (h2->ha_index_init(keyno, false) || 
 
3756
      h2->handler::multi_range_read_init(seq_funcs, seq_init_param, n_ranges,
 
3757
                                         mode, buf))
 
3758
    goto error;
 
3759
  use_default_impl= false;
 
3760
  
 
3761
  if (pushed_cond)
 
3762
    h2->idx_cond_push(keyno, pushed_cond);
 
3763
  if (dsmrr_fill_buffer(new_h2))
 
3764
    goto error;
 
3765
 
 
3766
  /*
 
3767
    If the above call has scanned through all intervals in *seq, then
 
3768
    adjust *buf to indicate that the remaining buffer space will not be used.
 
3769
  */
 
3770
  if (dsmrr_eof) 
 
3771
    buf->end_of_used_area= rowids_buf_last;
 
3772
 
 
3773
  if (h->ha_rnd_init(false))
 
3774
    goto error;
 
3775
  
 
3776
  return(0);
 
3777
error:
 
3778
  h2->ha_index_or_rnd_end();
 
3779
  h2->ha_external_lock(thd, F_UNLCK);
 
3780
  h2->close();
 
3781
  delete h2;
 
3782
  return(1);
 
3783
}
 
3784
 
 
3785
 
 
3786
void DsMrr_impl::dsmrr_close()
 
3787
{
 
3788
  if (h2)
 
3789
  {
 
3790
    h2->ha_external_lock(current_thd, F_UNLCK);
 
3791
    h2->close();
 
3792
    delete h2;
 
3793
    h2= NULL;
 
3794
  }
 
3795
  use_default_impl= true;
 
3796
  return;
 
3797
}
 
3798
 
 
3799
 
 
3800
static int rowid_cmp(void *h, uchar *a, uchar *b)
 
3801
{
 
3802
  return ((handler*)h)->cmp_ref(a, b);
 
3803
}
 
3804
 
 
3805
 
 
3806
/**
 
3807
  DS-MRR: Fill the buffer with rowids and sort it by rowid
 
3808
 
 
3809
  {This is an internal function of DiskSweep MRR implementation}
 
3810
  Scan the MRR ranges and collect ROWIDs (or {ROWID, range_id} pairs) into 
 
3811
  buffer. When the buffer is full or scan is completed, sort the buffer by 
 
3812
  rowid and return.
 
3813
  
 
3814
  The function assumes that rowids buffer is empty when it is invoked. 
 
3815
  
 
3816
  @param h  Table handler
 
3817
 
 
3818
  @retval 0      OK, the next portion of rowids is in the buffer,
 
3819
                 properly ordered
 
3820
  @retval other  Error
 
3821
*/
 
3822
 
 
3823
int DsMrr_impl::dsmrr_fill_buffer(handler *unused __attribute__((unused)))
 
3824
{
 
3825
  char *range_info;
 
3826
  int res = 0;
 
3827
 
 
3828
  rowids_buf_cur= rowids_buf;
 
3829
  while ((rowids_buf_cur < rowids_buf_end) && 
 
3830
         !(res= h2->handler::multi_range_read_next(&range_info)))
 
3831
  {
 
3832
    /* Put rowid, or {rowid, range_id} pair into the buffer */
 
3833
    h2->position(table->record[0]);
 
3834
    memcpy(rowids_buf_cur, h2->ref, h2->ref_length);
 
3835
    rowids_buf_cur += h->ref_length;
 
3836
 
 
3837
    if (is_mrr_assoc)
 
3838
    {
 
3839
      memcpy(rowids_buf_cur, &range_info, sizeof(void*));
 
3840
      rowids_buf_cur += sizeof(void*);
 
3841
    }
 
3842
  }
 
3843
 
 
3844
  if (res && res != HA_ERR_END_OF_FILE)
 
3845
    return(res); 
 
3846
  dsmrr_eof= test(res == HA_ERR_END_OF_FILE);
 
3847
 
 
3848
  /* Sort the buffer contents by rowid */
 
3849
  uint elem_size= h->ref_length + (int)is_mrr_assoc * sizeof(void*);
 
3850
  uint n_rowids= (rowids_buf_cur - rowids_buf) / elem_size;
 
3851
  
 
3852
  my_qsort2(rowids_buf, n_rowids, elem_size, (qsort2_cmp)rowid_cmp,
 
3853
            (void*)h);
 
3854
  rowids_buf_last= rowids_buf_cur;
 
3855
  rowids_buf_cur=  rowids_buf;
 
3856
  return(0);
 
3857
}
 
3858
 
 
3859
 
 
3860
/**
 
3861
  DS-MRR implementation: multi_range_read_next() function
 
3862
*/
 
3863
 
 
3864
int DsMrr_impl::dsmrr_next(handler *h, char **range_info)
 
3865
{
 
3866
  int res;
 
3867
  
 
3868
  if (use_default_impl)
 
3869
    return h->handler::multi_range_read_next(range_info);
 
3870
    
 
3871
  if (rowids_buf_cur == rowids_buf_last)
 
3872
  {
 
3873
    if (dsmrr_eof)
 
3874
    {
 
3875
      res= HA_ERR_END_OF_FILE;
 
3876
      goto end;
 
3877
    }
 
3878
    res= dsmrr_fill_buffer(h);
 
3879
    if (res)
 
3880
      goto end;
 
3881
  }
 
3882
  
 
3883
  /* Return EOF if there are no rowids in the buffer after re-fill attempt */
 
3884
  if (rowids_buf_cur == rowids_buf_last)
 
3885
  {
 
3886
    res= HA_ERR_END_OF_FILE;
 
3887
    goto end;
 
3888
  }
 
3889
 
 
3890
  res= h->rnd_pos(table->record[0], rowids_buf_cur);
 
3891
  rowids_buf_cur += h->ref_length;
 
3892
  if (is_mrr_assoc)
 
3893
  {
 
3894
    memcpy(range_info, rowids_buf_cur, sizeof(void*));
 
3895
    rowids_buf_cur += sizeof(void*);
 
3896
  }
 
3897
 
 
3898
end:
 
3899
  if (res)
 
3900
    dsmrr_close();
 
3901
  return res;
 
3902
}
 
3903
 
 
3904
 
 
3905
/**
 
3906
  DS-MRR implementation: multi_range_read_info() function
 
3907
*/
 
3908
int DsMrr_impl::dsmrr_info(uint keyno, uint n_ranges, uint rows, uint *bufsz,
 
3909
                           uint *flags, COST_VECT *cost)
 
3910
{  
 
3911
  int res;
 
3912
  uint def_flags= *flags;
 
3913
  uint def_bufsz= *bufsz;
 
3914
 
 
3915
  /* Get cost/flags/mem_usage of default MRR implementation */
 
3916
  res= h->handler::multi_range_read_info(keyno, n_ranges, rows, &def_bufsz,
 
3917
                                         &def_flags, cost);
 
3918
  assert(!res);
 
3919
 
 
3920
  if ((*flags & HA_MRR_USE_DEFAULT_IMPL) || 
 
3921
      choose_mrr_impl(keyno, rows, &def_flags, &def_bufsz, cost))
 
3922
  {
 
3923
    /* Default implementation is choosen */
 
3924
    *flags= def_flags;
 
3925
    *bufsz= def_bufsz;
 
3926
  }
 
3927
  return 0;
 
3928
}
 
3929
 
 
3930
 
 
3931
/**
 
3932
  DS-MRR Implementation: multi_range_read_info_const() function
 
3933
*/
 
3934
 
 
3935
ha_rows DsMrr_impl::dsmrr_info_const(uint keyno, RANGE_SEQ_IF *seq,
 
3936
                                 void *seq_init_param, uint n_ranges, 
 
3937
                                 uint *bufsz, uint *flags, COST_VECT *cost)
 
3938
{
 
3939
  ha_rows rows;
 
3940
  uint def_flags= *flags;
 
3941
  uint def_bufsz= *bufsz;
 
3942
  /* Get cost/flags/mem_usage of default MRR implementation */
 
3943
  rows= h->handler::multi_range_read_info_const(keyno, seq, seq_init_param,
 
3944
                                                n_ranges, &def_bufsz, 
 
3945
                                                &def_flags, cost);
 
3946
  if (rows == HA_POS_ERROR)
 
3947
  {
 
3948
    /* Default implementation can't perform MRR scan => we can't either */
 
3949
    return rows;
 
3950
  }
 
3951
 
 
3952
  /*
 
3953
    If HA_MRR_USE_DEFAULT_IMPL has been passed to us, that is an order to
 
3954
    use the default MRR implementation (we need it for UPDATE/DELETE).
 
3955
    Otherwise, make a choice based on cost and @@optimizer_use_mrr.
 
3956
  */
 
3957
  if ((*flags & HA_MRR_USE_DEFAULT_IMPL) ||
 
3958
      choose_mrr_impl(keyno, rows, flags, bufsz, cost))
 
3959
  {
 
3960
    *flags= def_flags;
 
3961
    *bufsz= def_bufsz;
 
3962
  }
 
3963
  else
 
3964
  {
 
3965
    *flags &= ~HA_MRR_USE_DEFAULT_IMPL;
 
3966
  }
 
3967
  return rows;
 
3968
}
 
3969
 
 
3970
 
 
3971
/**
 
3972
  Check if key has partially-covered columns
 
3973
 
 
3974
  We can't use DS-MRR to perform range scans when the ranges are over
 
3975
  partially-covered keys, because we'll not have full key part values
 
3976
  (we'll have their prefixes from the index) and will not be able to check
 
3977
  if we've reached the end the range.
 
3978
 
 
3979
  @param keyno  Key to check
 
3980
 
 
3981
  @todo
 
3982
    Allow use of DS-MRR in cases where the index has partially-covered
 
3983
    components but they are not used for scanning.
 
3984
 
 
3985
  @retval true   Yes
 
3986
  @retval false  No
 
3987
*/
 
3988
 
 
3989
bool DsMrr_impl::key_uses_partial_cols(uint keyno)
 
3990
{
 
3991
  KEY_PART_INFO *kp= table->key_info[keyno].key_part;
 
3992
  KEY_PART_INFO *kp_end= kp + table->key_info[keyno].key_parts;
 
3993
  for (; kp != kp_end; kp++)
 
3994
  {
 
3995
    if (!kp->field->part_of_key.is_set(keyno))
 
3996
      return true;
 
3997
  }
 
3998
  return false;
 
3999
}
 
4000
 
 
4001
 
 
4002
/**
 
4003
  DS-MRR Internals: Choose between Default MRR implementation and DS-MRR
 
4004
 
 
4005
  Make the choice between using Default MRR implementation and DS-MRR.
 
4006
  This function contains common functionality factored out of dsmrr_info()
 
4007
  and dsmrr_info_const(). The function assumes that the default MRR
 
4008
  implementation's applicability requirements are satisfied.
 
4009
 
 
4010
  @param keyno       Index number
 
4011
  @param rows        E(full rows to be retrieved)
 
4012
  @param flags  IN   MRR flags provided by the MRR user
 
4013
                OUT  If DS-MRR is choosen, flags of DS-MRR implementation
 
4014
                     else the value is not modified
 
4015
  @param bufsz  IN   If DS-MRR is choosen, buffer use of DS-MRR implementation
 
4016
                     else the value is not modified
 
4017
  @param cost   IN   Cost of default MRR implementation
 
4018
                OUT  If DS-MRR is choosen, cost of DS-MRR scan
 
4019
                     else the value is not modified
 
4020
 
 
4021
  @retval true   Default MRR implementation should be used
 
4022
  @retval false  DS-MRR implementation should be used
 
4023
*/
 
4024
 
 
4025
bool DsMrr_impl::choose_mrr_impl(uint keyno, ha_rows rows, uint *flags,
 
4026
                                 uint *bufsz, COST_VECT *cost)
 
4027
{
 
4028
  COST_VECT dsmrr_cost;
 
4029
  bool res;
 
4030
  THD *thd= current_thd;
 
4031
  if ((thd->variables.optimizer_use_mrr == 2) || 
 
4032
      (*flags & HA_MRR_INDEX_ONLY) || (*flags & HA_MRR_SORTED) ||
 
4033
      (keyno == table->s->primary_key && 
 
4034
       h->primary_key_is_clustered()) || 
 
4035
       key_uses_partial_cols(keyno))
 
4036
  {
 
4037
    /* Use the default implementation */
 
4038
    *flags |= HA_MRR_USE_DEFAULT_IMPL;
 
4039
    return true;
 
4040
  }
 
4041
  
 
4042
  uint add_len= table->key_info[keyno].key_length + h->ref_length; 
 
4043
  *bufsz -= add_len;
 
4044
  if (get_disk_sweep_mrr_cost(keyno, rows, *flags, bufsz, &dsmrr_cost))
 
4045
    return true;
 
4046
  *bufsz += add_len;
 
4047
  
 
4048
  bool force_dsmrr;
 
4049
  /* 
 
4050
    If @@optimizer_use_mrr==force, then set cost of DS-MRR to be minimum of
 
4051
    DS-MRR and Default implementations cost. This allows one to force use of
 
4052
    DS-MRR whenever it is applicable without affecting other cost-based
 
4053
    choices.
 
4054
  */
 
4055
  if ((force_dsmrr= (thd->variables.optimizer_use_mrr == 1)) &&
 
4056
      dsmrr_cost.total_cost() > cost->total_cost())
 
4057
    dsmrr_cost= *cost;
 
4058
 
 
4059
  if (force_dsmrr || dsmrr_cost.total_cost() <= cost->total_cost())
 
4060
  {
 
4061
    *flags &= ~HA_MRR_USE_DEFAULT_IMPL;  /* Use the DS-MRR implementation */
 
4062
    *flags &= ~HA_MRR_SORTED;          /* We will return unordered output */
 
4063
    *cost= dsmrr_cost;
 
4064
    res= false;
 
4065
  }
 
4066
  else
 
4067
  {
 
4068
    /* Use the default MRR implementation */
 
4069
    res= true;
 
4070
  }
 
4071
  return res;
 
4072
}
 
4073
 
 
4074
 
 
4075
static void get_sort_and_sweep_cost(Table *table, ha_rows nrows, COST_VECT *cost);
 
4076
 
 
4077
 
 
4078
/**
 
4079
  Get cost of DS-MRR scan
 
4080
 
 
4081
  @param keynr              Index to be used
 
4082
  @param rows               E(Number of rows to be scanned)
 
4083
  @param flags              Scan parameters (HA_MRR_* flags)
 
4084
  @param buffer_size INOUT  Buffer size
 
4085
  @param cost        OUT    The cost
 
4086
 
 
4087
  @retval false  OK
 
4088
  @retval true   Error, DS-MRR cannot be used (the buffer is too small
 
4089
                 for even 1 rowid)
 
4090
*/
 
4091
 
 
4092
bool DsMrr_impl::get_disk_sweep_mrr_cost(uint keynr, ha_rows rows, uint flags,
 
4093
                                         uint *buffer_size, COST_VECT *cost)
 
4094
{
 
4095
  uint32_t max_buff_entries, elem_size;
 
4096
  ha_rows rows_in_full_step, rows_in_last_step;
 
4097
  uint n_full_steps;
 
4098
  double index_read_cost;
 
4099
 
 
4100
  elem_size= h->ref_length + sizeof(void*) * (!test(flags & HA_MRR_NO_ASSOCIATION));
 
4101
  max_buff_entries = *buffer_size / elem_size;
 
4102
 
 
4103
  if (!max_buff_entries)
 
4104
    return true; /* Buffer has not enough space for even 1 rowid */
 
4105
 
 
4106
  /* Number of iterations we'll make with full buffer */
 
4107
  n_full_steps= (uint)floor(rows2double(rows) / max_buff_entries);
 
4108
  
 
4109
  /* 
 
4110
    Get numbers of rows we'll be processing in 
 
4111
     - non-last sweep, with full buffer 
 
4112
     - last iteration, with non-full buffer
 
4113
  */
 
4114
  rows_in_full_step= max_buff_entries;
 
4115
  rows_in_last_step= rows % max_buff_entries;
 
4116
  
 
4117
  /* Adjust buffer size if we expect to use only part of the buffer */
 
4118
  if (n_full_steps)
 
4119
  {
 
4120
    get_sort_and_sweep_cost(table, rows, cost);
 
4121
    cost->multiply(n_full_steps);
 
4122
  }
 
4123
  else
 
4124
  {
 
4125
    cost->zero();
 
4126
    *buffer_size= max((ulong)*buffer_size, 
 
4127
                      (size_t)(1.2*rows_in_last_step) * elem_size + 
 
4128
                      h->ref_length + table->key_info[keynr].key_length);
 
4129
  }
 
4130
  
 
4131
  COST_VECT last_step_cost;
 
4132
  get_sort_and_sweep_cost(table, rows_in_last_step, &last_step_cost);
 
4133
  cost->add(&last_step_cost);
 
4134
 
 
4135
  if (n_full_steps != 0)
 
4136
    cost->mem_cost= *buffer_size;
 
4137
  else
 
4138
    cost->mem_cost= (double)rows_in_last_step * elem_size;
 
4139
  
 
4140
  /* Total cost of all index accesses */
 
4141
  index_read_cost= h->index_only_read_time(keynr, (double)rows);
 
4142
  cost->add_io(index_read_cost, 1 /* Random seeks */);
 
4143
  return false;
 
4144
}
 
4145
 
 
4146
 
 
4147
/* 
 
4148
  Get cost of one sort-and-sweep step
 
4149
 
 
4150
  SYNOPSIS
 
4151
    get_sort_and_sweep_cost()
 
4152
      table       Table being accessed
 
4153
      nrows       Number of rows to be sorted and retrieved
 
4154
      cost   OUT  The cost
 
4155
 
 
4156
  DESCRIPTION
 
4157
    Get cost of these operations:
 
4158
     - sort an array of #nrows ROWIDs using qsort
 
4159
     - read #nrows records from table in a sweep.
 
4160
*/
 
4161
 
 
4162
static 
 
4163
void get_sort_and_sweep_cost(Table *table, ha_rows nrows, COST_VECT *cost)
 
4164
{
 
4165
  if (nrows)
 
4166
  {
 
4167
    get_sweep_read_cost(table, nrows, false, cost);
 
4168
    /* Add cost of qsort call: n * log2(n) * cost(rowid_comparison) */
 
4169
    double cmp_op= rows2double(nrows) * (1.0 / TIME_FOR_COMPARE_ROWID);
 
4170
    if (cmp_op < 3)
 
4171
      cmp_op= 3;
 
4172
    cost->cpu_cost += cmp_op * log2(cmp_op);
 
4173
  }
 
4174
  else
 
4175
    cost->zero();
 
4176
}
 
4177
 
 
4178
 
 
4179
/**
 
4180
  Get cost of reading nrows table records in a "disk sweep"
 
4181
 
 
4182
  A disk sweep read is a sequence of handler->rnd_pos(rowid) calls that made
 
4183
  for an ordered sequence of rowids.
 
4184
 
 
4185
  We assume hard disk IO. The read is performed as follows:
 
4186
 
 
4187
   1. The disk head is moved to the needed cylinder
 
4188
   2. The controller waits for the plate to rotate
 
4189
   3. The data is transferred
 
4190
 
 
4191
  Time to do #3 is insignificant compared to #2+#1.
 
4192
 
 
4193
  Time to move the disk head is proportional to head travel distance.
 
4194
 
 
4195
  Time to wait for the plate to rotate depends on whether the disk head
 
4196
  was moved or not. 
 
4197
 
 
4198
  If disk head wasn't moved, the wait time is proportional to distance
 
4199
  between the previous block and the block we're reading.
 
4200
 
 
4201
  If the head was moved, we don't know how much we'll need to wait for the
 
4202
  plate to rotate. We assume the wait time to be a variate with a mean of
 
4203
  0.5 of full rotation time.
 
4204
 
 
4205
  Our cost units are "random disk seeks". The cost of random disk seek is
 
4206
  actually not a constant, it depends one range of cylinders we're going
 
4207
  to access. We make it constant by introducing a fuzzy concept of "typical 
 
4208
  datafile length" (it's fuzzy as it's hard to tell whether it should
 
4209
  include index file, temp.tables etc). Then random seek cost is:
 
4210
 
 
4211
    1 = half_rotation_cost + move_cost * 1/3 * typical_data_file_length
 
4212
 
 
4213
  We define half_rotation_cost as DISK_SEEK_BASE_COST=0.9.
 
4214
 
 
4215
  @param table             Table to be accessed
 
4216
  @param nrows             Number of rows to retrieve
 
4217
  @param interrupted       true <=> Assume that the disk sweep will be
 
4218
                           interrupted by other disk IO. false - otherwise.
 
4219
  @param cost         OUT  The cost.
 
4220
*/
 
4221
 
 
4222
void get_sweep_read_cost(Table *table, ha_rows nrows, bool interrupted, 
 
4223
                         COST_VECT *cost)
 
4224
{
 
4225
  cost->zero();
 
4226
  if (table->file->primary_key_is_clustered())
 
4227
  {
 
4228
    cost->io_count= table->file->read_time(table->s->primary_key,
 
4229
                                           (uint) nrows, nrows);
 
4230
  }
 
4231
  else
 
4232
  {
 
4233
    double n_blocks=
 
4234
      ceil(uint64_t2double(table->file->stats.data_file_length) / IO_SIZE);
 
4235
    double busy_blocks=
 
4236
      n_blocks * (1.0 - pow(1.0 - 1.0/n_blocks, rows2double(nrows)));
 
4237
    if (busy_blocks < 1.0)
 
4238
      busy_blocks= 1.0;
 
4239
 
 
4240
    cost->io_count= busy_blocks;
 
4241
 
 
4242
    if (!interrupted)
 
4243
    {
 
4244
      /* Assume reading is done in one 'sweep' */
 
4245
      cost->avg_io_cost= (DISK_SEEK_BASE_COST +
 
4246
                          DISK_SEEK_PROP_COST*n_blocks/busy_blocks);
 
4247
    }
 
4248
  }
 
4249
  return;
1153
4250
}
1154
4251
 
1155
4252
 
1166
4263
  @param sorted         Set to 1 if result should be sorted per key
1167
4264
 
1168
4265
  @note
1169
 
    Record is read into table->getInsertRecord()
 
4266
    Record is read into table->record[0]
1170
4267
 
1171
4268
  @retval
1172
4269
    0                   Found row
1175
4272
  @retval
1176
4273
    \#                  Error code
1177
4274
*/
1178
 
int Cursor::read_range_first(const key_range *start_key,
1179
 
                             const key_range *end_key,
1180
 
                             bool eq_range_arg,
1181
 
                             bool )
 
4275
int handler::read_range_first(const key_range *start_key,
 
4276
                              const key_range *end_key,
 
4277
                              bool eq_range_arg,
 
4278
                              bool sorted  __attribute__((unused)))
1182
4279
{
1183
4280
  int result;
1184
4281
 
1191
4288
    key_compare_result_on_equal= ((end_key->flag == HA_READ_BEFORE_KEY) ? 1 :
1192
4289
                                  (end_key->flag == HA_READ_AFTER_KEY) ? -1 : 0);
1193
4290
  }
1194
 
  range_key_part= getTable()->key_info[active_index].key_part;
 
4291
  range_key_part= table->key_info[active_index].key_part;
1195
4292
 
1196
4293
  if (!start_key)                       // Read first record
1197
 
    result= index_first(getTable()->getInsertRecord());
 
4294
    result= index_first(table->record[0]);
1198
4295
  else
1199
 
    result= index_read_map(getTable()->getInsertRecord(),
 
4296
    result= index_read_map(table->record[0],
1200
4297
                           start_key->key,
1201
4298
                           start_key->keypart_map,
1202
4299
                           start_key->flag);
1203
4300
  if (result)
1204
 
    return((result == HA_ERR_KEY_NOT_FOUND)
 
4301
    return((result == HA_ERR_KEY_NOT_FOUND) 
1205
4302
                ? HA_ERR_END_OF_FILE
1206
4303
                : result);
1207
4304
 
1213
4310
  Read next row between two endpoints.
1214
4311
 
1215
4312
  @note
1216
 
    Record is read into table->getInsertRecord()
 
4313
    Record is read into table->record[0]
1217
4314
 
1218
4315
  @retval
1219
4316
    0                   Found row
1222
4319
  @retval
1223
4320
    \#                  Error code
1224
4321
*/
1225
 
int Cursor::read_range_next()
 
4322
int handler::read_range_next()
1226
4323
{
1227
4324
  int result;
1228
4325
 
1229
4326
  if (eq_range)
1230
4327
  {
1231
4328
    /* We trust that index_next_same always gives a row in range */
1232
 
    return(index_next_same(getTable()->getInsertRecord(),
 
4329
    return(index_next_same(table->record[0],
1233
4330
                                end_range->key,
1234
4331
                                end_range->length));
1235
4332
  }
1236
 
  result= index_next(getTable()->getInsertRecord());
 
4333
  result= index_next(table->record[0]);
1237
4334
  if (result)
1238
 
    return result;
 
4335
    return(result);
1239
4336
  return(compare_key(end_range) <= 0 ? 0 : HA_ERR_END_OF_FILE);
1240
4337
}
1241
4338
 
1255
4352
    - -1  : Key is less than range
1256
4353
    - 1   : Key is larger than range
1257
4354
*/
1258
 
int Cursor::compare_key(key_range *range)
 
4355
int handler::compare_key(key_range *range)
1259
4356
{
1260
4357
  int cmp;
1261
 
  if (not range)
 
4358
  if (!range || in_range_check_pushed_down)
1262
4359
    return 0;                                   // No max range
1263
4360
  cmp= key_cmp(range_key_part, range->key, range->length);
1264
4361
  if (!cmp)
1266
4363
  return cmp;
1267
4364
}
1268
4365
 
1269
 
int Cursor::index_read_idx_map(unsigned char * buf, uint32_t index,
1270
 
                                const unsigned char * key,
 
4366
 
 
4367
/*
 
4368
  Same as compare_key() but doesn't check have in_range_check_pushed_down.
 
4369
  This is used by index condition pushdown implementation.
 
4370
*/
 
4371
 
 
4372
int handler::compare_key2(key_range *range)
 
4373
{
 
4374
  int cmp;
 
4375
  if (!range)
 
4376
    return 0;                                   // no max range
 
4377
  cmp= key_cmp(range_key_part, range->key, range->length);
 
4378
  if (!cmp)
 
4379
    cmp= key_compare_result_on_equal;
 
4380
  return cmp;
 
4381
}
 
4382
 
 
4383
int handler::index_read_idx_map(uchar * buf, uint index, const uchar * key,
1271
4384
                                key_part_map keypart_map,
1272
4385
                                enum ha_rkey_function find_flag)
1273
4386
{
1274
4387
  int error, error1;
1275
 
  error= doStartIndexScan(index, 0);
 
4388
  error= index_init(index, 0);
1276
4389
  if (!error)
1277
4390
  {
1278
4391
    error= index_read_map(buf, key, keypart_map, find_flag);
1279
 
    error1= doEndIndexScan();
 
4392
    error1= index_end();
1280
4393
  }
1281
4394
  return error ?  error : error1;
1282
4395
}
1283
4396
 
 
4397
 
 
4398
/**
 
4399
  Returns a list of all known extensions.
 
4400
 
 
4401
    No mutexes, worst case race is a minor surplus memory allocation
 
4402
    We have to recreate the extension map if mysqld is restarted (for example
 
4403
    within libmysqld)
 
4404
 
 
4405
  @retval
 
4406
    pointer             pointer to TYPELIB structure
 
4407
*/
 
4408
static bool exts_handlerton(THD *unused __attribute__((unused)),
 
4409
                            plugin_ref plugin,
 
4410
                            void *arg)
 
4411
{
 
4412
  List<char> *found_exts= (List<char> *) arg;
 
4413
  handlerton *hton= plugin_data(plugin, handlerton *);
 
4414
  handler *file;
 
4415
  if (hton->state == SHOW_OPTION_YES && hton->create &&
 
4416
      (file= hton->create(hton, (TABLE_SHARE*) 0, current_thd->mem_root)))
 
4417
  {
 
4418
    List_iterator_fast<char> it(*found_exts);
 
4419
    const char **ext, *old_ext;
 
4420
 
 
4421
    for (ext= file->bas_ext(); *ext; ext++)
 
4422
    {
 
4423
      while ((old_ext= it++))
 
4424
      {
 
4425
        if (!strcmp(old_ext, *ext))
 
4426
          break;
 
4427
      }
 
4428
      if (!old_ext)
 
4429
        found_exts->push_back((char *) *ext);
 
4430
 
 
4431
      it.rewind();
 
4432
    }
 
4433
    delete file;
 
4434
  }
 
4435
  return false;
 
4436
}
 
4437
 
 
4438
TYPELIB *ha_known_exts(void)
 
4439
{
 
4440
  if (!known_extensions.type_names || mysys_usage_id != known_extensions_id)
 
4441
  {
 
4442
    List<char> found_exts;
 
4443
    const char **ext, *old_ext;
 
4444
 
 
4445
    known_extensions_id= mysys_usage_id;
 
4446
 
 
4447
    plugin_foreach(NULL, exts_handlerton,
 
4448
                   DRIZZLE_STORAGE_ENGINE_PLUGIN, &found_exts);
 
4449
 
 
4450
    ext= (const char **) my_once_alloc(sizeof(char *)*
 
4451
                                       (found_exts.elements+1),
 
4452
                                       MYF(MY_WME | MY_FAE));
 
4453
 
 
4454
    assert(ext != 0);
 
4455
    known_extensions.count= found_exts.elements;
 
4456
    known_extensions.type_names= ext;
 
4457
 
 
4458
    List_iterator_fast<char> it(found_exts);
 
4459
    while ((old_ext= it++))
 
4460
      *ext++= old_ext;
 
4461
    *ext= 0;
 
4462
  }
 
4463
  return &known_extensions;
 
4464
}
 
4465
 
 
4466
 
 
4467
static bool stat_print(THD *thd, const char *type, uint type_len,
 
4468
                       const char *file, uint file_len,
 
4469
                       const char *status, uint status_len)
 
4470
{
 
4471
  Protocol *protocol= thd->protocol;
 
4472
  protocol->prepare_for_resend();
 
4473
  protocol->store(type, type_len, system_charset_info);
 
4474
  protocol->store(file, file_len, system_charset_info);
 
4475
  protocol->store(status, status_len, system_charset_info);
 
4476
  if (protocol->write())
 
4477
    return true;
 
4478
  return false;
 
4479
}
 
4480
 
 
4481
bool ha_show_status(THD *thd, handlerton *db_type, enum ha_stat_type stat)
 
4482
{
 
4483
  List<Item> field_list;
 
4484
  Protocol *protocol= thd->protocol;
 
4485
  bool result;
 
4486
 
 
4487
  field_list.push_back(new Item_empty_string("Type",10));
 
4488
  field_list.push_back(new Item_empty_string("Name",FN_REFLEN));
 
4489
  field_list.push_back(new Item_empty_string("Status",10));
 
4490
 
 
4491
  if (protocol->send_fields(&field_list,
 
4492
                            Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
 
4493
    return true;
 
4494
 
 
4495
  result= db_type->show_status &&
 
4496
    db_type->show_status(db_type, thd, stat_print, stat) ? 1 : 0;
 
4497
 
 
4498
  if (!result)
 
4499
    my_eof(thd);
 
4500
  return result;
 
4501
}
 
4502
 
 
4503
 
1284
4504
/**
1285
4505
  Check if the conditions for row-based binlogging is correct for the table.
1286
4506
 
1287
4507
  A row in the given table should be replicated if:
 
4508
  - Row-based replication is enabled in the current thread
 
4509
  - The binlog is enabled
1288
4510
  - It is not a temporary table
1289
 
*/
1290
 
 
1291
 
static bool log_row_for_replication(Table* table,
1292
 
                                    const unsigned char *before_record,
1293
 
                                    const unsigned char *after_record)
1294
 
{
1295
 
  TransactionServices &transaction_services= TransactionServices::singleton();
1296
 
  Session *const session= table->in_use;
1297
 
 
1298
 
  if (table->getShare()->getType() || not transaction_services.shouldConstructMessages())
1299
 
    return false;
1300
 
 
1301
 
  bool result= false;
1302
 
 
1303
 
  switch (session->lex->sql_command)
1304
 
  {
1305
 
  case SQLCOM_CREATE_TABLE:
1306
 
    /*
1307
 
     * We are in a CREATE TABLE ... SELECT statement
1308
 
     * and the kernel has already created the table
1309
 
     * and put a CreateTableStatement in the active
1310
 
     * Transaction message.  Here, we add a new InsertRecord
1311
 
     * to a new Transaction message (because the above
1312
 
     * CREATE TABLE will commit the transaction containing
1313
 
     * it).
1314
 
     */
1315
 
    result= transaction_services.insertRecord(*session, *table);
1316
 
    break;
1317
 
  case SQLCOM_REPLACE:
1318
 
  case SQLCOM_REPLACE_SELECT:
1319
 
    /*
1320
 
     * This is a total hack because of the code that is
1321
 
     * in write_record() in sql_insert.cc. During
1322
 
     * a REPLACE statement, a call to insertRecord() is
1323
 
     * called.  If it fails, then a call to deleteRecord()
1324
 
     * is called, followed by a repeat of the original
1325
 
     * call to insertRecord().  So, log_row_for_replication
1326
 
     * could be called multiple times for a REPLACE
1327
 
     * statement.  The below looks at the values of before_record
1328
 
     * and after_record to determine which call to this
1329
 
     * function is for the delete or the insert, since NULL
1330
 
     * is passed for after_record for the delete and NULL is
1331
 
     * passed for before_record for the insert...
1332
 
     *
1333
 
     * In addition, there is an optimization that allows an
1334
 
     * engine to convert the above delete + insert into an
1335
 
     * update, so we must also check for this case below...
1336
 
     */
1337
 
    if (after_record == NULL)
1338
 
    {
1339
 
      /*
1340
 
       * The storage engine is passed the record in table->record[1]
1341
 
       * as the row to delete (this is the conflicting row), so
1342
 
       * we need to notify TransactionService to use that row.
1343
 
       */
1344
 
      transaction_services.deleteRecord(*session, *table, true);
1345
 
      /* 
1346
 
       * We set the "current" statement message to NULL.  This triggers
1347
 
       * the replication services component to generate a new statement
1348
 
       * message for the inserted record which will come next.
1349
 
       */
1350
 
      transaction_services.finalizeStatementMessage(*session->getStatementMessage(), *session);
1351
 
    }
1352
 
    else
1353
 
    {
1354
 
      if (before_record == NULL)
1355
 
        result= transaction_services.insertRecord(*session, *table);
1356
 
      else
1357
 
        transaction_services.updateRecord(*session, *table, before_record, after_record);
1358
 
    }
1359
 
    break;
1360
 
  case SQLCOM_INSERT:
1361
 
  case SQLCOM_INSERT_SELECT:
1362
 
  case SQLCOM_LOAD:
1363
 
    /*
1364
 
     * The else block below represents an 
1365
 
     * INSERT ... ON DUPLICATE KEY UPDATE that
1366
 
     * has hit a key conflict and actually done
1367
 
     * an update.
1368
 
     */
1369
 
    if (before_record == NULL)
1370
 
      result= transaction_services.insertRecord(*session, *table);
1371
 
    else
1372
 
      transaction_services.updateRecord(*session, *table, before_record, after_record);
1373
 
    break;
1374
 
 
1375
 
  case SQLCOM_UPDATE:
1376
 
    transaction_services.updateRecord(*session, *table, before_record, after_record);
1377
 
    break;
1378
 
 
1379
 
  case SQLCOM_DELETE:
1380
 
    transaction_services.deleteRecord(*session, *table);
1381
 
    break;
1382
 
  default:
1383
 
    break;
1384
 
  }
1385
 
 
1386
 
  return result;
1387
 
}
1388
 
 
1389
 
int Cursor::ha_external_lock(Session *session, int lock_type)
 
4511
  - The binary log is open
 
4512
  - The database the table resides in shall be binlogged (binlog_*_db rules)
 
4513
  - table is not mysql.event
 
4514
*/
 
4515
 
 
4516
static bool check_table_binlog_row_based(THD *thd, Table *table)
 
4517
{
 
4518
  if (table->s->cached_row_logging_check == -1)
 
4519
  {
 
4520
    int const check(table->s->tmp_table == NO_TMP_TABLE &&
 
4521
                    binlog_filter->db_ok(table->s->db.str));
 
4522
    table->s->cached_row_logging_check= check;
 
4523
  }
 
4524
 
 
4525
  assert(table->s->cached_row_logging_check == 0 ||
 
4526
              table->s->cached_row_logging_check == 1);
 
4527
 
 
4528
  return (thd->current_stmt_binlog_row_based &&
 
4529
          table->s->cached_row_logging_check &&
 
4530
          (thd->options & OPTION_BIN_LOG) &&
 
4531
          mysql_bin_log.is_open());
 
4532
}
 
4533
 
 
4534
 
 
4535
/**
 
4536
   Write table maps for all (manually or automatically) locked tables
 
4537
   to the binary log.
 
4538
 
 
4539
   This function will generate and write table maps for all tables
 
4540
   that are locked by the thread 'thd'.  Either manually locked
 
4541
   (stored in THD::locked_tables) and automatically locked (stored
 
4542
   in THD::lock) are considered.
 
4543
 
 
4544
   @param thd     Pointer to THD structure
 
4545
 
 
4546
   @retval 0   All OK
 
4547
   @retval 1   Failed to write all table maps
 
4548
 
 
4549
   @sa
 
4550
       THD::lock
 
4551
       THD::locked_tables
 
4552
*/
 
4553
 
 
4554
static int write_locked_table_maps(THD *thd)
 
4555
{
 
4556
  if (thd->get_binlog_table_maps() == 0)
 
4557
  {
 
4558
    DRIZZLE_LOCK *locks[3];
 
4559
    locks[0]= thd->extra_lock;
 
4560
    locks[1]= thd->lock;
 
4561
    locks[2]= thd->locked_tables;
 
4562
    for (uint i= 0 ; i < sizeof(locks)/sizeof(*locks) ; ++i )
 
4563
    {
 
4564
      DRIZZLE_LOCK const *const lock= locks[i];
 
4565
      if (lock == NULL)
 
4566
        continue;
 
4567
 
 
4568
      Table **const end_ptr= lock->table + lock->table_count;
 
4569
      for (Table **table_ptr= lock->table ; 
 
4570
           table_ptr != end_ptr ;
 
4571
           ++table_ptr)
 
4572
      {
 
4573
        Table *const table= *table_ptr;
 
4574
        if (table->current_lock == F_WRLCK &&
 
4575
            check_table_binlog_row_based(thd, table))
 
4576
        {
 
4577
          int const has_trans= table->file->has_transactions();
 
4578
          int const error= thd->binlog_write_table_map(table, has_trans);
 
4579
          /*
 
4580
            If an error occurs, it is the responsibility of the caller to
 
4581
            roll back the transaction.
 
4582
          */
 
4583
          if (unlikely(error))
 
4584
            return(1);
 
4585
        }
 
4586
      }
 
4587
    }
 
4588
  }
 
4589
  return(0);
 
4590
}
 
4591
 
 
4592
 
 
4593
typedef bool Log_func(THD*, Table*, bool, const uchar*, const uchar*);
 
4594
 
 
4595
static int binlog_log_row(Table* table,
 
4596
                          const uchar *before_record,
 
4597
                          const uchar *after_record,
 
4598
                          Log_func *log_func)
 
4599
{
 
4600
  if (table->no_replicate)
 
4601
    return 0;
 
4602
  bool error= 0;
 
4603
  THD *const thd= table->in_use;
 
4604
 
 
4605
  if (check_table_binlog_row_based(thd, table))
 
4606
  {
 
4607
    /*
 
4608
      If there are no table maps written to the binary log, this is
 
4609
      the first row handled in this statement. In that case, we need
 
4610
      to write table maps for all locked tables to the binary log.
 
4611
    */
 
4612
    if (likely(!(error= write_locked_table_maps(thd))))
 
4613
    {
 
4614
      bool const has_trans= table->file->has_transactions();
 
4615
      error= (*log_func)(thd, table, has_trans, before_record, after_record);
 
4616
    }
 
4617
  }
 
4618
  return error ? HA_ERR_RBR_LOGGING_FAILED : 0;
 
4619
}
 
4620
 
 
4621
int handler::ha_external_lock(THD *thd, int lock_type)
1390
4622
{
1391
4623
  /*
1392
4624
    Whether this is lock or unlock, this should be true, and is to verify that
1395
4627
  */
1396
4628
  assert(next_insert_id == 0);
1397
4629
 
1398
 
  if (DRIZZLE_CURSOR_RDLOCK_START_ENABLED() ||
1399
 
      DRIZZLE_CURSOR_WRLOCK_START_ENABLED() ||
1400
 
      DRIZZLE_CURSOR_UNLOCK_START_ENABLED())
1401
 
  {
1402
 
    if (lock_type == F_RDLCK)
1403
 
    {
1404
 
      DRIZZLE_CURSOR_RDLOCK_START(getTable()->getShare()->getSchemaName(),
1405
 
                                  getTable()->getShare()->getTableName());
1406
 
    }
1407
 
    else if (lock_type == F_WRLCK)
1408
 
    {
1409
 
      DRIZZLE_CURSOR_WRLOCK_START(getTable()->getShare()->getSchemaName(),
1410
 
                                  getTable()->getShare()->getTableName());
1411
 
    }
1412
 
    else if (lock_type == F_UNLCK)
1413
 
    {
1414
 
      DRIZZLE_CURSOR_UNLOCK_START(getTable()->getShare()->getSchemaName(),
1415
 
                                  getTable()->getShare()->getTableName());
1416
 
    }
1417
 
  }
1418
 
 
1419
4630
  /*
1420
4631
    We cache the table flags if the locking succeeded. Otherwise, we
1421
4632
    keep them as they were when they were fetched in ha_open().
1422
4633
  */
1423
 
 
1424
 
  int error= external_lock(session, lock_type);
1425
 
 
1426
 
  if (DRIZZLE_CURSOR_RDLOCK_DONE_ENABLED() ||
1427
 
      DRIZZLE_CURSOR_WRLOCK_DONE_ENABLED() ||
1428
 
      DRIZZLE_CURSOR_UNLOCK_DONE_ENABLED())
1429
 
  {
1430
 
    if (lock_type == F_RDLCK)
1431
 
    {
1432
 
      DRIZZLE_CURSOR_RDLOCK_DONE(error);
1433
 
    }
1434
 
    else if (lock_type == F_WRLCK)
1435
 
    {
1436
 
      DRIZZLE_CURSOR_WRLOCK_DONE(error);
1437
 
    }
1438
 
    else if (lock_type == F_UNLCK)
1439
 
    {
1440
 
      DRIZZLE_CURSOR_UNLOCK_DONE(error);
1441
 
    }
1442
 
  }
1443
 
 
1444
 
  return error;
 
4634
  DRIZZLE_EXTERNAL_LOCK(lock_type);
 
4635
 
 
4636
  int error= external_lock(thd, lock_type);
 
4637
  if (error == 0)
 
4638
    cached_table_flags= table_flags();
 
4639
  return(error);
1445
4640
}
1446
4641
 
1447
4642
 
1448
4643
/**
1449
 
  Check Cursor usage and reset state of file to after 'open'
 
4644
  Check handler usage and reset state of file to after 'open'
1450
4645
*/
1451
 
int Cursor::ha_reset()
 
4646
int handler::ha_reset()
1452
4647
{
1453
4648
  /* Check that we have called all proper deallocation functions */
1454
 
  assert(! getTable()->getShare()->all_set.none());
1455
 
  assert(getTable()->key_read == 0);
1456
 
  /* ensure that ha_index_end / endTableScan has been called */
 
4649
  assert((uchar*) table->def_read_set.bitmap +
 
4650
              table->s->column_bitmap_size ==
 
4651
              (uchar*) table->def_write_set.bitmap);
 
4652
  assert(bitmap_is_set_all(&table->s->all_set));
 
4653
  assert(table->key_read == 0);
 
4654
  /* ensure that ha_index_end / ha_rnd_end has been called */
1457
4655
  assert(inited == NONE);
1458
4656
  /* Free cache used by filesort */
1459
 
  getTable()->free_io_cache();
 
4657
  free_io_cache(table);
1460
4658
  /* reset the bitmaps to point to defaults */
1461
 
  getTable()->default_column_bitmaps();
 
4659
  table->default_column_bitmaps();
1462
4660
  return(reset());
1463
4661
}
1464
4662
 
1465
4663
 
1466
 
int Cursor::insertRecord(unsigned char *buf)
1467
 
{
1468
 
  int error;
1469
 
 
1470
 
  /*
1471
 
   * If we have a timestamp column, update it to the current time
1472
 
   *
1473
 
   * @TODO Technically, the below two lines can be take even further out of the
1474
 
   * Cursor interface and into the fill_record() method.
1475
 
   */
1476
 
  if (getTable()->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
1477
 
  {
1478
 
    getTable()->timestamp_field->set_time();
1479
 
  }
1480
 
 
1481
 
  DRIZZLE_INSERT_ROW_START(getTable()->getShare()->getSchemaName(), getTable()->getShare()->getTableName());
1482
 
  setTransactionReadWrite();
1483
 
  
1484
 
  if (unlikely(plugin::EventObserver::beforeInsertRecord(*getTable(), buf)))
1485
 
  {
1486
 
    error= ER_EVENT_OBSERVER_PLUGIN;
1487
 
  }
1488
 
  else
1489
 
  {
1490
 
    error= doInsertRecord(buf);
1491
 
    if (unlikely(plugin::EventObserver::afterInsertRecord(*getTable(), buf, error))) 
1492
 
    {
1493
 
      error= ER_EVENT_OBSERVER_PLUGIN;
1494
 
    }
1495
 
  }
1496
 
 
1497
 
  ha_statistic_increment(&system_status_var::ha_write_count);
1498
 
 
1499
 
  DRIZZLE_INSERT_ROW_DONE(error);
1500
 
 
1501
 
  if (unlikely(error))
1502
 
  {
1503
 
    return error;
1504
 
  }
1505
 
 
1506
 
  if (unlikely(log_row_for_replication(getTable(), NULL, buf)))
1507
 
    return HA_ERR_RBR_LOGGING_FAILED;
1508
 
 
1509
 
  return 0;
1510
 
}
1511
 
 
1512
 
 
1513
 
int Cursor::updateRecord(const unsigned char *old_data, unsigned char *new_data)
1514
 
{
1515
 
  int error;
1516
 
 
1517
 
  /*
1518
 
    Some storage engines require that the new record is in getInsertRecord()
1519
 
    (and the old record is in getUpdateRecord()).
1520
 
   */
1521
 
  assert(new_data == getTable()->getInsertRecord());
1522
 
 
1523
 
  DRIZZLE_UPDATE_ROW_START(getTable()->getShare()->getSchemaName(), getTable()->getShare()->getTableName());
1524
 
  setTransactionReadWrite();
1525
 
  if (unlikely(plugin::EventObserver::beforeUpdateRecord(*getTable(), old_data, new_data)))
1526
 
  {
1527
 
    error= ER_EVENT_OBSERVER_PLUGIN;
1528
 
  }
1529
 
  else
1530
 
  {
1531
 
    if (getTable()->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
1532
 
    {
1533
 
      getTable()->timestamp_field->set_time();
1534
 
    }
1535
 
 
1536
 
    error= doUpdateRecord(old_data, new_data);
1537
 
    if (unlikely(plugin::EventObserver::afterUpdateRecord(*getTable(), old_data, new_data, error)))
1538
 
    {
1539
 
      error= ER_EVENT_OBSERVER_PLUGIN;
1540
 
    }
1541
 
  }
1542
 
 
1543
 
  ha_statistic_increment(&system_status_var::ha_update_count);
1544
 
 
1545
 
  DRIZZLE_UPDATE_ROW_DONE(error);
1546
 
 
1547
 
  if (unlikely(error))
1548
 
  {
1549
 
    return error;
1550
 
  }
1551
 
 
1552
 
  if (unlikely(log_row_for_replication(getTable(), old_data, new_data)))
1553
 
    return HA_ERR_RBR_LOGGING_FAILED;
1554
 
 
1555
 
  return 0;
1556
 
}
1557
 
TableShare *Cursor::getShare()
1558
 
{
1559
 
  return getTable()->getMutableShare();
1560
 
}
1561
 
 
1562
 
int Cursor::deleteRecord(const unsigned char *buf)
1563
 
{
1564
 
  int error;
1565
 
 
1566
 
  DRIZZLE_DELETE_ROW_START(getTable()->getShare()->getSchemaName(), getTable()->getShare()->getTableName());
1567
 
  setTransactionReadWrite();
1568
 
  if (unlikely(plugin::EventObserver::beforeDeleteRecord(*getTable(), buf)))
1569
 
  {
1570
 
    error= ER_EVENT_OBSERVER_PLUGIN;
1571
 
  }
1572
 
  else
1573
 
  {
1574
 
    error= doDeleteRecord(buf);
1575
 
    if (unlikely(plugin::EventObserver::afterDeleteRecord(*getTable(), buf, error)))
1576
 
    {
1577
 
      error= ER_EVENT_OBSERVER_PLUGIN;
1578
 
    }
1579
 
  }
1580
 
 
1581
 
  ha_statistic_increment(&system_status_var::ha_delete_count);
1582
 
 
1583
 
  DRIZZLE_DELETE_ROW_DONE(error);
1584
 
 
1585
 
  if (unlikely(error))
1586
 
    return error;
1587
 
 
1588
 
  if (unlikely(log_row_for_replication(getTable(), buf, NULL)))
1589
 
    return HA_ERR_RBR_LOGGING_FAILED;
1590
 
 
1591
 
  return 0;
1592
 
}
1593
 
 
1594
 
} /* namespace drizzled */
 
4664
int handler::ha_write_row(uchar *buf)
 
4665
{
 
4666
  int error;
 
4667
  Log_func *log_func= Write_rows_log_event::binlog_row_logging_function;
 
4668
  DRIZZLE_INSERT_ROW_START();
 
4669
 
 
4670
  mark_trx_read_write();
 
4671
 
 
4672
  if (unlikely(error= write_row(buf)))
 
4673
    return(error);
 
4674
  if (unlikely(error= binlog_log_row(table, 0, buf, log_func)))
 
4675
    return(error); /* purecov: inspected */
 
4676
  DRIZZLE_INSERT_ROW_END();
 
4677
  return(0);
 
4678
}
 
4679
 
 
4680
 
 
4681
int handler::ha_update_row(const uchar *old_data, uchar *new_data)
 
4682
{
 
4683
  int error;
 
4684
  Log_func *log_func= Update_rows_log_event::binlog_row_logging_function;
 
4685
 
 
4686
  /*
 
4687
    Some storage engines require that the new record is in record[0]
 
4688
    (and the old record is in record[1]).
 
4689
   */
 
4690
  assert(new_data == table->record[0]);
 
4691
 
 
4692
  mark_trx_read_write();
 
4693
 
 
4694
  if (unlikely(error= update_row(old_data, new_data)))
 
4695
    return error;
 
4696
  if (unlikely(error= binlog_log_row(table, old_data, new_data, log_func)))
 
4697
    return error;
 
4698
  return 0;
 
4699
}
 
4700
 
 
4701
int handler::ha_delete_row(const uchar *buf)
 
4702
{
 
4703
  int error;
 
4704
  Log_func *log_func= Delete_rows_log_event::binlog_row_logging_function;
 
4705
 
 
4706
  mark_trx_read_write();
 
4707
 
 
4708
  if (unlikely(error= delete_row(buf)))
 
4709
    return error;
 
4710
  if (unlikely(error= binlog_log_row(table, buf, 0, log_func)))
 
4711
    return error;
 
4712
  return 0;
 
4713
}
 
4714
 
 
4715
 
 
4716
 
 
4717
/**
 
4718
  @details
 
4719
  use_hidden_primary_key() is called in case of an update/delete when
 
4720
  (table_flags() and HA_PRIMARY_KEY_REQUIRED_FOR_DELETE) is defined
 
4721
  but we don't have a primary key
 
4722
*/
 
4723
void handler::use_hidden_primary_key()
 
4724
{
 
4725
  /* fallback to use all columns in the table to identify row */
 
4726
  table->use_all_columns();
 
4727
}