summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--client/client_priv.h4
-rw-r--r--client/mysqlslap.c109
-rw-r--r--mysql-test/include/have_bug25714.inc7
-rw-r--r--mysql-test/include/mix1.inc84
-rw-r--r--mysql-test/lib/mtr_report.pl6
-rwxr-xr-xmysql-test/mysql-test-run.pl12
-rw-r--r--mysql-test/r/alter_table.result14
-rw-r--r--mysql-test/r/check.result8
-rw-r--r--mysql-test/r/create.result29
-rw-r--r--mysql-test/r/federated.result33
-rw-r--r--mysql-test/r/federated_bug_25714.result56
-rw-r--r--mysql-test/r/have_bug25714.require2
-rw-r--r--mysql-test/r/having.result19
-rw-r--r--mysql-test/r/innodb.result2
-rw-r--r--mysql-test/r/innodb_mysql.result268
-rw-r--r--mysql-test/r/log_state.result2
-rw-r--r--mysql-test/r/lowercase_table3.result8
-rw-r--r--mysql-test/r/mysqldump.result22
-rw-r--r--mysql-test/r/mysqlslap.result44
-rw-r--r--mysql-test/r/sp-prelocking.result22
-rw-r--r--mysql-test/r/sp.result35
-rw-r--r--mysql-test/r/trigger.result28
-rw-r--r--mysql-test/r/type_enum.result24
-rw-r--r--mysql-test/suite/binlog/t/disabled.def3
-rw-r--r--mysql-test/t/alter_table.test12
-rw-r--r--mysql-test/t/check.test9
-rw-r--r--mysql-test/t/create.test29
-rw-r--r--mysql-test/t/disabled.def3
-rw-r--r--mysql-test/t/federated.test35
-rw-r--r--mysql-test/t/federated_bug_25714.test47
-rw-r--r--mysql-test/t/having.test26
-rw-r--r--mysql-test/t/innodb.test2
-rw-r--r--mysql-test/t/lowercase_table3.test6
-rw-r--r--mysql-test/t/mysqldump.test22
-rw-r--r--mysql-test/t/mysqlslap.test2
-rw-r--r--mysql-test/t/sp-prelocking.test23
-rw-r--r--mysql-test/t/sp.test34
-rw-r--r--mysql-test/t/trigger.test23
-rw-r--r--mysql-test/t/type_enum.test20
-rw-r--r--sql-common/client.c14
-rw-r--r--sql/field.cc7
-rw-r--r--sql/ha_ndbcluster.cc6
-rw-r--r--sql/ha_partition.cc15
-rw-r--r--sql/handler.cc8
-rw-r--r--sql/item_func.cc10
-rw-r--r--sql/item_func.h2
-rw-r--r--sql/lock.cc8
-rw-r--r--sql/set_var.cc6
-rw-r--r--sql/sql_base.cc13
-rw-r--r--sql/sql_cache.cc12
-rw-r--r--sql/sql_class.h2
-rw-r--r--sql/sql_insert.cc131
-rw-r--r--sql/sql_lex.cc24
-rw-r--r--sql/sql_lex.h58
-rw-r--r--sql/sql_parse.cc2
-rw-r--r--sql/sql_select.cc32
-rw-r--r--sql/sql_table.cc4
-rw-r--r--sql/table.cc9
-rw-r--r--sql/table.h4
-rw-r--r--storage/archive/ha_archive.cc59
-rw-r--r--storage/archive/ha_archive.h3
-rw-r--r--storage/federated/ha_federated.cc325
-rw-r--r--storage/federated/ha_federated.h3
-rw-r--r--storage/innobase/handler/ha_innodb.cc12
-rw-r--r--storage/myisam/mi_extra.c2
-rw-r--r--storage/myisammrg/myrg_locking.c8
-rw-r--r--tests/CMakeLists.txt3
-rw-r--r--tests/Makefile.am5
-rw-r--r--tests/bug25714.c71
69 files changed, 1609 insertions, 383 deletions
diff --git a/client/client_priv.h b/client/client_priv.h
index 25241cc8c59..8bc8ef692de 100644
--- a/client/client_priv.h
+++ b/client/client_priv.h
@@ -73,6 +73,10 @@ enum options_client
OPT_SLAP_AUTO_GENERATE_UNIQUE_QUERY_NUM,
OPT_SLAP_PRE_QUERY,
OPT_SLAP_POST_QUERY,
+ OPT_SLAP_PRE_SYSTEM,
+ OPT_SLAP_POST_SYSTEM,
+ OPT_SLAP_COMMIT,
+ OPT_SLAP_DETACH,
OPT_MYSQL_REPLACE_INTO, OPT_BASE64_OUTPUT, OPT_SERVER_ID,
OPT_FIX_TABLE_NAMES, OPT_FIX_DB_NAMES, OPT_SSL_VERIFY_SERVER_CERT,
OPT_DEBUG_INFO, OPT_COLUMN_TYPES, OPT_ERROR_LOG_FILE, OPT_WRITE_BINLOG,
diff --git a/client/mysqlslap.c b/client/mysqlslap.c
index 546b9dee3f5..aa15141bfdc 100644
--- a/client/mysqlslap.c
+++ b/client/mysqlslap.c
@@ -81,6 +81,7 @@ TODO:
#define UPDATE_TYPE_REQUIRES_PREFIX 3
#define CREATE_TABLE_TYPE 4
#define SELECT_TYPE_REQUIRES_PREFIX 5
+#define DELETE_TYPE_REQUIRES_PREFIX 6
#include "client_priv.h"
#include <mysqld_error.h>
@@ -122,6 +123,8 @@ static char *host= NULL, *opt_password= NULL, *user= NULL,
*user_supplied_pre_statements= NULL,
*user_supplied_post_statements= NULL,
*default_engine= NULL,
+ *pre_system= NULL,
+ *post_system= NULL,
*opt_mysql_unix_port= NULL;
const char *delimiter= "\n";
@@ -142,6 +145,8 @@ const char *auto_generate_sql_type= "mixed";
static unsigned long connect_flags= CLIENT_MULTI_RESULTS;
static int verbose, delimiter_length;
+static uint commit_rate;
+static uint detach_rate;
const char *num_int_cols_opt;
const char *num_char_cols_opt;
/* Yes, we do set defaults here */
@@ -254,6 +259,8 @@ void statement_cleanup(statement *stmt);
void option_cleanup(option_string *stmt);
void concurrency_loop(MYSQL *mysql, uint current, option_string *eptr);
static int run_statements(MYSQL *mysql, statement *stmt);
+int slap_connect(MYSQL *mysql);
+static int run_query(MYSQL *mysql, const char *query, int len);
static const char ALPHANUMERICS[]=
"0123456789ABCDEFGHIJKLMNOPQRSTWXYZabcdefghijklmnopqrstuvwxyz";
@@ -451,6 +458,16 @@ void concurrency_loop(MYSQL *mysql, uint current, option_string *eptr)
if (auto_generate_sql_autoincrement || auto_generate_sql_guid_primary)
generate_primary_key_list(mysql, eptr);
+ if (commit_rate)
+ run_query(mysql, "SET AUTOCOMMIT=0", strlen("SET AUTOCOMMIT=0"));
+
+ if (pre_system)
+ system(pre_system);
+
+ /*
+ Pre statements are always run after all other logic so they can
+ correct/adjust any item that they want.
+ */
if (pre_statements)
run_statements(mysql, pre_statements);
@@ -459,6 +476,9 @@ void concurrency_loop(MYSQL *mysql, uint current, option_string *eptr)
if (post_statements)
run_statements(mysql, post_statements);
+ if (post_system)
+ system(post_system);
+
/* We are finished with this run */
if (auto_generate_sql_autoincrement || auto_generate_sql_guid_primary)
drop_primary_key_list();
@@ -527,6 +547,9 @@ static struct my_option my_long_options[] =
"Number of rows to insert to used in read and write loads (default is 100).\n",
(uchar**) &auto_generate_sql_number, (uchar**) &auto_generate_sql_number,
0, GET_ULL, REQUIRED_ARG, 100, 0, 0, 0, 0, 0},
+ {"commit", OPT_SLAP_COMMIT, "Commit records after X number of statements.",
+ (uchar**) &commit_rate, (uchar**) &commit_rate, 0, GET_UINT, REQUIRED_ARG,
+ 0, 0, 0, 0, 0, 0},
{"compress", 'C', "Use compression in server/client protocol.",
(uchar**) &opt_compress, (uchar**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
0, 0, 0},
@@ -550,6 +573,9 @@ static struct my_option my_long_options[] =
"Delimiter to use in SQL statements supplied in file or command line.",
(uchar**) &delimiter, (uchar**) &delimiter, 0, GET_STR, REQUIRED_ARG,
0, 0, 0, 0, 0, 0},
+ {"detach", OPT_SLAP_DETACH, "Detach connections after X number of requests.",
+ (uchar**) &detach_rate, (uchar**) &detach_rate, 0, GET_UINT, REQUIRED_ARG,
+ 0, 0, 0, 0, 0, 0},
{"engine", 'e', "Storage engine to use for creating the table.",
(uchar**) &default_engine, (uchar**) &default_engine, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
@@ -589,11 +615,21 @@ static struct my_option my_long_options[] =
(uchar**) &user_supplied_post_statements,
(uchar**) &user_supplied_post_statements,
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"post-system", OPT_SLAP_POST_SYSTEM,
+ "System() string to run after the load has completed.",
+ (uchar**) &post_system,
+ (uchar**) &post_system,
+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"pre-query", OPT_SLAP_PRE_QUERY,
"Query to run or file containing query to run before executing.",
(uchar**) &user_supplied_pre_statements,
(uchar**) &user_supplied_pre_statements,
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"pre-system", OPT_SLAP_PRE_SYSTEM,
+ "System() string to before load has completed.",
+ (uchar**) &pre_system,
+ (uchar**) &pre_system,
+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"preserve-schema", OPT_MYSQL_PRESERVE_SCHEMA,
"Preserve the schema from the mysqlslap run, this happens unless "
"--auto-generate-sql or --create are used.",
@@ -1715,6 +1751,7 @@ run_scheduler(stats *sptr, statement *stmts, uint concur, ulonglong limit)
pthread_handler_t run_task(void *p)
{
ulonglong counter= 0, queries;
+ ulonglong trans_counter;
MYSQL *mysql;
MYSQL_RES *result;
MYSQL_ROW row;
@@ -1749,38 +1786,28 @@ pthread_handler_t run_task(void *p)
if (!opt_only_print)
{
- /* Connect to server */
- static ulong connection_retry_sleep= 100000; /* Microseconds */
- int i, connect_error= 1;
- for (i= 0; i < 10; i++)
- {
- if (mysql_real_connect(mysql, host, user, opt_password,
- create_schema_string,
- opt_mysql_port,
- opt_mysql_unix_port,
- connect_flags))
- {
- /* Connect suceeded */
- connect_error= 0;
- break;
- }
- my_sleep(connection_retry_sleep);
- }
- if (connect_error)
- {
- fprintf(stderr,"%s: Error when connecting to server: %d %s\n",
- my_progname, mysql_errno(mysql), mysql_error(mysql));
+ if (slap_connect(mysql))
goto end;
- }
}
+
DBUG_PRINT("info", ("connected."));
if (verbose >= 3)
printf("connected!\n");
queries= 0;
limit_not_met:
- for (ptr= con->stmt; ptr && ptr->length; ptr= ptr->next)
+ for (ptr= con->stmt, trans_counter= 0;
+ ptr && ptr->length;
+ ptr= ptr->next, trans_counter++)
{
+ if (!opt_only_print && detach_rate && !(trans_counter % detach_rate))
+ {
+ mysql_close(mysql);
+
+ if (slap_connect(mysql))
+ goto end;
+ }
+
/*
We have to execute differently based on query type. This should become a function.
*/
@@ -1837,6 +1864,9 @@ limit_not_met:
}
queries++;
+ if (commit_rate && commit_rate <= trans_counter)
+ run_query(mysql, "COMMIT", strlen("COMMIT"));
+
if (con->limit && queries == con->limit)
goto end;
}
@@ -1845,6 +1875,8 @@ limit_not_met:
goto limit_not_met;
end:
+ if (commit_rate)
+ run_query(mysql, "COMMIT", strlen("COMMIT"));
if (!opt_only_print)
mysql_close(mysql);
@@ -2104,3 +2136,34 @@ statement_cleanup(statement *stmt)
my_free(ptr, MYF(0));
}
}
+
+
+int
+slap_connect(MYSQL *mysql)
+{
+ /* Connect to server */
+ static ulong connection_retry_sleep= 100000; /* Microseconds */
+ int x, connect_error= 1;
+ for (x= 0; x < 10; x++)
+ {
+ if (mysql_real_connect(mysql, host, user, opt_password,
+ create_schema_string,
+ opt_mysql_port,
+ opt_mysql_unix_port,
+ connect_flags))
+ {
+ /* Connect suceeded */
+ connect_error= 0;
+ break;
+ }
+ my_sleep(connection_retry_sleep);
+ }
+ if (connect_error)
+ {
+ fprintf(stderr,"%s: Error when connecting to server: %d %s\n",
+ my_progname, mysql_errno(mysql), mysql_error(mysql));
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/mysql-test/include/have_bug25714.inc b/mysql-test/include/have_bug25714.inc
new file mode 100644
index 00000000000..0c995cd0d4c
--- /dev/null
+++ b/mysql-test/include/have_bug25714.inc
@@ -0,0 +1,7 @@
+#
+# Check if the variable MYSQL_BUG25714 is set
+#
+--require r/have_bug25714.require
+disable_query_log;
+eval select LENGTH("MYSQL_BUG25714") > 0 as "have_bug25714_exe";
+enable_query_log;
diff --git a/mysql-test/include/mix1.inc b/mysql-test/include/mix1.inc
index bffb748dd6b..d8bc4c40bf3 100644
--- a/mysql-test/include/mix1.inc
+++ b/mysql-test/include/mix1.inc
@@ -815,6 +815,90 @@ alter table t1 alter a set default 1;
drop table t1;
#
+# Bug #28591: MySQL need not sort the records in case of ORDER BY
+# primary_key on InnoDB table
+#
+
+CREATE TABLE t1 (a int, b int, PRIMARY KEY (a), KEY bkey (b)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1,2),(3,2),(2,2),(4,2),(5,2),(6,2),(7,2),(8,2);
+INSERT INTO t1 SELECT a + 8, 2 FROM t1;
+INSERT INTO t1 SELECT a + 16, 1 FROM t1;
+query_vertical EXPLAIN SELECT * FROM t1 WHERE b=2 ORDER BY a;
+SELECT * FROM t1 WHERE b=2 ORDER BY a;
+query_vertical EXPLAIN SELECT * FROM t1 WHERE b BETWEEN 1 AND 2 ORDER BY a;
+SELECT * FROM t1 WHERE b BETWEEN 1 AND 2 ORDER BY a;
+query_vertical EXPLAIN SELECT * FROM t1 WHERE b BETWEEN 1 AND 2 ORDER BY b,a;
+SELECT * FROM t1 WHERE b BETWEEN 1 AND 2 ORDER BY b,a;
+
+CREATE TABLE t2 (a int, b int, c int, PRIMARY KEY (a), KEY bkey (b,c))
+ ENGINE=InnoDB;
+INSERT INTO t2 VALUES (1,1,1),(3,1,1),(2,1,1),(4,1,1);
+INSERT INTO t2 SELECT a + 4, 1, 1 FROM t2;
+INSERT INTO t2 SELECT a + 8, 1, 1 FROM t2;
+
+query_vertical EXPLAIN SELECT * FROM t2 WHERE b=1 ORDER BY a;
+SELECT * FROM t2 WHERE b=1 ORDER BY a;
+query_vertical EXPLAIN SELECT * FROM t2 WHERE b=1 AND c=1 ORDER BY a;
+SELECT * FROM t2 WHERE b=1 AND c=1 ORDER BY a;
+query_vertical EXPLAIN SELECT * FROM t2 WHERE b=1 AND c=1 ORDER BY b,c,a;
+SELECT * FROM t2 WHERE b=1 AND c=1 ORDER BY b,c,a;
+query_vertical EXPLAIN SELECT * FROM t2 WHERE b=1 AND c=1 ORDER BY c,a;
+SELECT * FROM t2 WHERE b=1 AND c=1 ORDER BY c,a;
+
+DROP TABLE t1,t2;
+
+
+#
+# Bug #29644: alter table hangs if records locked in share mode by long
+# running transaction
+#
+
+CREATE TABLE t1 (a INT, PRIMARY KEY (a)) ENGINE=InnoDB;
+
+INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8);
+INSERT INTO t1 SELECT a + 8 FROM t1;
+INSERT INTO t1 SELECT a + 16 FROM t1;
+
+DELIMITER |;
+CREATE PROCEDURE p1 ()
+BEGIN
+ DECLARE i INT DEFAULT 50;
+ DECLARE cnt INT;
+ START TRANSACTION;
+ ALTER TABLE t1 ENGINE=InnoDB;
+ COMMIT;
+ START TRANSACTION;
+ WHILE (i > 0) DO
+ SET i = i - 1;
+ SELECT COUNT(*) INTO cnt FROM t1 LOCK IN SHARE MODE;
+ END WHILE;
+ COMMIT;
+END;|
+
+DELIMITER ;|
+
+CONNECT (con1,localhost,root,,);
+CONNECT (con2,localhost,root,,);
+
+CONNECTION con1;
+SEND CALL p1();
+CONNECTION con2;
+SEND CALL p1();
+CONNECTION default;
+CALL p1();
+
+CONNECTION con1;
+REAP;
+CONNECTION con2;
+REAP;
+CONNECTION default;
+DISCONNECT con1;
+DISCONNECT con2;
+
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+#
# Bug #28125: ERROR 2013 when adding index.
#
create table t1(a text) engine=innodb default charset=utf8;
diff --git a/mysql-test/lib/mtr_report.pl b/mysql-test/lib/mtr_report.pl
index 306a0fe5d9d..fa38e8507f8 100644
--- a/mysql-test/lib/mtr_report.pl
+++ b/mysql-test/lib/mtr_report.pl
@@ -362,7 +362,11 @@ sub mtr_report_stats ($) {
# BUG#29807 - innodb_mysql.test: Cannot find table test/t2
# from the internal data dictionary
- /Cannot find table test\/bug29807 from the internal data dictionary/
+ /Cannot find table test\/bug29807 from the internal data dictionary/ or
+
+ # BUG#29839 - lowercase_table3.test: Cannot find table test/T1
+ # from the internal data dictiona
+ /Cannot find table test\/BUG29839 from the internal data dictionary/
)
{
next; # Skip these lines
diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl
index 6ec4045bb43..1effa7c878d 100755
--- a/mysql-test/mysql-test-run.pl
+++ b/mysql-test/mysql-test-run.pl
@@ -143,6 +143,7 @@ our $exe_mysqladmin;
our $exe_mysql_upgrade;
our $exe_mysqlbinlog;
our $exe_mysql_client_test;
+our $exe_bug25714;
our $exe_mysqld;
our $exe_mysqlcheck;
our $exe_mysqldump;
@@ -1648,6 +1649,12 @@ sub executable_setup () {
"$glob_basedir/tests/mysql_client_test",
"$glob_basedir/bin/mysql_client_test");
}
+
+ # Look for bug25714 executable which may _not_ exist in
+ # some versions, test using it should be skipped
+ $exe_bug25714=
+ mtr_exe_maybe_exists(vs_config_dirs('tests', 'bug25714'),
+ "$glob_basedir/tests/bug25714");
}
@@ -2019,6 +2026,11 @@ sub environment_setup () {
$ENV{'MYSQL'}= $cmdline_mysql;
# ----------------------------------------------------
+ # Setup env so childs can execute bug25714
+ # ----------------------------------------------------
+ $ENV{'MYSQL_BUG25714'}= $exe_bug25714;
+
+ # ----------------------------------------------------
# Setup env so childs can execute mysql_client_test
# ----------------------------------------------------
$ENV{'MYSQL_CLIENT_TEST'}= mysql_client_test_arguments();
diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result
index a9c01f308f7..7c0ac177cb5 100644
--- a/mysql-test/r/alter_table.result
+++ b/mysql-test/r/alter_table.result
@@ -1030,6 +1030,7 @@ select * from t2;
c
NULL
1
+Two
Three
lock table t2 write, t3 read;
alter table t2 change c vc varchar(100) default "Four", rename to t1;
@@ -1046,6 +1047,7 @@ select * from t1;
vc
NULL
1
+Two
Three
Four
drop tables t1, t3;
@@ -1170,3 +1172,15 @@ SELECT * FROM t1;
f1 f2 f3
1 2 NULL
DROP TABLE t1;
+create table t1 (c char(10) default "Two");
+lock table t1 write;
+insert into t1 values ();
+alter table t1 modify c char(10) default "Three";
+unlock tables;
+select * from t1;
+c
+Two
+check table t1;
+Table Op Msg_type Msg_text
+test.t1 check status OK
+drop table t1;
diff --git a/mysql-test/r/check.result b/mysql-test/r/check.result
index 739eab2ed76..0bff34dba20 100644
--- a/mysql-test/r/check.result
+++ b/mysql-test/r/check.result
@@ -15,3 +15,11 @@ test.v1 check status OK
test.t2 check status OK
drop view v1;
drop table t1, t2;
+CREATE TEMPORARY TABLE t1(a INT);
+CHECK TABLE t1;
+Table Op Msg_type Msg_text
+test.t1 check status OK
+REPAIR TABLE t1;
+Table Op Msg_type Msg_text
+test.t1 repair status OK
+DROP TABLE t1;
diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result
index cdbb767dd9f..84a620336dc 100644
--- a/mysql-test/r/create.result
+++ b/mysql-test/r/create.result
@@ -1516,6 +1516,35 @@ t1 CREATE TABLE `t1` (
`c17` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
+
+Bug #26104 Bug on foreign key class constructor
+
+Check that ref_columns is initalized correctly in the constructor
+and semantic checks in mysql_prepare_table work.
+
+We do not need a storage engine that supports foreign keys
+for this test, as the checks are purely syntax-based, and the
+syntax is supported for all engines.
+
+drop table if exists t1,t2;
+create table t1(a int not null, b int not null, primary key (a, b));
+create table t2(a int not null, b int not null, c int not null, primary key (a),
+foreign key fk_bug26104 (b,c) references t1(a));
+ERROR 42000: Incorrect foreign key definition for 'fk_bug26104': Key reference and table reference don't match
+drop table t1;
+create table t1(f1 int,f2 int);
+insert into t1 value(1,1),(1,2),(1,3),(2,1),(2,2),(2,3);
+flush status;
+create table t2 select sql_big_result f1,count(f2) from t1 group by f1;
+show status like 'handler_read%';
+Variable_name Value
+Handler_read_first 0
+Handler_read_key 0
+Handler_read_next 0
+Handler_read_prev 0
+Handler_read_rnd 0
+Handler_read_rnd_next 7
+drop table t1,t2;
End of 5.0 tests
CREATE TABLE t1 (a int, b int);
insert into t1 values (1,1),(1,2);
diff --git a/mysql-test/r/federated.result b/mysql-test/r/federated.result
index 5c5cb7eaa79..ca936cd5fde 100644
--- a/mysql-test/r/federated.result
+++ b/mysql-test/r/federated.result
@@ -40,17 +40,18 @@ CREATE TABLE federated.t1 (
)
ENGINE="FEDERATED" DEFAULT CHARSET=latin1
CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t3';
-ERROR HY000: Can't create federated table. Foreign data src error: error: 1146 'Table 'federated.t3' doesn't exist'
+SELECT * FROM federated.t1;
+ERROR HY000: The foreign data source you are trying to reference does not exist. Data source error: error: 1146 'Table 'federated.t3' doesn't exist'
+DROP TABLE federated.t1;
CREATE TABLE federated.t1 (
`id` int(20) NOT NULL,
`name` varchar(32) NOT NULL default ''
)
ENGINE="FEDERATED" DEFAULT CHARSET=latin1
CONNECTION='mysql://user:pass@127.0.0.1:SLAVE_PORT/federated/t1';
-ERROR HY000: Unable to connect to foreign data source: database: 'federated' username: 'user' hostname: '127.0.0.1'
-DROP TABLE IF EXISTS federated.t1;
-Warnings:
-Note 1051 Unknown table 't1'
+SELECT * FROM federated.t1;
+ERROR HY000: Unable to connect to foreign data source: Access denied for user 'user'@'localhost' (using password: YES)
+DROP TABLE federated.t1;
CREATE TABLE federated.t1 (
`id` int(20) NOT NULL,
`name` varchar(32) NOT NULL default ''
@@ -1919,6 +1920,28 @@ a b
2 Curly
drop table federated.t1;
drop table federated.t1;
+CREATE TABLE federated.t1 (a INT PRIMARY KEY) DEFAULT CHARSET=utf8;
+CREATE TABLE federated.t1 (a INT PRIMARY KEY)
+ENGINE=FEDERATED
+CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1'
+ DEFAULT CHARSET=utf8;
+SELECT transactions FROM information_schema.engines WHERE engine="FEDERATED";
+transactions
+NO
+INSERT INTO federated.t1 VALUES (1);
+SET autocommit=0;
+INSERT INTO federated.t1 VALUES (2);
+ROLLBACK;
+Warnings:
+Warning 1196 Some non-transactional changed tables couldn't be rolled back
+SET autocommit=1;
+SELECT * FROM federated.t1;
+a
+1
+2
+DROP TABLE federated.t1;
+DROP TABLE federated.t1;
+End of 5.1 tests
DROP TABLE IF EXISTS federated.t1;
DROP DATABASE IF EXISTS federated;
DROP TABLE IF EXISTS federated.t1;
diff --git a/mysql-test/r/federated_bug_25714.result b/mysql-test/r/federated_bug_25714.result
new file mode 100644
index 00000000000..12554f7af3a
--- /dev/null
+++ b/mysql-test/r/federated_bug_25714.result
@@ -0,0 +1,56 @@
+stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+start slave;
+stop slave;
+DROP DATABASE IF EXISTS federated;
+CREATE DATABASE federated;
+DROP DATABASE IF EXISTS federated;
+CREATE DATABASE federated;
+DROP TABLE IF EXISTS federated.bug_13118_table;
+CREATE TABLE federated.t1 (
+`id` int auto_increment primary key,
+`value` int
+) ENGINE=MyISAM;
+INSERT INTO federated.t1 SET value=1;
+INSERT INTO federated.t1 SET value=2;
+INSERT INTO federated.t1 SET value=2;
+DROP TABLE IF EXISTS federated.t1;
+CREATE TABLE federated.t1 (
+`id` int auto_increment primary key,
+`value` int
+) ENGINE=FEDERATED
+CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1';
+SELECT * from federated.t1;
+id value
+1 1
+2 2
+3 2
+INSERT INTO federated.t1 SET value=4;
+SELECT LAST_INSERT_ID();
+LAST_INSERT_ID()
+4
+
+5 inserted
+6 inserted
+
+7 inserted
+8 inserted
+SELECT * from federated.t1;
+id value
+1 1
+2 2
+3 2
+4 4
+5 54
+6 55
+7 54
+8 55
+DROP TABLE federated.t1;
+DROP TABLE federated.t1;
+DROP TABLE IF EXISTS federated.t1;
+DROP DATABASE IF EXISTS federated;
+DROP TABLE IF EXISTS federated.t1;
+DROP DATABASE IF EXISTS federated;
diff --git a/mysql-test/r/have_bug25714.require b/mysql-test/r/have_bug25714.require
new file mode 100644
index 00000000000..5acc378dcf7
--- /dev/null
+++ b/mysql-test/r/have_bug25714.require
@@ -0,0 +1,2 @@
+have_bug25714_exe
+1
diff --git a/mysql-test/r/having.result b/mysql-test/r/having.result
index 149391396b6..a5a96fd4958 100644
--- a/mysql-test/r/having.result
+++ b/mysql-test/r/having.result
@@ -158,6 +158,25 @@ EXPLAIN SELECT 0 AS x, a FROM t1 GROUP BY x,a HAVING x=1 AND a > 1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible HAVING
DROP table t1;
+CREATE TABLE t1 (a int PRIMARY KEY);
+CREATE TABLE t2 (b int PRIMARY KEY, a int);
+CREATE TABLE t3 (b int, flag int);
+INSERT INTO t1 VALUES (1);
+INSERT INTO t2 VALUES (1,1), (2,1), (3,1);
+INSERT INTO t3(b,flag) VALUES (2, 1);
+SELECT t1.a
+FROM t1 INNER JOIN t2 ON t1.a=t2.a LEFT JOIN t3 ON t2.b=t3.b
+GROUP BY t1.a, t2.b HAVING MAX(t3.flag)=0;
+a
+SELECT DISTINCT t1.a, MAX(t3.flag)
+FROM t1 INNER JOIN t2 ON t1.a=t2.a LEFT JOIN t3 ON t2.b=t3.b
+GROUP BY t1.a, t2.b HAVING MAX(t3.flag)=0;
+a MAX(t3.flag)
+SELECT DISTINCT t1.a
+FROM t1 INNER JOIN t2 ON t1.a=t2.a LEFT JOIN t3 ON t2.b=t3.b
+GROUP BY t1.a, t2.b HAVING MAX(t3.flag)=0;
+a
+DROP TABLE t1,t2,t3;
create table t1 (col1 int, col2 varchar(5), col_t1 int);
create table t2 (col1 int, col2 varchar(5), col_t2 int);
create table t3 (col1 int, col2 varchar(5), col_t3 int);
diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result
index 9a96145ef06..804c4b81c17 100644
--- a/mysql-test/r/innodb.result
+++ b/mysql-test/r/innodb.result
@@ -1640,7 +1640,7 @@ t2 CREATE TABLE `t2` (
) ENGINE=InnoDB DEFAULT CHARSET=latin1
drop table t2;
create table t2 (id int(11) not null, id2 int(11) not null, constraint t1_id_fk foreign key (id2,id) references t1 (id)) engine = innodb;
-ERROR HY000: Can't create table 'test.t2' (errno: 150)
+ERROR 42000: Incorrect foreign key definition for 't1_id_fk': Key reference and table reference don't match
create table t2 (a int auto_increment primary key, b int, index(b), foreign key (b) references t1(id), unique(b)) engine=innodb;
show create table t2;
Table Create Table
diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result
index 1dd82d2dd88..4beb818c1eb 100644
--- a/mysql-test/r/innodb_mysql.result
+++ b/mysql-test/r/innodb_mysql.result
@@ -814,6 +814,274 @@ drop table if exists t1;
create table t1 (a int) engine=innodb;
alter table t1 alter a set default 1;
drop table t1;
+CREATE TABLE t1 (a int, b int, PRIMARY KEY (a), KEY bkey (b)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1,2),(3,2),(2,2),(4,2),(5,2),(6,2),(7,2),(8,2);
+INSERT INTO t1 SELECT a + 8, 2 FROM t1;
+INSERT INTO t1 SELECT a + 16, 1 FROM t1;
+EXPLAIN SELECT * FROM t1 WHERE b=2 ORDER BY a;
+id 1
+select_type SIMPLE
+table t1
+type ref
+possible_keys bkey
+key bkey
+key_len 5
+ref const
+rows 16
+Extra Using where; Using index
+SELECT * FROM t1 WHERE b=2 ORDER BY a;
+a b
+1 2
+2 2
+3 2
+4 2
+5 2
+6 2
+7 2
+8 2
+9 2
+10 2
+11 2
+12 2
+13 2
+14 2
+15 2
+16 2
+EXPLAIN SELECT * FROM t1 WHERE b BETWEEN 1 AND 2 ORDER BY a;
+id 1
+select_type SIMPLE
+table t1
+type range
+possible_keys bkey
+key bkey
+key_len 5
+ref NULL
+rows 16
+Extra Using where; Using index; Using filesort
+SELECT * FROM t1 WHERE b BETWEEN 1 AND 2 ORDER BY a;
+a b
+1 2
+2 2
+3 2
+4 2
+5 2
+6 2
+7 2
+8 2
+9 2
+10 2
+11 2
+12 2
+13 2
+14 2
+15 2
+16 2
+17 1
+18 1
+19 1
+20 1
+21 1
+22 1
+23 1
+24 1
+25 1
+26 1
+27 1
+28 1
+29 1
+30 1
+31 1
+32 1
+EXPLAIN SELECT * FROM t1 WHERE b BETWEEN 1 AND 2 ORDER BY b,a;
+id 1
+select_type SIMPLE
+table t1
+type range
+possible_keys bkey
+key bkey
+key_len 5
+ref NULL
+rows 16
+Extra Using where; Using index
+SELECT * FROM t1 WHERE b BETWEEN 1 AND 2 ORDER BY b,a;
+a b
+17 1
+18 1
+19 1
+20 1
+21 1
+22 1
+23 1
+24 1
+25 1
+26 1
+27 1
+28 1
+29 1
+30 1
+31 1
+32 1
+1 2
+2 2
+3 2
+4 2
+5 2
+6 2
+7 2
+8 2
+9 2
+10 2
+11 2
+12 2
+13 2
+14 2
+15 2
+16 2
+CREATE TABLE t2 (a int, b int, c int, PRIMARY KEY (a), KEY bkey (b,c))
+ENGINE=InnoDB;
+INSERT INTO t2 VALUES (1,1,1),(3,1,1),(2,1,1),(4,1,1);
+INSERT INTO t2 SELECT a + 4, 1, 1 FROM t2;
+INSERT INTO t2 SELECT a + 8, 1, 1 FROM t2;
+EXPLAIN SELECT * FROM t2 WHERE b=1 ORDER BY a;
+id 1
+select_type SIMPLE
+table t2
+type ref
+possible_keys bkey
+key bkey
+key_len 5
+ref const
+rows 8
+Extra Using where; Using index; Using filesort
+SELECT * FROM t2 WHERE b=1 ORDER BY a;
+a b c
+1 1 1
+2 1 1
+3 1 1
+4 1 1
+5 1 1
+6 1 1
+7 1 1
+8 1 1
+9 1 1
+10 1 1
+11 1 1
+12 1 1
+13 1 1
+14 1 1
+15 1 1
+16 1 1
+EXPLAIN SELECT * FROM t2 WHERE b=1 AND c=1 ORDER BY a;
+id 1
+select_type SIMPLE
+table t2
+type ref
+possible_keys bkey
+key bkey
+key_len 10
+ref const,const
+rows 8
+Extra Using where; Using index
+SELECT * FROM t2 WHERE b=1 AND c=1 ORDER BY a;
+a b c
+1 1 1
+2 1 1
+3 1 1
+4 1 1
+5 1 1
+6 1 1
+7 1 1
+8 1 1
+9 1 1
+10 1 1
+11 1 1
+12 1 1
+13 1 1
+14 1 1
+15 1 1
+16 1 1
+EXPLAIN SELECT * FROM t2 WHERE b=1 AND c=1 ORDER BY b,c,a;
+id 1
+select_type SIMPLE
+table t2
+type ref
+possible_keys bkey
+key bkey
+key_len 10
+ref const,const
+rows 8
+Extra Using where; Using index
+SELECT * FROM t2 WHERE b=1 AND c=1 ORDER BY b,c,a;
+a b c
+1 1 1
+2 1 1
+3 1 1
+4 1 1
+5 1 1
+6 1 1
+7 1 1
+8 1 1
+9 1 1
+10 1 1
+11 1 1
+12 1 1
+13 1 1
+14 1 1
+15 1 1
+16 1 1
+EXPLAIN SELECT * FROM t2 WHERE b=1 AND c=1 ORDER BY c,a;
+id 1
+select_type SIMPLE
+table t2
+type ref
+possible_keys bkey
+key bkey
+key_len 10
+ref const,const
+rows 8
+Extra Using where; Using index
+SELECT * FROM t2 WHERE b=1 AND c=1 ORDER BY c,a;
+a b c
+1 1 1
+2 1 1
+3 1 1
+4 1 1
+5 1 1
+6 1 1
+7 1 1
+8 1 1
+9 1 1
+10 1 1
+11 1 1
+12 1 1
+13 1 1
+14 1 1
+15 1 1
+16 1 1
+DROP TABLE t1,t2;
+CREATE TABLE t1 (a INT, PRIMARY KEY (a)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8);
+INSERT INTO t1 SELECT a + 8 FROM t1;
+INSERT INTO t1 SELECT a + 16 FROM t1;
+CREATE PROCEDURE p1 ()
+BEGIN
+DECLARE i INT DEFAULT 50;
+DECLARE cnt INT;
+START TRANSACTION;
+ALTER TABLE t1 ENGINE=InnoDB;
+COMMIT;
+START TRANSACTION;
+WHILE (i > 0) DO
+SET i = i - 1;
+SELECT COUNT(*) INTO cnt FROM t1 LOCK IN SHARE MODE;
+END WHILE;
+COMMIT;
+END;|
+CALL p1();
+CALL p1();
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
create table t1(a text) engine=innodb default charset=utf8;
insert into t1 values('aaa');
alter table t1 add index(a(1024));
diff --git a/mysql-test/r/log_state.result b/mysql-test/r/log_state.result
index 946797aeec7..38b3ebd6e98 100644
--- a/mysql-test/r/log_state.result
+++ b/mysql-test/r/log_state.result
@@ -131,7 +131,7 @@ set global general_log=ON;
set global log_output=default;
show variables like 'log_output';
Variable_name Value
-log_output TABLE
+log_output FILE
set global general_log=OFF;
set global log_output=FILE;
truncate table mysql.general_log;
diff --git a/mysql-test/r/lowercase_table3.result b/mysql-test/r/lowercase_table3.result
index 995a2c0d08a..14cff4f98c9 100644
--- a/mysql-test/r/lowercase_table3.result
+++ b/mysql-test/r/lowercase_table3.result
@@ -4,7 +4,7 @@ SELECT * from T1;
a
drop table t1;
flush tables;
-CREATE TABLE t1 (a int) ENGINE=INNODB;
-SELECT * from T1;
-ERROR 42S02: Table 'test.T1' doesn't exist
-drop table t1;
+CREATE TABLE bug29839 (a int) ENGINE=INNODB;
+SELECT * from BUG29839;
+ERROR 42S02: Table 'test.BUG29839' doesn't exist
+drop table bug29839;
diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result
index e8c971a41bc..1fa18482b9c 100644
--- a/mysql-test/r/mysqldump.result
+++ b/mysql-test/r/mysqldump.result
@@ -3573,6 +3573,28 @@ SELECT * FROM v1;
1
DROP VIEW v1;
#
+# Bug #29788: mysqldump discards the NO_AUTO_VALUE_ON_ZERO value of
+# the SQL_MODE variable after the dumping of triggers.
+#
+CREATE TABLE t1 (c1 INT);
+CREATE TRIGGER t1bd BEFORE DELETE ON t1 FOR EACH ROW BEGIN END;
+CREATE TABLE t2 (c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY);
+SET @TMP_SQL_MODE = @@SQL_MODE;
+SET SQL_MODE = 'NO_AUTO_VALUE_ON_ZERO';
+INSERT INTO t2 VALUES (0), (1), (2);
+SET SQL_MODE = @TMP_SQL_MODE;
+SELECT * FROM t2;
+c1
+0
+1
+2
+SELECT * FROM t2;
+c1
+0
+1
+2
+DROP TABLE t1,t2;
+#
# End of 5.0 tests
#
drop table if exists t1;
diff --git a/mysql-test/r/mysqlslap.result b/mysql-test/r/mysqlslap.result
index bca7919d78c..cc8bc3dac31 100644
--- a/mysql-test/r/mysqlslap.result
+++ b/mysql-test/r/mysqlslap.result
@@ -167,3 +167,47 @@ SHOW TABLES;
select * from t1;
SHOW TABLES;
DROP SCHEMA IF EXISTS `mysqlslap`;
+DROP SCHEMA IF EXISTS `mysqlslap`;
+CREATE SCHEMA `mysqlslap`;
+use mysqlslap;
+set storage_engine=`heap`;
+CREATE TABLE t1 (id int, name varchar(64));
+create table t2(foo1 varchar(32), foo2 varchar(32));
+INSERT INTO t1 VALUES (1, 'This is a test');
+insert into t2 values ('test', 'test2');
+SET AUTOCOMMIT=0;
+SHOW TABLES;
+select * from t1;
+select * from t2;
+COMMIT;
+select * from t1;
+select * from t2;
+COMMIT;
+select * from t1;
+select * from t2;
+COMMIT;
+COMMIT;
+SHOW TABLES;
+DROP SCHEMA IF EXISTS `mysqlslap`;
+DROP SCHEMA IF EXISTS `mysqlslap`;
+CREATE SCHEMA `mysqlslap`;
+use mysqlslap;
+set storage_engine=`myisam`;
+CREATE TABLE t1 (id int, name varchar(64));
+create table t2(foo1 varchar(32), foo2 varchar(32));
+INSERT INTO t1 VALUES (1, 'This is a test');
+insert into t2 values ('test', 'test2');
+SET AUTOCOMMIT=0;
+SHOW TABLES;
+select * from t1;
+select * from t2;
+COMMIT;
+select * from t1;
+select * from t2;
+COMMIT;
+select * from t1;
+select * from t2;
+COMMIT;
+COMMIT;
+SHOW TABLES;
+DROP SCHEMA IF EXISTS `mysqlslap`;
diff --git a/mysql-test/r/sp-prelocking.result b/mysql-test/r/sp-prelocking.result
index 5eac54803f0..c19bd1abd26 100644
--- a/mysql-test/r/sp-prelocking.result
+++ b/mysql-test/r/sp-prelocking.result
@@ -267,4 +267,26 @@ drop table bug_27907_logs;
insert into bug_27907_t1(a) values (1);
ERROR 42S02: Table 'test.bug_27907_logs' doesn't exist
drop table bug_27907_t1;
+
+Bug#22427 create table if not exists + stored function results in
+inconsistent behavior
+
+Add a test case, the bug itself was fixed by the patch for
+Bug#20662
+
+drop table if exists t1;
+drop function if exists f_bug22427;
+create table t1 (i int);
+insert into t1 values (1);
+create function f_bug22427() returns int return (select max(i) from t1);
+select f_bug22427();
+f_bug22427()
+1
+create table if not exists t1 select f_bug22427() as i;
+Warnings:
+Note 1050 Table 't1' already exists
+create table t1 select f_bug22427() as i;
+ERROR 42S01: Table 't1' already exists
+drop table t1;
+drop function f_bug22427;
End of 5.0 tests
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result
index 273c60110b3..07661f9ae54 100644
--- a/mysql-test/r/sp.result
+++ b/mysql-test/r/sp.result
@@ -1,5 +1,7 @@
use test;
drop table if exists t1,t2,t3,t4;
+drop function if exists f1;
+drop function if exists f2;
create table t1 (
id char(16) not null default '',
data int not null
@@ -6249,7 +6251,7 @@ drop table t1,t2;
CREATE TABLE t1 (a int auto_increment primary key) engine=MyISAM;
CREATE TABLE t2 (a int auto_increment primary key, b int) engine=innodb;
set @a=0;
-CREATE function bug27354() RETURNS int deterministic
+CREATE function bug27354() RETURNS int not deterministic
begin
insert into t1 values (null);
set @a=@a+1;
@@ -6433,3 +6435,34 @@ where ROUTINE_NAME = "proc_26302";
ROUTINE_NAME ROUTINE_DEFINITION
proc_26302 select 1 /* testing */
drop procedure proc_26302;
+CREATE FUNCTION f1() RETURNS INT DETERMINISTIC RETURN 2;
+CREATE FUNCTION f2(I INT) RETURNS INT DETERMINISTIC RETURN 3;
+CREATE TABLE t1 (c1 INT, INDEX(c1));
+INSERT INTO t1 VALUES (1), (2), (3), (4), (5);
+CREATE VIEW v1 AS SELECT c1 FROM t1;
+EXPLAIN SELECT * FROM t1 WHERE c1=1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref c1 c1 5 const 1 Using where; Using index
+EXPLAIN SELECT * FROM t1 WHERE c1=f1();
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref c1 c1 5 const 1 Using where; Using index
+EXPLAIN SELECT * FROM v1 WHERE c1=1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref c1 c1 5 const 1 Using where; Using index
+EXPLAIN SELECT * FROM v1 WHERE c1=f1();
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref c1 c1 5 const 1 Using where; Using index
+EXPLAIN SELECT * FROM t1 WHERE c1=f2(10);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref c1 c1 5 const 1 Using where; Using index
+EXPLAIN SELECT * FROM t1 WHERE c1=f2(c1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL c1 5 NULL 5 Using where; Using index
+EXPLAIN SELECT * FROM t1 WHERE c1=f2(rand());
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL c1 5 NULL 5 Using where; Using index
+DROP VIEW v1;
+DROP FUNCTION f1;
+DROP FUNCTION f2;
+DROP TABLE t1;
+End of 5.0 tests
diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result
index 5d41d60c37a..189722bfe9b 100644
--- a/mysql-test/r/trigger.result
+++ b/mysql-test/r/trigger.result
@@ -1933,6 +1933,34 @@ Before UPDATE, new=multi-UPDATE, SET for t2, but the trigger is fired, old=multi
After UPDATE, new=multi-UPDATE, SET for t2, but the trigger is fired, old=multi-UPDATE
drop view v1;
drop table t1, t2, t1_op_log;
+
+Bug#27248 Triggers: error if insert affects temporary table
+
+The bug was fixed by the fix for Bug#26141
+
+drop table if exists t1;
+drop temporary table if exists t2;
+create table t1 (s1 int);
+create temporary table t2 (s1 int);
+create trigger t1_bi before insert on t1 for each row insert into t2 values (0);
+create trigger t1_bd before delete on t1 for each row delete from t2;
+insert into t1 values (0);
+insert into t1 values (0);
+select * from t1;
+s1
+0
+0
+select * from t2;
+s1
+0
+0
+delete from t1;
+select * from t1;
+s1
+select * from t2;
+s1
+drop table t1;
+drop temporary table t2;
End of 5.0 tests
drop table if exists table_25411_a;
drop table if exists table_25411_b;
diff --git a/mysql-test/r/type_enum.result b/mysql-test/r/type_enum.result
index ec72a6eb995..051cfe61384 100644
--- a/mysql-test/r/type_enum.result
+++ b/mysql-test/r/type_enum.result
@@ -1829,4 +1829,28 @@ c1 + 0
0
2
DROP TABLE t1,t2;
+CREATE TABLE t1(a enum('a','b','c','d'));
+INSERT INTO t1 VALUES (4),(1),(0),(3);
+Warnings:
+Warning 1265 Data truncated for column 'a' at row 3
+SELECT a FROM t1;
+a
+d
+a
+
+c
+EXPLAIN SELECT a FROM t1 WHERE a=0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where
+SELECT a FROM t1 WHERE a=0;
+a
+
+ALTER TABLE t1 ADD PRIMARY KEY (a);
+EXPLAIN SELECT a FROM t1 WHERE a=0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 const PRIMARY PRIMARY 1 const 1 Using index
+SELECT a FROM t1 WHERE a=0;
+a
+
+DROP TABLE t1;
End of 5.1 tests
diff --git a/mysql-test/suite/binlog/t/disabled.def b/mysql-test/suite/binlog/t/disabled.def
index 76eeb5b00ef..888298bbb09 100644
--- a/mysql-test/suite/binlog/t/disabled.def
+++ b/mysql-test/suite/binlog/t/disabled.def
@@ -9,6 +9,3 @@
# Do not use any TAB characters for whitespace.
#
##############################################################################
-
-binlog_innodb : Bug#29806 2007-07-15 ingo master.err: InnoDB: Error: MySQL is freeing a thd
-binlog_killed : Bug#29806 2007-07-17 ingo master.err: InnoDB: Error: MySQL is freeing a thd
diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test
index fa50d75b8d2..99c9ae23801 100644
--- a/mysql-test/t/alter_table.test
+++ b/mysql-test/t/alter_table.test
@@ -902,3 +902,15 @@ SELECT * FROM t1;
ALTER TABLE t1 MODIFY COLUMN f3 INT AFTER f2;
SELECT * FROM t1;
DROP TABLE t1;
+
+#
+# BUG#29957 - alter_table.test fails
+#
+create table t1 (c char(10) default "Two");
+lock table t1 write;
+insert into t1 values ();
+alter table t1 modify c char(10) default "Three";
+unlock tables;
+select * from t1;
+check table t1;
+drop table t1;
diff --git a/mysql-test/t/check.test b/mysql-test/t/check.test
index eb72d75da3c..363f9d419d6 100644
--- a/mysql-test/t/check.test
+++ b/mysql-test/t/check.test
@@ -37,3 +37,12 @@ Create view v1 as Select * from t1;
Check Table v1,t2;
drop view v1;
drop table t1, t2;
+
+#
+# BUG#26325 - TEMPORARY TABLE "corrupt" after first read, according to CHECK
+# TABLE
+#
+CREATE TEMPORARY TABLE t1(a INT);
+CHECK TABLE t1;
+REPAIR TABLE t1;
+DROP TABLE t1;
diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test
index dd3037ce88d..341c019af6e 100644
--- a/mysql-test/t/create.test
+++ b/mysql-test/t/create.test
@@ -1122,6 +1122,35 @@ show create table t1;
drop table t1;
+--echo
+--echo Bug #26104 Bug on foreign key class constructor
+--echo
+--echo Check that ref_columns is initalized correctly in the constructor
+--echo and semantic checks in mysql_prepare_table work.
+--echo
+--echo We do not need a storage engine that supports foreign keys
+--echo for this test, as the checks are purely syntax-based, and the
+--echo syntax is supported for all engines.
+--echo
+--disable_warnings
+drop table if exists t1,t2;
+--enable_warnings
+
+create table t1(a int not null, b int not null, primary key (a, b));
+--error ER_WRONG_FK_DEF
+create table t2(a int not null, b int not null, c int not null, primary key (a),
+foreign key fk_bug26104 (b,c) references t1(a));
+drop table t1;
+
+#
+# Bug#15130:CREATE .. SELECT was denied to use advantages of the SQL_BIG_RESULT.
+#
+create table t1(f1 int,f2 int);
+insert into t1 value(1,1),(1,2),(1,3),(2,1),(2,2),(2,3);
+flush status;
+create table t2 select sql_big_result f1,count(f2) from t1 group by f1;
+show status like 'handler_read%';
+drop table t1,t2;
--echo End of 5.0 tests
diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def
index 07c5b4d56a3..368a659d939 100644
--- a/mysql-test/t/disabled.def
+++ b/mysql-test/t/disabled.def
@@ -24,5 +24,4 @@ ctype_big5 : BUG#26711 2007-06-21 Lars Test has never worked on Do
mysql_upgrade : Bug#28560 test links to /usr/local/mysql/lib libraries, causes non-determinism and failures on ABI breakage
-federated_innodb : Bug#29522 failed assertion in binlog_close_connection()
-lowercase_table3 : Bug#29839 2007-07-17 ingo Cannot find table test/T1 from the internal data dictionary
+federated_transactions : Bug#29523 Transactions do not work
diff --git a/mysql-test/t/federated.test b/mysql-test/t/federated.test
index a75eae8f8a0..6597c77e798 100644
--- a/mysql-test/t/federated.test
+++ b/mysql-test/t/federated.test
@@ -32,25 +32,28 @@ CREATE TABLE federated.t1 (
# test non-existant table
--replace_result $SLAVE_MYPORT SLAVE_PORT
---error 1434
eval CREATE TABLE federated.t1 (
`id` int(20) NOT NULL,
`name` varchar(32) NOT NULL default ''
)
ENGINE="FEDERATED" DEFAULT CHARSET=latin1
CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t3';
+--error 1431
+SELECT * FROM federated.t1;
+DROP TABLE federated.t1;
# test bad user/password
--replace_result $SLAVE_MYPORT SLAVE_PORT
---error 1429
eval CREATE TABLE federated.t1 (
`id` int(20) NOT NULL,
`name` varchar(32) NOT NULL default ''
)
ENGINE="FEDERATED" DEFAULT CHARSET=latin1
CONNECTION='mysql://user:pass@127.0.0.1:$SLAVE_MYPORT/federated/t1';
+--error 1429
+SELECT * FROM federated.t1;
+DROP TABLE federated.t1;
-DROP TABLE IF EXISTS federated.t1;
# # correct connection, same named tables
--replace_result $SLAVE_MYPORT SLAVE_PORT
eval CREATE TABLE federated.t1 (
@@ -1723,4 +1726,30 @@ connection slave;
drop table federated.t1;
+#
+# BUG#29875 Disable support for transactions
+#
+connection slave;
+CREATE TABLE federated.t1 (a INT PRIMARY KEY) DEFAULT CHARSET=utf8;
+connection master;
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+eval CREATE TABLE federated.t1 (a INT PRIMARY KEY)
+ ENGINE=FEDERATED
+ CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1'
+ DEFAULT CHARSET=utf8;
+
+SELECT transactions FROM information_schema.engines WHERE engine="FEDERATED";
+INSERT INTO federated.t1 VALUES (1);
+SET autocommit=0;
+INSERT INTO federated.t1 VALUES (2);
+ROLLBACK;
+SET autocommit=1;
+SELECT * FROM federated.t1;
+
+DROP TABLE federated.t1;
+connection slave;
+DROP TABLE federated.t1;
+
+--echo End of 5.1 tests
+
source include/federated_cleanup.inc;
diff --git a/mysql-test/t/federated_bug_25714.test b/mysql-test/t/federated_bug_25714.test
new file mode 100644
index 00000000000..9c185181511
--- /dev/null
+++ b/mysql-test/t/federated_bug_25714.test
@@ -0,0 +1,47 @@
+--source include/have_bug25714.inc
+source include/federated.inc;
+
+
+connection slave;
+--disable_warnings
+DROP TABLE IF EXISTS federated.bug_13118_table;
+--enable_warnings
+
+CREATE TABLE federated.t1 (
+ `id` int auto_increment primary key,
+ `value` int
+ ) ENGINE=MyISAM;
+INSERT INTO federated.t1 SET value=1;
+INSERT INTO federated.t1 SET value=2;
+INSERT INTO federated.t1 SET value=2;
+
+connection master;
+--disable_warnings
+DROP TABLE IF EXISTS federated.t1;
+--enable_warnings
+
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+eval CREATE TABLE federated.t1 (
+ `id` int auto_increment primary key,
+ `value` int
+ ) ENGINE=FEDERATED
+ CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1';
+
+SELECT * from federated.t1;
+
+INSERT INTO federated.t1 SET value=4;
+
+SELECT LAST_INSERT_ID();
+
+--exec $MYSQL_BUG25714 $SLAVE_MYPORT
+--exec $MYSQL_BUG25714 $MASTER_MYPORT
+
+SELECT * from federated.t1;
+
+DROP TABLE federated.t1;
+connection slave;
+DROP TABLE federated.t1;
+
+
+source include/federated_cleanup.inc;
+
diff --git a/mysql-test/t/having.test b/mysql-test/t/having.test
index 41266cc6d32..683abfd3783 100644
--- a/mysql-test/t/having.test
+++ b/mysql-test/t/having.test
@@ -151,6 +151,32 @@ EXPLAIN SELECT 0 AS x, a FROM t1 GROUP BY x,a HAVING x=1 AND a > 1;
DROP table t1;
+#
+# Bug #29911: HAVING clause depending on constant table and evaluated to false
+#
+
+CREATE TABLE t1 (a int PRIMARY KEY);
+CREATE TABLE t2 (b int PRIMARY KEY, a int);
+CREATE TABLE t3 (b int, flag int);
+
+INSERT INTO t1 VALUES (1);
+INSERT INTO t2 VALUES (1,1), (2,1), (3,1);
+INSERT INTO t3(b,flag) VALUES (2, 1);
+
+SELECT t1.a
+ FROM t1 INNER JOIN t2 ON t1.a=t2.a LEFT JOIN t3 ON t2.b=t3.b
+ GROUP BY t1.a, t2.b HAVING MAX(t3.flag)=0;
+
+SELECT DISTINCT t1.a, MAX(t3.flag)
+ FROM t1 INNER JOIN t2 ON t1.a=t2.a LEFT JOIN t3 ON t2.b=t3.b
+ GROUP BY t1.a, t2.b HAVING MAX(t3.flag)=0;
+
+SELECT DISTINCT t1.a
+ FROM t1 INNER JOIN t2 ON t1.a=t2.a LEFT JOIN t3 ON t2.b=t3.b
+ GROUP BY t1.a, t2.b HAVING MAX(t3.flag)=0;
+
+DROP TABLE t1,t2,t3;
+
# End of 4.1 tests
#
diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test
index 96b2ffda7d6..140aac3b9c3 100644
--- a/mysql-test/t/innodb.test
+++ b/mysql-test/t/innodb.test
@@ -1178,7 +1178,7 @@ drop table t2;
# Clean up filename -- embedded server reports whole path without .frm,
# regular server reports relative path with .frm (argh!)
--replace_result \\ / $MYSQL_TEST_DIR . /var/master-data/ / t2.frm t2
---error 1005
+--error ER_WRONG_FK_DEF
create table t2 (id int(11) not null, id2 int(11) not null, constraint t1_id_fk foreign key (id2,id) references t1 (id)) engine = innodb;
# bug#3749
diff --git a/mysql-test/t/lowercase_table3.test b/mysql-test/t/lowercase_table3.test
index 75f6e5188c5..51385b4b178 100644
--- a/mysql-test/t/lowercase_table3.test
+++ b/mysql-test/t/lowercase_table3.test
@@ -27,9 +27,9 @@ flush tables;
# storing things in lower case.
#
-CREATE TABLE t1 (a int) ENGINE=INNODB;
+CREATE TABLE bug29839 (a int) ENGINE=INNODB;
--error 1146
-SELECT * from T1;
-drop table t1;
+SELECT * from BUG29839;
+drop table bug29839;
# End of 4.1 tests
diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test
index 38d8a07fe48..4e8d3ae916e 100644
--- a/mysql-test/t/mysqldump.test
+++ b/mysql-test/t/mysqldump.test
@@ -1555,6 +1555,28 @@ SELECT * FROM v1;
DROP VIEW v1;
--echo #
+--echo # Bug #29788: mysqldump discards the NO_AUTO_VALUE_ON_ZERO value of
+--echo # the SQL_MODE variable after the dumping of triggers.
+--echo #
+
+CREATE TABLE t1 (c1 INT);
+CREATE TRIGGER t1bd BEFORE DELETE ON t1 FOR EACH ROW BEGIN END;
+
+CREATE TABLE t2 (c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY);
+
+SET @TMP_SQL_MODE = @@SQL_MODE;
+SET SQL_MODE = 'NO_AUTO_VALUE_ON_ZERO';
+INSERT INTO t2 VALUES (0), (1), (2);
+SET SQL_MODE = @TMP_SQL_MODE;
+SELECT * FROM t2;
+
+--exec $MYSQL_DUMP --routines test >$MYSQLTEST_VARDIR/tmp/bug29788.sql
+--exec $MYSQL test < $MYSQLTEST_VARDIR/tmp/bug29788.sql
+SELECT * FROM t2;
+
+DROP TABLE t1,t2;
+
+--echo #
--echo # End of 5.0 tests
--echo #
diff --git a/mysql-test/t/mysqlslap.test b/mysql-test/t/mysqlslap.test
index 2a7bbfed932..192aefb0e03 100644
--- a/mysql-test/t/mysqlslap.test
+++ b/mysql-test/t/mysqlslap.test
@@ -36,3 +36,5 @@
--exec $MYSQL_SLAP --silent --concurrency=5 --iterations=1 --number-int-cols=2 --number-char-cols=3 --auto-generate-sql --auto-generate-sql-guid-primary --auto-generate-sql-load-type=key --auto-generate-sql-execute-number=5 --auto-generate-sql-secondary-indexes=3
--exec $MYSQL_SLAP --only-print --delimiter=";" --query="select * from t1;select * from t2" --create="CREATE TABLE t1 (id int, name varchar(64)); create table t2(foo1 varchar(32), foo2 varchar(32)); INSERT INTO t1 VALUES (1, 'This is a test'); insert into t2 values ('test', 'test2')" --engine="heap,myisam" --post-query="SHOW TABLES" --pre-query="SHOW TABLES";
+
+ --exec $MYSQL_SLAP --only-print --delimiter=";" --query="select * from t1;select * from t2" --create="CREATE TABLE t1 (id int, name varchar(64)); create table t2(foo1 varchar(32), foo2 varchar(32)); INSERT INTO t1 VALUES (1, 'This is a test'); insert into t2 values ('test', 'test2')" --engine="heap,myisam" --post-query="SHOW TABLES" --pre-query="SHOW TABLES" --number-of-queries=6 --commit=1;
diff --git a/mysql-test/t/sp-prelocking.test b/mysql-test/t/sp-prelocking.test
index ec5b7fbad7c..60e97260839 100644
--- a/mysql-test/t/sp-prelocking.test
+++ b/mysql-test/t/sp-prelocking.test
@@ -333,4 +333,27 @@ insert into bug_27907_t1(a) values (1);
drop table bug_27907_t1;
+--echo
+--echo Bug#22427 create table if not exists + stored function results in
+--echo inconsistent behavior
+--echo
+--echo Add a test case, the bug itself was fixed by the patch for
+--echo Bug#20662
+--echo
+--disable_warnings
+drop table if exists t1;
+drop function if exists f_bug22427;
+--enable_warnings
+create table t1 (i int);
+insert into t1 values (1);
+create function f_bug22427() returns int return (select max(i) from t1);
+select f_bug22427();
+# Until this bug was fixed, the following emitted error
+# ERROR 1213: Deadlock found when trying to get lock
+create table if not exists t1 select f_bug22427() as i;
+--error ER_TABLE_EXISTS_ERROR
+create table t1 select f_bug22427() as i;
+drop table t1;
+drop function f_bug22427;
+
--echo End of 5.0 tests
diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test
index 7bd20d226c2..dfda1b7a6ab 100644
--- a/mysql-test/t/sp.test
+++ b/mysql-test/t/sp.test
@@ -24,6 +24,8 @@ use test;
#
--disable_warnings
drop table if exists t1,t2,t3,t4;
+drop function if exists f1;
+drop function if exists f2;
--enable_warnings
create table t1 (
id char(16) not null default '',
@@ -7214,7 +7216,7 @@ CREATE TABLE t2 (a int auto_increment primary key, b int) engine=innodb;
set @a=0;
delimiter |;
-CREATE function bug27354() RETURNS int deterministic
+CREATE function bug27354() RETURNS int not deterministic
begin
insert into t1 values (null);
set @a=@a+1;
@@ -7368,3 +7370,33 @@ where ROUTINE_NAME = "proc_26302";
drop procedure proc_26302;
+# Bug #29338: no optimization for stored functions with a trivial body
+# always returning constant.
+#
+
+CREATE FUNCTION f1() RETURNS INT DETERMINISTIC RETURN 2;
+CREATE FUNCTION f2(I INT) RETURNS INT DETERMINISTIC RETURN 3;
+
+CREATE TABLE t1 (c1 INT, INDEX(c1));
+
+INSERT INTO t1 VALUES (1), (2), (3), (4), (5);
+
+CREATE VIEW v1 AS SELECT c1 FROM t1;
+
+EXPLAIN SELECT * FROM t1 WHERE c1=1;
+EXPLAIN SELECT * FROM t1 WHERE c1=f1();
+
+EXPLAIN SELECT * FROM v1 WHERE c1=1;
+EXPLAIN SELECT * FROM v1 WHERE c1=f1();
+
+EXPLAIN SELECT * FROM t1 WHERE c1=f2(10);
+EXPLAIN SELECT * FROM t1 WHERE c1=f2(c1);
+EXPLAIN SELECT * FROM t1 WHERE c1=f2(rand());
+
+
+DROP VIEW v1;
+DROP FUNCTION f1;
+DROP FUNCTION f2;
+DROP TABLE t1;
+
+--echo End of 5.0 tests
diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test
index 8db432b27c3..c7251040544 100644
--- a/mysql-test/t/trigger.test
+++ b/mysql-test/t/trigger.test
@@ -2194,6 +2194,29 @@ drop table t1, t2, t1_op_log;
#
# TODO: test LOAD DATA INFILE
+#
+--echo
+--echo Bug#27248 Triggers: error if insert affects temporary table
+--echo
+--echo The bug was fixed by the fix for Bug#26141
+--echo
+--disable_warnings
+drop table if exists t1;
+drop temporary table if exists t2;
+--enable_warnings
+create table t1 (s1 int);
+create temporary table t2 (s1 int);
+create trigger t1_bi before insert on t1 for each row insert into t2 values (0);
+create trigger t1_bd before delete on t1 for each row delete from t2;
+insert into t1 values (0);
+insert into t1 values (0);
+select * from t1;
+select * from t2;
+delete from t1;
+select * from t1;
+select * from t2;
+drop table t1;
+drop temporary table t2;
--echo End of 5.0 tests
#
diff --git a/mysql-test/t/type_enum.test b/mysql-test/t/type_enum.test
index 4d5d5ec8a86..2043342e2c8 100644
--- a/mysql-test/t/type_enum.test
+++ b/mysql-test/t/type_enum.test
@@ -200,4 +200,24 @@ CREATE TABLE t2 SELECT * FROM t1;
SELECT c1 + 0 FROM t2;
DROP TABLE t1,t2;
+
+#
+# Bug#29661: Lookup by 0 for a primary index over a enum type
+#
+
+CREATE TABLE t1(a enum('a','b','c','d'));
+INSERT INTO t1 VALUES (4),(1),(0),(3);
+
+SELECT a FROM t1;
+
+EXPLAIN SELECT a FROM t1 WHERE a=0;
+SELECT a FROM t1 WHERE a=0;
+
+ALTER TABLE t1 ADD PRIMARY KEY (a);
+
+EXPLAIN SELECT a FROM t1 WHERE a=0;
+SELECT a FROM t1 WHERE a=0;
+
+DROP TABLE t1;
+
--echo End of 5.1 tests
diff --git a/sql-common/client.c b/sql-common/client.c
index 6d63c457390..cdf9eed8574 100644
--- a/sql-common/client.c
+++ b/sql-common/client.c
@@ -1226,12 +1226,12 @@ unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields,
/* fields count may be wrong */
DBUG_ASSERT((uint) (field - result) < fields);
cli_fetch_lengths(&lengths[0], row->data, default_value ? 8 : 7);
- field->catalog = strdup_root(alloc,(char*) row->data[0]);
- field->db = strdup_root(alloc,(char*) row->data[1]);
- field->table = strdup_root(alloc,(char*) row->data[2]);
- field->org_table= strdup_root(alloc,(char*) row->data[3]);
- field->name = strdup_root(alloc,(char*) row->data[4]);
- field->org_name = strdup_root(alloc,(char*) row->data[5]);
+ field->catalog= strmake_root(alloc,(char*) row->data[0], lengths[0]);
+ field->db= strmake_root(alloc,(char*) row->data[1], lengths[1]);
+ field->table= strmake_root(alloc,(char*) row->data[2], lengths[2]);
+ field->org_table= strmake_root(alloc,(char*) row->data[3], lengths[3]);
+ field->name= strmake_root(alloc,(char*) row->data[4], lengths[4]);
+ field->org_name= strmake_root(alloc,(char*) row->data[5], lengths[5]);
field->catalog_length= lengths[0];
field->db_length= lengths[1];
@@ -1252,7 +1252,7 @@ unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields,
field->flags|= NUM_FLAG;
if (default_value && row->data[7])
{
- field->def=strdup_root(alloc,(char*) row->data[7]);
+ field->def=strmake_root(alloc,(char*) row->data[7], lengths[7]);
field->def_length= lengths[7];
}
else
diff --git a/sql/field.cc b/sql/field.cc
index a970a6e4318..3213f84ee3e 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -7901,8 +7901,11 @@ int Field_enum::store(longlong nr, bool unsigned_val)
if ((ulonglong) nr > typelib->count || nr == 0)
{
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
- nr=0;
- error=1;
+ if (nr != 0 || table->in_use->count_cuted_fields)
+ {
+ nr= 0;
+ error= 1;
+ }
}
store_type((ulonglong) (uint) nr);
return error;
diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc
index 0b8ffd4a2fb..dd29eb17059 100644
--- a/sql/ha_ndbcluster.cc
+++ b/sql/ha_ndbcluster.cc
@@ -4383,7 +4383,10 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type)
trans= ndb->startTransaction();
if (trans == NULL)
+ {
+ thd_ndb->lock_count= 0;
ERR_RETURN(ndb->getNdbError());
+ }
thd_ndb->init_open_tables();
thd_ndb->stmt= trans;
thd_ndb->query_state&= NDB_QUERY_NORMAL;
@@ -4409,7 +4412,10 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type)
trans= ndb->startTransaction();
if (trans == NULL)
+ {
+ thd_ndb->lock_count= 0;
ERR_RETURN(ndb->getNdbError());
+ }
thd_ndb->init_open_tables();
thd_ndb->all= trans;
thd_ndb->query_state&= NDB_QUERY_NORMAL;
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index e4924e8e8f2..d46b3a3bb08 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -1142,6 +1142,12 @@ int ha_partition::prepare_new_partition(TABLE *table,
create_flag= TRUE;
if ((error= file->ha_open(table, part_name, m_mode, m_open_test_lock)))
goto error;
+ /*
+ Note: if you plan to add another call that may return failure,
+ better to do it before external_lock() as cleanup_new_partition()
+ assumes that external_lock() is last call that may fail here.
+ Otherwise see description for cleanup_new_partition().
+ */
if ((error= file->external_lock(current_thd, m_lock_type)))
goto error;
@@ -1164,6 +1170,14 @@ error:
NONE
DESCRIPTION
+ This function is called immediately after prepare_new_partition() in
+ case the latter fails.
+
+ In prepare_new_partition() last call that may return failure is
+ external_lock(). That means if prepare_new_partition() fails,
+ partition does not have external lock. Thus no need to call
+ external_lock(F_UNLCK) here.
+
TODO:
We must ensure that in the case that we get an error during the process
that we call external_lock with F_UNLCK, close the table and delete the
@@ -1182,7 +1196,6 @@ void ha_partition::cleanup_new_partition(uint part_count)
m_file= m_added_file;
m_added_file= NULL;
- external_lock(current_thd, F_UNLCK);
/* delete_table also needed, a bit more complex */
close();
diff --git a/sql/handler.cc b/sql/handler.cc
index 2d836b30862..55e2e478027 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -2355,7 +2355,13 @@ static bool update_frm_version(TABLE *table)
int result= 1;
DBUG_ENTER("update_frm_version");
- if (table->s->mysql_version != MYSQL_VERSION_ID)
+ /*
+ No need to update frm version in case table was created or checked
+ by server with the same version. This also ensures that we do not
+ update frm version for temporary tables as this code doesn't support
+ temporary tables.
+ */
+ if (table->s->mysql_version == MYSQL_VERSION_ID)
DBUG_RETURN(0);
strxmov(path, table->s->normalized_path.str, reg_ext, NullS);
diff --git a/sql/item_func.cc b/sql/item_func.cc
index f14091b4592..4012371bedb 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -5599,10 +5599,20 @@ Item_func_sp::fix_fields(THD *thd, Item **ref)
#endif /* ! NO_EMBEDDED_ACCESS_CHECKS */
}
+ if (!m_sp->m_chistics->detistic)
+ used_tables_cache |= RAND_TABLE_BIT;
DBUG_RETURN(res);
}
+void Item_func_sp::update_used_tables()
+{
+ Item_func::update_used_tables();
+ if (!m_sp->m_chistics->detistic)
+ used_tables_cache |= RAND_TABLE_BIT;
+}
+
+
/*
uuid_short handling.
diff --git a/sql/item_func.h b/sql/item_func.h
index 568effb2f63..ea22e35773d 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -1472,7 +1472,7 @@ public:
virtual ~Item_func_sp()
{}
- table_map used_tables() const { return RAND_TABLE_BIT; }
+ void update_used_tables();
void cleanup();
diff --git a/sql/lock.cc b/sql/lock.cc
index 4260a031def..63d0807b975 100644
--- a/sql/lock.cc
+++ b/sql/lock.cc
@@ -60,6 +60,11 @@
- When calling UNLOCK TABLES we call mysql_unlock_tables() for all
tables used in LOCK TABLES
+ If table_handler->external_lock(thd, locktype) fails, we call
+ table_handler->external_lock(thd, F_UNLCK) for each table that was locked,
+ excluding one that caused failure. That means handler must cleanup itself
+ in case external_lock() fails.
+
TODO:
Change to use my_malloc() ONLY when using LOCK TABLES command or when
we are forced to use mysql_lock_merge.
@@ -269,8 +274,9 @@ static int lock_external(THD *thd, TABLE **tables, uint count)
if ((error=(*tables)->file->ha_external_lock(thd,lock_type)))
{
print_lock_error(error, (*tables)->file->table_type());
- for (; i-- ; tables--)
+ while (--i)
{
+ tables--;
(*tables)->file->ha_external_lock(thd, F_UNLCK);
(*tables)->current_lock=F_UNLCK;
}
diff --git a/sql/set_var.cc b/sql/set_var.cc
index bd5234b42be..7f3e808090d 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -2220,9 +2220,9 @@ void sys_var_log_output::set_default(THD *thd, enum_var_type type)
{
pthread_mutex_lock(&LOCK_global_system_variables);
logger.lock();
- logger.init_slow_log(LOG_TABLE);
- logger.init_general_log(LOG_TABLE);
- *value= LOG_TABLE;
+ logger.init_slow_log(LOG_FILE);
+ logger.init_general_log(LOG_FILE);
+ *value= LOG_FILE;
logger.unlock();
pthread_mutex_unlock(&LOCK_global_system_variables);
}
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 6fd57c5a428..f1319010270 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -64,11 +64,11 @@ Prelock_error_handler::handle_error(uint sql_errno,
if (sql_errno == ER_NO_SUCH_TABLE)
{
m_handled_errors++;
- return TRUE; // 'TRUE', as per coding style
+ return TRUE;
}
m_unhandled_errors++;
- return FALSE; // 'FALSE', as per coding style
+ return FALSE;
}
@@ -3533,7 +3533,7 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags)
*/
for (tables= *start; tables ;tables= tables->next_global)
{
- safe_to_ignore_table= FALSE; // 'FALSE', as per coding style
+ safe_to_ignore_table= FALSE;
if (tables->lock_type == TL_WRITE_DEFAULT)
{
@@ -3797,13 +3797,6 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type)
if (table)
{
-#if defined( __WIN__)
- /* Win32 can't drop a file that is open */
- if (lock_type == TL_WRITE_ALLOW_READ)
- {
- lock_type= TL_WRITE;
- }
-#endif /* __WIN__ */
table_list->lock_type= lock_type;
table_list->table= table;
table->grant= table_list->grant;
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index cab9ef94d6d..39a7aebcc5d 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -878,10 +878,14 @@ ulong Query_cache::resize(ulong query_cache_size_arg)
query_cache_size= query_cache_size_arg;
ulong new_query_cache_size= init_cache();
- DBUG_EXECUTE("check_querycache",check_integrity(0););
-
STRUCT_LOCK(&structure_guard_mutex);
m_cache_status= Query_cache::NO_FLUSH_IN_PROGRESS;
+ /*
+ Must not call check_integrity() with
+ m_cache_status != Query_cache::NO_FLUSH_IN_PROGRESS.
+ It would wait forever.
+ */
+ DBUG_EXECUTE("check_querycache",check_integrity(1););
pthread_cond_signal(&COND_cache_status_changed);
STRUCT_UNLOCK(&structure_guard_mutex);
@@ -4025,6 +4029,10 @@ my_bool Query_cache::check_integrity(bool locked)
Query_cache_block * block = first_block;
do
{
+ /* When checking at system start, there is no block. */
+ if (!block)
+ break;
+
DBUG_PRINT("qcache", ("block 0x%lx, type %u...",
(ulong) block, (uint) block->type));
// Check allignment
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 7fa66893f69..71c13e001ee 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -189,7 +189,7 @@ public:
Table_ident *table, List<Key_part_spec> &ref_cols,
uint delete_opt_arg, uint update_opt_arg, uint match_opt_arg)
:Key(FOREIGN_KEY, name_arg, &default_key_create_info, 0, cols),
- ref_table(table), ref_columns(cols),
+ ref_table(table), ref_columns(ref_cols),
delete_opt(delete_opt_arg), update_opt(update_opt_arg),
match_opt(match_opt_arg)
{}
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index b14241bbef3..b747c706f75 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -1763,18 +1763,18 @@ Delayed_insert *find_handler(THD *thd, TABLE_LIST *table_list)
thd->proc_info="waiting for delay_list";
pthread_mutex_lock(&LOCK_delayed_insert); // Protect master list
I_List_iterator<Delayed_insert> it(delayed_threads);
- Delayed_insert *tmp;
- while ((tmp=it++))
+ Delayed_insert *di;
+ while ((di= it++))
{
- if (!strcmp(tmp->thd.db, table_list->db) &&
- !strcmp(table_list->table_name, tmp->table->s->table_name.str))
+ if (!strcmp(table_list->db, di->table_list.db) &&
+ !strcmp(table_list->table_name, di->table_list.table_name))
{
- tmp->lock();
+ di->lock();
break;
}
}
pthread_mutex_unlock(&LOCK_delayed_insert); // For unlink from list
- return tmp;
+ return di;
}
@@ -1800,21 +1800,41 @@ Delayed_insert *find_handler(THD *thd, TABLE_LIST *table_list)
Two latter cases indicate a request for lock upgrade.
XXX: why do we regard INSERT DELAYED into a view as an error and
- do not simply a lock upgrade?
+ do not simply perform a lock upgrade?
+
+ TODO: The approach with using two mutexes to work with the
+ delayed thread list -- LOCK_delayed_insert and
+ LOCK_delayed_create -- is redundant, and we only need one of
+ them to protect the list. The reason we have two locks is that
+ we do not want to block look-ups in the list while we're waiting
+ for the newly created thread to open the delayed table. However,
+ this wait itself is redundant -- we always call get_local_table
+ later on, and there wait again until the created thread acquires
+ a table lock.
+
+ As is redundant the concept of locks_in_memory, since we already
+ have another counter with similar semantics - tables_in_use,
+ both of them are devoted to counting the number of producers for
+ a given consumer (delayed insert thread), only at different
+ stages of producer-consumer relationship.
+
+ 'dead' and 'status' variables in Delayed_insert are redundant
+ too, since there is already 'di->thd.killed' and
+ di->stacked_inserts.
*/
static
bool delayed_get_table(THD *thd, TABLE_LIST *table_list)
{
int error;
- Delayed_insert *tmp;
+ Delayed_insert *di;
DBUG_ENTER("delayed_get_table");
/* Must be set in the parser */
DBUG_ASSERT(table_list->db);
/* Find the thread which handles this table. */
- if (!(tmp=find_handler(thd,table_list)))
+ if (!(di= find_handler(thd, table_list)))
{
/*
No match. Create a new thread to handle the table, but
@@ -1828,9 +1848,9 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list)
The first search above was done without LOCK_delayed_create.
Another thread might have created the handler in between. Search again.
*/
- if (! (tmp= find_handler(thd, table_list)))
+ if (! (di= find_handler(thd, table_list)))
{
- if (!(tmp=new Delayed_insert()))
+ if (!(di= new Delayed_insert()))
{
my_error(ER_OUTOFMEMORY,MYF(0),sizeof(Delayed_insert));
thd->fatal_error();
@@ -1839,28 +1859,30 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list)
pthread_mutex_lock(&LOCK_thread_count);
thread_count++;
pthread_mutex_unlock(&LOCK_thread_count);
- tmp->thd.set_db(table_list->db, strlen(table_list->db));
- tmp->thd.query= my_strdup(table_list->table_name,MYF(MY_WME));
- if (tmp->thd.db == NULL || tmp->thd.query == NULL)
+ di->thd.set_db(table_list->db, strlen(table_list->db));
+ di->thd.query= my_strdup(table_list->table_name, MYF(MY_WME));
+ if (di->thd.db == NULL || di->thd.query == NULL)
{
/* The error is reported */
- delete tmp;
+ delete di;
thd->fatal_error();
goto end_create;
}
- tmp->table_list= *table_list; // Needed to open table
- tmp->table_list.alias= tmp->table_list.table_name= tmp->thd.query;
- tmp->lock();
- pthread_mutex_lock(&tmp->mutex);
- if ((error=pthread_create(&tmp->thd.real_id,&connection_attrib,
- handle_delayed_insert,(void*) tmp)))
+ di->table_list= *table_list; // Needed to open table
+ /* Replace volatile strings with local copies */
+ di->table_list.alias= di->table_list.table_name= di->thd.query;
+ di->table_list.db= di->thd.db;
+ di->lock();
+ pthread_mutex_lock(&di->mutex);
+ if ((error= pthread_create(&di->thd.real_id, &connection_attrib,
+ handle_delayed_insert, (void*) di)))
{
DBUG_PRINT("error",
("Can't create thread to handle delayed insert (error %d)",
error));
- pthread_mutex_unlock(&tmp->mutex);
- tmp->unlock();
- delete tmp;
+ pthread_mutex_unlock(&di->mutex);
+ di->unlock();
+ delete di;
my_error(ER_CANT_CREATE_THREAD, MYF(0), error);
thd->fatal_error();
goto end_create;
@@ -1868,15 +1890,15 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list)
/* Wait until table is open */
thd->proc_info="waiting for handler open";
- while (!tmp->thd.killed && !tmp->table && !thd->killed)
+ while (!di->thd.killed && !di->table && !thd->killed)
{
- pthread_cond_wait(&tmp->cond_client,&tmp->mutex);
+ pthread_cond_wait(&di->cond_client, &di->mutex);
}
- pthread_mutex_unlock(&tmp->mutex);
+ pthread_mutex_unlock(&di->mutex);
thd->proc_info="got old table";
- if (tmp->thd.killed)
+ if (di->thd.killed)
{
- if (tmp->thd.net.report_error)
+ if (di->thd.net.report_error)
{
/*
Copy the error message. Note that we don't treat fatal
@@ -1884,31 +1906,34 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list)
main thread. Use of my_message will enable stored
procedures continue handlers.
*/
- my_message(tmp->thd.net.last_errno, tmp->thd.net.last_error,
+ my_message(di->thd.net.last_errno, di->thd.net.last_error,
MYF(0));
}
- tmp->unlock();
+ di->unlock();
goto end_create;
}
if (thd->killed)
{
- tmp->unlock();
+ di->unlock();
goto end_create;
}
+ pthread_mutex_lock(&LOCK_delayed_insert);
+ delayed_threads.append(di);
+ pthread_mutex_unlock(&LOCK_delayed_insert);
}
pthread_mutex_unlock(&LOCK_delayed_create);
}
- pthread_mutex_lock(&tmp->mutex);
- table_list->table= tmp->get_local_table(thd);
- pthread_mutex_unlock(&tmp->mutex);
+ pthread_mutex_lock(&di->mutex);
+ table_list->table= di->get_local_table(thd);
+ pthread_mutex_unlock(&di->mutex);
if (table_list->table)
{
DBUG_ASSERT(thd->net.report_error == 0);
- thd->di=tmp;
+ thd->di= di;
}
/* Unlock the delayed insert object after its last access. */
- tmp->unlock();
+ di->unlock();
DBUG_RETURN((table_list->table == NULL));
end_create:
@@ -1938,7 +1963,7 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd)
my_ptrdiff_t adjust_ptrs;
Field **field,**org_field, *found_next_number_field;
TABLE *copy;
- TABLE_SHARE *share= table->s;
+ TABLE_SHARE *share;
uchar *bitmap;
DBUG_ENTER("Delayed_insert::get_local_table");
@@ -1962,6 +1987,7 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd)
goto error;
}
}
+ share= table->s;
/*
Allocate memory for the TABLE object, the field pointers array, and
@@ -2157,26 +2183,26 @@ void kill_delayed_threads(void)
VOID(pthread_mutex_lock(&LOCK_delayed_insert)); // For unlink from list
I_List_iterator<Delayed_insert> it(delayed_threads);
- Delayed_insert *tmp;
- while ((tmp=it++))
+ Delayed_insert *di;
+ while ((di= it++))
{
- tmp->thd.killed= THD::KILL_CONNECTION;
- if (tmp->thd.mysys_var)
+ di->thd.killed= THD::KILL_CONNECTION;
+ if (di->thd.mysys_var)
{
- pthread_mutex_lock(&tmp->thd.mysys_var->mutex);
- if (tmp->thd.mysys_var->current_cond)
+ pthread_mutex_lock(&di->thd.mysys_var->mutex);
+ if (di->thd.mysys_var->current_cond)
{
/*
We need the following test because the main mutex may be locked
in handle_delayed_insert()
*/
- if (&tmp->mutex != tmp->thd.mysys_var->current_mutex)
- pthread_mutex_lock(tmp->thd.mysys_var->current_mutex);
- pthread_cond_broadcast(tmp->thd.mysys_var->current_cond);
- if (&tmp->mutex != tmp->thd.mysys_var->current_mutex)
- pthread_mutex_unlock(tmp->thd.mysys_var->current_mutex);
+ if (&di->mutex != di->thd.mysys_var->current_mutex)
+ pthread_mutex_lock(di->thd.mysys_var->current_mutex);
+ pthread_cond_broadcast(di->thd.mysys_var->current_cond);
+ if (&di->mutex != di->thd.mysys_var->current_mutex)
+ pthread_mutex_unlock(di->thd.mysys_var->current_mutex);
}
- pthread_mutex_unlock(&tmp->thd.mysys_var->mutex);
+ pthread_mutex_unlock(&di->thd.mysys_var->mutex);
}
}
VOID(pthread_mutex_unlock(&LOCK_delayed_insert)); // For unlink from list
@@ -2250,11 +2276,6 @@ pthread_handler_t handle_delayed_insert(void *arg)
}
di->table->copy_blobs=1;
- /* One can now use this */
- pthread_mutex_lock(&LOCK_delayed_insert);
- delayed_threads.append(di);
- pthread_mutex_unlock(&LOCK_delayed_insert);
-
/* Tell client that the thread is initialized */
pthread_cond_signal(&di->cond_client);
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 9f69e7dee05..8ab4dee12ac 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -124,7 +124,7 @@ Lex_input_stream::Lex_input_stream(THD *thd,
m_tok_start_prev(NULL),
m_buf(buffer),
m_buf_length(length),
- m_echo(true),
+ m_echo(TRUE),
m_cpp_tok_start(NULL),
m_cpp_tok_start_prev(NULL),
m_cpp_tok_end(NULL),
@@ -1200,7 +1200,7 @@ int MYSQLlex(void *arg, void *yythd)
{
lip->in_comment= DISCARD_COMMENT;
/* Accept '/' '*' '!', but do not keep this marker. */
- lip->set_echo(false);
+ lip->set_echo(FALSE);
lip->yySkip();
lip->yySkip();
lip->yySkip();
@@ -1233,7 +1233,7 @@ int MYSQLlex(void *arg, void *yythd)
if (version <= MYSQL_VERSION_ID)
{
/* Expand the content of the special comment as real code */
- lip->set_echo(true);
+ lip->set_echo(TRUE);
state=MY_LEX_START;
break;
}
@@ -1241,7 +1241,7 @@ int MYSQLlex(void *arg, void *yythd)
else
{
state=MY_LEX_START;
- lip->set_echo(true);
+ lip->set_echo(TRUE);
break;
}
}
@@ -1261,7 +1261,7 @@ int MYSQLlex(void *arg, void *yythd)
if (! lip->eof())
lip->yySkip(); // remove last '/'
state = MY_LEX_START; // Try again
- lip->set_echo(true);
+ lip->set_echo(TRUE);
break;
case MY_LEX_END_LONG_COMMENT:
if ((lip->in_comment != NO_COMMENT) && lip->yyPeek() == '/')
@@ -1272,7 +1272,7 @@ int MYSQLlex(void *arg, void *yythd)
lip->set_echo(lip->in_comment == PRESERVE_COMMENT);
lip->yySkipn(2);
/* And start recording the tokens again */
- lip->set_echo(true);
+ lip->set_echo(TRUE);
lip->in_comment=NO_COMMENT;
state=MY_LEX_START;
}
@@ -1297,7 +1297,7 @@ int MYSQLlex(void *arg, void *yythd)
lip->found_semicolon= lip->get_ptr();
thd->server_status|= SERVER_MORE_RESULTS_EXISTS;
lip->next_state= MY_LEX_END;
- lip->set_echo(true);
+ lip->set_echo(TRUE);
return (END_OF_INPUT);
}
state= MY_LEX_CHAR; // Return ';'
@@ -1309,9 +1309,9 @@ int MYSQLlex(void *arg, void *yythd)
if (lip->eof())
{
lip->yyUnget(); // Reject the last '\0'
- lip->set_echo(false);
+ lip->set_echo(FALSE);
lip->yySkip();
- lip->set_echo(true);
+ lip->set_echo(TRUE);
lip->next_state=MY_LEX_END; // Mark for next loop
return(END_OF_INPUT);
}
@@ -1770,7 +1770,7 @@ TABLE_LIST *st_select_lex_node::add_table_to_list (THD *thd, Table_ident *table,
LEX_STRING *alias,
ulong table_join_options,
thr_lock_type flags,
- List<index_hint> *hints,
+ List<Index_hint> *hints,
LEX_STRING *option)
{
return 0;
@@ -2723,7 +2723,7 @@ void st_select_lex::set_index_hint_type(enum index_hint_type type,
void st_select_lex::alloc_index_hints (THD *thd)
{
- index_hints= new (thd->mem_root) List<index_hint>();
+ index_hints= new (thd->mem_root) List<Index_hint>();
}
@@ -2744,7 +2744,7 @@ void st_select_lex::alloc_index_hints (THD *thd)
bool st_select_lex::add_index_hint (THD *thd, char *str, uint length)
{
return index_hints->push_front (new (thd->mem_root)
- index_hint(current_index_hint_type,
+ Index_hint(current_index_hint_type,
current_index_hint_clause,
str, length));
}
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 4ac59fbacde..b769930958e 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -236,7 +236,7 @@ typedef uchar index_clause_map;
INDEX_HINT_MASK_ORDER)
/* Single element of an USE/FORCE/IGNORE INDEX list specified as a SQL hint */
-class index_hint : public Sql_alloc
+class Index_hint : public Sql_alloc
{
public:
/* The type of the hint : USE/FORCE/IGNORE */
@@ -249,7 +249,7 @@ public:
*/
LEX_STRING key_name;
- index_hint (enum index_hint_type type_arg, index_clause_map clause_arg,
+ Index_hint (enum index_hint_type type_arg, index_clause_map clause_arg,
char *str, uint length) :
type(type_arg), clause(clause_arg)
{
@@ -441,7 +441,7 @@ public:
LEX_STRING *alias,
ulong table_options,
thr_lock_type flags= TL_UNLOCK,
- List<index_hint> *hints= 0,
+ List<Index_hint> *hints= 0,
LEX_STRING *option= 0);
virtual void set_lock_for_tables(thr_lock_type lock_type) {}
@@ -719,7 +719,7 @@ public:
LEX_STRING *alias,
ulong table_options,
thr_lock_type flags= TL_UNLOCK,
- List<index_hint> *hints= 0,
+ List<Index_hint> *hints= 0,
LEX_STRING *option= 0);
TABLE_LIST* get_table_list();
bool init_nested_join(THD *thd);
@@ -779,9 +779,9 @@ public:
/* make a list to hold index hints */
void alloc_index_hints (THD *thd);
/* read and clear the index hints */
- List<index_hint>* pop_index_hints(void)
+ List<Index_hint>* pop_index_hints(void)
{
- List<index_hint> *hints= index_hints;
+ List<Index_hint> *hints= index_hints;
index_hints= NULL;
return hints;
}
@@ -793,7 +793,7 @@ private:
enum index_hint_type current_index_hint_type;
index_clause_map current_index_hint_clause;
/* a list of USE/FORCE/IGNORE INDEX */
- List<index_hint> *index_hints;
+ List<Index_hint> *index_hints;
};
typedef class st_select_lex SELECT_LEX;
@@ -1239,19 +1239,19 @@ public:
}
/** Get the raw query buffer. */
- const char* get_buf()
+ const char *get_buf()
{
return m_buf;
}
/** Get the pre-processed query buffer. */
- const char* get_cpp_buf()
+ const char *get_cpp_buf()
{
return m_cpp_buf;
}
/** Get the end of the raw query buffer. */
- const char* get_end_of_query()
+ const char *get_end_of_query()
{
return m_end_of_query;
}
@@ -1279,43 +1279,43 @@ public:
}
/** Get the token start position, in the raw buffer. */
- const char* get_tok_start()
+ const char *get_tok_start()
{
return m_tok_start;
}
/** Get the token start position, in the pre-processed buffer. */
- const char* get_cpp_tok_start()
+ const char *get_cpp_tok_start()
{
return m_cpp_tok_start;
}
/** Get the token end position, in the raw buffer. */
- const char* get_tok_end()
+ const char *get_tok_end()
{
return m_tok_end;
}
/** Get the token end position, in the pre-processed buffer. */
- const char* get_cpp_tok_end()
+ const char *get_cpp_tok_end()
{
return m_cpp_tok_end;
}
/** Get the previous token start position, in the raw buffer. */
- const char* get_tok_start_prev()
+ const char *get_tok_start_prev()
{
return m_tok_start_prev;
}
/** Get the current stream pointer, in the raw buffer. */
- const char* get_ptr()
+ const char *get_ptr()
{
return m_ptr;
}
/** Get the current stream pointer, in the pre-processed buffer. */
- const char* get_cpp_ptr()
+ const char *get_cpp_ptr()
{
return m_cpp_ptr;
}
@@ -1365,22 +1365,22 @@ public:
private:
/** Pointer to the current position in the raw input stream. */
- const char* m_ptr;
+ const char *m_ptr;
/** Starting position of the last token parsed, in the raw buffer. */
- const char* m_tok_start;
+ const char *m_tok_start;
/** Ending position of the previous token parsed, in the raw buffer. */
- const char* m_tok_end;
+ const char *m_tok_end;
/** End of the query text in the input stream, in the raw buffer. */
- const char* m_end_of_query;
+ const char *m_end_of_query;
/** Starting position of the previous token parsed, in the raw buffer. */
- const char* m_tok_start_prev;
+ const char *m_tok_start_prev;
/** Begining of the query text in the input stream, in the raw buffer. */
- const char* m_buf;
+ const char *m_buf;
/** Length of the raw buffer. */
uint m_buf_length;
@@ -1389,28 +1389,28 @@ private:
bool m_echo;
/** Pre-processed buffer. */
- char* m_cpp_buf;
+ char *m_cpp_buf;
/** Pointer to the current position in the pre-processed input stream. */
- char* m_cpp_ptr;
+ char *m_cpp_ptr;
/**
Starting position of the last token parsed,
in the pre-processed buffer.
*/
- const char* m_cpp_tok_start;
+ const char *m_cpp_tok_start;
/**
Starting position of the previous token parsed,
in the pre-procedded buffer.
*/
- const char* m_cpp_tok_start_prev;
+ const char *m_cpp_tok_start_prev;
/**
Ending position of the previous token parsed,
in the pre-processed buffer.
*/
- const char* m_cpp_tok_end;
+ const char *m_cpp_tok_end;
/** UTF8-body buffer created during parsing. */
char *m_body_utf8;
@@ -1433,7 +1433,7 @@ public:
Position of ';' in the stream, to delimit multiple queries.
This delimiter is in the raw buffer.
*/
- const char* found_semicolon;
+ const char *found_semicolon;
/** SQL_MODE = IGNORE_SPACE. */
bool ignore_space;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index f2a61b7f7c5..93887db88e1 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -5636,7 +5636,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
LEX_STRING *alias,
ulong table_options,
thr_lock_type lock_type,
- List<index_hint> *index_hints_arg,
+ List<Index_hint> *index_hints_arg,
LEX_STRING *option)
{
register TABLE_LIST *ptr;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 4c48c70dcca..b7757d3e5fc 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -12289,6 +12289,7 @@ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx,
key_part_end=key_part+table->key_info[idx].key_parts;
key_part_map const_key_parts=table->const_key_parts[idx];
int reverse=0;
+ my_bool on_primary_key= FALSE;
DBUG_ENTER("test_if_order_by_key");
for (; order ; order=order->next, const_key_parts>>=1)
@@ -12303,7 +12304,31 @@ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx,
for (; const_key_parts & 1 ; const_key_parts>>= 1)
key_part++;
- if (key_part == key_part_end || key_part->field != field)
+ if (key_part == key_part_end)
+ {
+ /*
+ We are at the end of the key. Check if the engine has the primary
+ key as a suffix to the secondary keys. If it has continue to check
+ the primary key as a suffix.
+ */
+ if (!on_primary_key &&
+ (table->file->ha_table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX) &&
+ ha_legacy_type(table->s->db_type()) == DB_TYPE_INNODB &&
+ table->s->primary_key != MAX_KEY)
+ {
+ on_primary_key= TRUE;
+ key_part= table->key_info[table->s->primary_key].key_part;
+ key_part_end=key_part+table->key_info[table->s->primary_key].key_parts;
+ const_key_parts=table->const_key_parts[table->s->primary_key];
+
+ for (; const_key_parts & 1 ; const_key_parts>>= 1)
+ key_part++;
+ }
+ else
+ DBUG_RETURN(0);
+ }
+
+ if (key_part->field != field)
DBUG_RETURN(0);
/* set flag to 1 if we can use read-next on key, else to -1 */
@@ -12314,7 +12339,8 @@ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx,
reverse=flag; // Remember if reverse
key_part++;
}
- *used_key_parts= (uint) (key_part - table->key_info[idx].key_part);
+ *used_key_parts= on_primary_key ? table->key_info[idx].key_parts :
+ (uint) (key_part - table->key_info[idx].key_part);
if (reverse == -1 && !(table->file->index_flags(idx, *used_key_parts-1, 1) &
HA_READ_PREV))
reverse= 0; // Index can't be used
@@ -13030,7 +13056,7 @@ remove_duplicates(JOIN *join, TABLE *entry,List<Item> &fields, Item *having)
field_count++;
}
- if (!field_count && !(join->select_options & OPTION_FOUND_ROWS))
+ if (!field_count && !(join->select_options & OPTION_FOUND_ROWS) && !having)
{ // only const items with no OPTION_FOUND_ROWS
join->unit->select_limit_cnt= 1; // Only send first row
DBUG_RETURN(0);
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 31828617c14..33448ea3c5f 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -6336,11 +6336,9 @@ view_err:
{
VOID(pthread_mutex_lock(&LOCK_open));
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
- table->file->ha_external_lock(thd, F_WRLCK);
+ VOID(pthread_mutex_unlock(&LOCK_open));
alter_table_manage_keys(table, table->file->indexes_are_disabled(),
alter_info->keys_onoff);
- table->file->ha_external_lock(thd, F_UNLCK);
- VOID(pthread_mutex_unlock(&LOCK_open));
error= ha_commit_stmt(thd);
if (ha_commit(thd))
error= 1;
diff --git a/sql/table.cc b/sql/table.cc
index a58f59d3a75..e6f9b1086c7 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -1349,7 +1349,12 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
the primary key, then we can use any key to find this column
*/
if (ha_option & HA_PRIMARY_KEY_IN_READ_INDEX)
+ {
field->part_of_key= share->keys_in_use;
+ if (ha_legacy_type(share->db_type()) == DB_TYPE_INNODB &&
+ field->part_of_sortkey.is_set(key))
+ field->part_of_sortkey= share->keys_in_use;
+ }
}
if (field->key_length() != key_part->length)
{
@@ -4642,11 +4647,11 @@ bool TABLE_LIST::process_index_hints(TABLE *table)
key_map index_join[INDEX_HINT_FORCE + 1];
key_map index_order[INDEX_HINT_FORCE + 1];
key_map index_group[INDEX_HINT_FORCE + 1];
- index_hint *hint;
+ Index_hint *hint;
int type;
bool have_empty_use_join= FALSE, have_empty_use_order= FALSE,
have_empty_use_group= FALSE;
- List_iterator <index_hint> iter(*index_hints);
+ List_iterator <Index_hint> iter(*index_hints);
/* initialize temporary variables used to collect hints of each kind */
for (type= INDEX_HINT_IGNORE; type <= INDEX_HINT_FORCE; type++)
diff --git a/sql/table.h b/sql/table.h
index 494b74d564c..a276a9f32fd 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -754,7 +754,7 @@ public:
(TABLE_LIST::join_using_fields != NULL)
*/
-class index_hint;
+class Index_hint;
struct TABLE_LIST
{
TABLE_LIST() {} /* Remove gcc warning */
@@ -826,7 +826,7 @@ struct TABLE_LIST
*/
TABLE_LIST *next_name_resolution_table;
/* Index names in a "... JOIN ... USE/IGNORE INDEX ..." clause. */
- List<index_hint> *index_hints;
+ List<Index_hint> *index_hints;
TABLE *table; /* opened table */
uint table_id; /* table id (from binlog) for opened table */
/*
diff --git a/storage/archive/ha_archive.cc b/storage/archive/ha_archive.cc
index bdc59cbe795..6696eac2fbb 100644
--- a/storage/archive/ha_archive.cc
+++ b/storage/archive/ha_archive.cc
@@ -436,6 +436,9 @@ int ha_archive::init_archive_writer()
}
+/*
+ No locks are required because it is associated with just one handler instance
+*/
int ha_archive::init_archive_reader()
{
DBUG_ENTER("ha_archive::init_archive_reader");
@@ -794,15 +797,16 @@ int ha_archive::write_row(uchar *buf)
if (share->crashed)
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
- if (!share->archive_write_open)
- if (init_archive_writer())
- DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
-
ha_statistic_increment(&SSV::ha_write_count);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
table->timestamp_field->set_time();
pthread_mutex_lock(&share->mutex);
+ if (!share->archive_write_open)
+ if (init_archive_writer())
+ DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
+
+
if (table->next_number_field && record == table->record[0])
{
KEY *mkey= &table->s->key_info[0]; // We only support one key right now
@@ -992,24 +996,6 @@ int ha_archive::rnd_init(bool scan)
{
DBUG_PRINT("info", ("archive will retrieve %llu rows",
(unsigned long long) scan_rows));
- stats.records= 0;
-
- /*
- If dirty, we lock, and then reset/flush the data.
- I found that just calling azflush() doesn't always work.
- */
- pthread_mutex_lock(&share->mutex);
- scan_rows= share->rows_recorded;
- if (share->dirty == TRUE)
- {
- if (share->dirty == TRUE)
- {
- DBUG_PRINT("ha_archive", ("archive flushing out rows for scan"));
- azflush(&(share->archive_write), Z_SYNC_FLUSH);
- share->dirty= FALSE;
- }
- }
- pthread_mutex_unlock(&share->mutex);
if (read_data_header(&archive))
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
@@ -1223,9 +1209,7 @@ int ha_archive::rnd_next(uchar *buf)
current_position= aztell(&archive);
rc= get_row(&archive, buf);
-
- if (rc != HA_ERR_END_OF_FILE)
- stats.records++;
+ table->status=rc ? STATUS_NOT_FOUND: 0;
DBUG_RETURN(rc);
}
@@ -1461,12 +1445,33 @@ void ha_archive::update_create_info(HA_CREATE_INFO *create_info)
int ha_archive::info(uint flag)
{
DBUG_ENTER("ha_archive::info");
+
+ /*
+ If dirty, we lock, and then reset/flush the data.
+ I found that just calling azflush() doesn't always work.
+ */
+ pthread_mutex_lock(&share->mutex);
+ if (share->dirty == TRUE)
+ {
+ if (share->dirty == TRUE)
+ {
+ DBUG_PRINT("ha_archive", ("archive flushing out rows for scan"));
+ azflush(&(share->archive_write), Z_SYNC_FLUSH);
+ share->dirty= FALSE;
+ }
+ }
+
/*
This should be an accurate number now, though bulk and delayed inserts can
cause the number to be inaccurate.
*/
stats.records= share->rows_recorded;
+ pthread_mutex_unlock(&share->mutex);
+
+ scan_rows= stats.records;
stats.deleted= 0;
+
+ DBUG_PRINT("ha_archive", ("Stats rows is %d\n", (int)stats.records));
/* Costs quite a bit more to get all information */
if (flag & HA_STATUS_TIME)
{
@@ -1486,7 +1491,9 @@ int ha_archive::info(uint flag)
if (flag & HA_STATUS_AUTO)
{
init_archive_reader();
+ pthread_mutex_lock(&share->mutex);
azflush(&archive, Z_SYNC_FLUSH);
+ pthread_mutex_unlock(&share->mutex);
stats.auto_increment_value= archive.auto_increment;
}
@@ -1554,7 +1561,9 @@ int ha_archive::check(THD* thd, HA_CHECK_OPT* check_opt)
old_proc_info= thd_proc_info(thd, "Checking table");
/* Flush any waiting data */
+ pthread_mutex_lock(&share->mutex);
azflush(&(share->archive_write), Z_SYNC_FLUSH);
+ pthread_mutex_unlock(&share->mutex);
/*
Now we will rewind the archive file so that we are positioned at the
diff --git a/storage/archive/ha_archive.h b/storage/archive/ha_archive.h
index 22fb57b0cc7..ab630ed22fd 100644
--- a/storage/archive/ha_archive.h
+++ b/storage/archive/ha_archive.h
@@ -88,6 +88,8 @@ public:
{
return (HA_NO_TRANSACTIONS | HA_REC_NOT_IN_SEQ | HA_CAN_BIT_FIELD |
HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE |
+ HA_STATS_RECORDS_IS_EXACT |
+ HA_HAS_RECORDS |
HA_FILE_BASED | HA_CAN_INSERT_DELAYED | HA_CAN_GEOMETRY);
}
ulong index_flags(uint idx, uint part, bool all_parts) const
@@ -101,6 +103,7 @@ public:
uint max_supported_keys() const { return 1; }
uint max_supported_key_length() const { return sizeof(ulonglong); }
uint max_supported_key_part_length() const { return sizeof(ulonglong); }
+ ha_rows records() { return share->rows_recorded; }
int index_init(uint keynr, bool sorted);
virtual int index_read(uchar * buf, const uchar * key,
uint key_len, enum ha_rkey_function find_flag);
diff --git a/storage/federated/ha_federated.cc b/storage/federated/ha_federated.cc
index 635a6fa79e0..ded0ce88484 100644
--- a/storage/federated/ha_federated.cc
+++ b/storage/federated/ha_federated.cc
@@ -449,6 +449,13 @@ int federated_db_init(void *p)
federated_hton->create= federated_create_handler;
federated_hton->flags= HTON_ALTER_NOT_SUPPORTED | HTON_NO_PARTITION;
+ /*
+ Support for transactions disabled until WL#2952 fixes it.
+ We do it like this to avoid "defined but not used" compiler warnings.
+ */
+ federated_hton->commit= 0;
+ federated_hton->rollback= 0;
+
if (pthread_mutex_init(&federated_mutex, MY_MUTEX_INIT_FAST))
goto error;
if (!hash_init(&federated_open_tables, &my_charset_bin, 32, 0, 0,
@@ -533,102 +540,6 @@ err:
}
-/*
- Check (in create) whether the tables exists, and that it can be connected to
-
- SYNOPSIS
- check_foreign_data_source()
- share pointer to FEDERATED share
- table_create_flag tells us that ::create is the caller,
- therefore, return CANT_CREATE_FEDERATED_TABLE
-
- DESCRIPTION
- This method first checks that the connection information that parse url
- has populated into the share will be sufficient to connect to the foreign
- table, and if so, does the foreign table exist.
-*/
-
-static int check_foreign_data_source(FEDERATED_SHARE *share,
- bool table_create_flag)
-{
- char query_buffer[FEDERATED_QUERY_BUFFER_SIZE];
- char error_buffer[FEDERATED_QUERY_BUFFER_SIZE];
- uint error_code;
- String query(query_buffer, sizeof(query_buffer), &my_charset_bin);
- MYSQL *mysql;
- DBUG_ENTER("ha_federated::check_foreign_data_source");
-
- /* Zero the length, otherwise the string will have misc chars */
- query.length(0);
-
- /* error out if we can't alloc memory for mysql_init(NULL) (per Georg) */
- if (!(mysql= mysql_init(NULL)))
- DBUG_RETURN(HA_ERR_OUT_OF_MEM);
- /* check if we can connect */
- if (!mysql_real_connect(mysql,
- share->hostname,
- share->username,
- share->password,
- share->database,
- share->port,
- share->socket, 0))
- {
- /*
- we want the correct error message, but it to return
- ER_CANT_CREATE_FEDERATED_TABLE if called by ::create
- */
- error_code= (table_create_flag ?
- ER_CANT_CREATE_FEDERATED_TABLE :
- ER_CONNECT_TO_FOREIGN_DATA_SOURCE);
-
- my_sprintf(error_buffer,
- (error_buffer,
- "database: '%s' username: '%s' hostname: '%s'",
- share->database, share->username, share->hostname));
-
- my_error(ER_CONNECT_TO_FOREIGN_DATA_SOURCE, MYF(0), error_buffer);
- goto error;
- }
- else
- {
- /*
- Since we do not support transactions at this version, we can let the
- client API silently reconnect. For future versions, we will need more
- logic to deal with transactions
- */
- mysql->reconnect= 1;
- /*
- Note: I am not using INORMATION_SCHEMA because this needs to work with
- versions prior to 5.0
-
- if we can connect, then make sure the table exists
-
- the query will be: SELECT * FROM `tablename` WHERE 1=0
- */
- query.append(STRING_WITH_LEN("SELECT * FROM "));
- append_ident(&query, share->table_name, share->table_name_length,
- ident_quote_char);
- query.append(STRING_WITH_LEN(" WHERE 1=0"));
-
- if (mysql_real_query(mysql, query.ptr(), query.length()))
- {
- error_code= table_create_flag ?
- ER_CANT_CREATE_FEDERATED_TABLE : ER_FOREIGN_DATA_SOURCE_DOESNT_EXIST;
- my_sprintf(error_buffer, (error_buffer, "error: %d '%s'",
- mysql_errno(mysql), mysql_error(mysql)));
-
- my_error(error_code, MYF(0), error_buffer);
- goto error;
- }
- }
- error_code=0;
-
-error:
- mysql_close(mysql);
- DBUG_RETURN(error_code);
-}
-
-
static int parse_url_error(FEDERATED_SHARE *share, TABLE *table, int error_num)
{
char buf[FEDERATED_QUERY_BUFFER_SIZE];
@@ -1681,38 +1592,7 @@ int ha_federated::open(const char *name, int mode, uint test_if_locked)
DBUG_RETURN(1);
thr_lock_data_init(&share->lock, &lock, NULL);
- /* Connect to foreign database mysql_real_connect() */
- mysql= mysql_init(0);
-
- /*
- BUG# 17044 Federated Storage Engine is not UTF8 clean
- Add set names to whatever charset the table is at open
- of table
- */
- /* this sets the csname like 'set names utf8' */
- mysql_options(mysql,MYSQL_SET_CHARSET_NAME,
- this->table->s->table_charset->csname);
-
- DBUG_PRINT("info", ("calling mysql_real_connect hostname %s user %s",
- share->hostname, share->username));
- if (!mysql || !mysql_real_connect(mysql,
- share->hostname,
- share->username,
- share->password,
- share->database,
- share->port,
- share->socket, 0))
- {
- free_share(share);
- DBUG_RETURN(stash_remote_error());
- }
- /*
- Since we do not support transactions at this version, we can let the client
- API silently reconnect. For future versions, we will need more logic to
- deal with transactions
- */
-
- mysql->reconnect= 1;
+ DBUG_ASSERT(mysql == NULL);
ref_length= (table->s->primary_key != MAX_KEY ?
table->key_info[table->s->primary_key].key_length :
@@ -1748,8 +1628,8 @@ int ha_federated::close(void)
stored_result= 0;
}
/* Disconnect from mysql */
- if (mysql) // QQ is this really needed
- mysql_close(mysql);
+ mysql_close(mysql);
+ mysql= NULL;
retval= free_share(share);
DBUG_RETURN(retval);
@@ -1981,7 +1861,7 @@ int ha_federated::write_row(uchar *buf)
if (bulk_insert.length + values_string.length() + bulk_padding >
mysql->net.max_packet_size && bulk_insert.length)
{
- error= mysql_real_query(mysql, bulk_insert.str, bulk_insert.length);
+ error= real_query(bulk_insert.str, bulk_insert.length);
bulk_insert.length= 0;
}
else
@@ -2005,8 +1885,7 @@ int ha_federated::write_row(uchar *buf)
}
else
{
- error= mysql_real_query(mysql, values_string.ptr(),
- values_string.length());
+ error= real_query(values_string.ptr(), values_string.length());
}
if (error)
@@ -2018,8 +1897,13 @@ int ha_federated::write_row(uchar *buf)
field, then store the last_insert_id() value from the foreign server
*/
if (auto_increment_update_required)
+ {
update_auto_increment();
+ /* mysql_insert() uses this for protocol return value */
+ table->next_number_field->store(stats.auto_increment_value, 1);
+ }
+
DBUG_RETURN(0);
}
@@ -2049,6 +1933,13 @@ void ha_federated::start_bulk_insert(ha_rows rows)
if (rows == 1)
DBUG_VOID_RETURN;
+ /*
+ Make sure we have an open connection so that we know the
+ maximum packet size.
+ */
+ if (!mysql && real_connect())
+ DBUG_VOID_RETURN;
+
page_size= (uint) my_getpagesize();
if (init_dynamic_string(&bulk_insert, NULL, page_size, page_size))
@@ -2077,7 +1968,7 @@ int ha_federated::end_bulk_insert()
if (bulk_insert.str && bulk_insert.length)
{
- if (mysql_real_query(mysql, bulk_insert.str, bulk_insert.length))
+ if (real_query(bulk_insert.str, bulk_insert.length))
error= stash_remote_error();
else
if (table->next_number_field)
@@ -2103,8 +1994,9 @@ void ha_federated::update_auto_increment(void)
THD *thd= current_thd;
DBUG_ENTER("ha_federated::update_auto_increment");
+ ha_federated::info(HA_STATUS_AUTO);
thd->first_successful_insert_id_in_cur_stmt=
- mysql->last_used_con->insert_id;
+ stats.auto_increment_value;
DBUG_PRINT("info",("last_insert_id: %ld", (long) stats.auto_increment_value));
DBUG_VOID_RETURN;
@@ -2123,7 +2015,7 @@ int ha_federated::optimize(THD* thd, HA_CHECK_OPT* check_opt)
append_ident(&query, share->table_name, share->table_name_length,
ident_quote_char);
- if (mysql_real_query(mysql, query.ptr(), query.length()))
+ if (real_query(query.ptr(), query.length()))
{
DBUG_RETURN(stash_remote_error());
}
@@ -2151,7 +2043,7 @@ int ha_federated::repair(THD* thd, HA_CHECK_OPT* check_opt)
if (check_opt->sql_flags & TT_USEFRM)
query.append(STRING_WITH_LEN(" USE_FRM"));
- if (mysql_real_query(mysql, query.ptr(), query.length()))
+ if (real_query(query.ptr(), query.length()))
{
DBUG_RETURN(stash_remote_error());
}
@@ -2308,7 +2200,7 @@ int ha_federated::update_row(const uchar *old_data, uchar *new_data)
if (!has_a_primary_key)
update_string.append(STRING_WITH_LEN(" LIMIT 1"));
- if (mysql_real_query(mysql, update_string.ptr(), update_string.length()))
+ if (real_query(update_string.ptr(), update_string.length()))
{
DBUG_RETURN(stash_remote_error());
}
@@ -2381,7 +2273,7 @@ int ha_federated::delete_row(const uchar *buf)
delete_string.append(STRING_WITH_LEN(" LIMIT 1"));
DBUG_PRINT("info",
("Delete sql: %s", delete_string.c_ptr_quick()));
- if (mysql_real_query(mysql, delete_string.ptr(), delete_string.length()))
+ if (real_query(delete_string.ptr(), delete_string.length()))
{
DBUG_RETURN(stash_remote_error());
}
@@ -2489,7 +2381,7 @@ int ha_federated::index_read_idx_with_result_set(uchar *buf, uint index,
NULL, 0, 0);
sql_query.append(index_string);
- if (mysql_real_query(mysql, sql_query.ptr(), sql_query.length()))
+ if (real_query(sql_query.ptr(), sql_query.length()))
{
my_sprintf(error_buffer, (error_buffer, "error: %d '%s'",
mysql_errno(mysql), mysql_error(mysql)));
@@ -2555,7 +2447,7 @@ int ha_federated::read_range_first(const key_range *start_key,
mysql_free_result(stored_result);
stored_result= 0;
}
- if (mysql_real_query(mysql, sql_query.ptr(), sql_query.length()))
+ if (real_query(sql_query.ptr(), sql_query.length()))
{
retval= ER_QUERY_ON_FOREIGN_DATA_SOURCE;
goto error;
@@ -2654,9 +2546,7 @@ int ha_federated::rnd_init(bool scan)
stored_result= 0;
}
- if (mysql_real_query(mysql,
- share->select_query,
- strlen(share->select_query)))
+ if (real_query(share->select_query, strlen(share->select_query)))
goto error;
stored_result= mysql_store_result(mysql);
@@ -2873,8 +2763,7 @@ int ha_federated::info(uint flag)
append_ident(&status_query_string, share->table_name,
share->table_name_length, value_quote_char);
- if (mysql_real_query(mysql, status_query_string.ptr(),
- status_query_string.length()))
+ if (real_query(status_query_string.ptr(), status_query_string.length()))
goto error;
status_query_string.length(0);
@@ -2926,18 +2815,27 @@ int ha_federated::info(uint flag)
}
- if (result)
- mysql_free_result(result);
+ if (flag & HA_STATUS_AUTO)
+ stats.auto_increment_value= mysql->last_used_con->insert_id;
+
+ mysql_free_result(result);
DBUG_RETURN(0);
error:
- if (result)
- mysql_free_result(result);
-
- my_sprintf(error_buffer, (error_buffer, ": %d : %s",
- mysql_errno(mysql), mysql_error(mysql)));
- my_error(error_code, MYF(0), error_buffer);
+ mysql_free_result(result);
+ if (mysql)
+ {
+ my_sprintf(error_buffer, (error_buffer, ": %d : %s",
+ mysql_errno(mysql), mysql_error(mysql)));
+ my_error(error_code, MYF(0), error_buffer);
+ }
+ else
+ if (remote_error_number != -1 /* error already reported */)
+ {
+ error_code= remote_error_number;
+ my_error(error_code, MYF(0), ER(error_code));
+ }
DBUG_RETURN(error_code);
}
@@ -3029,7 +2927,7 @@ int ha_federated::delete_all_rows()
/*
TRUNCATE won't return anything in mysql_affected_rows
*/
- if (mysql_real_query(mysql, query.ptr(), query.length()))
+ if (real_query(query.ptr(), query.length()))
{
DBUG_RETURN(stash_remote_error());
}
@@ -3119,17 +3017,120 @@ int ha_federated::create(const char *name, TABLE *table_arg,
FEDERATED_SHARE tmp_share; // Only a temporary share, to test the url
DBUG_ENTER("ha_federated::create");
- if (!(retval= parse_url(thd->mem_root, &tmp_share, table_arg, 1)))
- retval= check_foreign_data_source(&tmp_share, 1);
+ retval= parse_url(thd->mem_root, &tmp_share, table_arg, 1);
DBUG_RETURN(retval);
}
+int ha_federated::real_connect()
+{
+ char buffer[FEDERATED_QUERY_BUFFER_SIZE];
+ String sql_query(buffer, sizeof(buffer), &my_charset_bin);
+ DBUG_ENTER("ha_federated::real_connect");
+
+ /*
+ Bug#25679
+ Ensure that we do not hold the LOCK_open mutex while attempting
+ to establish Federated connection to guard against a trivial
+ Denial of Service scenerio.
+ */
+ safe_mutex_assert_not_owner(&LOCK_open);
+
+ DBUG_ASSERT(mysql == NULL);
+
+ if (!(mysql= mysql_init(NULL)))
+ {
+ remote_error_number= HA_ERR_OUT_OF_MEM;
+ DBUG_RETURN(-1);
+ }
+
+ /*
+ BUG# 17044 Federated Storage Engine is not UTF8 clean
+ Add set names to whatever charset the table is at open
+ of table
+ */
+ /* this sets the csname like 'set names utf8' */
+ mysql_options(mysql,MYSQL_SET_CHARSET_NAME,
+ this->table->s->table_charset->csname);
+
+ sql_query.length(0);
+
+ if (!mysql_real_connect(mysql,
+ share->hostname,
+ share->username,
+ share->password,
+ share->database,
+ share->port,
+ share->socket, 0))
+ {
+ stash_remote_error();
+ mysql_close(mysql);
+ mysql= NULL;
+ my_error(ER_CONNECT_TO_FOREIGN_DATA_SOURCE, MYF(0), remote_error_buf);
+ remote_error_number= -1;
+ DBUG_RETURN(-1);
+ }
+
+ /*
+ We have established a connection, lets try a simple dummy query just
+ to check that the table and expected columns are present.
+ */
+ sql_query.append(share->select_query);
+ sql_query.append(STRING_WITH_LEN(" WHERE 1=0"));
+ if (mysql_real_query(mysql, sql_query.ptr(), sql_query.length()))
+ {
+ sql_query.length(0);
+ sql_query.append("error: ");
+ sql_query.qs_append(mysql_errno(mysql));
+ sql_query.append(" '");
+ sql_query.append(mysql_error(mysql));
+ sql_query.append("'");
+ mysql_close(mysql);
+ mysql= NULL;
+ my_error(ER_FOREIGN_DATA_SOURCE_DOESNT_EXIST, MYF(0), sql_query.ptr());
+ remote_error_number= -1;
+ DBUG_RETURN(-1);
+ }
+
+ /* Just throw away the result, no rows anyways but need to keep in sync */
+ mysql_free_result(mysql_store_result(mysql));
+
+ /*
+ Since we do not support transactions at this version, we can let the client
+ API silently reconnect. For future versions, we will need more logic to
+ deal with transactions
+ */
+
+ mysql->reconnect= 1;
+ DBUG_RETURN(0);
+}
+
+
+int ha_federated::real_query(const char *query, uint length)
+{
+ int rc= 0;
+ DBUG_ENTER("ha_federated::real_query");
+
+ if (!mysql && (rc= real_connect()))
+ goto end;
+
+ if (!query || !length)
+ goto end;
+
+ rc= mysql_real_query(mysql, query, length);
+
+end:
+ DBUG_RETURN(rc);
+}
+
+
int ha_federated::stash_remote_error()
{
DBUG_ENTER("ha_federated::stash_remote_error()");
+ if (!mysql)
+ DBUG_RETURN(remote_error_number);
remote_error_number= mysql_errno(mysql);
strmake(remote_error_buf, mysql_error(mysql), sizeof(remote_error_buf)-1);
if (remote_error_number == ER_DUP_ENTRY ||
@@ -3160,11 +3161,16 @@ bool ha_federated::get_error_message(int error, String* buf)
int ha_federated::external_lock(THD *thd, int lock_type)
{
int error= 0;
- ha_federated *trx= (ha_federated *)thd->ha_data[ht->slot];
DBUG_ENTER("ha_federated::external_lock");
+ /*
+ Support for transactions disabled until WL#2952 fixes it.
+ */
+#ifdef XXX_SUPERCEDED_BY_WL2952
if (lock_type != F_UNLCK)
{
+ ha_federated *trx= (ha_federated *)thd->ha_data[ht->slot];
+
DBUG_PRINT("info",("federated not lock F_UNLCK"));
if (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
{
@@ -3216,7 +3222,8 @@ int ha_federated::external_lock(THD *thd, int lock_type)
}
}
}
- DBUG_RETURN(0);
+#endif /* XXX_SUPERCEDED_BY_WL2952 */
+ DBUG_RETURN(error);
}
diff --git a/storage/federated/ha_federated.h b/storage/federated/ha_federated.h
index 5f0f1cec2a2..40bcf9cc402 100644
--- a/storage/federated/ha_federated.h
+++ b/storage/federated/ha_federated.h
@@ -113,6 +113,8 @@ private:
uint key_len,
ha_rkey_function find_flag,
MYSQL_RES **result);
+ int real_query(const char *query, uint length);
+ int real_connect();
public:
ha_federated(handlerton *hton, TABLE_SHARE *table_arg);
~ha_federated() {}
@@ -141,6 +143,7 @@ public:
| HA_REC_NOT_IN_SEQ | HA_AUTO_PART_KEY | HA_CAN_INDEX_BLOBS |
HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE |
HA_NO_PREFIX_CHAR_KEYS | HA_PRIMARY_KEY_REQUIRED_FOR_DELETE |
+ HA_NO_TRANSACTIONS /* until fixed by WL#2952 */ |
HA_PARTIAL_COLUMN_READ | HA_NULL_IN_KEY);
}
/*
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index c2e230d2087..ca566f1300e 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -7039,18 +7039,6 @@ ha_innobase::store_lock(
&& !thd_tablespace_op(thd)
&& sql_command != SQLCOM_TRUNCATE
&& sql_command != SQLCOM_OPTIMIZE
-
-#ifdef __WIN__
- /* For alter table on win32 for successful
- operation completion it is used TL_WRITE(=10) lock
- instead of TL_WRITE_ALLOW_READ(=6), however here
- in innodb handler TL_WRITE is lifted to
- TL_WRITE_ALLOW_WRITE, which causes race condition
- when several clients do alter table simultaneously
- (bug #17264). This fix avoids the problem. */
- && sql_command != SQLCOM_ALTER_TABLE
-#endif
-
&& sql_command != SQLCOM_CREATE_TABLE) {
lock_type = TL_WRITE_ALLOW_WRITE;
diff --git a/storage/myisam/mi_extra.c b/storage/myisam/mi_extra.c
index 72c40741a22..30802a50513 100644
--- a/storage/myisam/mi_extra.c
+++ b/storage/myisam/mi_extra.c
@@ -258,7 +258,7 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
case HA_EXTRA_PREPARE_FOR_DELETE:
pthread_mutex_lock(&THR_LOCK_myisam);
share->last_version= 0L; /* Impossible version */
-#ifdef __WIN__
+#ifdef __WIN__REMOVE_OBSOLETE_WORKAROUND
/* Close the isam and data files as Win32 can't drop an open table */
pthread_mutex_lock(&share->intern_lock);
if (flush_key_blocks(share->key_cache, share->kfile,
diff --git a/storage/myisammrg/myrg_locking.c b/storage/myisammrg/myrg_locking.c
index a07833bc829..4f1e3f844a1 100644
--- a/storage/myisammrg/myrg_locking.c
+++ b/storage/myisammrg/myrg_locking.c
@@ -37,7 +37,15 @@ int myrg_lock_database(MYRG_INFO *info, int lock_type)
(file->table)->owned_by_merge = TRUE;
#endif
if ((new_error=mi_lock_database(file->table,lock_type)))
+ {
error=new_error;
+ if (lock_type != F_UNLCK)
+ {
+ while (--file >= info->open_tables)
+ mi_lock_database(file->table, F_UNLCK);
+ break;
+ }
+ }
}
return(error);
}
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 5eade93621b..7559ca9ec6b 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -22,3 +22,6 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include)
ADD_EXECUTABLE(mysql_client_test mysql_client_test.c)
TARGET_LINK_LIBRARIES(mysql_client_test dbug mysys mysqlclient yassl taocrypt zlib wsock32)
+
+ADD_EXECUTABLE(bug25714 bug25714.c)
+TARGET_LINK_LIBRARIES(bug25714 dbug mysys mysqlclient yassl taocrypt zlib wsock32)
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 5f34def19bd..fbd58b88b9c 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -35,7 +35,7 @@ EXTRA_DIST = auto_increment.res auto_increment.tst \
CMakeLists.txt
bin_PROGRAMS = mysql_client_test
-noinst_PROGRAMS = insert_test select_test thread_test
+noinst_PROGRAMS = insert_test select_test thread_test bug25714
INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include \
$(openssl_includes)
@@ -52,6 +52,9 @@ select_test_SOURCES= select_test.c
insert_test_DEPENDENCIES= $(LIBRARIES) $(pkglib_LTLIBRARIES)
select_test_DEPENDENCIES= $(LIBRARIES) $(pkglib_LTLIBRARIES)
+bug25714_SOURCES= bug25714.c
+bug25714_DEPENDENCIES= $(LIBRARIES) $(pkglib_LTLIBRARIES)
+
# Fix for mit-threads
DEFS = -DUNDEF_THREADS_HACK
diff --git a/tests/bug25714.c b/tests/bug25714.c
new file mode 100644
index 00000000000..e9b2be44209
--- /dev/null
+++ b/tests/bug25714.c
@@ -0,0 +1,71 @@
+/* Copyright (C) 2007 MySQL 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; version 2 of the License.
+
+ 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 */
+
+#include <my_global.h>
+#include <my_sys.h>
+#include <mysql.h>
+#include <m_string.h>
+#include <assert.h>
+
+int main (int argc, char **argv)
+{
+ MYSQL conn;
+ int OK;
+
+ const char* query4= "INSERT INTO federated.t1 SET Value=54";
+ const char* query5= "INSERT INTO federated.t1 SET Value=55";
+
+ MY_INIT(argv[0]);
+
+ if (argc != 2)
+ return -1;
+
+ mysql_init(&conn);
+ if (!mysql_real_connect(
+ &conn,
+ "127.0.0.1",
+ "root",
+ "",
+ "test",
+ atoi(argv[1]),
+ NULL,
+ CLIENT_FOUND_ROWS))
+ {
+ fprintf(stderr, "Failed to connect to database: Error: %s\n",
+ mysql_error(&conn));
+ return 1;
+ } else {
+ printf("%s\n", mysql_error(&conn));
+ }
+
+ OK = mysql_real_query (&conn, query4, strlen(query4));
+
+ assert(0 == OK);
+
+ printf("%ld inserted\n",
+ (long) mysql_insert_id(&conn));
+
+ OK = mysql_real_query (&conn, query5, strlen(query5));
+
+ assert(0 == OK);
+
+ printf("%ld inserted\n",
+ (long) mysql_insert_id(&conn));
+
+ mysql_close(&conn);
+ my_end(0);
+
+ return 0;
+};