summaryrefslogtreecommitdiff
path: root/sql/handler.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/handler.cc')
-rw-r--r--sql/handler.cc155
1 files changed, 105 insertions, 50 deletions
diff --git a/sql/handler.cc b/sql/handler.cc
index 5968a78b587..612eda84a10 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -1,4 +1,5 @@
-/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2011, Oracle and/or its affiliates.
+ Copyright (c) 2009-2011 Monty Program Ab
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -26,7 +27,7 @@
#include "mysql_priv.h"
#include "rpl_filter.h"
#include <myisampack.h>
-#include <errno.h>
+#include "myisam.h"
#ifdef WITH_PARTITION_STORAGE_ENGINE
#include "ha_partition.h"
@@ -58,12 +59,13 @@ static const LEX_STRING sys_table_aliases[]=
{ C_STRING_WITH_LEN("NDB") }, { C_STRING_WITH_LEN("NDBCLUSTER") },
{ C_STRING_WITH_LEN("HEAP") }, { C_STRING_WITH_LEN("MEMORY") },
{ C_STRING_WITH_LEN("MERGE") }, { C_STRING_WITH_LEN("MRG_MYISAM") },
+ { C_STRING_WITH_LEN("Aria") }, { C_STRING_WITH_LEN("Maria") },
{NullS, 0}
};
const char *ha_row_type[] = {
"", "FIXED", "DYNAMIC", "COMPRESSED", "REDUNDANT", "COMPACT",
- /* Reserved to be "PAGE" in future versions */ "?",
+ "PAGE",
"?","?","?"
};
@@ -82,7 +84,7 @@ static plugin_ref ha_default_plugin(THD *thd)
{
if (thd->variables.table_plugin)
return thd->variables.table_plugin;
- return my_plugin_lock(thd, &global_system_variables.table_plugin);
+ return my_plugin_lock(thd, global_system_variables.table_plugin);
}
@@ -163,13 +165,8 @@ plugin_ref ha_lock_engine(THD *thd, const handlerton *hton)
{
if (hton)
{
- st_plugin_int **plugin= hton2plugin + hton->slot;
-
-#ifdef DBUG_OFF
- return my_plugin_lock(thd, plugin);
-#else
- return my_plugin_lock(thd, &plugin);
-#endif
+ st_plugin_int *plugin= hton2plugin[hton->slot];
+ return my_plugin_lock(thd, plugin_int_to_ref(plugin));
}
return NULL;
}
@@ -380,8 +377,7 @@ int ha_finalize_handlerton(st_plugin_int *plugin)
if (!hton)
goto end;
- switch (hton->state)
- {
+ switch (hton->state) {
case SHOW_OPTION_NO:
case SHOW_OPTION_DISABLED:
break;
@@ -435,8 +431,8 @@ int ha_initialize_handlerton(st_plugin_int *plugin)
if (plugin->plugin->init && plugin->plugin->init(hton))
{
sql_print_error("Plugin '%s' init function returned error.",
- plugin->name.str);
- goto err;
+ plugin->name.str);
+ goto err;
}
/*
@@ -463,13 +459,19 @@ int ha_initialize_handlerton(st_plugin_int *plugin)
if (idx == (int) DB_TYPE_DEFAULT)
{
sql_print_warning("Too many storage engines!");
- goto err_deinit;
+ my_free(hton, MYF(0));
+ plugin->data= 0;
+ goto err_deinit;
}
if (hton->db_type != DB_TYPE_UNKNOWN)
sql_print_warning("Storage engine '%s' has conflicting typecode. "
"Assigning value %d.", plugin->plugin->name, idx);
hton->db_type= (enum legacy_db_type) idx;
}
+ installed_htons[hton->db_type]= hton;
+ tmp= hton->savepoint_offset;
+ hton->savepoint_offset= savepoint_alloc_size;
+ savepoint_alloc_size+= tmp;
/*
In case a plugin is uninstalled and re-installed later, it should
@@ -1092,6 +1094,12 @@ int ha_commit_trans(THD *thd, bool all)
my_xid xid= thd->transaction.xid_state.xid.get_my_xid();
DBUG_ENTER("ha_commit_trans");
+ /* Just a random warning to test warnings pushed during autocommit. */
+ DBUG_EXECUTE_IF("warn_during_ha_commit_trans",
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARNING_NOT_COMPLETE_ROLLBACK,
+ ER(ER_WARNING_NOT_COMPLETE_ROLLBACK)););
+
/*
We must not commit the normal transaction if a statement
transaction is pending. Otherwise statement transaction
@@ -1520,7 +1528,7 @@ static my_bool xarecover_handlerton(THD *unused, plugin_ref plugin,
while ((got= hton->recover(hton, info->list, info->len)) > 0 )
{
sql_print_information("Found %d prepared transaction(s) in %s",
- got, ha_resolve_storage_engine_name(hton));
+ got, hton_name(hton)->str);
for (int i=0; i < got; i ++)
{
my_xid x=info->list[i].get_my_xid();
@@ -1587,16 +1595,6 @@ int ha_recover(HASH *commit_list)
if (info.commit_list)
sql_print_information("Starting crash recovery...");
-#ifndef WILL_BE_DELETED_LATER
- /*
- for now, only InnoDB supports 2pc. It means we can always safely
- rollback all pending transactions, without risking inconsistent data
- */
- DBUG_ASSERT(total_ha_2pc == (ulong) opt_bin_log+1); // only InnoDB and binlog
- tc_heuristic_recover= TC_HEURISTIC_RECOVER_ROLLBACK; // forcing ROLLBACK
- info.dry_run=FALSE;
-#endif
-
for (info.len= MAX_XID_LIST_SIZE ;
info.list==0 && info.len > MIN_XID_LIST_SIZE; info.len/=2)
{
@@ -2040,6 +2038,10 @@ int ha_delete_table(THD *thd, handlerton *table_type, const char *path,
handler *handler::clone(MEM_ROOT *mem_root)
{
handler *new_handler= get_new_handler(table->s, mem_root, table->s->db_type());
+
+ if (!new_handler)
+ return NULL;
+
/*
Allocate handler->ref here because otherwise ha_open will allocate it
on this->table->mem_root and we will not be able to reclaim that memory
@@ -2047,15 +2049,30 @@ handler *handler::clone(MEM_ROOT *mem_root)
*/
if (!(new_handler->ref= (uchar*) alloc_root(mem_root, ALIGN_SIZE(ref_length)*2)))
return NULL;
- if (new_handler && !new_handler->ha_open(table,
- table->s->normalized_path.str,
- table->db_stat,
- HA_OPEN_IGNORE_IF_LOCKED))
- return new_handler;
- return NULL;
+ if (new_handler->ha_open(table,
+ table->s->normalized_path.str,
+ table->db_stat,
+ HA_OPEN_IGNORE_IF_LOCKED))
+ return NULL;
+ new_handler->cloned= 1; // Marker for debugging
+ return new_handler;
}
-
+double handler::keyread_time(uint index, uint ranges, ha_rows rows)
+{
+ /*
+ It is assumed that we will read trough the whole key range and that all
+ key blocks are half full (normally things are much better). It is also
+ assumed that each time we read the next key from the index, the handler
+ performs a random seek, thus the cost is proportional to the number of
+ blocks read. This model does not take into account clustered indexes -
+ engines that support that (e.g. InnoDB) may want to overwrite this method.
+ */
+ double keys_per_block= (stats.block_size/2.0/
+ (table->key_info[index].key_length +
+ ref_length) + 1);
+ return (rows + keys_per_block - 1)/ keys_per_block;
+}
void handler::ha_statistic_increment(ulong SSV::*offset) const
{
@@ -2158,8 +2175,8 @@ int handler::read_first_row(uchar * buf, uint primary_key)
else
{
/* Find the first row through the primary key */
- (void) ha_index_init(primary_key, 0);
- error=index_first(buf);
+ if (!(error = ha_index_init(primary_key, 0)))
+ error= index_first(buf);
(void) ha_index_end();
}
DBUG_RETURN(error);
@@ -2346,7 +2363,7 @@ int handler::update_auto_increment()
if ((nr= table->next_number_field->val_int()) != 0 ||
(table->auto_increment_field_not_null &&
- thd->variables.sql_mode & MODE_NO_AUTO_VALUE_ON_ZERO))
+ thd->variables.sql_mode & MODE_NO_AUTO_VALUE_ON_ZERO))
{
/*
Update next_insert_id if we had already generated a value in this
@@ -2544,7 +2561,7 @@ void handler::get_auto_increment(ulonglong offset, ulonglong increment,
table->mark_columns_used_by_index_no_reset(table->s->next_number_index,
table->read_set);
column_bitmaps_signal();
- index_init(table->s->next_number_index, 1);
+ ha_index_init(table->s->next_number_index, 1);
if (table->s->next_number_keypart == 0)
{ // Autoincrement at key-start
error=index_last(table->record[1]);
@@ -2578,7 +2595,7 @@ void handler::get_auto_increment(ulonglong offset, ulonglong increment,
else
nr= ((ulonglong) table->next_number_field->
val_int_offset(table->s->rec_buff_length)+1);
- index_end();
+ ha_index_end();
(void) extra(HA_EXTRA_NO_KEYREAD);
*first_value= nr;
}
@@ -2639,8 +2656,12 @@ void handler::print_keydup_error(uint key_nr, const char *msg)
- table->s->path
- table->alias
*/
+
+#define SET_FATAL_ERROR fatal_error=1
+
void handler::print_error(int error, myf errflag)
{
+ bool fatal_error= 0;
DBUG_ENTER("handler::print_error");
DBUG_PRINT("enter",("error: %d",error));
@@ -2658,6 +2679,13 @@ void handler::print_error(int error, myf errflag)
case HA_ERR_KEY_NOT_FOUND:
case HA_ERR_NO_ACTIVE_RECORD:
case HA_ERR_END_OF_FILE:
+ /*
+ This errors is not not normally fatal (for example for reads). However
+ if you get it during an update or delete, then its fatal.
+ As the user is calling print_error() (which is not done on read), we
+ assume something when wrong with the update or delete.
+ */
+ SET_FATAL_ERROR;
textno=ER_KEY_NOT_FOUND;
break;
case HA_ERR_WRONG_MRG_TABLE_DEF:
@@ -2665,11 +2693,14 @@ void handler::print_error(int error, myf errflag)
break;
case HA_ERR_FOUND_DUPP_KEY:
{
- uint key_nr=get_dup_key(error);
- if ((int) key_nr >= 0)
+ if (table)
{
- print_keydup_error(key_nr, ER(ER_DUP_ENTRY_WITH_KEY_NAME));
- DBUG_VOID_RETURN;
+ uint key_nr=get_dup_key(error);
+ if ((int) key_nr >= 0)
+ {
+ print_keydup_error(key_nr, ER(ER_DUP_ENTRY_WITH_KEY_NAME));
+ DBUG_VOID_RETURN;
+ }
}
textno=ER_DUP_KEY;
break;
@@ -2706,21 +2737,29 @@ void handler::print_error(int error, myf errflag)
textno=ER_DUP_UNIQUE;
break;
case HA_ERR_RECORD_CHANGED:
+ /*
+ This is not fatal error when using HANDLER interface
+ SET_FATAL_ERROR;
+ */
textno=ER_CHECKREAD;
break;
case HA_ERR_CRASHED:
+ SET_FATAL_ERROR;
textno=ER_NOT_KEYFILE;
break;
case HA_ERR_WRONG_IN_RECORD:
+ SET_FATAL_ERROR;
textno= ER_CRASHED_ON_USAGE;
break;
case HA_ERR_CRASHED_ON_USAGE:
+ SET_FATAL_ERROR;
textno=ER_CRASHED_ON_USAGE;
break;
case HA_ERR_NOT_A_TABLE:
textno= error;
break;
case HA_ERR_CRASHED_ON_REPAIR:
+ SET_FATAL_ERROR;
textno=ER_CRASHED_ON_REPAIR;
break;
case HA_ERR_OUT_OF_MEM:
@@ -2819,14 +2858,27 @@ void handler::print_error(int error, myf errflag)
if (temporary)
my_error(ER_GET_TEMPORARY_ERRMSG, MYF(0), error, str.ptr(), engine);
else
+ {
+ SET_FATAL_ERROR;
my_error(ER_GET_ERRMSG, MYF(0), error, str.ptr(), engine);
+ }
}
else
my_error(ER_GET_ERRNO,errflag,error);
DBUG_VOID_RETURN;
}
}
+ if (fatal_error && (debug_assert_if_crashed_table ||
+ global_system_variables.log_warnings > 1))
+ {
+ /*
+ Log error to log before we crash or if extended warnings are requested
+ */
+ errflag|= ME_NOREFRESH;
+ }
+
my_error(textno, errflag, table_share->table_name.str, error);
+ DBUG_ASSERT(!fatal_error || !debug_assert_if_crashed_table);
DBUG_VOID_RETURN;
}
@@ -3584,7 +3636,7 @@ void handler::get_dynamic_partition_info(PARTITION_INFO *stat_info,
stat_info->update_time= stats.update_time;
stat_info->check_time= stats.check_time;
stat_info->check_sum= 0;
- if (table_flags() & (ulong) HA_HAS_CHECKSUM)
+ if (table_flags() & (HA_HAS_OLD_CHECKSUM | HA_HAS_OLD_CHECKSUM))
stat_info->check_sum= checksum();
return;
}
@@ -3705,7 +3757,7 @@ int ha_create_table_from_engine(THD* thd, const char *db, const char *name)
void st_ha_check_opt::init()
{
flags= sql_flags= 0;
- sort_buffer_size = current_thd->variables.myisam_sort_buff_size;
+ start_time= my_time(0);
}
@@ -3891,7 +3943,8 @@ ha_find_files(THD *thd,const char *db,const char *path,
int error= 0;
DBUG_ENTER("ha_find_files");
DBUG_PRINT("enter", ("db: '%s' path: '%s' wild: '%s' dir: %d",
- db, path, wild ? wild : "NULL", dir));
+ val_or_null(db), val_or_null(path),
+ val_or_null(wild), dir));
st_find_files_args args= {db, path, wild, dir, files};
plugin_foreach(thd, find_files_handlerton,
@@ -4159,7 +4212,7 @@ int handler::read_multi_range_first(KEY_MULTI_RANGE **found_range_p,
*/
int handler::read_multi_range_next(KEY_MULTI_RANGE **found_range_p)
{
- int UNINIT_VAR(result);
+ int result= 0;
DBUG_ENTER("handler::read_multi_range_next");
/* We should not be called after the last call returned EOF. */
@@ -4328,11 +4381,13 @@ int handler::index_read_idx_map(uchar * buf, uint index, const uchar * key,
enum ha_rkey_function find_flag)
{
int error, error1;
- error= index_init(index, 0);
+ LINT_INIT(error1);
+
+ error= ha_index_init(index, 0);
if (!error)
{
error= index_read_map(buf, key, keypart_map, find_flag);
- error1= index_end();
+ error1= ha_index_end();
}
return error ? error : error1;
}
@@ -4457,7 +4512,7 @@ bool ha_show_status(THD *thd, handlerton *db_type, enum ha_stat_type stat)
{
if (db_type->state != SHOW_OPTION_YES)
{
- const LEX_STRING *name=&hton2plugin[db_type->slot]->name;
+ const LEX_STRING *name= hton_name(db_type);
result= stat_print(thd, name->str, name->length,
"", 0, "DISABLED", 8) ? 1 : 0;
}