1
/* Copyright (C) 2000-2006 MySQL AB
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.
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.
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:
4
* Copyright (C) 2008 Sun Microsystems
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.
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.
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
19
23
Handler-calling-functions
22
#ifdef USE_PRAGMA_IMPLEMENTATION
23
#pragma implementation // gcc: Class implementation
26
#include <drizzled/server_includes.h>
27
#include "rpl_filter.h"
28
#include <drizzled/drizzled_error_messages.h>
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
35
st_plugin_int *hton2plugin[MAX_HA];
37
static handlerton *installed_htons[128];
39
#define BITMAP_STACKBUF_SIZE (128/8)
26
#include "drizzled/server_includes.h"
27
#include "mysys/hash.h"
28
#include "drizzled/error.h"
29
#include "drizzled/gettext.h"
30
#include "drizzled/data_home.h"
31
#include "drizzled/probes.h"
32
#include "drizzled/sql_parse.h"
33
#include "drizzled/cost_vect.h"
34
#include "drizzled/session.h"
35
#include "drizzled/sql_base.h"
36
#include "drizzled/replicator.h"
37
#include "drizzled/lock.h"
38
#include "drizzled/item/int.h"
39
#include "drizzled/item/empty_string.h"
40
#include "drizzled/unireg.h" // for mysql_frm_type
41
#include "drizzled/field/timestamp.h"
42
#include "drizzled/serialize/table.pb.h"
41
46
KEY_CREATE_INFO default_key_create_info= { HA_KEY_ALG_UNDEF, 0, {NULL,0}, {NULL,0} };
43
/* number of entries in handlertons[] */
48
/* number of entries in storage_engines[] */
44
49
uint32_t total_ha= 0;
45
/* number of storage engines (from handlertons[]) that support 2pc */
50
/* number of storage engines (from storage_engines[]) that support 2pc */
46
51
uint32_t total_ha_2pc= 0;
47
52
/* size of savepoint storage area (see ha_init) */
48
53
uint32_t savepoint_alloc_size= 0;
50
static const LEX_STRING sys_table_aliases[]=
52
{ C_STRING_WITH_LEN("INNOBASE") }, { C_STRING_WITH_LEN("INNODB") },
53
{ C_STRING_WITH_LEN("HEAP") }, { C_STRING_WITH_LEN("MEMORY") },
57
55
const char *ha_row_type[] = {
58
56
"", "FIXED", "DYNAMIC", "COMPRESSED", "REDUNDANT", "COMPACT", "PAGE", "?","?","?"
61
59
const char *tx_isolation_names[] =
62
60
{ "READ-UNCOMMITTED", "READ-COMMITTED", "REPEATABLE-READ", "SERIALIZABLE",
64
63
TYPELIB tx_isolation_typelib= {array_elements(tx_isolation_names)-1,"",
65
tx_isolation_names, NULL};
64
tx_isolation_names, NULL};
67
66
static TYPELIB known_extensions= {0,"known_exts", NULL, NULL};
68
67
uint32_t known_extensions_id= 0;
72
static plugin_ref ha_default_plugin(THD *thd)
74
if (thd->variables.table_plugin)
75
return thd->variables.table_plugin;
76
return my_plugin_lock(thd, &global_system_variables.table_plugin);
81
Return the default storage engine handlerton for thread
83
@param ha_default_handlerton(thd)
84
@param thd current thread
89
handlerton *ha_default_handlerton(THD *thd)
91
plugin_ref plugin= ha_default_plugin(thd);
93
handlerton *hton= plugin_data(plugin, handlerton*);
100
Return the storage engine handlerton for the supplied name
102
@param thd current thread
103
@param name name of storage engine
106
pointer to storage engine plugin handle
108
plugin_ref ha_resolve_by_name(THD *thd, const LEX_STRING *name)
110
const LEX_STRING *table_alias;
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);
120
if ((plugin= my_plugin_lock_by_name(thd, name, DRIZZLE_STORAGE_ENGINE_PLUGIN)))
122
handlerton *hton= plugin_data(plugin, handlerton *);
123
if (!(hton->flags & HTON_NOT_USER_SELECTABLE))
127
unlocking plugin immediately after locking is relatively low cost.
129
plugin_unlock(thd, plugin);
133
We check for the historical aliases.
135
for (table_alias= sys_table_aliases; table_alias->str; table_alias+= 2)
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))
141
name= table_alias + 1;
150
plugin_ref ha_lock_engine(THD *thd, handlerton *hton)
154
st_plugin_int **plugin= hton2plugin + hton->slot;
156
return my_plugin_lock(thd, &plugin);
162
handlerton *ha_resolve_by_legacy_type(THD *thd, enum legacy_db_type db_type)
166
case DB_TYPE_DEFAULT:
167
return ha_default_handlerton(thd);
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*);
173
case DB_TYPE_UNKNOWN:
180
Use other database handler if databasehandler is not compiled in.
182
handlerton *ha_checktype(THD *thd, enum legacy_db_type database_type,
183
bool no_substitute, bool report_error)
185
handlerton *hton= ha_resolve_by_legacy_type(thd, database_type);
186
if (ha_storage_engine_is_enabled(hton))
193
const char *engine_name= ha_resolve_storage_engine_name(hton);
194
my_error(ER_FEATURE_DISABLED,MYF(0),engine_name,engine_name);
199
return ha_default_handlerton(thd);
203
handler *get_new_handler(TABLE_SHARE *share, MEM_ROOT *alloc,
208
if (db_type && db_type->state == SHOW_OPTION_YES && db_type->create)
210
if ((file= db_type->create(db_type, share, alloc)))
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.
219
return(get_new_handler(share, alloc, ha_default_handlerton(current_thd)));
224
71
Register handler error messages for use with my_error().
311
int ha_finalize_handlerton(st_plugin_int *plugin)
313
handlerton *hton= (handlerton *)plugin->data;
318
case SHOW_OPTION_DISABLED:
320
case SHOW_OPTION_YES:
321
if (installed_htons[hton->db_type] == hton)
322
installed_htons[hton->db_type]= NULL;
326
if (hton && plugin->plugin->deinit)
327
(void)plugin->plugin->deinit(hton);
329
free((unsigned char*)hton);
335
int ha_initialize_handlerton(st_plugin_int *plugin)
339
hton= (handlerton *)my_malloc(sizeof(handlerton),
340
MYF(MY_WME | MY_ZEROFILL));
342
FIXME: the MY_ZEROFILL flag above doesn't zero all the bytes.
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
348
memset(hton, 0, sizeof(hton));
349
/* Historical Requirement */
350
plugin->data= hton; // shortcut for the future
351
if (plugin->plugin->init)
353
if (plugin->plugin->init(hton))
355
sql_print_error(_("Plugin '%s' init function returned error."),
362
the switch below and hton->state should be removed when
363
command-line options for plugins will be implemented
365
switch (hton->state) {
368
case SHOW_OPTION_YES:
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])
376
int idx= (int) DB_TYPE_FIRST_DYNAMIC;
378
while (idx < (int) DB_TYPE_DEFAULT && installed_htons[idx])
381
if (idx == (int) DB_TYPE_DEFAULT)
383
sql_print_warning(_("Too many storage engines!"));
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;
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;
403
hton->state= SHOW_OPTION_DISABLED;
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.
412
if (strcmp(plugin->plugin->name, "MEMORY") == 0)
415
if (strcmp(plugin->plugin->name, "MyISAM") == 0)
453
static bool dropdb_handlerton(THD *unused1 __attribute__((unused)),
186
static bool dropdb_storage_engine(Session *,
457
handlerton *hton= plugin_data(plugin, handlerton *);
458
if (hton->state == SHOW_OPTION_YES && hton->drop_database)
459
hton->drop_database(hton, (char *)path);
190
StorageEngine *engine= plugin_data(plugin, StorageEngine *);
191
if (engine->is_enabled())
192
engine->drop_database((char *)path);
464
197
void ha_drop_database(char* path)
466
plugin_foreach(NULL, dropdb_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN, path);
199
plugin_foreach(NULL, dropdb_storage_engine, DRIZZLE_STORAGE_ENGINE_PLUGIN, path);
470
static bool closecon_handlerton(THD *thd, plugin_ref plugin,
471
void *unused __attribute__((unused)))
203
static bool closecon_storage_engine(Session *session, plugin_ref plugin,
473
handlerton *hton= plugin_data(plugin, handlerton *);
206
StorageEngine *engine= plugin_data(plugin, StorageEngine *);
475
208
there's no need to rollback here as all transactions must
476
209
be rolled back already
478
if (hton->state == SHOW_OPTION_YES && hton->close_connection &&
479
thd_get_ha_data(thd, hton))
480
hton->close_connection(hton, thd);
211
if (engine->is_enabled() &&
212
session_get_ha_data(session, engine))
213
engine->close_connection(session);
595
328
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
329
session->transaction. This structure has two members of type
330
Session_TRANS. These members correspond to the statement and
598
331
normal transactions respectively:
600
- thd->transaction.stmt contains a list of engines
333
- session->transaction.stmt contains a list of engines
601
334
that are participating in the given statement
602
- thd->transaction.all contains a list of engines that
335
- session->transaction.all contains a list of engines that
603
336
have participated in any of the statement transactions started
604
337
within the context of the normal transaction.
605
338
Each element of the list contains a pointer to the storage
606
339
engine, engine-specific transactional data, and engine-specific
607
340
transaction flags.
609
In autocommit mode thd->transaction.all is empty.
610
Instead, data of thd->transaction.stmt is
342
In autocommit mode session->transaction.all is empty.
343
Instead, data of session->transaction.stmt is
611
344
used to commit/rollback the normal transaction.
613
346
The list of registered engines has a few important properties:
736
469
At the end of a statement, server call
737
470
ha_autocommit_or_rollback() is invoked. This call in turn
738
invokes handlerton::prepare() for every involved engine.
739
Prepare is followed by a call to handlerton::commit_one_phase()
740
If a one-phase commit will suffice, handlerton::prepare() is not
741
invoked and the server only calls handlerton::commit_one_phase().
471
invokes StorageEngine::prepare() for every involved engine.
472
Prepare is followed by a call to StorageEngine::commit_one_phase()
473
If a one-phase commit will suffice, StorageEngine::prepare() is not
474
invoked and the server only calls StorageEngine::commit_one_phase().
742
475
At statement commit, the statement-related read-write engine
743
476
flag is propagated to the corresponding flag in the normal
744
477
transaction. When the commit is complete, the list of registered
750
483
---------------------------------------------------
752
485
DDLs and operations with non-transactional engines
753
do not "register" in thd->transaction lists, and thus do not
486
do not "register" in session->transaction lists, and thus do not
754
487
modify the transaction state. Besides, each DDL in
755
488
MySQL is prefixed with an implicit normal transaction commit
756
(a call to end_active_trans()), and thus leaves nothing
489
(a call to Session::endActiveTransaction()), and thus leaves nothing
758
491
However, as it has been pointed out with CREATE TABLE .. SELECT,
759
492
some DDL statements can start a *new* transaction.
797
530
times per transaction.
800
void trans_register_ha(THD *thd, bool all, handlerton *ht_arg)
533
void trans_register_ha(Session *session, bool all, StorageEngine *engine)
535
Session_TRANS *trans;
803
536
Ha_trx_info *ha_info;
807
trans= &thd->transaction.all;
808
thd->server_status|= SERVER_STATUS_IN_TRANS;
540
trans= &session->transaction.all;
541
session->server_status|= SERVER_STATUS_IN_TRANS;
811
trans= &thd->transaction.stmt;
544
trans= &session->transaction.stmt;
813
ha_info= thd->ha_data[ht_arg->slot].ha_info + static_cast<unsigned>(all);
546
ha_info= session->ha_data[engine->slot].ha_info + static_cast<unsigned>(all);
815
548
if (ha_info->is_started())
816
549
return; /* already registered, return */
818
ha_info->register_ha(trans, ht_arg);
551
ha_info->register_ha(trans, engine);
820
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);
553
trans->no_2pc|= not engine->has_2pc();
554
if (session->transaction.xid_state.xid.is_null())
555
session->transaction.xid_state.xid.set(session->query_id);
831
564
1 error, transaction was rolled back
833
int ha_prepare(THD *thd)
566
int ha_prepare(Session *session)
835
568
int error=0, all=1;
836
THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt;
569
Session_TRANS *trans=all ? &session->transaction.all : &session->transaction.stmt;
837
570
Ha_trx_info *ha_info= trans->ha_list;
840
573
for (; ha_info; ha_info= ha_info->next())
843
handlerton *ht= ha_info->ht();
844
status_var_increment(thd->status_var.ha_prepare_count);
576
StorageEngine *engine= ha_info->engine();
577
status_var_increment(session->status_var.ha_prepare_count);
578
if ((err= engine->prepare(session, all)))
847
if ((err= ht->prepare(ht, thd, all)))
849
my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
850
ha_rollback_trans(thd, all);
580
my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
581
ha_rollback_trans(session, all);
857
push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
587
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
858
588
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
859
ha_resolve_storage_engine_name(ht));
589
ha_resolve_storage_engine_name(engine));
933
663
stored functions or triggers. So we simply do nothing now.
934
664
TODO: This should be fixed in later ( >= 5.1) releases.
936
int ha_commit_trans(THD *thd, bool all)
666
int ha_commit_trans(Session *session, bool all)
938
668
int error= 0, cookie= 0;
940
670
'all' means that this is either an explicit commit issued by
941
671
user, or an implicit commit issued by a DDL.
943
THD_TRANS *trans= all ? &thd->transaction.all : &thd->transaction.stmt;
944
bool is_real_trans= all || thd->transaction.all.ha_list == 0;
673
Session_TRANS *trans= all ? &session->transaction.all : &session->transaction.stmt;
674
bool is_real_trans= all || session->transaction.all.ha_list == 0;
945
675
Ha_trx_info *ha_info= trans->ha_list;
946
my_xid xid= thd->transaction.xid_state.xid.get_my_xid();
949
678
We must not commit the normal transaction if a statement
951
680
flags will not get propagated to its normal transaction's
954
assert(thd->transaction.stmt.ha_list == NULL ||
955
trans == &thd->transaction.stmt);
683
assert(session->transaction.stmt.ha_list == NULL ||
684
trans == &session->transaction.stmt);
957
if (thd->in_sub_stmt)
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.
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.
974
my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
981
if (is_real_trans && wait_if_global_read_lock(thd, 0, 0))
690
if (is_real_trans && wait_if_global_read_lock(session, 0, 0))
983
ha_rollback_trans(thd, all);
692
ha_rollback_trans(session, all);
989
&& ! thd->slave_thread
992
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only");
993
ha_rollback_trans(thd, all);
998
must_2pc= ha_check_and_coalesce_trx_read_only(thd, ha_info, all);
696
must_2pc= ha_check_and_coalesce_trx_read_only(session, ha_info, all);
1000
698
if (!trans->no_2pc && must_2pc)
1002
700
for (; ha_info && !error; ha_info= ha_info->next())
1005
handlerton *ht= ha_info->ht();
703
StorageEngine *engine= ha_info->engine();
1007
705
Do not call two-phase commit if this particular
1008
706
transaction is read-only. This allows for simpler
1014
712
Sic: we know that prepare() is not NULL since otherwise
1015
713
trans->no_2pc would have been set.
1017
if ((err= ht->prepare(ht, thd, all)))
715
if ((err= engine->prepare(session, all)))
1019
717
my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
1022
status_var_increment(thd->status_var.ha_prepare_count);
720
status_var_increment(session->status_var.ha_prepare_count);
1024
if (error || (is_real_trans && xid &&
1025
(error= !(cookie= tc_log->log_xid(thd, xid)))))
1027
ha_rollback_trans(thd, all);
724
ha_rollback_trans(session, all);
1032
error=ha_commit_one_phase(thd, all) ? (cookie ? 2 : 1) : 0;
1034
tc_log->unlog(cookie, xid);
729
error=ha_commit_one_phase(session, all) ? (cookie ? 2 : 1) : 0;
1036
731
if (is_real_trans)
1037
start_waiting_global_read_lock(thd);
732
start_waiting_global_read_lock(session);
1044
739
This function does not care about global read lock. A caller should.
1046
int ha_commit_one_phase(THD *thd, bool all)
741
int ha_commit_one_phase(Session *session, bool all)
1049
THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt;
1050
bool is_real_trans=all || thd->transaction.all.ha_list == 0;
744
Session_TRANS *trans=all ? &session->transaction.all : &session->transaction.stmt;
745
bool is_real_trans=all || session->transaction.all.ha_list == 0;
1051
746
Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
1054
749
for (; ha_info; ha_info= ha_info_next)
1057
handlerton *ht= ha_info->ht();
1058
if ((err= ht->commit(ht, thd, all)))
752
StorageEngine *engine= ha_info->engine();
753
if ((err= engine->commit(session, all)))
1060
755
my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
1063
status_var_increment(thd->status_var.ha_commit_count);
758
status_var_increment(session->status_var.ha_commit_count);
1064
759
ha_info_next= ha_info->next();
1065
760
ha_info->reset(); /* keep it conveniently zero-filled */
1067
762
trans->ha_list= 0;
1068
763
trans->no_2pc=0;
1069
764
if (is_real_trans)
1070
thd->transaction.xid_state.xid.null();
765
session->transaction.xid_state.xid.null();
1073
thd->variables.tx_isolation=thd->session_tx_isolation;
1074
thd->transaction.cleanup();
768
session->variables.tx_isolation=session->session_tx_isolation;
769
session->transaction.cleanup();
1081
int ha_rollback_trans(THD *thd, bool all)
776
int ha_rollback_trans(Session *session, bool all)
1084
THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt;
779
Session_TRANS *trans=all ? &session->transaction.all : &session->transaction.stmt;
1085
780
Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
1086
bool is_real_trans=all || thd->transaction.all.ha_list == 0;
781
bool is_real_trans=all || session->transaction.all.ha_list == 0;
1089
784
We must not rollback the normal transaction if a statement
1090
785
transaction is pending.
1092
assert(thd->transaction.stmt.ha_list == NULL ||
1093
trans == &thd->transaction.stmt);
787
assert(session->transaction.stmt.ha_list == NULL ||
788
trans == &session->transaction.stmt);
1095
if (thd->in_sub_stmt)
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.
1105
my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
1110
792
for (; ha_info; ha_info= ha_info_next)
1113
handlerton *ht= ha_info->ht();
1114
if ((err= ht->rollback(ht, thd, all)))
795
StorageEngine *engine= ha_info->engine();
796
if ((err= engine->rollback(session, all)))
1115
797
{ // cannot happen
1116
798
my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
1119
status_var_increment(thd->status_var.ha_rollback_count);
801
status_var_increment(session->status_var.ha_rollback_count);
1120
802
ha_info_next= ha_info->next();
1121
803
ha_info->reset(); /* keep it conveniently zero-filled */
1123
805
trans->ha_list= 0;
1124
806
trans->no_2pc=0;
1125
807
if (is_real_trans)
1126
thd->transaction.xid_state.xid.null();
808
session->transaction.xid_state.xid.null();
1129
thd->variables.tx_isolation=thd->session_tx_isolation;
1130
thd->transaction.cleanup();
811
session->variables.tx_isolation=session->session_tx_isolation;
812
session->transaction.cleanup();
1134
thd->transaction_rollback_request= false;
816
session->transaction_rollback_request= false;
1137
819
If a non-transactional table was updated, warn; don't warn if this is a
1161
842
the user has used LOCK TABLES then that mechanism does not know to do the
1164
int ha_autocommit_or_rollback(THD *thd, int error)
845
int ha_autocommit_or_rollback(Session *session, int error)
1166
if (thd->transaction.stmt.ha_list)
847
if (session->transaction.stmt.ha_list)
1170
if (ha_commit_trans(thd, 0))
851
if (ha_commit_trans(session, 0))
1175
(void) ha_rollback_trans(thd, 0);
1176
if (thd->transaction_rollback_request && !thd->in_sub_stmt)
1177
(void) ha_rollback(thd);
856
(void) ha_rollback_trans(session, 0);
857
if (session->transaction_rollback_request)
858
(void) ha_rollback(session);
1180
thd->variables.tx_isolation=thd->session_tx_isolation;
861
session->variables.tx_isolation=session->session_tx_isolation;
1191
static bool xacommit_handlerton(THD *unused1 __attribute__((unused)),
872
static bool xacommit_storage_engine(Session *,
1195
handlerton *hton= plugin_data(plugin, handlerton *);
1196
if (hton->state == SHOW_OPTION_YES && hton->recover)
876
StorageEngine *engine= plugin_data(plugin, StorageEngine *);
877
if (engine->is_enabled())
1198
hton->commit_by_xid(hton, ((struct xahton_st *)arg)->xid);
1199
((struct xahton_st *)arg)->result= 0;
879
engine->commit_by_xid(((struct xaengine_st *)arg)->xid);
880
((struct xaengine_st *)arg)->result= 0;
1204
static bool xarollback_handlerton(THD *unused1 __attribute__((unused)),
885
static bool xarollback_storage_engine(Session *,
1205
886
plugin_ref plugin,
1208
handlerton *hton= plugin_data(plugin, handlerton *);
1209
if (hton->state == SHOW_OPTION_YES && hton->recover)
889
StorageEngine *engine= plugin_data(plugin, StorageEngine *);
890
if (engine->is_enabled())
1211
hton->rollback_by_xid(hton, ((struct xahton_st *)arg)->xid);
1212
((struct xahton_st *)arg)->result= 0;
892
engine->rollback_by_xid(((struct xaengine_st *)arg)->xid);
893
((struct xaengine_st *)arg)->result= 0;
1254
static bool xarecover_handlerton(THD *unused __attribute__((unused)),
935
static bool xarecover_storage_engine(Session *,
1258
handlerton *hton= plugin_data(plugin, handlerton *);
939
StorageEngine *engine= plugin_data(plugin, StorageEngine *);
1259
940
struct xarecover_st *info= (struct xarecover_st *) arg;
1262
if (hton->state == SHOW_OPTION_YES && hton->recover)
943
if (engine->is_enabled())
1264
while ((got= hton->recover(hton, info->list, info->len)) > 0 )
945
while ((got= engine->recover(info->list, info->len)) > 0 )
1266
sql_print_information(_("Found %d prepared transaction(s) in %s"),
1267
got, ha_resolve_storage_engine_name(hton));
947
errmsg_printf(ERRMSG_LVL_INFO, _("Found %d prepared transaction(s) in %s"),
948
got, ha_resolve_storage_engine_name(engine));
1268
949
for (int i=0; i < got; i ++)
1270
951
my_xid x=info->list[i].get_my_xid();
1325
1006
rollback all pending transactions, without risking inconsistent data
1328
assert(total_ha_2pc == (uint32_t) opt_bin_log+1); // only InnoDB and binlog
1009
assert(total_ha_2pc == 2); // only InnoDB and binlog
1329
1010
tc_heuristic_recover= TC_HEURISTIC_RECOVER_ROLLBACK; // forcing ROLLBACK
1330
1011
info.dry_run=false;
1334
for (info.len= MAX_XID_LIST_SIZE ;
1015
for (info.len= MAX_XID_LIST_SIZE ;
1335
1016
info.list==0 && info.len > MIN_XID_LIST_SIZE; info.len/=2)
1337
info.list=(XID *)my_malloc(info.len*sizeof(XID), MYF(0));
1018
info.list=(XID *)malloc(info.len*sizeof(XID));
1339
1020
if (!info.list)
1341
sql_print_error(ER(ER_OUTOFMEMORY), info.len*sizeof(XID));
1022
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_OUTOFMEMORY), info.len*sizeof(XID));
1345
plugin_foreach(NULL, xarecover_handlerton,
1026
plugin_foreach(NULL, xarecover_storage_engine,
1346
1027
DRIZZLE_STORAGE_ENGINE_PLUGIN, &info);
1348
1029
free((unsigned char*)info.list);
1349
1030
if (info.found_foreign_xids)
1350
sql_print_warning(_("Found %d prepared XA transactions"),
1351
info.found_foreign_xids);
1031
errmsg_printf(ERRMSG_LVL_WARN, _("Found %d prepared XA transactions"),
1032
info.found_foreign_xids);
1352
1033
if (info.dry_run && info.found_my_xids)
1354
sql_print_error(_("Found %d prepared transactions! It means that drizzled "
1035
errmsg_printf(ERRMSG_LVL_ERROR,
1036
_("Found %d prepared transactions! It means that drizzled "
1355
1037
"was not shut down properly last time and critical "
1356
1038
"recovery information (last binlog or %s file) was "
1357
1039
"manually deleted after a crash. You have to start "
1426
1108
performs another SQL query. In MySQL-4.1 this is even more important because
1427
1109
there a connection can have several SELECT queries open at the same time.
1429
@param thd the thread handle of the current connection
1111
@param session the thread handle of the current connection
1434
static bool release_temporary_latches(THD *thd, plugin_ref plugin,
1435
void *unused __attribute__((unused)))
1116
static bool release_temporary_latches(Session *session, plugin_ref plugin,
1437
handlerton *hton= plugin_data(plugin, handlerton *);
1119
StorageEngine *engine= plugin_data(plugin, StorageEngine *);
1439
if (hton->state == SHOW_OPTION_YES && hton->release_temporary_latches)
1440
hton->release_temporary_latches(hton, thd);
1121
if (engine->is_enabled())
1122
engine->release_temporary_latches(session);
1446
int ha_release_temporary_latches(THD *thd)
1128
int ha_release_temporary_latches(Session *session)
1448
plugin_foreach(thd, release_temporary_latches, DRIZZLE_STORAGE_ENGINE_PLUGIN,
1130
plugin_foreach(session, release_temporary_latches, DRIZZLE_STORAGE_ENGINE_PLUGIN,
1454
int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv)
1136
int ha_rollback_to_savepoint(Session *session, SAVEPOINT *sv)
1457
THD_TRANS *trans= (thd->in_sub_stmt ? &thd->transaction.stmt :
1458
&thd->transaction.all);
1139
Session_TRANS *trans= &session->transaction.all;
1459
1140
Ha_trx_info *ha_info, *ha_info_next;
1461
1142
trans->no_2pc=0;
1466
1147
for (ha_info= sv->ha_list; ha_info; ha_info= ha_info->next())
1469
handlerton *ht= ha_info->ht();
1471
assert(ht->savepoint_set != 0);
1472
if ((err= ht->savepoint_rollback(ht, thd,
1473
(unsigned char *)(sv+1)+ht->savepoint_offset)))
1150
StorageEngine *engine= ha_info->engine();
1152
if ((err= engine->savepoint_rollback(session,
1474
1154
{ // cannot happen
1475
1155
my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
1478
status_var_increment(thd->status_var.ha_savepoint_rollback_count);
1479
trans->no_2pc|= ht->prepare == 0;
1158
status_var_increment(session->status_var.ha_savepoint_rollback_count);
1159
trans->no_2pc|= not engine->has_2pc();
1482
1162
rolling back the transaction in all storage engines that were not part of
1506
1186
section "4.33.4 SQL-statements and transaction states",
1507
1187
SAVEPOINT is *not* transaction-initiating SQL-statement
1509
int ha_savepoint(THD *thd, SAVEPOINT *sv)
1189
int ha_savepoint(Session *session, SAVEPOINT *sv)
1512
THD_TRANS *trans= (thd->in_sub_stmt ? &thd->transaction.stmt :
1513
&thd->transaction.all);
1192
Session_TRANS *trans= &session->transaction.all;
1514
1193
Ha_trx_info *ha_info= trans->ha_list;
1515
1194
for (; ha_info; ha_info= ha_info->next())
1518
handlerton *ht= ha_info->ht();
1520
if (! ht->savepoint_set)
1197
StorageEngine *engine= ha_info->engine();
1199
/* if (! engine->savepoint_set)
1522
1201
my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "SAVEPOINT");
1526
if ((err= ht->savepoint_set(ht, thd, (unsigned char *)(sv+1)+ht->savepoint_offset)))
1205
if ((err= engine->savepoint_set(session, (void *)(sv+1))))
1527
1206
{ // cannot happen
1528
1207
my_error(ER_GET_ERRNO, MYF(0), err);
1531
status_var_increment(thd->status_var.ha_savepoint_count);
1210
status_var_increment(session->status_var.ha_savepoint_count);
1534
1213
Remember the list of registered storage engines. All new
1565
static bool snapshot_handlerton(THD *thd, plugin_ref plugin, void *arg)
1242
static bool snapshot_storage_engine(Session *session, plugin_ref plugin, void *arg)
1567
handlerton *hton= plugin_data(plugin, handlerton *);
1568
if (hton->state == SHOW_OPTION_YES &&
1569
hton->start_consistent_snapshot)
1244
StorageEngine *engine= plugin_data(plugin, StorageEngine *);
1245
if (engine->is_enabled())
1571
hton->start_consistent_snapshot(hton, thd);
1247
engine->start_consistent_snapshot(session);
1572
1248
*((bool *)arg)= false;
1577
int ha_start_consistent_snapshot(THD *thd)
1253
int ha_start_consistent_snapshot(Session *session)
1579
1255
bool warn= true;
1581
plugin_foreach(thd, snapshot_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN, &warn);
1257
plugin_foreach(session, snapshot_storage_engine, DRIZZLE_STORAGE_ENGINE_PLUGIN, &warn);
1584
1260
Same idea as when one wants to CREATE TABLE in one engine which does not
1588
push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
1589
"This MySQL server does not support any "
1264
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
1265
"This Drizzle server does not support any "
1590
1266
"consistent-read capable storage engine");
1595
static bool flush_handlerton(THD *thd __attribute__((unused)),
1271
static bool flush_storage_engine(Session *,
1596
1272
plugin_ref plugin,
1597
void *arg __attribute__((unused)))
1599
handlerton *hton= plugin_data(plugin, handlerton *);
1600
if (hton->state == SHOW_OPTION_YES && hton->flush_logs &&
1601
hton->flush_logs(hton))
1275
StorageEngine *engine= plugin_data(plugin, StorageEngine *);
1276
if (engine->is_enabled() &&
1277
engine->flush_logs())
1607
bool ha_flush_logs(handlerton *db_type)
1283
bool ha_flush_logs(StorageEngine *engine)
1609
if (db_type == NULL)
1611
if (plugin_foreach(NULL, flush_handlerton,
1287
if (plugin_foreach(NULL, flush_storage_engine,
1612
1288
DRIZZLE_STORAGE_ENGINE_PLUGIN, 0))
1617
if (db_type->state != SHOW_OPTION_YES ||
1618
(db_type->flush_logs && db_type->flush_logs(db_type)))
1293
if ((!engine->is_enabled()) ||
1294
(engine->flush_logs()))
1649
1325
struct Ha_delete_table_error_handler: public Internal_error_handler
1328
Ha_delete_table_error_handler() : Internal_error_handler() {}
1652
1329
virtual bool handle_error(uint32_t sql_errno,
1653
1330
const char *message,
1654
1331
DRIZZLE_ERROR::enum_warning_level level,
1656
1333
char buff[DRIZZLE_ERRMSG_SIZE];
1661
1338
Ha_delete_table_error_handler::
1662
handle_error(uint32_t sql_errno __attribute__((unused)),
1339
handle_error(uint32_t ,
1663
1340
const char *message,
1664
DRIZZLE_ERROR::enum_warning_level level __attribute__((unused)),
1665
THD *thd __attribute__((unused)))
1341
DRIZZLE_ERROR::enum_warning_level ,
1667
1344
/* Grab the error message */
1668
strmake(buff, message, sizeof(buff)-1);
1345
strncpy(buff, message, sizeof(buff)-1);
1350
struct storage_engine_delete_table_args {
1357
static bool deletetable_storage_engine(Session *,
1361
struct storage_engine_delete_table_args *dtargs= (struct storage_engine_delete_table_args *) args;
1363
Session *session= dtargs->session;
1364
const char *path= dtargs->path;
1367
char tmp_path[FN_REFLEN];
1369
if(dtargs->error!=ENOENT) /* already deleted table */
1372
StorageEngine *engine= plugin_data(plugin, StorageEngine *);
1377
if (!engine->is_enabled())
1380
if ((file= engine->create(NULL, session->mem_root)))
1385
path= check_lowercase_names(file, path, tmp_path);
1386
int error= file->ha_delete_table(path);
1390
dtargs->error= error;
1392
delete dtargs->file;
1674
1403
This should return ENOENT if the file doesn't exists.
1675
1404
The .frm file will be deleted only if we return 0 or ENOENT
1677
int ha_delete_table(THD *thd, handlerton *table_type, const char *path,
1406
int ha_delete_table(Session *session, const char *path,
1678
1407
const char *db, const char *alias, bool generate_warning)
1681
char tmp_path[FN_REFLEN];
1409
TABLE_SHARE dummy_share;
1683
1410
Table dummy_table;
1684
TABLE_SHARE dummy_share;
1412
struct storage_engine_delete_table_args dtargs;
1413
dtargs.error= ENOENT;
1414
dtargs.session= session;
1418
plugin_foreach(NULL, deletetable_storage_engine, DRIZZLE_STORAGE_ENGINE_PLUGIN,
1686
1421
memset(&dummy_table, 0, sizeof(dummy_table));
1687
1422
memset(&dummy_share, 0, sizeof(dummy_share));
1688
1423
dummy_table.s= &dummy_share;
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)))
1695
path= check_lowercase_names(file, path, tmp_path);
1696
if ((error= file->ha_delete_table(path)) && generate_warning)
1425
if (dtargs.error && generate_warning)
1699
1428
Because file->print_error() use my_error() to generate the error message
1712
1441
dummy_share.table_name.length= strlen(alias);
1713
1442
dummy_table.alias= alias;
1715
file->change_table_ptr(&dummy_table, &dummy_share);
1717
thd->push_internal_handler(&ha_delete_table_error_handler);
1718
file->print_error(error, 0);
1720
thd->pop_internal_handler();
1446
handler *file= dtargs.file;
1447
file->change_table_ptr(&dummy_table, &dummy_share);
1449
session->push_internal_handler(&ha_delete_table_error_handler);
1450
file->print_error(dtargs.error, 0);
1452
session->pop_internal_handler();
1455
dtargs.error= -1; /* General form of fail. maybe bad FRM */
1723
1458
XXX: should we convert *all* errors to warnings here?
1724
1459
What if the error is fatal?
1726
push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_ERROR, error,
1461
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR, dtargs.error,
1727
1462
ha_delete_table_error_handler.buff);
1468
return dtargs.error;
1733
1471
/****************************************************************************
1492
int handler::ha_index_init(uint32_t idx, bool sorted)
1495
assert(inited==NONE);
1496
if (!(result= index_init(idx, sorted)))
1502
int handler::ha_index_end()
1504
assert(inited==INDEX);
1507
return(index_end());
1510
int handler::ha_rnd_init(bool scan)
1513
assert(inited==NONE || (inited==RND && scan));
1514
inited= (result= rnd_init(scan)) ? NONE: RND;
1518
int handler::ha_rnd_end()
1520
assert(inited==RND);
1525
int handler::ha_index_or_rnd_end()
1527
return inited == INDEX ? ha_index_end() : inited == RND ? ha_rnd_end() : 0;
1530
handler::Table_flags handler::ha_table_flags() const
1532
return cached_table_flags;
1535
void handler::ha_start_bulk_insert(ha_rows rows)
1537
estimation_rows_to_insert= rows;
1538
start_bulk_insert(rows);
1541
int handler::ha_end_bulk_insert()
1543
estimation_rows_to_insert= 0;
1544
return end_bulk_insert();
1547
void handler::change_table_ptr(Table *table_arg, TABLE_SHARE *share)
1553
const key_map *handler::keys_to_use_for_scanning()
1555
return &key_map_empty;
1558
bool handler::has_transactions()
1560
return (ha_table_flags() & HA_NO_TRANSACTIONS) == 0;
1756
1563
void handler::ha_statistic_increment(ulong SSV::*offset) const
1758
1565
status_var_increment(table->in_use->status_var.*offset);
1761
void **handler::ha_data(THD *thd) const
1763
return thd_ha_data(thd, ht);
1766
THD *handler::ha_thd(void) const
1768
assert(!table || !table->in_use || table->in_use == current_thd);
1769
return (table && table->in_use) ? table->in_use : current_thd;
1568
void **handler::ha_data(Session *session) const
1570
return session_ha_data(session, engine);
1573
Session *handler::ha_session(void) const
1575
assert(!table || !table->in_use || table->in_use == current_session);
1576
return (table && table->in_use) ? table->in_use : current_session;
1580
bool handler::is_fatal_error(int error, uint32_t flags)
1583
((flags & HA_CHECK_DUP_KEY) &&
1584
(error == HA_ERR_FOUND_DUPP_KEY ||
1585
error == HA_ERR_FOUND_DUPP_UNIQUE)))
1591
ha_rows handler::records() { return stats.records; }
1773
1594
Open database-handler.
1990
1811
start counting from the inserted value.
1992
1813
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
1814
with a value, session->next_insert_id is filled with the value to use for the
1994
1815
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
1816
session->insert_id_for_cur_row, if get_auto_increment() was called
1817
session->auto_inc_interval_for_cur_row is modified, if that interval is not
1818
present in session->auto_inc_intervals_in_cur_stmt_for_binlog it is added to
2471
2286
temporary= get_error_message(error, &str);
2472
2287
if (!str.is_empty())
2474
const char* engine= table_type();
2476
my_error(ER_GET_TEMPORARY_ERRMSG, MYF(0), error, str.ptr(), engine);
2478
my_error(ER_GET_ERRMSG, MYF(0), error, str.ptr(), engine);
2289
const char* engine_name= table_type();
2291
my_error(ER_GET_TEMPORARY_ERRMSG, MYF(0), error, str.ptr(),
2294
my_error(ER_GET_ERRMSG, MYF(0), error, str.ptr(), engine_name);
2481
my_error(ER_GET_ERRNO,errflag,error);
2298
my_error(ER_GET_ERRNO,errflag,error);
2545
static bool update_frm_version(Table *table)
2547
char path[FN_REFLEN];
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
2557
if (table->s->mysql_version == DRIZZLE_VERSION_ID)
2560
strxmov(path, table->s->normalized_path.str, reg_ext, NULL);
2562
if ((file= my_open(path, O_RDWR|O_BINARY, MYF(MY_WME))) >= 0)
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;
2568
HASH_SEARCH_STATE state;
2570
int4store(version, DRIZZLE_VERSION_ID);
2572
if (pwrite(file, (unsigned char*)version, 4, 51L) == 0)
2578
for (entry=(Table*) hash_first(&open_cache,(unsigned char*) key,key_length, &state);
2580
entry= (Table*) hash_next(&open_cache,(unsigned char*) key,key_length, &state))
2581
entry->s->mysql_version= DRIZZLE_VERSION_ID;
2585
my_close(file,MYF(MY_WME));
2593
2362
key if error because of duplicated keys
2595
2364
uint32_t handler::get_dup_key(int error)
2597
table->file->errkey = (uint) -1;
2366
table->file->errkey = (uint32_t) -1;
2598
2367
if (error == HA_ERR_FOUND_DUPP_KEY || error == HA_ERR_FOREIGN_DUPLICATE_KEY ||
2599
2368
error == HA_ERR_FOUND_DUPP_UNIQUE ||
2600
2369
error == HA_ERR_DROP_INDEX_FK)
3078
2842
char name_buff[FN_REFLEN];
3079
2843
const char *name;
3080
2844
TABLE_SHARE share;
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,
2846
init_tmp_table_share(session, &share, db, 0, table_name, path);
2847
if (open_table_def(session, &share, 0) ||
2848
open_table_from_share(session, &share, "", 0, (uint32_t) READ_ALL, 0, &table,
3102
2866
return(error != 0);
3106
Try to discover table from engine.
3109
If found, write the frm file to disk.
3112
-1 Table did not exists
3116
> 0 Error, table existed but could not be created
3118
int ha_create_table_from_engine(THD* thd, const char *db, const char *name)
3121
unsigned char *frmblob;
3123
char path[FN_REFLEN];
3124
HA_CREATE_INFO create_info;
3128
memset(&create_info, 0, sizeof(create_info));
3129
if ((error= ha_discover(thd, db, name, &frmblob, &frmlen)))
3131
/* Table could not be discovered and thus not created */
3136
Table exists in handler and could be discovered
3137
frmblob and frmlen are set, write the frm to disk
3140
build_table_filename(path, FN_REFLEN-1, db, name, "", 0);
3141
// Save the frm file
3142
error= writefrm(path, frmblob, frmlen);
3147
init_tmp_table_share(thd, &share, db, 0, name, path);
3148
if (open_table_def(thd, &share, 0))
3152
if (open_table_from_share(thd, &share, "" ,0, 0, 0, &table, OTM_OPEN))
3154
free_table_share(&share);
3158
table.updateCreateInfo(&create_info);
3159
create_info.table_options|= HA_OPTION_CREATE_FROM_ENGINE;
3161
check_lowercase_names(table.file, path, path);
3162
error=table.file->ha_create(path, &table, &create_info);
3163
closefrm(&table, 1);
3168
2869
void st_ha_check_opt::init()
3170
flags= sql_flags= 0;
3171
sort_buffer_size = current_thd->variables.myisam_sort_buff_size;
3266
Try to discover one table from handler(s).
3269
-1 Table did not exists
3271
0 OK. In this case *frmblob and *frmlen are set
3273
>0 error. frmblob and frmlen may not be set
3275
struct st_discover_args
3279
unsigned char **frmblob;
3283
static bool discover_handlerton(THD *thd, plugin_ref plugin,
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,
3297
int ha_discover(THD *thd, const char *db, const char *name,
3298
unsigned char **frmblob, size_t *frmlen)
3300
int error= -1; // Table does not exist in any handler
3301
st_discover_args args= {db, name, frmblob, frmlen};
3303
if (is_prefix(name,tmp_file_prefix)) /* skip temporary tables */
3306
if (plugin_foreach(thd, discover_handlerton,
3307
DRIZZLE_STORAGE_ENGINE_PLUGIN, &args))
3311
status_var_increment(thd->status_var.ha_discover_count);
3317
2966
Call this function in order to give the handler the possiblity
3318
2967
to ask engine if there are any new tables that should be written to disk
3339
struct st_table_exists_in_engine_args
2988
struct st_table_exists_in_storage_engine_args
3341
2990
const char *db;
3342
2991
const char *name;
2993
StorageEngine* engine;
3346
static bool table_exists_in_engine_handlerton(THD *thd, plugin_ref plugin,
2996
static bool table_exists_in_storage_engine(Session *session, plugin_ref plugin,
3349
st_table_exists_in_engine_args *vargs= (st_table_exists_in_engine_args *)arg;
3350
handlerton *hton= plugin_data(plugin, handlerton *);
2999
st_table_exists_in_storage_engine_args *vargs= (st_table_exists_in_storage_engine_args *)arg;
3000
StorageEngine *engine= plugin_data(plugin, StorageEngine *);
3352
3002
int err= HA_ERR_NO_SUCH_TABLE;
3354
if (hton->state == SHOW_OPTION_YES && hton->table_exists_in_engine)
3355
err = hton->table_exists_in_engine(hton, thd, vargs->db, vargs->name);
3004
if (engine->is_enabled())
3005
err = engine->table_exists_in_engine(session, vargs->db, vargs->name);
3357
3007
vargs->err = err;
3358
3008
if (vargs->err == HA_ERR_TABLE_EXIST)
3010
vargs->engine= engine;
3364
int ha_table_exists_in_engine(THD* thd, const char* db, const char* name)
3017
int ha_table_exists_in_engine(Session* session,
3018
const char* db, const char* name,
3019
StorageEngine **engine)
3366
st_table_exists_in_engine_args args= {db, name, HA_ERR_NO_SUCH_TABLE};
3367
plugin_foreach(thd, table_exists_in_engine_handlerton,
3021
st_table_exists_in_storage_engine_args args= {db, name, HA_ERR_NO_SUCH_TABLE, NULL};
3022
plugin_foreach(session, table_exists_in_storage_engine,
3368
3023
DRIZZLE_STORAGE_ENGINE_PLUGIN, &args);
3025
if(args.err==HA_ERR_NO_SUCH_TABLE)
3027
/* Default way of knowing if a table exists. (checking .frm exists) */
3029
char path[FN_REFLEN];
3030
build_table_filename(path, sizeof(path),
3032
if (table_proto_exists(path)==EEXIST)
3033
args.err= HA_ERR_TABLE_EXIST;
3035
args.err= HA_ERR_NO_SUCH_TABLE;
3037
if(args.err==HA_ERR_TABLE_EXIST)
3039
drizzle::Table table;
3040
build_table_filename(path, sizeof(path),
3041
db, name, ".dfe", 0);
3042
if(drizzle_read_table_proto(path, &table)==0)
3044
LEX_STRING engine_name= { (char*)table.engine().name().c_str(),
3045
strlen(table.engine().name().c_str()) };
3046
plugin_ref plugin= ha_resolve_by_name(session, &engine_name);
3048
args.engine= plugin_data(plugin,StorageEngine *);
3054
*engine= args.engine;
3369
3056
return(args.err);
3440
3125
handler::multi_range_read_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
3441
3126
void *seq_init_param,
3442
uint32_t n_ranges_arg __attribute__((unused)),
3443
3128
uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
3445
3130
KEY_MULTI_RANGE range;
3446
3131
range_seq_t seq_it;
3447
3132
ha_rows rows, total_rows= 0;
3448
3133
uint32_t n_ranges=0;
3449
THD *thd= current_thd;
3134
Session *session= current_session;
3451
3136
/* Default MRR implementation doesn't need buffer */
3454
3139
seq_it= seq->init(seq_init_param, n_ranges, *flags);
3455
3140
while (!seq->next(seq_it, &range))
3457
if (unlikely(thd->killed != 0))
3142
if (unlikely(session->killed != 0))
3458
3143
return HA_POS_ERROR;
3461
3146
key_range *min_endp, *max_endp;
3551
3236
Initialize the MRR scan
3553
Initialize the MRR scan. This function may do heavyweight scan
3238
Initialize the MRR scan. This function may do heavyweight scan
3554
3239
initialization like row prefetching/sorting/etc (NOTE: but better not do
3555
3240
it here as we may not need it, e.g. if we never satisfy WHERE clause on
3556
3241
previous tables. For many implementations it would be natural to do such
3557
3242
initializations in the first multi_read_range_next() call)
3559
3244
mode is a combination of the following flags: HA_MRR_SORTED,
3560
HA_MRR_INDEX_ONLY, HA_MRR_NO_ASSOCIATION
3245
HA_MRR_INDEX_ONLY, HA_MRR_NO_ASSOCIATION
3562
3247
@param seq Range sequence to be traversed
3563
3248
@param seq_init_param First parameter for seq->init()
3698
3383
uint32_t keyno;
3699
3384
Item *pushed_cond= NULL;
3700
3385
handler *new_h2;
3701
keyno= h->active_index;
3386
keyno= h_in->active_index;
3702
3387
assert(h2 == NULL);
3703
3388
if (mode & HA_MRR_USE_DEFAULT_IMPL || mode & HA_MRR_SORTED)
3705
3390
use_default_impl= true;
3706
return(h->handler::multi_range_read_init(seq_funcs, seq_init_param,
3391
return(h_in->handler::multi_range_read_init(seq_funcs, seq_init_param,
3707
3392
n_ranges, mode, buf));
3709
3394
rowids_buf= buf->buffer;
3710
3395
//psergey-todo: don't add key_length as it is not needed anymore
3711
rowids_buf += key->key_length + h->ref_length;
3396
rowids_buf += key->key_length + h_in->ref_length;
3713
3398
is_mrr_assoc= !test(mode & HA_MRR_NO_ASSOCIATION);
3714
3399
rowids_buf_end= buf->buffer_end;
3716
elem_size= h->ref_length + (int)is_mrr_assoc * sizeof(void*);
3717
rowids_buf_last= rowids_buf +
3401
elem_size= h_in->ref_length + (int)is_mrr_assoc * sizeof(void*);
3402
rowids_buf_last= rowids_buf +
3718
3403
((rowids_buf_end - rowids_buf)/ elem_size)*
3720
3405
rowids_buf_end= rowids_buf_last;
3722
3407
/* 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))
3408
Session *session= current_session;
3409
if (!(new_h2= h_in->clone(session->mem_root)) ||
3410
new_h2->ha_external_lock(session, F_RDLCK))
3731
if (keyno == h->pushed_idx_cond_keyno)
3732
pushed_cond= h->pushed_idx_cond;
3733
if (h->ha_index_end())
3416
if (keyno == h_in->pushed_idx_cond_keyno)
3417
pushed_cond= h_in->pushed_idx_cond;
3418
if (h_in->ha_index_end())
4016
3701
COST_VECT dsmrr_cost;
4018
THD *thd= current_thd;
4019
if ((thd->variables.optimizer_use_mrr == 2) ||
3703
Session *session= current_session;
3704
if ((session->variables.optimizer_use_mrr == 2) ||
4020
3705
(*flags & HA_MRR_INDEX_ONLY) || (*flags & HA_MRR_SORTED) ||
4021
(keyno == table->s->primary_key &&
4022
h->primary_key_is_clustered()) ||
3706
(keyno == table->s->primary_key &&
3707
h->primary_key_is_clustered()) ||
4023
3708
key_uses_partial_cols(keyno))
4025
3710
/* Use the default implementation */
4026
3711
*flags |= HA_MRR_USE_DEFAULT_IMPL;
4030
uint32_t add_len= table->key_info[keyno].key_length + h->ref_length;
3715
uint32_t add_len= table->key_info[keyno].key_length + h->ref_length;
4031
3716
*bufsz -= add_len;
4032
3717
if (get_disk_sweep_mrr_cost(keyno, rows, *flags, bufsz, &dsmrr_cost))
4034
3719
*bufsz += add_len;
4036
3721
bool force_dsmrr;
4038
3723
If @@optimizer_use_mrr==force, then set cost of DS-MRR to be minimum of
4039
3724
DS-MRR and Default implementations cost. This allows one to force use of
4040
3725
DS-MRR whenever it is applicable without affecting other cost-based
4043
if ((force_dsmrr= (thd->variables.optimizer_use_mrr == 1)) &&
3728
if ((force_dsmrr= (session->variables.optimizer_use_mrr == 1)) &&
4044
3729
dsmrr_cost.total_cost() > cost->total_cost())
4045
3730
dsmrr_cost= *cost;
4092
3777
return true; /* Buffer has not enough space for even 1 rowid */
4094
3779
/* Number of iterations we'll make with full buffer */
4095
n_full_steps= (uint)floor(rows2double(rows) / max_buff_entries);
4098
Get numbers of rows we'll be processing in
4099
- non-last sweep, with full buffer
3780
n_full_steps= (uint32_t)floor(rows2double(rows) / max_buff_entries);
3783
Get numbers of rows we'll be processing in
3784
- non-last sweep, with full buffer
4100
3785
- last iteration, with non-full buffer
4102
3787
rows_in_full_step= max_buff_entries;
4103
3788
rows_in_last_step= rows % max_buff_entries;
4105
3790
/* Adjust buffer size if we expect to use only part of the buffer */
4106
3791
if (n_full_steps)
4114
*buffer_size= cmax((ulong)*buffer_size,
4115
(size_t)(1.2*rows_in_last_step) * elem_size +
3799
*buffer_size= cmax((ulong)*buffer_size,
3800
(size_t)(1.2*rows_in_last_step) * elem_size +
4116
3801
h->ref_length + table->key_info[keynr].key_length);
4119
3804
COST_VECT last_step_cost;
4120
3805
get_sort_and_sweep_cost(table, rows_in_last_step, &last_step_cost);
4121
3806
cost->add(&last_step_cost);
4123
3808
if (n_full_steps != 0)
4124
3809
cost->mem_cost= *buffer_size;
4126
3811
cost->mem_cost= (double)rows_in_last_step * elem_size;
4128
3813
/* Total cost of all index accesses */
4129
3814
index_read_cost= h->index_only_read_time(keynr, (double)rows);
4130
3815
cost->add_io(index_read_cost, 1 /* Random seeks */);
4394
4080
pointer pointer to TYPELIB structure
4396
static bool exts_handlerton(THD *unused __attribute__((unused)),
4082
static bool exts_handlerton(Session *,
4397
4083
plugin_ref plugin,
4400
4086
List<char> *found_exts= (List<char> *) arg;
4401
handlerton *hton= plugin_data(plugin, handlerton *);
4087
StorageEngine *engine= plugin_data(plugin, StorageEngine *);
4403
if (hton->state == SHOW_OPTION_YES && hton->create &&
4404
(file= hton->create(hton, (TABLE_SHARE*) 0, current_thd->mem_root)))
4089
if (engine->is_enabled() &&
4090
(file= engine->create((TABLE_SHARE*) 0, current_session->mem_root)))
4406
4092
List_iterator_fast<char> it(*found_exts);
4407
4093
const char **ext, *old_ext;
4455
static bool stat_print(THD *thd, const char *type, uint32_t type_len,
4141
static bool stat_print(Session *session, const char *type, uint32_t type_len,
4456
4142
const char *file, uint32_t file_len,
4457
4143
const char *status, uint32_t status_len)
4459
Protocol *protocol= thd->protocol;
4145
Protocol *protocol= session->protocol;
4460
4146
protocol->prepare_for_resend();
4461
4147
protocol->store(type, type_len, system_charset_info);
4462
4148
protocol->store(file, file_len, system_charset_info);
4501
4186
- table is not mysql.event
4504
static bool check_table_binlog_row_based(THD *thd, Table *table)
4506
if (table->s->cached_row_logging_check == -1)
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;
4513
assert(table->s->cached_row_logging_check == 0 ||
4514
table->s->cached_row_logging_check == 1);
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());
4524
Write table maps for all (manually or automatically) locked tables
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.
4532
@param thd Pointer to THD structure
4535
@retval 1 Failed to write all table maps
4542
static int write_locked_table_maps(THD *thd)
4544
if (thd->get_binlog_table_maps() == 0)
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 )
4552
DRIZZLE_LOCK const *const lock= locks[i];
4556
Table **const end_ptr= lock->table + lock->table_count;
4557
for (Table **table_ptr= lock->table ;
4558
table_ptr != end_ptr ;
4561
Table *const table= *table_ptr;
4562
if (table->current_lock == F_WRLCK &&
4563
check_table_binlog_row_based(thd, table))
4565
int const has_trans= table->file->has_transactions();
4566
int const error= thd->binlog_write_table_map(table, has_trans);
4568
If an error occurs, it is the responsibility of the caller to
4569
roll back the transaction.
4571
if (unlikely(error))
4581
typedef bool Log_func(THD*, Table*, bool, const unsigned char*, const unsigned char*);
4583
static int binlog_log_row(Table* table,
4584
const unsigned char *before_record,
4585
const unsigned char *after_record,
4588
if (table->no_replicate)
4591
THD *const thd= table->in_use;
4593
if (check_table_binlog_row_based(thd, table))
4189
static bool binlog_log_row(Table* table,
4190
const unsigned char *before_record,
4191
const unsigned char *after_record)
4194
Session *const session= table->in_use;
4196
if (table->no_replicate == false)
4199
error= replicator_session_init(session);
4201
switch (session->lex->sql_command)
4203
case SQLCOM_REPLACE:
4205
case SQLCOM_REPLACE_SELECT:
4206
case SQLCOM_INSERT_SELECT:
4207
case SQLCOM_CREATE_TABLE:
4208
error= replicator_write_row(session, table);
4212
case SQLCOM_UPDATE_MULTI:
4213
error= replicator_update_row(session, table, before_record, after_record);
4217
case SQLCOM_DELETE_MULTI:
4218
error= replicator_delete_row(session, table);
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.
4222
For everything else we ignore the event (since it just involves a temp table)
4600
if (likely(!(error= write_locked_table_maps(thd))))
4602
bool const has_trans= table->file->has_transactions();
4603
error= (*log_func)(thd, table, has_trans, before_record, after_record);
4606
return error ? HA_ERR_RBR_LOGGING_FAILED : 0;
4609
int handler::ha_external_lock(THD *thd, int lock_type)
4231
int handler::ha_external_lock(Session *session, int lock_type)
4612
4234
Whether this is lock or unlock, this should be true, and is to verify that
4652
4274
int handler::ha_write_row(unsigned char *buf)
4655
Log_func *log_func= Write_rows_log_event::binlog_row_logging_function;
4656
4277
DRIZZLE_INSERT_ROW_START();
4280
* If we have a timestamp column, update it to the current time
4282
* @TODO Technically, the below two lines can be take even further out of the
4283
* handler interface and into the fill_record() method.
4285
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
4286
table->timestamp_field->set_time();
4658
4288
mark_trx_read_write();
4660
4290
if (unlikely(error= write_row(buf)))
4662
if (unlikely(error= binlog_log_row(table, 0, buf, log_func)))
4663
return(error); /* purecov: inspected */
4293
if (unlikely(binlog_log_row(table, 0, buf)))
4294
return HA_ERR_RBR_LOGGING_FAILED; /* purecov: inspected */
4664
4296
DRIZZLE_INSERT_ROW_END();
4682
4313
if (unlikely(error= update_row(old_data, new_data)))
4684
if (unlikely(error= binlog_log_row(table, old_data, new_data, log_func)))
4316
if (unlikely(binlog_log_row(table, old_data, new_data)))
4317
return HA_ERR_RBR_LOGGING_FAILED;
4689
4322
int handler::ha_delete_row(const unsigned char *buf)
4692
Log_func *log_func= Delete_rows_log_event::binlog_row_logging_function;
4694
4326
mark_trx_read_write();
4696
4328
if (unlikely(error= delete_row(buf)))
4698
if (unlikely(error= binlog_log_row(table, buf, 0, log_func)))
4331
if (unlikely(binlog_log_row(table, buf, 0)))
4332
return HA_ERR_RBR_LOGGING_FAILED;