mirror of
https://github.com/MariaDB/server.git
synced 2025-01-25 00:04:33 +01:00
f537319d42
A lot of new tests to mysqltest Fixed bug with BDB tables and autocommit BitKeeper/deleted/.del-delete.test~389410e29f2cebe5: Delete: mysql-test/t/delete.test BitKeeper/deleted/.del-delete.result~e866a6678e29f186: Delete: mysql-test/r/delete.result BitKeeper/deleted/.del-sel000014.test~74cb8c70f1d73fcc: Delete: mysql-test/t/sel000014.test BitKeeper/deleted/.del-sel000015.test~7442bf9cbc96fe07: Delete: mysql-test/t/sel000015.test BitKeeper/deleted/.del-sel000016.test~f495235f14c47ec: Delete: mysql-test/t/sel000016.test BitKeeper/deleted/.del-sel000017.test~7c39f2b45a6aa780: Delete: mysql-test/t/sel000017.test BitKeeper/deleted/.del-sel000018.test~16207f3ad74de75e: Delete: mysql-test/t/sel000018.test BitKeeper/deleted/.del-sel000014.result~fc8de0ec89d9e35: Delete: mysql-test/r/sel000014.result BitKeeper/deleted/.del-sel000015.result~cadbc52051d47bac: Delete: mysql-test/r/sel000015.result BitKeeper/deleted/.del-sel000016.result~6177851869bd5b07: Delete: mysql-test/r/sel000016.result BitKeeper/deleted/.del-sel000017.result~84ebf147850ff31c: Delete: mysql-test/r/sel000017.result BitKeeper/deleted/.del-sel000018.result~562ac9094cf53aba: Delete: mysql-test/r/sel000018.result BitKeeper/deleted/.del-sel000005.test~982fde89a4d6d886: Delete: mysql-test/t/sel000005.test BitKeeper/deleted/.del-sel000006.test~291cc6c8d85e51df: Delete: mysql-test/t/sel000006.test BitKeeper/deleted/.del-sel000005.result~d5410bb765199cc5: Delete: mysql-test/r/sel000005.result BitKeeper/deleted/.del-sel000006.result~d38004d1acfc11a5: Delete: mysql-test/r/sel000006.result BitKeeper/deleted/.del-sel000004.test~daf9ad4a1a31cd3c: Delete: mysql-test/t/sel000004.test BitKeeper/deleted/.del-sel000007.test~f431e4f4739a24c3: Delete: mysql-test/t/sel000007.test BitKeeper/deleted/.del-sel000008.test~b338ef585cadf7ae: Delete: mysql-test/t/sel000008.test BitKeeper/deleted/.del-sel000009.test~a455c38f5c942cd1: Delete: mysql-test/t/sel000009.test BitKeeper/deleted/.del-sel000010.test~ca07085ae92255f1: Delete: mysql-test/t/sel000010.test BitKeeper/deleted/.del-sel000011.test~c2a971726c9d18d6: Delete: mysql-test/t/sel000011.test BitKeeper/deleted/.del-sel000012.test~ae64bff363c42e92: Delete: mysql-test/t/sel000012.test BitKeeper/deleted/.del-sel000013.test~ce8aa504ba4f74ba: Delete: mysql-test/t/sel000013.test BitKeeper/deleted/.del-sel000019.test~8fd63c8dc6be8dbc: Delete: mysql-test/t/sel000019.test BitKeeper/deleted/.del-sel000020.test~c5758ad18a6dff1e: Delete: mysql-test/t/sel000020.test BitKeeper/deleted/.del-sel000021.test~94dd47de2872264a: Delete: mysql-test/t/sel000021.test BitKeeper/deleted/.del-sel000022.test~6e3e5435e66875e9: Delete: mysql-test/t/sel000022.test BitKeeper/deleted/.del-sel000023.test~7bdfcfaa278f837d: Delete: mysql-test/t/sel000023.test BitKeeper/deleted/.del-sel000024.test~849f47e6cbdc4fe3: Delete: mysql-test/t/sel000024.test BitKeeper/deleted/.del-sel000025.test~65b32b4b67e4c77: Delete: mysql-test/t/sel000025.test BitKeeper/deleted/.del-sel000026.test~d8aa2d614f23b1: Delete: mysql-test/t/sel000026.test BitKeeper/deleted/.del-sel000027.test~ab44bb57a580de9: Delete: mysql-test/t/sel000027.test BitKeeper/deleted/.del-sel000028.test~db9bfc0a808fb629: Delete: mysql-test/t/sel000028.test BitKeeper/deleted/.del-sel000029.test~6aae34dbb3ee86d9: Delete: mysql-test/t/sel000029.test BitKeeper/deleted/.del-sel000030.test~a29683eac3e7b706: Delete: mysql-test/t/sel000030.test BitKeeper/deleted/.del-sel000004.result~1f8d1265be521c17: Delete: mysql-test/r/sel000004.result BitKeeper/deleted/.del-sel000007.result~df455e49f9727c4f: Delete: mysql-test/r/sel000007.result BitKeeper/deleted/.del-sel000008.result~67a459ff62c84d6a: Delete: mysql-test/r/sel000008.result BitKeeper/deleted/.del-sel000009.result~e042b35ab131fb3: Delete: mysql-test/r/sel000009.result BitKeeper/deleted/.del-sel000010.result~eee5b9631a1e0066: Delete: mysql-test/r/sel000010.result BitKeeper/deleted/.del-sel000011.result~6907fe356973ed25: Delete: mysql-test/r/sel000011.result BitKeeper/deleted/.del-sel000012.result~be18991fc28954c2: Delete: mysql-test/r/sel000012.result BitKeeper/deleted/.del-sel000013.result~513389e06c96af73: Delete: mysql-test/r/sel000013.result BitKeeper/deleted/.del-sel000019.result~2870fe1c4998d929: Delete: mysql-test/r/sel000019.result BitKeeper/deleted/.del-sel000020.result~faa670294ef5fa91: Delete: mysql-test/r/sel000020.result BitKeeper/deleted/.del-sel000021.result~8f0ce4ec26e0c21d: Delete: mysql-test/r/sel000021.result BitKeeper/deleted/.del-sel000022.result~34828a43753ee767: Delete: mysql-test/r/sel000022.result BitKeeper/deleted/.del-sel000023.result~13e112d77573bf17: Delete: mysql-test/r/sel000023.result BitKeeper/deleted/.del-sel000024.result~b10d449624f48d07: Delete: mysql-test/r/sel000024.result BitKeeper/deleted/.del-sel000025.result~f31e08fcca805f35: Delete: mysql-test/r/sel000025.result BitKeeper/deleted/.del-sel000026.result~854fa951666b7982: Delete: mysql-test/r/sel000026.result BitKeeper/deleted/.del-sel000027.result~cfd73fe738f27da: Delete: mysql-test/r/sel000027.result BitKeeper/deleted/.del-sel000028.result~13ff5add6ac24908: Delete: mysql-test/r/sel000028.result BitKeeper/deleted/.del-sel000029.result~c6d071781808aa26: Delete: mysql-test/r/sel000029.result BitKeeper/deleted/.del-sel000030.result~98d496948e15064d: Delete: mysql-test/r/sel000030.result BitKeeper/deleted/.del-alt000001.test~633aed61c4bad94c: Delete: mysql-test/t/alt000001.test BitKeeper/deleted/.del-alt000001.result~393103dbf15f35c9: Delete: mysql-test/r/alt000001.result BitKeeper/deleted/.del-mrg000001.dummy.result~bf7e6d609f22b897: Delete: mysql-test/r/mrg000001.dummy.result BitKeeper/deleted/.del-mrg000001.result~db2ef2e717ab8332: Delete: mysql-test/r/mrg000001.result BitKeeper/deleted/.del-mrg000002.result~745be0854aaaaf5e: Delete: mysql-test/r/mrg000002.result BitKeeper/deleted/.del-mrg000001.test~e0327f9d1e6cb4e: Delete: mysql-test/t/mrg000001.test BitKeeper/deleted/.del-mrg000002.test~16b3a176adc0f311: Delete: mysql-test/t/mrg000002.test Docs/manual.texi: Changelog client/mysqlimport.c: Added support for hex strings client/mysqltest.c: Added linenumbers in output Only allow '{' first on a row (Conflicts with ODBC {} syntax). Handle bigger queries. Handle double '' Truncate result files. mysql-test/mysql-test-run.sh: Added --verbose cleanup mysql-test/r/bdb.result: Updating of test mysql-test/r/func_crypt.result: Updating of test mysql-test/r/func_equal.result: Updating of test mysql-test/r/func_str.result: Updating of test mysql-test/r/ins000001.result: Updating of test mysql-test/t/bdb.test: Updating of test mysql-test/t/err000001.test: Updating of test mysql-test/t/func_crypt.test: Updating of test mysql-test/t/func_equal.test: Updating of test mysql-test/t/func_str.test: Updating of test mysql-test/t/ins000001.test: Updating of test sql/gen_lex_hash.cc: Smaller table sql/handler.cc: Fixed bug in auto_commit
719 lines
16 KiB
C++
719 lines
16 KiB
C++
/* 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 */
|
|
|
|
|
|
/* Handler-calling-functions */
|
|
|
|
#ifdef __GNUC__
|
|
#pragma implementation // gcc: Class implementation
|
|
#endif
|
|
|
|
#include "mysql_priv.h"
|
|
#include "ha_heap.h"
|
|
#include "ha_myisam.h"
|
|
#include "ha_myisammrg.h"
|
|
#ifndef NO_ISAM
|
|
#include "ha_isam.h"
|
|
#include "ha_isammrg.h"
|
|
#endif
|
|
#ifdef HAVE_BERKELEY_DB
|
|
#include "ha_berkeley.h"
|
|
#endif
|
|
#ifdef HAVE_INNOBASE_DB
|
|
#include "ha_innobase.h"
|
|
#endif
|
|
#include <myisampack.h>
|
|
#include <errno.h>
|
|
|
|
/* static functions defined in this file */
|
|
|
|
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_read_rnd_count, ha_read_rnd_next_count;
|
|
|
|
const char *ha_table_type[] = {
|
|
"", "DIAB_ISAM","HASH","MISAM","PISAM","RMS_ISAM","HEAP", "ISAM",
|
|
"MRG_ISAM","MYISAM", "MRG_MYISAM", "BDB", "INNOBASE", "?", "?",NullS
|
|
};
|
|
|
|
const char *ha_row_type[] = {
|
|
"", "FIXED", "DYNAMIC", "COMPRESSED","?","?","?"
|
|
};
|
|
|
|
TYPELIB ha_table_typelib= {array_elements(ha_table_type)-4,"",
|
|
ha_table_type+1};
|
|
|
|
|
|
/* Use other database handler if databasehandler is not incompiled */
|
|
|
|
enum db_type ha_checktype(enum db_type database_type)
|
|
{
|
|
switch (database_type) {
|
|
#ifdef HAVE_BERKELEY_DB
|
|
case DB_TYPE_BERKELEY_DB:
|
|
return(berkeley_skip ? DB_TYPE_MYISAM : database_type);
|
|
#endif
|
|
#ifdef HAVE_INNOBASE_DB
|
|
case DB_TYPE_INNOBASE:
|
|
return(innobase_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
|
|
case DB_TYPE_ISAM:
|
|
#endif
|
|
case DB_TYPE_HEAP:
|
|
case DB_TYPE_MYISAM:
|
|
case DB_TYPE_MRG_MYISAM:
|
|
return (database_type); /* Database exists on system */
|
|
default:
|
|
break;
|
|
}
|
|
return(DB_TYPE_MYISAM); /* Use this as default */
|
|
} /* ha_checktype */
|
|
|
|
|
|
handler *get_new_handler(TABLE *table, enum db_type db_type)
|
|
{
|
|
switch (db_type) {
|
|
#ifndef NO_HASH
|
|
return new ha_hash(table);
|
|
#endif
|
|
#ifndef NO_MERGE
|
|
case DB_TYPE_MRG_ISAM:
|
|
return new ha_isammrg(table);
|
|
#endif
|
|
#ifndef NO_ISAM
|
|
case DB_TYPE_ISAM:
|
|
return new ha_isam(table);
|
|
#endif
|
|
#ifdef HAVE_BERKELEY_DB
|
|
case DB_TYPE_BERKELEY_DB:
|
|
return new ha_berkeley(table);
|
|
#endif
|
|
#ifdef HAVE_INNOBASE_DB
|
|
case DB_TYPE_INNOBASE_DB:
|
|
return new ha_innobase(table);
|
|
#endif
|
|
case DB_TYPE_HEAP:
|
|
return new ha_heap(table);
|
|
case DB_TYPE_MYISAM:
|
|
default: // should never happen
|
|
return new ha_myisam(table);
|
|
case DB_TYPE_MRG_MYISAM:
|
|
return new ha_myisammrg(table);
|
|
}
|
|
}
|
|
|
|
int ha_init()
|
|
{
|
|
#ifdef HAVE_BERKELEY_DB
|
|
if (!berkeley_skip)
|
|
{
|
|
int error;
|
|
if ((error=berkeley_init()))
|
|
return error;
|
|
}
|
|
#endif
|
|
#ifdef HAVE_INNOBASE_DB
|
|
if (!innobase_skip)
|
|
{
|
|
int error;
|
|
if ((error=innobase_init()))
|
|
return error;
|
|
}
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
/* close, flush or restart databases */
|
|
/* Ignore this for other databases than ours */
|
|
|
|
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);
|
|
error|=nisam_panic(flag);
|
|
error|=mi_panic(flag);
|
|
error|=myrg_panic(flag);
|
|
#ifdef HAVE_BERKELEY_DB
|
|
if (!berkeley_skip)
|
|
error|=berkeley_end();
|
|
#endif
|
|
#ifdef HAVE_INNOBASE_DB
|
|
if (!innobase_skip)
|
|
error|=innobase_end();
|
|
#endif
|
|
return error;
|
|
} /* ha_panic */
|
|
|
|
|
|
void ha_close_connection(THD* thd)
|
|
{
|
|
#ifdef HAVE_INNOBASE_DB
|
|
if (!innobase_skip)
|
|
innobase_close_connection(THD* thd);
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
This is used to commit or rollback a single statement depending
|
|
on the value of error
|
|
*/
|
|
|
|
int ha_autocommit_or_rollback(THD *thd, int error)
|
|
{
|
|
DBUG_ENTER("ha_autocommit_or_rollback");
|
|
#ifdef USING_TRANSACTIONS
|
|
if (!error)
|
|
{
|
|
if (ha_commit_stmt(thd))
|
|
error=1;
|
|
}
|
|
else
|
|
(void) ha_rollback_stmt(thd);
|
|
#endif
|
|
DBUG_RETURN(error);
|
|
}
|
|
|
|
|
|
int ha_commit_trans(THD *thd, THD_TRANS* trans)
|
|
{
|
|
int error=0;
|
|
DBUG_ENTER("ha_commit");
|
|
#ifdef USING_TRANSACTIONS
|
|
/* 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))
|
|
{
|
|
mysql_bin_log.write(&thd->transaction.trans_log);
|
|
reinit_io_cache(&thd->transaction.trans_log,
|
|
WRITE_CACHE, (my_off_t) 0, 0, 1);
|
|
thd->transaction.trans_log.end_of_file= max_binlog_cache_size;
|
|
}
|
|
#ifdef HAVE_BERKELEY_DB
|
|
if (trans->bdb_tid)
|
|
{
|
|
if ((error=berkeley_commit(thd,trans->bdb_tid)))
|
|
{
|
|
my_error(ER_ERROR_DURING_COMMIT, MYF(0), error);
|
|
error=1;
|
|
}
|
|
trans->bdb_tid=0;
|
|
}
|
|
#endif
|
|
#ifdef HAVE_INNOBASE_DB
|
|
if (trans->innobase_tid)
|
|
{
|
|
if ((error=innobase_commit(thd,trans->innobase_tid)))
|
|
{
|
|
my_error(ER_ERROR_DURING_COMMIT, MYF(0), error);
|
|
error=1;
|
|
}
|
|
trans->innobase_tid=0;
|
|
}
|
|
#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!");
|
|
#endif
|
|
DBUG_RETURN(error);
|
|
}
|
|
|
|
int ha_rollback_trans(THD *thd, THD_TRANS *trans)
|
|
{
|
|
int error=0;
|
|
DBUG_ENTER("ha_rollback");
|
|
#ifdef HAVE_BERKELEY_DB
|
|
if (trans->bdb_tid)
|
|
{
|
|
if ((error=berkeley_rollback(thd, trans->bdb_tid)))
|
|
{
|
|
my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), error);
|
|
error=1;
|
|
}
|
|
trans->bdb_tid=0;
|
|
}
|
|
#endif
|
|
#ifdef HAVE_INNOBASE_DB
|
|
if (trans->innobase_tid)
|
|
{
|
|
if ((error=innobase_rollback(thd)))
|
|
{
|
|
my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), error);
|
|
error=1;
|
|
}
|
|
trans->innobase_tid=0;
|
|
}
|
|
#endif
|
|
#ifdef USING_TRANSACTIONS
|
|
if (trans == &thd->transaction.all)
|
|
reinit_io_cache(&thd->transaction.trans_log,
|
|
WRITE_CACHE, (my_off_t) 0, 0, 1);
|
|
thd->transaction.trans_log.end_of_file= max_binlog_cache_size;
|
|
#endif
|
|
DBUG_RETURN(error);
|
|
}
|
|
|
|
|
|
bool ha_flush_logs()
|
|
{
|
|
bool result=0;
|
|
#ifdef HAVE_BERKELEY_DB
|
|
if (!berkeley_skip && berkeley_flush_logs())
|
|
result=1;
|
|
#endif
|
|
#ifdef HAVE_INNOBASE_DB
|
|
if (!innobase_skip && innobase_flush_logs())
|
|
result=1;
|
|
#endif
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
This should return ENOENT if the file doesn't exists.
|
|
The .frm file will be deleted only if we return 0 or ENOENT
|
|
*/
|
|
|
|
int ha_delete_table(enum db_type table_type, const char *path)
|
|
{
|
|
handler *file=get_new_handler((TABLE*) 0, table_type);
|
|
if (!file)
|
|
return ENOENT;
|
|
int error=file->delete_table(path);
|
|
delete file;
|
|
return error;
|
|
}
|
|
|
|
void ha_store_ptr(byte *buff, uint pack_length, my_off_t pos)
|
|
{
|
|
switch (pack_length) {
|
|
#if SIZEOF_OFF_T > 4
|
|
case 8: mi_int8store(buff,pos); break;
|
|
case 7: mi_int7store(buff,pos); break;
|
|
case 6: mi_int6store(buff,pos); break;
|
|
case 5: mi_int5store(buff,pos); break;
|
|
#endif
|
|
case 4: mi_int4store(buff,pos); break;
|
|
case 3: mi_int3store(buff,pos); break;
|
|
case 2: mi_int2store(buff,(uint) pos); break;
|
|
case 1: buff[0]= (uchar) pos; break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
my_off_t ha_get_ptr(byte *ptr, uint pack_length)
|
|
{
|
|
my_off_t pos;
|
|
switch (pack_length) {
|
|
#if SIZEOF_OFF_T > 4
|
|
case 8:
|
|
pos= (my_off_t) mi_uint8korr(ptr);
|
|
break;
|
|
case 7:
|
|
pos= (my_off_t) mi_uint7korr(ptr);
|
|
break;
|
|
case 6:
|
|
pos= (my_off_t) mi_uint6korr(ptr);
|
|
break;
|
|
case 5:
|
|
pos= (my_off_t) mi_uint5korr(ptr);
|
|
break;
|
|
#endif
|
|
case 4:
|
|
pos= (my_off_t) mi_uint4korr(ptr);
|
|
break;
|
|
case 3:
|
|
pos= (my_off_t) mi_uint3korr(ptr);
|
|
break;
|
|
case 2:
|
|
pos= (my_off_t) mi_uint2korr(ptr);
|
|
break;
|
|
case 1:
|
|
pos= (my_off_t) mi_uint2korr(ptr);
|
|
break;
|
|
default:
|
|
pos=0; // Impossible
|
|
break;
|
|
}
|
|
return pos;
|
|
}
|
|
|
|
/****************************************************************************
|
|
** General handler functions
|
|
****************************************************************************/
|
|
|
|
/* Open database-handler. Try O_RDONLY if can't open as O_RDWR */
|
|
/* Don't wait for locks if not HA_OPEN_WAIT_IF_LOCKED is set */
|
|
|
|
int handler::ha_open(const char *name, int mode, int test_if_locked)
|
|
{
|
|
int error;
|
|
DBUG_ENTER("handler::open");
|
|
DBUG_PRINT("enter",("db_type: %d db_stat: %d mode: %d lock_test: %d",
|
|
table->db_type, table->db_stat, mode, test_if_locked));
|
|
|
|
if ((error=open(name,mode,test_if_locked)))
|
|
{
|
|
if ((error == EACCES || error == EROFS) && mode == O_RDWR &&
|
|
(table->db_stat & HA_TRY_READ_ONLY))
|
|
{
|
|
table->db_stat|=HA_READ_ONLY;
|
|
error=open(name,O_RDONLY,test_if_locked);
|
|
}
|
|
}
|
|
if (error)
|
|
{
|
|
my_errno=error; /* Safeguard */
|
|
DBUG_PRINT("error",("error: %d errno: %d",error,errno));
|
|
}
|
|
else
|
|
{
|
|
if (table->db_options_in_use & HA_OPTION_READ_ONLY_DATA)
|
|
table->db_stat|=HA_READ_ONLY;
|
|
}
|
|
if (!error)
|
|
{
|
|
if (!alloc_root_inited(&table->mem_root)) // If temporary table
|
|
ref=(byte*) sql_alloc(ALIGN_SIZE(ref_length)*2);
|
|
else
|
|
ref=(byte*) alloc_root(&table->mem_root, ALIGN_SIZE(ref_length)*2);
|
|
if (!ref)
|
|
{
|
|
close();
|
|
error=HA_ERR_OUT_OF_MEM;
|
|
}
|
|
else
|
|
dupp_ref=ref+ALIGN_SIZE(ref_length);
|
|
}
|
|
DBUG_RETURN(error);
|
|
}
|
|
|
|
int handler::check(THD* thd, HA_CHECK_OPT* check_opt)
|
|
{
|
|
return HA_ADMIN_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
int handler::backup(THD* thd, HA_CHECK_OPT* check_opt)
|
|
{
|
|
return HA_ADMIN_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
int handler::restore(THD* thd, HA_CHECK_OPT* check_opt)
|
|
{
|
|
return HA_ADMIN_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
int handler::repair(THD* thd, HA_CHECK_OPT* check_opt)
|
|
{
|
|
return HA_ADMIN_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
int handler::optimize(THD* thd, HA_CHECK_OPT* check_opt)
|
|
{
|
|
return HA_ADMIN_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
int handler::analyze(THD* thd, HA_CHECK_OPT* check_opt)
|
|
{
|
|
return HA_ADMIN_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
/* Read first row from a table */
|
|
|
|
int handler::rnd_first(byte * buf)
|
|
{
|
|
register int error;
|
|
DBUG_ENTER("handler::rnd_first");
|
|
|
|
statistic_increment(ha_read_first_count,&LOCK_status);
|
|
(void) rnd_init();
|
|
while ((error= rnd_next(buf)) == HA_ERR_RECORD_DELETED) ;
|
|
(void) rnd_end();
|
|
DBUG_RETURN(error);
|
|
}
|
|
|
|
|
|
/*
|
|
The following function is only needed for tables that may be temporary tables
|
|
during joins
|
|
*/
|
|
|
|
int handler::restart_rnd_next(byte *buf, byte *pos)
|
|
{
|
|
return HA_ERR_WRONG_COMMAND;
|
|
}
|
|
|
|
|
|
/* Set a timestamp in record */
|
|
|
|
void handler::update_timestamp(byte *record)
|
|
{
|
|
long skr= (long) current_thd->query_start();
|
|
#ifdef WORDS_BIGENDIAN
|
|
if (table->db_low_byte_first)
|
|
{
|
|
int4store(record,skr);
|
|
}
|
|
else
|
|
#endif
|
|
longstore(record,skr);
|
|
return;
|
|
}
|
|
|
|
/* 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()
|
|
{
|
|
longlong nr;
|
|
THD *thd;
|
|
DBUG_ENTER("update_auto_increment");
|
|
if (table->next_number_field->val_int() != 0)
|
|
DBUG_VOID_RETURN;
|
|
thd=current_thd;
|
|
if ((nr=thd->next_insert_id))
|
|
thd->next_insert_id=0; // Clear after use
|
|
else
|
|
nr=get_auto_increment();
|
|
thd->insert_id((ulonglong) nr);
|
|
table->next_number_field->store(nr);
|
|
DBUG_VOID_RETURN;
|
|
}
|
|
|
|
|
|
longlong handler::get_auto_increment()
|
|
{
|
|
longlong nr;
|
|
int error;
|
|
(void) extra(HA_EXTRA_KEYREAD);
|
|
index_init(table->next_number_index);
|
|
error=index_last(table->record[1]);
|
|
if (error)
|
|
nr=1;
|
|
else
|
|
nr=(longlong) table->next_number_field->
|
|
val_int_offset(table->rec_buff_length)+1;
|
|
(void) extra(HA_EXTRA_NO_KEYREAD);
|
|
index_end();
|
|
return nr;
|
|
}
|
|
|
|
/* Print error that we got from handler function */
|
|
|
|
void handler::print_error(int error, myf errflag)
|
|
{
|
|
DBUG_ENTER("print_error");
|
|
DBUG_PRINT("enter",("error: %d",error));
|
|
|
|
int textno=ER_GET_ERRNO;
|
|
switch (error) {
|
|
case EAGAIN:
|
|
textno=ER_FILE_USED;
|
|
break;
|
|
case ENOENT:
|
|
textno=ER_FILE_NOT_FOUND;
|
|
break;
|
|
case HA_ERR_KEY_NOT_FOUND:
|
|
case HA_ERR_NO_ACTIVE_RECORD:
|
|
case HA_ERR_END_OF_FILE:
|
|
textno=ER_KEY_NOT_FOUND;
|
|
break;
|
|
case HA_ERR_WRONG_TABLE_DEF:
|
|
textno=ER_WRONG_MRG_TABLE;
|
|
break;
|
|
case HA_ERR_FOUND_DUPP_KEY:
|
|
{
|
|
uint key_nr=get_dup_key(error);
|
|
if ((int) key_nr >= 0)
|
|
{
|
|
/* Write the dupplicated key in the error message */
|
|
char key[MAX_KEY_LENGTH];
|
|
String str(key,sizeof(key));
|
|
key_unpack(&str,table,(uint) key_nr);
|
|
uint max_length=MYSQL_ERRMSG_SIZE-(uint) strlen(ER(ER_DUP_ENTRY));
|
|
if (str.length() >= max_length)
|
|
{
|
|
str.length(max_length-4);
|
|
str.append("...");
|
|
}
|
|
my_error(ER_DUP_ENTRY,MYF(0),str.c_ptr(),key_nr+1);
|
|
DBUG_VOID_RETURN;
|
|
}
|
|
textno=ER_DUP_KEY;
|
|
break;
|
|
}
|
|
case HA_ERR_FOUND_DUPP_UNIQUE:
|
|
textno=ER_DUP_UNIQUE;
|
|
break;
|
|
case HA_ERR_RECORD_CHANGED:
|
|
textno=ER_CHECKREAD;
|
|
break;
|
|
case HA_ERR_CRASHED:
|
|
textno=ER_NOT_KEYFILE;
|
|
break;
|
|
case HA_ERR_CRASHED_ON_USAGE:
|
|
textno=ER_CRASHED_ON_USAGE;
|
|
break;
|
|
case HA_ERR_CRASHED_ON_REPAIR:
|
|
textno=ER_CRASHED_ON_REPAIR;
|
|
break;
|
|
case HA_ERR_OUT_OF_MEM:
|
|
my_error(ER_OUT_OF_RESOURCES,errflag);
|
|
DBUG_VOID_RETURN;
|
|
case HA_ERR_WRONG_COMMAND:
|
|
textno=ER_ILLEGAL_HA;
|
|
break;
|
|
case HA_ERR_OLD_FILE:
|
|
textno=ER_OLD_KEYFILE;
|
|
break;
|
|
case HA_ERR_UNSUPPORTED:
|
|
textno=ER_UNSUPPORTED_EXTENSION;
|
|
break;
|
|
case HA_ERR_RECORD_FILE_FULL:
|
|
textno=ER_RECORD_FILE_FULL;
|
|
break;
|
|
default:
|
|
{
|
|
my_error(ER_GET_ERRNO,errflag,error);
|
|
DBUG_VOID_RETURN;
|
|
}
|
|
}
|
|
my_error(textno,errflag,table->table_name,error);
|
|
DBUG_VOID_RETURN;
|
|
}
|
|
|
|
/* Return key if error because of duplicated keys */
|
|
|
|
uint handler::get_dup_key(int error)
|
|
{
|
|
DBUG_ENTER("get_dup_key");
|
|
table->file->errkey = (uint) -1;
|
|
if (error == HA_ERR_FOUND_DUPP_KEY || error == HA_ERR_FOUND_DUPP_UNIQUE)
|
|
info(HA_STATUS_ERRKEY | HA_STATUS_NO_LOCK);
|
|
DBUG_RETURN(table->file->errkey);
|
|
}
|
|
|
|
int handler::delete_table(const char *name)
|
|
{
|
|
int error=0;
|
|
for (const char **ext=bas_ext(); *ext ; ext++)
|
|
{
|
|
if (delete_file(name,*ext,2))
|
|
{
|
|
if ((error=errno) != ENOENT)
|
|
break;
|
|
}
|
|
}
|
|
return error;
|
|
}
|
|
|
|
|
|
int handler::rename_table(const char * from, const char * to)
|
|
{
|
|
DBUG_ENTER("handler::rename_table");
|
|
for (const char **ext=bas_ext(); *ext ; ext++)
|
|
{
|
|
if (rename_file_ext(from,to,*ext))
|
|
DBUG_RETURN(my_errno);
|
|
}
|
|
DBUG_RETURN(0);
|
|
}
|
|
|
|
|
|
int handler::index_next_same(byte *buf, const byte *key, uint keylen)
|
|
{
|
|
int error;
|
|
if (!(error=index_next(buf)))
|
|
{
|
|
if (key_cmp(table, key, active_index, keylen))
|
|
{
|
|
table->status=STATUS_NOT_FOUND;
|
|
error=HA_ERR_END_OF_FILE;
|
|
}
|
|
}
|
|
return error;
|
|
}
|
|
|
|
|
|
/*
|
|
The following is only needed if we would like to use the database
|
|
for internal temporary tables
|
|
*/
|
|
|
|
int handler::delete_all_rows()
|
|
{
|
|
return (my_errno=HA_ERR_WRONG_COMMAND);
|
|
}
|
|
|
|
/****************************************************************************
|
|
** Some general functions that isn't in the handler class
|
|
****************************************************************************/
|
|
|
|
/* Initiates table-file and calls apropriate database-creator */
|
|
/* Returns 1 if something got wrong */
|
|
|
|
int ha_create_table(const char *name, HA_CREATE_INFO *create_info,
|
|
bool update_create_info)
|
|
|
|
{
|
|
int error;
|
|
TABLE table;
|
|
DBUG_ENTER("ha_create_table");
|
|
|
|
if (openfrm(name,"",0,(uint) READ_ALL, 0, &table))
|
|
DBUG_RETURN(1);
|
|
if (update_create_info)
|
|
{
|
|
update_create_info_from_table(create_info, &table);
|
|
if (table.file->option_flag() & HA_DROP_BEFORE_CREATE)
|
|
table.file->delete_table(name); // Needed for BDB tables
|
|
}
|
|
error=table.file->create(name,&table,create_info);
|
|
VOID(closefrm(&table));
|
|
if (error)
|
|
my_error(ER_CANT_CREATE_TABLE,MYF(ME_BELL+ME_WAITTANG),name,my_errno);
|
|
DBUG_RETURN(error != 0);
|
|
}
|
|
|
|
/* Use key cacheing on all databases */
|
|
|
|
void ha_key_cache(void)
|
|
{
|
|
if (keybuff_size)
|
|
(void) init_key_cache(keybuff_size,0);
|
|
} /* ha_key_cache */
|
|
|
|
|
|
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)));
|
|
}
|