Commit 004f3990 authored by lars@mysql.com's avatar lars@mysql.com

Merge lthalmann@bk-internal.mysql.com:/home/bk/mysql-5.1-new

into  mysql.com:/users/lthalmann/bkroot/mysql-5.1-new
parents 2d3fcf26 0b30190c
...@@ -49,6 +49,8 @@ mysqlbinlog_SOURCES = mysqlbinlog.cc $(top_srcdir)/mysys/mf_tempdir.c \ ...@@ -49,6 +49,8 @@ mysqlbinlog_SOURCES = mysqlbinlog.cc $(top_srcdir)/mysys/mf_tempdir.c \
$(top_srcdir)/mysys/base64.c $(top_srcdir)/mysys/base64.c
mysqlbinlog_LDADD = $(LDADD) $(CXXLDFLAGS) mysqlbinlog_LDADD = $(LDADD) $(CXXLDFLAGS)
mysqlslap_LDADD = $(LDADD) $(CXXLDFLAGS) $(CLIENT_THREAD_LIBS) mysqlslap_LDADD = $(LDADD) $(CXXLDFLAGS) $(CLIENT_THREAD_LIBS)
mysqlimport_LDADD = $(LDADD) $(CXXLDFLAGS) $(CLIENT_THREAD_LIBS) \
$(top_builddir)/mysys/libmysys.a
mysqltestmanager_pwgen_SOURCES = mysqlmanager-pwgen.c mysqltestmanager_pwgen_SOURCES = mysqlmanager-pwgen.c
mysqltestmanagerc_SOURCES= mysqlmanagerc.c $(yassl_dummy_link_fix) mysqltestmanagerc_SOURCES= mysqlmanagerc.c $(yassl_dummy_link_fix)
mysqlcheck_SOURCES= mysqlcheck.c $(yassl_dummy_link_fix) mysqlcheck_SOURCES= mysqlcheck.c $(yassl_dummy_link_fix)
...@@ -57,7 +59,8 @@ mysqlslap_SOURCES= mysqlslap.c $(top_srcdir)/mysys/my_lock.c \ ...@@ -57,7 +59,8 @@ mysqlslap_SOURCES= mysqlslap.c $(top_srcdir)/mysys/my_lock.c \
$(top_srcdir)/mysys/my_alarm.c \ $(top_srcdir)/mysys/my_alarm.c \
$(yassl_dummy_link_fix) $(yassl_dummy_link_fix)
mysqldump_SOURCES= mysqldump.c my_user.c $(yassl_dummy_link_fix) mysqldump_SOURCES= mysqldump.c my_user.c $(yassl_dummy_link_fix)
mysqlimport_SOURCES= mysqlimport.c $(yassl_dummy_link_fix) mysqlimport_SOURCES= mysqlimport.c \
$(yassl_dummy_link_fix)
sql_src=log_event.h mysql_priv.h log_event.cc my_decimal.h my_decimal.cc sql_src=log_event.h mysql_priv.h log_event.cc my_decimal.h my_decimal.cc
strings_src=decimal.c strings_src=decimal.c
......
...@@ -54,6 +54,7 @@ enum options_client ...@@ -54,6 +54,7 @@ enum options_client
OPT_MYSQL_LOCK_DIRECTORY, OPT_MYSQL_LOCK_DIRECTORY,
OPT_MYSQL_SLAP_SLAVE, OPT_MYSQL_SLAP_SLAVE,
OPT_USE_THREADS, OPT_USE_THREADS,
OPT_IMPORT_USE_THREADS,
OPT_MYSQL_NUMBER_OF_QUERY, OPT_MYSQL_NUMBER_OF_QUERY,
OPT_MYSQL_PRESERVE_SCHEMA, OPT_MYSQL_PRESERVE_SCHEMA,
OPT_IGNORE_TABLE,OPT_INSERT_IGNORE,OPT_SHOW_WARNINGS,OPT_DROP_DATABASE, OPT_IGNORE_TABLE,OPT_INSERT_IGNORE,OPT_SHOW_WARNINGS,OPT_DROP_DATABASE,
......
...@@ -29,6 +29,12 @@ ...@@ -29,6 +29,12 @@
#include "client_priv.h" #include "client_priv.h"
#include "mysql_version.h" #include "mysql_version.h"
#include <my_pthread.h>
/* Global Thread counter */
int counter= 0;
pthread_mutex_t counter_mutex;
static void db_error_with_table(MYSQL *mysql, char *table); static void db_error_with_table(MYSQL *mysql, char *table);
static void db_error(MYSQL *mysql); static void db_error(MYSQL *mysql);
...@@ -39,6 +45,7 @@ static char *add_load_option(char *ptr,const char *object, ...@@ -39,6 +45,7 @@ static char *add_load_option(char *ptr,const char *object,
static my_bool verbose=0,lock_tables=0,ignore_errors=0,opt_delete=0, static my_bool verbose=0,lock_tables=0,ignore_errors=0,opt_delete=0,
replace=0,silent=0,ignore=0,opt_compress=0, replace=0,silent=0,ignore=0,opt_compress=0,
opt_low_priority= 0, tty_password= 0; opt_low_priority= 0, tty_password= 0;
static my_bool opt_use_threads= 0;
static uint opt_local_file=0; static uint opt_local_file=0;
static MYSQL mysql_connection; static MYSQL mysql_connection;
static char *opt_password=0, *current_user=0, static char *opt_password=0, *current_user=0,
...@@ -108,8 +115,9 @@ static struct my_option my_long_options[] = ...@@ -108,8 +115,9 @@ static struct my_option my_long_options[] =
REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"local", 'L', "Read all files through the client.", (gptr*) &opt_local_file, {"local", 'L', "Read all files through the client.", (gptr*) &opt_local_file,
(gptr*) &opt_local_file, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, (gptr*) &opt_local_file, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"lock-tables", 'l', "Lock all tables for write.", (gptr*) &lock_tables, {"lock-tables", 'l', "Lock all tables for write (this disables threads).",
(gptr*) &lock_tables, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, (gptr*) &lock_tables, (gptr*) &lock_tables, 0, GET_BOOL, NO_ARG,
0, 0, 0, 0, 0, 0},
{"low-priority", OPT_LOW_PRIORITY, {"low-priority", OPT_LOW_PRIORITY,
"Use LOW_PRIORITY when updating the table.", (gptr*) &opt_low_priority, "Use LOW_PRIORITY when updating the table.", (gptr*) &opt_low_priority,
(gptr*) &opt_low_priority, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, (gptr*) &opt_low_priority, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
...@@ -138,6 +146,11 @@ static struct my_option my_long_options[] = ...@@ -138,6 +146,11 @@ static struct my_option my_long_options[] =
(gptr*) &opt_mysql_unix_port, (gptr*) &opt_mysql_unix_port, 0, GET_STR, (gptr*) &opt_mysql_unix_port, (gptr*) &opt_mysql_unix_port, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
#include <sslopt-longopts.h> #include <sslopt-longopts.h>
{"use-threads", OPT_USE_THREADS,
"Parrelize the loading of files. Requires an arguement for the number \
threads to use for loading of data.",
(gptr*) &opt_use_threads, (gptr*) &opt_use_threads, 0,
GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
#ifndef DONT_ALLOW_USER_CHANGE #ifndef DONT_ALLOW_USER_CHANGE
{"user", 'u', "User for login if not current user.", (gptr*) &current_user, {"user", 'u', "User for login if not current user.", (gptr*) &current_user,
(gptr*) &current_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, (gptr*) &current_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
...@@ -287,7 +300,7 @@ static int write_to_table(char *filename, MYSQL *sock) ...@@ -287,7 +300,7 @@ static int write_to_table(char *filename, MYSQL *sock)
{ {
if (verbose) if (verbose)
fprintf(stdout, "Deleting the old data from table %s\n", tablename); fprintf(stdout, "Deleting the old data from table %s\n", tablename);
sprintf(sql_statement, "DELETE FROM %s", tablename); snprintf(sql_statement, FN_REFLEN*16+256, "DELETE FROM %s", tablename);
if (mysql_query(sock, sql_statement)) if (mysql_query(sock, sql_statement))
{ {
db_error_with_table(sock, tablename); db_error_with_table(sock, tablename);
...@@ -497,12 +510,41 @@ static char *field_escape(char *to,const char *from,uint length) ...@@ -497,12 +510,41 @@ static char *field_escape(char *to,const char *from,uint length)
} }
int
worker_thread(char *raw_table_name)
{
MYSQL *sock= 0;
if (!(sock= db_connect(current_host,current_db,current_user,opt_password)))
{
goto error;
}
if (mysql_query(sock, "set @@character_set_database=binary;"))
{
db_error(sock); /* We shall countinue here, if --force was given */
goto error;
}
/*
We should do something about the error
*/
write_to_table(raw_table_name, sock);
error:
if (sock)
db_disconnect(current_host, sock);
pthread_mutex_lock(&counter_mutex);
counter--;
pthread_mutex_unlock(&counter_mutex);
return 0;
}
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
int exitcode=0, error=0; int exitcode=0, error=0;
char **argv_to_free; char **argv_to_free;
MYSQL *sock=0;
MY_INIT(argv[0]); MY_INIT(argv[0]);
load_defaults("my",load_default_groups,&argc,&argv); load_defaults("my",load_default_groups,&argc,&argv);
...@@ -513,6 +555,59 @@ int main(int argc, char **argv) ...@@ -513,6 +555,59 @@ int main(int argc, char **argv)
free_defaults(argv_to_free); free_defaults(argv_to_free);
return(1); return(1);
} }
if (opt_use_threads && !lock_tables)
{
pthread_t mainthread; /* Thread descriptor */
pthread_attr_t attr; /* Thread attributes */
VOID(pthread_mutex_init(&counter_mutex, NULL));
for (; *argv != NULL; argv++) // Loop through tables
{
/*
If we hit thread count limit we loop until some threads exit.
We sleep for a second, so that we don't chew up a lot of
CPU in the loop.
*/
sanity_label:
if (counter == opt_use_threads)
{
sleep(1);
goto sanity_label;
}
pthread_mutex_lock(&counter_mutex);
counter++;
pthread_mutex_unlock(&counter_mutex);
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr,
PTHREAD_CREATE_DETACHED);
/* now create the thread */
if (pthread_create(&mainthread, &attr, (void *)worker_thread,
(void *)*argv) != 0)
{
pthread_mutex_lock(&counter_mutex);
counter--;
pthread_mutex_unlock(&counter_mutex);
fprintf(stderr,"%s: Could not create thread\n",
my_progname);
}
}
/*
We loop until we know that all children have cleaned up.
*/
loop_label:
if (counter)
{
sleep(1);
goto loop_label;
}
VOID(pthread_mutex_destroy(&counter_mutex));
}
else
{
MYSQL *sock= 0;
if (!(sock= db_connect(current_host,current_db,current_user,opt_password))) if (!(sock= db_connect(current_host,current_db,current_user,opt_password)))
{ {
free_defaults(argv_to_free); free_defaults(argv_to_free);
...@@ -532,6 +627,7 @@ int main(int argc, char **argv) ...@@ -532,6 +627,7 @@ int main(int argc, char **argv)
if (exitcode == 0) if (exitcode == 0)
exitcode = error; exitcode = error;
db_disconnect(current_host, sock); db_disconnect(current_host, sock);
}
my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR)); my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
#ifdef HAVE_SMEM #ifdef HAVE_SMEM
my_free(shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR)); my_free(shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
......
...@@ -2650,3 +2650,35 @@ DELIMITER ; ...@@ -2650,3 +2650,35 @@ DELIMITER ;
DROP TRIGGER tr1; DROP TRIGGER tr1;
DROP TABLE t1; DROP TABLE t1;
create table t1 (a text , b text);
create table t2 (a text , b text);
insert t1 values ("Duck, Duck", "goose");
insert t1 values ("Duck, Duck", "pidgeon");
insert t2 values ("We the people", "in order to perform");
insert t2 values ("a more perfect", "union");
select * from t1;
a b
Duck, Duck goose
Duck, Duck pidgeon
select * from t2;
a b
We the people in order to perform
a more perfect union
test.t1: Records: 2 Deleted: 0 Skipped: 0 Warnings: 0
test.t2: Records: 2 Deleted: 0 Skipped: 0 Warnings: 0
test.t1: Records: 2 Deleted: 0 Skipped: 0 Warnings: 0
test.t2: Records: 2 Deleted: 0 Skipped: 0 Warnings: 0
select * from t1;
a b
Duck, Duck goose
Duck, Duck pidgeon
Duck, Duck goose
Duck, Duck pidgeon
select * from t2;
a b
We the people in order to perform
a more perfect union
We the people in order to perform
a more perfect union
drop table t1;
drop table t2;
drop database if exists testdb1;
create database testdb1 default character set latin2;
use testdb1;
create table t1 (a int);
insert into t1 values (1),(2),(3);
show create database testdb1;
Database Create Database
testdb1 CREATE DATABASE `testdb1` /*!40100 DEFAULT CHARACTER SET latin2 */
show tables;
Tables_in_testdb1
t1
rename database testdb1 to testdb2;
show create database testdb1;
ERROR 42000: Unknown database 'testdb1'
show create database testdb2;
Database Create Database
testdb2 CREATE DATABASE `testdb2` /*!40100 DEFAULT CHARACTER SET latin2 */
select database();
database()
testdb2
show tables;
Tables_in_testdb2
t1
select a from t1 order by a;
a
1
2
3
drop database testdb2;
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
# #
############################################################################## ##############################################################################
archive : Change between azio and gzio is causing an issue
events : Test case instability - infinite locking. To be fixed. events : Test case instability - infinite locking. To be fixed.
func_group : Bug#15448 func_group : Bug#15448
func_math : Bug#15448 func_math : Bug#15448
......
...@@ -1048,3 +1048,27 @@ SET SQL_MODE = @old_sql_mode; ...@@ -1048,3 +1048,27 @@ SET SQL_MODE = @old_sql_mode;
DROP TRIGGER tr1; DROP TRIGGER tr1;
DROP TABLE t1; DROP TABLE t1;
#
# Added for use-thread option
#
create table t1 (a text , b text);
create table t2 (a text , b text);
insert t1 values ("Duck, Duck", "goose");
insert t1 values ("Duck, Duck", "pidgeon");
insert t2 values ("We the people", "in order to perform");
insert t2 values ("a more perfect", "union");
select * from t1;
select * from t2;
--exec $MYSQL_DUMP --tab=$MYSQLTEST_VARDIR/tmp/ test
--exec $MYSQL test < $MYSQLTEST_VARDIR/tmp/t1.sql
--exec $MYSQL test < $MYSQLTEST_VARDIR/tmp/t2.sql
# The first load tests the pausing code
--exec $MYSQL_IMPORT --use-threads=1 test $MYSQLTEST_VARDIR/tmp/t1.txt $MYSQLTEST_VARDIR/tmp/t2.txt
# Now we test with multiple threads!
--exec $MYSQL_IMPORT --use-threads=5 test $MYSQLTEST_VARDIR/tmp/t1.txt $MYSQLTEST_VARDIR/tmp/t2.txt
select * from t1;
select * from t2;
drop table t1;
drop table t2;
--disable_warnings
drop database if exists testdb1;
--enable_warnings
create database testdb1 default character set latin2;
use testdb1;
create table t1 (a int);
insert into t1 values (1),(2),(3);
show create database testdb1;
show tables;
rename database testdb1 to testdb2;
--error 1049
show create database testdb1;
show create database testdb2;
select database();
show tables;
select a from t1 order by a;
drop database testdb2;
...@@ -405,12 +405,14 @@ int ha_archive::write_meta_file(File meta_file, ha_rows rows, ...@@ -405,12 +405,14 @@ int ha_archive::write_meta_file(File meta_file, ha_rows rows,
See ha_example.cc for a longer description. See ha_example.cc for a longer description.
*/ */
ARCHIVE_SHARE *ha_archive::get_share(const char *table_name, TABLE *table) ARCHIVE_SHARE *ha_archive::get_share(const char *table_name,
TABLE *table, int *rc)
{ {
ARCHIVE_SHARE *share; ARCHIVE_SHARE *share;
char meta_file_name[FN_REFLEN]; char meta_file_name[FN_REFLEN];
uint length; uint length;
char *tmp_name; char *tmp_name;
DBUG_ENTER("ha_archive::get_share");
pthread_mutex_lock(&archive_mutex); pthread_mutex_lock(&archive_mutex);
length=(uint) strlen(table_name); length=(uint) strlen(table_name);
...@@ -425,7 +427,8 @@ ARCHIVE_SHARE *ha_archive::get_share(const char *table_name, TABLE *table) ...@@ -425,7 +427,8 @@ ARCHIVE_SHARE *ha_archive::get_share(const char *table_name, TABLE *table)
NullS)) NullS))
{ {
pthread_mutex_unlock(&archive_mutex); pthread_mutex_unlock(&archive_mutex);
return NULL; *rc= HA_ERR_OUT_OF_MEM;
DBUG_RETURN(NULL);
} }
share->use_count= 0; share->use_count= 0;
...@@ -468,9 +471,14 @@ ARCHIVE_SHARE *ha_archive::get_share(const char *table_name, TABLE *table) ...@@ -468,9 +471,14 @@ ARCHIVE_SHARE *ha_archive::get_share(const char *table_name, TABLE *table)
thr_lock_init(&share->lock); thr_lock_init(&share->lock);
} }
share->use_count++; share->use_count++;
DBUG_PRINT("info", ("archive table %.*s has %d open handles now",
share->table_name_length, share->table_name,
share->use_count));
if (share->crashed)
*rc= HA_ERR_CRASHED_ON_USAGE;
pthread_mutex_unlock(&archive_mutex); pthread_mutex_unlock(&archive_mutex);
return share; DBUG_RETURN(share);
} }
...@@ -481,12 +489,21 @@ ARCHIVE_SHARE *ha_archive::get_share(const char *table_name, TABLE *table) ...@@ -481,12 +489,21 @@ ARCHIVE_SHARE *ha_archive::get_share(const char *table_name, TABLE *table)
int ha_archive::free_share(ARCHIVE_SHARE *share) int ha_archive::free_share(ARCHIVE_SHARE *share)
{ {
int rc= 0; int rc= 0;
DBUG_ENTER("ha_archive::free_share");
DBUG_PRINT("info", ("archive table %.*s has %d open handles on entrance",
share->table_name_length, share->table_name,
share->use_count));
pthread_mutex_lock(&archive_mutex); pthread_mutex_lock(&archive_mutex);
if (!--share->use_count) if (!--share->use_count)
{ {
hash_delete(&archive_open_tables, (byte*) share); hash_delete(&archive_open_tables, (byte*) share);
thr_lock_delete(&share->lock); thr_lock_delete(&share->lock);
VOID(pthread_mutex_destroy(&share->mutex)); VOID(pthread_mutex_destroy(&share->mutex));
if (share->crashed)
(void)write_meta_file(share->meta_file, share->rows_recorded,
share->auto_increment_value, TRUE);
else
(void)write_meta_file(share->meta_file, share->rows_recorded, (void)write_meta_file(share->meta_file, share->rows_recorded,
share->auto_increment_value, FALSE); share->auto_increment_value, FALSE);
if (azclose(&(share->archive_write))) if (azclose(&(share->archive_write)))
...@@ -497,7 +514,7 @@ int ha_archive::free_share(ARCHIVE_SHARE *share) ...@@ -497,7 +514,7 @@ int ha_archive::free_share(ARCHIVE_SHARE *share)
} }
pthread_mutex_unlock(&archive_mutex); pthread_mutex_unlock(&archive_mutex);
return rc; DBUG_RETURN(rc);
} }
...@@ -524,10 +541,23 @@ const char **ha_archive::bas_ext() const ...@@ -524,10 +541,23 @@ const char **ha_archive::bas_ext() const
*/ */
int ha_archive::open(const char *name, int mode, uint open_options) int ha_archive::open(const char *name, int mode, uint open_options)
{ {
int rc= 0;
DBUG_ENTER("ha_archive::open"); DBUG_ENTER("ha_archive::open");
if (!(share= get_share(name, table))) DBUG_PRINT("info", ("archive table was opened for crash %s",
DBUG_RETURN(HA_ERR_OUT_OF_MEM); // Not handled well by calling code! (open_options & HA_OPEN_FOR_REPAIR) ? "yes" : "no"));
share= get_share(name, table, &rc);
if (rc == HA_ERR_CRASHED_ON_USAGE && !(open_options & HA_OPEN_FOR_REPAIR))
{
free_share(share);
DBUG_RETURN(rc);
}
else if (rc == HA_ERR_OUT_OF_MEM)
{
DBUG_RETURN(rc);
}
thr_lock_data_init(&share->lock,&lock,NULL); thr_lock_data_init(&share->lock,&lock,NULL);
if (!(azopen(&archive, share->data_file_name, O_RDONLY|O_BINARY))) if (!(azopen(&archive, share->data_file_name, O_RDONLY|O_BINARY)))
...@@ -537,10 +567,14 @@ int ha_archive::open(const char *name, int mode, uint open_options) ...@@ -537,10 +567,14 @@ int ha_archive::open(const char *name, int mode, uint open_options)
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE); DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
} }
if (open_options & HA_OPEN_FOR_REPAIR) DBUG_PRINT("info", ("archive table was crashed %s",
rc == HA_ERR_CRASHED_ON_USAGE ? "yes" : "no"));
if (rc == HA_ERR_CRASHED_ON_USAGE && open_options & HA_OPEN_FOR_REPAIR)
{
DBUG_RETURN(0); DBUG_RETURN(0);
}
DBUG_RETURN(share->crashed ? HA_ERR_CRASHED_ON_USAGE : 0); else
DBUG_RETURN(rc);
} }
...@@ -926,6 +960,7 @@ int ha_archive::rnd_init(bool scan) ...@@ -926,6 +960,7 @@ int ha_archive::rnd_init(bool scan)
if (scan) if (scan)
{ {
scan_rows= share->rows_recorded; scan_rows= share->rows_recorded;
DBUG_PRINT("info", ("archive will retrieve %llu rows", scan_rows));
records= 0; records= 0;
/* /*
...@@ -937,6 +972,7 @@ int ha_archive::rnd_init(bool scan) ...@@ -937,6 +972,7 @@ int ha_archive::rnd_init(bool scan)
pthread_mutex_lock(&share->mutex); pthread_mutex_lock(&share->mutex);
if (share->dirty == TRUE) if (share->dirty == TRUE)
{ {
DBUG_PRINT("info", ("archive flushing out rows for scan"));
azflush(&(share->archive_write), Z_SYNC_FLUSH); azflush(&(share->archive_write), Z_SYNC_FLUSH);
share->dirty= FALSE; share->dirty= FALSE;
} }
...@@ -1176,6 +1212,7 @@ int ha_archive::optimize(THD* thd, HA_CHECK_OPT* check_opt) ...@@ -1176,6 +1212,7 @@ int ha_archive::optimize(THD* thd, HA_CHECK_OPT* check_opt)
share->rows_recorded++; share->rows_recorded++;
} }
} }
DBUG_PRINT("info", ("recovered %llu archive rows", share->rows_recorded));
my_free((char*)buf, MYF(0)); my_free((char*)buf, MYF(0));
if (rc && rc != HA_ERR_END_OF_FILE) if (rc && rc != HA_ERR_END_OF_FILE)
...@@ -1200,10 +1237,24 @@ int ha_archive::optimize(THD* thd, HA_CHECK_OPT* check_opt) ...@@ -1200,10 +1237,24 @@ int ha_archive::optimize(THD* thd, HA_CHECK_OPT* check_opt)
azwrite(&writer, block, read); azwrite(&writer, block, read);
} }
azclose(&writer); azflush(&writer, Z_SYNC_FLUSH);
share->dirty= FALSE;
azclose(&(share->archive_write));
share->archive_write= writer;
my_rename(writer_filename,share->data_file_name,MYF(0)); my_rename(writer_filename,share->data_file_name,MYF(0));
/*
Now we need to reopen our read descriptor since it has changed.
*/
azclose(&archive);
if (!(azopen(&archive, share->data_file_name, O_RDONLY|O_BINARY)))
{
rc= HA_ERR_CRASHED_ON_USAGE;
goto error;
}
DBUG_RETURN(0); DBUG_RETURN(0);
error: error:
......
...@@ -101,7 +101,7 @@ class ha_archive: public handler ...@@ -101,7 +101,7 @@ class ha_archive: public handler
int read_meta_file(File meta_file, ha_rows *rows, ulonglong *auto_increment); int read_meta_file(File meta_file, ha_rows *rows, ulonglong *auto_increment);
int write_meta_file(File meta_file, ha_rows rows, int write_meta_file(File meta_file, ha_rows rows,
ulonglong auto_increment, bool dirty); ulonglong auto_increment, bool dirty);
ARCHIVE_SHARE *get_share(const char *table_name, TABLE *table); ARCHIVE_SHARE *get_share(const char *table_name, TABLE *table, int *rc);
int free_share(ARCHIVE_SHARE *share); int free_share(ARCHIVE_SHARE *share);
bool auto_repair() const { return 1; } // For the moment we just do this bool auto_repair() const { return 1; } // For the moment we just do this
int read_data_header(azio_stream *file_to_read); int read_data_header(azio_stream *file_to_read);
......
...@@ -611,6 +611,7 @@ void write_bin_log(THD *thd, bool clear_error, ...@@ -611,6 +611,7 @@ void write_bin_log(THD *thd, bool clear_error,
bool mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create, bool silent); bool mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create, bool silent);
bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create); bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create);
bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent); bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent);
bool mysql_rename_db(THD *thd, LEX_STRING *old_db, LEX_STRING *new_db);
void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos, ushort flags); void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos, ushort flags);
void mysql_client_binlog_statement(THD *thd); void mysql_client_binlog_statement(THD *thd);
bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists, bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
...@@ -623,7 +624,7 @@ int mysql_rm_table_part2_with_lock(THD *thd, TABLE_LIST *tables, ...@@ -623,7 +624,7 @@ int mysql_rm_table_part2_with_lock(THD *thd, TABLE_LIST *tables,
bool quick_rm_table(handlerton *base,const char *db, bool quick_rm_table(handlerton *base,const char *db,
const char *table_name); const char *table_name);
void close_cached_table(THD *thd, TABLE *table); void close_cached_table(THD *thd, TABLE *table);
bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list); bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent);
bool mysql_change_db(THD *thd,const char *name,bool no_access_check); bool mysql_change_db(THD *thd,const char *name,bool no_access_check);
void mysql_parse(THD *thd,char *inBuf,uint length); void mysql_parse(THD *thd,char *inBuf,uint length);
bool mysql_test_parse_for_slave(THD *thd,char *inBuf,uint length); bool mysql_test_parse_for_slave(THD *thd,char *inBuf,uint length);
...@@ -1228,10 +1229,12 @@ uint check_word(TYPELIB *lib, const char *val, const char *end, ...@@ -1228,10 +1229,12 @@ uint check_word(TYPELIB *lib, const char *val, const char *end,
bool is_keyword(const char *name, uint len); bool is_keyword(const char *name, uint len);
#define MY_DB_OPT_FILE "db.opt" #define MY_DB_OPT_FILE "db.opt"
bool my_database_names_init(void);
void my_database_names_free(void);
bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create); bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create);
bool my_dbopt_init(void);
void my_dbopt_cleanup(void); void my_dbopt_cleanup(void);
void my_dbopt_free(void); extern int creating_database; // How many database locks are made
extern int creating_table; // How many mysql_create_table() are running
/* /*
External variables External variables
...@@ -1333,7 +1336,7 @@ extern FILE *bootstrap_file; ...@@ -1333,7 +1336,7 @@ extern FILE *bootstrap_file;
extern int bootstrap_error; extern int bootstrap_error;
extern FILE *stderror_file; extern FILE *stderror_file;
extern pthread_key(MEM_ROOT**,THR_MALLOC); extern pthread_key(MEM_ROOT**,THR_MALLOC);
extern pthread_mutex_t LOCK_mysql_create_db,LOCK_Acl,LOCK_open, extern pthread_mutex_t LOCK_mysql_create_db,LOCK_Acl,LOCK_open, LOCK_lock_db,
LOCK_thread_count,LOCK_mapped_file,LOCK_user_locks, LOCK_status, LOCK_thread_count,LOCK_mapped_file,LOCK_user_locks, LOCK_status,
LOCK_error_log, LOCK_delayed_insert, LOCK_uuid_generator, LOCK_error_log, LOCK_delayed_insert, LOCK_uuid_generator,
LOCK_delayed_status, LOCK_delayed_create, LOCK_crypt, LOCK_timezone, LOCK_delayed_status, LOCK_delayed_create, LOCK_crypt, LOCK_timezone,
...@@ -1364,7 +1367,7 @@ extern const char *opt_date_time_formats[]; ...@@ -1364,7 +1367,7 @@ extern const char *opt_date_time_formats[];
extern KNOWN_DATE_TIME_FORMAT known_date_time_formats[]; extern KNOWN_DATE_TIME_FORMAT known_date_time_formats[];
extern String null_string; extern String null_string;
extern HASH open_cache; extern HASH open_cache, lock_db_cache;
extern TABLE *unused_tables; extern TABLE *unused_tables;
extern const char* any_db; extern const char* any_db;
extern struct my_option my_long_options[]; extern struct my_option my_long_options[];
......
...@@ -1170,7 +1170,7 @@ void clean_up(bool print_message) ...@@ -1170,7 +1170,7 @@ void clean_up(bool print_message)
bitmap_free(&slave_error_mask); bitmap_free(&slave_error_mask);
#endif #endif
my_tz_free(); my_tz_free();
my_dbopt_free(); my_database_names_free();
#ifndef NO_EMBEDDED_ACCESS_CHECKS #ifndef NO_EMBEDDED_ACCESS_CHECKS
acl_free(1); acl_free(1);
grant_free(); grant_free();
...@@ -1283,6 +1283,7 @@ static void wait_for_signal_thread_to_end() ...@@ -1283,6 +1283,7 @@ static void wait_for_signal_thread_to_end()
static void clean_up_mutexes() static void clean_up_mutexes()
{ {
(void) pthread_mutex_destroy(&LOCK_mysql_create_db); (void) pthread_mutex_destroy(&LOCK_mysql_create_db);
(void) pthread_mutex_destroy(&LOCK_lock_db);
(void) pthread_mutex_destroy(&LOCK_Acl); (void) pthread_mutex_destroy(&LOCK_Acl);
(void) rwlock_destroy(&LOCK_grant); (void) rwlock_destroy(&LOCK_grant);
(void) pthread_mutex_destroy(&LOCK_open); (void) pthread_mutex_destroy(&LOCK_open);
...@@ -2838,7 +2839,7 @@ static int init_common_variables(const char *conf_file_name, int argc, ...@@ -2838,7 +2839,7 @@ static int init_common_variables(const char *conf_file_name, int argc,
if (use_temp_pool && bitmap_init(&temp_pool,0,1024,1)) if (use_temp_pool && bitmap_init(&temp_pool,0,1024,1))
return 1; return 1;
if (my_dbopt_init()) if (my_database_names_init())
return 1; return 1;
/* /*
...@@ -2892,6 +2893,7 @@ You should consider changing lower_case_table_names to 1 or 2", ...@@ -2892,6 +2893,7 @@ You should consider changing lower_case_table_names to 1 or 2",
static int init_thread_environment() static int init_thread_environment()
{ {
(void) pthread_mutex_init(&LOCK_mysql_create_db,MY_MUTEX_INIT_SLOW); (void) pthread_mutex_init(&LOCK_mysql_create_db,MY_MUTEX_INIT_SLOW);
(void) pthread_mutex_init(&LOCK_lock_db,MY_MUTEX_INIT_SLOW);
(void) pthread_mutex_init(&LOCK_Acl,MY_MUTEX_INIT_SLOW); (void) pthread_mutex_init(&LOCK_Acl,MY_MUTEX_INIT_SLOW);
(void) pthread_mutex_init(&LOCK_open, NULL); (void) pthread_mutex_init(&LOCK_open, NULL);
(void) pthread_mutex_init(&LOCK_thread_count,MY_MUTEX_INIT_FAST); (void) pthread_mutex_init(&LOCK_thread_count,MY_MUTEX_INIT_FAST);
...@@ -5232,8 +5234,8 @@ Disable with --skip-innodb-doublewrite.", (gptr*) &innobase_use_doublewrite, ...@@ -5232,8 +5234,8 @@ Disable with --skip-innodb-doublewrite.", (gptr*) &innobase_use_doublewrite,
*/ */
{"log-bin-trust-function-creators", OPT_LOG_BIN_TRUST_FUNCTION_CREATORS, {"log-bin-trust-function-creators", OPT_LOG_BIN_TRUST_FUNCTION_CREATORS,
"If equal to 0 (the default), then when --log-bin is used, creation of " "If equal to 0 (the default), then when --log-bin is used, creation of "
"a function is allowed only to users having the SUPER privilege and only " "a function (a trigger) is allowed only to users having the SUPER privilege "
"if this function may not break binary logging." "and only if this function (trigger) may not break binary logging."
#ifdef HAVE_ROW_BASED_REPLICATION #ifdef HAVE_ROW_BASED_REPLICATION
" If using --binlog-format=row, the security issues do not exist and the " " If using --binlog-format=row, the security issues do not exist and the "
"binary logging cannot break so this option is automatically set to 1." "binary logging cannot break so this option is automatically set to 1."
......
This diff is collapsed.
...@@ -67,6 +67,7 @@ enum enum_sql_command { ...@@ -67,6 +67,7 @@ enum enum_sql_command {
SQLCOM_LOAD,SQLCOM_SET_OPTION,SQLCOM_LOCK_TABLES,SQLCOM_UNLOCK_TABLES, SQLCOM_LOAD,SQLCOM_SET_OPTION,SQLCOM_LOCK_TABLES,SQLCOM_UNLOCK_TABLES,
SQLCOM_GRANT, SQLCOM_GRANT,
SQLCOM_CHANGE_DB, SQLCOM_CREATE_DB, SQLCOM_DROP_DB, SQLCOM_ALTER_DB, SQLCOM_CHANGE_DB, SQLCOM_CREATE_DB, SQLCOM_DROP_DB, SQLCOM_ALTER_DB,
SQLCOM_RENAME_DB,
SQLCOM_REPAIR, SQLCOM_REPLACE, SQLCOM_REPLACE_SELECT, SQLCOM_REPAIR, SQLCOM_REPLACE, SQLCOM_REPLACE_SELECT,
SQLCOM_CREATE_FUNCTION, SQLCOM_DROP_FUNCTION, SQLCOM_CREATE_FUNCTION, SQLCOM_DROP_FUNCTION,
SQLCOM_REVOKE,SQLCOM_OPTIMIZE, SQLCOM_CHECK, SQLCOM_REVOKE,SQLCOM_OPTIMIZE, SQLCOM_CHECK,
...@@ -818,6 +819,7 @@ typedef struct st_lex ...@@ -818,6 +819,7 @@ typedef struct st_lex
required a local context, the parser pops the top-most context. required a local context, the parser pops the top-most context.
*/ */
List<Name_resolution_context> context_stack; List<Name_resolution_context> context_stack;
List<LEX_STRING> db_list;
SQL_LIST proc_list, auxilliary_table_list, save_list; SQL_LIST proc_list, auxilliary_table_list, save_list;
create_field *last_field; create_field *last_field;
......
...@@ -3073,7 +3073,7 @@ mysql_execute_command(THD *thd) ...@@ -3073,7 +3073,7 @@ mysql_execute_command(THD *thd)
} }
} }
query_cache_invalidate3(thd, first_table, 0); query_cache_invalidate3(thd, first_table, 0);
if (end_active_trans(thd) || mysql_rename_tables(thd, first_table)) if (end_active_trans(thd) || mysql_rename_tables(thd, first_table, 0))
goto error; goto error;
break; break;
} }
...@@ -3663,6 +3663,48 @@ mysql_execute_command(THD *thd) ...@@ -3663,6 +3663,48 @@ mysql_execute_command(THD *thd)
res= mysql_rm_db(thd, lex->name, lex->drop_if_exists, 0); res= mysql_rm_db(thd, lex->name, lex->drop_if_exists, 0);
break; break;
} }
case SQLCOM_RENAME_DB:
{
LEX_STRING *olddb, *newdb;
List_iterator <LEX_STRING> db_list(lex->db_list);
olddb= db_list++;
newdb= db_list++;
if (end_active_trans(thd))
{
res= 1;
break;
}
#ifdef HAVE_REPLICATION
if (thd->slave_thread &&
(!rpl_filter->db_ok(olddb->str) ||
!rpl_filter->db_ok(newdb->str) ||
!rpl_filter->db_ok_with_wild_table(olddb->str) ||
!rpl_filter->db_ok_with_wild_table(newdb->str)))
{
res= 1;
my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
break;
}
#endif
if (check_access(thd,ALTER_ACL,olddb->str,0,1,0,is_schema_db(olddb->str)) ||
check_access(thd,DROP_ACL,olddb->str,0,1,0,is_schema_db(olddb->str)) ||
check_access(thd,CREATE_ACL,newdb->str,0,1,0,is_schema_db(newdb->str)))
{
res= 1;
break;
}
if (thd->locked_tables || thd->active_transaction())
{
res= 1;
my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
goto error;
}
res= mysql_rename_db(thd, olddb, newdb);
if (!res)
send_ok(thd);
break;
}
case SQLCOM_ALTER_DB: case SQLCOM_ALTER_DB:
{ {
char *db= lex->name ? lex->name : thd->db; char *db= lex->name ? lex->name : thd->db;
......
...@@ -31,7 +31,7 @@ static TABLE_LIST *reverse_table_list(TABLE_LIST *table_list); ...@@ -31,7 +31,7 @@ static TABLE_LIST *reverse_table_list(TABLE_LIST *table_list);
second entry is the new name. second entry is the new name.
*/ */
bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list) bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent)
{ {
bool error= 1; bool error= 1;
TABLE_LIST *ren_table= 0; TABLE_LIST *ren_table= 0;
...@@ -79,7 +79,7 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list) ...@@ -79,7 +79,7 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list)
} }
/* Lets hope this doesn't fail as the result will be messy */ /* Lets hope this doesn't fail as the result will be messy */
if (!error) if (!silent && !error)
{ {
if (mysql_bin_log.is_open()) if (mysql_bin_log.is_open())
{ {
......
...@@ -28,6 +28,8 @@ ...@@ -28,6 +28,8 @@
#include <io.h> #include <io.h>
#endif #endif
int creating_table= 0; // How many mysql_create_table are running
const char *primary_key_name="PRIMARY"; const char *primary_key_name="PRIMARY";
static bool check_if_keyname_exists(const char *name,KEY *start, KEY *end); static bool check_if_keyname_exists(const char *name,KEY *start, KEY *end);
...@@ -1973,7 +1975,7 @@ void sp_prepare_create_field(THD *thd, create_field *sql_field) ...@@ -1973,7 +1975,7 @@ void sp_prepare_create_field(THD *thd, create_field *sql_field)
Create a table Create a table
SYNOPSIS SYNOPSIS
mysql_create_table() mysql_create_table_internal()
thd Thread object thd Thread object
db Database db Database
table_name Table name table_name Table name
...@@ -1996,7 +1998,8 @@ void sp_prepare_create_field(THD *thd, create_field *sql_field) ...@@ -1996,7 +1998,8 @@ void sp_prepare_create_field(THD *thd, create_field *sql_field)
TRUE error TRUE error
*/ */
bool mysql_create_table(THD *thd,const char *db, const char *table_name, bool mysql_create_table_internal(THD *thd,
const char *db, const char *table_name,
HA_CREATE_INFO *create_info, HA_CREATE_INFO *create_info,
List<create_field> &fields, List<create_field> &fields,
List<Key> &keys,bool internal_tmp_table, List<Key> &keys,bool internal_tmp_table,
...@@ -2009,7 +2012,7 @@ bool mysql_create_table(THD *thd,const char *db, const char *table_name, ...@@ -2009,7 +2012,7 @@ bool mysql_create_table(THD *thd,const char *db, const char *table_name,
KEY *key_info_buffer; KEY *key_info_buffer;
handler *file; handler *file;
bool error= TRUE; bool error= TRUE;
DBUG_ENTER("mysql_create_table"); DBUG_ENTER("mysql_create_table_internal");
/* Check for duplicate fields and check type of table to create */ /* Check for duplicate fields and check type of table to create */
if (!fields.elements) if (!fields.elements)
...@@ -2289,6 +2292,49 @@ bool mysql_create_table(THD *thd,const char *db, const char *table_name, ...@@ -2289,6 +2292,49 @@ bool mysql_create_table(THD *thd,const char *db, const char *table_name,
goto unlock_and_end; goto unlock_and_end;
} }
/*
Database locking aware wrapper for mysql_create_table_internal(),
*/
bool mysql_create_table(THD *thd, const char *db, const char *table_name,
HA_CREATE_INFO *create_info,
List<create_field> &fields,
List<Key> &keys,bool internal_tmp_table,
uint select_field_count)
{
bool result;
DBUG_ENTER("mysql_create_table");
/* Wait for any database locks */
pthread_mutex_lock(&LOCK_lock_db);
while (!thd->killed &&
hash_search(&lock_db_cache,(byte*) db, strlen(db)))
{
wait_for_condition(thd, &LOCK_lock_db, &COND_refresh);
pthread_mutex_lock(&LOCK_lock_db);
}
if (thd->killed)
{
pthread_mutex_unlock(&LOCK_lock_db);
DBUG_RETURN(TRUE);
}
creating_table++;
pthread_mutex_unlock(&LOCK_lock_db);
result= mysql_create_table_internal(thd, db, table_name, create_info,
fields, keys, internal_tmp_table,
select_field_count);
pthread_mutex_lock(&LOCK_lock_db);
if (!--creating_table && creating_database)
pthread_cond_signal(&COND_refresh);
pthread_mutex_unlock(&LOCK_lock_db);
DBUG_RETURN(result);
}
/* /*
** Give the key name after the first field with an optional '_#' after ** Give the key name after the first field with an optional '_#' after
**/ **/
......
...@@ -195,10 +195,8 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) ...@@ -195,10 +195,8 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
/* /*
There is no DETERMINISTIC clause for triggers, so can't check it. There is no DETERMINISTIC clause for triggers, so can't check it.
But a trigger can in theory be used to do nasty things (if it supported But a trigger can in theory be used to do nasty things (if it supported
DROP for example) so we do the check for privileges. For now there is DROP for example) so we do the check for privileges. Triggers have the
already a stronger test right above; but when this stronger test will same nature as functions regarding binlogging: their body is implicitely
be removed, the test below will hold. Because triggers have the same
nature as functions regarding binlogging: their body is implicitely
binlogged, so they share the same danger, so trust_function_creators binlogged, so they share the same danger, so trust_function_creators
applies to them too. applies to them too.
*/ */
......
...@@ -863,7 +863,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); ...@@ -863,7 +863,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
clear_privileges flush_options flush_option clear_privileges flush_options flush_option
equal optional_braces opt_key_definition key_usage_list2 equal optional_braces opt_key_definition key_usage_list2
opt_mi_check_type opt_to mi_check_types normal_join opt_mi_check_type opt_to mi_check_types normal_join
table_to_table_list table_to_table opt_table_list opt_as db_to_db table_to_table_list table_to_table opt_table_list opt_as
handler_rkey_function handler_read_or_scan handler_rkey_function handler_read_or_scan
single_multi table_wild_list table_wild_one opt_wild single_multi table_wild_list table_wild_one opt_wild
union_clause union_list union_clause union_list
...@@ -5485,6 +5485,13 @@ rename: ...@@ -5485,6 +5485,13 @@ rename:
} }
table_to_table_list table_to_table_list
{} {}
| RENAME DATABASE
{
Lex->db_list.empty();
Lex->sql_command= SQLCOM_RENAME_DB;
}
db_to_db
{}
| RENAME USER clear_privileges rename_list | RENAME USER clear_privileges rename_list
{ {
Lex->sql_command = SQLCOM_RENAME_USER; Lex->sql_command = SQLCOM_RENAME_USER;
...@@ -5520,6 +5527,17 @@ table_to_table: ...@@ -5520,6 +5527,17 @@ table_to_table:
YYABORT; YYABORT;
}; };
db_to_db:
ident TO_SYM ident
{
LEX *lex=Lex;
if (Lex->db_list.push_back((LEX_STRING*)
sql_memdup(&$1, sizeof(LEX_STRING))) ||
Lex->db_list.push_back((LEX_STRING*)
sql_memdup(&$3, sizeof(LEX_STRING))))
YYABORT;
};
keycache: keycache:
CACHE_SYM INDEX_SYM keycache_list IN_SYM key_cache_name CACHE_SYM INDEX_SYM keycache_list IN_SYM key_cache_name
{ {
......
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