~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/handler.cc

  • Committer: Monty Taylor
  • Date: 2009-01-30 21:02:37 UTC
  • mto: (779.7.3 devel)
  • mto: This revision was merged to the branch mainline in revision 823.
  • Revision ID: mordred@inaugust.com-20090130210237-3n6ld8a9jc084jko
Commented out a test in subselect_sj - I think it might be a regression. Jay?

Show diffs side-by-side

added added

removed removed

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