Commit b67d11e1 authored by unknown's avatar unknown

Changed DB_TYPE_INNOBASE to DB_TYPE_INNODB

Fix that DROP DATABASE works with all table types
Use BULK_INSERT when inserting more than one row
Better TRUNCATE TABLE


BitKeeper/deleted/.del-compilation_finished.au.gz~70bd14095a918139:
  Delete: sounds/compilation_finished.au.gz
BUILD/FINISH.sh:
  Removed 'finished' sound as this isn't a general solution.
Docs/manual.texi:
  Added upgrading from 3.23
configure.in:
  Fixed version number
sql/ha_innobase.cc:
  Default creation of InnoDB tables.
sql/ha_myisam.cc:
  Disable BULK_INSERT of using safe mode
sql/handler.cc:
  Changed DB_TYPE_INNOBASE to DB_TYPE_INNODB
sql/handler.h:
  Changed DB_TYPE_INNOBASE to DB_TYPE_INNODB
sql/lock.cc:
  Added lock_and_wait_for_table_name
sql/mysql_priv.h:
  Better TRUNCATE TABLE
sql/sql_db.cc:
  Fix that DROP DATABASE works with all table types
sql/sql_delete.cc:
  Better TRUNCATE TABLE
sql/sql_insert.cc:
  Use BULK_INSERT when inserting more than one row
sql/sql_load.cc:
  Small bug fix.
sql/sql_parse.cc:
  Better TRUNCATE TABLE
sql/sql_select.cc:
  Change INNOBASE -> INNODB
sql/sql_table.cc:
  Better TRUNCATE TABLE
sql/sql_yacc.yy:
  INNOBASE -> INNODB
sql/thr_malloc.cc:
  Fix for replication
parent fc140664
...@@ -45,11 +45,3 @@ then ...@@ -45,11 +45,3 @@ then
else else
echo "$commands" echo "$commands"
fi fi
comp_finished=sounds/compilation_finished.au.gz
if [ -c /dev/audio ] && [ -f "$comp_finished" ]
then
gunzip -c $comp_finished > /dev/audio
fi
...@@ -326,6 +326,7 @@ Post-installation Setup and Testing ...@@ -326,6 +326,7 @@ Post-installation Setup and Testing
Upgrading/Downgrading MySQL Upgrading/Downgrading MySQL
* Upgrading-from-3.23::
* Upgrading-from-3.22:: Upgrading from a 3.22 version to 3.23 * Upgrading-from-3.22:: Upgrading from a 3.22 version to 3.23
* Upgrading-from-3.21:: Upgrading from a 3.21 version to 3.22 * Upgrading-from-3.21:: Upgrading from a 3.21 version to 3.22
* Upgrading-from-3.20:: Upgrading from a 3.20 version to 3.21 * Upgrading-from-3.20:: Upgrading from a 3.20 version to 3.21
...@@ -643,7 +644,6 @@ Replication in MySQL ...@@ -643,7 +644,6 @@ Replication in MySQL
MySQL Full-text Search MySQL Full-text Search
* Fulltext Search::
* Fulltext Fine-tuning:: * Fulltext Fine-tuning::
* Fulltext Features to Appear in MySQL 4.0:: * Fulltext Features to Appear in MySQL 4.0::
* Fulltext TODO:: * Fulltext TODO::
...@@ -10828,15 +10828,39 @@ particularly if you notice symptoms such as all your @code{DBI} scripts ...@@ -10828,15 +10828,39 @@ particularly if you notice symptoms such as all your @code{DBI} scripts
dumping core after you upgrade @strong{MySQL}. dumping core after you upgrade @strong{MySQL}.
@menu @menu
* Upgrading-from-3.23::
* Upgrading-from-3.22:: Upgrading from a 3.22 version to 3.23 * Upgrading-from-3.22:: Upgrading from a 3.22 version to 3.23
* Upgrading-from-3.21:: Upgrading from a 3.21 version to 3.22 * Upgrading-from-3.21:: Upgrading from a 3.21 version to 3.22
* Upgrading-from-3.20:: Upgrading from a 3.20 version to 3.21 * Upgrading-from-3.20:: Upgrading from a 3.20 version to 3.21
* Upgrading-to-arch:: Upgrading to another architecture * Upgrading-to-arch:: Upgrading to another architecture
@end menu @end menu
@cindex compatibility, between MySQL versions
@cindex upgrading, 3.23 to 4.0
@node Upgrading-from-3.23, Upgrading-from-3.22, Upgrade, Upgrade
@subsection Upgrading From Version 3.23 to Version 4.0
You can use your old data files without any modification with Version 4.0
All old clients will work with a Version 4.0 server.
The following lists tell what you have to watch out for when upgrading to
Version 4.0;
@itemize @bullet
@item
You should use @code{TRUNCATE TABLE} when you want to delete all rows
from a table and you don't care of how many rows where deleted.
(Because @code{TRUNCATE TABLE} is faster than @code{DELETE FROM table_name}).
@item
You will get an error if you have an active @code{LOCK TABLES} or
transaction when trying to execute @code{TRUNCATE TABLE} or @code{DROP
DATABASE}.
@end itemize
@cindex compatibility, between MySQL versions @cindex compatibility, between MySQL versions
@cindex upgrading, 3.22 to 3.23 @cindex upgrading, 3.22 to 3.23
@node Upgrading-from-3.22, Upgrading-from-3.21, Upgrade, Upgrade @node Upgrading-from-3.22, Upgrading-from-3.21, Upgrading-from-3.23, Upgrade
@subsection Upgrading From Version 3.22 to Version 3.23 @subsection Upgrading From Version 3.22 to Version 3.23
@strong{MySQL} Version 3.23 supports tables of the new @code{MyISAM} type and @strong{MySQL} Version 3.23 supports tables of the new @code{MyISAM} type and
...@@ -20108,16 +20132,19 @@ the @code{LIMIT} value. ...@@ -20108,16 +20132,19 @@ the @code{LIMIT} value.
TRUNCATE TABLE table_name TRUNCATE TABLE table_name
@end example @end example
Is in 3.23 and the same thing as @code{DELETE FROM table_name}. @xref{DELETE}. In 3.23 @code{TRUNCATE TABLE} is mapped to
The differences are: @code{COMMIT ; DELETE FROM table_name}. @xref{DELETE}.
The differences between @code{TRUNCATE TABLE} and @code{DELETE FROM ..}
are:
@itemize @bullet @itemize @bullet
@item @item
Implemented as a drop and re-create of the table, which makes this Truncates does a drop and re-create of the table, which is much faster
much faster when deleting many rows. than deleting rows one by one.
@item @item
Not transaction-safe; @code{TRUNCATE TABLE} will automatically end the current Not transaction-safe; You will get an error if you have an active
transaction as if @code{COMMIT} would have been called. transaction or an active table lock.
@item @item
Doesn't return the number of deleted rows. Doesn't return the number of deleted rows.
@item @item
...@@ -25970,7 +25997,7 @@ Finland ...@@ -25970,7 +25997,7 @@ Finland
@cindex tables, @code{BDB} @cindex tables, @code{BDB}
@cindex tables, @code{Berkeley DB} @cindex tables, @code{Berkeley DB}
@node BDB, , InnoDB, Table types @node BDB, , InnoDB, Table types
@section BDB or Berkeley_DB Tables @section BDB or Berkeley_DB Tables
@menu @menu
...@@ -45722,6 +45749,13 @@ Our TODO section contains what we plan to have in 4.0. @xref{TODO MySQL 4.0}. ...@@ -45722,6 +45749,13 @@ Our TODO section contains what we plan to have in 4.0. @xref{TODO MySQL 4.0}.
@itemize @bullet @itemize @bullet
@item @item
@code{TRUNCATE TABLE} and @code{DELETE FROM table_name} are now separate
functions. One bonus is that @code{DELETE FROM table_name} now returns
the number of deleted rows.
@item
@code{DROP DATABASE} now executes a @code{DROP TABLE} on all tables in
the database, which fixes a problem with InnoDB tables.
@item
Changed WEEK(#,0) to match the calender in the USA. Changed WEEK(#,0) to match the calender in the USA.
@item @item
Cleaned up global lock handling for @code{FLUSH TABLES WITH READ LOCK} Cleaned up global lock handling for @code{FLUSH TABLES WITH READ LOCK}
...@@ -4,7 +4,7 @@ dnl Process this file with autoconf to produce a configure script. ...@@ -4,7 +4,7 @@ dnl Process this file with autoconf to produce a configure script.
AC_INIT(sql/mysqld.cc) AC_INIT(sql/mysqld.cc)
AC_CANONICAL_SYSTEM AC_CANONICAL_SYSTEM
# The Docs Makefile.am parses this line! # The Docs Makefile.am parses this line!
AM_INIT_AUTOMAKE(mysql, 4.0.0) AM_INIT_AUTOMAKE(mysql, 4.0.0-alpha)
AM_CONFIG_HEADER(config.h) AM_CONFIG_HEADER(config.h)
PROTOCOL_VERSION=10 PROTOCOL_VERSION=10
......
...@@ -81,13 +81,18 @@ long innobase_mirrored_log_groups, innobase_log_files_in_group, ...@@ -81,13 +81,18 @@ long innobase_mirrored_log_groups, innobase_log_files_in_group,
innobase_buffer_pool_size, innobase_additional_mem_pool_size, innobase_buffer_pool_size, innobase_additional_mem_pool_size,
innobase_file_io_threads, innobase_lock_wait_timeout; innobase_file_io_threads, innobase_lock_wait_timeout;
char *innobase_data_home_dir, *innobase_data_file_path; char *innobase_data_home_dir;
char *innobase_log_group_home_dir, *innobase_log_arch_dir; char *innobase_log_group_home_dir, *innobase_log_arch_dir;
char *innobase_unix_file_flush_method; char *innobase_unix_file_flush_method;
bool innobase_flush_log_at_trx_commit, innobase_log_archive, bool innobase_flush_log_at_trx_commit, innobase_log_archive,
innobase_use_native_aio; innobase_use_native_aio;
/* innobase_data_file_path=ibdata:15,idata2:1,... */ /*
Set default InnoDB size to 64M, to let users use InnoDB without having
to specify any startup options.
*/
char *innobase_data_file_path= (char*) "ibdata:64M";
/* The following counter is used to convey information to InnoDB /* The following counter is used to convey information to InnoDB
about server activity: in selects it is not sensible to call about server activity: in selects it is not sensible to call
......
...@@ -890,7 +890,8 @@ int ha_myisam::extra(enum ha_extra_function operation) ...@@ -890,7 +890,8 @@ int ha_myisam::extra(enum ha_extra_function operation)
{ {
if (((specialflag & SPECIAL_SAFE_MODE) || (test_flags & TEST_NO_EXTRA)) && if (((specialflag & SPECIAL_SAFE_MODE) || (test_flags & TEST_NO_EXTRA)) &&
(operation == HA_EXTRA_WRITE_CACHE || (operation == HA_EXTRA_WRITE_CACHE ||
operation == HA_EXTRA_KEYREAD)) operation == HA_EXTRA_KEYREAD ||
operation == HA_EXTRA_BULK_INSERT_BEGIN))
return 0; return 0;
return mi_extra(file,operation); return mi_extra(file,operation);
} }
......
...@@ -78,7 +78,7 @@ enum db_type ha_checktype(enum db_type database_type) ...@@ -78,7 +78,7 @@ enum db_type ha_checktype(enum db_type database_type)
return(berkeley_skip ? DB_TYPE_MYISAM : database_type); return(berkeley_skip ? DB_TYPE_MYISAM : database_type);
#endif #endif
#ifdef HAVE_INNOBASE_DB #ifdef HAVE_INNOBASE_DB
case DB_TYPE_INNOBASE: case DB_TYPE_INNODB:
return(innodb_skip ? DB_TYPE_MYISAM : database_type); return(innodb_skip ? DB_TYPE_MYISAM : database_type);
#endif #endif
#ifdef HAVE_GEMINI_DB #ifdef HAVE_GEMINI_DB
...@@ -124,7 +124,7 @@ handler *get_new_handler(TABLE *table, enum db_type db_type) ...@@ -124,7 +124,7 @@ handler *get_new_handler(TABLE *table, enum db_type db_type)
return new ha_berkeley(table); return new ha_berkeley(table);
#endif #endif
#ifdef HAVE_INNOBASE_DB #ifdef HAVE_INNOBASE_DB
case DB_TYPE_INNOBASE: case DB_TYPE_INNODB:
return new ha_innobase(table); return new ha_innobase(table);
#endif #endif
#ifdef HAVE_GEMINI_DB #ifdef HAVE_GEMINI_DB
...@@ -801,8 +801,10 @@ int handler::index_next_same(byte *buf, const byte *key, uint keylen) ...@@ -801,8 +801,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 This is called to delete all rows in a table
for internal temporary tables 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() int handler::delete_all_rows()
......
...@@ -111,7 +111,7 @@ enum db_type { DB_TYPE_UNKNOWN=0,DB_TYPE_DIAB_ISAM=1, ...@@ -111,7 +111,7 @@ enum db_type { DB_TYPE_UNKNOWN=0,DB_TYPE_DIAB_ISAM=1,
DB_TYPE_HASH,DB_TYPE_MISAM,DB_TYPE_PISAM, DB_TYPE_HASH,DB_TYPE_MISAM,DB_TYPE_PISAM,
DB_TYPE_RMS_ISAM, DB_TYPE_HEAP, DB_TYPE_ISAM, DB_TYPE_RMS_ISAM, DB_TYPE_HEAP, DB_TYPE_ISAM,
DB_TYPE_MRG_ISAM, DB_TYPE_MYISAM, DB_TYPE_MRG_MYISAM, DB_TYPE_MRG_ISAM, DB_TYPE_MYISAM, DB_TYPE_MRG_MYISAM,
DB_TYPE_BERKELEY_DB, DB_TYPE_INNOBASE, DB_TYPE_GEMINI, DB_TYPE_BERKELEY_DB, DB_TYPE_INNODB, DB_TYPE_GEMINI,
DB_TYPE_DEFAULT }; DB_TYPE_DEFAULT };
enum row_type { ROW_TYPE_DEFAULT, ROW_TYPE_FIXED, ROW_TYPE_DYNAMIC, enum row_type { ROW_TYPE_DEFAULT, ROW_TYPE_FIXED, ROW_TYPE_DYNAMIC,
...@@ -337,6 +337,8 @@ extern TYPELIB ha_table_typelib, tx_isolation_typelib; ...@@ -337,6 +337,8 @@ extern TYPELIB ha_table_typelib, tx_isolation_typelib;
#define ha_commit(thd) (ha_commit_trans((thd), &((thd)->transaction.all))) #define ha_commit(thd) (ha_commit_trans((thd), &((thd)->transaction.all)))
#define ha_rollback(thd) (ha_rollback_trans((thd), &((thd)->transaction.all))) #define ha_rollback(thd) (ha_rollback_trans((thd), &((thd)->transaction.all)))
#define ha_supports_generate(T) (T != DB_TYPE_INNODB)
handler *get_new_handler(TABLE *table, enum db_type db_type); handler *get_new_handler(TABLE *table, enum db_type db_type);
my_off_t ha_get_ptr(byte *ptr, uint pack_length); my_off_t ha_get_ptr(byte *ptr, uint pack_length);
void ha_store_ptr(byte *buff, uint pack_length, my_off_t pos); void ha_store_ptr(byte *buff, uint pack_length, my_off_t pos);
......
...@@ -370,6 +370,36 @@ static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count, ...@@ -370,6 +370,36 @@ static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count,
** This is used when we need total access to a closed, not open table ** This is used when we need total access to a closed, not open table
*****************************************************************************/ *****************************************************************************/
/*
Lock and wait for the named lock.
Returns 0 on ok
*/
int lock_and_wait_for_table_name(THD *thd, TABLE_LIST *table_list)
{
int lock_retcode;
int error= -1;
DBUG_ENTER("lock_and_wait_for_table_name");
if (wait_if_global_read_lock(thd,0))
DBUG_RETURN(1);
VOID(pthread_mutex_lock(&LOCK_open));
if ((lock_retcode = lock_table_name(thd, table_list)) < 0)
goto end;
if (lock_retcode && wait_for_locked_table_names(thd, table_list))
{
unlock_table_name(thd, table_list);
goto end;
}
error=0;
end:
start_waiting_global_read_lock(thd);
pthread_mutex_unlock(&LOCK_open);
DBUG_RETURN(error);
}
/* /*
Put a not open table with an old refresh version in the table cache. Put a not open table with an old refresh version in the table cache.
This will force any other threads that uses the table to release it This will force any other threads that uses the table to release it
...@@ -381,7 +411,6 @@ static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count, ...@@ -381,7 +411,6 @@ static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count,
> 0 table locked, but someone is using it > 0 table locked, but someone is using it
*/ */
int lock_table_name(THD *thd, TABLE_LIST *table_list) int lock_table_name(THD *thd, TABLE_LIST *table_list)
{ {
TABLE *table; TABLE *table;
......
...@@ -237,6 +237,8 @@ inline THD *_current_thd(void) ...@@ -237,6 +237,8 @@ inline THD *_current_thd(void)
int mysql_create_db(THD *thd, char *db, uint create_info); int mysql_create_db(THD *thd, char *db, uint create_info);
void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags); void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags);
int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists); int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists);
int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
bool log_query);
int quick_rm_table(enum db_type base,const char *db, int quick_rm_table(enum db_type base,const char *db,
const char *table_name); const char *table_name);
bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list); bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list);
...@@ -268,10 +270,6 @@ bool check_access(THD *thd,uint access,const char *db=0,uint *save_priv=0, ...@@ -268,10 +270,6 @@ bool check_access(THD *thd,uint access,const char *db=0,uint *save_priv=0,
bool check_table_access(THD *thd,uint want_access, TABLE_LIST *tables); bool check_table_access(THD *thd,uint want_access, TABLE_LIST *tables);
bool check_process_priv(THD *thd=0); bool check_process_priv(THD *thd=0);
int generate_table(THD *thd, TABLE_LIST *table_list,
TABLE *locked_table);
int mysql_backup_table(THD* thd, TABLE_LIST* table_list); int mysql_backup_table(THD* thd, TABLE_LIST* table_list);
int mysql_restore_table(THD* thd, TABLE_LIST* table_list); int mysql_restore_table(THD* thd, TABLE_LIST* table_list);
...@@ -364,6 +362,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table,List<Item> &fields, ...@@ -364,6 +362,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table,List<Item> &fields,
void kill_delayed_threads(void); void kill_delayed_threads(void);
int mysql_delete(THD *thd, TABLE_LIST *table, COND *conds, ORDER *order, int mysql_delete(THD *thd, TABLE_LIST *table, COND *conds, ORDER *order,
ha_rows rows, thr_lock_type lock_type, ulong options); ha_rows rows, thr_lock_type lock_type, ulong options);
int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok=0);
TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update); TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update);
TABLE *open_table(THD *thd,const char *db,const char *table,const char *alias, TABLE *open_table(THD *thd,const char *db,const char *table,const char *alias,
bool *refresh); bool *refresh);
...@@ -592,6 +591,7 @@ bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh); ...@@ -592,6 +591,7 @@ bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh);
void start_waiting_global_read_lock(THD *thd); void start_waiting_global_read_lock(THD *thd);
/* Lock based on name */ /* Lock based on name */
int lock_and_wait_for_table_name(THD *thd, TABLE_LIST *table_list);
int lock_table_name(THD *thd, TABLE_LIST *table_list); int lock_table_name(THD *thd, TABLE_LIST *table_list);
void unlock_table_name(THD *thd, TABLE_LIST *table_list); void unlock_table_name(THD *thd, TABLE_LIST *table_list);
bool wait_for_locked_table_names(THD *thd, TABLE_LIST *table_list); bool wait_for_locked_table_names(THD *thd, TABLE_LIST *table_list);
......
...@@ -25,7 +25,8 @@ ...@@ -25,7 +25,8 @@
#include <direct.h> #include <direct.h>
#endif #endif
static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *path, static long mysql_rm_known_files(THD *thd, MY_DIR *dirp,
const char *db, const char *path,
uint level); uint level);
/* db-name is already validated when we come here */ /* db-name is already validated when we come here */
...@@ -121,17 +122,20 @@ int mysql_create_db(THD *thd, char *db, uint create_options) ...@@ -121,17 +122,20 @@ int mysql_create_db(THD *thd, char *db, uint create_options)
DBUG_RETURN(error); DBUG_RETURN(error);
} }
const char *del_exts[]= const char *del_exts[]= {".frm", ".BAK", NullS};
{".frm",".ISM",".ISD",".ISM",".HSH",".DAT",".MRG",".MYI",".MYD", ".db", ".BAK", NullS};
static TYPELIB deletable_extentions= static TYPELIB deletable_extentions=
{array_elements(del_exts)-1,"del_exts", del_exts}; {array_elements(del_exts)-1,"del_exts", del_exts};
/* db-name is already validated when we come here */ /*
/* If thd == 0, do not write any messages Drop all tables in a database.
This is useful in replication when we want to remove
a stale database before replacing it with the new one db-name is already validated when we come here
If thd == 0, do not write any messages; This is useful in replication
when we want to remove a stale database before replacing it with the new one
*/ */
int mysql_rm_db(THD *thd,char *db,bool if_exists) int mysql_rm_db(THD *thd,char *db,bool if_exists)
{ {
long deleted=0; long deleted=0;
...@@ -144,31 +148,15 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists) ...@@ -144,31 +148,15 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists)
VOID(pthread_mutex_lock(&LOCK_open)); VOID(pthread_mutex_lock(&LOCK_open));
// do not drop database if another thread is holding read lock // do not drop database if another thread is holding read lock
if (global_read_lock) if (wait_if_global_read_lock(thd,0))
{ goto exit;
if (thd->global_read_lock)
{
net_printf(&thd->net, ER_DROP_DB_WITH_READ_LOCK);
goto exit;
}
while (global_read_lock && ! thd->killed)
{
(void) pthread_cond_wait(&COND_refresh,&LOCK_open);
}
if (thd->killed)
{
net_printf(&thd->net, ER_SERVER_SHUTDOWN);
goto exit;
}
}
(void) sprintf(path,"%s/%s",mysql_data_home,db); (void) sprintf(path,"%s/%s",mysql_data_home,db);
unpack_dirname(path,path); // Convert if not unix unpack_dirname(path,path); // Convert if not unix
/* See if the directory exists */ /* See if the directory exists */
if (!(dirp = my_dir(path,MYF(MY_WME | MY_DONT_SORT)))) if (!(dirp = my_dir(path,MYF(MY_WME | MY_DONT_SORT))))
{ {
if(thd) if (thd)
{ {
if (!if_exists) if (!if_exists)
net_printf(&thd->net,ER_DB_DROP_EXISTS,db); net_printf(&thd->net,ER_DB_DROP_EXISTS,db);
...@@ -180,7 +168,8 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists) ...@@ -180,7 +168,8 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists)
} }
remove_db_from_cache(db); remove_db_from_cache(db);
if ((deleted=mysql_rm_known_files(thd, dirp, path,0)) >= 0 && thd) error = -1;
if ((deleted=mysql_rm_known_files(thd, dirp, db, path,0)) >= 0 && thd)
{ {
if (!thd->query) if (!thd->query)
{ {
...@@ -206,27 +195,31 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists) ...@@ -206,27 +195,31 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists)
exit: exit:
VOID(pthread_mutex_unlock(&LOCK_open)); VOID(pthread_mutex_unlock(&LOCK_open));
VOID(pthread_mutex_unlock(&LOCK_mysql_create_db)); VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));
start_waiting_global_read_lock(thd);
DBUG_RETURN(error); DBUG_RETURN(error);
} }
/* /*
Removes files with known extensions plus all found subdirectories that Removes files with known extensions plus all found subdirectories that
are 2 digits (raid directories). are 2 digits (raid directories).
thd MUST be set when calling this function!
*/ */
/* This one also needs to work with thd == 0 for replication */ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db,
static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *org_path, const char *org_path, uint level)
uint level)
{ {
long deleted=0; long deleted=0;
ulong found_other_files=0; ulong found_other_files=0;
char filePath[FN_REFLEN]; char filePath[FN_REFLEN];
TABLE_LIST *tot_list=0, **tot_list_next;
DBUG_ENTER("mysql_rm_known_files"); DBUG_ENTER("mysql_rm_known_files");
DBUG_PRINT("enter",("path: %s", org_path)); DBUG_PRINT("enter",("path: %s", org_path));
/* remove all files with known extensions */
tot_list_next= &tot_list;
for (uint idx=2 ; for (uint idx=2 ;
idx < (uint) dirp->number_off_files && (!thd || !thd->killed) ; idx < (uint) dirp->number_off_files && !thd->killed ;
idx++) idx++)
{ {
FILEINFO *file=dirp->dir_entry+idx; FILEINFO *file=dirp->dir_entry+idx;
...@@ -243,7 +236,7 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *org_path, ...@@ -243,7 +236,7 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *org_path,
if ((new_dirp = my_dir(newpath,MYF(MY_DONT_SORT)))) if ((new_dirp = my_dir(newpath,MYF(MY_DONT_SORT))))
{ {
DBUG_PRINT("my",("New subdir found: %s", newpath)); DBUG_PRINT("my",("New subdir found: %s", newpath));
if ((mysql_rm_known_files(thd,new_dirp,newpath,1)) < 0) if ((mysql_rm_known_files(thd, new_dirp, NullS, newpath,1)) < 0)
{ {
my_dirend(dirp); my_dirend(dirp);
DBUG_RETURN(-1); DBUG_RETURN(-1);
...@@ -257,24 +250,39 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *org_path, ...@@ -257,24 +250,39 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *org_path,
continue; continue;
} }
strxmov(filePath,org_path,"/",file->name,NullS); strxmov(filePath,org_path,"/",file->name,NullS);
unpack_filename(filePath,filePath); if (db && !strcasecmp(fn_ext(file->name), reg_ext))
if (my_delete_with_symlink(filePath,MYF(MY_WME)))
{ {
if(thd) /* Drop the table nicely */
net_printf(&thd->net,ER_DB_DROP_DELETE,filePath,my_error); *fn_ext(file->name)=0; // Remove extension
my_dirend(dirp); TABLE_LIST *table_list=(TABLE_LIST*)
DBUG_RETURN(-1); thd->calloc(sizeof(*table_list)+ strlen(db)+strlen(file->name)+1);
if (!table_list)
{
my_dirend(dirp);
DBUG_RETURN(-1);
}
table_list->db= (char*) (table_list+1);
strmov(table_list->real_name=strmov(table_list->db,db)+1,
file->name);
/* Link into list */
(*tot_list_next)= table_list;
tot_list_next= &table_list->next;
} }
deleted++; else
} {
if (my_delete_with_symlink(filePath,MYF(MY_WME)))
{
my_dirend(dirp);
DBUG_RETURN(-1);
}
deleted++;
}
}
my_dirend(dirp); my_dirend(dirp);
if (thd && thd->killed) if (thd->killed || (tot_list && mysql_rm_table_part2(thd, tot_list, 1, 1)))
{
send_error(&thd->net,ER_SERVER_SHUTDOWN);
DBUG_RETURN(-1); DBUG_RETURN(-1);
}
/* /*
If the directory is a symbolic link, remove the link first, then If the directory is a symbolic link, remove the link first, then
...@@ -294,22 +302,19 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *org_path, ...@@ -294,22 +302,19 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *org_path,
/* Don't give errors if we can't delete 'RAID' directory */ /* Don't give errors if we can't delete 'RAID' directory */
if (level) if (level)
DBUG_RETURN(deleted); DBUG_RETURN(deleted);
if(thd)
send_error(&thd->net);
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
path=filePath; path=filePath;
} }
#endif #endif
/* Remove last FN_LIBCHAR to not cause a probelm on OS/2 */ /* Remove last FN_LIBCHAR to not cause a problem on OS/2 */
char *pos=strend(path); char *pos=strend(path);
if (pos > path && pos[-1] == FN_LIBCHAR) if (pos > path && pos[-1] == FN_LIBCHAR)
*--pos=0; *--pos=0;
/* Don't give errors if we can't delete 'RAID' directory */ /* Don't give errors if we can't delete 'RAID' directory */
if (rmdir(path) < 0 && !level) if (rmdir(path) < 0 && !level)
{ {
if(thd) my_error(ER_DB_DROP_RMDIR, MYF(0), path, errno);
net_printf(&thd->net,ER_DB_DROP_RMDIR, path,errno);
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
} }
......
...@@ -15,113 +15,28 @@ ...@@ -15,113 +15,28 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* Delete of records */
/* Multi-table deletes were introduced by Monty and Sinisa */
#include "mysql_priv.h"
#include "ha_innobase.h"
#include "sql_select.h"
/* /*
Optimize delete of all rows by doing a full generate of the table Delete of records and truncate of tables.
This will work even if the .ISM and .ISD tables are destroyed
Multi-table deletes were introduced by Monty and Sinisa
*/ */
int generate_table(THD *thd, TABLE_LIST *table_list, TABLE *locked_table)
{
char path[FN_REFLEN];
int error;
TABLE **table_ptr;
DBUG_ENTER("generate_table");
if (wait_if_global_read_lock(thd,0))
DBUG_RETURN(1);
thd->proc_info="generate_table";
/* If it is a temporary table, close and regenerate it */
if ((table_ptr=find_temporary_table(thd,table_list->db,
table_list->real_name)))
{
TABLE *table= *table_ptr;
HA_CREATE_INFO create_info;
table->file->info(HA_STATUS_AUTO | HA_STATUS_NO_LOCK);
bzero((char*) &create_info,sizeof(create_info));
create_info.auto_increment_value= table->file->auto_increment_value;
db_type table_type=table->db_type;
strmov(path,table->path);
*table_ptr= table->next; // Unlink table from list
close_temporary(table,0);
*fn_ext(path)=0; // Remove the .frm extension
ha_create_table(path, &create_info,1);
if ((error= (int) !(open_temporary_table(thd, path, table_list->db,
table_list->real_name, 1))))
{
(void) rm_temporary_table(table_type, path);
}
}
else
{
(void) sprintf(path,"%s/%s/%s%s",mysql_data_home,table_list->db,
table_list->real_name,reg_ext);
fn_format(path,path,"","",4);
VOID(pthread_mutex_lock(&LOCK_open));
if (locked_table)
mysql_lock_abort(thd,locked_table); // end threads waiting on lock
// close all copies in use
if (remove_table_from_cache(thd,table_list->db,table_list->real_name))
{
if (!locked_table)
{
VOID(pthread_mutex_unlock(&LOCK_open));
start_waiting_global_read_lock(thd);
DBUG_RETURN(1); // We must get a lock on table
}
}
if (locked_table)
locked_table->file->extra(HA_EXTRA_FORCE_REOPEN);
if (thd->locked_tables)
close_data_tables(thd,table_list->db,table_list->real_name);
else
close_thread_tables(thd,1);
HA_CREATE_INFO create_info;
bzero((char*) &create_info,sizeof(create_info));
*fn_ext(path)=0; // Remove the .frm extension
error= ha_create_table(path,&create_info,1) ? -1 : 0;
if (thd->locked_tables && reopen_tables(thd,1,0))
error= -1;
VOID(pthread_mutex_unlock(&LOCK_open));
}
if (!error)
{
mysql_update_log.write(thd,thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
Query_log_event qinfo(thd, thd->query);
mysql_bin_log.write(&qinfo);
}
send_ok(&thd->net); // This should return record count
}
start_waiting_global_read_lock(thd);
DBUG_RETURN(error ? -1 : 0);
}
#include "mysql_priv.h"
#include "ha_innobase.h"
#include "sql_select.h"
int mysql_delete(THD *thd, int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
TABLE_LIST *table_list, ha_rows limit, thr_lock_type lock_type, ulong options)
COND *conds,
ORDER *order,
ha_rows limit,
thr_lock_type lock_type,
ulong options)
{ {
int error; int error;
TABLE *table; TABLE *table;
SQL_SELECT *select; SQL_SELECT *select=0;
READ_RECORD info; READ_RECORD info;
bool using_limit=limit != HA_POS_ERROR; bool using_limit=limit != HA_POS_ERROR;
bool use_generate_table,using_transactions; bool using_transactions;
ha_rows deleted;
DBUG_ENTER("mysql_delete"); DBUG_ENTER("mysql_delete");
if (!table_list->db) if (!table_list->db)
...@@ -132,34 +47,33 @@ int mysql_delete(THD *thd, ...@@ -132,34 +47,33 @@ int mysql_delete(THD *thd,
DBUG_RETURN(1); DBUG_RETURN(1);
} }
use_generate_table= (!using_limit && !conds && if (!(table = open_ltable(thd,table_list, lock_type)))
!(specialflag &
(SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE)) &&
!(thd->options &
(OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN)));
#ifdef HAVE_INNOBASE_DB
/* We need to add code to not generate table based on the table type */
if (!innodb_skip)
use_generate_table=0; // Innobase can't use re-generate table
#endif
if (use_generate_table && ! thd->open_tables)
{
error=generate_table(thd,table_list,(TABLE*) 0);
if (error <= 0)
DBUG_RETURN(error); // Error or ok
}
if (!(table = open_ltable(thd,table_list,
limit != HA_POS_ERROR ? TL_WRITE_LOW_PRIORITY :
lock_type)))
DBUG_RETURN(-1); DBUG_RETURN(-1);
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
thd->proc_info="init"; thd->proc_info="init";
if (use_generate_table)
DBUG_RETURN(generate_table(thd,table_list,table));
table->map=1; table->map=1;
if (setup_conds(thd,table_list,&conds)) if (setup_conds(thd,table_list,&conds))
DBUG_RETURN(-1); DBUG_RETURN(-1);
/* Test if the user wants to delete all rows */
if (!using_limit && (!conds || conds->const_item()) &&
!(specialflag & (SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE)))
{
deleted= table->file->records;
if (!(error=table->file->delete_all_rows()))
{
error= -1; // ok
goto cleanup;
}
if (error != HA_ERR_WRONG_COMMAND)
{
table->file->print_error(error,MYF(0));
error=0;
goto cleanup;
}
/* Handler didn't support fast delete; Delete rows one by one */
}
table->used_keys=table->quick_keys=0; // Can't use 'only index' table->used_keys=table->quick_keys=0; // Can't use 'only index'
select=make_select(table,0,0,conds,&error); select=make_select(table,0,0,conds,&error);
if (error) if (error)
...@@ -215,7 +129,7 @@ int mysql_delete(THD *thd, ...@@ -215,7 +129,7 @@ int mysql_delete(THD *thd,
} }
init_read_record(&info,thd,table,select,1,1); init_read_record(&info,thd,table,select,1,1);
ulong deleted=0L; deleted=0L;
thd->proc_info="updating"; thd->proc_info="updating";
while (!(error=info.read_record(&info)) && !thd->killed) while (!(error=info.read_record(&info)) && !thd->killed)
{ {
...@@ -244,6 +158,8 @@ int mysql_delete(THD *thd, ...@@ -244,6 +158,8 @@ int mysql_delete(THD *thd,
(void) table->file->extra(HA_EXTRA_READCHECK); (void) table->file->extra(HA_EXTRA_READCHECK);
if (options & OPTION_QUICK) if (options & OPTION_QUICK)
(void) table->file->extra(HA_EXTRA_NORMAL); (void) table->file->extra(HA_EXTRA_NORMAL);
cleanup:
using_transactions=table->file->has_transactions(); using_transactions=table->file->has_transactions();
if (deleted && (error <= 0 || !using_transactions)) if (deleted && (error <= 0 || !using_transactions))
{ {
...@@ -555,3 +471,90 @@ bool multi_delete::send_eof() ...@@ -555,3 +471,90 @@ bool multi_delete::send_eof()
::send_ok(&thd->net,deleted); ::send_ok(&thd->net,deleted);
return 0; return 0;
} }
/***************************************************************************
* TRUNCATE TABLE
****************************************************************************/
/*
Optimize delete of all rows by doing a full generate of the table
This will work even if the .ISM and .ISD tables are destroyed
dont_send_ok should be set if:
- We should always wants to generate the table (even if the table type
normally can't safely do this.
- We don't want an ok to be sent to the end user.
- We don't want to log the truncate command
*/
int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
{
HA_CREATE_INFO create_info;
char path[FN_REFLEN];
TABLE **table_ptr;
int error;
DBUG_ENTER("mysql_truncate");
/* If it is a temporary table, close and regenerate it */
if ((table_ptr=find_temporary_table(thd,table_list->db,
table_list->real_name)))
{
TABLE *table= *table_ptr;
HA_CREATE_INFO create_info;
table->file->info(HA_STATUS_AUTO | HA_STATUS_NO_LOCK);
bzero((char*) &create_info,sizeof(create_info));
create_info.auto_increment_value= table->file->auto_increment_value;
db_type table_type=table->db_type;
strmov(path,table->path);
*table_ptr= table->next; // Unlink table from list
close_temporary(table,0);
*fn_ext(path)=0; // Remove the .frm extension
ha_create_table(path, &create_info,1);
if ((error= (int) !(open_temporary_table(thd, path, table_list->db,
table_list->real_name, 1))))
(void) rm_temporary_table(table_type, path);
DBUG_RETURN(error ? -1 : 0);
}
(void) sprintf(path,"%s/%s/%s%s",mysql_data_home,table_list->db,
table_list->real_name,reg_ext);
fn_format(path,path,"","",4);
if (!dont_send_ok)
{
db_type table_type;
if ((table_type=get_table_type(path)) == DB_TYPE_UNKNOWN)
{
my_error(ER_NO_SUCH_TABLE, MYF(0), table_list->real_name);
DBUG_RETURN(-1);
}
if (!ha_supports_generate(table_type))
{
/* Probably InnoDB table */
DBUG_RETURN(mysql_delete(thd,table_list, (COND*) 0, (ORDER*) 0,
(ha_rows) 0, TL_WRITE, 0));
}
if (lock_and_wait_for_table_name(thd, table_list))
DBUG_RETURN(-1);
}
bzero((char*) &create_info,sizeof(create_info));
*fn_ext(path)=0; // Remove the .frm extension
error= ha_create_table(path,&create_info,1) ? -1 : 0;
VOID(pthread_mutex_unlock(&LOCK_open));
if (!error && !dont_send_ok)
{
mysql_update_log.write(thd,thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
Query_log_event qinfo(thd, thd->query);
mysql_bin_log.write(&qinfo);
}
send_ok(&thd->net); // This should return record count
}
unlock_table_name(thd, table_list);
DBUG_RETURN(error ? -1 : 0);
}
...@@ -103,7 +103,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields, ...@@ -103,7 +103,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
int error; int error;
bool log_on= ((thd->options & OPTION_UPDATE_LOG) || bool log_on= ((thd->options & OPTION_UPDATE_LOG) ||
!(thd->master_access & PROCESS_ACL)); !(thd->master_access & PROCESS_ACL));
bool using_transactions; bool using_transactions, bulk_insert=0;
uint value_count; uint value_count;
uint save_time_stamp; uint save_time_stamp;
ulong counter = 1; ulong counter = 1;
...@@ -193,6 +193,14 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields, ...@@ -193,6 +193,14 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
thd->proc_info="update"; thd->proc_info="update";
if (duplic == DUP_IGNORE || duplic == DUP_REPLACE) if (duplic == DUP_IGNORE || duplic == DUP_REPLACE)
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
if ((bulk_insert= (values_list.elements > 1 &&
lock_type != TL_WRITE_DELAYED &&
!(specialflag & SPECIAL_SAFE_MODE))))
{
table->file->extra(HA_EXTRA_WRITE_CACHE);
table->file->extra(HA_EXTRA_BULK_INSERT_BEGIN);
}
while ((values = its++)) while ((values = its++))
{ {
if (fields.elements || !value_count) if (fields.elements || !value_count)
...@@ -257,6 +265,25 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields, ...@@ -257,6 +265,25 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
} }
else else
{ {
if (bulk_insert)
{
if (table->file->extra(HA_EXTRA_NO_CACHE))
{
if (!error)
{
table->file->print_error(my_errno,MYF(0));
error=1;
}
}
if (table->file->extra(HA_EXTRA_BULK_INSERT_END))
{
if (!error)
{
table->file->print_error(my_errno,MYF(0));
error=1;
}
}
}
if (id && values_list.elements != 1) if (id && values_list.elements != 1)
thd->insert_id(id); // For update log thd->insert_id(id); // For update log
else if (table->next_number_field) else if (table->next_number_field)
...@@ -289,7 +316,6 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields, ...@@ -289,7 +316,6 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
thd->next_insert_id=0; // Reset this if wrongly used thd->next_insert_id=0; // Reset this if wrongly used
if (duplic == DUP_IGNORE || duplic == DUP_REPLACE) if (duplic == DUP_IGNORE || duplic == DUP_REPLACE)
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
if (error) if (error)
goto abort; goto abort;
......
...@@ -243,6 +243,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, ...@@ -243,6 +243,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
table->time_stamp=0; table->time_stamp=0;
table->next_number_field=table->found_next_number_field; table->next_number_field=table->found_next_number_field;
VOID(table->file->extra(HA_EXTRA_WRITE_CACHE)); VOID(table->file->extra(HA_EXTRA_WRITE_CACHE));
VOID(table->file->extra(HA_EXTRA_BULK_INSERT_BEGIN));
if (handle_duplicates == DUP_IGNORE || if (handle_duplicates == DUP_IGNORE ||
handle_duplicates == DUP_REPLACE) handle_duplicates == DUP_REPLACE)
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
...@@ -252,9 +253,10 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, ...@@ -252,9 +253,10 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
error=read_fixed_length(thd,info,table,fields,read_info); error=read_fixed_length(thd,info,table,fields,read_info);
else else
error=read_sep_field(thd,info,table,fields,read_info,*enclosed); error=read_sep_field(thd,info,table,fields,read_info,*enclosed);
if (table->file->extra(HA_EXTRA_NO_CACHE) || if (table->file->extra(HA_EXTRA_NO_CACHE))
table->file->activate_all_index(thd)) error=1; /* purecov: inspected */
error=1; /* purecov: inspected */ if (table->file->activate_all_index(thd))
error=1; /* purecov: inspected */
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
table->time_stamp=save_time_stamp; table->time_stamp=save_time_stamp;
table->next_number_field=0; table->next_number_field=0;
......
...@@ -1619,9 +1619,19 @@ mysql_execute_command(void) ...@@ -1619,9 +1619,19 @@ mysql_execute_command(void)
break; break;
} }
case SQLCOM_TRUNCATE: case SQLCOM_TRUNCATE:
select_lex->where=0; if (check_access(thd,DELETE_ACL,tables->db,&tables->grant.privilege))
select_lex->select_limit=HA_POS_ERROR; goto error; /* purecov: inspected */
/* Fall through */ /*
Don't allow this within a transaction because we want to use
re-generate table
*/
if (thd->locked_tables || thd->active_transaction())
{
my_error(ER_LOCK_OR_ACTIVE_TRANSACTION,MYF(0));
goto error;
}
res=mysql_truncate(thd,tables);
break;
case SQLCOM_DELETE: case SQLCOM_DELETE:
{ {
if (check_access(thd,DELETE_ACL,tables->db,&tables->grant.privilege)) if (check_access(thd,DELETE_ACL,tables->db,&tables->grant.privilege))
...@@ -1958,9 +1968,13 @@ mysql_execute_command(void) ...@@ -1958,9 +1968,13 @@ mysql_execute_command(void)
net_printf(&thd->net,ER_WRONG_DB_NAME, lex->name); net_printf(&thd->net,ER_WRONG_DB_NAME, lex->name);
break; break;
} }
if (check_access(thd,DROP_ACL,lex->name,0,1) || if (check_access(thd,DROP_ACL,lex->name,0,1))
end_active_trans(thd))
break; break;
if (thd->locked_tables || thd->active_transaction())
{
my_error(ER_LOCK_OR_ACTIVE_TRANSACTION,MYF(0));
goto error;
}
mysql_rm_db(thd,lex->name,lex->drop_if_exists); mysql_rm_db(thd,lex->name,lex->drop_if_exists);
break; break;
} }
......
...@@ -547,7 +547,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds, ...@@ -547,7 +547,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
for (uint i_h = join.const_tables; i_h < join.tables; i_h++) for (uint i_h = join.const_tables; i_h < join.tables; i_h++)
{ {
TABLE* table_h = join.join_tab[i_h].table; TABLE* table_h = join.join_tab[i_h].table;
if (table_h->db_type == DB_TYPE_INNOBASE) if (table_h->db_type == DB_TYPE_INNODB)
table_h->file->extra(HA_EXTRA_DONT_USE_CURSOR_TO_UPDATE); table_h->file->extra(HA_EXTRA_DONT_USE_CURSOR_TO_UPDATE);
} }
} }
......
...@@ -43,12 +43,7 @@ static int copy_data_between_tables(TABLE *from,TABLE *to, ...@@ -43,12 +43,7 @@ static int copy_data_between_tables(TABLE *from,TABLE *to,
int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists) int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists)
{ {
char path[FN_REFLEN]; int error;
String wrong_tables;
bool some_tables_deleted=0;
uint error;
db_type table_type;
TABLE_LIST *table;
DBUG_ENTER("mysql_rm_table"); DBUG_ENTER("mysql_rm_table");
/* mark for close and remove all cached entries */ /* mark for close and remove all cached entries */
...@@ -74,7 +69,35 @@ int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists) ...@@ -74,7 +69,35 @@ int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists)
} }
} }
error=mysql_rm_table_part2(thd,tables,if_exists,0);
err:
VOID(pthread_cond_broadcast(&COND_refresh)); // Signal to refresh
pthread_mutex_unlock(&LOCK_open);
pthread_mutex_lock(&thd->mysys_var->mutex);
thd->mysys_var->current_mutex= 0;
thd->mysys_var->current_cond= 0;
pthread_mutex_unlock(&thd->mysys_var->mutex);
if (error)
DBUG_RETURN(-1);
send_ok(&thd->net);
DBUG_RETURN(0);
}
int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
bool dont_log_query)
{
TABLE_LIST *table;
char path[FN_REFLEN];
String wrong_tables;
db_type table_type;
int error;
bool some_tables_deleted=0;
DBUG_ENTER("mysql_rm_table_part2");
for (table=tables ; table ; table=table->next) for (table=tables ; table ; table=table->next)
{ {
char *db=table->db ? table->db : thd->db; char *db=table->db ? table->db : thd->db;
...@@ -137,7 +160,7 @@ int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists) ...@@ -137,7 +160,7 @@ int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists)
wrong_tables.append(String(table->real_name)); wrong_tables.append(String(table->real_name));
} }
} }
if (some_tables_deleted) if (some_tables_deleted && !dont_log_query)
{ {
mysql_update_log.write(thd, thd->query,thd->query_length); mysql_update_log.write(thd, thd->query,thd->query_length);
if (mysql_bin_log.is_open()) if (mysql_bin_log.is_open())
...@@ -148,24 +171,12 @@ int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists) ...@@ -148,24 +171,12 @@ int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists)
} }
error = 0; error = 0;
err:
VOID(pthread_cond_broadcast(&COND_refresh)); // Signal to refresh
pthread_mutex_unlock(&LOCK_open);
pthread_mutex_lock(&thd->mysys_var->mutex);
thd->mysys_var->current_mutex= 0;
thd->mysys_var->current_cond= 0;
pthread_mutex_unlock(&thd->mysys_var->mutex);
if (wrong_tables.length()) if (wrong_tables.length())
{ {
my_error(ER_BAD_TABLE_ERROR,MYF(0),wrong_tables.c_ptr()); my_error(ER_BAD_TABLE_ERROR,MYF(0),wrong_tables.c_ptr());
error=1; error=1;
} }
if(error) DBUG_RETURN(error);
DBUG_RETURN(-1);
send_ok(&thd->net);
DBUG_RETURN(0);
} }
...@@ -837,21 +848,8 @@ static int prepare_for_restore(THD* thd, TABLE_LIST* table) ...@@ -837,21 +848,8 @@ static int prepare_for_restore(THD* thd, TABLE_LIST* table)
sprintf(dst_path, "%s/%s/%s", mysql_real_data_home, db, table_name); sprintf(dst_path, "%s/%s/%s", mysql_real_data_home, db, table_name);
int lock_retcode; if (lock_and_wait_for_table_name(thd,table))
pthread_mutex_lock(&LOCK_open);
if ((lock_retcode = lock_table_name(thd, table)) < 0)
{
pthread_mutex_unlock(&LOCK_open);
DBUG_RETURN(-1);
}
if (lock_retcode && wait_for_locked_table_names(thd, table))
{
unlock_table_name(thd, table);
pthread_mutex_unlock(&LOCK_open);
DBUG_RETURN(-1); DBUG_RETURN(-1);
}
pthread_mutex_unlock(&LOCK_open);
if (my_copy(src_path, if (my_copy(src_path,
fn_format(dst_path, dst_path,"", fn_format(dst_path, dst_path,"",
...@@ -862,25 +860,18 @@ static int prepare_for_restore(THD* thd, TABLE_LIST* table) ...@@ -862,25 +860,18 @@ static int prepare_for_restore(THD* thd, TABLE_LIST* table)
DBUG_RETURN(send_check_errmsg(thd, table, "restore", DBUG_RETURN(send_check_errmsg(thd, table, "restore",
"Failed copying .frm file")); "Failed copying .frm file"));
} }
bool save_no_send_ok = thd->net.no_send_ok; if (mysql_truncate(thd, table, 1))
thd->net.no_send_ok = 1;
// generate table will try to send OK which messes up the output
// for the client
if (generate_table(thd, table, 0))
{ {
unlock_table_name(thd, table); unlock_table_name(thd, table);
thd->net.no_send_ok = save_no_send_ok;
DBUG_RETURN(send_check_errmsg(thd, table, "restore", DBUG_RETURN(send_check_errmsg(thd, table, "restore",
"Failed generating table from .frm file")); "Failed generating table from .frm file"));
} }
/* truncate has released name lock */
thd->net.no_send_ok = save_no_send_ok;
} }
DBUG_RETURN(0); DBUG_RETURN(0);
} }
static int mysql_admin_table(THD* thd, TABLE_LIST* tables, static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
HA_CHECK_OPT* check_opt, HA_CHECK_OPT* check_opt,
const char *operator_name, const char *operator_name,
......
...@@ -796,7 +796,7 @@ table_types: ...@@ -796,7 +796,7 @@ table_types:
| MERGE_SYM { $$= DB_TYPE_MRG_MYISAM; } | MERGE_SYM { $$= DB_TYPE_MRG_MYISAM; }
| HEAP_SYM { $$= DB_TYPE_HEAP; } | HEAP_SYM { $$= DB_TYPE_HEAP; }
| BERKELEY_DB_SYM { $$= DB_TYPE_BERKELEY_DB; } | BERKELEY_DB_SYM { $$= DB_TYPE_BERKELEY_DB; }
| INNOBASE_SYM { $$= DB_TYPE_INNOBASE; } | INNOBASE_SYM { $$= DB_TYPE_INNODB; }
| GEMINI_SYM { $$= DB_TYPE_GEMINI; } | GEMINI_SYM { $$= DB_TYPE_GEMINI; }
row_types: row_types:
......
...@@ -22,7 +22,9 @@ ...@@ -22,7 +22,9 @@
extern "C" { extern "C" {
void sql_alloc_error_handler(void) void sql_alloc_error_handler(void)
{ {
current_thd->fatal_error=1; /* purecov: inspected */ THD *thd=current_thd;
if (thd) // QQ; To be removed
thd->fatal_error=1; /* purecov: inspected */
sql_print_error(ER(ER_OUT_OF_RESOURCES)); sql_print_error(ER(ER_OUT_OF_RESOURCES));
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment