summaryrefslogtreecommitdiff
path: root/sql/handler.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/handler.cc')
-rw-r--r--sql/handler.cc201
1 files changed, 71 insertions, 130 deletions
diff --git a/sql/handler.cc b/sql/handler.cc
index 098c3130de2..3e951efff48 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -25,7 +25,7 @@
#include "ha_heap.h"
#include "ha_myisam.h"
#include "ha_myisammrg.h"
-#ifndef NO_ISAM
+#ifdef HAVE_ISAM
#include "ha_isam.h"
#include "ha_isammrg.h"
#endif
@@ -33,10 +33,7 @@
#include "ha_berkeley.h"
#endif
#ifdef HAVE_INNOBASE_DB
-#include "ha_innobase.h"
-#endif
-#ifdef HAVE_GEMINI_DB
-#include "ha_gemini.h"
+#include "ha_innodb.h"
#endif
#include <myisampack.h>
#include <errno.h>
@@ -48,6 +45,7 @@ static int NEAR_F delete_file(const char *name,const char *ext,int extflag);
ulong ha_read_count, ha_write_count, ha_delete_count, ha_update_count,
ha_read_key_count, ha_read_next_count, ha_read_prev_count,
ha_read_first_count, ha_read_last_count,
+ ha_commit_count, ha_rollback_count,
ha_read_rnd_count, ha_read_rnd_next_count;
const char *ha_table_type[] = {
@@ -78,21 +76,15 @@ enum db_type ha_checktype(enum db_type database_type)
return(berkeley_skip ? DB_TYPE_MYISAM : database_type);
#endif
#ifdef HAVE_INNOBASE_DB
- case DB_TYPE_INNOBASE:
+ case DB_TYPE_INNODB:
return(innodb_skip ? DB_TYPE_MYISAM : database_type);
#endif
-#ifdef HAVE_GEMINI_DB
- case DB_TYPE_GEMINI:
- return(gemini_skip ? DB_TYPE_MYISAM : database_type);
-#endif
#ifndef NO_HASH
case DB_TYPE_HASH:
#endif
-#ifndef NO_MERGE
- case DB_TYPE_MRG_ISAM:
-#endif
-#ifndef NO_ISAM
+#ifdef HAVE_ISAM
case DB_TYPE_ISAM:
+ case DB_TYPE_MRG_ISAM:
#endif
case DB_TYPE_HEAP:
case DB_TYPE_MYISAM:
@@ -111,11 +103,9 @@ handler *get_new_handler(TABLE *table, enum db_type db_type)
#ifndef NO_HASH
return new ha_hash(table);
#endif
-#ifndef NO_MERGE
+#ifdef HAVE_ISAM
case DB_TYPE_MRG_ISAM:
return new ha_isammrg(table);
-#endif
-#ifndef NO_ISAM
case DB_TYPE_ISAM:
return new ha_isam(table);
#endif
@@ -124,13 +114,9 @@ handler *get_new_handler(TABLE *table, enum db_type db_type)
return new ha_berkeley(table);
#endif
#ifdef HAVE_INNOBASE_DB
- case DB_TYPE_INNOBASE:
+ case DB_TYPE_INNODB:
return new ha_innobase(table);
#endif
-#ifdef HAVE_GEMINI_DB
- case DB_TYPE_GEMINI:
- return new ha_gemini(table);
-#endif
case DB_TYPE_HEAP:
return new ha_heap(table);
case DB_TYPE_MYISAM:
@@ -166,17 +152,6 @@ int ha_init()
have_innodb=SHOW_OPTION_DISABLED;
}
#endif
-#ifdef HAVE_GEMINI_DB
- if (!gemini_skip)
- {
- if (gemini_init())
- return -1;
- if (!gemini_skip) // If we couldn't use handler
- opt_using_transactions=1;
- else
- have_gemini=SHOW_OPTION_DISABLED;
- }
-#endif
return 0;
}
@@ -186,14 +161,14 @@ int ha_init()
int ha_panic(enum ha_panic_function flag)
{
int error=0;
-#ifndef NO_MERGE
- error|=mrg_panic(flag);
-#endif
#ifndef NO_HASH
error|=h_panic(flag); /* fix hash */
#endif
- error|=heap_panic(flag);
+#ifdef HAVE_ISAM
+ error|=mrg_panic(flag);
error|=nisam_panic(flag);
+#endif
+ error|=heap_panic(flag);
error|=mi_panic(flag);
error|=myrg_panic(flag);
#ifdef HAVE_BERKELEY_DB
@@ -204,10 +179,6 @@ int ha_panic(enum ha_panic_function flag)
if (!innodb_skip)
error|=innobase_end();
#endif
-#ifdef HAVE_GEMINI_DB
- if (!gemini_skip)
- error|=gemini_end();
-#endif
return error;
} /* ha_panic */
@@ -225,12 +196,6 @@ void ha_close_connection(THD* thd)
if (!innodb_skip)
innobase_close_connection(thd);
#endif
-#ifdef HAVE_GEMINI_DB
- if (!gemini_skip && thd->gemini.context)
- {
- gemini_disconnect(thd);
- }
-#endif /* HAVE_GEMINI_DB */
}
/*
@@ -305,6 +270,7 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans)
#ifdef USING_TRANSACTIONS
if (opt_using_transactions)
{
+ bool operation_done=0;
/* Update the binary log if we have cached some queries */
if (trans == &thd->transaction.all && mysql_bin_log.is_open() &&
my_b_tell(&thd->transaction.trans_log))
@@ -334,25 +300,18 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans)
error=1;
}
trans->innodb_active_trans=0;
- }
-#endif
-#ifdef HAVE_GEMINI_DB
- /* Commit the transaction in behalf of the commit statement
- or if we're in auto-commit mode */
- if((trans == &thd->transaction.all) ||
- (!(thd->options & (OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN))))
- {
- error=gemini_commit(thd);
- if (error)
+ if (trans == &thd->transaction.all)
{
- my_error(ER_ERROR_DURING_COMMIT, MYF(0), error);
- error=1;
+ query_cache.invalidate(Query_cache_table::INNODB);
+ operation_done=1;
}
}
#endif
if (error && trans == &thd->transaction.all && mysql_bin_log.is_open())
sql_print_error("Error: Got error during commit; Binlog is not up to date!");
thd->tx_isolation=thd->session_tx_isolation;
+ if (operation_done)
+ statistic_increment(ha_commit_count,&LOCK_status);
}
#endif // using transactions
DBUG_RETURN(error);
@@ -366,6 +325,7 @@ int ha_rollback_trans(THD *thd, THD_TRANS *trans)
#ifdef USING_TRANSACTIONS
if (opt_using_transactions)
{
+ bool operation_done=0;
#ifdef HAVE_BERKELEY_DB
if (trans->bdb_tid)
{
@@ -375,6 +335,7 @@ int ha_rollback_trans(THD *thd, THD_TRANS *trans)
error=1;
}
trans->bdb_tid=0;
+ operation_done=1;
}
#endif
#ifdef HAVE_INNOBASE_DB
@@ -386,18 +347,7 @@ int ha_rollback_trans(THD *thd, THD_TRANS *trans)
error=1;
}
trans->innodb_active_trans=0;
- }
-#endif
-#ifdef HAVE_GEMINI_DB
- if((trans == &thd->transaction.stmt) &&
- (thd->options & (OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN)))
- error = gemini_rollback_to_savepoint(thd);
- else
- error=gemini_rollback(thd);
- if (error)
- {
- my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), error);
- error=1;
+ operation_done=1;
}
#endif
if (trans == &thd->transaction.all)
@@ -405,22 +355,13 @@ int ha_rollback_trans(THD *thd, THD_TRANS *trans)
WRITE_CACHE, (my_off_t) 0, 0, 1);
thd->transaction.trans_log.end_of_file= max_binlog_cache_size;
thd->tx_isolation=thd->session_tx_isolation;
+ if (operation_done)
+ statistic_increment(ha_rollback_count,&LOCK_status);
}
#endif /* USING_TRANSACTIONS */
DBUG_RETURN(error);
}
-void ha_set_spin_retries(uint retries)
-{
-#ifdef HAVE_GEMINI_DB
- if (!gemini_skip)
- {
- gemini_set_option_long(GEM_OPTID_SPIN_RETRIES, retries);
- }
-#endif /* HAVE_GEMINI_DB */
-}
-
-
bool ha_flush_logs()
{
bool result=0;
@@ -449,7 +390,7 @@ int ha_delete_table(enum db_type table_type, const char *path)
delete file;
return error;
}
-
+
void ha_store_ptr(byte *buff, uint pack_length, my_off_t pos)
{
switch (pack_length) {
@@ -536,9 +477,8 @@ int handler::ha_open(const char *name, int mode, int test_if_locked)
{
if (table->db_options_in_use & HA_OPTION_READ_ONLY_DATA)
table->db_stat|=HA_READ_ONLY;
- }
- if (!error)
- {
+ (void) extra(HA_EXTRA_NO_READCHECK); // Not needed in SQL
+
if (!alloc_root_inited(&table->mem_root)) // If temporary table
ref=(byte*) sql_alloc(ALIGN_SIZE(ref_length)*2);
else
@@ -584,17 +524,37 @@ int handler::analyze(THD* thd, HA_CHECK_OPT* check_opt)
return HA_ADMIN_NOT_IMPLEMENTED;
}
- /* Read first row from a table */
+/*
+ Read first row (only) from a table
+ This is never called for InnoDB or BDB tables, as these table types
+ has the HA_NOT_EXACT_COUNT set.
+*/
-int handler::rnd_first(byte * buf)
+int handler::read_first_row(byte * buf, uint primary_key)
{
register int error;
- DBUG_ENTER("handler::rnd_first");
+ DBUG_ENTER("handler::read_first_row");
statistic_increment(ha_read_first_count,&LOCK_status);
- (void) rnd_init();
- while ((error= rnd_next(buf)) == HA_ERR_RECORD_DELETED) ;
- (void) rnd_end();
+
+ /*
+ If there is very few deleted rows in the table, find the first row by
+ scanning the table.
+ */
+ if (deleted < 10 || primary_key >= MAX_KEY ||
+ !(option_flag() & HA_READ_ORDER))
+ {
+ (void) rnd_init();
+ while ((error= rnd_next(buf)) == HA_ERR_RECORD_DELETED) ;
+ (void) rnd_end();
+ }
+ else
+ {
+ /* Find the first row through the primary key */
+ (void) index_init(primary_key);
+ error=index_first(buf);
+ (void) index_end();
+ }
DBUG_RETURN(error);
}
@@ -610,7 +570,7 @@ int handler::restart_rnd_next(byte *buf, byte *pos)
}
- /* Set a timestamp in record */
+/* Set a timestamp in record */
void handler::update_timestamp(byte *record)
{
@@ -626,9 +586,10 @@ void handler::update_timestamp(byte *record)
return;
}
- /* Updates field with field_type NEXT_NUMBER according to following:
- ** if field = 0 change field to the next free key in database.
- */
+/*
+ Updates field with field_type NEXT_NUMBER according to following:
+ if field = 0 change field to the next free key in database.
+*/
void handler::update_auto_increment()
{
@@ -811,22 +772,6 @@ int handler::rename_table(const char * from, const char * to)
DBUG_RETURN(0);
}
-int ha_commit_rename(THD *thd)
-{
- int error=0;
-#ifdef HAVE_GEMINI_DB
- /* Gemini needs to commit the rename; otherwise a rollback will change
- ** the table names back internally but the physical files will still
- ** have the new names.
- */
- if (ha_commit_stmt(thd))
- error= -1;
- if (ha_commit(thd))
- error= -1;
-#endif
- return error;
-}
-
/* Tell the handler to turn on or off logging to the handler's
recovery log
*/
@@ -835,14 +780,6 @@ int ha_recovery_logging(THD *thd, bool on)
int error=0;
DBUG_ENTER("ha_recovery_logging");
-#ifdef USING_TRANSACTIONS
- if (opt_using_transactions)
- {
-#ifdef HAVE_GEMINI_DB
- error = gemini_recovery_logging(thd, on);
-#endif
- }
-#endif
DBUG_RETURN(error);
}
@@ -862,8 +799,10 @@ int handler::index_next_same(byte *buf, const byte *key, uint keylen)
/*
- The following is only needed if we would like to use the database
- for internal temporary tables
+ This is called to delete all rows in a table
+ If the handler don't support this, then this function will
+ return HA_ERR_WRONG_COMMAND and MySQL will delete the rows one
+ by one.
*/
int handler::delete_all_rows()
@@ -896,14 +835,16 @@ int ha_create_table(const char *name, HA_CREATE_INFO *create_info,
}
error=table.file->create(name,&table,create_info);
VOID(closefrm(&table));
- if (error) {
- if (table.db_type == DB_TYPE_INNOBASE) {
+ if (error)
+ {
+ if (table.db_type == DB_TYPE_INNODB)
+ {
/* Creation of InnoDB table cannot fail because of an OS error:
put error as the number */
my_error(ER_CANT_CREATE_TABLE,MYF(ME_BELL+ME_WAITTANG),name,error);
- } else {
- my_error(ER_CANT_CREATE_TABLE,MYF(ME_BELL+ME_WAITTANG),name,my_errno);
}
+ else
+ my_error(ER_CANT_CREATE_TABLE,MYF(ME_BELL+ME_WAITTANG),name,my_errno);
}
DBUG_RETURN(error != 0);
}
@@ -921,5 +862,5 @@ static int NEAR_F delete_file(const char *name,const char *ext,int extflag)
{
char buff[FN_REFLEN];
VOID(fn_format(buff,name,"",ext,extflag | 4));
- return(my_delete(buff,MYF(MY_WME)));
+ return(my_delete_with_symlink(buff,MYF(MY_WME)));
}