~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/handler.cc

  • Committer: Padraig O'Sullivan
  • Date: 2009-03-21 01:02:23 UTC
  • mto: (960.2.5 mordred)
  • mto: This revision was merged to the branch mainline in revision 961.
  • Revision ID: osullivan.padraig@gmail.com-20090321010223-j8cph7eeyt1u3xol
Fixed function object to ensure it correctly returns a boolean type since
memcmp returns an integer. Added some more comments.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2000-2006 MySQL AB
2
 
 
3
 
   This program is free software; you can redistribute it and/or modify
4
 
   it under the terms of the GNU General Public License as published by
5
 
   the Free Software Foundation; version 2 of the License.
6
 
 
7
 
   This program is distributed in the hope that it will be useful,
8
 
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
 
   GNU General Public License for more details.
11
 
 
12
 
   You should have received a copy of the GNU General Public License
13
 
   along with this program; if not, write to the Free Software
14
 
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
 
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
 
3
 *
 
4
 *  Copyright (C) 2008 Sun Microsystems
 
5
 *
 
6
 *  This program is free software; you can redistribute it and/or modify
 
7
 *  it under the terms of the GNU General Public License as published by
 
8
 *  the Free Software Foundation; version 2 of the License.
 
9
 *
 
10
 *  This program is distributed in the hope that it will be useful,
 
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 *  GNU General Public License for more details.
 
14
 *
 
15
 *  You should have received a copy of the GNU General Public License
 
16
 *  along with this program; if not, write to the Free Software
 
17
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
18
 */
15
19
 
16
20
/**
17
21
  @file handler.cc
19
23
  Handler-calling-functions
20
24
*/
21
25
 
22
 
#ifdef USE_PRAGMA_IMPLEMENTATION
23
 
#pragma implementation                          // gcc: Class implementation
24
 
#endif
25
 
 
26
 
#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)
 
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 "drizzled/session.h"
 
36
#include "drizzled/sql_base.h"
 
37
#include "drizzled/replicator.h"
 
38
#include "drizzled/lock.h"
 
39
#include "drizzled/item/int.h"
 
40
#include "drizzled/item/empty_string.h"
 
41
#include "drizzled/unireg.h" // for mysql_frm_type
 
42
#include "drizzled/field/timestamp.h"
 
43
#include "drizzled/serialize/table.pb.h"
 
44
 
 
45
using namespace std;
40
46
 
41
47
KEY_CREATE_INFO default_key_create_info= { HA_KEY_ALG_UNDEF, 0, {NULL,0}, {NULL,0} };
42
48
 
47
53
/* size of savepoint storage area (see ha_init) */
48
54
uint32_t savepoint_alloc_size= 0;
49
55
 
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
56
const char *ha_row_type[] = {
58
57
  "", "FIXED", "DYNAMIC", "COMPRESSED", "REDUNDANT", "COMPACT", "PAGE", "?","?","?"
59
58
};
61
60
const char *tx_isolation_names[] =
62
61
{ "READ-UNCOMMITTED", "READ-COMMITTED", "REPEATABLE-READ", "SERIALIZABLE",
63
62
  NULL};
 
63
 
64
64
TYPELIB tx_isolation_typelib= {array_elements(tx_isolation_names)-1,"",
65
 
                               tx_isolation_names, NULL};
 
65
                               tx_isolation_names, NULL};
66
66
 
67
67
static TYPELIB known_extensions= {0,"known_exts", NULL, NULL};
68
68
uint32_t known_extensions_id= 0;
69
69
 
70
70
 
71
 
 
72
 
static plugin_ref ha_default_plugin(THD *thd)
73
 
{
74
 
  if (thd->variables.table_plugin)
75
 
    return thd->variables.table_plugin;
76
 
  return my_plugin_lock(thd, &global_system_variables.table_plugin);
77
 
}
78
 
 
79
 
 
80
 
/**
81
 
  Return the default storage engine handlerton for thread
82
 
 
83
 
  @param ha_default_handlerton(thd)
84
 
  @param thd         current thread
85
 
 
86
 
  @return
87
 
    pointer to handlerton
88
 
*/
89
 
handlerton *ha_default_handlerton(THD *thd)
90
 
{
91
 
  plugin_ref plugin= ha_default_plugin(thd);
92
 
  assert(plugin);
93
 
  handlerton *hton= plugin_data(plugin, handlerton*);
94
 
  assert(hton);
95
 
  return hton;
96
 
}
97
 
 
98
 
 
99
 
/**
100
 
  Return the storage engine handlerton for the supplied name
101
 
  
102
 
  @param thd         current thread
103
 
  @param name        name of storage engine
104
 
  
105
 
  @return
106
 
    pointer to storage engine plugin handle
107
 
*/
108
 
plugin_ref ha_resolve_by_name(THD *thd, const LEX_STRING *name)
109
 
{
110
 
  const LEX_STRING *table_alias;
111
 
  plugin_ref plugin;
112
 
 
113
 
redo:
114
 
  /* my_strnncoll is a macro and gcc doesn't do early expansion of macro */
115
 
  if (thd && !my_charset_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
71
/**
224
72
  Register handler error messages for use with my_error().
225
73
 
236
84
 
237
85
  /* Allocate a pointer array for the error message strings. */
238
86
  /* Zerofill it to avoid uninitialized gaps. */
239
 
  if (! (errmsgs= (const char**) my_malloc(HA_ERR_ERRORS * sizeof(char*),
240
 
                                           MYF(MY_WME | MY_ZEROFILL))))
 
87
  if (! (errmsgs= (const char**) malloc(HA_ERR_ERRORS * sizeof(char*))))
241
88
    return 1;
 
89
  memset(errmsgs, 0, HA_ERR_ERRORS * sizeof(char *));
242
90
 
243
91
  /* Set the dedicated error messages. */
244
92
  SETMSG(HA_ERR_KEY_NOT_FOUND,          ER(ER_KEY_NOT_FOUND));
307
155
  return 0;
308
156
}
309
157
 
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
158
int ha_init()
424
159
{
425
160
  int error= 0;
430
165
    binary log (which is considered a transaction-capable storage engine in
431
166
    counting total_ha)
432
167
  */
433
 
  opt_using_transactions= total_ha>(uint32_t)opt_bin_log;
434
168
  savepoint_alloc_size+= sizeof(SAVEPOINT);
435
169
  return(error);
436
170
}
439
173
{
440
174
  int error= 0;
441
175
 
442
 
  /* 
 
176
  /*
443
177
    This should be eventualy based  on the graceful shutdown flag.
444
178
    So if flag is equal to HA_PANIC_CLOSE, the deallocate
445
179
    the errors.
450
184
  return(error);
451
185
}
452
186
 
453
 
static bool dropdb_handlerton(THD *unused1 __attribute__((unused)),
 
187
static bool dropdb_handlerton(Session *,
454
188
                              plugin_ref plugin,
455
189
                              void *path)
456
190
{
467
201
}
468
202
 
469
203
 
470
 
static bool closecon_handlerton(THD *thd, plugin_ref plugin,
471
 
                                void *unused __attribute__((unused)))
 
204
static bool closecon_handlerton(Session *session, plugin_ref plugin,
 
205
                                void *)
472
206
{
473
207
  handlerton *hton= plugin_data(plugin, handlerton *);
474
208
  /*
476
210
    be rolled back already
477
211
  */
478
212
  if (hton->state == SHOW_OPTION_YES && hton->close_connection &&
479
 
      thd_get_ha_data(thd, hton))
480
 
    hton->close_connection(hton, thd);
 
213
      session_get_ha_data(session, hton))
 
214
    hton->close_connection(hton, session);
481
215
  return false;
482
216
}
483
217
 
486
220
  @note
487
221
    don't bother to rollback here, it's done already
488
222
*/
489
 
void ha_close_connection(THD* thd)
 
223
void ha_close_connection(Session* session)
490
224
{
491
 
  plugin_foreach(thd, closecon_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN, 0);
 
225
  plugin_foreach(session, closecon_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN, 0);
492
226
}
493
227
 
494
228
/* ========================================================================
593
327
  -----------
594
328
 
595
329
  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
 
330
  session->transaction. This structure has two members of type
 
331
  Session_TRANS. These members correspond to the statement and
598
332
  normal transactions respectively:
599
333
 
600
 
  - thd->transaction.stmt contains a list of engines
 
334
  - session->transaction.stmt contains a list of engines
601
335
  that are participating in the given statement
602
 
  - thd->transaction.all contains a list of engines that
 
336
  - session->transaction.all contains a list of engines that
603
337
  have participated in any of the statement transactions started
604
338
  within the context of the normal transaction.
605
339
  Each element of the list contains a pointer to the storage
606
340
  engine, engine-specific transactional data, and engine-specific
607
341
  transaction flags.
608
342
 
609
 
  In autocommit mode thd->transaction.all is empty.
610
 
  Instead, data of thd->transaction.stmt is
 
343
  In autocommit mode session->transaction.all is empty.
 
344
  Instead, data of session->transaction.stmt is
611
345
  used to commit/rollback the normal transaction.
612
346
 
613
347
  The list of registered engines has a few important properties:
618
352
  Transaction life cycle
619
353
  ----------------------
620
354
 
621
 
  When a new connection is established, thd->transaction
 
355
  When a new connection is established, session->transaction
622
356
  members are initialized to an empty state.
623
357
  If a statement uses any tables, all affected engines
624
358
  are registered in the statement engine list. In
634
368
  and emptied again at the next statement's end.
635
369
 
636
370
  The normal transaction is committed in a similar way
637
 
  (by going over all engines in thd->transaction.all list)
 
371
  (by going over all engines in session->transaction.all list)
638
372
  but at different times:
639
373
  - upon COMMIT SQL statement is issued by the user
640
374
  - implicitly, by the server, at the beginning of a DDL statement
644
378
  - if the user has requested so, by issuing ROLLBACK SQL
645
379
  statement
646
380
  - if one of the storage engines requested a rollback
647
 
  by setting thd->transaction_rollback_request. This may
 
381
  by setting session->transaction_rollback_request. This may
648
382
  happen in case, e.g., when the transaction in the engine was
649
383
  chosen a victim of the internal deadlock resolution algorithm
650
384
  and rolled back internally. When such a situation happens, there
686
420
  transactions of other participants.
687
421
 
688
422
  After the normal transaction has been committed,
689
 
  thd->transaction.all list is cleared.
 
423
  session->transaction.all list is cleared.
690
424
 
691
425
  When a connection is closed, the current normal transaction, if
692
426
  any, is rolled back.
750
484
  ---------------------------------------------------
751
485
 
752
486
  DDLs and operations with non-transactional engines
753
 
  do not "register" in thd->transaction lists, and thus do not
 
487
  do not "register" in session->transaction lists, and thus do not
754
488
  modify the transaction state. Besides, each DDL in
755
489
  MySQL is prefixed with an implicit normal transaction commit
756
 
  (a call to end_active_trans()), and thus leaves nothing
 
490
  (a call to Session::endActiveTransaction()), and thus leaves nothing
757
491
  to modify.
758
492
  However, as it has been pointed out with CREATE TABLE .. SELECT,
759
493
  some DDL statements can start a *new* transaction.
797
531
    times per transaction.
798
532
 
799
533
*/
800
 
void trans_register_ha(THD *thd, bool all, handlerton *ht_arg)
 
534
void trans_register_ha(Session *session, bool all, handlerton *ht_arg)
801
535
{
802
 
  THD_TRANS *trans;
 
536
  Session_TRANS *trans;
803
537
  Ha_trx_info *ha_info;
804
538
 
805
539
  if (all)
806
540
  {
807
 
    trans= &thd->transaction.all;
808
 
    thd->server_status|= SERVER_STATUS_IN_TRANS;
 
541
    trans= &session->transaction.all;
 
542
    session->server_status|= SERVER_STATUS_IN_TRANS;
809
543
  }
810
544
  else
811
 
    trans= &thd->transaction.stmt;
 
545
    trans= &session->transaction.stmt;
812
546
 
813
 
  ha_info= thd->ha_data[ht_arg->slot].ha_info + static_cast<unsigned>(all);
 
547
  ha_info= session->ha_data[ht_arg->slot].ha_info + static_cast<unsigned>(all);
814
548
 
815
549
  if (ha_info->is_started())
816
550
    return; /* already registered, return */
818
552
  ha_info->register_ha(trans, ht_arg);
819
553
 
820
554
  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);
 
555
  if (session->transaction.xid_state.xid.is_null())
 
556
    session->transaction.xid_state.xid.set(session->query_id);
823
557
 
824
558
  return;
825
559
}
830
564
  @retval
831
565
    1   error, transaction was rolled back
832
566
*/
833
 
int ha_prepare(THD *thd)
 
567
int ha_prepare(Session *session)
834
568
{
835
569
  int error=0, all=1;
836
 
  THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt;
 
570
  Session_TRANS *trans=all ? &session->transaction.all : &session->transaction.stmt;
837
571
  Ha_trx_info *ha_info= trans->ha_list;
838
572
  if (ha_info)
839
573
  {
841
575
    {
842
576
      int err;
843
577
      handlerton *ht= ha_info->ht();
844
 
      status_var_increment(thd->status_var.ha_prepare_count);
 
578
      status_var_increment(session->status_var.ha_prepare_count);
845
579
      if (ht->prepare)
846
580
      {
847
 
        if ((err= ht->prepare(ht, thd, all)))
 
581
        if ((err= ht->prepare(ht, session, all)))
848
582
        {
849
583
          my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
850
 
          ha_rollback_trans(thd, all);
 
584
          ha_rollback_trans(session, all);
851
585
          error=1;
852
586
          break;
853
587
        }
854
588
      }
855
589
      else
856
590
      {
857
 
        push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
591
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
858
592
                            ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
859
593
                            ha_resolve_storage_engine_name(ht));
860
594
      }
879
613
 
880
614
static
881
615
bool
882
 
ha_check_and_coalesce_trx_read_only(THD *thd, Ha_trx_info *ha_list,
 
616
ha_check_and_coalesce_trx_read_only(Session *session, Ha_trx_info *ha_list,
883
617
                                    bool all)
884
618
{
885
619
  /* The number of storage engines that have actual changes. */
893
627
 
894
628
    if (! all)
895
629
    {
896
 
      Ha_trx_info *ha_info_all= &thd->ha_data[ha_info->ht()->slot].ha_info[1];
 
630
      Ha_trx_info *ha_info_all= &session->ha_data[ha_info->ht()->slot].ha_info[1];
897
631
      assert(ha_info != ha_info_all);
898
632
      /*
899
633
        Merge read-only/read-write information about statement
900
634
        transaction to its enclosing normal transaction. Do this
901
635
        only if in a real transaction -- that is, if we know
902
 
        that ha_info_all is registered in thd->transaction.all.
 
636
        that ha_info_all is registered in session->transaction.all.
903
637
        Since otherwise we only clutter the normal transaction flags.
904
638
      */
905
639
      if (ha_info_all->is_started()) /* false if autocommit. */
933
667
    stored functions or triggers. So we simply do nothing now.
934
668
    TODO: This should be fixed in later ( >= 5.1) releases.
935
669
*/
936
 
int ha_commit_trans(THD *thd, bool all)
 
670
int ha_commit_trans(Session *session, bool all)
937
671
{
938
672
  int error= 0, cookie= 0;
939
673
  /*
940
674
    'all' means that this is either an explicit commit issued by
941
675
    user, or an implicit commit issued by a DDL.
942
676
  */
943
 
  THD_TRANS *trans= all ? &thd->transaction.all : &thd->transaction.stmt;
944
 
  bool is_real_trans= all || thd->transaction.all.ha_list == 0;
 
677
  Session_TRANS *trans= all ? &session->transaction.all : &session->transaction.stmt;
 
678
  bool is_real_trans= all || session->transaction.all.ha_list == 0;
945
679
  Ha_trx_info *ha_info= trans->ha_list;
946
 
  my_xid xid= thd->transaction.xid_state.xid.get_my_xid();
947
680
 
948
681
  /*
949
682
    We must not commit the normal transaction if a statement
951
684
    flags will not get propagated to its normal transaction's
952
685
    counterpart.
953
686
  */
954
 
  assert(thd->transaction.stmt.ha_list == NULL ||
955
 
              trans == &thd->transaction.stmt);
 
687
  assert(session->transaction.stmt.ha_list == NULL ||
 
688
              trans == &session->transaction.stmt);
956
689
 
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
690
  if (ha_info)
978
691
  {
979
692
    bool must_2pc;
980
693
 
981
 
    if (is_real_trans && wait_if_global_read_lock(thd, 0, 0))
 
694
    if (is_real_trans && wait_if_global_read_lock(session, 0, 0))
982
695
    {
983
 
      ha_rollback_trans(thd, all);
 
696
      ha_rollback_trans(session, all);
984
697
      return(1);
985
698
    }
986
699
 
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);
 
700
    must_2pc= ha_check_and_coalesce_trx_read_only(session, ha_info, all);
999
701
 
1000
702
    if (!trans->no_2pc && must_2pc)
1001
703
    {
1014
716
          Sic: we know that prepare() is not NULL since otherwise
1015
717
          trans->no_2pc would have been set.
1016
718
        */
1017
 
        if ((err= ht->prepare(ht, thd, all)))
 
719
        if ((err= ht->prepare(ht, session, all)))
1018
720
        {
1019
721
          my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
1020
722
          error= 1;
1021
723
        }
1022
 
        status_var_increment(thd->status_var.ha_prepare_count);
 
724
        status_var_increment(session->status_var.ha_prepare_count);
1023
725
      }
1024
 
      if (error || (is_real_trans && xid &&
1025
 
                    (error= !(cookie= tc_log->log_xid(thd, xid)))))
 
726
      if (error)
1026
727
      {
1027
 
        ha_rollback_trans(thd, all);
 
728
        ha_rollback_trans(session, all);
1028
729
        error= 1;
1029
730
        goto end;
1030
731
      }
1031
732
    }
1032
 
    error=ha_commit_one_phase(thd, all) ? (cookie ? 2 : 1) : 0;
1033
 
    if (cookie)
1034
 
      tc_log->unlog(cookie, xid);
 
733
    error=ha_commit_one_phase(session, all) ? (cookie ? 2 : 1) : 0;
1035
734
end:
1036
735
    if (is_real_trans)
1037
 
      start_waiting_global_read_lock(thd);
 
736
      start_waiting_global_read_lock(session);
1038
737
  }
1039
738
  return(error);
1040
739
}
1043
742
  @note
1044
743
  This function does not care about global read lock. A caller should.
1045
744
*/
1046
 
int ha_commit_one_phase(THD *thd, bool all)
 
745
int ha_commit_one_phase(Session *session, bool all)
1047
746
{
1048
747
  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;
 
748
  Session_TRANS *trans=all ? &session->transaction.all : &session->transaction.stmt;
 
749
  bool is_real_trans=all || session->transaction.all.ha_list == 0;
1051
750
  Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
1052
751
  if (ha_info)
1053
752
  {
1055
754
    {
1056
755
      int err;
1057
756
      handlerton *ht= ha_info->ht();
1058
 
      if ((err= ht->commit(ht, thd, all)))
 
757
      if ((err= ht->commit(ht, session, all)))
1059
758
      {
1060
759
        my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
1061
760
        error=1;
1062
761
      }
1063
 
      status_var_increment(thd->status_var.ha_commit_count);
 
762
      status_var_increment(session->status_var.ha_commit_count);
1064
763
      ha_info_next= ha_info->next();
1065
764
      ha_info->reset(); /* keep it conveniently zero-filled */
1066
765
    }
1067
766
    trans->ha_list= 0;
1068
767
    trans->no_2pc=0;
1069
768
    if (is_real_trans)
1070
 
      thd->transaction.xid_state.xid.null();
 
769
      session->transaction.xid_state.xid.null();
1071
770
    if (all)
1072
771
    {
1073
 
      thd->variables.tx_isolation=thd->session_tx_isolation;
1074
 
      thd->transaction.cleanup();
 
772
      session->variables.tx_isolation=session->session_tx_isolation;
 
773
      session->transaction.cleanup();
1075
774
    }
1076
775
  }
1077
776
  return(error);
1078
777
}
1079
778
 
1080
779
 
1081
 
int ha_rollback_trans(THD *thd, bool all)
 
780
int ha_rollback_trans(Session *session, bool all)
1082
781
{
1083
782
  int error=0;
1084
 
  THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt;
 
783
  Session_TRANS *trans=all ? &session->transaction.all : &session->transaction.stmt;
1085
784
  Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
1086
 
  bool is_real_trans=all || thd->transaction.all.ha_list == 0;
 
785
  bool is_real_trans=all || session->transaction.all.ha_list == 0;
1087
786
 
1088
787
  /*
1089
788
    We must not rollback the normal transaction if a statement
1090
789
    transaction is pending.
1091
790
  */
1092
 
  assert(thd->transaction.stmt.ha_list == NULL ||
1093
 
              trans == &thd->transaction.stmt);
 
791
  assert(session->transaction.stmt.ha_list == NULL ||
 
792
              trans == &session->transaction.stmt);
1094
793
 
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
794
  if (ha_info)
1109
795
  {
1110
796
    for (; ha_info; ha_info= ha_info_next)
1111
797
    {
1112
798
      int err;
1113
799
      handlerton *ht= ha_info->ht();
1114
 
      if ((err= ht->rollback(ht, thd, all)))
 
800
      if ((err= ht->rollback(ht, session, all)))
1115
801
      { // cannot happen
1116
802
        my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
1117
803
        error=1;
1118
804
      }
1119
 
      status_var_increment(thd->status_var.ha_rollback_count);
 
805
      status_var_increment(session->status_var.ha_rollback_count);
1120
806
      ha_info_next= ha_info->next();
1121
807
      ha_info->reset(); /* keep it conveniently zero-filled */
1122
808
    }
1123
809
    trans->ha_list= 0;
1124
810
    trans->no_2pc=0;
1125
811
    if (is_real_trans)
1126
 
      thd->transaction.xid_state.xid.null();
 
812
      session->transaction.xid_state.xid.null();
1127
813
    if (all)
1128
814
    {
1129
 
      thd->variables.tx_isolation=thd->session_tx_isolation;
1130
 
      thd->transaction.cleanup();
 
815
      session->variables.tx_isolation=session->session_tx_isolation;
 
816
      session->transaction.cleanup();
1131
817
    }
1132
818
  }
1133
819
  if (all)
1134
 
    thd->transaction_rollback_request= false;
 
820
    session->transaction_rollback_request= false;
1135
821
 
1136
822
  /*
1137
823
    If a non-transactional table was updated, warn; don't warn if this is a
1142
828
    the error log; but we don't want users to wonder why they have this
1143
829
    message in the error log, so we don't send it.
1144
830
  */
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,
 
831
  if (is_real_trans && session->transaction.all.modified_non_trans_table && session->killed != Session::KILL_CONNECTION)
 
832
    push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1148
833
                 ER_WARNING_NOT_COMPLETE_ROLLBACK,
1149
834
                 ER(ER_WARNING_NOT_COMPLETE_ROLLBACK));
1150
835
  return(error);
1161
846
    the user has used LOCK TABLES then that mechanism does not know to do the
1162
847
    commit.
1163
848
*/
1164
 
int ha_autocommit_or_rollback(THD *thd, int error)
 
849
int ha_autocommit_or_rollback(Session *session, int error)
1165
850
{
1166
 
  if (thd->transaction.stmt.ha_list)
 
851
  if (session->transaction.stmt.ha_list)
1167
852
  {
1168
853
    if (!error)
1169
854
    {
1170
 
      if (ha_commit_trans(thd, 0))
1171
 
        error=1;
 
855
      if (ha_commit_trans(session, 0))
 
856
        error=1;
1172
857
    }
1173
 
    else 
 
858
    else
1174
859
    {
1175
 
      (void) ha_rollback_trans(thd, 0);
1176
 
      if (thd->transaction_rollback_request && !thd->in_sub_stmt)
1177
 
        (void) ha_rollback(thd);
 
860
      (void) ha_rollback_trans(session, 0);
 
861
      if (session->transaction_rollback_request)
 
862
        (void) ha_rollback(session);
1178
863
    }
1179
864
 
1180
 
    thd->variables.tx_isolation=thd->session_tx_isolation;
 
865
    session->variables.tx_isolation=session->session_tx_isolation;
1181
866
  }
1182
867
  return(error);
1183
868
}
1188
873
  int result;
1189
874
};
1190
875
 
1191
 
static bool xacommit_handlerton(THD *unused1 __attribute__((unused)),
 
876
static bool xacommit_handlerton(Session *,
1192
877
                                plugin_ref plugin,
1193
878
                                void *arg)
1194
879
{
1201
886
  return false;
1202
887
}
1203
888
 
1204
 
static bool xarollback_handlerton(THD *unused1 __attribute__((unused)),
 
889
static bool xarollback_handlerton(Session *,
1205
890
                                  plugin_ref plugin,
1206
891
                                  void *arg)
1207
892
{
1251
936
  bool dry_run;
1252
937
};
1253
938
 
1254
 
static bool xarecover_handlerton(THD *unused __attribute__((unused)),
 
939
static bool xarecover_handlerton(Session *,
1255
940
                                 plugin_ref plugin,
1256
941
                                 void *arg)
1257
942
{
1263
948
  {
1264
949
    while ((got= hton->recover(hton, info->list, info->len)) > 0 )
1265
950
    {
1266
 
      sql_print_information(_("Found %d prepared transaction(s) in %s"),
 
951
      errmsg_printf(ERRMSG_LVL_INFO, _("Found %d prepared transaction(s) in %s"),
1267
952
                            got, ha_resolve_storage_engine_name(hton));
1268
953
      for (int i=0; i < got; i ++)
1269
954
      {
1309
994
  /* commit_list and tc_heuristic_recover cannot be set both */
1310
995
  assert(info.commit_list==0 || tc_heuristic_recover==0);
1311
996
  /* if either is set, total_ha_2pc must be set too */
1312
 
  assert(info.dry_run || total_ha_2pc>(uint32_t)opt_bin_log);
 
997
  assert(info.dry_run);
1313
998
 
1314
 
  if (total_ha_2pc <= (uint32_t)opt_bin_log)
1315
 
    return(0);
 
999
  if (total_ha_2pc <= 1)
 
1000
    return 0;
1316
1001
 
1317
1002
  if (info.commit_list)
1318
 
    sql_print_information(_("Starting crash recovery..."));
 
1003
    errmsg_printf(ERRMSG_LVL_INFO, _("Starting crash recovery..."));
1319
1004
 
1320
1005
 
1321
1006
#ifndef WILL_BE_DELETED_LATER
1325
1010
    rollback all pending transactions, without risking inconsistent data
1326
1011
  */
1327
1012
 
1328
 
  assert(total_ha_2pc == (uint32_t) opt_bin_log+1); // only InnoDB and binlog
 
1013
  assert(total_ha_2pc == 2); // only InnoDB and binlog
1329
1014
  tc_heuristic_recover= TC_HEURISTIC_RECOVER_ROLLBACK; // forcing ROLLBACK
1330
1015
  info.dry_run=false;
1331
1016
#endif
1332
1017
 
1333
1018
 
1334
 
  for (info.len= MAX_XID_LIST_SIZE ; 
 
1019
  for (info.len= MAX_XID_LIST_SIZE ;
1335
1020
       info.list==0 && info.len > MIN_XID_LIST_SIZE; info.len/=2)
1336
1021
  {
1337
 
    info.list=(XID *)my_malloc(info.len*sizeof(XID), MYF(0));
 
1022
    info.list=(XID *)malloc(info.len*sizeof(XID));
1338
1023
  }
1339
1024
  if (!info.list)
1340
1025
  {
1341
 
    sql_print_error(ER(ER_OUTOFMEMORY), info.len*sizeof(XID));
 
1026
    errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_OUTOFMEMORY), info.len*sizeof(XID));
1342
1027
    return(1);
1343
1028
  }
1344
1029
 
1345
 
  plugin_foreach(NULL, xarecover_handlerton, 
 
1030
  plugin_foreach(NULL, xarecover_handlerton,
1346
1031
                 DRIZZLE_STORAGE_ENGINE_PLUGIN, &info);
1347
1032
 
1348
1033
  free((unsigned char*)info.list);
1349
1034
  if (info.found_foreign_xids)
1350
 
    sql_print_warning(_("Found %d prepared XA transactions"), 
1351
 
                      info.found_foreign_xids);
 
1035
    errmsg_printf(ERRMSG_LVL_WARN, _("Found %d prepared XA transactions"),
 
1036
                  info.found_foreign_xids);
1352
1037
  if (info.dry_run && info.found_my_xids)
1353
1038
  {
1354
 
    sql_print_error(_("Found %d prepared transactions! It means that drizzled "
 
1039
    errmsg_printf(ERRMSG_LVL_ERROR,
 
1040
                  _("Found %d prepared transactions! It means that drizzled "
1355
1041
                    "was not shut down properly last time and critical "
1356
1042
                    "recovery information (last binlog or %s file) was "
1357
1043
                    "manually deleted after a crash. You have to start "
1361
1047
    return(1);
1362
1048
  }
1363
1049
  if (info.commit_list)
1364
 
    sql_print_information(_("Crash recovery finished."));
 
1050
    errmsg_printf(ERRMSG_LVL_INFO, _("Crash recovery finished."));
1365
1051
  return(0);
1366
1052
}
1367
1053
 
1373
1059
    so mysql_xa_recover does not filter XID's to ensure uniqueness.
1374
1060
    It can be easily fixed later, if necessary.
1375
1061
*/
1376
 
bool mysql_xa_recover(THD *thd)
 
1062
bool mysql_xa_recover(Session *session)
1377
1063
{
1378
1064
  List<Item> field_list;
1379
 
  Protocol *protocol= thd->protocol;
 
1065
  Protocol *protocol= session->protocol;
1380
1066
  int i=0;
1381
1067
  XID_STATE *xs;
1382
1068
 
1409
1095
  }
1410
1096
 
1411
1097
  pthread_mutex_unlock(&LOCK_xid_cache);
1412
 
  my_eof(thd);
 
1098
  session->my_eof();
1413
1099
  return(0);
1414
1100
}
1415
1101
 
1417
1103
  @details
1418
1104
  This function should be called when MySQL sends rows of a SELECT result set
1419
1105
  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
 
1106
  S-latch held by session in InnoDB and also releases a possible InnoDB query
 
1107
  FIFO ticket to enter InnoDB. To save CPU time, InnoDB allows a session to
1422
1108
  keep them over several calls of the InnoDB handler interface when a join
1423
1109
  is executed. But when we let the control to pass to the client they have
1424
1110
  to be released because if the application program uses mysql_use_result(),
1426
1112
  performs another SQL query. In MySQL-4.1 this is even more important because
1427
1113
  there a connection can have several SELECT queries open at the same time.
1428
1114
 
1429
 
  @param thd           the thread handle of the current connection
 
1115
  @param session           the thread handle of the current connection
1430
1116
 
1431
1117
  @return
1432
1118
    always 0
1433
1119
*/
1434
 
static bool release_temporary_latches(THD *thd, plugin_ref plugin,
1435
 
                                      void *unused __attribute__((unused)))
 
1120
static bool release_temporary_latches(Session *session, plugin_ref plugin,
 
1121
                                      void *)
1436
1122
{
1437
1123
  handlerton *hton= plugin_data(plugin, handlerton *);
1438
1124
 
1439
1125
  if (hton->state == SHOW_OPTION_YES && hton->release_temporary_latches)
1440
 
    hton->release_temporary_latches(hton, thd);
 
1126
    hton->release_temporary_latches(hton, session);
1441
1127
 
1442
1128
  return false;
1443
1129
}
1444
1130
 
1445
1131
 
1446
 
int ha_release_temporary_latches(THD *thd)
 
1132
int ha_release_temporary_latches(Session *session)
1447
1133
{
1448
 
  plugin_foreach(thd, release_temporary_latches, DRIZZLE_STORAGE_ENGINE_PLUGIN, 
 
1134
  plugin_foreach(session, release_temporary_latches, DRIZZLE_STORAGE_ENGINE_PLUGIN,
1449
1135
                 NULL);
1450
1136
 
1451
1137
  return 0;
1452
1138
}
1453
1139
 
1454
 
int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv)
 
1140
int ha_rollback_to_savepoint(Session *session, SAVEPOINT *sv)
1455
1141
{
1456
1142
  int error=0;
1457
 
  THD_TRANS *trans= (thd->in_sub_stmt ? &thd->transaction.stmt :
1458
 
                                        &thd->transaction.all);
 
1143
  Session_TRANS *trans= &session->transaction.all;
1459
1144
  Ha_trx_info *ha_info, *ha_info_next;
1460
1145
 
1461
1146
  trans->no_2pc=0;
1469
1154
    handlerton *ht= ha_info->ht();
1470
1155
    assert(ht);
1471
1156
    assert(ht->savepoint_set != 0);
1472
 
    if ((err= ht->savepoint_rollback(ht, thd,
 
1157
    if ((err= ht->savepoint_rollback(ht, session,
1473
1158
                                     (unsigned char *)(sv+1)+ht->savepoint_offset)))
1474
1159
    { // cannot happen
1475
1160
      my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
1476
1161
      error=1;
1477
1162
    }
1478
 
    status_var_increment(thd->status_var.ha_savepoint_rollback_count);
 
1163
    status_var_increment(session->status_var.ha_savepoint_rollback_count);
1479
1164
    trans->no_2pc|= ht->prepare == 0;
1480
1165
  }
1481
1166
  /*
1487
1172
  {
1488
1173
    int err;
1489
1174
    handlerton *ht= ha_info->ht();
1490
 
    if ((err= ht->rollback(ht, thd, !thd->in_sub_stmt)))
 
1175
    if ((err= ht->rollback(ht, session, !(0))))
1491
1176
    { // cannot happen
1492
1177
      my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
1493
1178
      error=1;
1494
1179
    }
1495
 
    status_var_increment(thd->status_var.ha_rollback_count);
 
1180
    status_var_increment(session->status_var.ha_rollback_count);
1496
1181
    ha_info_next= ha_info->next();
1497
1182
    ha_info->reset(); /* keep it conveniently zero-filled */
1498
1183
  }
1506
1191
  section "4.33.4 SQL-statements and transaction states",
1507
1192
  SAVEPOINT is *not* transaction-initiating SQL-statement
1508
1193
*/
1509
 
int ha_savepoint(THD *thd, SAVEPOINT *sv)
 
1194
int ha_savepoint(Session *session, SAVEPOINT *sv)
1510
1195
{
1511
1196
  int error=0;
1512
 
  THD_TRANS *trans= (thd->in_sub_stmt ? &thd->transaction.stmt :
1513
 
                                        &thd->transaction.all);
 
1197
  Session_TRANS *trans= &session->transaction.all;
1514
1198
  Ha_trx_info *ha_info= trans->ha_list;
1515
1199
  for (; ha_info; ha_info= ha_info->next())
1516
1200
  {
1523
1207
      error=1;
1524
1208
      break;
1525
1209
    }
1526
 
    if ((err= ht->savepoint_set(ht, thd, (unsigned char *)(sv+1)+ht->savepoint_offset)))
 
1210
    if ((err= ht->savepoint_set(ht, session, (unsigned char *)(sv+1)+ht->savepoint_offset)))
1527
1211
    { // cannot happen
1528
1212
      my_error(ER_GET_ERRNO, MYF(0), err);
1529
1213
      error=1;
1530
1214
    }
1531
 
    status_var_increment(thd->status_var.ha_savepoint_count);
 
1215
    status_var_increment(session->status_var.ha_savepoint_count);
1532
1216
  }
1533
1217
  /*
1534
1218
    Remember the list of registered storage engines. All new
1538
1222
  return(error);
1539
1223
}
1540
1224
 
1541
 
int ha_release_savepoint(THD *thd, SAVEPOINT *sv)
 
1225
int ha_release_savepoint(Session *session, SAVEPOINT *sv)
1542
1226
{
1543
1227
  int error=0;
1544
1228
  Ha_trx_info *ha_info= sv->ha_list;
1551
1235
    assert(ht);
1552
1236
    if (!ht->savepoint_release)
1553
1237
      continue;
1554
 
    if ((err= ht->savepoint_release(ht, thd,
 
1238
    if ((err= ht->savepoint_release(ht, session,
1555
1239
                                    (unsigned char *)(sv+1) + ht->savepoint_offset)))
1556
1240
    { // cannot happen
1557
1241
      my_error(ER_GET_ERRNO, MYF(0), err);
1562
1246
}
1563
1247
 
1564
1248
 
1565
 
static bool snapshot_handlerton(THD *thd, plugin_ref plugin, void *arg)
 
1249
static bool snapshot_handlerton(Session *session, plugin_ref plugin, void *arg)
1566
1250
{
1567
1251
  handlerton *hton= plugin_data(plugin, handlerton *);
1568
1252
  if (hton->state == SHOW_OPTION_YES &&
1569
1253
      hton->start_consistent_snapshot)
1570
1254
  {
1571
 
    hton->start_consistent_snapshot(hton, thd);
 
1255
    hton->start_consistent_snapshot(hton, session);
1572
1256
    *((bool *)arg)= false;
1573
1257
  }
1574
1258
  return false;
1575
1259
}
1576
1260
 
1577
 
int ha_start_consistent_snapshot(THD *thd)
 
1261
int ha_start_consistent_snapshot(Session *session)
1578
1262
{
1579
1263
  bool warn= true;
1580
1264
 
1581
 
  plugin_foreach(thd, snapshot_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN, &warn);
 
1265
  plugin_foreach(session, snapshot_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN, &warn);
1582
1266
 
1583
1267
  /*
1584
1268
    Same idea as when one wants to CREATE TABLE in one engine which does not
1585
1269
    exist:
1586
1270
  */
1587
1271
  if (warn)
1588
 
    push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
1589
 
                 "This MySQL server does not support any "
 
1272
    push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
 
1273
                 "This Drizzle server does not support any "
1590
1274
                 "consistent-read capable storage engine");
1591
1275
  return 0;
1592
1276
}
1593
1277
 
1594
1278
 
1595
 
static bool flush_handlerton(THD *thd __attribute__((unused)),
 
1279
static bool flush_handlerton(Session *,
1596
1280
                             plugin_ref plugin,
1597
 
                             void *arg __attribute__((unused)))
 
1281
                             void *)
1598
1282
{
1599
1283
  handlerton *hton= plugin_data(plugin, handlerton *);
1600
 
  if (hton->state == SHOW_OPTION_YES && hton->flush_logs && 
 
1284
  if (hton->state == SHOW_OPTION_YES && hton->flush_logs &&
1601
1285
      hton->flush_logs(hton))
1602
1286
    return true;
1603
1287
  return false;
1629
1313
 
1630
1314
  /* Ensure that table handler get path in lower case */
1631
1315
  if (tmp_path != path)
1632
 
    my_stpcpy(tmp_path, path);
 
1316
    strcpy(tmp_path, path);
1633
1317
 
1634
1318
  /*
1635
1319
    we only should turn into lowercase database/table part
1636
1320
    so start the process after homedirectory
1637
1321
  */
1638
 
  my_casedn_str(files_charset_info, tmp_path + mysql_data_home_len);
 
1322
  my_casedn_str(files_charset_info, tmp_path + drizzle_data_home_len);
1639
1323
  return tmp_path;
1640
1324
}
1641
1325
 
1649
1333
struct Ha_delete_table_error_handler: public Internal_error_handler
1650
1334
{
1651
1335
public:
 
1336
  Ha_delete_table_error_handler() : Internal_error_handler() {}
1652
1337
  virtual bool handle_error(uint32_t sql_errno,
1653
1338
                            const char *message,
1654
1339
                            DRIZZLE_ERROR::enum_warning_level level,
1655
 
                            THD *thd);
 
1340
                            Session *session);
1656
1341
  char buff[DRIZZLE_ERRMSG_SIZE];
1657
1342
};
1658
1343
 
1659
1344
 
1660
1345
bool
1661
1346
Ha_delete_table_error_handler::
1662
 
handle_error(uint32_t sql_errno  __attribute__((unused)),
 
1347
handle_error(uint32_t ,
1663
1348
             const char *message,
1664
 
             DRIZZLE_ERROR::enum_warning_level level __attribute__((unused)),
1665
 
             THD *thd __attribute__((unused)))
 
1349
             DRIZZLE_ERROR::enum_warning_level ,
 
1350
             Session *)
1666
1351
{
1667
1352
  /* Grab the error message */
1668
 
  strmake(buff, message, sizeof(buff)-1);
 
1353
  strncpy(buff, message, sizeof(buff)-1);
1669
1354
  return true;
1670
1355
}
1671
1356
 
1672
1357
 
 
1358
struct handlerton_delete_table_args {
 
1359
  Session *session;
 
1360
  const char *path;
 
1361
  handler *file;
 
1362
  int error;
 
1363
};
 
1364
 
 
1365
static bool deletetable_handlerton(Session *,
 
1366
                                   plugin_ref plugin,
 
1367
                                   void *args)
 
1368
{
 
1369
  struct handlerton_delete_table_args *dtargs= (struct handlerton_delete_table_args *) args;
 
1370
 
 
1371
  Session *session= dtargs->session;
 
1372
  const char *path= dtargs->path;
 
1373
 
 
1374
  handler *file;
 
1375
  char tmp_path[FN_REFLEN];
 
1376
 
 
1377
  if(dtargs->error!=ENOENT) /* already deleted table */
 
1378
    return false;
 
1379
 
 
1380
  handlerton *table_type= plugin_data(plugin, handlerton *);
 
1381
 
 
1382
  if(!table_type)
 
1383
    return false;
 
1384
 
 
1385
  if(!(table_type->state == SHOW_OPTION_YES && table_type->create))
 
1386
    return false;
 
1387
 
 
1388
  if ((file= table_type->create(table_type, NULL, session->mem_root)))
 
1389
    file->init();
 
1390
  else
 
1391
    return false;
 
1392
 
 
1393
  path= check_lowercase_names(file, path, tmp_path);
 
1394
  int error= file->ha_delete_table(path);
 
1395
 
 
1396
  if(error!=ENOENT)
 
1397
  {
 
1398
    dtargs->error= error;
 
1399
    if(dtargs->file)
 
1400
      delete dtargs->file;
 
1401
    dtargs->file= file;
 
1402
    return true;
 
1403
  }
 
1404
  else
 
1405
    delete file;
 
1406
 
 
1407
  return false;
 
1408
}
 
1409
 
1673
1410
/**
1674
1411
  This should return ENOENT if the file doesn't exists.
1675
1412
  The .frm file will be deleted only if we return 0 or ENOENT
1676
1413
*/
1677
 
int ha_delete_table(THD *thd, handlerton *table_type, const char *path,
 
1414
int ha_delete_table(Session *session, const char *path,
1678
1415
                    const char *db, const char *alias, bool generate_warning)
1679
1416
{
1680
 
  handler *file;
1681
 
  char tmp_path[FN_REFLEN];
1682
 
  int error;
 
1417
  TABLE_SHARE dummy_share;
1683
1418
  Table dummy_table;
1684
 
  TABLE_SHARE dummy_share;
 
1419
 
 
1420
  struct handlerton_delete_table_args dtargs;
 
1421
  dtargs.error= ENOENT;
 
1422
  dtargs.session= session;
 
1423
  dtargs.path= path;
 
1424
  dtargs.file= NULL;
 
1425
 
 
1426
  plugin_foreach(NULL, deletetable_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN,
 
1427
                 &dtargs);
1685
1428
 
1686
1429
  memset(&dummy_table, 0, sizeof(dummy_table));
1687
1430
  memset(&dummy_share, 0, sizeof(dummy_share));
1688
1431
  dummy_table.s= &dummy_share;
1689
1432
 
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)
 
1433
  if (dtargs.error && generate_warning)
1697
1434
  {
1698
1435
    /*
1699
1436
      Because file->print_error() use my_error() to generate the error message
1712
1449
    dummy_share.table_name.length= strlen(alias);
1713
1450
    dummy_table.alias= alias;
1714
1451
 
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();
 
1452
    if(dtargs.file)
 
1453
    {
 
1454
      handler *file= dtargs.file;
 
1455
      file->change_table_ptr(&dummy_table, &dummy_share);
 
1456
 
 
1457
      session->push_internal_handler(&ha_delete_table_error_handler);
 
1458
      file->print_error(dtargs.error, 0);
 
1459
 
 
1460
      session->pop_internal_handler();
 
1461
    }
 
1462
    else
 
1463
      dtargs.error= -1; /* General form of fail. maybe bad FRM */
1721
1464
 
1722
1465
    /*
1723
1466
      XXX: should we convert *all* errors to warnings here?
1724
1467
      What if the error is fatal?
1725
1468
    */
1726
 
    push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_ERROR, error,
 
1469
    push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR, dtargs.error,
1727
1470
                ha_delete_table_error_handler.buff);
1728
1471
  }
1729
 
  delete file;
1730
 
  return(error);
 
1472
 
 
1473
  if(dtargs.file)
 
1474
    delete dtargs.file;
 
1475
 
 
1476
  return dtargs.error;
1731
1477
}
1732
1478
 
1733
1479
/****************************************************************************
1738
1484
  handler *new_handler= get_new_handler(table->s, mem_root, table->s->db_type());
1739
1485
  /*
1740
1486
    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 
 
1487
    on this->table->mem_root and we will not be able to reclaim that memory
1742
1488
    when the clone handler object is destroyed.
1743
1489
  */
1744
1490
  if (!(new_handler->ref= (unsigned char*) alloc_root(mem_root, ALIGN_SIZE(ref_length)*2)))
1751
1497
  return NULL;
1752
1498
}
1753
1499
 
1754
 
 
 
1500
int handler::ha_index_init(uint32_t idx, bool sorted)
 
1501
{
 
1502
  int result;
 
1503
  assert(inited==NONE);
 
1504
  if (!(result= index_init(idx, sorted)))
 
1505
    inited=INDEX;
 
1506
  end_range= NULL;
 
1507
  return(result);
 
1508
}
 
1509
 
 
1510
int handler::ha_index_end()
 
1511
{
 
1512
  assert(inited==INDEX);
 
1513
  inited=NONE;
 
1514
  end_range= NULL;
 
1515
  return(index_end());
 
1516
}
 
1517
 
 
1518
int handler::ha_rnd_init(bool scan)
 
1519
{
 
1520
  int result;
 
1521
  assert(inited==NONE || (inited==RND && scan));
 
1522
  inited= (result= rnd_init(scan)) ? NONE: RND;
 
1523
  return(result);
 
1524
}
 
1525
 
 
1526
int handler::ha_rnd_end()
 
1527
{
 
1528
  assert(inited==RND);
 
1529
  inited=NONE;
 
1530
  return(rnd_end());
 
1531
}
 
1532
 
 
1533
int handler::ha_index_or_rnd_end()
 
1534
{
 
1535
  return inited == INDEX ? ha_index_end() : inited == RND ? ha_rnd_end() : 0;
 
1536
}
 
1537
 
 
1538
handler::Table_flags handler::ha_table_flags() const
 
1539
{
 
1540
  return cached_table_flags;
 
1541
}
 
1542
 
 
1543
void handler::ha_start_bulk_insert(ha_rows rows)
 
1544
{
 
1545
  estimation_rows_to_insert= rows;
 
1546
  start_bulk_insert(rows);
 
1547
}
 
1548
 
 
1549
int handler::ha_end_bulk_insert()
 
1550
{
 
1551
  estimation_rows_to_insert= 0;
 
1552
  return end_bulk_insert();
 
1553
}
 
1554
 
 
1555
void handler::change_table_ptr(Table *table_arg, TABLE_SHARE *share)
 
1556
{
 
1557
  table= table_arg;
 
1558
  table_share= share;
 
1559
}
 
1560
 
 
1561
const key_map *handler::keys_to_use_for_scanning()
 
1562
{
 
1563
  return &key_map_empty;
 
1564
}
 
1565
 
 
1566
bool handler::has_transactions()
 
1567
{
 
1568
  return (ha_table_flags() & HA_NO_TRANSACTIONS) == 0;
 
1569
}
1755
1570
 
1756
1571
void handler::ha_statistic_increment(ulong SSV::*offset) const
1757
1572
{
1758
1573
  status_var_increment(table->in_use->status_var.*offset);
1759
1574
}
1760
1575
 
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
 
}
 
1576
void **handler::ha_data(Session *session) const
 
1577
{
 
1578
  return session_ha_data(session, ht);
 
1579
}
 
1580
 
 
1581
Session *handler::ha_session(void) const
 
1582
{
 
1583
  assert(!table || !table->in_use || table->in_use == current_session);
 
1584
  return (table && table->in_use) ? table->in_use : current_session;
 
1585
}
 
1586
 
 
1587
 
 
1588
bool handler::is_fatal_error(int error, uint32_t flags)
 
1589
{
 
1590
  if (!error ||
 
1591
      ((flags & HA_CHECK_DUP_KEY) &&
 
1592
       (error == HA_ERR_FOUND_DUPP_KEY ||
 
1593
        error == HA_ERR_FOUND_DUPP_UNIQUE)))
 
1594
    return false;
 
1595
  return true;
 
1596
}
 
1597
 
 
1598
 
 
1599
ha_rows handler::records() { return stats.records; }
1771
1600
 
1772
1601
/**
1773
1602
  Open database-handler.
1804
1633
    (void) extra(HA_EXTRA_NO_READCHECK);        // Not needed in SQL
1805
1634
 
1806
1635
    /* ref is already allocated for us if we're called from handler::clone() */
1807
 
    if (!ref && !(ref= (unsigned char*) alloc_root(&table->mem_root, 
 
1636
    if (!ref && !(ref= (unsigned char*) alloc_root(&table->mem_root,
1808
1637
                                          ALIGN_SIZE(ref_length)*2)))
1809
1638
    {
1810
1639
      close();
1898
1727
void handler::adjust_next_insert_id_after_explicit_value(uint64_t nr)
1899
1728
{
1900
1729
  /*
1901
 
    If we have set THD::next_insert_id previously and plan to insert an
 
1730
    If we have set Session::next_insert_id previously and plan to insert an
1902
1731
    explicitely-specified value larger than this, we need to increase
1903
 
    THD::next_insert_id to be greater than the explicit value.
 
1732
    Session::next_insert_id to be greater than the explicit value.
1904
1733
  */
1905
1734
  if ((next_insert_id > 0) && (nr >= next_insert_id))
1906
1735
    set_next_insert_id(compute_next_insert_id(nr, &table->in_use->variables));
1976
1805
    again to reserve a new interval.
1977
1806
 
1978
1807
  - In both cases, the reserved intervals are remembered in
1979
 
    thd->auto_inc_intervals_in_cur_stmt_for_binlog if statement-based
 
1808
    session->auto_inc_intervals_in_cur_stmt_for_binlog if statement-based
1980
1809
    binlogging; the last reserved interval is remembered in
1981
1810
    auto_inc_interval_for_cur_row.
1982
1811
 
1990
1819
    start counting from the inserted value.
1991
1820
 
1992
1821
    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
 
1822
    with a value, session->next_insert_id is filled with the value to use for the
1994
1823
    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
 
1824
    session->insert_id_for_cur_row, if get_auto_increment() was called
 
1825
    session->auto_inc_interval_for_cur_row is modified, if that interval is not
 
1826
    present in session->auto_inc_intervals_in_cur_stmt_for_binlog it is added to
1998
1827
    this list.
1999
1828
 
2000
1829
  @todo
2021
1850
{
2022
1851
  uint64_t nr, nb_reserved_values;
2023
1852
  bool append= false;
2024
 
  THD *thd= table->in_use;
2025
 
  struct system_variables *variables= &thd->variables;
 
1853
  Session *session= table->in_use;
 
1854
  struct system_variables *variables= &session->variables;
2026
1855
 
2027
1856
  /*
2028
1857
    next_insert_id is a "cursor" into the reserved interval, it may go greater
2047
1876
  {
2048
1877
    /* next_insert_id is beyond what is reserved, so we reserve more. */
2049
1878
    const Discrete_interval *forced=
2050
 
      thd->auto_inc_intervals_forced.get_next();
 
1879
      session->auto_inc_intervals_forced.get_next();
2051
1880
    if (forced != NULL)
2052
1881
    {
2053
1882
      nr= forced->minimum();
2060
1889
        handler::ha_start_bulk_insert(); if 0 it means "unknown".
2061
1890
      */
2062
1891
      uint32_t nb_already_reserved_intervals=
2063
 
        thd->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements();
 
1892
        session->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements();
2064
1893
      uint64_t nb_desired_values;
2065
1894
      /*
2066
1895
        If an estimation was given to the engine:
2081
1910
        /* avoid overflow in formula, with this if() */
2082
1911
        if (nb_already_reserved_intervals <= AUTO_INC_DEFAULT_NB_MAX_BITS)
2083
1912
        {
2084
 
          nb_desired_values= AUTO_INC_DEFAULT_NB_ROWS * 
 
1913
          nb_desired_values= AUTO_INC_DEFAULT_NB_ROWS *
2085
1914
            (1 << nb_already_reserved_intervals);
2086
 
          set_if_smaller(nb_desired_values, AUTO_INC_DEFAULT_NB_MAX);
 
1915
          set_if_smaller(nb_desired_values, (uint64_t)AUTO_INC_DEFAULT_NB_MAX);
2087
1916
        }
2088
1917
        else
2089
1918
          nb_desired_values= AUTO_INC_DEFAULT_NB_MAX;
2095
1924
                         &nb_reserved_values);
2096
1925
      if (nr == ~(uint64_t) 0)
2097
1926
        return(HA_ERR_AUTOINC_READ_FAILED);  // Mark failure
2098
 
      
 
1927
 
2099
1928
      /*
2100
1929
        That rounding below should not be needed when all engines actually
2101
1930
        respect offset and increment in get_auto_increment(). But they don't
2106
1935
      */
2107
1936
      nr= compute_next_insert_id(nr-1, variables);
2108
1937
    }
2109
 
    
 
1938
 
2110
1939
    if (table->s->next_number_keypart == 0)
2111
1940
    {
2112
1941
      /* We must defer the appending until "nr" has been possibly truncated */
2119
1948
    /*
2120
1949
      first test if the query was aborted due to strict mode constraints
2121
1950
    */
2122
 
    if (thd->killed == THD::KILL_BAD_DATA)
 
1951
    if (session->killed == Session::KILL_BAD_DATA)
2123
1952
      return(HA_ERR_AUTOINC_ERANGE);
2124
1953
 
2125
1954
    /*
2138
1967
  {
2139
1968
    auto_inc_interval_for_cur_row.replace(nr, nb_reserved_values,
2140
1969
                                          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
1970
  }
2147
1971
 
2148
1972
  /*
2196
2020
  @param first_value         (OUT) the first value reserved by the handler
2197
2021
  @param nb_reserved_values  (OUT) how many values the handler reserved
2198
2022
*/
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)),
 
2023
void handler::get_auto_increment(uint64_t ,
 
2024
                                 uint64_t ,
 
2025
                                 uint64_t ,
2202
2026
                                 uint64_t *first_value,
2203
2027
                                 uint64_t *nb_reserved_values)
2204
2028
{
2281
2105
  else
2282
2106
  {
2283
2107
    /* Table is opened and defined at this point */
2284
 
    key_unpack(&str,table,(uint) key_nr);
2285
 
    uint32_t max_length=DRIZZLE_ERRMSG_SIZE-(uint) strlen(msg);
 
2108
    key_unpack(&str,table,(uint32_t) key_nr);
 
2109
    uint32_t max_length=DRIZZLE_ERRMSG_SIZE-(uint32_t) strlen(msg);
2286
2110
    if (str.length() >= max_length)
2287
2111
    {
2288
2112
      str.length(max_length-4);
2345
2169
      char key[MAX_KEY_LENGTH];
2346
2170
      String str(key,sizeof(key),system_charset_info);
2347
2171
      /* Table is opened and defined at this point */
2348
 
      key_unpack(&str,table,(uint) key_nr);
 
2172
      key_unpack(&str,table,(uint32_t) key_nr);
2349
2173
      max_length= (DRIZZLE_ERRMSG_SIZE-
2350
 
                   (uint) strlen(ER(ER_FOREIGN_DUPLICATE_KEY)));
 
2174
                   (uint32_t) strlen(ER(ER_FOREIGN_DUPLICATE_KEY)));
2351
2175
      if (str.length() >= max_length)
2352
2176
      {
2353
2177
        str.length(max_length-4);
2461
2285
    my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
2462
2286
               ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
2463
2287
    return;
2464
 
    break;
2465
2288
  default:
2466
2289
    {
2467
2290
      /* The error was "unknown" to this function.
2496
2319
  @return
2497
2320
    Returns true if this is a temporary error
2498
2321
*/
2499
 
bool handler::get_error_message(int error __attribute__((unused)),
2500
 
                                String* buf __attribute__((unused)))
 
2322
bool handler::get_error_message(int ,
 
2323
                                String* )
2501
2324
{
2502
2325
  return false;
2503
2326
}
2524
2347
        Field *field= table->field[keypart->fieldnr-1];
2525
2348
        if (field->type() == DRIZZLE_TYPE_BLOB)
2526
2349
        {
2527
 
          if (check_opt->sql_flags & TT_FOR_UPGRADE)
2528
 
            check_opt->flags= T_MEDIUM;
2529
2350
          return HA_ADMIN_NEEDS_CHECK;
2530
2351
        }
2531
2352
      }
2541
2362
  return 0;
2542
2363
}
2543
2364
 
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
2365
/**
2592
2366
  @return
2593
2367
    key if error because of duplicated keys
2594
2368
*/
2595
2369
uint32_t handler::get_dup_key(int error)
2596
2370
{
2597
 
  table->file->errkey  = (uint) -1;
 
2371
  table->file->errkey  = (uint32_t) -1;
2598
2372
  if (error == HA_ERR_FOUND_DUPP_KEY || error == HA_ERR_FOREIGN_DUPLICATE_KEY ||
2599
2373
      error == HA_ERR_FOUND_DUPP_UNIQUE ||
2600
2374
      error == HA_ERR_DROP_INDEX_FK)
2666
2440
/**
2667
2441
  Performs checks upon the table.
2668
2442
 
2669
 
  @param thd                thread doing CHECK Table operation
 
2443
  @param session                thread doing CHECK Table operation
2670
2444
  @param check_opt          options from the parser
2671
2445
 
2672
2446
  @retval
2678
2452
  @retval
2679
2453
    HA_ADMIN_NOT_IMPLEMENTED
2680
2454
*/
2681
 
int handler::ha_check(THD *thd, HA_CHECK_OPT *check_opt)
 
2455
int handler::ha_check(Session *session, HA_CHECK_OPT *check_opt)
2682
2456
{
2683
2457
  int error;
2684
2458
 
2685
 
  if ((table->s->mysql_version >= DRIZZLE_VERSION_ID) &&
2686
 
      (check_opt->sql_flags & TT_FOR_UPGRADE))
2687
 
    return 0;
2688
 
 
2689
2459
  if (table->s->mysql_version < DRIZZLE_VERSION_ID)
2690
2460
  {
2691
2461
    if ((error= check_old_types()))
2693
2463
    error= ha_check_for_upgrade(check_opt);
2694
2464
    if (error && (error != HA_ADMIN_NEEDS_CHECK))
2695
2465
      return error;
2696
 
    if (!error && (check_opt->sql_flags & TT_FOR_UPGRADE))
2697
 
      return 0;
2698
2466
  }
2699
 
  if ((error= check(thd, check_opt)))
 
2467
  if ((error= check(session, check_opt)))
2700
2468
    return error;
2701
 
  return update_frm_version(table);
 
2469
  return HA_ADMIN_OK;
2702
2470
}
2703
2471
 
2704
2472
/**
2710
2478
void
2711
2479
handler::mark_trx_read_write()
2712
2480
{
2713
 
  Ha_trx_info *ha_info= &ha_thd()->ha_data[ht->slot].ha_info[0];
 
2481
  Ha_trx_info *ha_info= &ha_session()->ha_data[ht->slot].ha_info[0];
2714
2482
  /*
2715
2483
    When a storage engine method is called, the transaction must
2716
2484
    have been started, unless it's a DDL call, for which the
2721
2489
  */
2722
2490
  if (ha_info->is_started())
2723
2491
  {
2724
 
    assert(has_transactions());
2725
2492
    /*
2726
2493
      table_share can be NULL in ha_delete_table(). See implementation
2727
2494
      of standalone function ha_delete_table() in sql_base.cc.
2738
2505
  @sa handler::repair()
2739
2506
*/
2740
2507
 
2741
 
int handler::ha_repair(THD* thd, HA_CHECK_OPT* check_opt)
 
2508
int handler::ha_repair(Session* session, HA_CHECK_OPT* check_opt)
2742
2509
{
2743
2510
  int result;
2744
2511
 
2745
2512
  mark_trx_read_write();
2746
2513
 
2747
 
  if ((result= repair(thd, check_opt)))
 
2514
  if ((result= repair(session, check_opt)))
2748
2515
    return result;
2749
 
  return update_frm_version(table);
 
2516
  return HA_ADMIN_OK;
2750
2517
}
2751
2518
 
2752
2519
 
2803
2570
*/
2804
2571
 
2805
2572
int
2806
 
handler::ha_optimize(THD* thd, HA_CHECK_OPT* check_opt)
 
2573
handler::ha_optimize(Session* session, HA_CHECK_OPT* check_opt)
2807
2574
{
2808
2575
  mark_trx_read_write();
2809
2576
 
2810
 
  return optimize(thd, check_opt);
 
2577
  return optimize(session, check_opt);
2811
2578
}
2812
2579
 
2813
2580
 
2818
2585
*/
2819
2586
 
2820
2587
int
2821
 
handler::ha_analyze(THD* thd, HA_CHECK_OPT* check_opt)
 
2588
handler::ha_analyze(Session* session, HA_CHECK_OPT* check_opt)
2822
2589
{
2823
2590
  mark_trx_read_write();
2824
2591
 
2825
 
  return analyze(thd, check_opt);
 
2592
  return analyze(session, check_opt);
2826
2593
}
2827
2594
 
2828
2595
 
2833
2600
*/
2834
2601
 
2835
2602
bool
2836
 
handler::ha_check_and_repair(THD *thd)
 
2603
handler::ha_check_and_repair(Session *session)
2837
2604
{
2838
2605
  mark_trx_read_write();
2839
2606
 
2840
 
  return check_and_repair(thd);
 
2607
  return check_and_repair(session);
2841
2608
}
2842
2609
 
2843
2610
 
2955
2722
*/
2956
2723
 
2957
2724
int
2958
 
handler::ha_create(const char *name, Table *form, HA_CREATE_INFO *info)
 
2725
handler::ha_create(const char *name, Table *form, HA_CREATE_INFO *create_info)
2959
2726
{
2960
2727
  mark_trx_read_write();
2961
2728
 
2962
 
  return create(name, form, info);
 
2729
  return create(name, form, create_info);
2963
2730
}
2964
2731
 
2965
2732
 
2971
2738
 
2972
2739
int
2973
2740
handler::ha_create_handler_files(const char *name, const char *old_name,
2974
 
                        int action_flag, HA_CREATE_INFO *info)
 
2741
                                 int action_flag, HA_CREATE_INFO *create_info)
2975
2742
{
2976
2743
  mark_trx_read_write();
2977
2744
 
2978
 
  return create_handler_files(name, old_name, action_flag, info);
 
2745
  return create_handler_files(name, old_name, action_flag, create_info);
2979
2746
}
2980
2747
 
2981
2748
 
2987
2754
  starts to commit every now and then automatically.
2988
2755
  This hint can be safely ignored.
2989
2756
*/
2990
 
int ha_enable_transaction(THD *thd, bool on)
 
2757
int ha_enable_transaction(Session *session, bool on)
2991
2758
{
2992
2759
  int error=0;
2993
2760
 
2994
 
  if ((thd->transaction.on= on))
 
2761
  if ((session->transaction.on= on))
2995
2762
  {
2996
2763
    /*
2997
2764
      Now all storage engines should have transaction handling enabled.
2999
2766
      is an optimization hint that storage engine is free to ignore.
3000
2767
      So, let's commit an open transaction (if any) now.
3001
2768
    */
3002
 
    if (!(error= ha_commit_trans(thd, 0)))
3003
 
      error= end_trans(thd, COMMIT);
 
2769
    if (!(error= ha_commit_trans(session, 0)))
 
2770
      if (! session->endTransaction(COMMIT))
 
2771
        error= 1;
 
2772
 
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, (uint32_t) 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)
3192
2898
  {
3193
2899
    pthread_mutex_lock(&LOCK_global_system_variables);
3194
2900
    uint32_t tmp_buff_size= (uint32_t) key_cache->param_buff_size;
3195
 
    uint32_t tmp_block_size= (uint) key_cache->param_block_size;
 
2901
    uint32_t tmp_block_size= (uint32_t) key_cache->param_block_size;
3196
2902
    uint32_t division_limit= key_cache->param_division_limit;
3197
2903
    uint32_t age_threshold=  key_cache->param_age_threshold;
3198
2904
    pthread_mutex_unlock(&LOCK_global_system_variables);
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, "", 0);
 
3037
    if (table_proto_exists(path)==EEXIST)
 
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
      build_table_filename(path, sizeof(path),
 
3046
                           db, name, ".dfe", 0);
 
3047
      if(drizzle_read_table_proto(path, &table)==0)
 
3048
      {
 
3049
        LEX_STRING engine_name= { (char*)table.engine().name().c_str(),
 
3050
                                 strlen(table.engine().name().c_str()) };
 
3051
        plugin_ref plugin= ha_resolve_by_name(session, &engine_name);
 
3052
        if(plugin)
 
3053
          args.hton= plugin_data(plugin,handlerton *);
 
3054
      }
 
3055
    }
 
3056
  }
 
3057
 
 
3058
  if(hton)
 
3059
    *hton= args.hton;
 
3060
 
3369
3061
  return(args.err);
3370
3062
}
3371
3063
 
3390
3082
    Estimated cost of 'index only' scan
3391
3083
*/
3392
3084
 
3393
 
double handler::index_only_read_time(uint32_t keynr, double records)
 
3085
double handler::index_only_read_time(uint32_t keynr, double key_records)
3394
3086
{
3395
 
  double read_time;
3396
3087
  uint32_t keys_per_block= (stats.block_size/2/
3397
3088
                        (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;
 
3089
  return ((double) (key_records + keys_per_block-1) /
 
3090
          (double) keys_per_block);
3401
3091
}
3402
3092
 
3403
3093
 
3424
3114
 
3425
3115
  @note
3426
3116
    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
 
3117
    session->killed and return HA_POS_ERROR if it is not zero. This is required
3428
3118
    for a user to be able to interrupt the calculation by killing the
3429
3119
    connection/query.
3430
3120
 
3439
3129
ha_rows
3440
3130
handler::multi_range_read_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
3441
3131
                                     void *seq_init_param,
3442
 
                                     uint32_t n_ranges_arg __attribute__((unused)),
 
3132
                                     uint32_t ,
3443
3133
                                     uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
3444
3134
{
3445
3135
  KEY_MULTI_RANGE range;
3446
3136
  range_seq_t seq_it;
3447
3137
  ha_rows rows, total_rows= 0;
3448
3138
  uint32_t n_ranges=0;
3449
 
  THD *thd= current_thd;
3450
 
  
 
3139
  Session *session= current_session;
 
3140
 
3451
3141
  /* Default MRR implementation doesn't need buffer */
3452
3142
  *bufsz= 0;
3453
3143
 
3454
3144
  seq_it= seq->init(seq_init_param, n_ranges, *flags);
3455
3145
  while (!seq->next(seq_it, &range))
3456
3146
  {
3457
 
    if (unlikely(thd->killed != 0))
 
3147
    if (unlikely(session->killed != 0))
3458
3148
      return HA_POS_ERROR;
3459
 
    
 
3149
 
3460
3150
    n_ranges++;
3461
3151
    key_range *min_endp, *max_endp;
3462
3152
    {
3467
3157
      rows= 1; /* there can be at most one row */
3468
3158
    else
3469
3159
    {
3470
 
      if (HA_POS_ERROR == (rows= this->records_in_range(keyno, min_endp, 
 
3160
      if (HA_POS_ERROR == (rows= this->records_in_range(keyno, min_endp,
3471
3161
                                                        max_endp)))
3472
3162
      {
3473
3163
        /* Can't scan one range => can't do MRR scan at all */
3477
3167
    }
3478
3168
    total_rows += rows;
3479
3169
  }
3480
 
  
 
3170
 
3481
3171
  if (total_rows != HA_POS_ERROR)
3482
3172
  {
3483
3173
    /* The following calculation is the same as in multi_range_read_info(): */
3485
3175
    cost->zero();
3486
3176
    cost->avg_io_cost= 1; /* assume random seeks */
3487
3177
    if ((*flags & HA_MRR_INDEX_ONLY) && total_rows > 2)
3488
 
      cost->io_count= index_only_read_time(keyno, (uint)total_rows);
 
3178
      cost->io_count= index_only_read_time(keyno, (uint32_t)total_rows);
3489
3179
    else
3490
3180
      cost->io_count= read_time(keyno, n_ranges, total_rows);
3491
3181
    cost->cpu_cost= (double) total_rows / TIME_FOR_COMPARE + 0.01;
3550
3240
/**
3551
3241
  Initialize the MRR scan
3552
3242
 
3553
 
  Initialize the MRR scan. This function may do heavyweight scan 
 
3243
  Initialize the MRR scan. This function may do heavyweight scan
3554
3244
  initialization like row prefetching/sorting/etc (NOTE: but better not do
3555
3245
  it here as we may not need it, e.g. if we never satisfy WHERE clause on
3556
3246
  previous tables. For many implementations it would be natural to do such
3557
3247
  initializations in the first multi_read_range_next() call)
3558
3248
 
3559
3249
  mode is a combination of the following flags: HA_MRR_SORTED,
3560
 
  HA_MRR_INDEX_ONLY, HA_MRR_NO_ASSOCIATION 
 
3250
  HA_MRR_INDEX_ONLY, HA_MRR_NO_ASSOCIATION
3561
3251
 
3562
3252
  @param seq             Range sequence to be traversed
3563
3253
  @param seq_init_param  First parameter for seq->init()
3569
3259
    One must have called index_init() before calling this function. Several
3570
3260
    multi_range_read_init() calls may be made in course of one query.
3571
3261
 
3572
 
    Until WL#2623 is done (see its text, section 3.2), the following will 
 
3262
    Until WL#2623 is done (see its text, section 3.2), the following will
3573
3263
    also hold:
3574
3264
    The caller will guarantee that if "seq->init == mrr_ranges_array_init"
3575
3265
    then seq_init_param is an array of n_ranges KEY_MULTI_RANGE structures.
3576
3266
    This property will only be used by NDB handler until WL#2623 is done.
3577
 
     
 
3267
 
3578
3268
    Buffer memory management is done according to the following scenario:
3579
3269
    The caller allocates the buffer and provides it to the callee by filling
3580
3270
    the members of HANDLER_BUFFER structure.
3591
3281
int
3592
3282
handler::multi_range_read_init(RANGE_SEQ_IF *seq_funcs, void *seq_init_param,
3593
3283
                               uint32_t n_ranges, uint32_t mode,
3594
 
                               HANDLER_BUFFER *buf __attribute__((unused)))
 
3284
                               HANDLER_BUFFER *)
3595
3285
{
3596
3286
  mrr_iter= seq_funcs->init(seq_init_param, n_ranges, mode);
3597
3287
  mrr_funcs= *seq_funcs;
3669
3359
 
3670
3360
 
3671
3361
/* **************************************************************************
3672
 
 * DS-MRR implementation 
 
3362
 * DS-MRR implementation
3673
3363
 ***************************************************************************/
3674
3364
 
3675
3365
/**
3690
3380
  @retval other Error
3691
3381
*/
3692
3382
 
3693
 
int DsMrr_impl::dsmrr_init(handler *h, KEY *key,
 
3383
int DsMrr_impl::dsmrr_init(handler *h_in, KEY *key,
3694
3384
                           RANGE_SEQ_IF *seq_funcs, void *seq_init_param,
3695
3385
                           uint32_t n_ranges, uint32_t mode, HANDLER_BUFFER *buf)
3696
3386
{
3698
3388
  uint32_t keyno;
3699
3389
  Item *pushed_cond= NULL;
3700
3390
  handler *new_h2;
3701
 
  keyno= h->active_index;
 
3391
  keyno= h_in->active_index;
3702
3392
  assert(h2 == NULL);
3703
3393
  if (mode & HA_MRR_USE_DEFAULT_IMPL || mode & HA_MRR_SORTED)
3704
3394
  {
3705
3395
    use_default_impl= true;
3706
 
    return(h->handler::multi_range_read_init(seq_funcs, seq_init_param,
 
3396
    return(h_in->handler::multi_range_read_init(seq_funcs, seq_init_param,
3707
3397
                                                  n_ranges, mode, buf));
3708
3398
  }
3709
3399
  rowids_buf= buf->buffer;
3710
3400
  //psergey-todo: don't add key_length as it is not needed anymore
3711
 
  rowids_buf += key->key_length + h->ref_length;
 
3401
  rowids_buf += key->key_length + h_in->ref_length;
3712
3402
 
3713
3403
  is_mrr_assoc= !test(mode & HA_MRR_NO_ASSOCIATION);
3714
3404
  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 + 
 
3405
 
 
3406
  elem_size= h_in->ref_length + (int)is_mrr_assoc * sizeof(void*);
 
3407
  rowids_buf_last= rowids_buf +
3718
3408
                      ((rowids_buf_end - rowids_buf)/ elem_size)*
3719
3409
                      elem_size;
3720
3410
  rowids_buf_end= rowids_buf_last;
3721
3411
 
3722
3412
  /* 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))
 
3413
  Session *session= current_session;
 
3414
  if (!(new_h2= h_in->clone(session->mem_root)) ||
 
3415
      new_h2->ha_external_lock(session, F_RDLCK))
3726
3416
  {
3727
3417
    delete new_h2;
3728
3418
    return(1);
3729
3419
  }
3730
3420
 
3731
 
  if (keyno == h->pushed_idx_cond_keyno)
3732
 
    pushed_cond= h->pushed_idx_cond;
3733
 
  if (h->ha_index_end())
 
3421
  if (keyno == h_in->pushed_idx_cond_keyno)
 
3422
    pushed_cond= h_in->pushed_idx_cond;
 
3423
  if (h_in->ha_index_end())
3734
3424
  {
3735
3425
    new_h2= h2;
3736
3426
    goto error;
3740
3430
  table->prepare_for_position();
3741
3431
  new_h2->extra(HA_EXTRA_KEYREAD);
3742
3432
 
3743
 
  if (h2->ha_index_init(keyno, false) || 
 
3433
  if (h2->ha_index_init(keyno, false) ||
3744
3434
      h2->handler::multi_range_read_init(seq_funcs, seq_init_param, n_ranges,
3745
3435
                                         mode, buf))
3746
3436
    goto error;
3747
3437
  use_default_impl= false;
3748
 
  
 
3438
 
3749
3439
  if (pushed_cond)
3750
3440
    h2->idx_cond_push(keyno, pushed_cond);
3751
3441
  if (dsmrr_fill_buffer(new_h2))
3755
3445
    If the above call has scanned through all intervals in *seq, then
3756
3446
    adjust *buf to indicate that the remaining buffer space will not be used.
3757
3447
  */
3758
 
  if (dsmrr_eof) 
 
3448
  if (dsmrr_eof)
3759
3449
    buf->end_of_used_area= rowids_buf_last;
3760
3450
 
3761
 
  if (h->ha_rnd_init(false))
 
3451
  if (h_in->ha_rnd_init(false))
3762
3452
    goto error;
3763
 
  
 
3453
 
3764
3454
  return(0);
3765
3455
error:
3766
3456
  h2->ha_index_or_rnd_end();
3767
 
  h2->ha_external_lock(thd, F_UNLCK);
 
3457
  h2->ha_external_lock(session, F_UNLCK);
3768
3458
  h2->close();
3769
3459
  delete h2;
3770
3460
  return(1);
3775
3465
{
3776
3466
  if (h2)
3777
3467
  {
3778
 
    h2->ha_external_lock(current_thd, F_UNLCK);
 
3468
    h2->ha_external_lock(current_session, F_UNLCK);
3779
3469
    h2->close();
3780
3470
    delete h2;
3781
3471
    h2= NULL;
3795
3485
  DS-MRR: Fill the buffer with rowids and sort it by rowid
3796
3486
 
3797
3487
  {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 
 
3488
  Scan the MRR ranges and collect ROWIDs (or {ROWID, range_id} pairs) into
 
3489
  buffer. When the buffer is full or scan is completed, sort the buffer by
3800
3490
  rowid and return.
3801
 
  
3802
 
  The function assumes that rowids buffer is empty when it is invoked. 
3803
 
  
 
3491
 
 
3492
  The function assumes that rowids buffer is empty when it is invoked.
 
3493
 
3804
3494
  @param h  Table handler
3805
3495
 
3806
3496
  @retval 0      OK, the next portion of rowids is in the buffer,
3808
3498
  @retval other  Error
3809
3499
*/
3810
3500
 
3811
 
int DsMrr_impl::dsmrr_fill_buffer(handler *unused __attribute__((unused)))
 
3501
int DsMrr_impl::dsmrr_fill_buffer(handler *)
3812
3502
{
3813
3503
  char *range_info;
3814
3504
  int res = 0;
3815
3505
 
3816
3506
  rowids_buf_cur= rowids_buf;
3817
 
  while ((rowids_buf_cur < rowids_buf_end) && 
 
3507
  while ((rowids_buf_cur < rowids_buf_end) &&
3818
3508
         !(res= h2->handler::multi_range_read_next(&range_info)))
3819
3509
  {
3820
3510
    /* Put rowid, or {rowid, range_id} pair into the buffer */
3830
3520
  }
3831
3521
 
3832
3522
  if (res && res != HA_ERR_END_OF_FILE)
3833
 
    return(res); 
 
3523
    return(res);
3834
3524
  dsmrr_eof= test(res == HA_ERR_END_OF_FILE);
3835
3525
 
3836
3526
  /* Sort the buffer contents by rowid */
3837
3527
  uint32_t elem_size= h->ref_length + (int)is_mrr_assoc * sizeof(void*);
3838
3528
  uint32_t n_rowids= (rowids_buf_cur - rowids_buf) / elem_size;
3839
 
  
 
3529
 
3840
3530
  my_qsort2(rowids_buf, n_rowids, elem_size, (qsort2_cmp)rowid_cmp,
3841
3531
            (void*)h);
3842
3532
  rowids_buf_last= rowids_buf_cur;
3849
3539
  DS-MRR implementation: multi_range_read_next() function
3850
3540
*/
3851
3541
 
3852
 
int DsMrr_impl::dsmrr_next(handler *h, char **range_info)
 
3542
int DsMrr_impl::dsmrr_next(handler *h_in, char **range_info)
3853
3543
{
3854
3544
  int res;
3855
 
  
 
3545
 
3856
3546
  if (use_default_impl)
3857
 
    return h->handler::multi_range_read_next(range_info);
3858
 
    
 
3547
    return h_in->handler::multi_range_read_next(range_info);
 
3548
 
3859
3549
  if (rowids_buf_cur == rowids_buf_last)
3860
3550
  {
3861
3551
    if (dsmrr_eof)
3867
3557
    if (res)
3868
3558
      goto end;
3869
3559
  }
3870
 
  
 
3560
 
3871
3561
  /* Return EOF if there are no rowids in the buffer after re-fill attempt */
3872
3562
  if (rowids_buf_cur == rowids_buf_last)
3873
3563
  {
3875
3565
    goto end;
3876
3566
  }
3877
3567
 
3878
 
  res= h->rnd_pos(table->record[0], rowids_buf_cur);
3879
 
  rowids_buf_cur += h->ref_length;
 
3568
  res= h_in->rnd_pos(table->record[0], rowids_buf_cur);
 
3569
  rowids_buf_cur += h_in->ref_length;
3880
3570
  if (is_mrr_assoc)
3881
3571
  {
3882
3572
    memcpy(range_info, rowids_buf_cur, sizeof(void*));
3895
3585
*/
3896
3586
int DsMrr_impl::dsmrr_info(uint32_t keyno, uint32_t n_ranges, uint32_t rows, uint32_t *bufsz,
3897
3587
                           uint32_t *flags, COST_VECT *cost)
3898
 
{  
 
3588
{
3899
3589
  int res;
3900
3590
  uint32_t def_flags= *flags;
3901
3591
  uint32_t def_bufsz= *bufsz;
3905
3595
                                         &def_flags, cost);
3906
3596
  assert(!res);
3907
3597
 
3908
 
  if ((*flags & HA_MRR_USE_DEFAULT_IMPL) || 
 
3598
  if ((*flags & HA_MRR_USE_DEFAULT_IMPL) ||
3909
3599
      choose_mrr_impl(keyno, rows, &def_flags, &def_bufsz, cost))
3910
3600
  {
3911
3601
    /* Default implementation is choosen */
3921
3611
*/
3922
3612
 
3923
3613
ha_rows DsMrr_impl::dsmrr_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
3924
 
                                 void *seq_init_param, uint32_t n_ranges, 
 
3614
                                 void *seq_init_param, uint32_t n_ranges,
3925
3615
                                 uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
3926
3616
{
3927
3617
  ha_rows rows;
3929
3619
  uint32_t def_bufsz= *bufsz;
3930
3620
  /* Get cost/flags/mem_usage of default MRR implementation */
3931
3621
  rows= h->handler::multi_range_read_info_const(keyno, seq, seq_init_param,
3932
 
                                                n_ranges, &def_bufsz, 
 
3622
                                                n_ranges, &def_bufsz,
3933
3623
                                                &def_flags, cost);
3934
3624
  if (rows == HA_POS_ERROR)
3935
3625
  {
4015
3705
{
4016
3706
  COST_VECT dsmrr_cost;
4017
3707
  bool res;
4018
 
  THD *thd= current_thd;
4019
 
  if ((thd->variables.optimizer_use_mrr == 2) || 
 
3708
  Session *session= current_session;
 
3709
  if ((session->variables.optimizer_use_mrr == 2) ||
4020
3710
      (*flags & HA_MRR_INDEX_ONLY) || (*flags & HA_MRR_SORTED) ||
4021
 
      (keyno == table->s->primary_key && 
4022
 
       h->primary_key_is_clustered()) || 
 
3711
      (keyno == table->s->primary_key &&
 
3712
       h->primary_key_is_clustered()) ||
4023
3713
       key_uses_partial_cols(keyno))
4024
3714
  {
4025
3715
    /* Use the default implementation */
4026
3716
    *flags |= HA_MRR_USE_DEFAULT_IMPL;
4027
3717
    return true;
4028
3718
  }
4029
 
  
4030
 
  uint32_t add_len= table->key_info[keyno].key_length + h->ref_length; 
 
3719
 
 
3720
  uint32_t add_len= table->key_info[keyno].key_length + h->ref_length;
4031
3721
  *bufsz -= add_len;
4032
3722
  if (get_disk_sweep_mrr_cost(keyno, rows, *flags, bufsz, &dsmrr_cost))
4033
3723
    return true;
4034
3724
  *bufsz += add_len;
4035
 
  
 
3725
 
4036
3726
  bool force_dsmrr;
4037
 
  /* 
 
3727
  /*
4038
3728
    If @@optimizer_use_mrr==force, then set cost of DS-MRR to be minimum of
4039
3729
    DS-MRR and Default implementations cost. This allows one to force use of
4040
3730
    DS-MRR whenever it is applicable without affecting other cost-based
4041
3731
    choices.
4042
3732
  */
4043
 
  if ((force_dsmrr= (thd->variables.optimizer_use_mrr == 1)) &&
 
3733
  if ((force_dsmrr= (session->variables.optimizer_use_mrr == 1)) &&
4044
3734
      dsmrr_cost.total_cost() > cost->total_cost())
4045
3735
    dsmrr_cost= *cost;
4046
3736
 
4092
3782
    return true; /* Buffer has not enough space for even 1 rowid */
4093
3783
 
4094
3784
  /* Number of iterations we'll make with full buffer */
4095
 
  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 
 
3785
  n_full_steps= (uint32_t)floor(rows2double(rows) / max_buff_entries);
 
3786
 
 
3787
  /*
 
3788
    Get numbers of rows we'll be processing in
 
3789
     - non-last sweep, with full buffer
4100
3790
     - last iteration, with non-full buffer
4101
3791
  */
4102
3792
  rows_in_full_step= max_buff_entries;
4103
3793
  rows_in_last_step= rows % max_buff_entries;
4104
 
  
 
3794
 
4105
3795
  /* Adjust buffer size if we expect to use only part of the buffer */
4106
3796
  if (n_full_steps)
4107
3797
  {
4111
3801
  else
4112
3802
  {
4113
3803
    cost->zero();
4114
 
    *buffer_size= cmax((ulong)*buffer_size, 
4115
 
                      (size_t)(1.2*rows_in_last_step) * elem_size + 
 
3804
    *buffer_size= cmax((ulong)*buffer_size,
 
3805
                      (size_t)(1.2*rows_in_last_step) * elem_size +
4116
3806
                      h->ref_length + table->key_info[keynr].key_length);
4117
3807
  }
4118
 
  
 
3808
 
4119
3809
  COST_VECT last_step_cost;
4120
3810
  get_sort_and_sweep_cost(table, rows_in_last_step, &last_step_cost);
4121
3811
  cost->add(&last_step_cost);
4122
 
 
 
3812
 
4123
3813
  if (n_full_steps != 0)
4124
3814
    cost->mem_cost= *buffer_size;
4125
3815
  else
4126
3816
    cost->mem_cost= (double)rows_in_last_step * elem_size;
4127
 
  
 
3817
 
4128
3818
  /* Total cost of all index accesses */
4129
3819
  index_read_cost= h->index_only_read_time(keynr, (double)rows);
4130
3820
  cost->add_io(index_read_cost, 1 /* Random seeks */);
4132
3822
}
4133
3823
 
4134
3824
 
4135
 
/* 
 
3825
/*
4136
3826
  Get cost of one sort-and-sweep step
4137
3827
 
4138
3828
  SYNOPSIS
4147
3837
     - read #nrows records from table in a sweep.
4148
3838
*/
4149
3839
 
4150
 
static 
 
3840
static
4151
3841
void get_sort_and_sweep_cost(Table *table, ha_rows nrows, COST_VECT *cost)
4152
3842
{
4153
3843
  if (nrows)
4181
3871
  Time to move the disk head is proportional to head travel distance.
4182
3872
 
4183
3873
  Time to wait for the plate to rotate depends on whether the disk head
4184
 
  was moved or not. 
 
3874
  was moved or not.
4185
3875
 
4186
3876
  If disk head wasn't moved, the wait time is proportional to distance
4187
3877
  between the previous block and the block we're reading.
4192
3882
 
4193
3883
  Our cost units are "random disk seeks". The cost of random disk seek is
4194
3884
  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 
 
3885
  to access. We make it constant by introducing a fuzzy concept of "typical
4196
3886
  datafile length" (it's fuzzy as it's hard to tell whether it should
4197
3887
  include index file, temp.tables etc). Then random seek cost is:
4198
3888
 
4207
3897
  @param cost         OUT  The cost.
4208
3898
*/
4209
3899
 
4210
 
void get_sweep_read_cost(Table *table, ha_rows nrows, bool interrupted, 
 
3900
void get_sweep_read_cost(Table *table, ha_rows nrows, bool interrupted,
4211
3901
                         COST_VECT *cost)
4212
3902
{
4213
3903
  cost->zero();
4214
3904
  if (table->file->primary_key_is_clustered())
4215
3905
  {
4216
3906
    cost->io_count= table->file->read_time(table->s->primary_key,
4217
 
                                           (uint) nrows, nrows);
 
3907
                                           (uint32_t) nrows, nrows);
4218
3908
  }
4219
3909
  else
4220
3910
  {
4263
3953
int handler::read_range_first(const key_range *start_key,
4264
3954
                              const key_range *end_key,
4265
3955
                              bool eq_range_arg,
4266
 
                              bool sorted  __attribute__((unused)))
 
3956
                              bool )
4267
3957
{
4268
3958
  int result;
4269
3959
 
4286
3976
                           start_key->keypart_map,
4287
3977
                           start_key->flag);
4288
3978
  if (result)
4289
 
    return((result == HA_ERR_KEY_NOT_FOUND) 
 
3979
    return((result == HA_ERR_KEY_NOT_FOUND)
4290
3980
                ? HA_ERR_END_OF_FILE
4291
3981
                : result);
4292
3982
 
4368
4058
  return cmp;
4369
4059
}
4370
4060
 
4371
 
int handler::index_read_idx_map(unsigned char * buf, uint32_t index, const unsigned char * key,
 
4061
int handler::index_read_idx_map(unsigned char * buf, uint32_t index,
 
4062
                                const unsigned char * key,
4372
4063
                                key_part_map keypart_map,
4373
4064
                                enum ha_rkey_function find_flag)
4374
4065
{
4393
4084
  @retval
4394
4085
    pointer             pointer to TYPELIB structure
4395
4086
*/
4396
 
static bool exts_handlerton(THD *unused __attribute__((unused)),
 
4087
static bool exts_handlerton(Session *,
4397
4088
                            plugin_ref plugin,
4398
4089
                            void *arg)
4399
4090
{
4401
4092
  handlerton *hton= plugin_data(plugin, handlerton *);
4402
4093
  handler *file;
4403
4094
  if (hton->state == SHOW_OPTION_YES && hton->create &&
4404
 
      (file= hton->create(hton, (TABLE_SHARE*) 0, current_thd->mem_root)))
 
4095
      (file= hton->create(hton, (TABLE_SHARE*) 0, current_session->mem_root)))
4405
4096
  {
4406
4097
    List_iterator_fast<char> it(*found_exts);
4407
4098
    const char **ext, *old_ext;
4435
4126
    plugin_foreach(NULL, exts_handlerton,
4436
4127
                   DRIZZLE_STORAGE_ENGINE_PLUGIN, &found_exts);
4437
4128
 
4438
 
    ext= (const char **) my_once_alloc(sizeof(char *)*
4439
 
                                       (found_exts.elements+1),
4440
 
                                       MYF(MY_WME | MY_FAE));
 
4129
    ext= (const char **) malloc(sizeof(char *)*
 
4130
                                (found_exts.elements+1));
 
4131
                              
4441
4132
 
4442
4133
    assert(ext != 0);
4443
4134
    known_extensions.count= found_exts.elements;
4452
4143
}
4453
4144
 
4454
4145
 
4455
 
static bool stat_print(THD *thd, const char *type, uint32_t type_len,
 
4146
static bool stat_print(Session *session, const char *type, uint32_t type_len,
4456
4147
                       const char *file, uint32_t file_len,
4457
4148
                       const char *status, uint32_t status_len)
4458
4149
{
4459
 
  Protocol *protocol= thd->protocol;
 
4150
  Protocol *protocol= session->protocol;
4460
4151
  protocol->prepare_for_resend();
4461
4152
  protocol->store(type, type_len, system_charset_info);
4462
4153
  protocol->store(file, file_len, system_charset_info);
4466
4157
  return false;
4467
4158
}
4468
4159
 
4469
 
bool ha_show_status(THD *thd, handlerton *db_type, enum ha_stat_type stat)
 
4160
bool ha_show_status(Session *session, handlerton *db_type, enum ha_stat_type stat)
4470
4161
{
4471
4162
  List<Item> field_list;
4472
 
  Protocol *protocol= thd->protocol;
 
4163
  Protocol *protocol= session->protocol;
4473
4164
  bool result;
4474
4165
 
4475
4166
  field_list.push_back(new Item_empty_string("Type",10));
4481
4172
    return true;
4482
4173
 
4483
4174
  result= db_type->show_status &&
4484
 
    db_type->show_status(db_type, thd, stat_print, stat) ? 1 : 0;
 
4175
    db_type->show_status(db_type, session, stat_print, stat) ? 1 : 0;
4485
4176
 
4486
4177
  if (!result)
4487
 
    my_eof(thd);
 
4178
    session->my_eof();
4488
4179
  return result;
4489
4180
}
4490
4181
 
4501
4192
  - table is not mysql.event
4502
4193
*/
4503
4194
 
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
 
  {
 
4195
static bool binlog_log_row(Table* table,
 
4196
                           const unsigned char *before_record,
 
4197
                           const unsigned char *after_record)
 
4198
{
 
4199
  bool error= false;
 
4200
  Session *const session= table->in_use;
 
4201
 
 
4202
  if (table->no_replicate == false)
 
4203
    return false;
 
4204
 
 
4205
  error= replicator_session_init(session);
 
4206
 
 
4207
  switch (session->lex->sql_command)
 
4208
  {
 
4209
  case SQLCOM_REPLACE:
 
4210
  case SQLCOM_INSERT:
 
4211
  case SQLCOM_REPLACE_SELECT:
 
4212
  case SQLCOM_INSERT_SELECT:
 
4213
  case SQLCOM_CREATE_TABLE:
 
4214
    error= replicator_write_row(session, table);
 
4215
    break;
 
4216
 
 
4217
  case SQLCOM_UPDATE:
 
4218
  case SQLCOM_UPDATE_MULTI:
 
4219
    error= replicator_update_row(session, table, before_record, after_record);
 
4220
    break;
 
4221
 
 
4222
  case SQLCOM_DELETE:
 
4223
  case SQLCOM_DELETE_MULTI:
 
4224
    error= replicator_delete_row(session, table);
 
4225
    break;
 
4226
 
4595
4227
    /*
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.
 
4228
      For everything else we ignore the event (since it just involves a temp table)
4599
4229
    */
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
 
    }
 
4230
  default:
 
4231
    break;
4605
4232
  }
4606
 
  return error ? HA_ERR_RBR_LOGGING_FAILED : 0;
 
4233
 
 
4234
  return error;
4607
4235
}
4608
4236
 
4609
 
int handler::ha_external_lock(THD *thd, int lock_type)
 
4237
int handler::ha_external_lock(Session *session, int lock_type)
4610
4238
{
4611
4239
  /*
4612
4240
    Whether this is lock or unlock, this should be true, and is to verify that
4621
4249
  */
4622
4250
  DRIZZLE_EXTERNAL_LOCK(lock_type);
4623
4251
 
4624
 
  int error= external_lock(thd, lock_type);
 
4252
  int error= external_lock(session, lock_type);
4625
4253
  if (error == 0)
4626
4254
    cached_table_flags= table_flags();
4627
4255
  return(error);
4652
4280
int handler::ha_write_row(unsigned char *buf)
4653
4281
{
4654
4282
  int error;
4655
 
  Log_func *log_func= Write_rows_log_event::binlog_row_logging_function;
4656
4283
  DRIZZLE_INSERT_ROW_START();
4657
4284
 
 
4285
  /* 
 
4286
   * If we have a timestamp column, update it to the current time 
 
4287
   * 
 
4288
   * @TODO Technically, the below two lines can be take even further out of the
 
4289
   * handler interface and into the fill_record() method.
 
4290
   */
 
4291
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
 
4292
    table->timestamp_field->set_time();
 
4293
 
4658
4294
  mark_trx_read_write();
4659
4295
 
4660
4296
  if (unlikely(error= write_row(buf)))
4661
4297
    return(error);
4662
 
  if (unlikely(error= binlog_log_row(table, 0, buf, log_func)))
4663
 
    return(error); /* purecov: inspected */
 
4298
 
 
4299
  if (unlikely(binlog_log_row(table, 0, buf)))
 
4300
    return HA_ERR_RBR_LOGGING_FAILED; /* purecov: inspected */
 
4301
 
4664
4302
  DRIZZLE_INSERT_ROW_END();
4665
4303
  return(0);
4666
4304
}
4669
4307
int handler::ha_update_row(const unsigned char *old_data, unsigned char *new_data)
4670
4308
{
4671
4309
  int error;
4672
 
  Log_func *log_func= Update_rows_log_event::binlog_row_logging_function;
4673
4310
 
4674
4311
  /*
4675
4312
    Some storage engines require that the new record is in record[0]
4681
4318
 
4682
4319
  if (unlikely(error= update_row(old_data, new_data)))
4683
4320
    return error;
4684
 
  if (unlikely(error= binlog_log_row(table, old_data, new_data, log_func)))
4685
 
    return error;
 
4321
 
 
4322
  if (unlikely(binlog_log_row(table, old_data, new_data)))
 
4323
    return HA_ERR_RBR_LOGGING_FAILED;
 
4324
 
4686
4325
  return 0;
4687
4326
}
4688
4327
 
4689
4328
int handler::ha_delete_row(const unsigned char *buf)
4690
4329
{
4691
4330
  int error;
4692
 
  Log_func *log_func= Delete_rows_log_event::binlog_row_logging_function;
4693
4331
 
4694
4332
  mark_trx_read_write();
4695
4333
 
4696
4334
  if (unlikely(error= delete_row(buf)))
4697
4335
    return error;
4698
 
  if (unlikely(error= binlog_log_row(table, buf, 0, log_func)))
4699
 
    return error;
 
4336
 
 
4337
  if (unlikely(binlog_log_row(table, buf, 0)))
 
4338
    return HA_ERR_RBR_LOGGING_FAILED;
 
4339
 
4700
4340
  return 0;
4701
4341
}
4702
4342
 
4713
4353
  /* fallback to use all columns in the table to identify row */
4714
4354
  table->use_all_columns();
4715
4355
}
 
4356
 
 
4357
void table_case_convert(char * name, uint32_t length)
 
4358
{
 
4359
  if (lower_case_table_names)
 
4360
    files_charset_info->cset->casedn(files_charset_info,
 
4361
                                     name, length, name, length);
 
4362
}
 
4363
 
 
4364
const char *table_case_name(HA_CREATE_INFO *info, const char *name)
 
4365
{
 
4366
  return ((lower_case_table_names == 2 && info->alias) ? info->alias : name);
 
4367
}