~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/handler.cc

  • Committer: Monty Taylor
  • Date: 2008-08-04 19:37:18 UTC
  • mto: (261.2.2 codestyle)
  • mto: This revision was merged to the branch mainline in revision 262.
  • Revision ID: monty@inaugust.com-20080804193718-f0rz13uli4429ozb
Changed gettext_noop() to N_()

Show diffs side-by-side

added added

removed removed

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