~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/handler.cc

  • Committer: Brian Aker
  • Date: 2008-10-12 01:59:02 UTC
  • Revision ID: brian@tangent.org-20081012015902-prhy6wsimdqr28om
Dead code around unsigned (first pass)

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