~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/handler.cc

  • Committer: Brian Aker
  • Date: 2009-02-20 22:48:37 UTC
  • Revision ID: brian@tangent.org-20090220224837-fw5wrf46n4ru3e6a
First pass of stripping uint

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
 
26
#include "drizzled/server_includes.h"
 
27
#include "libdrizzleclient/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
#include "drizzled/field/timestamp.h"
 
44
#include "drizzled/serialize/table.pb.h"
 
45
 
 
46
#if defined(CMATH_NAMESPACE)
 
47
using namespace CMATH_NAMESPACE;
24
48
#endif
25
49
 
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
50
 
41
51
KEY_CREATE_INFO default_key_create_info= { HA_KEY_ALG_UNDEF, 0, {NULL,0}, {NULL,0} };
42
52
 
47
57
/* size of savepoint storage area (see ha_init) */
48
58
uint32_t savepoint_alloc_size= 0;
49
59
 
50
 
static const LEX_STRING sys_table_aliases[]=
51
 
{
52
 
  { C_STRING_WITH_LEN("INNOBASE") },  { C_STRING_WITH_LEN("INNODB") },
53
 
  { C_STRING_WITH_LEN("HEAP") },      { C_STRING_WITH_LEN("MEMORY") },
54
 
  {NULL, 0}
55
 
};
56
 
 
57
60
const char *ha_row_type[] = {
58
61
  "", "FIXED", "DYNAMIC", "COMPRESSED", "REDUNDANT", "COMPACT", "PAGE", "?","?","?"
59
62
};
61
64
const char *tx_isolation_names[] =
62
65
{ "READ-UNCOMMITTED", "READ-COMMITTED", "REPEATABLE-READ", "SERIALIZABLE",
63
66
  NULL};
 
67
 
64
68
TYPELIB tx_isolation_typelib= {array_elements(tx_isolation_names)-1,"",
65
 
                               tx_isolation_names, NULL};
 
69
                               tx_isolation_names, NULL};
66
70
 
67
71
static TYPELIB known_extensions= {0,"known_exts", NULL, NULL};
68
72
uint32_t known_extensions_id= 0;
69
73
 
70
74
 
71
 
 
72
 
static plugin_ref ha_default_plugin(THD *thd)
73
 
{
74
 
  if (thd->variables.table_plugin)
75
 
    return thd->variables.table_plugin;
76
 
  return my_plugin_lock(thd, &global_system_variables.table_plugin);
77
 
}
78
 
 
79
 
 
80
 
/**
81
 
  Return the default storage engine handlerton for thread
82
 
 
83
 
  @param ha_default_handlerton(thd)
84
 
  @param thd         current thread
85
 
 
86
 
  @return
87
 
    pointer to handlerton
88
 
*/
89
 
handlerton *ha_default_handlerton(THD *thd)
90
 
{
91
 
  plugin_ref plugin= ha_default_plugin(thd);
92
 
  assert(plugin);
93
 
  handlerton *hton= plugin_data(plugin, handlerton*);
94
 
  assert(hton);
95
 
  return hton;
96
 
}
97
 
 
98
 
 
99
 
/**
100
 
  Return the storage engine handlerton for the supplied name
101
 
  
102
 
  @param thd         current thread
103
 
  @param name        name of storage engine
104
 
  
105
 
  @return
106
 
    pointer to storage engine plugin handle
107
 
*/
108
 
plugin_ref ha_resolve_by_name(THD *thd, const LEX_STRING *name)
109
 
{
110
 
  const LEX_STRING *table_alias;
111
 
  plugin_ref plugin;
112
 
 
113
 
redo:
114
 
  /* my_strnncoll is a macro and gcc doesn't do early expansion of macro */
115
 
  if (thd && !my_charset_utf8_general_ci.coll->strnncoll(&my_charset_utf8_general_ci,
116
 
                           (const unsigned char *)name->str, name->length,
117
 
                           (const unsigned char *)STRING_WITH_LEN("DEFAULT"), 0))
118
 
    return ha_default_plugin(thd);
119
 
 
120
 
  if ((plugin= my_plugin_lock_by_name(thd, name, DRIZZLE_STORAGE_ENGINE_PLUGIN)))
121
 
  {
122
 
    handlerton *hton= plugin_data(plugin, handlerton *);
123
 
    if (!(hton->flags & HTON_NOT_USER_SELECTABLE))
124
 
      return plugin;
125
 
      
126
 
    /*
127
 
      unlocking plugin immediately after locking is relatively low cost.
128
 
    */
129
 
    plugin_unlock(thd, plugin);
130
 
  }
131
 
 
132
 
  /*
133
 
    We check for the historical aliases.
134
 
  */
135
 
  for (table_alias= sys_table_aliases; table_alias->str; table_alias+= 2)
136
 
  {
137
 
    if (!my_strnncoll(&my_charset_utf8_general_ci,
138
 
                      (const unsigned char *)name->str, name->length,
139
 
                      (const unsigned char *)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
 
  return ha_default_handlerton(thd);
200
 
} /* ha_checktype */
201
 
 
202
 
 
203
 
handler *get_new_handler(TABLE_SHARE *share, MEM_ROOT *alloc,
204
 
                         handlerton *db_type)
205
 
{
206
 
  handler *file;
207
 
 
208
 
  if (db_type && db_type->state == SHOW_OPTION_YES && db_type->create)
209
 
  {
210
 
    if ((file= db_type->create(db_type, share, alloc)))
211
 
      file->init();
212
 
    return(file);
213
 
  }
214
 
  /*
215
 
    Try the default table type
216
 
    Here the call to current_thd() is ok as we call this function a lot of
217
 
    times but we enter this branch very seldom.
218
 
  */
219
 
  return(get_new_handler(share, alloc, ha_default_handlerton(current_thd)));
220
 
}
221
 
 
222
 
 
223
75
/**
224
76
  Register handler error messages for use with my_error().
225
77
 
236
88
 
237
89
  /* Allocate a pointer array for the error message strings. */
238
90
  /* Zerofill it to avoid uninitialized gaps. */
239
 
  if (! (errmsgs= (const char**) my_malloc(HA_ERR_ERRORS * sizeof(char*),
240
 
                                           MYF(MY_WME | MY_ZEROFILL))))
 
91
  if (! (errmsgs= (const char**) malloc(HA_ERR_ERRORS * sizeof(char*))))
241
92
    return 1;
 
93
  memset(errmsgs, 0, HA_ERR_ERRORS * sizeof(char *));
242
94
 
243
95
  /* Set the dedicated error messages. */
244
96
  SETMSG(HA_ERR_KEY_NOT_FOUND,          ER(ER_KEY_NOT_FOUND));
307
159
  return 0;
308
160
}
309
161
 
310
 
 
311
 
int ha_finalize_handlerton(st_plugin_int *plugin)
312
 
{
313
 
  handlerton *hton= (handlerton *)plugin->data;
314
 
 
315
 
  switch (hton->state)
316
 
  {
317
 
  case SHOW_OPTION_NO:
318
 
  case SHOW_OPTION_DISABLED:
319
 
    break;
320
 
  case SHOW_OPTION_YES:
321
 
    if (installed_htons[hton->db_type] == hton)
322
 
      installed_htons[hton->db_type]= NULL;
323
 
    break;
324
 
  };
325
 
 
326
 
  if (hton && plugin->plugin->deinit)
327
 
    (void)plugin->plugin->deinit(hton);
328
 
 
329
 
  free((unsigned char*)hton);
330
 
 
331
 
  return(0);
332
 
}
333
 
 
334
 
 
335
 
int ha_initialize_handlerton(st_plugin_int *plugin)
336
 
{
337
 
  handlerton *hton;
338
 
 
339
 
  hton= (handlerton *)my_malloc(sizeof(handlerton),
340
 
                                MYF(MY_WME | MY_ZEROFILL));
341
 
  /* 
342
 
    FIXME: the MY_ZEROFILL flag above doesn't zero all the bytes.
343
 
    
344
 
    This was detected after adding get_backup_engine member to handlerton
345
 
    structure. Apparently get_backup_engine was not NULL even though it was
346
 
    not initialized.
347
 
   */
348
 
  memset(hton, 0, sizeof(hton));
349
 
  /* Historical Requirement */
350
 
  plugin->data= hton; // shortcut for the future
351
 
  if (plugin->plugin->init)
352
 
  {
353
 
    if (plugin->plugin->init(hton))
354
 
    {
355
 
      sql_print_error(_("Plugin '%s' init function returned error."),
356
 
                      plugin->name.str);
357
 
      goto err;
358
 
    }
359
 
  }
360
 
 
361
 
  /*
362
 
    the switch below and hton->state should be removed when
363
 
    command-line options for plugins will be implemented
364
 
  */
365
 
  switch (hton->state) {
366
 
  case SHOW_OPTION_NO:
367
 
    break;
368
 
  case SHOW_OPTION_YES:
369
 
    {
370
 
      uint32_t tmp;
371
 
      /* now check the db_type for conflict */
372
 
      if (hton->db_type <= DB_TYPE_UNKNOWN ||
373
 
          hton->db_type >= DB_TYPE_DEFAULT ||
374
 
          installed_htons[hton->db_type])
375
 
      {
376
 
        int idx= (int) DB_TYPE_FIRST_DYNAMIC;
377
 
 
378
 
        while (idx < (int) DB_TYPE_DEFAULT && installed_htons[idx])
379
 
          idx++;
380
 
 
381
 
        if (idx == (int) DB_TYPE_DEFAULT)
382
 
        {
383
 
          sql_print_warning(_("Too many storage engines!"));
384
 
          return(1);
385
 
        }
386
 
        if (hton->db_type != DB_TYPE_UNKNOWN)
387
 
          sql_print_warning(_("Storage engine '%s' has conflicting typecode. "
388
 
                            "Assigning value %d."), plugin->plugin->name, idx);
389
 
        hton->db_type= (enum legacy_db_type) idx;
390
 
      }
391
 
      installed_htons[hton->db_type]= hton;
392
 
      tmp= hton->savepoint_offset;
393
 
      hton->savepoint_offset= savepoint_alloc_size;
394
 
      savepoint_alloc_size+= tmp;
395
 
      hton->slot= total_ha++;
396
 
      hton2plugin[hton->slot]=plugin;
397
 
      if (hton->prepare)
398
 
        total_ha_2pc++;
399
 
      break;
400
 
    }
401
 
    /* fall through */
402
 
  default:
403
 
    hton->state= SHOW_OPTION_DISABLED;
404
 
    break;
405
 
  }
406
 
  
407
 
  /* 
408
 
    This is entirely for legacy. We will create a new "disk based" hton and a 
409
 
    "memory" hton which will be configurable longterm. We should be able to 
410
 
    remove partition and myisammrg.
411
 
  */
412
 
  if (strcmp(plugin->plugin->name, "MEMORY") == 0)
413
 
    heap_hton= hton;
414
 
 
415
 
  if (strcmp(plugin->plugin->name, "MyISAM") == 0)
416
 
    myisam_hton= hton;
417
 
 
418
 
  return(0);
419
 
err:
420
 
  return(1);
421
 
}
422
 
 
423
162
int ha_init()
424
163
{
425
164
  int error= 0;
439
178
{
440
179
  int error= 0;
441
180
 
442
 
  /* 
 
181
  /*
443
182
    This should be eventualy based  on the graceful shutdown flag.
444
183
    So if flag is equal to HA_PANIC_CLOSE, the deallocate
445
184
    the errors.
450
189
  return(error);
451
190
}
452
191
 
453
 
static bool dropdb_handlerton(THD *unused1 __attribute__((unused)),
 
192
static bool dropdb_handlerton(Session *,
454
193
                              plugin_ref plugin,
455
194
                              void *path)
456
195
{
467
206
}
468
207
 
469
208
 
470
 
static bool closecon_handlerton(THD *thd, plugin_ref plugin,
471
 
                                void *unused __attribute__((unused)))
 
209
static bool closecon_handlerton(Session *session, plugin_ref plugin,
 
210
                                void *)
472
211
{
473
212
  handlerton *hton= plugin_data(plugin, handlerton *);
474
213
  /*
476
215
    be rolled back already
477
216
  */
478
217
  if (hton->state == SHOW_OPTION_YES && hton->close_connection &&
479
 
      thd_get_ha_data(thd, hton))
480
 
    hton->close_connection(hton, thd);
 
218
      session_get_ha_data(session, hton))
 
219
    hton->close_connection(hton, session);
481
220
  return false;
482
221
}
483
222
 
486
225
  @note
487
226
    don't bother to rollback here, it's done already
488
227
*/
489
 
void ha_close_connection(THD* thd)
 
228
void ha_close_connection(Session* session)
490
229
{
491
 
  plugin_foreach(thd, closecon_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN, 0);
 
230
  plugin_foreach(session, closecon_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN, 0);
492
231
}
493
232
 
494
233
/* ========================================================================
593
332
  -----------
594
333
 
595
334
  The server stores its transaction-related data in
596
 
  thd->transaction. This structure has two members of type
597
 
  THD_TRANS. These members correspond to the statement and
 
335
  session->transaction. This structure has two members of type
 
336
  Session_TRANS. These members correspond to the statement and
598
337
  normal transactions respectively:
599
338
 
600
 
  - thd->transaction.stmt contains a list of engines
 
339
  - session->transaction.stmt contains a list of engines
601
340
  that are participating in the given statement
602
 
  - thd->transaction.all contains a list of engines that
 
341
  - session->transaction.all contains a list of engines that
603
342
  have participated in any of the statement transactions started
604
343
  within the context of the normal transaction.
605
344
  Each element of the list contains a pointer to the storage
606
345
  engine, engine-specific transactional data, and engine-specific
607
346
  transaction flags.
608
347
 
609
 
  In autocommit mode thd->transaction.all is empty.
610
 
  Instead, data of thd->transaction.stmt is
 
348
  In autocommit mode session->transaction.all is empty.
 
349
  Instead, data of session->transaction.stmt is
611
350
  used to commit/rollback the normal transaction.
612
351
 
613
352
  The list of registered engines has a few important properties:
618
357
  Transaction life cycle
619
358
  ----------------------
620
359
 
621
 
  When a new connection is established, thd->transaction
 
360
  When a new connection is established, session->transaction
622
361
  members are initialized to an empty state.
623
362
  If a statement uses any tables, all affected engines
624
363
  are registered in the statement engine list. In
634
373
  and emptied again at the next statement's end.
635
374
 
636
375
  The normal transaction is committed in a similar way
637
 
  (by going over all engines in thd->transaction.all list)
 
376
  (by going over all engines in session->transaction.all list)
638
377
  but at different times:
639
378
  - upon COMMIT SQL statement is issued by the user
640
379
  - implicitly, by the server, at the beginning of a DDL statement
644
383
  - if the user has requested so, by issuing ROLLBACK SQL
645
384
  statement
646
385
  - if one of the storage engines requested a rollback
647
 
  by setting thd->transaction_rollback_request. This may
 
386
  by setting session->transaction_rollback_request. This may
648
387
  happen in case, e.g., when the transaction in the engine was
649
388
  chosen a victim of the internal deadlock resolution algorithm
650
389
  and rolled back internally. When such a situation happens, there
686
425
  transactions of other participants.
687
426
 
688
427
  After the normal transaction has been committed,
689
 
  thd->transaction.all list is cleared.
 
428
  session->transaction.all list is cleared.
690
429
 
691
430
  When a connection is closed, the current normal transaction, if
692
431
  any, is rolled back.
750
489
  ---------------------------------------------------
751
490
 
752
491
  DDLs and operations with non-transactional engines
753
 
  do not "register" in thd->transaction lists, and thus do not
 
492
  do not "register" in session->transaction lists, and thus do not
754
493
  modify the transaction state. Besides, each DDL in
755
494
  MySQL is prefixed with an implicit normal transaction commit
756
495
  (a call to end_active_trans()), and thus leaves nothing
797
536
    times per transaction.
798
537
 
799
538
*/
800
 
void trans_register_ha(THD *thd, bool all, handlerton *ht_arg)
 
539
void trans_register_ha(Session *session, bool all, handlerton *ht_arg)
801
540
{
802
 
  THD_TRANS *trans;
 
541
  Session_TRANS *trans;
803
542
  Ha_trx_info *ha_info;
804
543
 
805
544
  if (all)
806
545
  {
807
 
    trans= &thd->transaction.all;
808
 
    thd->server_status|= SERVER_STATUS_IN_TRANS;
 
546
    trans= &session->transaction.all;
 
547
    session->server_status|= SERVER_STATUS_IN_TRANS;
809
548
  }
810
549
  else
811
 
    trans= &thd->transaction.stmt;
 
550
    trans= &session->transaction.stmt;
812
551
 
813
 
  ha_info= thd->ha_data[ht_arg->slot].ha_info + static_cast<unsigned>(all);
 
552
  ha_info= session->ha_data[ht_arg->slot].ha_info + static_cast<unsigned>(all);
814
553
 
815
554
  if (ha_info->is_started())
816
555
    return; /* already registered, return */
818
557
  ha_info->register_ha(trans, ht_arg);
819
558
 
820
559
  trans->no_2pc|=(ht_arg->prepare==0);
821
 
  if (thd->transaction.xid_state.xid.is_null())
822
 
    thd->transaction.xid_state.xid.set(thd->query_id);
 
560
  if (session->transaction.xid_state.xid.is_null())
 
561
    session->transaction.xid_state.xid.set(session->query_id);
823
562
 
824
563
  return;
825
564
}
830
569
  @retval
831
570
    1   error, transaction was rolled back
832
571
*/
833
 
int ha_prepare(THD *thd)
 
572
int ha_prepare(Session *session)
834
573
{
835
574
  int error=0, all=1;
836
 
  THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt;
 
575
  Session_TRANS *trans=all ? &session->transaction.all : &session->transaction.stmt;
837
576
  Ha_trx_info *ha_info= trans->ha_list;
838
577
  if (ha_info)
839
578
  {
841
580
    {
842
581
      int err;
843
582
      handlerton *ht= ha_info->ht();
844
 
      status_var_increment(thd->status_var.ha_prepare_count);
 
583
      status_var_increment(session->status_var.ha_prepare_count);
845
584
      if (ht->prepare)
846
585
      {
847
 
        if ((err= ht->prepare(ht, thd, all)))
 
586
        if ((err= ht->prepare(ht, session, all)))
848
587
        {
849
588
          my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
850
 
          ha_rollback_trans(thd, all);
 
589
          ha_rollback_trans(session, all);
851
590
          error=1;
852
591
          break;
853
592
        }
854
593
      }
855
594
      else
856
595
      {
857
 
        push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
596
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
858
597
                            ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
859
598
                            ha_resolve_storage_engine_name(ht));
860
599
      }
879
618
 
880
619
static
881
620
bool
882
 
ha_check_and_coalesce_trx_read_only(THD *thd, Ha_trx_info *ha_list,
 
621
ha_check_and_coalesce_trx_read_only(Session *session, Ha_trx_info *ha_list,
883
622
                                    bool all)
884
623
{
885
624
  /* The number of storage engines that have actual changes. */
893
632
 
894
633
    if (! all)
895
634
    {
896
 
      Ha_trx_info *ha_info_all= &thd->ha_data[ha_info->ht()->slot].ha_info[1];
 
635
      Ha_trx_info *ha_info_all= &session->ha_data[ha_info->ht()->slot].ha_info[1];
897
636
      assert(ha_info != ha_info_all);
898
637
      /*
899
638
        Merge read-only/read-write information about statement
900
639
        transaction to its enclosing normal transaction. Do this
901
640
        only if in a real transaction -- that is, if we know
902
 
        that ha_info_all is registered in thd->transaction.all.
 
641
        that ha_info_all is registered in session->transaction.all.
903
642
        Since otherwise we only clutter the normal transaction flags.
904
643
      */
905
644
      if (ha_info_all->is_started()) /* false if autocommit. */
933
672
    stored functions or triggers. So we simply do nothing now.
934
673
    TODO: This should be fixed in later ( >= 5.1) releases.
935
674
*/
936
 
int ha_commit_trans(THD *thd, bool all)
 
675
int ha_commit_trans(Session *session, bool all)
937
676
{
938
677
  int error= 0, cookie= 0;
939
678
  /*
940
679
    'all' means that this is either an explicit commit issued by
941
680
    user, or an implicit commit issued by a DDL.
942
681
  */
943
 
  THD_TRANS *trans= all ? &thd->transaction.all : &thd->transaction.stmt;
944
 
  bool is_real_trans= all || thd->transaction.all.ha_list == 0;
 
682
  Session_TRANS *trans= all ? &session->transaction.all : &session->transaction.stmt;
 
683
  bool is_real_trans= all || session->transaction.all.ha_list == 0;
945
684
  Ha_trx_info *ha_info= trans->ha_list;
946
 
  my_xid xid= thd->transaction.xid_state.xid.get_my_xid();
947
685
 
948
686
  /*
949
687
    We must not commit the normal transaction if a statement
951
689
    flags will not get propagated to its normal transaction's
952
690
    counterpart.
953
691
  */
954
 
  assert(thd->transaction.stmt.ha_list == NULL ||
955
 
              trans == &thd->transaction.stmt);
 
692
  assert(session->transaction.stmt.ha_list == NULL ||
 
693
              trans == &session->transaction.stmt);
956
694
 
957
 
  if (thd->in_sub_stmt)
958
 
  {
959
 
    /*
960
 
      Since we don't support nested statement transactions in 5.0,
961
 
      we can't commit or rollback stmt transactions while we are inside
962
 
      stored functions or triggers. So we simply do nothing now.
963
 
      TODO: This should be fixed in later ( >= 5.1) releases.
964
 
    */
965
 
    if (!all)
966
 
      return(0);
967
 
    /*
968
 
      We assume that all statements which commit or rollback main transaction
969
 
      are prohibited inside of stored functions or triggers. So they should
970
 
      bail out with error even before ha_commit_trans() call. To be 100% safe
971
 
      let us throw error in non-debug builds.
972
 
    */
973
 
    assert(0);
974
 
    my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
975
 
    return(2);
976
 
  }
977
695
  if (ha_info)
978
696
  {
979
697
    bool must_2pc;
980
698
 
981
 
    if (is_real_trans && wait_if_global_read_lock(thd, 0, 0))
 
699
    if (is_real_trans && wait_if_global_read_lock(session, 0, 0))
982
700
    {
983
 
      ha_rollback_trans(thd, all);
 
701
      ha_rollback_trans(session, all);
984
702
      return(1);
985
703
    }
986
704
 
987
 
    if (   is_real_trans
988
 
        && opt_readonly
989
 
        && ! thd->slave_thread
990
 
       )
991
 
    {
992
 
      my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only");
993
 
      ha_rollback_trans(thd, all);
994
 
      error= 1;
995
 
      goto end;
996
 
    }
997
 
 
998
 
    must_2pc= ha_check_and_coalesce_trx_read_only(thd, ha_info, all);
 
705
    must_2pc= ha_check_and_coalesce_trx_read_only(session, ha_info, all);
999
706
 
1000
707
    if (!trans->no_2pc && must_2pc)
1001
708
    {
1014
721
          Sic: we know that prepare() is not NULL since otherwise
1015
722
          trans->no_2pc would have been set.
1016
723
        */
1017
 
        if ((err= ht->prepare(ht, thd, all)))
 
724
        if ((err= ht->prepare(ht, session, all)))
1018
725
        {
1019
726
          my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
1020
727
          error= 1;
1021
728
        }
1022
 
        status_var_increment(thd->status_var.ha_prepare_count);
 
729
        status_var_increment(session->status_var.ha_prepare_count);
1023
730
      }
1024
 
      if (error || (is_real_trans && xid &&
1025
 
                    (error= !(cookie= tc_log->log_xid(thd, xid)))))
 
731
      if (error)
1026
732
      {
1027
 
        ha_rollback_trans(thd, all);
 
733
        ha_rollback_trans(session, all);
1028
734
        error= 1;
1029
735
        goto end;
1030
736
      }
1031
737
    }
1032
 
    error=ha_commit_one_phase(thd, all) ? (cookie ? 2 : 1) : 0;
1033
 
    if (cookie)
1034
 
      tc_log->unlog(cookie, xid);
 
738
    error=ha_commit_one_phase(session, all) ? (cookie ? 2 : 1) : 0;
1035
739
end:
1036
740
    if (is_real_trans)
1037
 
      start_waiting_global_read_lock(thd);
 
741
      start_waiting_global_read_lock(session);
1038
742
  }
1039
743
  return(error);
1040
744
}
1043
747
  @note
1044
748
  This function does not care about global read lock. A caller should.
1045
749
*/
1046
 
int ha_commit_one_phase(THD *thd, bool all)
 
750
int ha_commit_one_phase(Session *session, bool all)
1047
751
{
1048
752
  int error=0;
1049
 
  THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt;
1050
 
  bool is_real_trans=all || thd->transaction.all.ha_list == 0;
 
753
  Session_TRANS *trans=all ? &session->transaction.all : &session->transaction.stmt;
 
754
  bool is_real_trans=all || session->transaction.all.ha_list == 0;
1051
755
  Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
1052
756
  if (ha_info)
1053
757
  {
1055
759
    {
1056
760
      int err;
1057
761
      handlerton *ht= ha_info->ht();
1058
 
      if ((err= ht->commit(ht, thd, all)))
 
762
      if ((err= ht->commit(ht, session, all)))
1059
763
      {
1060
764
        my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
1061
765
        error=1;
1062
766
      }
1063
 
      status_var_increment(thd->status_var.ha_commit_count);
 
767
      status_var_increment(session->status_var.ha_commit_count);
1064
768
      ha_info_next= ha_info->next();
1065
769
      ha_info->reset(); /* keep it conveniently zero-filled */
1066
770
    }
1067
771
    trans->ha_list= 0;
1068
772
    trans->no_2pc=0;
1069
773
    if (is_real_trans)
1070
 
      thd->transaction.xid_state.xid.null();
 
774
      session->transaction.xid_state.xid.null();
1071
775
    if (all)
1072
776
    {
1073
 
      thd->variables.tx_isolation=thd->session_tx_isolation;
1074
 
      thd->transaction.cleanup();
 
777
      session->variables.tx_isolation=session->session_tx_isolation;
 
778
      session->transaction.cleanup();
1075
779
    }
1076
780
  }
1077
781
  return(error);
1078
782
}
1079
783
 
1080
784
 
1081
 
int ha_rollback_trans(THD *thd, bool all)
 
785
int ha_rollback_trans(Session *session, bool all)
1082
786
{
1083
787
  int error=0;
1084
 
  THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt;
 
788
  Session_TRANS *trans=all ? &session->transaction.all : &session->transaction.stmt;
1085
789
  Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
1086
 
  bool is_real_trans=all || thd->transaction.all.ha_list == 0;
 
790
  bool is_real_trans=all || session->transaction.all.ha_list == 0;
1087
791
 
1088
792
  /*
1089
793
    We must not rollback the normal transaction if a statement
1090
794
    transaction is pending.
1091
795
  */
1092
 
  assert(thd->transaction.stmt.ha_list == NULL ||
1093
 
              trans == &thd->transaction.stmt);
 
796
  assert(session->transaction.stmt.ha_list == NULL ||
 
797
              trans == &session->transaction.stmt);
1094
798
 
1095
 
  if (thd->in_sub_stmt)
1096
 
  {
1097
 
    /*
1098
 
      If we are inside stored function or trigger we should not commit or
1099
 
      rollback current statement transaction. See comment in ha_commit_trans()
1100
 
      call for more information.
1101
 
    */
1102
 
    if (!all)
1103
 
      return(0);
1104
 
    assert(0);
1105
 
    my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
1106
 
    return(1);
1107
 
  }
1108
799
  if (ha_info)
1109
800
  {
1110
801
    for (; ha_info; ha_info= ha_info_next)
1111
802
    {
1112
803
      int err;
1113
804
      handlerton *ht= ha_info->ht();
1114
 
      if ((err= ht->rollback(ht, thd, all)))
 
805
      if ((err= ht->rollback(ht, session, all)))
1115
806
      { // cannot happen
1116
807
        my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
1117
808
        error=1;
1118
809
      }
1119
 
      status_var_increment(thd->status_var.ha_rollback_count);
 
810
      status_var_increment(session->status_var.ha_rollback_count);
1120
811
      ha_info_next= ha_info->next();
1121
812
      ha_info->reset(); /* keep it conveniently zero-filled */
1122
813
    }
1123
814
    trans->ha_list= 0;
1124
815
    trans->no_2pc=0;
1125
816
    if (is_real_trans)
1126
 
      thd->transaction.xid_state.xid.null();
 
817
      session->transaction.xid_state.xid.null();
1127
818
    if (all)
1128
819
    {
1129
 
      thd->variables.tx_isolation=thd->session_tx_isolation;
1130
 
      thd->transaction.cleanup();
 
820
      session->variables.tx_isolation=session->session_tx_isolation;
 
821
      session->transaction.cleanup();
1131
822
    }
1132
823
  }
1133
824
  if (all)
1134
 
    thd->transaction_rollback_request= false;
 
825
    session->transaction_rollback_request= false;
1135
826
 
1136
827
  /*
1137
828
    If a non-transactional table was updated, warn; don't warn if this is a
1142
833
    the error log; but we don't want users to wonder why they have this
1143
834
    message in the error log, so we don't send it.
1144
835
  */
1145
 
  if (is_real_trans && thd->transaction.all.modified_non_trans_table &&
1146
 
      !thd->slave_thread && thd->killed != THD::KILL_CONNECTION)
1147
 
    push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
836
  if (is_real_trans && session->transaction.all.modified_non_trans_table && session->killed != Session::KILL_CONNECTION)
 
837
    push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1148
838
                 ER_WARNING_NOT_COMPLETE_ROLLBACK,
1149
839
                 ER(ER_WARNING_NOT_COMPLETE_ROLLBACK));
1150
840
  return(error);
1161
851
    the user has used LOCK TABLES then that mechanism does not know to do the
1162
852
    commit.
1163
853
*/
1164
 
int ha_autocommit_or_rollback(THD *thd, int error)
 
854
int ha_autocommit_or_rollback(Session *session, int error)
1165
855
{
1166
 
  if (thd->transaction.stmt.ha_list)
 
856
  if (session->transaction.stmt.ha_list)
1167
857
  {
1168
858
    if (!error)
1169
859
    {
1170
 
      if (ha_commit_trans(thd, 0))
1171
 
        error=1;
 
860
      if (ha_commit_trans(session, 0))
 
861
        error=1;
1172
862
    }
1173
 
    else 
 
863
    else
1174
864
    {
1175
 
      (void) ha_rollback_trans(thd, 0);
1176
 
      if (thd->transaction_rollback_request && !thd->in_sub_stmt)
1177
 
        (void) ha_rollback(thd);
 
865
      (void) ha_rollback_trans(session, 0);
 
866
      if (session->transaction_rollback_request)
 
867
        (void) ha_rollback(session);
1178
868
    }
1179
869
 
1180
 
    thd->variables.tx_isolation=thd->session_tx_isolation;
 
870
    session->variables.tx_isolation=session->session_tx_isolation;
1181
871
  }
1182
872
  return(error);
1183
873
}
1188
878
  int result;
1189
879
};
1190
880
 
1191
 
static bool xacommit_handlerton(THD *unused1 __attribute__((unused)),
 
881
static bool xacommit_handlerton(Session *,
1192
882
                                plugin_ref plugin,
1193
883
                                void *arg)
1194
884
{
1201
891
  return false;
1202
892
}
1203
893
 
1204
 
static bool xarollback_handlerton(THD *unused1 __attribute__((unused)),
 
894
static bool xarollback_handlerton(Session *,
1205
895
                                  plugin_ref plugin,
1206
896
                                  void *arg)
1207
897
{
1251
941
  bool dry_run;
1252
942
};
1253
943
 
1254
 
static bool xarecover_handlerton(THD *unused __attribute__((unused)),
 
944
static bool xarecover_handlerton(Session *,
1255
945
                                 plugin_ref plugin,
1256
946
                                 void *arg)
1257
947
{
1263
953
  {
1264
954
    while ((got= hton->recover(hton, info->list, info->len)) > 0 )
1265
955
    {
1266
 
      sql_print_information(_("Found %d prepared transaction(s) in %s"),
 
956
      errmsg_printf(ERRMSG_LVL_INFO, _("Found %d prepared transaction(s) in %s"),
1267
957
                            got, ha_resolve_storage_engine_name(hton));
1268
958
      for (int i=0; i < got; i ++)
1269
959
      {
1315
1005
    return(0);
1316
1006
 
1317
1007
  if (info.commit_list)
1318
 
    sql_print_information(_("Starting crash recovery..."));
 
1008
    errmsg_printf(ERRMSG_LVL_INFO, _("Starting crash recovery..."));
1319
1009
 
1320
1010
 
1321
1011
#ifndef WILL_BE_DELETED_LATER
1331
1021
#endif
1332
1022
 
1333
1023
 
1334
 
  for (info.len= MAX_XID_LIST_SIZE ; 
 
1024
  for (info.len= MAX_XID_LIST_SIZE ;
1335
1025
       info.list==0 && info.len > MIN_XID_LIST_SIZE; info.len/=2)
1336
1026
  {
1337
 
    info.list=(XID *)my_malloc(info.len*sizeof(XID), MYF(0));
 
1027
    info.list=(XID *)malloc(info.len*sizeof(XID));
1338
1028
  }
1339
1029
  if (!info.list)
1340
1030
  {
1341
 
    sql_print_error(ER(ER_OUTOFMEMORY), info.len*sizeof(XID));
 
1031
    errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_OUTOFMEMORY), info.len*sizeof(XID));
1342
1032
    return(1);
1343
1033
  }
1344
1034
 
1345
 
  plugin_foreach(NULL, xarecover_handlerton, 
 
1035
  plugin_foreach(NULL, xarecover_handlerton,
1346
1036
                 DRIZZLE_STORAGE_ENGINE_PLUGIN, &info);
1347
1037
 
1348
1038
  free((unsigned char*)info.list);
1349
1039
  if (info.found_foreign_xids)
1350
 
    sql_print_warning(_("Found %d prepared XA transactions"), 
1351
 
                      info.found_foreign_xids);
 
1040
    errmsg_printf(ERRMSG_LVL_WARN, _("Found %d prepared XA transactions"),
 
1041
                  info.found_foreign_xids);
1352
1042
  if (info.dry_run && info.found_my_xids)
1353
1043
  {
1354
 
    sql_print_error(_("Found %d prepared transactions! It means that drizzled "
 
1044
    errmsg_printf(ERRMSG_LVL_ERROR,
 
1045
                  _("Found %d prepared transactions! It means that drizzled "
1355
1046
                    "was not shut down properly last time and critical "
1356
1047
                    "recovery information (last binlog or %s file) was "
1357
1048
                    "manually deleted after a crash. You have to start "
1361
1052
    return(1);
1362
1053
  }
1363
1054
  if (info.commit_list)
1364
 
    sql_print_information(_("Crash recovery finished."));
 
1055
    errmsg_printf(ERRMSG_LVL_INFO, _("Crash recovery finished."));
1365
1056
  return(0);
1366
1057
}
1367
1058
 
1373
1064
    so mysql_xa_recover does not filter XID's to ensure uniqueness.
1374
1065
    It can be easily fixed later, if necessary.
1375
1066
*/
1376
 
bool mysql_xa_recover(THD *thd)
 
1067
bool mysql_xa_recover(Session *session)
1377
1068
{
1378
1069
  List<Item> field_list;
1379
 
  Protocol *protocol= thd->protocol;
 
1070
  Protocol *protocol= session->protocol;
1380
1071
  int i=0;
1381
1072
  XID_STATE *xs;
1382
1073
 
1409
1100
  }
1410
1101
 
1411
1102
  pthread_mutex_unlock(&LOCK_xid_cache);
1412
 
  my_eof(thd);
 
1103
  session->my_eof();
1413
1104
  return(0);
1414
1105
}
1415
1106
 
1417
1108
  @details
1418
1109
  This function should be called when MySQL sends rows of a SELECT result set
1419
1110
  or the EOF mark to the client. It releases a possible adaptive hash index
1420
 
  S-latch held by thd in InnoDB and also releases a possible InnoDB query
1421
 
  FIFO ticket to enter InnoDB. To save CPU time, InnoDB allows a thd to
 
1111
  S-latch held by session in InnoDB and also releases a possible InnoDB query
 
1112
  FIFO ticket to enter InnoDB. To save CPU time, InnoDB allows a session to
1422
1113
  keep them over several calls of the InnoDB handler interface when a join
1423
1114
  is executed. But when we let the control to pass to the client they have
1424
1115
  to be released because if the application program uses mysql_use_result(),
1426
1117
  performs another SQL query. In MySQL-4.1 this is even more important because
1427
1118
  there a connection can have several SELECT queries open at the same time.
1428
1119
 
1429
 
  @param thd           the thread handle of the current connection
 
1120
  @param session           the thread handle of the current connection
1430
1121
 
1431
1122
  @return
1432
1123
    always 0
1433
1124
*/
1434
 
static bool release_temporary_latches(THD *thd, plugin_ref plugin,
1435
 
                                      void *unused __attribute__((unused)))
 
1125
static bool release_temporary_latches(Session *session, plugin_ref plugin,
 
1126
                                      void *)
1436
1127
{
1437
1128
  handlerton *hton= plugin_data(plugin, handlerton *);
1438
1129
 
1439
1130
  if (hton->state == SHOW_OPTION_YES && hton->release_temporary_latches)
1440
 
    hton->release_temporary_latches(hton, thd);
 
1131
    hton->release_temporary_latches(hton, session);
1441
1132
 
1442
1133
  return false;
1443
1134
}
1444
1135
 
1445
1136
 
1446
 
int ha_release_temporary_latches(THD *thd)
 
1137
int ha_release_temporary_latches(Session *session)
1447
1138
{
1448
 
  plugin_foreach(thd, release_temporary_latches, DRIZZLE_STORAGE_ENGINE_PLUGIN, 
 
1139
  plugin_foreach(session, release_temporary_latches, DRIZZLE_STORAGE_ENGINE_PLUGIN,
1449
1140
                 NULL);
1450
1141
 
1451
1142
  return 0;
1452
1143
}
1453
1144
 
1454
 
int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv)
 
1145
int ha_rollback_to_savepoint(Session *session, SAVEPOINT *sv)
1455
1146
{
1456
1147
  int error=0;
1457
 
  THD_TRANS *trans= (thd->in_sub_stmt ? &thd->transaction.stmt :
1458
 
                                        &thd->transaction.all);
 
1148
  Session_TRANS *trans= &session->transaction.all;
1459
1149
  Ha_trx_info *ha_info, *ha_info_next;
1460
1150
 
1461
1151
  trans->no_2pc=0;
1469
1159
    handlerton *ht= ha_info->ht();
1470
1160
    assert(ht);
1471
1161
    assert(ht->savepoint_set != 0);
1472
 
    if ((err= ht->savepoint_rollback(ht, thd,
 
1162
    if ((err= ht->savepoint_rollback(ht, session,
1473
1163
                                     (unsigned char *)(sv+1)+ht->savepoint_offset)))
1474
1164
    { // cannot happen
1475
1165
      my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
1476
1166
      error=1;
1477
1167
    }
1478
 
    status_var_increment(thd->status_var.ha_savepoint_rollback_count);
 
1168
    status_var_increment(session->status_var.ha_savepoint_rollback_count);
1479
1169
    trans->no_2pc|= ht->prepare == 0;
1480
1170
  }
1481
1171
  /*
1487
1177
  {
1488
1178
    int err;
1489
1179
    handlerton *ht= ha_info->ht();
1490
 
    if ((err= ht->rollback(ht, thd, !thd->in_sub_stmt)))
 
1180
    if ((err= ht->rollback(ht, session, !(0))))
1491
1181
    { // cannot happen
1492
1182
      my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
1493
1183
      error=1;
1494
1184
    }
1495
 
    status_var_increment(thd->status_var.ha_rollback_count);
 
1185
    status_var_increment(session->status_var.ha_rollback_count);
1496
1186
    ha_info_next= ha_info->next();
1497
1187
    ha_info->reset(); /* keep it conveniently zero-filled */
1498
1188
  }
1506
1196
  section "4.33.4 SQL-statements and transaction states",
1507
1197
  SAVEPOINT is *not* transaction-initiating SQL-statement
1508
1198
*/
1509
 
int ha_savepoint(THD *thd, SAVEPOINT *sv)
 
1199
int ha_savepoint(Session *session, SAVEPOINT *sv)
1510
1200
{
1511
1201
  int error=0;
1512
 
  THD_TRANS *trans= (thd->in_sub_stmt ? &thd->transaction.stmt :
1513
 
                                        &thd->transaction.all);
 
1202
  Session_TRANS *trans= &session->transaction.all;
1514
1203
  Ha_trx_info *ha_info= trans->ha_list;
1515
1204
  for (; ha_info; ha_info= ha_info->next())
1516
1205
  {
1523
1212
      error=1;
1524
1213
      break;
1525
1214
    }
1526
 
    if ((err= ht->savepoint_set(ht, thd, (unsigned char *)(sv+1)+ht->savepoint_offset)))
 
1215
    if ((err= ht->savepoint_set(ht, session, (unsigned char *)(sv+1)+ht->savepoint_offset)))
1527
1216
    { // cannot happen
1528
1217
      my_error(ER_GET_ERRNO, MYF(0), err);
1529
1218
      error=1;
1530
1219
    }
1531
 
    status_var_increment(thd->status_var.ha_savepoint_count);
 
1220
    status_var_increment(session->status_var.ha_savepoint_count);
1532
1221
  }
1533
1222
  /*
1534
1223
    Remember the list of registered storage engines. All new
1538
1227
  return(error);
1539
1228
}
1540
1229
 
1541
 
int ha_release_savepoint(THD *thd, SAVEPOINT *sv)
 
1230
int ha_release_savepoint(Session *session, SAVEPOINT *sv)
1542
1231
{
1543
1232
  int error=0;
1544
1233
  Ha_trx_info *ha_info= sv->ha_list;
1551
1240
    assert(ht);
1552
1241
    if (!ht->savepoint_release)
1553
1242
      continue;
1554
 
    if ((err= ht->savepoint_release(ht, thd,
 
1243
    if ((err= ht->savepoint_release(ht, session,
1555
1244
                                    (unsigned char *)(sv+1) + ht->savepoint_offset)))
1556
1245
    { // cannot happen
1557
1246
      my_error(ER_GET_ERRNO, MYF(0), err);
1562
1251
}
1563
1252
 
1564
1253
 
1565
 
static bool snapshot_handlerton(THD *thd, plugin_ref plugin, void *arg)
 
1254
static bool snapshot_handlerton(Session *session, plugin_ref plugin, void *arg)
1566
1255
{
1567
1256
  handlerton *hton= plugin_data(plugin, handlerton *);
1568
1257
  if (hton->state == SHOW_OPTION_YES &&
1569
1258
      hton->start_consistent_snapshot)
1570
1259
  {
1571
 
    hton->start_consistent_snapshot(hton, thd);
 
1260
    hton->start_consistent_snapshot(hton, session);
1572
1261
    *((bool *)arg)= false;
1573
1262
  }
1574
1263
  return false;
1575
1264
}
1576
1265
 
1577
 
int ha_start_consistent_snapshot(THD *thd)
 
1266
int ha_start_consistent_snapshot(Session *session)
1578
1267
{
1579
1268
  bool warn= true;
1580
1269
 
1581
 
  plugin_foreach(thd, snapshot_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN, &warn);
 
1270
  plugin_foreach(session, snapshot_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN, &warn);
1582
1271
 
1583
1272
  /*
1584
1273
    Same idea as when one wants to CREATE TABLE in one engine which does not
1585
1274
    exist:
1586
1275
  */
1587
1276
  if (warn)
1588
 
    push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
1589
 
                 "This MySQL server does not support any "
 
1277
    push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
 
1278
                 "This Drizzle server does not support any "
1590
1279
                 "consistent-read capable storage engine");
1591
1280
  return 0;
1592
1281
}
1593
1282
 
1594
1283
 
1595
 
static bool flush_handlerton(THD *thd __attribute__((unused)),
 
1284
static bool flush_handlerton(Session *,
1596
1285
                             plugin_ref plugin,
1597
 
                             void *arg __attribute__((unused)))
 
1286
                             void *)
1598
1287
{
1599
1288
  handlerton *hton= plugin_data(plugin, handlerton *);
1600
 
  if (hton->state == SHOW_OPTION_YES && hton->flush_logs && 
 
1289
  if (hton->state == SHOW_OPTION_YES && hton->flush_logs &&
1601
1290
      hton->flush_logs(hton))
1602
1291
    return true;
1603
1292
  return false;
1629
1318
 
1630
1319
  /* Ensure that table handler get path in lower case */
1631
1320
  if (tmp_path != path)
1632
 
    my_stpcpy(tmp_path, path);
 
1321
    strcpy(tmp_path, path);
1633
1322
 
1634
1323
  /*
1635
1324
    we only should turn into lowercase database/table part
1636
1325
    so start the process after homedirectory
1637
1326
  */
1638
 
  my_casedn_str(files_charset_info, tmp_path + mysql_data_home_len);
 
1327
  my_casedn_str(files_charset_info, tmp_path + drizzle_data_home_len);
1639
1328
  return tmp_path;
1640
1329
}
1641
1330
 
1652
1341
  virtual bool handle_error(uint32_t sql_errno,
1653
1342
                            const char *message,
1654
1343
                            DRIZZLE_ERROR::enum_warning_level level,
1655
 
                            THD *thd);
 
1344
                            Session *session);
1656
1345
  char buff[DRIZZLE_ERRMSG_SIZE];
1657
1346
};
1658
1347
 
1659
1348
 
1660
1349
bool
1661
1350
Ha_delete_table_error_handler::
1662
 
handle_error(uint32_t sql_errno  __attribute__((unused)),
 
1351
handle_error(uint32_t ,
1663
1352
             const char *message,
1664
 
             DRIZZLE_ERROR::enum_warning_level level __attribute__((unused)),
1665
 
             THD *thd __attribute__((unused)))
 
1353
             DRIZZLE_ERROR::enum_warning_level ,
 
1354
             Session *)
1666
1355
{
1667
1356
  /* Grab the error message */
1668
 
  strmake(buff, message, sizeof(buff)-1);
 
1357
  strncpy(buff, message, sizeof(buff)-1);
1669
1358
  return true;
1670
1359
}
1671
1360
 
1672
1361
 
 
1362
struct handlerton_delete_table_args {
 
1363
  Session *session;
 
1364
  const char *path;
 
1365
  handler *file;
 
1366
  int error;
 
1367
};
 
1368
 
 
1369
static bool deletetable_handlerton(Session *,
 
1370
                                   plugin_ref plugin,
 
1371
                                   void *args)
 
1372
{
 
1373
  struct handlerton_delete_table_args *dtargs= (struct handlerton_delete_table_args *) args;
 
1374
 
 
1375
  Session *session= dtargs->session;
 
1376
  const char *path= dtargs->path;
 
1377
 
 
1378
  handler *file;
 
1379
  char tmp_path[FN_REFLEN];
 
1380
 
 
1381
  if(dtargs->error!=ENOENT) /* already deleted table */
 
1382
    return false;
 
1383
 
 
1384
  handlerton *table_type= plugin_data(plugin, handlerton *);
 
1385
 
 
1386
  if(!table_type)
 
1387
    return false;
 
1388
 
 
1389
  if(!(table_type->state == SHOW_OPTION_YES && table_type->create))
 
1390
    return false;
 
1391
 
 
1392
  if ((file= table_type->create(table_type, NULL, session->mem_root)))
 
1393
    file->init();
 
1394
  else
 
1395
    return false;
 
1396
 
 
1397
  path= check_lowercase_names(file, path, tmp_path);
 
1398
  int error= file->ha_delete_table(path);
 
1399
 
 
1400
  if(error!=ENOENT)
 
1401
  {
 
1402
    dtargs->error= error;
 
1403
    if(dtargs->file)
 
1404
      delete dtargs->file;
 
1405
    dtargs->file= file;
 
1406
    return true;
 
1407
  }
 
1408
 
 
1409
  return false;
 
1410
}
 
1411
 
1673
1412
/**
1674
1413
  This should return ENOENT if the file doesn't exists.
1675
1414
  The .frm file will be deleted only if we return 0 or ENOENT
1676
1415
*/
1677
 
int ha_delete_table(THD *thd, handlerton *table_type, const char *path,
 
1416
int ha_delete_table(Session *session, const char *path,
1678
1417
                    const char *db, const char *alias, bool generate_warning)
1679
1418
{
1680
 
  handler *file;
1681
 
  char tmp_path[FN_REFLEN];
1682
 
  int error;
 
1419
  TABLE_SHARE dummy_share;
1683
1420
  Table dummy_table;
1684
 
  TABLE_SHARE dummy_share;
 
1421
 
 
1422
  struct handlerton_delete_table_args dtargs;
 
1423
  dtargs.error= ENOENT;
 
1424
  dtargs.session= session;
 
1425
  dtargs.path= path;
 
1426
  dtargs.file= NULL;
 
1427
 
 
1428
  plugin_foreach(NULL, deletetable_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN,
 
1429
                 &dtargs);
1685
1430
 
1686
1431
  memset(&dummy_table, 0, sizeof(dummy_table));
1687
1432
  memset(&dummy_share, 0, sizeof(dummy_share));
1688
1433
  dummy_table.s= &dummy_share;
1689
1434
 
1690
 
  /* DB_TYPE_UNKNOWN is used in ALTER Table when renaming only .frm files */
1691
 
  if (table_type == NULL ||
1692
 
      ! (file=get_new_handler((TABLE_SHARE*)0, thd->mem_root, table_type)))
1693
 
    return(ENOENT);
1694
 
 
1695
 
  path= check_lowercase_names(file, path, tmp_path);
1696
 
  if ((error= file->ha_delete_table(path)) && generate_warning)
 
1435
  if (dtargs.error && generate_warning)
1697
1436
  {
1698
1437
    /*
1699
1438
      Because file->print_error() use my_error() to generate the error message
1712
1451
    dummy_share.table_name.length= strlen(alias);
1713
1452
    dummy_table.alias= alias;
1714
1453
 
1715
 
    file->change_table_ptr(&dummy_table, &dummy_share);
1716
 
 
1717
 
    thd->push_internal_handler(&ha_delete_table_error_handler);
1718
 
    file->print_error(error, 0);
1719
 
 
1720
 
    thd->pop_internal_handler();
 
1454
    if(dtargs.file)
 
1455
    {
 
1456
      handler *file= dtargs.file;
 
1457
      file->change_table_ptr(&dummy_table, &dummy_share);
 
1458
 
 
1459
      session->push_internal_handler(&ha_delete_table_error_handler);
 
1460
      file->print_error(dtargs.error, 0);
 
1461
 
 
1462
      session->pop_internal_handler();
 
1463
    }
 
1464
    else
 
1465
      dtargs.error= -1; /* General form of fail. maybe bad FRM */
1721
1466
 
1722
1467
    /*
1723
1468
      XXX: should we convert *all* errors to warnings here?
1724
1469
      What if the error is fatal?
1725
1470
    */
1726
 
    push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_ERROR, error,
 
1471
    push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR, dtargs.error,
1727
1472
                ha_delete_table_error_handler.buff);
1728
1473
  }
1729
 
  delete file;
1730
 
  return(error);
 
1474
 
 
1475
  if(dtargs.file)
 
1476
    delete dtargs.file;
 
1477
 
 
1478
  return dtargs.error;
1731
1479
}
1732
1480
 
1733
1481
/****************************************************************************
1738
1486
  handler *new_handler= get_new_handler(table->s, mem_root, table->s->db_type());
1739
1487
  /*
1740
1488
    Allocate handler->ref here because otherwise ha_open will allocate it
1741
 
    on this->table->mem_root and we will not be able to reclaim that memory 
 
1489
    on this->table->mem_root and we will not be able to reclaim that memory
1742
1490
    when the clone handler object is destroyed.
1743
1491
  */
1744
1492
  if (!(new_handler->ref= (unsigned char*) alloc_root(mem_root, ALIGN_SIZE(ref_length)*2)))
1751
1499
  return NULL;
1752
1500
}
1753
1501
 
1754
 
 
 
1502
int handler::ha_index_init(uint32_t idx, bool sorted)
 
1503
{
 
1504
  int result;
 
1505
  assert(inited==NONE);
 
1506
  if (!(result= index_init(idx, sorted)))
 
1507
    inited=INDEX;
 
1508
  end_range= NULL;
 
1509
  return(result);
 
1510
}
 
1511
 
 
1512
int handler::ha_index_end()
 
1513
{
 
1514
  assert(inited==INDEX);
 
1515
  inited=NONE;
 
1516
  end_range= NULL;
 
1517
  return(index_end());
 
1518
}
 
1519
 
 
1520
int handler::ha_rnd_init(bool scan)
 
1521
{
 
1522
  int result;
 
1523
  assert(inited==NONE || (inited==RND && scan));
 
1524
  inited= (result= rnd_init(scan)) ? NONE: RND;
 
1525
  return(result);
 
1526
}
 
1527
 
 
1528
int handler::ha_rnd_end()
 
1529
{
 
1530
  assert(inited==RND);
 
1531
  inited=NONE;
 
1532
  return(rnd_end());
 
1533
}
 
1534
 
 
1535
int handler::ha_index_or_rnd_end()
 
1536
{
 
1537
  return inited == INDEX ? ha_index_end() : inited == RND ? ha_rnd_end() : 0;
 
1538
}
 
1539
 
 
1540
handler::Table_flags handler::ha_table_flags() const
 
1541
{
 
1542
  return cached_table_flags;
 
1543
}
 
1544
 
 
1545
void handler::ha_start_bulk_insert(ha_rows rows)
 
1546
{
 
1547
  estimation_rows_to_insert= rows;
 
1548
  start_bulk_insert(rows);
 
1549
}
 
1550
 
 
1551
int handler::ha_end_bulk_insert()
 
1552
{
 
1553
  estimation_rows_to_insert= 0;
 
1554
  return end_bulk_insert();
 
1555
}
 
1556
 
 
1557
void handler::change_table_ptr(Table *table_arg, TABLE_SHARE *share)
 
1558
{
 
1559
  table= table_arg;
 
1560
  table_share= share;
 
1561
}
 
1562
 
 
1563
const key_map *handler::keys_to_use_for_scanning()
 
1564
{
 
1565
  return &key_map_empty;
 
1566
}
 
1567
 
 
1568
bool handler::has_transactions()
 
1569
{
 
1570
  return (ha_table_flags() & HA_NO_TRANSACTIONS) == 0;
 
1571
}
1755
1572
 
1756
1573
void handler::ha_statistic_increment(ulong SSV::*offset) const
1757
1574
{
1758
1575
  status_var_increment(table->in_use->status_var.*offset);
1759
1576
}
1760
1577
 
1761
 
void **handler::ha_data(THD *thd) const
1762
 
{
1763
 
  return thd_ha_data(thd, ht);
1764
 
}
1765
 
 
1766
 
THD *handler::ha_thd(void) const
1767
 
{
1768
 
  assert(!table || !table->in_use || table->in_use == current_thd);
1769
 
  return (table && table->in_use) ? table->in_use : current_thd;
1770
 
}
 
1578
void **handler::ha_data(Session *session) const
 
1579
{
 
1580
  return session_ha_data(session, ht);
 
1581
}
 
1582
 
 
1583
Session *handler::ha_session(void) const
 
1584
{
 
1585
  assert(!table || !table->in_use || table->in_use == current_session);
 
1586
  return (table && table->in_use) ? table->in_use : current_session;
 
1587
}
 
1588
 
 
1589
 
 
1590
bool handler::is_fatal_error(int error, uint32_t flags)
 
1591
{
 
1592
  if (!error ||
 
1593
      ((flags & HA_CHECK_DUP_KEY) &&
 
1594
       (error == HA_ERR_FOUND_DUPP_KEY ||
 
1595
        error == HA_ERR_FOUND_DUPP_UNIQUE)))
 
1596
    return false;
 
1597
  return true;
 
1598
}
 
1599
 
 
1600
 
 
1601
ha_rows handler::records() { return stats.records; }
1771
1602
 
1772
1603
/**
1773
1604
  Open database-handler.
1804
1635
    (void) extra(HA_EXTRA_NO_READCHECK);        // Not needed in SQL
1805
1636
 
1806
1637
    /* ref is already allocated for us if we're called from handler::clone() */
1807
 
    if (!ref && !(ref= (unsigned char*) alloc_root(&table->mem_root, 
 
1638
    if (!ref && !(ref= (unsigned char*) alloc_root(&table->mem_root,
1808
1639
                                          ALIGN_SIZE(ref_length)*2)))
1809
1640
    {
1810
1641
      close();
1898
1729
void handler::adjust_next_insert_id_after_explicit_value(uint64_t nr)
1899
1730
{
1900
1731
  /*
1901
 
    If we have set THD::next_insert_id previously and plan to insert an
 
1732
    If we have set Session::next_insert_id previously and plan to insert an
1902
1733
    explicitely-specified value larger than this, we need to increase
1903
 
    THD::next_insert_id to be greater than the explicit value.
 
1734
    Session::next_insert_id to be greater than the explicit value.
1904
1735
  */
1905
1736
  if ((next_insert_id > 0) && (nr >= next_insert_id))
1906
1737
    set_next_insert_id(compute_next_insert_id(nr, &table->in_use->variables));
1976
1807
    again to reserve a new interval.
1977
1808
 
1978
1809
  - In both cases, the reserved intervals are remembered in
1979
 
    thd->auto_inc_intervals_in_cur_stmt_for_binlog if statement-based
 
1810
    session->auto_inc_intervals_in_cur_stmt_for_binlog if statement-based
1980
1811
    binlogging; the last reserved interval is remembered in
1981
1812
    auto_inc_interval_for_cur_row.
1982
1813
 
1990
1821
    start counting from the inserted value.
1991
1822
 
1992
1823
    This function's "outputs" are: the table's auto_increment field is filled
1993
 
    with a value, thd->next_insert_id is filled with the value to use for the
 
1824
    with a value, session->next_insert_id is filled with the value to use for the
1994
1825
    next row, if a value was autogenerated for the current row it is stored in
1995
 
    thd->insert_id_for_cur_row, if get_auto_increment() was called
1996
 
    thd->auto_inc_interval_for_cur_row is modified, if that interval is not
1997
 
    present in thd->auto_inc_intervals_in_cur_stmt_for_binlog it is added to
 
1826
    session->insert_id_for_cur_row, if get_auto_increment() was called
 
1827
    session->auto_inc_interval_for_cur_row is modified, if that interval is not
 
1828
    present in session->auto_inc_intervals_in_cur_stmt_for_binlog it is added to
1998
1829
    this list.
1999
1830
 
2000
1831
  @todo
2021
1852
{
2022
1853
  uint64_t nr, nb_reserved_values;
2023
1854
  bool append= false;
2024
 
  THD *thd= table->in_use;
2025
 
  struct system_variables *variables= &thd->variables;
 
1855
  Session *session= table->in_use;
 
1856
  struct system_variables *variables= &session->variables;
2026
1857
 
2027
1858
  /*
2028
1859
    next_insert_id is a "cursor" into the reserved interval, it may go greater
2047
1878
  {
2048
1879
    /* next_insert_id is beyond what is reserved, so we reserve more. */
2049
1880
    const Discrete_interval *forced=
2050
 
      thd->auto_inc_intervals_forced.get_next();
 
1881
      session->auto_inc_intervals_forced.get_next();
2051
1882
    if (forced != NULL)
2052
1883
    {
2053
1884
      nr= forced->minimum();
2060
1891
        handler::ha_start_bulk_insert(); if 0 it means "unknown".
2061
1892
      */
2062
1893
      uint32_t nb_already_reserved_intervals=
2063
 
        thd->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements();
 
1894
        session->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements();
2064
1895
      uint64_t nb_desired_values;
2065
1896
      /*
2066
1897
        If an estimation was given to the engine:
2081
1912
        /* avoid overflow in formula, with this if() */
2082
1913
        if (nb_already_reserved_intervals <= AUTO_INC_DEFAULT_NB_MAX_BITS)
2083
1914
        {
2084
 
          nb_desired_values= AUTO_INC_DEFAULT_NB_ROWS * 
 
1915
          nb_desired_values= AUTO_INC_DEFAULT_NB_ROWS *
2085
1916
            (1 << nb_already_reserved_intervals);
2086
1917
          set_if_smaller(nb_desired_values, AUTO_INC_DEFAULT_NB_MAX);
2087
1918
        }
2095
1926
                         &nb_reserved_values);
2096
1927
      if (nr == ~(uint64_t) 0)
2097
1928
        return(HA_ERR_AUTOINC_READ_FAILED);  // Mark failure
2098
 
      
 
1929
 
2099
1930
      /*
2100
1931
        That rounding below should not be needed when all engines actually
2101
1932
        respect offset and increment in get_auto_increment(). But they don't
2106
1937
      */
2107
1938
      nr= compute_next_insert_id(nr-1, variables);
2108
1939
    }
2109
 
    
 
1940
 
2110
1941
    if (table->s->next_number_keypart == 0)
2111
1942
    {
2112
1943
      /* We must defer the appending until "nr" has been possibly truncated */
2119
1950
    /*
2120
1951
      first test if the query was aborted due to strict mode constraints
2121
1952
    */
2122
 
    if (thd->killed == THD::KILL_BAD_DATA)
 
1953
    if (session->killed == Session::KILL_BAD_DATA)
2123
1954
      return(HA_ERR_AUTOINC_ERANGE);
2124
1955
 
2125
1956
    /*
2138
1969
  {
2139
1970
    auto_inc_interval_for_cur_row.replace(nr, nb_reserved_values,
2140
1971
                                          variables->auto_increment_increment);
2141
 
    /* Row-based replication does not need to store intervals in binlog */
2142
 
    if (!thd->current_stmt_binlog_row_based)
2143
 
        thd->auto_inc_intervals_in_cur_stmt_for_binlog.append(auto_inc_interval_for_cur_row.minimum(),
2144
 
                                                              auto_inc_interval_for_cur_row.values(),
2145
 
                                                              variables->auto_increment_increment);
2146
1972
  }
2147
1973
 
2148
1974
  /*
2196
2022
  @param first_value         (OUT) the first value reserved by the handler
2197
2023
  @param nb_reserved_values  (OUT) how many values the handler reserved
2198
2024
*/
2199
 
void handler::get_auto_increment(uint64_t offset __attribute__((unused)),
2200
 
                                 uint64_t increment __attribute__((unused)),
2201
 
                                 uint64_t nb_desired_values __attribute__((unused)),
 
2025
void handler::get_auto_increment(uint64_t ,
 
2026
                                 uint64_t ,
 
2027
                                 uint64_t ,
2202
2028
                                 uint64_t *first_value,
2203
2029
                                 uint64_t *nb_reserved_values)
2204
2030
{
2461
2287
    my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
2462
2288
               ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
2463
2289
    return;
2464
 
    break;
2465
2290
  default:
2466
2291
    {
2467
2292
      /* The error was "unknown" to this function.
2496
2321
  @return
2497
2322
    Returns true if this is a temporary error
2498
2323
*/
2499
 
bool handler::get_error_message(int error __attribute__((unused)),
2500
 
                                String* buf __attribute__((unused)))
 
2324
bool handler::get_error_message(int ,
 
2325
                                String* )
2501
2326
{
2502
2327
  return false;
2503
2328
}
2524
2349
        Field *field= table->field[keypart->fieldnr-1];
2525
2350
        if (field->type() == DRIZZLE_TYPE_BLOB)
2526
2351
        {
2527
 
          if (check_opt->sql_flags & TT_FOR_UPGRADE)
2528
 
            check_opt->flags= T_MEDIUM;
2529
2352
          return HA_ADMIN_NEEDS_CHECK;
2530
2353
        }
2531
2354
      }
2541
2364
  return 0;
2542
2365
}
2543
2366
 
2544
 
 
2545
 
static bool update_frm_version(Table *table)
2546
 
{
2547
 
  char path[FN_REFLEN];
2548
 
  File file;
2549
 
  bool result= true;
2550
 
 
2551
 
  /*
2552
 
    No need to update frm version in case table was created or checked
2553
 
    by server with the same version. This also ensures that we do not
2554
 
    update frm version for temporary tables as this code doesn't support
2555
 
    temporary tables.
2556
 
  */
2557
 
  if (table->s->mysql_version == DRIZZLE_VERSION_ID)
2558
 
    return(0);
2559
 
 
2560
 
  strxmov(path, table->s->normalized_path.str, reg_ext, NULL);
2561
 
 
2562
 
  if ((file= my_open(path, O_RDWR|O_BINARY, MYF(MY_WME))) >= 0)
2563
 
  {
2564
 
    unsigned char version[4];
2565
 
    char *key= table->s->table_cache_key.str;
2566
 
    uint32_t key_length= table->s->table_cache_key.length;
2567
 
    Table *entry;
2568
 
    HASH_SEARCH_STATE state;
2569
 
 
2570
 
    int4store(version, DRIZZLE_VERSION_ID);
2571
 
 
2572
 
    if (pwrite(file, (unsigned char*)version, 4, 51L) == 0)
2573
 
    {
2574
 
      result= false;
2575
 
      goto err;
2576
 
    }
2577
 
 
2578
 
    for (entry=(Table*) hash_first(&open_cache,(unsigned char*) key,key_length, &state);
2579
 
         entry;
2580
 
         entry= (Table*) hash_next(&open_cache,(unsigned char*) key,key_length, &state))
2581
 
      entry->s->mysql_version= DRIZZLE_VERSION_ID;
2582
 
  }
2583
 
err:
2584
 
  if (file >= 0)
2585
 
    my_close(file,MYF(MY_WME));
2586
 
  return(result);
2587
 
}
2588
 
 
2589
 
 
2590
 
 
2591
2367
/**
2592
2368
  @return
2593
2369
    key if error because of duplicated keys
2666
2442
/**
2667
2443
  Performs checks upon the table.
2668
2444
 
2669
 
  @param thd                thread doing CHECK Table operation
 
2445
  @param session                thread doing CHECK Table operation
2670
2446
  @param check_opt          options from the parser
2671
2447
 
2672
2448
  @retval
2678
2454
  @retval
2679
2455
    HA_ADMIN_NOT_IMPLEMENTED
2680
2456
*/
2681
 
int handler::ha_check(THD *thd, HA_CHECK_OPT *check_opt)
 
2457
int handler::ha_check(Session *session, HA_CHECK_OPT *check_opt)
2682
2458
{
2683
2459
  int error;
2684
2460
 
2685
 
  if ((table->s->mysql_version >= DRIZZLE_VERSION_ID) &&
2686
 
      (check_opt->sql_flags & TT_FOR_UPGRADE))
2687
 
    return 0;
2688
 
 
2689
2461
  if (table->s->mysql_version < DRIZZLE_VERSION_ID)
2690
2462
  {
2691
2463
    if ((error= check_old_types()))
2693
2465
    error= ha_check_for_upgrade(check_opt);
2694
2466
    if (error && (error != HA_ADMIN_NEEDS_CHECK))
2695
2467
      return error;
2696
 
    if (!error && (check_opt->sql_flags & TT_FOR_UPGRADE))
2697
 
      return 0;
2698
2468
  }
2699
 
  if ((error= check(thd, check_opt)))
 
2469
  if ((error= check(session, check_opt)))
2700
2470
    return error;
2701
 
  return update_frm_version(table);
 
2471
  return HA_ADMIN_OK;
2702
2472
}
2703
2473
 
2704
2474
/**
2710
2480
void
2711
2481
handler::mark_trx_read_write()
2712
2482
{
2713
 
  Ha_trx_info *ha_info= &ha_thd()->ha_data[ht->slot].ha_info[0];
 
2483
  Ha_trx_info *ha_info= &ha_session()->ha_data[ht->slot].ha_info[0];
2714
2484
  /*
2715
2485
    When a storage engine method is called, the transaction must
2716
2486
    have been started, unless it's a DDL call, for which the
2721
2491
  */
2722
2492
  if (ha_info->is_started())
2723
2493
  {
2724
 
    assert(has_transactions());
2725
2494
    /*
2726
2495
      table_share can be NULL in ha_delete_table(). See implementation
2727
2496
      of standalone function ha_delete_table() in sql_base.cc.
2738
2507
  @sa handler::repair()
2739
2508
*/
2740
2509
 
2741
 
int handler::ha_repair(THD* thd, HA_CHECK_OPT* check_opt)
 
2510
int handler::ha_repair(Session* session, HA_CHECK_OPT* check_opt)
2742
2511
{
2743
2512
  int result;
2744
2513
 
2745
2514
  mark_trx_read_write();
2746
2515
 
2747
 
  if ((result= repair(thd, check_opt)))
 
2516
  if ((result= repair(session, check_opt)))
2748
2517
    return result;
2749
 
  return update_frm_version(table);
 
2518
  return HA_ADMIN_OK;
2750
2519
}
2751
2520
 
2752
2521
 
2803
2572
*/
2804
2573
 
2805
2574
int
2806
 
handler::ha_optimize(THD* thd, HA_CHECK_OPT* check_opt)
 
2575
handler::ha_optimize(Session* session, HA_CHECK_OPT* check_opt)
2807
2576
{
2808
2577
  mark_trx_read_write();
2809
2578
 
2810
 
  return optimize(thd, check_opt);
 
2579
  return optimize(session, check_opt);
2811
2580
}
2812
2581
 
2813
2582
 
2818
2587
*/
2819
2588
 
2820
2589
int
2821
 
handler::ha_analyze(THD* thd, HA_CHECK_OPT* check_opt)
 
2590
handler::ha_analyze(Session* session, HA_CHECK_OPT* check_opt)
2822
2591
{
2823
2592
  mark_trx_read_write();
2824
2593
 
2825
 
  return analyze(thd, check_opt);
 
2594
  return analyze(session, check_opt);
2826
2595
}
2827
2596
 
2828
2597
 
2833
2602
*/
2834
2603
 
2835
2604
bool
2836
 
handler::ha_check_and_repair(THD *thd)
 
2605
handler::ha_check_and_repair(Session *session)
2837
2606
{
2838
2607
  mark_trx_read_write();
2839
2608
 
2840
 
  return check_and_repair(thd);
 
2609
  return check_and_repair(session);
2841
2610
}
2842
2611
 
2843
2612
 
2955
2724
*/
2956
2725
 
2957
2726
int
2958
 
handler::ha_create(const char *name, Table *form, HA_CREATE_INFO *info)
 
2727
handler::ha_create(const char *name, Table *form, HA_CREATE_INFO *create_info)
2959
2728
{
2960
2729
  mark_trx_read_write();
2961
2730
 
2962
 
  return create(name, form, info);
 
2731
  return create(name, form, create_info);
2963
2732
}
2964
2733
 
2965
2734
 
2971
2740
 
2972
2741
int
2973
2742
handler::ha_create_handler_files(const char *name, const char *old_name,
2974
 
                        int action_flag, HA_CREATE_INFO *info)
 
2743
                                 int action_flag, HA_CREATE_INFO *create_info)
2975
2744
{
2976
2745
  mark_trx_read_write();
2977
2746
 
2978
 
  return create_handler_files(name, old_name, action_flag, info);
 
2747
  return create_handler_files(name, old_name, action_flag, create_info);
2979
2748
}
2980
2749
 
2981
2750
 
2987
2756
  starts to commit every now and then automatically.
2988
2757
  This hint can be safely ignored.
2989
2758
*/
2990
 
int ha_enable_transaction(THD *thd, bool on)
 
2759
int ha_enable_transaction(Session *session, bool on)
2991
2760
{
2992
2761
  int error=0;
2993
2762
 
2994
 
  if ((thd->transaction.on= on))
 
2763
  if ((session->transaction.on= on))
2995
2764
  {
2996
2765
    /*
2997
2766
      Now all storage engines should have transaction handling enabled.
2999
2768
      is an optimization hint that storage engine is free to ignore.
3000
2769
      So, let's commit an open transaction (if any) now.
3001
2770
    */
3002
 
    if (!(error= ha_commit_trans(thd, 0)))
3003
 
      error= end_trans(thd, COMMIT);
 
2771
    if (!(error= ha_commit_trans(session, 0)))
 
2772
      error= end_trans(session, COMMIT);
3004
2773
  }
3005
2774
  return(error);
3006
2775
}
3068
2837
  @retval
3069
2838
   1  error
3070
2839
*/
3071
 
int ha_create_table(THD *thd, const char *path,
 
2840
int ha_create_table(Session *session, const char *path,
3072
2841
                    const char *db, const char *table_name,
3073
2842
                    HA_CREATE_INFO *create_info,
3074
2843
                    bool update_create_info)
3078
2847
  char name_buff[FN_REFLEN];
3079
2848
  const char *name;
3080
2849
  TABLE_SHARE share;
3081
 
  
3082
 
  init_tmp_table_share(thd, &share, db, 0, table_name, path);
3083
 
  if (open_table_def(thd, &share, 0) ||
3084
 
      open_table_from_share(thd, &share, "", 0, (uint) READ_ALL, 0, &table,
 
2850
 
 
2851
  init_tmp_table_share(session, &share, db, 0, table_name, path);
 
2852
  if (open_table_def(session, &share, 0) ||
 
2853
      open_table_from_share(session, &share, "", 0, (uint) READ_ALL, 0, &table,
3085
2854
                            OTM_CREATE))
3086
2855
    goto err;
3087
2856
 
3091
2860
  name= check_lowercase_names(table.file, share.path.str, name_buff);
3092
2861
 
3093
2862
  error= table.file->ha_create(name, &table, create_info);
3094
 
  closefrm(&table, 0);
 
2863
  table.closefrm(false);
3095
2864
  if (error)
3096
2865
  {
3097
 
    strxmov(name_buff, db, ".", table_name, NULL);
 
2866
    sprintf(name_buff,"%s.%s",db,table_name);
3098
2867
    my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), name_buff, error);
3099
2868
  }
3100
2869
err:
3102
2871
  return(error != 0);
3103
2872
}
3104
2873
 
3105
 
/**
3106
 
  Try to discover table from engine.
3107
 
 
3108
 
  @note
3109
 
    If found, write the frm file to disk.
3110
 
 
3111
 
  @retval
3112
 
  -1    Table did not exists
3113
 
  @retval
3114
 
   0    Table created ok
3115
 
  @retval
3116
 
   > 0  Error, table existed but could not be created
3117
 
*/
3118
 
int ha_create_table_from_engine(THD* thd, const char *db, const char *name)
3119
 
{
3120
 
  int error;
3121
 
  unsigned char *frmblob;
3122
 
  size_t frmlen;
3123
 
  char path[FN_REFLEN];
3124
 
  HA_CREATE_INFO create_info;
3125
 
  Table table;
3126
 
  TABLE_SHARE share;
3127
 
 
3128
 
  memset(&create_info, 0, sizeof(create_info));
3129
 
  if ((error= ha_discover(thd, db, name, &frmblob, &frmlen)))
3130
 
  {
3131
 
    /* Table could not be discovered and thus not created */
3132
 
    return(error);
3133
 
  }
3134
 
 
3135
 
  /*
3136
 
    Table exists in handler and could be discovered
3137
 
    frmblob and frmlen are set, write the frm to disk
3138
 
  */
3139
 
 
3140
 
  build_table_filename(path, FN_REFLEN-1, db, name, "", 0);
3141
 
  // Save the frm file
3142
 
  error= writefrm(path, frmblob, frmlen);
3143
 
  free(frmblob);
3144
 
  if (error)
3145
 
    return(2);
3146
 
 
3147
 
  init_tmp_table_share(thd, &share, db, 0, name, path);
3148
 
  if (open_table_def(thd, &share, 0))
3149
 
  {
3150
 
    return(3);
3151
 
  }
3152
 
  if (open_table_from_share(thd, &share, "" ,0, 0, 0, &table, OTM_OPEN))
3153
 
  {
3154
 
    free_table_share(&share);
3155
 
    return(3);
3156
 
  }
3157
 
 
3158
 
  table.updateCreateInfo(&create_info);
3159
 
  create_info.table_options|= HA_OPTION_CREATE_FROM_ENGINE;
3160
 
 
3161
 
  check_lowercase_names(table.file, path, path);
3162
 
  error=table.file->ha_create(path, &table, &create_info);
3163
 
  closefrm(&table, 1);
3164
 
 
3165
 
  return(error != 0);
3166
 
}
3167
 
 
3168
2874
void st_ha_check_opt::init()
3169
2875
{
3170
 
  flags= sql_flags= 0;
3171
 
  sort_buffer_size = current_thd->variables.myisam_sort_buff_size;
 
2876
  flags= 0; 
 
2877
  use_frm= false;
3172
2878
}
3173
2879
 
3174
2880
 
3185
2891
/**
3186
2892
  Init a key cache if it has not been initied before.
3187
2893
*/
3188
 
int ha_init_key_cache(const char *name __attribute__((unused)),
 
2894
int ha_init_key_cache(const char *,
3189
2895
                      KEY_CACHE *key_cache)
3190
2896
{
3191
2897
  if (!key_cache->key_cache_inited)
3261
2967
  return 0;
3262
2968
}
3263
2969
 
3264
 
 
3265
 
/**
3266
 
  Try to discover one table from handler(s).
3267
 
 
3268
 
  @retval
3269
 
    -1   Table did not exists
3270
 
  @retval
3271
 
    0   OK. In this case *frmblob and *frmlen are set
3272
 
  @retval
3273
 
    >0   error.  frmblob and frmlen may not be set
3274
 
*/
3275
 
struct st_discover_args
3276
 
{
3277
 
  const char *db;
3278
 
  const char *name;
3279
 
  unsigned char **frmblob; 
3280
 
  size_t *frmlen;
3281
 
};
3282
 
 
3283
 
static bool discover_handlerton(THD *thd, plugin_ref plugin,
3284
 
                                void *arg)
3285
 
{
3286
 
  st_discover_args *vargs= (st_discover_args *)arg;
3287
 
  handlerton *hton= plugin_data(plugin, handlerton *);
3288
 
  if (hton->state == SHOW_OPTION_YES && hton->discover &&
3289
 
      (!(hton->discover(hton, thd, vargs->db, vargs->name, 
3290
 
                        vargs->frmblob, 
3291
 
                        vargs->frmlen))))
3292
 
    return true;
3293
 
 
3294
 
  return false;
3295
 
}
3296
 
 
3297
 
int ha_discover(THD *thd, const char *db, const char *name,
3298
 
                unsigned char **frmblob, size_t *frmlen)
3299
 
{
3300
 
  int error= -1; // Table does not exist in any handler
3301
 
  st_discover_args args= {db, name, frmblob, frmlen};
3302
 
 
3303
 
  if (is_prefix(name,tmp_file_prefix)) /* skip temporary tables */
3304
 
    return(error);
3305
 
 
3306
 
  if (plugin_foreach(thd, discover_handlerton,
3307
 
                 DRIZZLE_STORAGE_ENGINE_PLUGIN, &args))
3308
 
    error= 0;
3309
 
 
3310
 
  if (!error)
3311
 
    status_var_increment(thd->status_var.ha_discover_count);
3312
 
  return(error);
3313
 
}
3314
 
 
3315
 
 
3316
2970
/**
3317
2971
  Call this function in order to give the handler the possiblity
3318
2972
  to ask engine if there are any new tables that should be written to disk
3341
2995
  const char *db;
3342
2996
  const char *name;
3343
2997
  int err;
 
2998
  handlerton* hton;
3344
2999
};
3345
3000
 
3346
 
static bool table_exists_in_engine_handlerton(THD *thd, plugin_ref plugin,
 
3001
static bool table_exists_in_engine_handlerton(Session *session, plugin_ref plugin,
3347
3002
                                              void *arg)
3348
3003
{
3349
3004
  st_table_exists_in_engine_args *vargs= (st_table_exists_in_engine_args *)arg;
3352
3007
  int err= HA_ERR_NO_SUCH_TABLE;
3353
3008
 
3354
3009
  if (hton->state == SHOW_OPTION_YES && hton->table_exists_in_engine)
3355
 
    err = hton->table_exists_in_engine(hton, thd, vargs->db, vargs->name);
 
3010
    err = hton->table_exists_in_engine(hton, session, vargs->db, vargs->name);
3356
3011
 
3357
3012
  vargs->err = err;
3358
3013
  if (vargs->err == HA_ERR_TABLE_EXIST)
 
3014
  {
 
3015
    vargs->hton= hton;
3359
3016
    return true;
 
3017
  }
3360
3018
 
3361
3019
  return false;
3362
3020
}
3363
3021
 
3364
 
int ha_table_exists_in_engine(THD* thd, const char* db, const char* name)
 
3022
int ha_table_exists_in_engine(Session* session,
 
3023
                              const char* db, const char* name,
 
3024
                              handlerton **hton)
3365
3025
{
3366
 
  st_table_exists_in_engine_args args= {db, name, HA_ERR_NO_SUCH_TABLE};
3367
 
  plugin_foreach(thd, table_exists_in_engine_handlerton,
 
3026
  st_table_exists_in_engine_args args= {db, name, HA_ERR_NO_SUCH_TABLE, NULL};
 
3027
  plugin_foreach(session, table_exists_in_engine_handlerton,
3368
3028
                 DRIZZLE_STORAGE_ENGINE_PLUGIN, &args);
 
3029
 
 
3030
  if(args.err==HA_ERR_NO_SUCH_TABLE)
 
3031
  {
 
3032
    /* Default way of knowing if a table exists. (checking .frm exists) */
 
3033
 
 
3034
    char path[FN_REFLEN];
 
3035
    build_table_filename(path, sizeof(path),
 
3036
                         db, name, ".dfe", 0);
 
3037
    if (!access(path, F_OK))
 
3038
      args.err= HA_ERR_TABLE_EXIST;
 
3039
    else
 
3040
      args.err= HA_ERR_NO_SUCH_TABLE;
 
3041
 
 
3042
    if(args.err==HA_ERR_TABLE_EXIST)
 
3043
    {
 
3044
      drizzle::Table table;
 
3045
      if(drizzle_read_table_proto(path, &table)==0)
 
3046
      {
 
3047
        LEX_STRING engine_name= { (char*)table.engine().name().c_str(),
 
3048
                                 strlen(table.engine().name().c_str()) };
 
3049
        plugin_ref plugin= ha_resolve_by_name(session, &engine_name);
 
3050
        if(plugin)
 
3051
          args.hton= plugin_data(plugin,handlerton *);
 
3052
      }
 
3053
    }
 
3054
  }
 
3055
 
 
3056
  if(hton)
 
3057
    *hton= args.hton;
 
3058
 
3369
3059
  return(args.err);
3370
3060
}
3371
3061
 
3390
3080
    Estimated cost of 'index only' scan
3391
3081
*/
3392
3082
 
3393
 
double handler::index_only_read_time(uint32_t keynr, double records)
 
3083
double handler::index_only_read_time(uint32_t keynr, double key_records)
3394
3084
{
3395
 
  double read_time;
3396
3085
  uint32_t keys_per_block= (stats.block_size/2/
3397
3086
                        (table->key_info[keynr].key_length + ref_length) + 1);
3398
 
  read_time=((double) (records + keys_per_block-1) /
3399
 
             (double) keys_per_block);
3400
 
  return read_time;
 
3087
  return ((double) (key_records + keys_per_block-1) /
 
3088
          (double) keys_per_block);
3401
3089
}
3402
3090
 
3403
3091
 
3424
3112
 
3425
3113
  @note
3426
3114
    This method (or an overriding one in a derived class) must check for
3427
 
    thd->killed and return HA_POS_ERROR if it is not zero. This is required
 
3115
    session->killed and return HA_POS_ERROR if it is not zero. This is required
3428
3116
    for a user to be able to interrupt the calculation by killing the
3429
3117
    connection/query.
3430
3118
 
3439
3127
ha_rows
3440
3128
handler::multi_range_read_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
3441
3129
                                     void *seq_init_param,
3442
 
                                     uint32_t n_ranges_arg __attribute__((unused)),
 
3130
                                     uint32_t ,
3443
3131
                                     uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
3444
3132
{
3445
3133
  KEY_MULTI_RANGE range;
3446
3134
  range_seq_t seq_it;
3447
3135
  ha_rows rows, total_rows= 0;
3448
3136
  uint32_t n_ranges=0;
3449
 
  THD *thd= current_thd;
3450
 
  
 
3137
  Session *session= current_session;
 
3138
 
3451
3139
  /* Default MRR implementation doesn't need buffer */
3452
3140
  *bufsz= 0;
3453
3141
 
3454
3142
  seq_it= seq->init(seq_init_param, n_ranges, *flags);
3455
3143
  while (!seq->next(seq_it, &range))
3456
3144
  {
3457
 
    if (unlikely(thd->killed != 0))
 
3145
    if (unlikely(session->killed != 0))
3458
3146
      return HA_POS_ERROR;
3459
 
    
 
3147
 
3460
3148
    n_ranges++;
3461
3149
    key_range *min_endp, *max_endp;
3462
3150
    {
3467
3155
      rows= 1; /* there can be at most one row */
3468
3156
    else
3469
3157
    {
3470
 
      if (HA_POS_ERROR == (rows= this->records_in_range(keyno, min_endp, 
 
3158
      if (HA_POS_ERROR == (rows= this->records_in_range(keyno, min_endp,
3471
3159
                                                        max_endp)))
3472
3160
      {
3473
3161
        /* Can't scan one range => can't do MRR scan at all */
3477
3165
    }
3478
3166
    total_rows += rows;
3479
3167
  }
3480
 
  
 
3168
 
3481
3169
  if (total_rows != HA_POS_ERROR)
3482
3170
  {
3483
3171
    /* The following calculation is the same as in multi_range_read_info(): */
3550
3238
/**
3551
3239
  Initialize the MRR scan
3552
3240
 
3553
 
  Initialize the MRR scan. This function may do heavyweight scan 
 
3241
  Initialize the MRR scan. This function may do heavyweight scan
3554
3242
  initialization like row prefetching/sorting/etc (NOTE: but better not do
3555
3243
  it here as we may not need it, e.g. if we never satisfy WHERE clause on
3556
3244
  previous tables. For many implementations it would be natural to do such
3557
3245
  initializations in the first multi_read_range_next() call)
3558
3246
 
3559
3247
  mode is a combination of the following flags: HA_MRR_SORTED,
3560
 
  HA_MRR_INDEX_ONLY, HA_MRR_NO_ASSOCIATION 
 
3248
  HA_MRR_INDEX_ONLY, HA_MRR_NO_ASSOCIATION
3561
3249
 
3562
3250
  @param seq             Range sequence to be traversed
3563
3251
  @param seq_init_param  First parameter for seq->init()
3569
3257
    One must have called index_init() before calling this function. Several
3570
3258
    multi_range_read_init() calls may be made in course of one query.
3571
3259
 
3572
 
    Until WL#2623 is done (see its text, section 3.2), the following will 
 
3260
    Until WL#2623 is done (see its text, section 3.2), the following will
3573
3261
    also hold:
3574
3262
    The caller will guarantee that if "seq->init == mrr_ranges_array_init"
3575
3263
    then seq_init_param is an array of n_ranges KEY_MULTI_RANGE structures.
3576
3264
    This property will only be used by NDB handler until WL#2623 is done.
3577
 
     
 
3265
 
3578
3266
    Buffer memory management is done according to the following scenario:
3579
3267
    The caller allocates the buffer and provides it to the callee by filling
3580
3268
    the members of HANDLER_BUFFER structure.
3591
3279
int
3592
3280
handler::multi_range_read_init(RANGE_SEQ_IF *seq_funcs, void *seq_init_param,
3593
3281
                               uint32_t n_ranges, uint32_t mode,
3594
 
                               HANDLER_BUFFER *buf __attribute__((unused)))
 
3282
                               HANDLER_BUFFER *)
3595
3283
{
3596
3284
  mrr_iter= seq_funcs->init(seq_init_param, n_ranges, mode);
3597
3285
  mrr_funcs= *seq_funcs;
3669
3357
 
3670
3358
 
3671
3359
/* **************************************************************************
3672
 
 * DS-MRR implementation 
 
3360
 * DS-MRR implementation
3673
3361
 ***************************************************************************/
3674
3362
 
3675
3363
/**
3690
3378
  @retval other Error
3691
3379
*/
3692
3380
 
3693
 
int DsMrr_impl::dsmrr_init(handler *h, KEY *key,
 
3381
int DsMrr_impl::dsmrr_init(handler *h_in, KEY *key,
3694
3382
                           RANGE_SEQ_IF *seq_funcs, void *seq_init_param,
3695
3383
                           uint32_t n_ranges, uint32_t mode, HANDLER_BUFFER *buf)
3696
3384
{
3698
3386
  uint32_t keyno;
3699
3387
  Item *pushed_cond= NULL;
3700
3388
  handler *new_h2;
3701
 
  keyno= h->active_index;
 
3389
  keyno= h_in->active_index;
3702
3390
  assert(h2 == NULL);
3703
3391
  if (mode & HA_MRR_USE_DEFAULT_IMPL || mode & HA_MRR_SORTED)
3704
3392
  {
3705
3393
    use_default_impl= true;
3706
 
    return(h->handler::multi_range_read_init(seq_funcs, seq_init_param,
 
3394
    return(h_in->handler::multi_range_read_init(seq_funcs, seq_init_param,
3707
3395
                                                  n_ranges, mode, buf));
3708
3396
  }
3709
3397
  rowids_buf= buf->buffer;
3710
3398
  //psergey-todo: don't add key_length as it is not needed anymore
3711
 
  rowids_buf += key->key_length + h->ref_length;
 
3399
  rowids_buf += key->key_length + h_in->ref_length;
3712
3400
 
3713
3401
  is_mrr_assoc= !test(mode & HA_MRR_NO_ASSOCIATION);
3714
3402
  rowids_buf_end= buf->buffer_end;
3715
 
  
3716
 
  elem_size= h->ref_length + (int)is_mrr_assoc * sizeof(void*);
3717
 
  rowids_buf_last= rowids_buf + 
 
3403
 
 
3404
  elem_size= h_in->ref_length + (int)is_mrr_assoc * sizeof(void*);
 
3405
  rowids_buf_last= rowids_buf +
3718
3406
                      ((rowids_buf_end - rowids_buf)/ elem_size)*
3719
3407
                      elem_size;
3720
3408
  rowids_buf_end= rowids_buf_last;
3721
3409
 
3722
3410
  /* Create a separate handler object to do rndpos() calls. */
3723
 
  THD *thd= current_thd;
3724
 
  if (!(new_h2= h->clone(thd->mem_root)) || 
3725
 
      new_h2->ha_external_lock(thd, F_RDLCK))
 
3411
  Session *session= current_session;
 
3412
  if (!(new_h2= h_in->clone(session->mem_root)) ||
 
3413
      new_h2->ha_external_lock(session, F_RDLCK))
3726
3414
  {
3727
3415
    delete new_h2;
3728
3416
    return(1);
3729
3417
  }
3730
3418
 
3731
 
  if (keyno == h->pushed_idx_cond_keyno)
3732
 
    pushed_cond= h->pushed_idx_cond;
3733
 
  if (h->ha_index_end())
 
3419
  if (keyno == h_in->pushed_idx_cond_keyno)
 
3420
    pushed_cond= h_in->pushed_idx_cond;
 
3421
  if (h_in->ha_index_end())
3734
3422
  {
3735
3423
    new_h2= h2;
3736
3424
    goto error;
3740
3428
  table->prepare_for_position();
3741
3429
  new_h2->extra(HA_EXTRA_KEYREAD);
3742
3430
 
3743
 
  if (h2->ha_index_init(keyno, false) || 
 
3431
  if (h2->ha_index_init(keyno, false) ||
3744
3432
      h2->handler::multi_range_read_init(seq_funcs, seq_init_param, n_ranges,
3745
3433
                                         mode, buf))
3746
3434
    goto error;
3747
3435
  use_default_impl= false;
3748
 
  
 
3436
 
3749
3437
  if (pushed_cond)
3750
3438
    h2->idx_cond_push(keyno, pushed_cond);
3751
3439
  if (dsmrr_fill_buffer(new_h2))
3755
3443
    If the above call has scanned through all intervals in *seq, then
3756
3444
    adjust *buf to indicate that the remaining buffer space will not be used.
3757
3445
  */
3758
 
  if (dsmrr_eof) 
 
3446
  if (dsmrr_eof)
3759
3447
    buf->end_of_used_area= rowids_buf_last;
3760
3448
 
3761
 
  if (h->ha_rnd_init(false))
 
3449
  if (h_in->ha_rnd_init(false))
3762
3450
    goto error;
3763
 
  
 
3451
 
3764
3452
  return(0);
3765
3453
error:
3766
3454
  h2->ha_index_or_rnd_end();
3767
 
  h2->ha_external_lock(thd, F_UNLCK);
 
3455
  h2->ha_external_lock(session, F_UNLCK);
3768
3456
  h2->close();
3769
3457
  delete h2;
3770
3458
  return(1);
3775
3463
{
3776
3464
  if (h2)
3777
3465
  {
3778
 
    h2->ha_external_lock(current_thd, F_UNLCK);
 
3466
    h2->ha_external_lock(current_session, F_UNLCK);
3779
3467
    h2->close();
3780
3468
    delete h2;
3781
3469
    h2= NULL;
3795
3483
  DS-MRR: Fill the buffer with rowids and sort it by rowid
3796
3484
 
3797
3485
  {This is an internal function of DiskSweep MRR implementation}
3798
 
  Scan the MRR ranges and collect ROWIDs (or {ROWID, range_id} pairs) into 
3799
 
  buffer. When the buffer is full or scan is completed, sort the buffer by 
 
3486
  Scan the MRR ranges and collect ROWIDs (or {ROWID, range_id} pairs) into
 
3487
  buffer. When the buffer is full or scan is completed, sort the buffer by
3800
3488
  rowid and return.
3801
 
  
3802
 
  The function assumes that rowids buffer is empty when it is invoked. 
3803
 
  
 
3489
 
 
3490
  The function assumes that rowids buffer is empty when it is invoked.
 
3491
 
3804
3492
  @param h  Table handler
3805
3493
 
3806
3494
  @retval 0      OK, the next portion of rowids is in the buffer,
3808
3496
  @retval other  Error
3809
3497
*/
3810
3498
 
3811
 
int DsMrr_impl::dsmrr_fill_buffer(handler *unused __attribute__((unused)))
 
3499
int DsMrr_impl::dsmrr_fill_buffer(handler *)
3812
3500
{
3813
3501
  char *range_info;
3814
3502
  int res = 0;
3815
3503
 
3816
3504
  rowids_buf_cur= rowids_buf;
3817
 
  while ((rowids_buf_cur < rowids_buf_end) && 
 
3505
  while ((rowids_buf_cur < rowids_buf_end) &&
3818
3506
         !(res= h2->handler::multi_range_read_next(&range_info)))
3819
3507
  {
3820
3508
    /* Put rowid, or {rowid, range_id} pair into the buffer */
3830
3518
  }
3831
3519
 
3832
3520
  if (res && res != HA_ERR_END_OF_FILE)
3833
 
    return(res); 
 
3521
    return(res);
3834
3522
  dsmrr_eof= test(res == HA_ERR_END_OF_FILE);
3835
3523
 
3836
3524
  /* Sort the buffer contents by rowid */
3837
3525
  uint32_t elem_size= h->ref_length + (int)is_mrr_assoc * sizeof(void*);
3838
3526
  uint32_t n_rowids= (rowids_buf_cur - rowids_buf) / elem_size;
3839
 
  
 
3527
 
3840
3528
  my_qsort2(rowids_buf, n_rowids, elem_size, (qsort2_cmp)rowid_cmp,
3841
3529
            (void*)h);
3842
3530
  rowids_buf_last= rowids_buf_cur;
3849
3537
  DS-MRR implementation: multi_range_read_next() function
3850
3538
*/
3851
3539
 
3852
 
int DsMrr_impl::dsmrr_next(handler *h, char **range_info)
 
3540
int DsMrr_impl::dsmrr_next(handler *h_in, char **range_info)
3853
3541
{
3854
3542
  int res;
3855
 
  
 
3543
 
3856
3544
  if (use_default_impl)
3857
 
    return h->handler::multi_range_read_next(range_info);
3858
 
    
 
3545
    return h_in->handler::multi_range_read_next(range_info);
 
3546
 
3859
3547
  if (rowids_buf_cur == rowids_buf_last)
3860
3548
  {
3861
3549
    if (dsmrr_eof)
3867
3555
    if (res)
3868
3556
      goto end;
3869
3557
  }
3870
 
  
 
3558
 
3871
3559
  /* Return EOF if there are no rowids in the buffer after re-fill attempt */
3872
3560
  if (rowids_buf_cur == rowids_buf_last)
3873
3561
  {
3875
3563
    goto end;
3876
3564
  }
3877
3565
 
3878
 
  res= h->rnd_pos(table->record[0], rowids_buf_cur);
3879
 
  rowids_buf_cur += h->ref_length;
 
3566
  res= h_in->rnd_pos(table->record[0], rowids_buf_cur);
 
3567
  rowids_buf_cur += h_in->ref_length;
3880
3568
  if (is_mrr_assoc)
3881
3569
  {
3882
3570
    memcpy(range_info, rowids_buf_cur, sizeof(void*));
3895
3583
*/
3896
3584
int DsMrr_impl::dsmrr_info(uint32_t keyno, uint32_t n_ranges, uint32_t rows, uint32_t *bufsz,
3897
3585
                           uint32_t *flags, COST_VECT *cost)
3898
 
{  
 
3586
{
3899
3587
  int res;
3900
3588
  uint32_t def_flags= *flags;
3901
3589
  uint32_t def_bufsz= *bufsz;
3905
3593
                                         &def_flags, cost);
3906
3594
  assert(!res);
3907
3595
 
3908
 
  if ((*flags & HA_MRR_USE_DEFAULT_IMPL) || 
 
3596
  if ((*flags & HA_MRR_USE_DEFAULT_IMPL) ||
3909
3597
      choose_mrr_impl(keyno, rows, &def_flags, &def_bufsz, cost))
3910
3598
  {
3911
3599
    /* Default implementation is choosen */
3921
3609
*/
3922
3610
 
3923
3611
ha_rows DsMrr_impl::dsmrr_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
3924
 
                                 void *seq_init_param, uint32_t n_ranges, 
 
3612
                                 void *seq_init_param, uint32_t n_ranges,
3925
3613
                                 uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
3926
3614
{
3927
3615
  ha_rows rows;
3929
3617
  uint32_t def_bufsz= *bufsz;
3930
3618
  /* Get cost/flags/mem_usage of default MRR implementation */
3931
3619
  rows= h->handler::multi_range_read_info_const(keyno, seq, seq_init_param,
3932
 
                                                n_ranges, &def_bufsz, 
 
3620
                                                n_ranges, &def_bufsz,
3933
3621
                                                &def_flags, cost);
3934
3622
  if (rows == HA_POS_ERROR)
3935
3623
  {
4015
3703
{
4016
3704
  COST_VECT dsmrr_cost;
4017
3705
  bool res;
4018
 
  THD *thd= current_thd;
4019
 
  if ((thd->variables.optimizer_use_mrr == 2) || 
 
3706
  Session *session= current_session;
 
3707
  if ((session->variables.optimizer_use_mrr == 2) ||
4020
3708
      (*flags & HA_MRR_INDEX_ONLY) || (*flags & HA_MRR_SORTED) ||
4021
 
      (keyno == table->s->primary_key && 
4022
 
       h->primary_key_is_clustered()) || 
 
3709
      (keyno == table->s->primary_key &&
 
3710
       h->primary_key_is_clustered()) ||
4023
3711
       key_uses_partial_cols(keyno))
4024
3712
  {
4025
3713
    /* Use the default implementation */
4026
3714
    *flags |= HA_MRR_USE_DEFAULT_IMPL;
4027
3715
    return true;
4028
3716
  }
4029
 
  
4030
 
  uint32_t add_len= table->key_info[keyno].key_length + h->ref_length; 
 
3717
 
 
3718
  uint32_t add_len= table->key_info[keyno].key_length + h->ref_length;
4031
3719
  *bufsz -= add_len;
4032
3720
  if (get_disk_sweep_mrr_cost(keyno, rows, *flags, bufsz, &dsmrr_cost))
4033
3721
    return true;
4034
3722
  *bufsz += add_len;
4035
 
  
 
3723
 
4036
3724
  bool force_dsmrr;
4037
 
  /* 
 
3725
  /*
4038
3726
    If @@optimizer_use_mrr==force, then set cost of DS-MRR to be minimum of
4039
3727
    DS-MRR and Default implementations cost. This allows one to force use of
4040
3728
    DS-MRR whenever it is applicable without affecting other cost-based
4041
3729
    choices.
4042
3730
  */
4043
 
  if ((force_dsmrr= (thd->variables.optimizer_use_mrr == 1)) &&
 
3731
  if ((force_dsmrr= (session->variables.optimizer_use_mrr == 1)) &&
4044
3732
      dsmrr_cost.total_cost() > cost->total_cost())
4045
3733
    dsmrr_cost= *cost;
4046
3734
 
4093
3781
 
4094
3782
  /* Number of iterations we'll make with full buffer */
4095
3783
  n_full_steps= (uint)floor(rows2double(rows) / max_buff_entries);
4096
 
  
4097
 
  /* 
4098
 
    Get numbers of rows we'll be processing in 
4099
 
     - non-last sweep, with full buffer 
 
3784
 
 
3785
  /*
 
3786
    Get numbers of rows we'll be processing in
 
3787
     - non-last sweep, with full buffer
4100
3788
     - last iteration, with non-full buffer
4101
3789
  */
4102
3790
  rows_in_full_step= max_buff_entries;
4103
3791
  rows_in_last_step= rows % max_buff_entries;
4104
 
  
 
3792
 
4105
3793
  /* Adjust buffer size if we expect to use only part of the buffer */
4106
3794
  if (n_full_steps)
4107
3795
  {
4111
3799
  else
4112
3800
  {
4113
3801
    cost->zero();
4114
 
    *buffer_size= cmax((ulong)*buffer_size, 
4115
 
                      (size_t)(1.2*rows_in_last_step) * elem_size + 
 
3802
    *buffer_size= cmax((ulong)*buffer_size,
 
3803
                      (size_t)(1.2*rows_in_last_step) * elem_size +
4116
3804
                      h->ref_length + table->key_info[keynr].key_length);
4117
3805
  }
4118
 
  
 
3806
 
4119
3807
  COST_VECT last_step_cost;
4120
3808
  get_sort_and_sweep_cost(table, rows_in_last_step, &last_step_cost);
4121
3809
  cost->add(&last_step_cost);
4122
 
 
 
3810
 
4123
3811
  if (n_full_steps != 0)
4124
3812
    cost->mem_cost= *buffer_size;
4125
3813
  else
4126
3814
    cost->mem_cost= (double)rows_in_last_step * elem_size;
4127
 
  
 
3815
 
4128
3816
  /* Total cost of all index accesses */
4129
3817
  index_read_cost= h->index_only_read_time(keynr, (double)rows);
4130
3818
  cost->add_io(index_read_cost, 1 /* Random seeks */);
4132
3820
}
4133
3821
 
4134
3822
 
4135
 
/* 
 
3823
/*
4136
3824
  Get cost of one sort-and-sweep step
4137
3825
 
4138
3826
  SYNOPSIS
4147
3835
     - read #nrows records from table in a sweep.
4148
3836
*/
4149
3837
 
4150
 
static 
 
3838
static
4151
3839
void get_sort_and_sweep_cost(Table *table, ha_rows nrows, COST_VECT *cost)
4152
3840
{
4153
3841
  if (nrows)
4181
3869
  Time to move the disk head is proportional to head travel distance.
4182
3870
 
4183
3871
  Time to wait for the plate to rotate depends on whether the disk head
4184
 
  was moved or not. 
 
3872
  was moved or not.
4185
3873
 
4186
3874
  If disk head wasn't moved, the wait time is proportional to distance
4187
3875
  between the previous block and the block we're reading.
4192
3880
 
4193
3881
  Our cost units are "random disk seeks". The cost of random disk seek is
4194
3882
  actually not a constant, it depends one range of cylinders we're going
4195
 
  to access. We make it constant by introducing a fuzzy concept of "typical 
 
3883
  to access. We make it constant by introducing a fuzzy concept of "typical
4196
3884
  datafile length" (it's fuzzy as it's hard to tell whether it should
4197
3885
  include index file, temp.tables etc). Then random seek cost is:
4198
3886
 
4207
3895
  @param cost         OUT  The cost.
4208
3896
*/
4209
3897
 
4210
 
void get_sweep_read_cost(Table *table, ha_rows nrows, bool interrupted, 
 
3898
void get_sweep_read_cost(Table *table, ha_rows nrows, bool interrupted,
4211
3899
                         COST_VECT *cost)
4212
3900
{
4213
3901
  cost->zero();
4263
3951
int handler::read_range_first(const key_range *start_key,
4264
3952
                              const key_range *end_key,
4265
3953
                              bool eq_range_arg,
4266
 
                              bool sorted  __attribute__((unused)))
 
3954
                              bool )
4267
3955
{
4268
3956
  int result;
4269
3957
 
4286
3974
                           start_key->keypart_map,
4287
3975
                           start_key->flag);
4288
3976
  if (result)
4289
 
    return((result == HA_ERR_KEY_NOT_FOUND) 
 
3977
    return((result == HA_ERR_KEY_NOT_FOUND)
4290
3978
                ? HA_ERR_END_OF_FILE
4291
3979
                : result);
4292
3980
 
4368
4056
  return cmp;
4369
4057
}
4370
4058
 
4371
 
int handler::index_read_idx_map(unsigned char * buf, uint32_t index, const unsigned char * key,
 
4059
int handler::index_read_idx_map(unsigned char * buf, uint32_t index,
 
4060
                                const unsigned char * key,
4372
4061
                                key_part_map keypart_map,
4373
4062
                                enum ha_rkey_function find_flag)
4374
4063
{
4393
4082
  @retval
4394
4083
    pointer             pointer to TYPELIB structure
4395
4084
*/
4396
 
static bool exts_handlerton(THD *unused __attribute__((unused)),
 
4085
static bool exts_handlerton(Session *,
4397
4086
                            plugin_ref plugin,
4398
4087
                            void *arg)
4399
4088
{
4401
4090
  handlerton *hton= plugin_data(plugin, handlerton *);
4402
4091
  handler *file;
4403
4092
  if (hton->state == SHOW_OPTION_YES && hton->create &&
4404
 
      (file= hton->create(hton, (TABLE_SHARE*) 0, current_thd->mem_root)))
 
4093
      (file= hton->create(hton, (TABLE_SHARE*) 0, current_session->mem_root)))
4405
4094
  {
4406
4095
    List_iterator_fast<char> it(*found_exts);
4407
4096
    const char **ext, *old_ext;
4435
4124
    plugin_foreach(NULL, exts_handlerton,
4436
4125
                   DRIZZLE_STORAGE_ENGINE_PLUGIN, &found_exts);
4437
4126
 
4438
 
    ext= (const char **) my_once_alloc(sizeof(char *)*
4439
 
                                       (found_exts.elements+1),
4440
 
                                       MYF(MY_WME | MY_FAE));
 
4127
    ext= (const char **) malloc(sizeof(char *)*
 
4128
                                (found_exts.elements+1));
 
4129
                              
4441
4130
 
4442
4131
    assert(ext != 0);
4443
4132
    known_extensions.count= found_exts.elements;
4452
4141
}
4453
4142
 
4454
4143
 
4455
 
static bool stat_print(THD *thd, const char *type, uint32_t type_len,
 
4144
static bool stat_print(Session *session, const char *type, uint32_t type_len,
4456
4145
                       const char *file, uint32_t file_len,
4457
4146
                       const char *status, uint32_t status_len)
4458
4147
{
4459
 
  Protocol *protocol= thd->protocol;
 
4148
  Protocol *protocol= session->protocol;
4460
4149
  protocol->prepare_for_resend();
4461
4150
  protocol->store(type, type_len, system_charset_info);
4462
4151
  protocol->store(file, file_len, system_charset_info);
4466
4155
  return false;
4467
4156
}
4468
4157
 
4469
 
bool ha_show_status(THD *thd, handlerton *db_type, enum ha_stat_type stat)
 
4158
bool ha_show_status(Session *session, handlerton *db_type, enum ha_stat_type stat)
4470
4159
{
4471
4160
  List<Item> field_list;
4472
 
  Protocol *protocol= thd->protocol;
 
4161
  Protocol *protocol= session->protocol;
4473
4162
  bool result;
4474
4163
 
4475
4164
  field_list.push_back(new Item_empty_string("Type",10));
4481
4170
    return true;
4482
4171
 
4483
4172
  result= db_type->show_status &&
4484
 
    db_type->show_status(db_type, thd, stat_print, stat) ? 1 : 0;
 
4173
    db_type->show_status(db_type, session, stat_print, stat) ? 1 : 0;
4485
4174
 
4486
4175
  if (!result)
4487
 
    my_eof(thd);
 
4176
    session->my_eof();
4488
4177
  return result;
4489
4178
}
4490
4179
 
4501
4190
  - table is not mysql.event
4502
4191
*/
4503
4192
 
4504
 
static bool check_table_binlog_row_based(THD *thd, Table *table)
4505
 
{
4506
 
  if (table->s->cached_row_logging_check == -1)
4507
 
  {
4508
 
    int const check(table->s->tmp_table == NO_TMP_TABLE &&
4509
 
                    binlog_filter->db_ok(table->s->db.str));
4510
 
    table->s->cached_row_logging_check= check;
4511
 
  }
4512
 
 
4513
 
  assert(table->s->cached_row_logging_check == 0 ||
4514
 
              table->s->cached_row_logging_check == 1);
4515
 
 
4516
 
  return (thd->current_stmt_binlog_row_based &&
4517
 
          table->s->cached_row_logging_check &&
4518
 
          (thd->options & OPTION_BIN_LOG) &&
4519
 
          mysql_bin_log.is_open());
4520
 
}
4521
 
 
4522
 
 
4523
 
/**
4524
 
   Write table maps for all (manually or automatically) locked tables
4525
 
   to the binary log.
4526
 
 
4527
 
   This function will generate and write table maps for all tables
4528
 
   that are locked by the thread 'thd'.  Either manually locked
4529
 
   (stored in THD::locked_tables) and automatically locked (stored
4530
 
   in THD::lock) are considered.
4531
 
 
4532
 
   @param thd     Pointer to THD structure
4533
 
 
4534
 
   @retval 0   All OK
4535
 
   @retval 1   Failed to write all table maps
4536
 
 
4537
 
   @sa
4538
 
       THD::lock
4539
 
       THD::locked_tables
4540
 
*/
4541
 
 
4542
 
static int write_locked_table_maps(THD *thd)
4543
 
{
4544
 
  if (thd->get_binlog_table_maps() == 0)
4545
 
  {
4546
 
    DRIZZLE_LOCK *locks[3];
4547
 
    locks[0]= thd->extra_lock;
4548
 
    locks[1]= thd->lock;
4549
 
    locks[2]= thd->locked_tables;
4550
 
    for (uint32_t i= 0 ; i < sizeof(locks)/sizeof(*locks) ; ++i )
4551
 
    {
4552
 
      DRIZZLE_LOCK const *const lock= locks[i];
4553
 
      if (lock == NULL)
4554
 
        continue;
4555
 
 
4556
 
      Table **const end_ptr= lock->table + lock->table_count;
4557
 
      for (Table **table_ptr= lock->table ; 
4558
 
           table_ptr != end_ptr ;
4559
 
           ++table_ptr)
4560
 
      {
4561
 
        Table *const table= *table_ptr;
4562
 
        if (table->current_lock == F_WRLCK &&
4563
 
            check_table_binlog_row_based(thd, table))
4564
 
        {
4565
 
          int const has_trans= table->file->has_transactions();
4566
 
          int const error= thd->binlog_write_table_map(table, has_trans);
4567
 
          /*
4568
 
            If an error occurs, it is the responsibility of the caller to
4569
 
            roll back the transaction.
4570
 
          */
4571
 
          if (unlikely(error))
4572
 
            return(1);
4573
 
        }
4574
 
      }
4575
 
    }
4576
 
  }
4577
 
  return(0);
4578
 
}
4579
 
 
4580
 
 
4581
 
typedef bool Log_func(THD*, Table*, bool, const unsigned char*, const unsigned char*);
4582
 
 
4583
 
static int binlog_log_row(Table* table,
4584
 
                          const unsigned char *before_record,
4585
 
                          const unsigned char *after_record,
4586
 
                          Log_func *log_func)
4587
 
{
4588
 
  if (table->no_replicate)
4589
 
    return 0;
4590
 
  bool error= 0;
4591
 
  THD *const thd= table->in_use;
4592
 
 
4593
 
  if (check_table_binlog_row_based(thd, table))
4594
 
  {
 
4193
static bool binlog_log_row(Table* table,
 
4194
                           const unsigned char *before_record,
 
4195
                           const unsigned char *after_record)
 
4196
{
 
4197
  bool error= false;
 
4198
  Session *const session= table->in_use;
 
4199
 
 
4200
  if (table->no_replicate == false)
 
4201
    return false;
 
4202
 
 
4203
  error= replicator_session_init(session);
 
4204
 
 
4205
  switch (session->lex->sql_command)
 
4206
  {
 
4207
  case SQLCOM_REPLACE:
 
4208
  case SQLCOM_INSERT:
 
4209
  case SQLCOM_REPLACE_SELECT:
 
4210
  case SQLCOM_INSERT_SELECT:
 
4211
  case SQLCOM_CREATE_TABLE:
 
4212
    error= replicator_write_row(session, table);
 
4213
    break;
 
4214
 
 
4215
  case SQLCOM_UPDATE:
 
4216
  case SQLCOM_UPDATE_MULTI:
 
4217
    error= replicator_update_row(session, table, before_record, after_record);
 
4218
    break;
 
4219
 
 
4220
  case SQLCOM_DELETE:
 
4221
  case SQLCOM_DELETE_MULTI:
 
4222
    error= replicator_delete_row(session, table);
 
4223
    break;
 
4224
 
4595
4225
    /*
4596
 
      If there are no table maps written to the binary log, this is
4597
 
      the first row handled in this statement. In that case, we need
4598
 
      to write table maps for all locked tables to the binary log.
 
4226
      For everything else we ignore the event (since it just involves a temp table)
4599
4227
    */
4600
 
    if (likely(!(error= write_locked_table_maps(thd))))
4601
 
    {
4602
 
      bool const has_trans= table->file->has_transactions();
4603
 
      error= (*log_func)(thd, table, has_trans, before_record, after_record);
4604
 
    }
 
4228
  default:
 
4229
    break;
4605
4230
  }
4606
 
  return error ? HA_ERR_RBR_LOGGING_FAILED : 0;
 
4231
 
 
4232
  return error;
4607
4233
}
4608
4234
 
4609
 
int handler::ha_external_lock(THD *thd, int lock_type)
 
4235
int handler::ha_external_lock(Session *session, int lock_type)
4610
4236
{
4611
4237
  /*
4612
4238
    Whether this is lock or unlock, this should be true, and is to verify that
4621
4247
  */
4622
4248
  DRIZZLE_EXTERNAL_LOCK(lock_type);
4623
4249
 
4624
 
  int error= external_lock(thd, lock_type);
 
4250
  int error= external_lock(session, lock_type);
4625
4251
  if (error == 0)
4626
4252
    cached_table_flags= table_flags();
4627
4253
  return(error);
4652
4278
int handler::ha_write_row(unsigned char *buf)
4653
4279
{
4654
4280
  int error;
4655
 
  Log_func *log_func= Write_rows_log_event::binlog_row_logging_function;
4656
4281
  DRIZZLE_INSERT_ROW_START();
4657
4282
 
 
4283
  /* 
 
4284
   * If we have a timestamp column, update it to the current time 
 
4285
   * 
 
4286
   * @TODO Technically, the below two lines can be take even further out of the
 
4287
   * handler interface and into the fill_record() method.
 
4288
   */
 
4289
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
 
4290
    table->timestamp_field->set_time();
 
4291
 
4658
4292
  mark_trx_read_write();
4659
4293
 
4660
4294
  if (unlikely(error= write_row(buf)))
4661
4295
    return(error);
4662
 
  if (unlikely(error= binlog_log_row(table, 0, buf, log_func)))
4663
 
    return(error); /* purecov: inspected */
 
4296
 
 
4297
  if (unlikely(binlog_log_row(table, 0, buf)))
 
4298
    return HA_ERR_RBR_LOGGING_FAILED; /* purecov: inspected */
 
4299
 
4664
4300
  DRIZZLE_INSERT_ROW_END();
4665
4301
  return(0);
4666
4302
}
4669
4305
int handler::ha_update_row(const unsigned char *old_data, unsigned char *new_data)
4670
4306
{
4671
4307
  int error;
4672
 
  Log_func *log_func= Update_rows_log_event::binlog_row_logging_function;
4673
4308
 
4674
4309
  /*
4675
4310
    Some storage engines require that the new record is in record[0]
4681
4316
 
4682
4317
  if (unlikely(error= update_row(old_data, new_data)))
4683
4318
    return error;
4684
 
  if (unlikely(error= binlog_log_row(table, old_data, new_data, log_func)))
4685
 
    return error;
 
4319
 
 
4320
  if (unlikely(binlog_log_row(table, old_data, new_data)))
 
4321
    return HA_ERR_RBR_LOGGING_FAILED;
 
4322
 
4686
4323
  return 0;
4687
4324
}
4688
4325
 
4689
4326
int handler::ha_delete_row(const unsigned char *buf)
4690
4327
{
4691
4328
  int error;
4692
 
  Log_func *log_func= Delete_rows_log_event::binlog_row_logging_function;
4693
4329
 
4694
4330
  mark_trx_read_write();
4695
4331
 
4696
4332
  if (unlikely(error= delete_row(buf)))
4697
4333
    return error;
4698
 
  if (unlikely(error= binlog_log_row(table, buf, 0, log_func)))
4699
 
    return error;
 
4334
 
 
4335
  if (unlikely(binlog_log_row(table, buf, 0)))
 
4336
    return HA_ERR_RBR_LOGGING_FAILED;
 
4337
 
4700
4338
  return 0;
4701
4339
}
4702
4340
 
4713
4351
  /* fallback to use all columns in the table to identify row */
4714
4352
  table->use_all_columns();
4715
4353
}
 
4354
 
 
4355
void table_case_convert(char * name, uint32_t length)
 
4356
{
 
4357
  if (lower_case_table_names)
 
4358
    files_charset_info->cset->casedn(files_charset_info,
 
4359
                                     name, length, name, length);
 
4360
}
 
4361
 
 
4362
const char *table_case_name(HA_CREATE_INFO *info, const char *name)
 
4363
{
 
4364
  return ((lower_case_table_names == 2 && info->alias) ? info->alias : name);
 
4365
}