~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/handler.cc

enable remaining subselect tests, merge with latest from the trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2000-2006 MySQL AB
2
 
 
3
 
   This program is free software; you can redistribute it and/or modify
4
 
   it under the terms of the GNU General Public License as published by
5
 
   the Free Software Foundation; version 2 of the License.
6
 
 
7
 
   This program is distributed in the hope that it will be useful,
8
 
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
 
   GNU General Public License for more details.
11
 
 
12
 
   You should have received a copy of the GNU General Public License
13
 
   along with this program; if not, write to the Free Software
14
 
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
 
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
 
3
 *
 
4
 *  Copyright (C) 2008 Sun Microsystems
 
5
 *
 
6
 *  This program is free software; you can redistribute it and/or modify
 
7
 *  it under the terms of the GNU General Public License as published by
 
8
 *  the Free Software Foundation; version 2 of the License.
 
9
 *
 
10
 *  This program is distributed in the hope that it will be useful,
 
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 *  GNU General Public License for more details.
 
14
 *
 
15
 *  You should have received a copy of the GNU General Public License
 
16
 *  along with this program; if not, write to the Free Software
 
17
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
18
 */
15
19
 
16
20
/**
17
21
  @file handler.cc
19
23
  Handler-calling-functions
20
24
*/
21
25
 
22
 
#ifdef USE_PRAGMA_IMPLEMENTATION
23
 
#pragma implementation                          // gcc: Class implementation
24
 
#endif
25
 
 
26
26
#include <drizzled/server_includes.h>
27
 
#include "rpl_filter.h"
28
 
#include <drizzled/drizzled_error_messages.h>
29
 
 
30
 
/*
31
 
  While we have legacy_db_type, we have this array to
32
 
  check for dups and to find handlerton from legacy_db_type.
33
 
  Remove when legacy_db_type is finally gone
34
 
*/
35
 
st_plugin_int *hton2plugin[MAX_HA];
36
 
 
37
 
static handlerton *installed_htons[128];
38
 
 
39
 
#define BITMAP_STACKBUF_SIZE (128/8)
40
 
 
41
 
KEY_CREATE_INFO default_key_create_info= { HA_KEY_ALG_UNDEF, 0, {NullS,0}, {NullS,0} };
 
27
#include <libdrizzle/libdrizzle.h>
 
28
#include <mysys/hash.h>
 
29
#include <drizzled/error.h>
 
30
#include <drizzled/gettext.h>
 
31
#include <drizzled/data_home.h>
 
32
#include <drizzled/probes.h>
 
33
#include <drizzled/sql_parse.h>
 
34
#include <drizzled/cost_vect.h>
 
35
#include CMATH_H
 
36
#include <drizzled/session.h>
 
37
#include <drizzled/sql_base.h>
 
38
#include <drizzled/replicator.h>
 
39
#include <drizzled/lock.h>
 
40
#include <drizzled/item/int.h>
 
41
#include <drizzled/item/empty_string.h>
 
42
#include <drizzled/unireg.h> // for mysql_frm_type
 
43
 
 
44
#if defined(CMATH_NAMESPACE)
 
45
using namespace CMATH_NAMESPACE;
 
46
#endif
 
47
 
 
48
 
 
49
extern HASH open_cache;
 
50
 
 
51
KEY_CREATE_INFO default_key_create_info= { HA_KEY_ALG_UNDEF, 0, {NULL,0}, {NULL,0} };
42
52
 
43
53
/* number of entries in handlertons[] */
44
54
uint32_t total_ha= 0;
47
57
/* size of savepoint storage area (see ha_init) */
48
58
uint32_t savepoint_alloc_size= 0;
49
59
 
50
 
static const LEX_STRING sys_table_aliases[]=
51
 
{
52
 
  { C_STRING_WITH_LEN("INNOBASE") },  { C_STRING_WITH_LEN("INNODB") },
53
 
  { C_STRING_WITH_LEN("HEAP") },      { C_STRING_WITH_LEN("MEMORY") },
54
 
  {NullS, 0}
55
 
};
56
 
 
57
60
const char *ha_row_type[] = {
58
61
  "", "FIXED", "DYNAMIC", "COMPRESSED", "REDUNDANT", "COMPACT", "PAGE", "?","?","?"
59
62
};
60
63
 
61
64
const char *tx_isolation_names[] =
62
65
{ "READ-UNCOMMITTED", "READ-COMMITTED", "REPEATABLE-READ", "SERIALIZABLE",
63
 
  NullS};
 
66
  NULL};
 
67
 
64
68
TYPELIB tx_isolation_typelib= {array_elements(tx_isolation_names)-1,"",
65
 
                               tx_isolation_names, NULL};
 
69
                               tx_isolation_names, NULL};
66
70
 
67
71
static TYPELIB known_extensions= {0,"known_exts", NULL, NULL};
68
 
uint known_extensions_id= 0;
69
 
 
70
 
 
71
 
 
72
 
static plugin_ref ha_default_plugin(THD *thd)
73
 
{
74
 
  if (thd->variables.table_plugin)
75
 
    return thd->variables.table_plugin;
76
 
  return my_plugin_lock(thd, &global_system_variables.table_plugin);
77
 
}
78
 
 
79
 
 
80
 
/**
81
 
  Return the default storage engine handlerton for thread
82
 
 
83
 
  @param ha_default_handlerton(thd)
84
 
  @param thd         current thread
85
 
 
86
 
  @return
87
 
    pointer to handlerton
88
 
*/
89
 
handlerton *ha_default_handlerton(THD *thd)
90
 
{
91
 
  plugin_ref plugin= ha_default_plugin(thd);
92
 
  assert(plugin);
93
 
  handlerton *hton= plugin_data(plugin, handlerton*);
94
 
  assert(hton);
95
 
  return hton;
96
 
}
97
 
 
98
 
 
99
 
/**
100
 
  Return the storage engine handlerton for the supplied name
101
 
  
102
 
  @param thd         current thread
103
 
  @param name        name of storage engine
104
 
  
105
 
  @return
106
 
    pointer to storage engine plugin handle
107
 
*/
108
 
plugin_ref ha_resolve_by_name(THD *thd, const LEX_STRING *name)
109
 
{
110
 
  const LEX_STRING *table_alias;
111
 
  plugin_ref plugin;
112
 
 
113
 
redo:
114
 
  /* my_strnncoll is a macro and gcc doesn't do early expansion of macro */
115
 
  if (thd && !my_charset_latin1.coll->strnncoll(&my_charset_latin1,
116
 
                           (const uchar *)name->str, name->length,
117
 
                           (const uchar *)STRING_WITH_LEN("DEFAULT"), 0))
118
 
    return ha_default_plugin(thd);
119
 
 
120
 
  if ((plugin= my_plugin_lock_by_name(thd, name, DRIZZLE_STORAGE_ENGINE_PLUGIN)))
121
 
  {
122
 
    handlerton *hton= plugin_data(plugin, handlerton *);
123
 
    if (!(hton->flags & HTON_NOT_USER_SELECTABLE))
124
 
      return plugin;
125
 
      
126
 
    /*
127
 
      unlocking plugin immediately after locking is relatively low cost.
128
 
    */
129
 
    plugin_unlock(thd, plugin);
130
 
  }
131
 
 
132
 
  /*
133
 
    We check for the historical aliases.
134
 
  */
135
 
  for (table_alias= sys_table_aliases; table_alias->str; table_alias+= 2)
136
 
  {
137
 
    if (!my_strnncoll(&my_charset_latin1,
138
 
                      (const uchar *)name->str, name->length,
139
 
                      (const uchar *)table_alias->str, table_alias->length))
140
 
    {
141
 
      name= table_alias + 1;
142
 
      goto redo;
143
 
    }
144
 
  }
145
 
 
146
 
  return NULL;
147
 
}
148
 
 
149
 
 
150
 
plugin_ref ha_lock_engine(THD *thd, handlerton *hton)
151
 
{
152
 
  if (hton)
153
 
  {
154
 
    st_plugin_int **plugin= hton2plugin + hton->slot;
155
 
    
156
 
    return my_plugin_lock(thd, &plugin);
157
 
  }
158
 
  return NULL;
159
 
}
160
 
 
161
 
 
162
 
handlerton *ha_resolve_by_legacy_type(THD *thd, enum legacy_db_type db_type)
163
 
{
164
 
  plugin_ref plugin;
165
 
  switch (db_type) {
166
 
  case DB_TYPE_DEFAULT:
167
 
    return ha_default_handlerton(thd);
168
 
  default:
169
 
    if (db_type > DB_TYPE_UNKNOWN && db_type < DB_TYPE_DEFAULT &&
170
 
        (plugin= ha_lock_engine(thd, installed_htons[db_type])))
171
 
      return plugin_data(plugin, handlerton*);
172
 
    /* fall through */
173
 
  case DB_TYPE_UNKNOWN:
174
 
    return NULL;
175
 
  }
176
 
}
177
 
 
178
 
 
179
 
/**
180
 
  Use other database handler if databasehandler is not compiled in.
181
 
*/
182
 
handlerton *ha_checktype(THD *thd, enum legacy_db_type database_type,
183
 
                          bool no_substitute, bool report_error)
184
 
{
185
 
  handlerton *hton= ha_resolve_by_legacy_type(thd, database_type);
186
 
  if (ha_storage_engine_is_enabled(hton))
187
 
    return hton;
188
 
 
189
 
  if (no_substitute)
190
 
  {
191
 
    if (report_error)
192
 
    {
193
 
      const char *engine_name= ha_resolve_storage_engine_name(hton);
194
 
      my_error(ER_FEATURE_DISABLED,MYF(0),engine_name,engine_name);
195
 
    }
196
 
    return NULL;
197
 
  }
198
 
 
199
 
  switch (database_type) {
200
 
  case DB_TYPE_HASH:
201
 
    return ha_resolve_by_legacy_type(thd, DB_TYPE_HASH);
202
 
  default:
203
 
    break;
204
 
  }
205
 
 
206
 
  return ha_default_handlerton(thd);
207
 
} /* ha_checktype */
208
 
 
209
 
 
210
 
handler *get_new_handler(TABLE_SHARE *share, MEM_ROOT *alloc,
211
 
                         handlerton *db_type)
212
 
{
213
 
  handler *file;
214
 
 
215
 
  if (db_type && db_type->state == SHOW_OPTION_YES && db_type->create)
216
 
  {
217
 
    if ((file= db_type->create(db_type, share, alloc)))
218
 
      file->init();
219
 
    return(file);
220
 
  }
221
 
  /*
222
 
    Try the default table type
223
 
    Here the call to current_thd() is ok as we call this function a lot of
224
 
    times but we enter this branch very seldom.
225
 
  */
226
 
  return(get_new_handler(share, alloc, ha_default_handlerton(current_thd)));
227
 
}
 
72
uint32_t known_extensions_id= 0;
228
73
 
229
74
 
230
75
/**
243
88
 
244
89
  /* Allocate a pointer array for the error message strings. */
245
90
  /* Zerofill it to avoid uninitialized gaps. */
246
 
  if (! (errmsgs= (const char**) my_malloc(HA_ERR_ERRORS * sizeof(char*),
247
 
                                           MYF(MY_WME | MY_ZEROFILL))))
 
91
  if (! (errmsgs= (const char**) malloc(HA_ERR_ERRORS * sizeof(char*))))
248
92
    return 1;
 
93
  memset(errmsgs, 0, HA_ERR_ERRORS * sizeof(char *));
249
94
 
250
95
  /* Set the dedicated error messages. */
251
96
  SETMSG(HA_ERR_KEY_NOT_FOUND,          ER(ER_KEY_NOT_FOUND));
310
155
  /* Allocate a pointer array for the error message strings. */
311
156
  if (! (errmsgs= my_error_unregister(HA_ERR_FIRST, HA_ERR_LAST)))
312
157
    return 1;
313
 
  my_free((uchar*) errmsgs, MYF(0));
 
158
  free((unsigned char*) errmsgs);
314
159
  return 0;
315
160
}
316
161
 
317
 
 
318
 
int ha_finalize_handlerton(st_plugin_int *plugin)
319
 
{
320
 
  handlerton *hton= (handlerton *)plugin->data;
321
 
 
322
 
  switch (hton->state)
323
 
  {
324
 
  case SHOW_OPTION_NO:
325
 
  case SHOW_OPTION_DISABLED:
326
 
    break;
327
 
  case SHOW_OPTION_YES:
328
 
    if (installed_htons[hton->db_type] == hton)
329
 
      installed_htons[hton->db_type]= NULL;
330
 
    break;
331
 
  };
332
 
 
333
 
  if (hton && plugin->plugin->deinit)
334
 
    (void)plugin->plugin->deinit(hton);
335
 
 
336
 
  my_free((uchar*)hton, MYF(0));
337
 
 
338
 
  return(0);
339
 
}
340
 
 
341
 
 
342
 
int ha_initialize_handlerton(st_plugin_int *plugin)
343
 
{
344
 
  handlerton *hton;
345
 
 
346
 
  hton= (handlerton *)my_malloc(sizeof(handlerton),
347
 
                                MYF(MY_WME | MY_ZEROFILL));
348
 
  /* 
349
 
    FIXME: the MY_ZEROFILL flag above doesn't zero all the bytes.
350
 
    
351
 
    This was detected after adding get_backup_engine member to handlerton
352
 
    structure. Apparently get_backup_engine was not NULL even though it was
353
 
    not initialized.
354
 
   */
355
 
  memset(hton, 0, sizeof(hton));
356
 
  /* Historical Requirement */
357
 
  plugin->data= hton; // shortcut for the future
358
 
  if (plugin->plugin->init)
359
 
  {
360
 
    if (plugin->plugin->init(hton))
361
 
    {
362
 
      sql_print_error("Plugin '%s' init function returned error.",
363
 
                      plugin->name.str);
364
 
      goto err;
365
 
    }
366
 
  }
367
 
 
368
 
  /*
369
 
    the switch below and hton->state should be removed when
370
 
    command-line options for plugins will be implemented
371
 
  */
372
 
  switch (hton->state) {
373
 
  case SHOW_OPTION_NO:
374
 
    break;
375
 
  case SHOW_OPTION_YES:
376
 
    {
377
 
      uint tmp;
378
 
      /* now check the db_type for conflict */
379
 
      if (hton->db_type <= DB_TYPE_UNKNOWN ||
380
 
          hton->db_type >= DB_TYPE_DEFAULT ||
381
 
          installed_htons[hton->db_type])
382
 
      {
383
 
        int idx= (int) DB_TYPE_FIRST_DYNAMIC;
384
 
 
385
 
        while (idx < (int) DB_TYPE_DEFAULT && installed_htons[idx])
386
 
          idx++;
387
 
 
388
 
        if (idx == (int) DB_TYPE_DEFAULT)
389
 
        {
390
 
          sql_print_warning("Too many storage engines!");
391
 
          return(1);
392
 
        }
393
 
        if (hton->db_type != DB_TYPE_UNKNOWN)
394
 
          sql_print_warning("Storage engine '%s' has conflicting typecode. "
395
 
                            "Assigning value %d.", plugin->plugin->name, idx);
396
 
        hton->db_type= (enum legacy_db_type) idx;
397
 
      }
398
 
      installed_htons[hton->db_type]= hton;
399
 
      tmp= hton->savepoint_offset;
400
 
      hton->savepoint_offset= savepoint_alloc_size;
401
 
      savepoint_alloc_size+= tmp;
402
 
      hton->slot= total_ha++;
403
 
      hton2plugin[hton->slot]=plugin;
404
 
      if (hton->prepare)
405
 
        total_ha_2pc++;
406
 
      break;
407
 
    }
408
 
    /* fall through */
409
 
  default:
410
 
    hton->state= SHOW_OPTION_DISABLED;
411
 
    break;
412
 
  }
413
 
  
414
 
  /* 
415
 
    This is entirely for legacy. We will create a new "disk based" hton and a 
416
 
    "memory" hton which will be configurable longterm. We should be able to 
417
 
    remove partition and myisammrg.
418
 
  */
419
 
  switch (hton->db_type) {
420
 
  case DB_TYPE_HEAP:
421
 
    heap_hton= hton;
422
 
    break;
423
 
  case DB_TYPE_MYISAM:
424
 
    myisam_hton= hton;
425
 
    break;
426
 
  default:
427
 
    break;
428
 
  };
429
 
 
430
 
  return(0);
431
 
err:
432
 
  return(1);
433
 
}
434
 
 
435
162
int ha_init()
436
163
{
437
164
  int error= 0;
451
178
{
452
179
  int error= 0;
453
180
 
454
 
  /* 
 
181
  /*
455
182
    This should be eventualy based  on the graceful shutdown flag.
456
183
    So if flag is equal to HA_PANIC_CLOSE, the deallocate
457
184
    the errors.
462
189
  return(error);
463
190
}
464
191
 
465
 
static bool dropdb_handlerton(THD *unused1 __attribute__((unused)),
 
192
static bool dropdb_handlerton(Session *unused1 __attribute__((unused)),
466
193
                              plugin_ref plugin,
467
194
                              void *path)
468
195
{
479
206
}
480
207
 
481
208
 
482
 
static bool closecon_handlerton(THD *thd, plugin_ref plugin,
 
209
static bool closecon_handlerton(Session *session, plugin_ref plugin,
483
210
                                void *unused __attribute__((unused)))
484
211
{
485
212
  handlerton *hton= plugin_data(plugin, handlerton *);
488
215
    be rolled back already
489
216
  */
490
217
  if (hton->state == SHOW_OPTION_YES && hton->close_connection &&
491
 
      thd_get_ha_data(thd, hton))
492
 
    hton->close_connection(hton, thd);
 
218
      session_get_ha_data(session, hton))
 
219
    hton->close_connection(hton, session);
493
220
  return false;
494
221
}
495
222
 
498
225
  @note
499
226
    don't bother to rollback here, it's done already
500
227
*/
501
 
void ha_close_connection(THD* thd)
 
228
void ha_close_connection(Session* session)
502
229
{
503
 
  plugin_foreach(thd, closecon_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN, 0);
 
230
  plugin_foreach(session, closecon_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN, 0);
504
231
}
505
232
 
506
233
/* ========================================================================
605
332
  -----------
606
333
 
607
334
  The server stores its transaction-related data in
608
 
  thd->transaction. This structure has two members of type
609
 
  THD_TRANS. These members correspond to the statement and
 
335
  session->transaction. This structure has two members of type
 
336
  Session_TRANS. These members correspond to the statement and
610
337
  normal transactions respectively:
611
338
 
612
 
  - thd->transaction.stmt contains a list of engines
 
339
  - session->transaction.stmt contains a list of engines
613
340
  that are participating in the given statement
614
 
  - thd->transaction.all contains a list of engines that
 
341
  - session->transaction.all contains a list of engines that
615
342
  have participated in any of the statement transactions started
616
343
  within the context of the normal transaction.
617
344
  Each element of the list contains a pointer to the storage
618
345
  engine, engine-specific transactional data, and engine-specific
619
346
  transaction flags.
620
347
 
621
 
  In autocommit mode thd->transaction.all is empty.
622
 
  Instead, data of thd->transaction.stmt is
 
348
  In autocommit mode session->transaction.all is empty.
 
349
  Instead, data of session->transaction.stmt is
623
350
  used to commit/rollback the normal transaction.
624
351
 
625
352
  The list of registered engines has a few important properties:
630
357
  Transaction life cycle
631
358
  ----------------------
632
359
 
633
 
  When a new connection is established, thd->transaction
 
360
  When a new connection is established, session->transaction
634
361
  members are initialized to an empty state.
635
362
  If a statement uses any tables, all affected engines
636
363
  are registered in the statement engine list. In
646
373
  and emptied again at the next statement's end.
647
374
 
648
375
  The normal transaction is committed in a similar way
649
 
  (by going over all engines in thd->transaction.all list)
 
376
  (by going over all engines in session->transaction.all list)
650
377
  but at different times:
651
378
  - upon COMMIT SQL statement is issued by the user
652
379
  - implicitly, by the server, at the beginning of a DDL statement
656
383
  - if the user has requested so, by issuing ROLLBACK SQL
657
384
  statement
658
385
  - if one of the storage engines requested a rollback
659
 
  by setting thd->transaction_rollback_request. This may
 
386
  by setting session->transaction_rollback_request. This may
660
387
  happen in case, e.g., when the transaction in the engine was
661
388
  chosen a victim of the internal deadlock resolution algorithm
662
389
  and rolled back internally. When such a situation happens, there
698
425
  transactions of other participants.
699
426
 
700
427
  After the normal transaction has been committed,
701
 
  thd->transaction.all list is cleared.
 
428
  session->transaction.all list is cleared.
702
429
 
703
430
  When a connection is closed, the current normal transaction, if
704
431
  any, is rolled back.
762
489
  ---------------------------------------------------
763
490
 
764
491
  DDLs and operations with non-transactional engines
765
 
  do not "register" in thd->transaction lists, and thus do not
 
492
  do not "register" in session->transaction lists, and thus do not
766
493
  modify the transaction state. Besides, each DDL in
767
494
  MySQL is prefixed with an implicit normal transaction commit
768
495
  (a call to end_active_trans()), and thus leaves nothing
776
503
  to maintain atomicity: if CREATE TABLE .. SELECT failed,
777
504
  the newly created table is deleted.
778
505
  In addition, some DDL statements issue interim transaction
779
 
  commits: e.g. ALTER TABLE issues a commit after data is copied
 
506
  commits: e.g. ALTER Table issues a commit after data is copied
780
507
  from the original table to the internal temporary table. Other
781
508
  statements, e.g. CREATE TABLE ... SELECT do not always commit
782
509
  after itself.
783
510
  And finally there is a group of DDL statements such as
784
 
  RENAME/DROP TABLE that doesn't start a new transaction
 
511
  RENAME/DROP Table that doesn't start a new transaction
785
512
  and doesn't commit.
786
513
 
787
514
  This diversity makes it hard to say what will happen if
809
536
    times per transaction.
810
537
 
811
538
*/
812
 
void trans_register_ha(THD *thd, bool all, handlerton *ht_arg)
 
539
void trans_register_ha(Session *session, bool all, handlerton *ht_arg)
813
540
{
814
 
  THD_TRANS *trans;
 
541
  Session_TRANS *trans;
815
542
  Ha_trx_info *ha_info;
816
543
 
817
544
  if (all)
818
545
  {
819
 
    trans= &thd->transaction.all;
820
 
    thd->server_status|= SERVER_STATUS_IN_TRANS;
 
546
    trans= &session->transaction.all;
 
547
    session->server_status|= SERVER_STATUS_IN_TRANS;
821
548
  }
822
549
  else
823
 
    trans= &thd->transaction.stmt;
 
550
    trans= &session->transaction.stmt;
824
551
 
825
 
  ha_info= thd->ha_data[ht_arg->slot].ha_info + static_cast<unsigned>(all);
 
552
  ha_info= session->ha_data[ht_arg->slot].ha_info + static_cast<unsigned>(all);
826
553
 
827
554
  if (ha_info->is_started())
828
555
    return; /* already registered, return */
830
557
  ha_info->register_ha(trans, ht_arg);
831
558
 
832
559
  trans->no_2pc|=(ht_arg->prepare==0);
833
 
  if (thd->transaction.xid_state.xid.is_null())
834
 
    thd->transaction.xid_state.xid.set(thd->query_id);
 
560
  if (session->transaction.xid_state.xid.is_null())
 
561
    session->transaction.xid_state.xid.set(session->query_id);
835
562
 
836
563
  return;
837
564
}
842
569
  @retval
843
570
    1   error, transaction was rolled back
844
571
*/
845
 
int ha_prepare(THD *thd)
 
572
int ha_prepare(Session *session)
846
573
{
847
574
  int error=0, all=1;
848
 
  THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt;
 
575
  Session_TRANS *trans=all ? &session->transaction.all : &session->transaction.stmt;
849
576
  Ha_trx_info *ha_info= trans->ha_list;
850
577
  if (ha_info)
851
578
  {
853
580
    {
854
581
      int err;
855
582
      handlerton *ht= ha_info->ht();
856
 
      status_var_increment(thd->status_var.ha_prepare_count);
 
583
      status_var_increment(session->status_var.ha_prepare_count);
857
584
      if (ht->prepare)
858
585
      {
859
 
        if ((err= ht->prepare(ht, thd, all)))
 
586
        if ((err= ht->prepare(ht, session, all)))
860
587
        {
861
588
          my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
862
 
          ha_rollback_trans(thd, all);
 
589
          ha_rollback_trans(session, all);
863
590
          error=1;
864
591
          break;
865
592
        }
866
593
      }
867
594
      else
868
595
      {
869
 
        push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
596
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
870
597
                            ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
871
598
                            ha_resolve_storage_engine_name(ht));
872
599
      }
891
618
 
892
619
static
893
620
bool
894
 
ha_check_and_coalesce_trx_read_only(THD *thd, Ha_trx_info *ha_list,
 
621
ha_check_and_coalesce_trx_read_only(Session *session, Ha_trx_info *ha_list,
895
622
                                    bool all)
896
623
{
897
624
  /* The number of storage engines that have actual changes. */
905
632
 
906
633
    if (! all)
907
634
    {
908
 
      Ha_trx_info *ha_info_all= &thd->ha_data[ha_info->ht()->slot].ha_info[1];
 
635
      Ha_trx_info *ha_info_all= &session->ha_data[ha_info->ht()->slot].ha_info[1];
909
636
      assert(ha_info != ha_info_all);
910
637
      /*
911
638
        Merge read-only/read-write information about statement
912
639
        transaction to its enclosing normal transaction. Do this
913
640
        only if in a real transaction -- that is, if we know
914
 
        that ha_info_all is registered in thd->transaction.all.
 
641
        that ha_info_all is registered in session->transaction.all.
915
642
        Since otherwise we only clutter the normal transaction flags.
916
643
      */
917
644
      if (ha_info_all->is_started()) /* false if autocommit. */
945
672
    stored functions or triggers. So we simply do nothing now.
946
673
    TODO: This should be fixed in later ( >= 5.1) releases.
947
674
*/
948
 
int ha_commit_trans(THD *thd, bool all)
 
675
int ha_commit_trans(Session *session, bool all)
949
676
{
950
677
  int error= 0, cookie= 0;
951
678
  /*
952
679
    'all' means that this is either an explicit commit issued by
953
680
    user, or an implicit commit issued by a DDL.
954
681
  */
955
 
  THD_TRANS *trans= all ? &thd->transaction.all : &thd->transaction.stmt;
956
 
  bool is_real_trans= all || thd->transaction.all.ha_list == 0;
 
682
  Session_TRANS *trans= all ? &session->transaction.all : &session->transaction.stmt;
 
683
  bool is_real_trans= all || session->transaction.all.ha_list == 0;
957
684
  Ha_trx_info *ha_info= trans->ha_list;
958
 
  my_xid xid= thd->transaction.xid_state.xid.get_my_xid();
 
685
  my_xid xid= session->transaction.xid_state.xid.get_my_xid();
959
686
 
960
687
  /*
961
688
    We must not commit the normal transaction if a statement
963
690
    flags will not get propagated to its normal transaction's
964
691
    counterpart.
965
692
  */
966
 
  assert(thd->transaction.stmt.ha_list == NULL ||
967
 
              trans == &thd->transaction.stmt);
 
693
  assert(session->transaction.stmt.ha_list == NULL ||
 
694
              trans == &session->transaction.stmt);
968
695
 
969
 
  if (thd->in_sub_stmt)
970
 
  {
971
 
    /*
972
 
      Since we don't support nested statement transactions in 5.0,
973
 
      we can't commit or rollback stmt transactions while we are inside
974
 
      stored functions or triggers. So we simply do nothing now.
975
 
      TODO: This should be fixed in later ( >= 5.1) releases.
976
 
    */
977
 
    if (!all)
978
 
      return(0);
979
 
    /*
980
 
      We assume that all statements which commit or rollback main transaction
981
 
      are prohibited inside of stored functions or triggers. So they should
982
 
      bail out with error even before ha_commit_trans() call. To be 100% safe
983
 
      let us throw error in non-debug builds.
984
 
    */
985
 
    assert(0);
986
 
    my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
987
 
    return(2);
988
 
  }
989
696
  if (ha_info)
990
697
  {
991
698
    bool must_2pc;
992
699
 
993
 
    if (is_real_trans && wait_if_global_read_lock(thd, 0, 0))
 
700
    if (is_real_trans && wait_if_global_read_lock(session, 0, 0))
994
701
    {
995
 
      ha_rollback_trans(thd, all);
 
702
      ha_rollback_trans(session, all);
996
703
      return(1);
997
704
    }
998
705
 
999
 
    if (   is_real_trans
1000
 
        && opt_readonly
1001
 
        && ! thd->slave_thread
1002
 
       )
1003
 
    {
1004
 
      my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only");
1005
 
      ha_rollback_trans(thd, all);
1006
 
      error= 1;
1007
 
      goto end;
1008
 
    }
1009
 
 
1010
 
    must_2pc= ha_check_and_coalesce_trx_read_only(thd, ha_info, all);
 
706
    must_2pc= ha_check_and_coalesce_trx_read_only(session, ha_info, all);
1011
707
 
1012
708
    if (!trans->no_2pc && must_2pc)
1013
709
    {
1026
722
          Sic: we know that prepare() is not NULL since otherwise
1027
723
          trans->no_2pc would have been set.
1028
724
        */
1029
 
        if ((err= ht->prepare(ht, thd, all)))
 
725
        if ((err= ht->prepare(ht, session, all)))
1030
726
        {
1031
727
          my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
1032
728
          error= 1;
1033
729
        }
1034
 
        status_var_increment(thd->status_var.ha_prepare_count);
 
730
        status_var_increment(session->status_var.ha_prepare_count);
1035
731
      }
1036
732
      if (error || (is_real_trans && xid &&
1037
 
                    (error= !(cookie= tc_log->log_xid(thd, xid)))))
 
733
                    (error= !(cookie= tc_log->log_xid(session, xid)))))
1038
734
      {
1039
 
        ha_rollback_trans(thd, all);
 
735
        ha_rollback_trans(session, all);
1040
736
        error= 1;
1041
737
        goto end;
1042
738
      }
1043
739
    }
1044
 
    error=ha_commit_one_phase(thd, all) ? (cookie ? 2 : 1) : 0;
 
740
    error=ha_commit_one_phase(session, all) ? (cookie ? 2 : 1) : 0;
1045
741
    if (cookie)
1046
742
      tc_log->unlog(cookie, xid);
1047
743
end:
1048
744
    if (is_real_trans)
1049
 
      start_waiting_global_read_lock(thd);
 
745
      start_waiting_global_read_lock(session);
1050
746
  }
1051
747
  return(error);
1052
748
}
1055
751
  @note
1056
752
  This function does not care about global read lock. A caller should.
1057
753
*/
1058
 
int ha_commit_one_phase(THD *thd, bool all)
 
754
int ha_commit_one_phase(Session *session, bool all)
1059
755
{
1060
756
  int error=0;
1061
 
  THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt;
1062
 
  bool is_real_trans=all || thd->transaction.all.ha_list == 0;
 
757
  Session_TRANS *trans=all ? &session->transaction.all : &session->transaction.stmt;
 
758
  bool is_real_trans=all || session->transaction.all.ha_list == 0;
1063
759
  Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
1064
760
  if (ha_info)
1065
761
  {
1067
763
    {
1068
764
      int err;
1069
765
      handlerton *ht= ha_info->ht();
1070
 
      if ((err= ht->commit(ht, thd, all)))
 
766
      if ((err= ht->commit(ht, session, all)))
1071
767
      {
1072
768
        my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
1073
769
        error=1;
1074
770
      }
1075
 
      status_var_increment(thd->status_var.ha_commit_count);
 
771
      status_var_increment(session->status_var.ha_commit_count);
1076
772
      ha_info_next= ha_info->next();
1077
773
      ha_info->reset(); /* keep it conveniently zero-filled */
1078
774
    }
1079
775
    trans->ha_list= 0;
1080
776
    trans->no_2pc=0;
1081
777
    if (is_real_trans)
1082
 
      thd->transaction.xid_state.xid.null();
 
778
      session->transaction.xid_state.xid.null();
1083
779
    if (all)
1084
780
    {
1085
 
      thd->variables.tx_isolation=thd->session_tx_isolation;
1086
 
      thd->transaction.cleanup();
 
781
      session->variables.tx_isolation=session->session_tx_isolation;
 
782
      session->transaction.cleanup();
1087
783
    }
1088
784
  }
1089
785
  return(error);
1090
786
}
1091
787
 
1092
788
 
1093
 
int ha_rollback_trans(THD *thd, bool all)
 
789
int ha_rollback_trans(Session *session, bool all)
1094
790
{
1095
791
  int error=0;
1096
 
  THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt;
 
792
  Session_TRANS *trans=all ? &session->transaction.all : &session->transaction.stmt;
1097
793
  Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
1098
 
  bool is_real_trans=all || thd->transaction.all.ha_list == 0;
 
794
  bool is_real_trans=all || session->transaction.all.ha_list == 0;
1099
795
 
1100
796
  /*
1101
797
    We must not rollback the normal transaction if a statement
1102
798
    transaction is pending.
1103
799
  */
1104
 
  assert(thd->transaction.stmt.ha_list == NULL ||
1105
 
              trans == &thd->transaction.stmt);
 
800
  assert(session->transaction.stmt.ha_list == NULL ||
 
801
              trans == &session->transaction.stmt);
1106
802
 
1107
 
  if (thd->in_sub_stmt)
1108
 
  {
1109
 
    /*
1110
 
      If we are inside stored function or trigger we should not commit or
1111
 
      rollback current statement transaction. See comment in ha_commit_trans()
1112
 
      call for more information.
1113
 
    */
1114
 
    if (!all)
1115
 
      return(0);
1116
 
    assert(0);
1117
 
    my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
1118
 
    return(1);
1119
 
  }
1120
803
  if (ha_info)
1121
804
  {
1122
805
    for (; ha_info; ha_info= ha_info_next)
1123
806
    {
1124
807
      int err;
1125
808
      handlerton *ht= ha_info->ht();
1126
 
      if ((err= ht->rollback(ht, thd, all)))
 
809
      if ((err= ht->rollback(ht, session, all)))
1127
810
      { // cannot happen
1128
811
        my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
1129
812
        error=1;
1130
813
      }
1131
 
      status_var_increment(thd->status_var.ha_rollback_count);
 
814
      status_var_increment(session->status_var.ha_rollback_count);
1132
815
      ha_info_next= ha_info->next();
1133
816
      ha_info->reset(); /* keep it conveniently zero-filled */
1134
817
    }
1135
818
    trans->ha_list= 0;
1136
819
    trans->no_2pc=0;
1137
820
    if (is_real_trans)
1138
 
      thd->transaction.xid_state.xid.null();
 
821
      session->transaction.xid_state.xid.null();
1139
822
    if (all)
1140
823
    {
1141
 
      thd->variables.tx_isolation=thd->session_tx_isolation;
1142
 
      thd->transaction.cleanup();
 
824
      session->variables.tx_isolation=session->session_tx_isolation;
 
825
      session->transaction.cleanup();
1143
826
    }
1144
827
  }
1145
828
  if (all)
1146
 
    thd->transaction_rollback_request= false;
 
829
    session->transaction_rollback_request= false;
1147
830
 
1148
831
  /*
1149
832
    If a non-transactional table was updated, warn; don't warn if this is a
1154
837
    the error log; but we don't want users to wonder why they have this
1155
838
    message in the error log, so we don't send it.
1156
839
  */
1157
 
  if (is_real_trans && thd->transaction.all.modified_non_trans_table &&
1158
 
      !thd->slave_thread && thd->killed != THD::KILL_CONNECTION)
1159
 
    push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
840
  if (is_real_trans && session->transaction.all.modified_non_trans_table &&
 
841
      !session->slave_thread && session->killed != Session::KILL_CONNECTION)
 
842
    push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1160
843
                 ER_WARNING_NOT_COMPLETE_ROLLBACK,
1161
844
                 ER(ER_WARNING_NOT_COMPLETE_ROLLBACK));
1162
845
  return(error);
1173
856
    the user has used LOCK TABLES then that mechanism does not know to do the
1174
857
    commit.
1175
858
*/
1176
 
int ha_autocommit_or_rollback(THD *thd, int error)
 
859
int ha_autocommit_or_rollback(Session *session, int error)
1177
860
{
1178
 
  if (thd->transaction.stmt.ha_list)
 
861
  if (session->transaction.stmt.ha_list)
1179
862
  {
1180
863
    if (!error)
1181
864
    {
1182
 
      if (ha_commit_trans(thd, 0))
1183
 
        error=1;
 
865
      if (ha_commit_trans(session, 0))
 
866
        error=1;
1184
867
    }
1185
 
    else 
 
868
    else
1186
869
    {
1187
 
      (void) ha_rollback_trans(thd, 0);
1188
 
      if (thd->transaction_rollback_request && !thd->in_sub_stmt)
1189
 
        (void) ha_rollback(thd);
 
870
      (void) ha_rollback_trans(session, 0);
 
871
      if (session->transaction_rollback_request)
 
872
        (void) ha_rollback(session);
1190
873
    }
1191
874
 
1192
 
    thd->variables.tx_isolation=thd->session_tx_isolation;
 
875
    session->variables.tx_isolation=session->session_tx_isolation;
1193
876
  }
1194
877
  return(error);
1195
878
}
1200
883
  int result;
1201
884
};
1202
885
 
1203
 
static bool xacommit_handlerton(THD *unused1 __attribute__((unused)),
 
886
static bool xacommit_handlerton(Session *unused1 __attribute__((unused)),
1204
887
                                plugin_ref plugin,
1205
888
                                void *arg)
1206
889
{
1213
896
  return false;
1214
897
}
1215
898
 
1216
 
static bool xarollback_handlerton(THD *unused1 __attribute__((unused)),
 
899
static bool xarollback_handlerton(Session *unused1 __attribute__((unused)),
1217
900
                                  plugin_ref plugin,
1218
901
                                  void *arg)
1219
902
{
1263
946
  bool dry_run;
1264
947
};
1265
948
 
1266
 
static bool xarecover_handlerton(THD *unused __attribute__((unused)),
 
949
static bool xarecover_handlerton(Session *unused __attribute__((unused)),
1267
950
                                 plugin_ref plugin,
1268
951
                                 void *arg)
1269
952
{
1275
958
  {
1276
959
    while ((got= hton->recover(hton, info->list, info->len)) > 0 )
1277
960
    {
1278
 
      sql_print_information("Found %d prepared transaction(s) in %s",
 
961
      sql_print_information(_("Found %d prepared transaction(s) in %s"),
1279
962
                            got, ha_resolve_storage_engine_name(hton));
1280
963
      for (int i=0; i < got; i ++)
1281
964
      {
1293
976
        }
1294
977
        // recovery mode
1295
978
        if (info->commit_list ?
1296
 
            hash_search(info->commit_list, (uchar *)&x, sizeof(x)) != 0 :
 
979
            hash_search(info->commit_list, (unsigned char *)&x, sizeof(x)) != 0 :
1297
980
            tc_heuristic_recover == TC_HEURISTIC_RECOVER_COMMIT)
1298
981
        {
1299
982
          hton->commit_by_xid(hton, info->list+i);
1327
1010
    return(0);
1328
1011
 
1329
1012
  if (info.commit_list)
1330
 
    sql_print_information("Starting crash recovery...");
 
1013
    sql_print_information(_("Starting crash recovery..."));
1331
1014
 
1332
1015
 
1333
1016
#ifndef WILL_BE_DELETED_LATER
1343
1026
#endif
1344
1027
 
1345
1028
 
1346
 
  for (info.len= MAX_XID_LIST_SIZE ; 
 
1029
  for (info.len= MAX_XID_LIST_SIZE ;
1347
1030
       info.list==0 && info.len > MIN_XID_LIST_SIZE; info.len/=2)
1348
1031
  {
1349
 
    info.list=(XID *)my_malloc(info.len*sizeof(XID), MYF(0));
 
1032
    info.list=(XID *)malloc(info.len*sizeof(XID));
1350
1033
  }
1351
1034
  if (!info.list)
1352
1035
  {
1354
1037
    return(1);
1355
1038
  }
1356
1039
 
1357
 
  plugin_foreach(NULL, xarecover_handlerton, 
 
1040
  plugin_foreach(NULL, xarecover_handlerton,
1358
1041
                 DRIZZLE_STORAGE_ENGINE_PLUGIN, &info);
1359
1042
 
1360
 
  my_free((uchar*)info.list, MYF(0));
 
1043
  free((unsigned char*)info.list);
1361
1044
  if (info.found_foreign_xids)
1362
 
    sql_print_warning("Found %d prepared XA transactions", 
 
1045
    sql_print_warning(_("Found %d prepared XA transactions"),
1363
1046
                      info.found_foreign_xids);
1364
1047
  if (info.dry_run && info.found_my_xids)
1365
1048
  {
1366
 
    sql_print_error("Found %d prepared transactions! It means that mysqld was "
1367
 
                    "not shut down properly last time and critical recovery "
1368
 
                    "information (last binlog or %s file) was manually deleted "
1369
 
                    "after a crash. You have to start mysqld with "
1370
 
                    "--tc-heuristic-recover switch to commit or rollback "
1371
 
                    "pending transactions.",
 
1049
    sql_print_error(_("Found %d prepared transactions! It means that drizzled "
 
1050
                    "was not shut down properly last time and critical "
 
1051
                    "recovery information (last binlog or %s file) was "
 
1052
                    "manually deleted after a crash. You have to start "
 
1053
                    "drizzled with the --tc-heuristic-recover switch to "
 
1054
                    "commit or rollback pending transactions."),
1372
1055
                    info.found_my_xids, opt_tc_log_file);
1373
1056
    return(1);
1374
1057
  }
1375
1058
  if (info.commit_list)
1376
 
    sql_print_information("Crash recovery finished.");
 
1059
    sql_print_information(_("Crash recovery finished."));
1377
1060
  return(0);
1378
1061
}
1379
1062
 
1385
1068
    so mysql_xa_recover does not filter XID's to ensure uniqueness.
1386
1069
    It can be easily fixed later, if necessary.
1387
1070
*/
1388
 
bool mysql_xa_recover(THD *thd)
 
1071
bool mysql_xa_recover(Session *session)
1389
1072
{
1390
1073
  List<Item> field_list;
1391
 
  Protocol *protocol= thd->protocol;
 
1074
  Protocol *protocol= session->protocol;
1392
1075
  int i=0;
1393
1076
  XID_STATE *xs;
1394
1077
 
1421
1104
  }
1422
1105
 
1423
1106
  pthread_mutex_unlock(&LOCK_xid_cache);
1424
 
  my_eof(thd);
 
1107
  my_eof(session);
1425
1108
  return(0);
1426
1109
}
1427
1110
 
1429
1112
  @details
1430
1113
  This function should be called when MySQL sends rows of a SELECT result set
1431
1114
  or the EOF mark to the client. It releases a possible adaptive hash index
1432
 
  S-latch held by thd in InnoDB and also releases a possible InnoDB query
1433
 
  FIFO ticket to enter InnoDB. To save CPU time, InnoDB allows a thd to
 
1115
  S-latch held by session in InnoDB and also releases a possible InnoDB query
 
1116
  FIFO ticket to enter InnoDB. To save CPU time, InnoDB allows a session to
1434
1117
  keep them over several calls of the InnoDB handler interface when a join
1435
1118
  is executed. But when we let the control to pass to the client they have
1436
1119
  to be released because if the application program uses mysql_use_result(),
1438
1121
  performs another SQL query. In MySQL-4.1 this is even more important because
1439
1122
  there a connection can have several SELECT queries open at the same time.
1440
1123
 
1441
 
  @param thd           the thread handle of the current connection
 
1124
  @param session           the thread handle of the current connection
1442
1125
 
1443
1126
  @return
1444
1127
    always 0
1445
1128
*/
1446
 
static bool release_temporary_latches(THD *thd, plugin_ref plugin,
 
1129
static bool release_temporary_latches(Session *session, plugin_ref plugin,
1447
1130
                                      void *unused __attribute__((unused)))
1448
1131
{
1449
1132
  handlerton *hton= plugin_data(plugin, handlerton *);
1450
1133
 
1451
1134
  if (hton->state == SHOW_OPTION_YES && hton->release_temporary_latches)
1452
 
    hton->release_temporary_latches(hton, thd);
 
1135
    hton->release_temporary_latches(hton, session);
1453
1136
 
1454
1137
  return false;
1455
1138
}
1456
1139
 
1457
1140
 
1458
 
int ha_release_temporary_latches(THD *thd)
 
1141
int ha_release_temporary_latches(Session *session)
1459
1142
{
1460
 
  plugin_foreach(thd, release_temporary_latches, DRIZZLE_STORAGE_ENGINE_PLUGIN, 
 
1143
  plugin_foreach(session, release_temporary_latches, DRIZZLE_STORAGE_ENGINE_PLUGIN,
1461
1144
                 NULL);
1462
1145
 
1463
1146
  return 0;
1464
1147
}
1465
1148
 
1466
 
int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv)
 
1149
int ha_rollback_to_savepoint(Session *session, SAVEPOINT *sv)
1467
1150
{
1468
1151
  int error=0;
1469
 
  THD_TRANS *trans= (thd->in_sub_stmt ? &thd->transaction.stmt :
1470
 
                                        &thd->transaction.all);
 
1152
  Session_TRANS *trans= &session->transaction.all;
1471
1153
  Ha_trx_info *ha_info, *ha_info_next;
1472
1154
 
1473
1155
  trans->no_2pc=0;
1481
1163
    handlerton *ht= ha_info->ht();
1482
1164
    assert(ht);
1483
1165
    assert(ht->savepoint_set != 0);
1484
 
    if ((err= ht->savepoint_rollback(ht, thd,
1485
 
                                     (uchar *)(sv+1)+ht->savepoint_offset)))
 
1166
    if ((err= ht->savepoint_rollback(ht, session,
 
1167
                                     (unsigned char *)(sv+1)+ht->savepoint_offset)))
1486
1168
    { // cannot happen
1487
1169
      my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
1488
1170
      error=1;
1489
1171
    }
1490
 
    status_var_increment(thd->status_var.ha_savepoint_rollback_count);
 
1172
    status_var_increment(session->status_var.ha_savepoint_rollback_count);
1491
1173
    trans->no_2pc|= ht->prepare == 0;
1492
1174
  }
1493
1175
  /*
1499
1181
  {
1500
1182
    int err;
1501
1183
    handlerton *ht= ha_info->ht();
1502
 
    if ((err= ht->rollback(ht, thd, !thd->in_sub_stmt)))
 
1184
    if ((err= ht->rollback(ht, session, !(0))))
1503
1185
    { // cannot happen
1504
1186
      my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
1505
1187
      error=1;
1506
1188
    }
1507
 
    status_var_increment(thd->status_var.ha_rollback_count);
 
1189
    status_var_increment(session->status_var.ha_rollback_count);
1508
1190
    ha_info_next= ha_info->next();
1509
1191
    ha_info->reset(); /* keep it conveniently zero-filled */
1510
1192
  }
1518
1200
  section "4.33.4 SQL-statements and transaction states",
1519
1201
  SAVEPOINT is *not* transaction-initiating SQL-statement
1520
1202
*/
1521
 
int ha_savepoint(THD *thd, SAVEPOINT *sv)
 
1203
int ha_savepoint(Session *session, SAVEPOINT *sv)
1522
1204
{
1523
1205
  int error=0;
1524
 
  THD_TRANS *trans= (thd->in_sub_stmt ? &thd->transaction.stmt :
1525
 
                                        &thd->transaction.all);
 
1206
  Session_TRANS *trans= &session->transaction.all;
1526
1207
  Ha_trx_info *ha_info= trans->ha_list;
1527
1208
  for (; ha_info; ha_info= ha_info->next())
1528
1209
  {
1535
1216
      error=1;
1536
1217
      break;
1537
1218
    }
1538
 
    if ((err= ht->savepoint_set(ht, thd, (uchar *)(sv+1)+ht->savepoint_offset)))
 
1219
    if ((err= ht->savepoint_set(ht, session, (unsigned char *)(sv+1)+ht->savepoint_offset)))
1539
1220
    { // cannot happen
1540
1221
      my_error(ER_GET_ERRNO, MYF(0), err);
1541
1222
      error=1;
1542
1223
    }
1543
 
    status_var_increment(thd->status_var.ha_savepoint_count);
 
1224
    status_var_increment(session->status_var.ha_savepoint_count);
1544
1225
  }
1545
1226
  /*
1546
1227
    Remember the list of registered storage engines. All new
1550
1231
  return(error);
1551
1232
}
1552
1233
 
1553
 
int ha_release_savepoint(THD *thd, SAVEPOINT *sv)
 
1234
int ha_release_savepoint(Session *session, SAVEPOINT *sv)
1554
1235
{
1555
1236
  int error=0;
1556
1237
  Ha_trx_info *ha_info= sv->ha_list;
1563
1244
    assert(ht);
1564
1245
    if (!ht->savepoint_release)
1565
1246
      continue;
1566
 
    if ((err= ht->savepoint_release(ht, thd,
1567
 
                                    (uchar *)(sv+1) + ht->savepoint_offset)))
 
1247
    if ((err= ht->savepoint_release(ht, session,
 
1248
                                    (unsigned char *)(sv+1) + ht->savepoint_offset)))
1568
1249
    { // cannot happen
1569
1250
      my_error(ER_GET_ERRNO, MYF(0), err);
1570
1251
      error=1;
1574
1255
}
1575
1256
 
1576
1257
 
1577
 
static bool snapshot_handlerton(THD *thd, plugin_ref plugin, void *arg)
 
1258
static bool snapshot_handlerton(Session *session, plugin_ref plugin, void *arg)
1578
1259
{
1579
1260
  handlerton *hton= plugin_data(plugin, handlerton *);
1580
1261
  if (hton->state == SHOW_OPTION_YES &&
1581
1262
      hton->start_consistent_snapshot)
1582
1263
  {
1583
 
    hton->start_consistent_snapshot(hton, thd);
 
1264
    hton->start_consistent_snapshot(hton, session);
1584
1265
    *((bool *)arg)= false;
1585
1266
  }
1586
1267
  return false;
1587
1268
}
1588
1269
 
1589
 
int ha_start_consistent_snapshot(THD *thd)
 
1270
int ha_start_consistent_snapshot(Session *session)
1590
1271
{
1591
1272
  bool warn= true;
1592
1273
 
1593
 
  plugin_foreach(thd, snapshot_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN, &warn);
 
1274
  plugin_foreach(session, snapshot_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN, &warn);
1594
1275
 
1595
1276
  /*
1596
1277
    Same idea as when one wants to CREATE TABLE in one engine which does not
1597
1278
    exist:
1598
1279
  */
1599
1280
  if (warn)
1600
 
    push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
1601
 
                 "This MySQL server does not support any "
 
1281
    push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
 
1282
                 "This Drizzle server does not support any "
1602
1283
                 "consistent-read capable storage engine");
1603
1284
  return 0;
1604
1285
}
1605
1286
 
1606
1287
 
1607
 
static bool flush_handlerton(THD *thd __attribute__((unused)),
 
1288
static bool flush_handlerton(Session *session __attribute__((unused)),
1608
1289
                             plugin_ref plugin,
1609
1290
                             void *arg __attribute__((unused)))
1610
1291
{
1611
1292
  handlerton *hton= plugin_data(plugin, handlerton *);
1612
 
  if (hton->state == SHOW_OPTION_YES && hton->flush_logs && 
 
1293
  if (hton->state == SHOW_OPTION_YES && hton->flush_logs &&
1613
1294
      hton->flush_logs(hton))
1614
1295
    return true;
1615
1296
  return false;
1641
1322
 
1642
1323
  /* Ensure that table handler get path in lower case */
1643
1324
  if (tmp_path != path)
1644
 
    stpcpy(tmp_path, path);
 
1325
    strcpy(tmp_path, path);
1645
1326
 
1646
1327
  /*
1647
1328
    we only should turn into lowercase database/table part
1648
1329
    so start the process after homedirectory
1649
1330
  */
1650
 
  my_casedn_str(files_charset_info, tmp_path + mysql_data_home_len);
 
1331
  my_casedn_str(files_charset_info, tmp_path + drizzle_data_home_len);
1651
1332
  return tmp_path;
1652
1333
}
1653
1334
 
1661
1342
struct Ha_delete_table_error_handler: public Internal_error_handler
1662
1343
{
1663
1344
public:
1664
 
  virtual bool handle_error(uint sql_errno,
 
1345
  virtual bool handle_error(uint32_t sql_errno,
1665
1346
                            const char *message,
1666
1347
                            DRIZZLE_ERROR::enum_warning_level level,
1667
 
                            THD *thd);
 
1348
                            Session *session);
1668
1349
  char buff[DRIZZLE_ERRMSG_SIZE];
1669
1350
};
1670
1351
 
1671
1352
 
1672
1353
bool
1673
1354
Ha_delete_table_error_handler::
1674
 
handle_error(uint sql_errno  __attribute__((unused)),
 
1355
handle_error(uint32_t sql_errno  __attribute__((unused)),
1675
1356
             const char *message,
1676
1357
             DRIZZLE_ERROR::enum_warning_level level __attribute__((unused)),
1677
 
             THD *thd __attribute__((unused)))
 
1358
             Session *session __attribute__((unused)))
1678
1359
{
1679
1360
  /* Grab the error message */
1680
 
  strmake(buff, message, sizeof(buff)-1);
 
1361
  strncpy(buff, message, sizeof(buff)-1);
1681
1362
  return true;
1682
1363
}
1683
1364
 
1684
1365
 
 
1366
struct handlerton_delete_table_args {
 
1367
  Session *session;
 
1368
  const char *path;
 
1369
  handler *file;
 
1370
  int error;
 
1371
};
 
1372
 
 
1373
static bool deletetable_handlerton(Session *unused1 __attribute__((unused)),
 
1374
                                   plugin_ref plugin,
 
1375
                                   void *args)
 
1376
{
 
1377
  struct handlerton_delete_table_args *dtargs= (struct handlerton_delete_table_args *) args;
 
1378
 
 
1379
  Session *session= dtargs->session;
 
1380
  const char *path= dtargs->path;
 
1381
 
 
1382
  handler *file;
 
1383
  char tmp_path[FN_REFLEN];
 
1384
 
 
1385
  if(dtargs->error!=ENOENT) /* already deleted table */
 
1386
    return false;
 
1387
 
 
1388
  handlerton *table_type= plugin_data(plugin, handlerton *);
 
1389
 
 
1390
  if(!table_type)
 
1391
    return false;
 
1392
 
 
1393
  if(!(table_type->state == SHOW_OPTION_YES && table_type->create))
 
1394
    return false;
 
1395
 
 
1396
  if ((file= table_type->create(table_type, NULL, session->mem_root)))
 
1397
    file->init();
 
1398
  else
 
1399
    return false;
 
1400
 
 
1401
  path= check_lowercase_names(file, path, tmp_path);
 
1402
  int error= file->ha_delete_table(path);
 
1403
 
 
1404
  if(error!=ENOENT)
 
1405
  {
 
1406
    dtargs->error= error;
 
1407
    if(dtargs->file)
 
1408
      delete dtargs->file;
 
1409
    dtargs->file= file;
 
1410
    return true;
 
1411
  }
 
1412
 
 
1413
  return false;
 
1414
}
 
1415
 
1685
1416
/**
1686
1417
  This should return ENOENT if the file doesn't exists.
1687
1418
  The .frm file will be deleted only if we return 0 or ENOENT
1688
1419
*/
1689
 
int ha_delete_table(THD *thd, handlerton *table_type, const char *path,
 
1420
int ha_delete_table(Session *session, const char *path,
1690
1421
                    const char *db, const char *alias, bool generate_warning)
1691
1422
{
1692
 
  handler *file;
1693
 
  char tmp_path[FN_REFLEN];
1694
 
  int error;
1695
 
  TABLE dummy_table;
1696
1423
  TABLE_SHARE dummy_share;
 
1424
  Table dummy_table;
 
1425
 
 
1426
  struct handlerton_delete_table_args dtargs;
 
1427
  dtargs.error= ENOENT;
 
1428
  dtargs.session= session;
 
1429
  dtargs.path= path;
 
1430
  dtargs.file= NULL;
 
1431
 
 
1432
  plugin_foreach(NULL, deletetable_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN,
 
1433
                 &dtargs);
1697
1434
 
1698
1435
  memset(&dummy_table, 0, sizeof(dummy_table));
1699
1436
  memset(&dummy_share, 0, sizeof(dummy_share));
1700
1437
  dummy_table.s= &dummy_share;
1701
1438
 
1702
 
  /* DB_TYPE_UNKNOWN is used in ALTER TABLE when renaming only .frm files */
1703
 
  if (table_type == NULL ||
1704
 
      ! (file=get_new_handler((TABLE_SHARE*)0, thd->mem_root, table_type)))
1705
 
    return(ENOENT);
1706
 
 
1707
 
  path= check_lowercase_names(file, path, tmp_path);
1708
 
  if ((error= file->ha_delete_table(path)) && generate_warning)
 
1439
  if (dtargs.error && generate_warning)
1709
1440
  {
1710
1441
    /*
1711
1442
      Because file->print_error() use my_error() to generate the error message
1724
1455
    dummy_share.table_name.length= strlen(alias);
1725
1456
    dummy_table.alias= alias;
1726
1457
 
 
1458
    handler *file= dtargs.file;
1727
1459
    file->change_table_ptr(&dummy_table, &dummy_share);
1728
1460
 
1729
 
    thd->push_internal_handler(&ha_delete_table_error_handler);
1730
 
    file->print_error(error, 0);
 
1461
    session->push_internal_handler(&ha_delete_table_error_handler);
 
1462
    file->print_error(dtargs.error, 0);
1731
1463
 
1732
 
    thd->pop_internal_handler();
 
1464
    session->pop_internal_handler();
1733
1465
 
1734
1466
    /*
1735
1467
      XXX: should we convert *all* errors to warnings here?
1736
1468
      What if the error is fatal?
1737
1469
    */
1738
 
    push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_ERROR, error,
 
1470
    push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR, dtargs.error,
1739
1471
                ha_delete_table_error_handler.buff);
1740
1472
  }
1741
 
  delete file;
1742
 
  return(error);
 
1473
 
 
1474
  if(dtargs.file)
 
1475
    delete dtargs.file;
 
1476
 
 
1477
  return dtargs.error;
1743
1478
}
1744
1479
 
1745
1480
/****************************************************************************
1750
1485
  handler *new_handler= get_new_handler(table->s, mem_root, table->s->db_type());
1751
1486
  /*
1752
1487
    Allocate handler->ref here because otherwise ha_open will allocate it
1753
 
    on this->table->mem_root and we will not be able to reclaim that memory 
 
1488
    on this->table->mem_root and we will not be able to reclaim that memory
1754
1489
    when the clone handler object is destroyed.
1755
1490
  */
1756
 
  if (!(new_handler->ref= (uchar*) alloc_root(mem_root, ALIGN_SIZE(ref_length)*2)))
 
1491
  if (!(new_handler->ref= (unsigned char*) alloc_root(mem_root, ALIGN_SIZE(ref_length)*2)))
1757
1492
    return NULL;
1758
1493
  if (new_handler && !new_handler->ha_open(table,
1759
1494
                                           table->s->normalized_path.str,
1760
 
                                           table->db_stat,
 
1495
                                           table->getDBStat(),
1761
1496
                                           HA_OPEN_IGNORE_IF_LOCKED))
1762
1497
    return new_handler;
1763
1498
  return NULL;
1764
1499
}
1765
1500
 
1766
 
 
 
1501
int handler::ha_index_init(uint32_t idx, bool sorted)
 
1502
{
 
1503
  int result;
 
1504
  assert(inited==NONE);
 
1505
  if (!(result= index_init(idx, sorted)))
 
1506
    inited=INDEX;
 
1507
  end_range= NULL;
 
1508
  return(result);
 
1509
}
 
1510
 
 
1511
int handler::ha_index_end()
 
1512
{
 
1513
  assert(inited==INDEX);
 
1514
  inited=NONE;
 
1515
  end_range= NULL;
 
1516
  return(index_end());
 
1517
}
 
1518
 
 
1519
int handler::ha_rnd_init(bool scan)
 
1520
{
 
1521
  int result;
 
1522
  assert(inited==NONE || (inited==RND && scan));
 
1523
  inited= (result= rnd_init(scan)) ? NONE: RND;
 
1524
  return(result);
 
1525
}
 
1526
 
 
1527
int handler::ha_rnd_end()
 
1528
{
 
1529
  assert(inited==RND);
 
1530
  inited=NONE;
 
1531
  return(rnd_end());
 
1532
}
 
1533
 
 
1534
int handler::ha_index_or_rnd_end()
 
1535
{
 
1536
  return inited == INDEX ? ha_index_end() : inited == RND ? ha_rnd_end() : 0;
 
1537
}
 
1538
 
 
1539
handler::Table_flags handler::ha_table_flags() const
 
1540
{
 
1541
  return cached_table_flags;
 
1542
}
 
1543
 
 
1544
void handler::ha_start_bulk_insert(ha_rows rows)
 
1545
{
 
1546
  estimation_rows_to_insert= rows;
 
1547
  start_bulk_insert(rows);
 
1548
}
 
1549
 
 
1550
int handler::ha_end_bulk_insert()
 
1551
{
 
1552
  estimation_rows_to_insert= 0;
 
1553
  return end_bulk_insert();
 
1554
}
 
1555
 
 
1556
void handler::change_table_ptr(Table *table_arg, TABLE_SHARE *share)
 
1557
{
 
1558
  table= table_arg;
 
1559
  table_share= share;
 
1560
}
 
1561
 
 
1562
const key_map *handler::keys_to_use_for_scanning()
 
1563
{
 
1564
  return &key_map_empty;
 
1565
}
 
1566
 
 
1567
bool handler::has_transactions()
 
1568
{
 
1569
  return (ha_table_flags() & HA_NO_TRANSACTIONS) == 0;
 
1570
}
1767
1571
 
1768
1572
void handler::ha_statistic_increment(ulong SSV::*offset) const
1769
1573
{
1770
1574
  status_var_increment(table->in_use->status_var.*offset);
1771
1575
}
1772
1576
 
1773
 
void **handler::ha_data(THD *thd) const
1774
 
{
1775
 
  return thd_ha_data(thd, ht);
1776
 
}
1777
 
 
1778
 
THD *handler::ha_thd(void) const
1779
 
{
1780
 
  assert(!table || !table->in_use || table->in_use == current_thd);
1781
 
  return (table && table->in_use) ? table->in_use : current_thd;
1782
 
}
 
1577
void **handler::ha_data(Session *session) const
 
1578
{
 
1579
  return session_ha_data(session, ht);
 
1580
}
 
1581
 
 
1582
Session *handler::ha_session(void) const
 
1583
{
 
1584
  assert(!table || !table->in_use || table->in_use == current_session);
 
1585
  return (table && table->in_use) ? table->in_use : current_session;
 
1586
}
 
1587
 
 
1588
 
 
1589
bool handler::is_fatal_error(int error, uint32_t flags)
 
1590
{
 
1591
  if (!error ||
 
1592
      ((flags & HA_CHECK_DUP_KEY) &&
 
1593
       (error == HA_ERR_FOUND_DUPP_KEY ||
 
1594
        error == HA_ERR_FOUND_DUPP_UNIQUE)))
 
1595
    return false;
 
1596
  return true;
 
1597
}
 
1598
 
 
1599
 
 
1600
ha_rows handler::records() { return stats.records; }
1783
1601
 
1784
1602
/**
1785
1603
  Open database-handler.
1787
1605
  Try O_RDONLY if cannot open as O_RDWR
1788
1606
  Don't wait for locks if not HA_OPEN_WAIT_IF_LOCKED is set
1789
1607
*/
1790
 
int handler::ha_open(TABLE *table_arg, const char *name, int mode,
 
1608
int handler::ha_open(Table *table_arg, const char *name, int mode,
1791
1609
                     int test_if_locked)
1792
1610
{
1793
1611
  int error;
1816
1634
    (void) extra(HA_EXTRA_NO_READCHECK);        // Not needed in SQL
1817
1635
 
1818
1636
    /* ref is already allocated for us if we're called from handler::clone() */
1819
 
    if (!ref && !(ref= (uchar*) alloc_root(&table->mem_root, 
 
1637
    if (!ref && !(ref= (unsigned char*) alloc_root(&table->mem_root,
1820
1638
                                          ALIGN_SIZE(ref_length)*2)))
1821
1639
    {
1822
1640
      close();
1836
1654
  handlers for random position
1837
1655
*/
1838
1656
 
1839
 
int handler::rnd_pos_by_record(uchar *record)
 
1657
int handler::rnd_pos_by_record(unsigned char *record)
1840
1658
{
1841
1659
  register int error;
1842
1660
 
1855
1673
  This is never called for InnoDB tables, as these table types
1856
1674
  has the HA_STATS_RECORDS_IS_EXACT set.
1857
1675
*/
1858
 
int handler::read_first_row(uchar * buf, uint primary_key)
 
1676
int handler::read_first_row(unsigned char * buf, uint32_t primary_key)
1859
1677
{
1860
1678
  register int error;
1861
1679
 
1910
1728
void handler::adjust_next_insert_id_after_explicit_value(uint64_t nr)
1911
1729
{
1912
1730
  /*
1913
 
    If we have set THD::next_insert_id previously and plan to insert an
 
1731
    If we have set Session::next_insert_id previously and plan to insert an
1914
1732
    explicitely-specified value larger than this, we need to increase
1915
 
    THD::next_insert_id to be greater than the explicit value.
 
1733
    Session::next_insert_id to be greater than the explicit value.
1916
1734
  */
1917
1735
  if ((next_insert_id > 0) && (nr >= next_insert_id))
1918
1736
    set_next_insert_id(compute_next_insert_id(nr, &table->in_use->variables));
1988
1806
    again to reserve a new interval.
1989
1807
 
1990
1808
  - In both cases, the reserved intervals are remembered in
1991
 
    thd->auto_inc_intervals_in_cur_stmt_for_binlog if statement-based
 
1809
    session->auto_inc_intervals_in_cur_stmt_for_binlog if statement-based
1992
1810
    binlogging; the last reserved interval is remembered in
1993
1811
    auto_inc_interval_for_cur_row.
1994
1812
 
2002
1820
    start counting from the inserted value.
2003
1821
 
2004
1822
    This function's "outputs" are: the table's auto_increment field is filled
2005
 
    with a value, thd->next_insert_id is filled with the value to use for the
 
1823
    with a value, session->next_insert_id is filled with the value to use for the
2006
1824
    next row, if a value was autogenerated for the current row it is stored in
2007
 
    thd->insert_id_for_cur_row, if get_auto_increment() was called
2008
 
    thd->auto_inc_interval_for_cur_row is modified, if that interval is not
2009
 
    present in thd->auto_inc_intervals_in_cur_stmt_for_binlog it is added to
 
1825
    session->insert_id_for_cur_row, if get_auto_increment() was called
 
1826
    session->auto_inc_interval_for_cur_row is modified, if that interval is not
 
1827
    present in session->auto_inc_intervals_in_cur_stmt_for_binlog it is added to
2010
1828
    this list.
2011
1829
 
2012
1830
  @todo
2033
1851
{
2034
1852
  uint64_t nr, nb_reserved_values;
2035
1853
  bool append= false;
2036
 
  THD *thd= table->in_use;
2037
 
  struct system_variables *variables= &thd->variables;
 
1854
  Session *session= table->in_use;
 
1855
  struct system_variables *variables= &session->variables;
2038
1856
 
2039
1857
  /*
2040
1858
    next_insert_id is a "cursor" into the reserved interval, it may go greater
2042
1860
  */
2043
1861
  assert(next_insert_id >= auto_inc_interval_for_cur_row.minimum());
2044
1862
 
2045
 
  if (((nr= table->next_number_field->val_int()) != 0) || 
2046
 
      (table->auto_increment_field_not_null && (thd->variables.sql_mode & MODE_NO_AUTO_VALUE_ON_ZERO)))
 
1863
  if ((nr= table->next_number_field->val_int()) != 0)
2047
1864
  {
2048
1865
    /*
2049
1866
      Update next_insert_id if we had already generated a value in this
2060
1877
  {
2061
1878
    /* next_insert_id is beyond what is reserved, so we reserve more. */
2062
1879
    const Discrete_interval *forced=
2063
 
      thd->auto_inc_intervals_forced.get_next();
 
1880
      session->auto_inc_intervals_forced.get_next();
2064
1881
    if (forced != NULL)
2065
1882
    {
2066
1883
      nr= forced->minimum();
2072
1889
        handler::estimation_rows_to_insert was set by
2073
1890
        handler::ha_start_bulk_insert(); if 0 it means "unknown".
2074
1891
      */
2075
 
      uint nb_already_reserved_intervals=
2076
 
        thd->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements();
 
1892
      uint32_t nb_already_reserved_intervals=
 
1893
        session->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements();
2077
1894
      uint64_t nb_desired_values;
2078
1895
      /*
2079
1896
        If an estimation was given to the engine:
2094
1911
        /* avoid overflow in formula, with this if() */
2095
1912
        if (nb_already_reserved_intervals <= AUTO_INC_DEFAULT_NB_MAX_BITS)
2096
1913
        {
2097
 
          nb_desired_values= AUTO_INC_DEFAULT_NB_ROWS * 
 
1914
          nb_desired_values= AUTO_INC_DEFAULT_NB_ROWS *
2098
1915
            (1 << nb_already_reserved_intervals);
2099
1916
          set_if_smaller(nb_desired_values, AUTO_INC_DEFAULT_NB_MAX);
2100
1917
        }
2108
1925
                         &nb_reserved_values);
2109
1926
      if (nr == ~(uint64_t) 0)
2110
1927
        return(HA_ERR_AUTOINC_READ_FAILED);  // Mark failure
2111
 
      
 
1928
 
2112
1929
      /*
2113
1930
        That rounding below should not be needed when all engines actually
2114
1931
        respect offset and increment in get_auto_increment(). But they don't
2119
1936
      */
2120
1937
      nr= compute_next_insert_id(nr-1, variables);
2121
1938
    }
2122
 
    
 
1939
 
2123
1940
    if (table->s->next_number_keypart == 0)
2124
1941
    {
2125
1942
      /* We must defer the appending until "nr" has been possibly truncated */
2132
1949
    /*
2133
1950
      first test if the query was aborted due to strict mode constraints
2134
1951
    */
2135
 
    if (thd->killed == THD::KILL_BAD_DATA)
 
1952
    if (session->killed == Session::KILL_BAD_DATA)
2136
1953
      return(HA_ERR_AUTOINC_ERANGE);
2137
1954
 
2138
1955
    /*
2151
1968
  {
2152
1969
    auto_inc_interval_for_cur_row.replace(nr, nb_reserved_values,
2153
1970
                                          variables->auto_increment_increment);
2154
 
    /* Row-based replication does not need to store intervals in binlog */
2155
 
    if (!thd->current_stmt_binlog_row_based)
2156
 
        thd->auto_inc_intervals_in_cur_stmt_for_binlog.append(auto_inc_interval_for_cur_row.minimum(),
2157
 
                                                              auto_inc_interval_for_cur_row.values(),
2158
 
                                                              variables->auto_increment_increment);
2159
1971
  }
2160
1972
 
2161
1973
  /*
2235
2047
  }
2236
2048
  else
2237
2049
  {
2238
 
    uchar key[MAX_KEY_LENGTH];
 
2050
    unsigned char key[MAX_KEY_LENGTH];
2239
2051
    key_copy(key, table->record[0],
2240
2052
             table->key_info + table->s->next_number_index,
2241
2053
             table->s->next_number_key_offset);
2279
2091
}
2280
2092
 
2281
2093
 
2282
 
void handler::print_keydup_error(uint key_nr, const char *msg)
 
2094
void handler::print_keydup_error(uint32_t key_nr, const char *msg)
2283
2095
{
2284
2096
  /* Write the duplicated key in the error message */
2285
2097
  char key[MAX_KEY_LENGTH];
2295
2107
  {
2296
2108
    /* Table is opened and defined at this point */
2297
2109
    key_unpack(&str,table,(uint) key_nr);
2298
 
    uint max_length=DRIZZLE_ERRMSG_SIZE-(uint) strlen(msg);
 
2110
    uint32_t max_length=DRIZZLE_ERRMSG_SIZE-(uint) strlen(msg);
2299
2111
    if (str.length() >= max_length)
2300
2112
    {
2301
2113
      str.length(max_length-4);
2339
2151
    break;
2340
2152
  case HA_ERR_FOUND_DUPP_KEY:
2341
2153
  {
2342
 
    uint key_nr=get_dup_key(error);
 
2154
    uint32_t key_nr=get_dup_key(error);
2343
2155
    if ((int) key_nr >= 0)
2344
2156
    {
2345
2157
      print_keydup_error(key_nr, ER(ER_DUP_ENTRY_WITH_KEY_NAME));
2350
2162
  }
2351
2163
  case HA_ERR_FOREIGN_DUPLICATE_KEY:
2352
2164
  {
2353
 
    uint key_nr= get_dup_key(error);
 
2165
    uint32_t key_nr= get_dup_key(error);
2354
2166
    if ((int) key_nr >= 0)
2355
2167
    {
2356
 
      uint max_length;
 
2168
      uint32_t max_length;
2357
2169
      /* Write the key in the error message */
2358
2170
      char key[MAX_KEY_LENGTH];
2359
2171
      String str(key,sizeof(key),system_charset_info);
2452
2264
  case HA_ERR_DROP_INDEX_FK:
2453
2265
  {
2454
2266
    const char *ptr= "???";
2455
 
    uint key_nr= get_dup_key(error);
 
2267
    uint32_t key_nr= get_dup_key(error);
2456
2268
    if ((int) key_nr >= 0)
2457
2269
      ptr= table->key_info[key_nr].name;
2458
2270
    my_error(ER_DROP_INDEX_FK, MYF(0), ptr);
2554
2366
  return 0;
2555
2367
}
2556
2368
 
2557
 
 
2558
 
static bool update_frm_version(TABLE *table)
2559
 
{
2560
 
  char path[FN_REFLEN];
2561
 
  File file;
2562
 
  bool result= true;
2563
 
 
2564
 
  /*
2565
 
    No need to update frm version in case table was created or checked
2566
 
    by server with the same version. This also ensures that we do not
2567
 
    update frm version for temporary tables as this code doesn't support
2568
 
    temporary tables.
2569
 
  */
2570
 
  if (table->s->mysql_version == DRIZZLE_VERSION_ID)
2571
 
    return(0);
2572
 
 
2573
 
  strxmov(path, table->s->normalized_path.str, reg_ext, NullS);
2574
 
 
2575
 
  if ((file= my_open(path, O_RDWR|O_BINARY, MYF(MY_WME))) >= 0)
2576
 
  {
2577
 
    uchar version[4];
2578
 
    char *key= table->s->table_cache_key.str;
2579
 
    uint key_length= table->s->table_cache_key.length;
2580
 
    TABLE *entry;
2581
 
    HASH_SEARCH_STATE state;
2582
 
 
2583
 
    int4store(version, DRIZZLE_VERSION_ID);
2584
 
 
2585
 
    if (pwrite(file, (uchar*)version, 4, 51L) == 0)
2586
 
    {
2587
 
      result= false;
2588
 
      goto err;
2589
 
    }
2590
 
 
2591
 
    for (entry=(TABLE*) hash_first(&open_cache,(uchar*) key,key_length, &state);
2592
 
         entry;
2593
 
         entry= (TABLE*) hash_next(&open_cache,(uchar*) key,key_length, &state))
2594
 
      entry->s->mysql_version= DRIZZLE_VERSION_ID;
2595
 
  }
2596
 
err:
2597
 
  if (file >= 0)
2598
 
    VOID(my_close(file,MYF(MY_WME)));
2599
 
  return(result);
2600
 
}
2601
 
 
2602
 
 
2603
 
 
2604
2369
/**
2605
2370
  @return
2606
2371
    key if error because of duplicated keys
2607
2372
*/
2608
 
uint handler::get_dup_key(int error)
 
2373
uint32_t handler::get_dup_key(int error)
2609
2374
{
2610
2375
  table->file->errkey  = (uint) -1;
2611
2376
  if (error == HA_ERR_FOUND_DUPP_KEY || error == HA_ERR_FOREIGN_DUPLICATE_KEY ||
2679
2444
/**
2680
2445
  Performs checks upon the table.
2681
2446
 
2682
 
  @param thd                thread doing CHECK TABLE operation
 
2447
  @param session                thread doing CHECK Table operation
2683
2448
  @param check_opt          options from the parser
2684
2449
 
2685
2450
  @retval
2687
2452
  @retval
2688
2453
    HA_ADMIN_NEEDS_UPGRADE    Table has structures requiring upgrade
2689
2454
  @retval
2690
 
    HA_ADMIN_NEEDS_ALTER      Table has structures requiring ALTER TABLE
 
2455
    HA_ADMIN_NEEDS_ALTER      Table has structures requiring ALTER Table
2691
2456
  @retval
2692
2457
    HA_ADMIN_NOT_IMPLEMENTED
2693
2458
*/
2694
 
int handler::ha_check(THD *thd, HA_CHECK_OPT *check_opt)
 
2459
int handler::ha_check(Session *session, HA_CHECK_OPT *check_opt)
2695
2460
{
2696
2461
  int error;
2697
2462
 
2709
2474
    if (!error && (check_opt->sql_flags & TT_FOR_UPGRADE))
2710
2475
      return 0;
2711
2476
  }
2712
 
  if ((error= check(thd, check_opt)))
 
2477
  if ((error= check(session, check_opt)))
2713
2478
    return error;
2714
 
  return update_frm_version(table);
 
2479
  return HA_ADMIN_OK;
2715
2480
}
2716
2481
 
2717
2482
/**
2723
2488
void
2724
2489
handler::mark_trx_read_write()
2725
2490
{
2726
 
  Ha_trx_info *ha_info= &ha_thd()->ha_data[ht->slot].ha_info[0];
 
2491
  Ha_trx_info *ha_info= &ha_session()->ha_data[ht->slot].ha_info[0];
2727
2492
  /*
2728
2493
    When a storage engine method is called, the transaction must
2729
2494
    have been started, unless it's a DDL call, for which the
2734
2499
  */
2735
2500
  if (ha_info->is_started())
2736
2501
  {
2737
 
    assert(has_transactions());
2738
2502
    /*
2739
2503
      table_share can be NULL in ha_delete_table(). See implementation
2740
2504
      of standalone function ha_delete_table() in sql_base.cc.
2751
2515
  @sa handler::repair()
2752
2516
*/
2753
2517
 
2754
 
int handler::ha_repair(THD* thd, HA_CHECK_OPT* check_opt)
 
2518
int handler::ha_repair(Session* session, HA_CHECK_OPT* check_opt)
2755
2519
{
2756
2520
  int result;
2757
2521
 
2758
2522
  mark_trx_read_write();
2759
2523
 
2760
 
  if ((result= repair(thd, check_opt)))
 
2524
  if ((result= repair(session, check_opt)))
2761
2525
    return result;
2762
 
  return update_frm_version(table);
 
2526
  return HA_ADMIN_OK;
2763
2527
}
2764
2528
 
2765
2529
 
2770
2534
*/
2771
2535
 
2772
2536
int
2773
 
handler::ha_bulk_update_row(const uchar *old_data, uchar *new_data,
2774
 
                            uint *dup_key_found)
 
2537
handler::ha_bulk_update_row(const unsigned char *old_data, unsigned char *new_data,
 
2538
                            uint32_t *dup_key_found)
2775
2539
{
2776
2540
  mark_trx_read_write();
2777
2541
 
2816
2580
*/
2817
2581
 
2818
2582
int
2819
 
handler::ha_optimize(THD* thd, HA_CHECK_OPT* check_opt)
 
2583
handler::ha_optimize(Session* session, HA_CHECK_OPT* check_opt)
2820
2584
{
2821
2585
  mark_trx_read_write();
2822
2586
 
2823
 
  return optimize(thd, check_opt);
 
2587
  return optimize(session, check_opt);
2824
2588
}
2825
2589
 
2826
2590
 
2831
2595
*/
2832
2596
 
2833
2597
int
2834
 
handler::ha_analyze(THD* thd, HA_CHECK_OPT* check_opt)
 
2598
handler::ha_analyze(Session* session, HA_CHECK_OPT* check_opt)
2835
2599
{
2836
2600
  mark_trx_read_write();
2837
2601
 
2838
 
  return analyze(thd, check_opt);
 
2602
  return analyze(session, check_opt);
2839
2603
}
2840
2604
 
2841
2605
 
2846
2610
*/
2847
2611
 
2848
2612
bool
2849
 
handler::ha_check_and_repair(THD *thd)
 
2613
handler::ha_check_and_repair(Session *session)
2850
2614
{
2851
2615
  mark_trx_read_write();
2852
2616
 
2853
 
  return check_and_repair(thd);
 
2617
  return check_and_repair(session);
2854
2618
}
2855
2619
 
2856
2620
 
2861
2625
*/
2862
2626
 
2863
2627
int
2864
 
handler::ha_disable_indexes(uint mode)
 
2628
handler::ha_disable_indexes(uint32_t mode)
2865
2629
{
2866
2630
  mark_trx_read_write();
2867
2631
 
2876
2640
*/
2877
2641
 
2878
2642
int
2879
 
handler::ha_enable_indexes(uint mode)
 
2643
handler::ha_enable_indexes(uint32_t mode)
2880
2644
{
2881
2645
  mark_trx_read_write();
2882
2646
 
2968
2732
*/
2969
2733
 
2970
2734
int
2971
 
handler::ha_create(const char *name, TABLE *form, HA_CREATE_INFO *info)
 
2735
handler::ha_create(const char *name, Table *form, HA_CREATE_INFO *info)
2972
2736
{
2973
2737
  mark_trx_read_write();
2974
2738
 
2995
2759
/**
2996
2760
  Tell the storage engine that it is allowed to "disable transaction" in the
2997
2761
  handler. It is a hint that ACID is not required - it is used in NDB for
2998
 
  ALTER TABLE, for example, when data are copied to temporary table.
 
2762
  ALTER Table, for example, when data are copied to temporary table.
2999
2763
  A storage engine may treat this hint any way it likes. NDB for example
3000
2764
  starts to commit every now and then automatically.
3001
2765
  This hint can be safely ignored.
3002
2766
*/
3003
 
int ha_enable_transaction(THD *thd, bool on)
 
2767
int ha_enable_transaction(Session *session, bool on)
3004
2768
{
3005
2769
  int error=0;
3006
2770
 
3007
 
  if ((thd->transaction.on= on))
 
2771
  if ((session->transaction.on= on))
3008
2772
  {
3009
2773
    /*
3010
2774
      Now all storage engines should have transaction handling enabled.
3012
2776
      is an optimization hint that storage engine is free to ignore.
3013
2777
      So, let's commit an open transaction (if any) now.
3014
2778
    */
3015
 
    if (!(error= ha_commit_trans(thd, 0)))
3016
 
      error= end_trans(thd, COMMIT);
 
2779
    if (!(error= ha_commit_trans(session, 0)))
 
2780
      error= end_trans(session, COMMIT);
3017
2781
  }
3018
2782
  return(error);
3019
2783
}
3020
2784
 
3021
 
int handler::index_next_same(uchar *buf, const uchar *key, uint keylen)
 
2785
int handler::index_next_same(unsigned char *buf, const unsigned char *key, uint32_t keylen)
3022
2786
{
3023
2787
  int error;
3024
2788
  if (!(error=index_next(buf)))
3025
2789
  {
3026
2790
    my_ptrdiff_t ptrdiff= buf - table->record[0];
3027
 
    uchar *save_record_0= NULL;
 
2791
    unsigned char *save_record_0= NULL;
3028
2792
    KEY *key_info= NULL;
3029
2793
    KEY_PART_INFO *key_part;
3030
2794
    KEY_PART_INFO *key_part_end= NULL;
3081
2845
  @retval
3082
2846
   1  error
3083
2847
*/
3084
 
int ha_create_table(THD *thd, const char *path,
 
2848
int ha_create_table(Session *session, const char *path,
3085
2849
                    const char *db, const char *table_name,
3086
2850
                    HA_CREATE_INFO *create_info,
3087
2851
                    bool update_create_info)
3088
2852
{
3089
2853
  int error= 1;
3090
 
  TABLE table;
 
2854
  Table table;
3091
2855
  char name_buff[FN_REFLEN];
3092
2856
  const char *name;
3093
2857
  TABLE_SHARE share;
3094
 
  
3095
 
  init_tmp_table_share(thd, &share, db, 0, table_name, path);
3096
 
  if (open_table_def(thd, &share, 0) ||
3097
 
      open_table_from_share(thd, &share, "", 0, (uint) READ_ALL, 0, &table,
 
2858
 
 
2859
  init_tmp_table_share(session, &share, db, 0, table_name, path);
 
2860
  if (open_table_def(session, &share, 0) ||
 
2861
      open_table_from_share(session, &share, "", 0, (uint) READ_ALL, 0, &table,
3098
2862
                            OTM_CREATE))
3099
2863
    goto err;
3100
2864
 
3101
2865
  if (update_create_info)
3102
 
    update_create_info_from_table(create_info, &table);
 
2866
    table.updateCreateInfo(create_info);
3103
2867
 
3104
2868
  name= check_lowercase_names(table.file, share.path.str, name_buff);
3105
2869
 
3106
2870
  error= table.file->ha_create(name, &table, create_info);
3107
 
  VOID(closefrm(&table, 0));
 
2871
  closefrm(&table, 0);
3108
2872
  if (error)
3109
2873
  {
3110
 
    strxmov(name_buff, db, ".", table_name, NullS);
 
2874
    sprintf(name_buff,"%s.%s",db,table_name);
3111
2875
    my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), name_buff, error);
3112
2876
  }
3113
2877
err:
3115
2879
  return(error != 0);
3116
2880
}
3117
2881
 
3118
 
/**
3119
 
  Try to discover table from engine.
3120
 
 
3121
 
  @note
3122
 
    If found, write the frm file to disk.
3123
 
 
3124
 
  @retval
3125
 
  -1    Table did not exists
3126
 
  @retval
3127
 
   0    Table created ok
3128
 
  @retval
3129
 
   > 0  Error, table existed but could not be created
3130
 
*/
3131
 
int ha_create_table_from_engine(THD* thd, const char *db, const char *name)
3132
 
{
3133
 
  int error;
3134
 
  uchar *frmblob;
3135
 
  size_t frmlen;
3136
 
  char path[FN_REFLEN];
3137
 
  HA_CREATE_INFO create_info;
3138
 
  TABLE table;
3139
 
  TABLE_SHARE share;
3140
 
 
3141
 
  memset(&create_info, 0, sizeof(create_info));
3142
 
  if ((error= ha_discover(thd, db, name, &frmblob, &frmlen)))
3143
 
  {
3144
 
    /* Table could not be discovered and thus not created */
3145
 
    return(error);
3146
 
  }
3147
 
 
3148
 
  /*
3149
 
    Table exists in handler and could be discovered
3150
 
    frmblob and frmlen are set, write the frm to disk
3151
 
  */
3152
 
 
3153
 
  build_table_filename(path, FN_REFLEN-1, db, name, "", 0);
3154
 
  // Save the frm file
3155
 
  error= writefrm(path, frmblob, frmlen);
3156
 
  my_free(frmblob, MYF(0));
3157
 
  if (error)
3158
 
    return(2);
3159
 
 
3160
 
  init_tmp_table_share(thd, &share, db, 0, name, path);
3161
 
  if (open_table_def(thd, &share, 0))
3162
 
  {
3163
 
    return(3);
3164
 
  }
3165
 
  if (open_table_from_share(thd, &share, "" ,0, 0, 0, &table, OTM_OPEN))
3166
 
  {
3167
 
    free_table_share(&share);
3168
 
    return(3);
3169
 
  }
3170
 
 
3171
 
  update_create_info_from_table(&create_info, &table);
3172
 
  create_info.table_options|= HA_OPTION_CREATE_FROM_ENGINE;
3173
 
 
3174
 
  check_lowercase_names(table.file, path, path);
3175
 
  error=table.file->ha_create(path, &table, &create_info);
3176
 
  VOID(closefrm(&table, 1));
3177
 
 
3178
 
  return(error != 0);
3179
 
}
3180
 
 
3181
2882
void st_ha_check_opt::init()
3182
2883
{
3183
2884
  flags= sql_flags= 0;
3184
 
  sort_buffer_size = current_thd->variables.myisam_sort_buff_size;
 
2885
  sort_buffer_size = current_session->variables.myisam_sort_buff_size;
3185
2886
}
3186
2887
 
3187
2888
 
3205
2906
  {
3206
2907
    pthread_mutex_lock(&LOCK_global_system_variables);
3207
2908
    uint32_t tmp_buff_size= (uint32_t) key_cache->param_buff_size;
3208
 
    uint tmp_block_size= (uint) key_cache->param_block_size;
3209
 
    uint division_limit= key_cache->param_division_limit;
3210
 
    uint age_threshold=  key_cache->param_age_threshold;
 
2909
    uint32_t tmp_block_size= (uint) key_cache->param_block_size;
 
2910
    uint32_t division_limit= key_cache->param_division_limit;
 
2911
    uint32_t age_threshold=  key_cache->param_age_threshold;
3211
2912
    pthread_mutex_unlock(&LOCK_global_system_variables);
3212
2913
    return(!init_key_cache(key_cache,
3213
2914
                                tmp_block_size,
3228
2929
    pthread_mutex_lock(&LOCK_global_system_variables);
3229
2930
    long tmp_buff_size= (long) key_cache->param_buff_size;
3230
2931
    long tmp_block_size= (long) key_cache->param_block_size;
3231
 
    uint division_limit= key_cache->param_division_limit;
3232
 
    uint age_threshold=  key_cache->param_age_threshold;
 
2932
    uint32_t division_limit= key_cache->param_division_limit;
 
2933
    uint32_t age_threshold=  key_cache->param_age_threshold;
3233
2934
    pthread_mutex_unlock(&LOCK_global_system_variables);
3234
2935
    return(!resize_key_cache(key_cache, tmp_block_size,
3235
2936
                                  tmp_buff_size,
3247
2948
  if (key_cache->key_cache_inited)
3248
2949
  {
3249
2950
    pthread_mutex_lock(&LOCK_global_system_variables);
3250
 
    uint division_limit= key_cache->param_division_limit;
3251
 
    uint age_threshold=  key_cache->param_age_threshold;
 
2951
    uint32_t division_limit= key_cache->param_division_limit;
 
2952
    uint32_t age_threshold=  key_cache->param_age_threshold;
3252
2953
    pthread_mutex_unlock(&LOCK_global_system_variables);
3253
2954
    change_key_cache_param(key_cache, division_limit, age_threshold);
3254
2955
  }
3274
2975
  return 0;
3275
2976
}
3276
2977
 
3277
 
 
3278
 
/**
3279
 
  Try to discover one table from handler(s).
3280
 
 
3281
 
  @retval
3282
 
    -1   Table did not exists
3283
 
  @retval
3284
 
    0   OK. In this case *frmblob and *frmlen are set
3285
 
  @retval
3286
 
    >0   error.  frmblob and frmlen may not be set
3287
 
*/
3288
 
struct st_discover_args
3289
 
{
3290
 
  const char *db;
3291
 
  const char *name;
3292
 
  uchar **frmblob; 
3293
 
  size_t *frmlen;
3294
 
};
3295
 
 
3296
 
static bool discover_handlerton(THD *thd, plugin_ref plugin,
3297
 
                                void *arg)
3298
 
{
3299
 
  st_discover_args *vargs= (st_discover_args *)arg;
3300
 
  handlerton *hton= plugin_data(plugin, handlerton *);
3301
 
  if (hton->state == SHOW_OPTION_YES && hton->discover &&
3302
 
      (!(hton->discover(hton, thd, vargs->db, vargs->name, 
3303
 
                        vargs->frmblob, 
3304
 
                        vargs->frmlen))))
3305
 
    return true;
3306
 
 
3307
 
  return false;
3308
 
}
3309
 
 
3310
 
int ha_discover(THD *thd, const char *db, const char *name,
3311
 
                uchar **frmblob, size_t *frmlen)
3312
 
{
3313
 
  int error= -1; // Table does not exist in any handler
3314
 
  st_discover_args args= {db, name, frmblob, frmlen};
3315
 
 
3316
 
  if (is_prefix(name,tmp_file_prefix)) /* skip temporary tables */
3317
 
    return(error);
3318
 
 
3319
 
  if (plugin_foreach(thd, discover_handlerton,
3320
 
                 DRIZZLE_STORAGE_ENGINE_PLUGIN, &args))
3321
 
    error= 0;
3322
 
 
3323
 
  if (!error)
3324
 
    status_var_increment(thd->status_var.ha_discover_count);
3325
 
  return(error);
3326
 
}
3327
 
 
3328
 
 
3329
2978
/**
3330
2979
  Call this function in order to give the handler the possiblity
3331
2980
  to ask engine if there are any new tables that should be written to disk
3354
3003
  const char *db;
3355
3004
  const char *name;
3356
3005
  int err;
 
3006
  handlerton* hton;
3357
3007
};
3358
3008
 
3359
 
static bool table_exists_in_engine_handlerton(THD *thd, plugin_ref plugin,
 
3009
static bool table_exists_in_engine_handlerton(Session *session, plugin_ref plugin,
3360
3010
                                              void *arg)
3361
3011
{
3362
3012
  st_table_exists_in_engine_args *vargs= (st_table_exists_in_engine_args *)arg;
3365
3015
  int err= HA_ERR_NO_SUCH_TABLE;
3366
3016
 
3367
3017
  if (hton->state == SHOW_OPTION_YES && hton->table_exists_in_engine)
3368
 
    err = hton->table_exists_in_engine(hton, thd, vargs->db, vargs->name);
 
3018
    err = hton->table_exists_in_engine(hton, session, vargs->db, vargs->name);
3369
3019
 
3370
3020
  vargs->err = err;
3371
3021
  if (vargs->err == HA_ERR_TABLE_EXIST)
 
3022
  {
 
3023
    vargs->hton= hton;
3372
3024
    return true;
 
3025
  }
3373
3026
 
3374
3027
  return false;
3375
3028
}
3376
3029
 
3377
 
int ha_table_exists_in_engine(THD* thd, const char* db, const char* name)
 
3030
int ha_table_exists_in_engine(Session* session,
 
3031
                              const char* db, const char* name,
 
3032
                              handlerton **hton)
3378
3033
{
3379
 
  st_table_exists_in_engine_args args= {db, name, HA_ERR_NO_SUCH_TABLE};
3380
 
  plugin_foreach(thd, table_exists_in_engine_handlerton,
 
3034
  st_table_exists_in_engine_args args= {db, name, HA_ERR_NO_SUCH_TABLE, NULL};
 
3035
  plugin_foreach(session, table_exists_in_engine_handlerton,
3381
3036
                 DRIZZLE_STORAGE_ENGINE_PLUGIN, &args);
 
3037
 
 
3038
  if(args.err==HA_ERR_NO_SUCH_TABLE)
 
3039
  {
 
3040
    /* Default way of knowing if a table exists. (checking .frm exists) */
 
3041
 
 
3042
    char path[FN_REFLEN];
 
3043
    build_table_filename(path, sizeof(path),
 
3044
                         db, name, ".frm", 0);
 
3045
    if (!access(path, F_OK))
 
3046
      args.err= HA_ERR_TABLE_EXIST;
 
3047
    else
 
3048
      args.err= HA_ERR_NO_SUCH_TABLE;
 
3049
 
 
3050
    enum legacy_db_type table_type;
 
3051
    if(args.err==HA_ERR_TABLE_EXIST && mysql_frm_type(path, &table_type)==0)
 
3052
    {
 
3053
      args.hton= ha_resolve_by_legacy_type(session, table_type);
 
3054
    }
 
3055
  }
 
3056
 
 
3057
  if(hton)
 
3058
    *hton= args.hton;
 
3059
 
3382
3060
  return(args.err);
3383
3061
}
3384
3062
 
3403
3081
    Estimated cost of 'index only' scan
3404
3082
*/
3405
3083
 
3406
 
double handler::index_only_read_time(uint keynr, double records)
 
3084
double handler::index_only_read_time(uint32_t keynr, double records)
3407
3085
{
3408
3086
  double read_time;
3409
 
  uint keys_per_block= (stats.block_size/2/
 
3087
  uint32_t keys_per_block= (stats.block_size/2/
3410
3088
                        (table->key_info[keynr].key_length + ref_length) + 1);
3411
3089
  read_time=((double) (records + keys_per_block-1) /
3412
3090
             (double) keys_per_block);
3437
3115
 
3438
3116
  @note
3439
3117
    This method (or an overriding one in a derived class) must check for
3440
 
    thd->killed and return HA_POS_ERROR if it is not zero. This is required
 
3118
    session->killed and return HA_POS_ERROR if it is not zero. This is required
3441
3119
    for a user to be able to interrupt the calculation by killing the
3442
3120
    connection/query.
3443
3121
 
3450
3128
*/
3451
3129
 
3452
3130
ha_rows
3453
 
handler::multi_range_read_info_const(uint keyno, RANGE_SEQ_IF *seq,
 
3131
handler::multi_range_read_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
3454
3132
                                     void *seq_init_param,
3455
 
                                     uint n_ranges_arg __attribute__((unused)),
3456
 
                                     uint *bufsz, uint *flags, COST_VECT *cost)
 
3133
                                     uint32_t n_ranges_arg __attribute__((unused)),
 
3134
                                     uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
3457
3135
{
3458
3136
  KEY_MULTI_RANGE range;
3459
3137
  range_seq_t seq_it;
3460
3138
  ha_rows rows, total_rows= 0;
3461
 
  uint n_ranges=0;
3462
 
  THD *thd= current_thd;
3463
 
  
 
3139
  uint32_t n_ranges=0;
 
3140
  Session *session= current_session;
 
3141
 
3464
3142
  /* Default MRR implementation doesn't need buffer */
3465
3143
  *bufsz= 0;
3466
3144
 
3467
3145
  seq_it= seq->init(seq_init_param, n_ranges, *flags);
3468
3146
  while (!seq->next(seq_it, &range))
3469
3147
  {
3470
 
    if (unlikely(thd->killed != 0))
 
3148
    if (unlikely(session->killed != 0))
3471
3149
      return HA_POS_ERROR;
3472
 
    
 
3150
 
3473
3151
    n_ranges++;
3474
3152
    key_range *min_endp, *max_endp;
3475
3153
    {
3480
3158
      rows= 1; /* there can be at most one row */
3481
3159
    else
3482
3160
    {
3483
 
      if (HA_POS_ERROR == (rows= this->records_in_range(keyno, min_endp, 
 
3161
      if (HA_POS_ERROR == (rows= this->records_in_range(keyno, min_endp,
3484
3162
                                                        max_endp)))
3485
3163
      {
3486
3164
        /* Can't scan one range => can't do MRR scan at all */
3490
3168
    }
3491
3169
    total_rows += rows;
3492
3170
  }
3493
 
  
 
3171
 
3494
3172
  if (total_rows != HA_POS_ERROR)
3495
3173
  {
3496
3174
    /* The following calculation is the same as in multi_range_read_info(): */
3541
3219
    other Error or can't perform the requested scan
3542
3220
*/
3543
3221
 
3544
 
int handler::multi_range_read_info(uint keyno, uint n_ranges, uint n_rows,
3545
 
                                   uint *bufsz, uint *flags, COST_VECT *cost)
 
3222
int handler::multi_range_read_info(uint32_t keyno, uint32_t n_ranges, uint32_t n_rows,
 
3223
                                   uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
3546
3224
{
3547
3225
  *bufsz= 0; /* Default implementation doesn't need a buffer */
3548
3226
 
3563
3241
/**
3564
3242
  Initialize the MRR scan
3565
3243
 
3566
 
  Initialize the MRR scan. This function may do heavyweight scan 
 
3244
  Initialize the MRR scan. This function may do heavyweight scan
3567
3245
  initialization like row prefetching/sorting/etc (NOTE: but better not do
3568
3246
  it here as we may not need it, e.g. if we never satisfy WHERE clause on
3569
3247
  previous tables. For many implementations it would be natural to do such
3570
3248
  initializations in the first multi_read_range_next() call)
3571
3249
 
3572
3250
  mode is a combination of the following flags: HA_MRR_SORTED,
3573
 
  HA_MRR_INDEX_ONLY, HA_MRR_NO_ASSOCIATION 
 
3251
  HA_MRR_INDEX_ONLY, HA_MRR_NO_ASSOCIATION
3574
3252
 
3575
3253
  @param seq             Range sequence to be traversed
3576
3254
  @param seq_init_param  First parameter for seq->init()
3582
3260
    One must have called index_init() before calling this function. Several
3583
3261
    multi_range_read_init() calls may be made in course of one query.
3584
3262
 
3585
 
    Until WL#2623 is done (see its text, section 3.2), the following will 
 
3263
    Until WL#2623 is done (see its text, section 3.2), the following will
3586
3264
    also hold:
3587
3265
    The caller will guarantee that if "seq->init == mrr_ranges_array_init"
3588
3266
    then seq_init_param is an array of n_ranges KEY_MULTI_RANGE structures.
3589
3267
    This property will only be used by NDB handler until WL#2623 is done.
3590
 
     
 
3268
 
3591
3269
    Buffer memory management is done according to the following scenario:
3592
3270
    The caller allocates the buffer and provides it to the callee by filling
3593
3271
    the members of HANDLER_BUFFER structure.
3603
3281
 
3604
3282
int
3605
3283
handler::multi_range_read_init(RANGE_SEQ_IF *seq_funcs, void *seq_init_param,
3606
 
                               uint n_ranges, uint mode,
 
3284
                               uint32_t n_ranges, uint32_t mode,
3607
3285
                               HANDLER_BUFFER *buf __attribute__((unused)))
3608
3286
{
3609
3287
  mrr_iter= seq_funcs->init(seq_init_param, n_ranges, mode);
3682
3360
 
3683
3361
 
3684
3362
/* **************************************************************************
3685
 
 * DS-MRR implementation 
 
3363
 * DS-MRR implementation
3686
3364
 ***************************************************************************/
3687
3365
 
3688
3366
/**
3705
3383
 
3706
3384
int DsMrr_impl::dsmrr_init(handler *h, KEY *key,
3707
3385
                           RANGE_SEQ_IF *seq_funcs, void *seq_init_param,
3708
 
                           uint n_ranges, uint mode, HANDLER_BUFFER *buf)
 
3386
                           uint32_t n_ranges, uint32_t mode, HANDLER_BUFFER *buf)
3709
3387
{
3710
 
  uint elem_size;
3711
 
  uint keyno;
 
3388
  uint32_t elem_size;
 
3389
  uint32_t keyno;
3712
3390
  Item *pushed_cond= NULL;
3713
3391
  handler *new_h2;
3714
3392
  keyno= h->active_index;
3725
3403
 
3726
3404
  is_mrr_assoc= !test(mode & HA_MRR_NO_ASSOCIATION);
3727
3405
  rowids_buf_end= buf->buffer_end;
3728
 
  
 
3406
 
3729
3407
  elem_size= h->ref_length + (int)is_mrr_assoc * sizeof(void*);
3730
 
  rowids_buf_last= rowids_buf + 
 
3408
  rowids_buf_last= rowids_buf +
3731
3409
                      ((rowids_buf_end - rowids_buf)/ elem_size)*
3732
3410
                      elem_size;
3733
3411
  rowids_buf_end= rowids_buf_last;
3734
3412
 
3735
3413
  /* Create a separate handler object to do rndpos() calls. */
3736
 
  THD *thd= current_thd;
3737
 
  if (!(new_h2= h->clone(thd->mem_root)) || 
3738
 
      new_h2->ha_external_lock(thd, F_RDLCK))
 
3414
  Session *session= current_session;
 
3415
  if (!(new_h2= h->clone(session->mem_root)) ||
 
3416
      new_h2->ha_external_lock(session, F_RDLCK))
3739
3417
  {
3740
3418
    delete new_h2;
3741
3419
    return(1);
3753
3431
  table->prepare_for_position();
3754
3432
  new_h2->extra(HA_EXTRA_KEYREAD);
3755
3433
 
3756
 
  if (h2->ha_index_init(keyno, false) || 
 
3434
  if (h2->ha_index_init(keyno, false) ||
3757
3435
      h2->handler::multi_range_read_init(seq_funcs, seq_init_param, n_ranges,
3758
3436
                                         mode, buf))
3759
3437
    goto error;
3760
3438
  use_default_impl= false;
3761
 
  
 
3439
 
3762
3440
  if (pushed_cond)
3763
3441
    h2->idx_cond_push(keyno, pushed_cond);
3764
3442
  if (dsmrr_fill_buffer(new_h2))
3768
3446
    If the above call has scanned through all intervals in *seq, then
3769
3447
    adjust *buf to indicate that the remaining buffer space will not be used.
3770
3448
  */
3771
 
  if (dsmrr_eof) 
 
3449
  if (dsmrr_eof)
3772
3450
    buf->end_of_used_area= rowids_buf_last;
3773
3451
 
3774
3452
  if (h->ha_rnd_init(false))
3775
3453
    goto error;
3776
 
  
 
3454
 
3777
3455
  return(0);
3778
3456
error:
3779
3457
  h2->ha_index_or_rnd_end();
3780
 
  h2->ha_external_lock(thd, F_UNLCK);
 
3458
  h2->ha_external_lock(session, F_UNLCK);
3781
3459
  h2->close();
3782
3460
  delete h2;
3783
3461
  return(1);
3788
3466
{
3789
3467
  if (h2)
3790
3468
  {
3791
 
    h2->ha_external_lock(current_thd, F_UNLCK);
 
3469
    h2->ha_external_lock(current_session, F_UNLCK);
3792
3470
    h2->close();
3793
3471
    delete h2;
3794
3472
    h2= NULL;
3798
3476
}
3799
3477
 
3800
3478
 
3801
 
static int rowid_cmp(void *h, uchar *a, uchar *b)
 
3479
static int rowid_cmp(void *h, unsigned char *a, unsigned char *b)
3802
3480
{
3803
3481
  return ((handler*)h)->cmp_ref(a, b);
3804
3482
}
3808
3486
  DS-MRR: Fill the buffer with rowids and sort it by rowid
3809
3487
 
3810
3488
  {This is an internal function of DiskSweep MRR implementation}
3811
 
  Scan the MRR ranges and collect ROWIDs (or {ROWID, range_id} pairs) into 
3812
 
  buffer. When the buffer is full or scan is completed, sort the buffer by 
 
3489
  Scan the MRR ranges and collect ROWIDs (or {ROWID, range_id} pairs) into
 
3490
  buffer. When the buffer is full or scan is completed, sort the buffer by
3813
3491
  rowid and return.
3814
 
  
3815
 
  The function assumes that rowids buffer is empty when it is invoked. 
3816
 
  
 
3492
 
 
3493
  The function assumes that rowids buffer is empty when it is invoked.
 
3494
 
3817
3495
  @param h  Table handler
3818
3496
 
3819
3497
  @retval 0      OK, the next portion of rowids is in the buffer,
3827
3505
  int res = 0;
3828
3506
 
3829
3507
  rowids_buf_cur= rowids_buf;
3830
 
  while ((rowids_buf_cur < rowids_buf_end) && 
 
3508
  while ((rowids_buf_cur < rowids_buf_end) &&
3831
3509
         !(res= h2->handler::multi_range_read_next(&range_info)))
3832
3510
  {
3833
3511
    /* Put rowid, or {rowid, range_id} pair into the buffer */
3843
3521
  }
3844
3522
 
3845
3523
  if (res && res != HA_ERR_END_OF_FILE)
3846
 
    return(res); 
 
3524
    return(res);
3847
3525
  dsmrr_eof= test(res == HA_ERR_END_OF_FILE);
3848
3526
 
3849
3527
  /* Sort the buffer contents by rowid */
3850
 
  uint elem_size= h->ref_length + (int)is_mrr_assoc * sizeof(void*);
3851
 
  uint n_rowids= (rowids_buf_cur - rowids_buf) / elem_size;
3852
 
  
 
3528
  uint32_t elem_size= h->ref_length + (int)is_mrr_assoc * sizeof(void*);
 
3529
  uint32_t n_rowids= (rowids_buf_cur - rowids_buf) / elem_size;
 
3530
 
3853
3531
  my_qsort2(rowids_buf, n_rowids, elem_size, (qsort2_cmp)rowid_cmp,
3854
3532
            (void*)h);
3855
3533
  rowids_buf_last= rowids_buf_cur;
3865
3543
int DsMrr_impl::dsmrr_next(handler *h, char **range_info)
3866
3544
{
3867
3545
  int res;
3868
 
  
 
3546
 
3869
3547
  if (use_default_impl)
3870
3548
    return h->handler::multi_range_read_next(range_info);
3871
 
    
 
3549
 
3872
3550
  if (rowids_buf_cur == rowids_buf_last)
3873
3551
  {
3874
3552
    if (dsmrr_eof)
3880
3558
    if (res)
3881
3559
      goto end;
3882
3560
  }
3883
 
  
 
3561
 
3884
3562
  /* Return EOF if there are no rowids in the buffer after re-fill attempt */
3885
3563
  if (rowids_buf_cur == rowids_buf_last)
3886
3564
  {
3906
3584
/**
3907
3585
  DS-MRR implementation: multi_range_read_info() function
3908
3586
*/
3909
 
int DsMrr_impl::dsmrr_info(uint keyno, uint n_ranges, uint rows, uint *bufsz,
3910
 
                           uint *flags, COST_VECT *cost)
3911
 
{  
 
3587
int DsMrr_impl::dsmrr_info(uint32_t keyno, uint32_t n_ranges, uint32_t rows, uint32_t *bufsz,
 
3588
                           uint32_t *flags, COST_VECT *cost)
 
3589
{
3912
3590
  int res;
3913
 
  uint def_flags= *flags;
3914
 
  uint def_bufsz= *bufsz;
 
3591
  uint32_t def_flags= *flags;
 
3592
  uint32_t def_bufsz= *bufsz;
3915
3593
 
3916
3594
  /* Get cost/flags/mem_usage of default MRR implementation */
3917
3595
  res= h->handler::multi_range_read_info(keyno, n_ranges, rows, &def_bufsz,
3918
3596
                                         &def_flags, cost);
3919
3597
  assert(!res);
3920
3598
 
3921
 
  if ((*flags & HA_MRR_USE_DEFAULT_IMPL) || 
 
3599
  if ((*flags & HA_MRR_USE_DEFAULT_IMPL) ||
3922
3600
      choose_mrr_impl(keyno, rows, &def_flags, &def_bufsz, cost))
3923
3601
  {
3924
3602
    /* Default implementation is choosen */
3933
3611
  DS-MRR Implementation: multi_range_read_info_const() function
3934
3612
*/
3935
3613
 
3936
 
ha_rows DsMrr_impl::dsmrr_info_const(uint keyno, RANGE_SEQ_IF *seq,
3937
 
                                 void *seq_init_param, uint n_ranges, 
3938
 
                                 uint *bufsz, uint *flags, COST_VECT *cost)
 
3614
ha_rows DsMrr_impl::dsmrr_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
 
3615
                                 void *seq_init_param, uint32_t n_ranges,
 
3616
                                 uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
3939
3617
{
3940
3618
  ha_rows rows;
3941
 
  uint def_flags= *flags;
3942
 
  uint def_bufsz= *bufsz;
 
3619
  uint32_t def_flags= *flags;
 
3620
  uint32_t def_bufsz= *bufsz;
3943
3621
  /* Get cost/flags/mem_usage of default MRR implementation */
3944
3622
  rows= h->handler::multi_range_read_info_const(keyno, seq, seq_init_param,
3945
 
                                                n_ranges, &def_bufsz, 
 
3623
                                                n_ranges, &def_bufsz,
3946
3624
                                                &def_flags, cost);
3947
3625
  if (rows == HA_POS_ERROR)
3948
3626
  {
3987
3665
  @retval false  No
3988
3666
*/
3989
3667
 
3990
 
bool DsMrr_impl::key_uses_partial_cols(uint keyno)
 
3668
bool DsMrr_impl::key_uses_partial_cols(uint32_t keyno)
3991
3669
{
3992
3670
  KEY_PART_INFO *kp= table->key_info[keyno].key_part;
3993
3671
  KEY_PART_INFO *kp_end= kp + table->key_info[keyno].key_parts;
4023
3701
  @retval false  DS-MRR implementation should be used
4024
3702
*/
4025
3703
 
4026
 
bool DsMrr_impl::choose_mrr_impl(uint keyno, ha_rows rows, uint *flags,
4027
 
                                 uint *bufsz, COST_VECT *cost)
 
3704
bool DsMrr_impl::choose_mrr_impl(uint32_t keyno, ha_rows rows, uint32_t *flags,
 
3705
                                 uint32_t *bufsz, COST_VECT *cost)
4028
3706
{
4029
3707
  COST_VECT dsmrr_cost;
4030
3708
  bool res;
4031
 
  THD *thd= current_thd;
4032
 
  if ((thd->variables.optimizer_use_mrr == 2) || 
 
3709
  Session *session= current_session;
 
3710
  if ((session->variables.optimizer_use_mrr == 2) ||
4033
3711
      (*flags & HA_MRR_INDEX_ONLY) || (*flags & HA_MRR_SORTED) ||
4034
 
      (keyno == table->s->primary_key && 
4035
 
       h->primary_key_is_clustered()) || 
 
3712
      (keyno == table->s->primary_key &&
 
3713
       h->primary_key_is_clustered()) ||
4036
3714
       key_uses_partial_cols(keyno))
4037
3715
  {
4038
3716
    /* Use the default implementation */
4039
3717
    *flags |= HA_MRR_USE_DEFAULT_IMPL;
4040
3718
    return true;
4041
3719
  }
4042
 
  
4043
 
  uint add_len= table->key_info[keyno].key_length + h->ref_length; 
 
3720
 
 
3721
  uint32_t add_len= table->key_info[keyno].key_length + h->ref_length;
4044
3722
  *bufsz -= add_len;
4045
3723
  if (get_disk_sweep_mrr_cost(keyno, rows, *flags, bufsz, &dsmrr_cost))
4046
3724
    return true;
4047
3725
  *bufsz += add_len;
4048
 
  
 
3726
 
4049
3727
  bool force_dsmrr;
4050
 
  /* 
 
3728
  /*
4051
3729
    If @@optimizer_use_mrr==force, then set cost of DS-MRR to be minimum of
4052
3730
    DS-MRR and Default implementations cost. This allows one to force use of
4053
3731
    DS-MRR whenever it is applicable without affecting other cost-based
4054
3732
    choices.
4055
3733
  */
4056
 
  if ((force_dsmrr= (thd->variables.optimizer_use_mrr == 1)) &&
 
3734
  if ((force_dsmrr= (session->variables.optimizer_use_mrr == 1)) &&
4057
3735
      dsmrr_cost.total_cost() > cost->total_cost())
4058
3736
    dsmrr_cost= *cost;
4059
3737
 
4073
3751
}
4074
3752
 
4075
3753
 
4076
 
static void get_sort_and_sweep_cost(TABLE *table, ha_rows nrows, COST_VECT *cost);
 
3754
static void get_sort_and_sweep_cost(Table *table, ha_rows nrows, COST_VECT *cost);
4077
3755
 
4078
3756
 
4079
3757
/**
4090
3768
                 for even 1 rowid)
4091
3769
*/
4092
3770
 
4093
 
bool DsMrr_impl::get_disk_sweep_mrr_cost(uint keynr, ha_rows rows, uint flags,
4094
 
                                         uint *buffer_size, COST_VECT *cost)
 
3771
bool DsMrr_impl::get_disk_sweep_mrr_cost(uint32_t keynr, ha_rows rows, uint32_t flags,
 
3772
                                         uint32_t *buffer_size, COST_VECT *cost)
4095
3773
{
4096
3774
  uint32_t max_buff_entries, elem_size;
4097
3775
  ha_rows rows_in_full_step, rows_in_last_step;
4098
 
  uint n_full_steps;
 
3776
  uint32_t n_full_steps;
4099
3777
  double index_read_cost;
4100
3778
 
4101
3779
  elem_size= h->ref_length + sizeof(void*) * (!test(flags & HA_MRR_NO_ASSOCIATION));
4106
3784
 
4107
3785
  /* Number of iterations we'll make with full buffer */
4108
3786
  n_full_steps= (uint)floor(rows2double(rows) / max_buff_entries);
4109
 
  
4110
 
  /* 
4111
 
    Get numbers of rows we'll be processing in 
4112
 
     - non-last sweep, with full buffer 
 
3787
 
 
3788
  /*
 
3789
    Get numbers of rows we'll be processing in
 
3790
     - non-last sweep, with full buffer
4113
3791
     - last iteration, with non-full buffer
4114
3792
  */
4115
3793
  rows_in_full_step= max_buff_entries;
4116
3794
  rows_in_last_step= rows % max_buff_entries;
4117
 
  
 
3795
 
4118
3796
  /* Adjust buffer size if we expect to use only part of the buffer */
4119
3797
  if (n_full_steps)
4120
3798
  {
4124
3802
  else
4125
3803
  {
4126
3804
    cost->zero();
4127
 
    *buffer_size= max((ulong)*buffer_size, 
4128
 
                      (size_t)(1.2*rows_in_last_step) * elem_size + 
 
3805
    *buffer_size= cmax((ulong)*buffer_size,
 
3806
                      (size_t)(1.2*rows_in_last_step) * elem_size +
4129
3807
                      h->ref_length + table->key_info[keynr].key_length);
4130
3808
  }
4131
 
  
 
3809
 
4132
3810
  COST_VECT last_step_cost;
4133
3811
  get_sort_and_sweep_cost(table, rows_in_last_step, &last_step_cost);
4134
3812
  cost->add(&last_step_cost);
4135
 
 
 
3813
 
4136
3814
  if (n_full_steps != 0)
4137
3815
    cost->mem_cost= *buffer_size;
4138
3816
  else
4139
3817
    cost->mem_cost= (double)rows_in_last_step * elem_size;
4140
 
  
 
3818
 
4141
3819
  /* Total cost of all index accesses */
4142
3820
  index_read_cost= h->index_only_read_time(keynr, (double)rows);
4143
3821
  cost->add_io(index_read_cost, 1 /* Random seeks */);
4145
3823
}
4146
3824
 
4147
3825
 
4148
 
/* 
 
3826
/*
4149
3827
  Get cost of one sort-and-sweep step
4150
3828
 
4151
3829
  SYNOPSIS
4160
3838
     - read #nrows records from table in a sweep.
4161
3839
*/
4162
3840
 
4163
 
static 
4164
 
void get_sort_and_sweep_cost(TABLE *table, ha_rows nrows, COST_VECT *cost)
 
3841
static
 
3842
void get_sort_and_sweep_cost(Table *table, ha_rows nrows, COST_VECT *cost)
4165
3843
{
4166
3844
  if (nrows)
4167
3845
  {
4194
3872
  Time to move the disk head is proportional to head travel distance.
4195
3873
 
4196
3874
  Time to wait for the plate to rotate depends on whether the disk head
4197
 
  was moved or not. 
 
3875
  was moved or not.
4198
3876
 
4199
3877
  If disk head wasn't moved, the wait time is proportional to distance
4200
3878
  between the previous block and the block we're reading.
4205
3883
 
4206
3884
  Our cost units are "random disk seeks". The cost of random disk seek is
4207
3885
  actually not a constant, it depends one range of cylinders we're going
4208
 
  to access. We make it constant by introducing a fuzzy concept of "typical 
 
3886
  to access. We make it constant by introducing a fuzzy concept of "typical
4209
3887
  datafile length" (it's fuzzy as it's hard to tell whether it should
4210
3888
  include index file, temp.tables etc). Then random seek cost is:
4211
3889
 
4220
3898
  @param cost         OUT  The cost.
4221
3899
*/
4222
3900
 
4223
 
void get_sweep_read_cost(TABLE *table, ha_rows nrows, bool interrupted, 
 
3901
void get_sweep_read_cost(Table *table, ha_rows nrows, bool interrupted,
4224
3902
                         COST_VECT *cost)
4225
3903
{
4226
3904
  cost->zero();
4299
3977
                           start_key->keypart_map,
4300
3978
                           start_key->flag);
4301
3979
  if (result)
4302
 
    return((result == HA_ERR_KEY_NOT_FOUND) 
 
3980
    return((result == HA_ERR_KEY_NOT_FOUND)
4303
3981
                ? HA_ERR_END_OF_FILE
4304
3982
                : result);
4305
3983
 
4381
4059
  return cmp;
4382
4060
}
4383
4061
 
4384
 
int handler::index_read_idx_map(uchar * buf, uint index, const uchar * key,
 
4062
int handler::index_read_idx_map(unsigned char * buf, uint32_t index,
 
4063
                                const unsigned char * key,
4385
4064
                                key_part_map keypart_map,
4386
4065
                                enum ha_rkey_function find_flag)
4387
4066
{
4406
4085
  @retval
4407
4086
    pointer             pointer to TYPELIB structure
4408
4087
*/
4409
 
static bool exts_handlerton(THD *unused __attribute__((unused)),
 
4088
static bool exts_handlerton(Session *unused __attribute__((unused)),
4410
4089
                            plugin_ref plugin,
4411
4090
                            void *arg)
4412
4091
{
4414
4093
  handlerton *hton= plugin_data(plugin, handlerton *);
4415
4094
  handler *file;
4416
4095
  if (hton->state == SHOW_OPTION_YES && hton->create &&
4417
 
      (file= hton->create(hton, (TABLE_SHARE*) 0, current_thd->mem_root)))
 
4096
      (file= hton->create(hton, (TABLE_SHARE*) 0, current_session->mem_root)))
4418
4097
  {
4419
4098
    List_iterator_fast<char> it(*found_exts);
4420
4099
    const char **ext, *old_ext;
4448
4127
    plugin_foreach(NULL, exts_handlerton,
4449
4128
                   DRIZZLE_STORAGE_ENGINE_PLUGIN, &found_exts);
4450
4129
 
4451
 
    ext= (const char **) my_once_alloc(sizeof(char *)*
4452
 
                                       (found_exts.elements+1),
4453
 
                                       MYF(MY_WME | MY_FAE));
 
4130
    ext= (const char **) malloc(sizeof(char *)*
 
4131
                                (found_exts.elements+1));
 
4132
                              
4454
4133
 
4455
4134
    assert(ext != 0);
4456
4135
    known_extensions.count= found_exts.elements;
4465
4144
}
4466
4145
 
4467
4146
 
4468
 
static bool stat_print(THD *thd, const char *type, uint type_len,
4469
 
                       const char *file, uint file_len,
4470
 
                       const char *status, uint status_len)
 
4147
static bool stat_print(Session *session, const char *type, uint32_t type_len,
 
4148
                       const char *file, uint32_t file_len,
 
4149
                       const char *status, uint32_t status_len)
4471
4150
{
4472
 
  Protocol *protocol= thd->protocol;
 
4151
  Protocol *protocol= session->protocol;
4473
4152
  protocol->prepare_for_resend();
4474
4153
  protocol->store(type, type_len, system_charset_info);
4475
4154
  protocol->store(file, file_len, system_charset_info);
4479
4158
  return false;
4480
4159
}
4481
4160
 
4482
 
bool ha_show_status(THD *thd, handlerton *db_type, enum ha_stat_type stat)
 
4161
bool ha_show_status(Session *session, handlerton *db_type, enum ha_stat_type stat)
4483
4162
{
4484
4163
  List<Item> field_list;
4485
 
  Protocol *protocol= thd->protocol;
 
4164
  Protocol *protocol= session->protocol;
4486
4165
  bool result;
4487
4166
 
4488
4167
  field_list.push_back(new Item_empty_string("Type",10));
4494
4173
    return true;
4495
4174
 
4496
4175
  result= db_type->show_status &&
4497
 
    db_type->show_status(db_type, thd, stat_print, stat) ? 1 : 0;
 
4176
    db_type->show_status(db_type, session, stat_print, stat) ? 1 : 0;
4498
4177
 
4499
4178
  if (!result)
4500
 
    my_eof(thd);
 
4179
    my_eof(session);
4501
4180
  return result;
4502
4181
}
4503
4182
 
4514
4193
  - table is not mysql.event
4515
4194
*/
4516
4195
 
4517
 
static bool check_table_binlog_row_based(THD *thd, TABLE *table)
4518
 
{
4519
 
  if (table->s->cached_row_logging_check == -1)
4520
 
  {
4521
 
    int const check(table->s->tmp_table == NO_TMP_TABLE &&
4522
 
                    binlog_filter->db_ok(table->s->db.str));
4523
 
    table->s->cached_row_logging_check= check;
4524
 
  }
4525
 
 
4526
 
  assert(table->s->cached_row_logging_check == 0 ||
4527
 
              table->s->cached_row_logging_check == 1);
4528
 
 
4529
 
  return (thd->current_stmt_binlog_row_based &&
4530
 
          table->s->cached_row_logging_check &&
4531
 
          (thd->options & OPTION_BIN_LOG) &&
4532
 
          mysql_bin_log.is_open());
4533
 
}
4534
 
 
4535
 
 
4536
 
/**
4537
 
   Write table maps for all (manually or automatically) locked tables
4538
 
   to the binary log.
4539
 
 
4540
 
   This function will generate and write table maps for all tables
4541
 
   that are locked by the thread 'thd'.  Either manually locked
4542
 
   (stored in THD::locked_tables) and automatically locked (stored
4543
 
   in THD::lock) are considered.
4544
 
 
4545
 
   @param thd     Pointer to THD structure
4546
 
 
4547
 
   @retval 0   All OK
4548
 
   @retval 1   Failed to write all table maps
4549
 
 
4550
 
   @sa
4551
 
       THD::lock
4552
 
       THD::locked_tables
4553
 
*/
4554
 
 
4555
 
static int write_locked_table_maps(THD *thd)
4556
 
{
4557
 
  if (thd->get_binlog_table_maps() == 0)
4558
 
  {
4559
 
    DRIZZLE_LOCK *locks[3];
4560
 
    locks[0]= thd->extra_lock;
4561
 
    locks[1]= thd->lock;
4562
 
    locks[2]= thd->locked_tables;
4563
 
    for (uint i= 0 ; i < sizeof(locks)/sizeof(*locks) ; ++i )
4564
 
    {
4565
 
      DRIZZLE_LOCK const *const lock= locks[i];
4566
 
      if (lock == NULL)
4567
 
        continue;
4568
 
 
4569
 
      TABLE **const end_ptr= lock->table + lock->table_count;
4570
 
      for (TABLE **table_ptr= lock->table ; 
4571
 
           table_ptr != end_ptr ;
4572
 
           ++table_ptr)
4573
 
      {
4574
 
        TABLE *const table= *table_ptr;
4575
 
        if (table->current_lock == F_WRLCK &&
4576
 
            check_table_binlog_row_based(thd, table))
4577
 
        {
4578
 
          int const has_trans= table->file->has_transactions();
4579
 
          int const error= thd->binlog_write_table_map(table, has_trans);
4580
 
          /*
4581
 
            If an error occurs, it is the responsibility of the caller to
4582
 
            roll back the transaction.
4583
 
          */
4584
 
          if (unlikely(error))
4585
 
            return(1);
4586
 
        }
4587
 
      }
4588
 
    }
4589
 
  }
4590
 
  return(0);
4591
 
}
4592
 
 
4593
 
 
4594
 
typedef bool Log_func(THD*, TABLE*, bool, const uchar*, const uchar*);
4595
 
 
4596
 
static int binlog_log_row(TABLE* table,
4597
 
                          const uchar *before_record,
4598
 
                          const uchar *after_record,
4599
 
                          Log_func *log_func)
4600
 
{
4601
 
  if (table->no_replicate)
4602
 
    return 0;
4603
 
  bool error= 0;
4604
 
  THD *const thd= table->in_use;
4605
 
 
4606
 
  if (check_table_binlog_row_based(thd, table))
4607
 
  {
 
4196
static bool binlog_log_row(Table* table,
 
4197
                           const unsigned char *before_record,
 
4198
                           const unsigned char *after_record)
 
4199
{
 
4200
  bool error= false;
 
4201
  Session *const session= table->in_use;
 
4202
 
 
4203
  if (table->no_replicate == false)
 
4204
    return false;
 
4205
 
 
4206
  error= replicator_session_init(session);
 
4207
 
 
4208
  switch (session->lex->sql_command)
 
4209
  {
 
4210
  case SQLCOM_REPLACE:
 
4211
  case SQLCOM_INSERT:
 
4212
  case SQLCOM_REPLACE_SELECT:
 
4213
  case SQLCOM_INSERT_SELECT:
 
4214
  case SQLCOM_CREATE_TABLE:
 
4215
    error= replicator_write_row(session, table);
 
4216
    break;
 
4217
 
 
4218
  case SQLCOM_UPDATE:
 
4219
  case SQLCOM_UPDATE_MULTI:
 
4220
    error= replicator_update_row(session, table, before_record, after_record);
 
4221
    break;
 
4222
 
 
4223
  case SQLCOM_DELETE:
 
4224
  case SQLCOM_DELETE_MULTI:
 
4225
    error= replicator_delete_row(session, table);
 
4226
    break;
 
4227
 
4608
4228
    /*
4609
 
      If there are no table maps written to the binary log, this is
4610
 
      the first row handled in this statement. In that case, we need
4611
 
      to write table maps for all locked tables to the binary log.
 
4229
      For everything else we ignore the event (since it just involves a temp table)
4612
4230
    */
4613
 
    if (likely(!(error= write_locked_table_maps(thd))))
4614
 
    {
4615
 
      bool const has_trans= table->file->has_transactions();
4616
 
      error= (*log_func)(thd, table, has_trans, before_record, after_record);
4617
 
    }
 
4231
  default:
 
4232
    break;
4618
4233
  }
4619
 
  return error ? HA_ERR_RBR_LOGGING_FAILED : 0;
 
4234
 
 
4235
  return error;
4620
4236
}
4621
4237
 
4622
 
int handler::ha_external_lock(THD *thd, int lock_type)
 
4238
int handler::ha_external_lock(Session *session, int lock_type)
4623
4239
{
4624
4240
  /*
4625
4241
    Whether this is lock or unlock, this should be true, and is to verify that
4634
4250
  */
4635
4251
  DRIZZLE_EXTERNAL_LOCK(lock_type);
4636
4252
 
4637
 
  int error= external_lock(thd, lock_type);
 
4253
  int error= external_lock(session, lock_type);
4638
4254
  if (error == 0)
4639
4255
    cached_table_flags= table_flags();
4640
4256
  return(error);
4647
4263
int handler::ha_reset()
4648
4264
{
4649
4265
  /* Check that we have called all proper deallocation functions */
4650
 
  assert((uchar*) table->def_read_set.bitmap +
 
4266
  assert((unsigned char*) table->def_read_set.bitmap +
4651
4267
              table->s->column_bitmap_size ==
4652
 
              (uchar*) table->def_write_set.bitmap);
 
4268
              (unsigned char*) table->def_write_set.bitmap);
4653
4269
  assert(bitmap_is_set_all(&table->s->all_set));
4654
4270
  assert(table->key_read == 0);
4655
4271
  /* ensure that ha_index_end / ha_rnd_end has been called */
4662
4278
}
4663
4279
 
4664
4280
 
4665
 
int handler::ha_write_row(uchar *buf)
 
4281
int handler::ha_write_row(unsigned char *buf)
4666
4282
{
4667
4283
  int error;
4668
 
  Log_func *log_func= Write_rows_log_event::binlog_row_logging_function;
4669
4284
  DRIZZLE_INSERT_ROW_START();
4670
4285
 
4671
4286
  mark_trx_read_write();
4672
4287
 
4673
4288
  if (unlikely(error= write_row(buf)))
4674
4289
    return(error);
4675
 
  if (unlikely(error= binlog_log_row(table, 0, buf, log_func)))
4676
 
    return(error); /* purecov: inspected */
 
4290
 
 
4291
  if (unlikely(binlog_log_row(table, 0, buf)))
 
4292
    return HA_ERR_RBR_LOGGING_FAILED; /* purecov: inspected */
 
4293
 
4677
4294
  DRIZZLE_INSERT_ROW_END();
4678
4295
  return(0);
4679
4296
}
4680
4297
 
4681
4298
 
4682
 
int handler::ha_update_row(const uchar *old_data, uchar *new_data)
 
4299
int handler::ha_update_row(const unsigned char *old_data, unsigned char *new_data)
4683
4300
{
4684
4301
  int error;
4685
 
  Log_func *log_func= Update_rows_log_event::binlog_row_logging_function;
4686
4302
 
4687
4303
  /*
4688
4304
    Some storage engines require that the new record is in record[0]
4694
4310
 
4695
4311
  if (unlikely(error= update_row(old_data, new_data)))
4696
4312
    return error;
4697
 
  if (unlikely(error= binlog_log_row(table, old_data, new_data, log_func)))
4698
 
    return error;
 
4313
 
 
4314
  if (unlikely(binlog_log_row(table, old_data, new_data)))
 
4315
    return HA_ERR_RBR_LOGGING_FAILED;
 
4316
 
4699
4317
  return 0;
4700
4318
}
4701
4319
 
4702
 
int handler::ha_delete_row(const uchar *buf)
 
4320
int handler::ha_delete_row(const unsigned char *buf)
4703
4321
{
4704
4322
  int error;
4705
 
  Log_func *log_func= Delete_rows_log_event::binlog_row_logging_function;
4706
4323
 
4707
4324
  mark_trx_read_write();
4708
4325
 
4709
4326
  if (unlikely(error= delete_row(buf)))
4710
4327
    return error;
4711
 
  if (unlikely(error= binlog_log_row(table, buf, 0, log_func)))
4712
 
    return error;
 
4328
 
 
4329
  if (unlikely(binlog_log_row(table, buf, 0)))
 
4330
    return HA_ERR_RBR_LOGGING_FAILED;
 
4331
 
4713
4332
  return 0;
4714
4333
}
4715
4334
 
4726
4345
  /* fallback to use all columns in the table to identify row */
4727
4346
  table->use_all_columns();
4728
4347
}
 
4348
 
 
4349
void table_case_convert(char * name, uint32_t length)
 
4350
{
 
4351
  if (lower_case_table_names)
 
4352
    files_charset_info->cset->casedn(files_charset_info,
 
4353
                                     name, length, name, length);
 
4354
}
 
4355
 
 
4356
const char *table_case_name(HA_CREATE_INFO *info, const char *name)
 
4357
{
 
4358
  return ((lower_case_table_names == 2 && info->alias) ? info->alias : name);
 
4359
}