summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey Kopytov <Alexey.Kopytov@Sun.com>2010-08-26 16:36:48 +0400
committerAlexey Kopytov <Alexey.Kopytov@Sun.com>2010-08-26 16:36:48 +0400
commit2df3a61c3febba980e955158c8e46f575c1a03c4 (patch)
treeb8d0085ad17c77e369ac166492efbb6f54155701
parent756076bd23d9e194d5730745d07ee86aa543d4e5 (diff)
parent0648087ca035bf3aebd4e886f11eec8ebdd4366c (diff)
downloadmariadb-git-2df3a61c3febba980e955158c8e46f575c1a03c4.tar.gz
Automerge.
-rw-r--r--client/mysqltest.cc6
-rw-r--r--mysql-test/suite/innodb/r/innodb_mysql.result58
-rw-r--r--mysql-test/suite/innodb/t/innodb_mysql.test30
-rw-r--r--sql/log.cc117
-rw-r--r--sql/mysqld.cc19
-rw-r--r--sql/sql_select.cc60
6 files changed, 218 insertions, 72 deletions
diff --git a/client/mysqltest.cc b/client/mysqltest.cc
index f4fe149f5b5..c39ba4ff6ce 100644
--- a/client/mysqltest.cc
+++ b/client/mysqltest.cc
@@ -5220,8 +5220,10 @@ void do_connect(struct st_command *command)
}
#endif
+#ifndef EMBEDDED_LIBRARY
if (opt_protocol)
mysql_options(&con_slot->mysql, MYSQL_OPT_PROTOCOL, (char*) &opt_protocol);
+#endif
#ifdef HAVE_SMEM
if (con_shm)
@@ -6179,8 +6181,10 @@ get_one_option(int optid, const struct my_option *opt,
print_version();
exit(0);
case OPT_MYSQL_PROTOCOL:
+#ifndef EMBEDDED_LIBRARY
opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib,
opt->name);
+#endif
break;
case '?':
usage();
@@ -7932,8 +7936,10 @@ int main(int argc, char **argv)
mysql_options(&con->mysql, MYSQL_SET_CHARSET_DIR,
opt_charsets_dir);
+#ifndef EMBEDDED_LIBRARY
if (opt_protocol)
mysql_options(&con->mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
+#endif
#ifdef HAVE_OPENSSL
diff --git a/mysql-test/suite/innodb/r/innodb_mysql.result b/mysql-test/suite/innodb/r/innodb_mysql.result
index 23619b91fbc..ba8ac0ba86c 100644
--- a/mysql-test/suite/innodb/r/innodb_mysql.result
+++ b/mysql-test/suite/innodb/r/innodb_mysql.result
@@ -2529,4 +2529,62 @@ SELECT * FROM t1 FOR UPDATE;
SELECT * FROM t1 GROUP BY (SELECT a FROM t2 LIMIT 1 FOR UPDATE) + t1.a;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
DROP TABLE t1,t2;
+#
+# Bug#55656: mysqldump can be slower after bug #39653 fix
+#
+CREATE TABLE t1 (a INT , b INT, c INT, d INT,
+KEY (b), PRIMARY KEY (a,b)) ENGINE=INNODB;
+INSERT INTO t1 VALUES (1,1,1,1), (2,2,2,2), (3,3,3,3);
+EXPLAIN SELECT COUNT(*) FROM t1;
+id 1
+select_type SIMPLE
+table t1
+type index
+possible_keys NULL
+key b
+key_len 4
+ref NULL
+rows 3
+Extra Using index
+DROP INDEX b ON t1;
+CREATE INDEX b ON t1(a,b);
+EXPLAIN SELECT COUNT(*) FROM t1;
+id 1
+select_type SIMPLE
+table t1
+type index
+possible_keys NULL
+key b
+key_len 8
+ref NULL
+rows 3
+Extra Using index
+DROP INDEX b ON t1;
+CREATE INDEX b ON t1(a,b,c);
+EXPLAIN SELECT COUNT(*) FROM t1;
+id 1
+select_type SIMPLE
+table t1
+type index
+possible_keys NULL
+key b
+key_len 13
+ref NULL
+rows 3
+Extra Using index
+DROP INDEX b ON t1;
+CREATE INDEX b ON t1(a,b,c,d);
+EXPLAIN SELECT COUNT(*) FROM t1;
+id 1
+select_type SIMPLE
+table t1
+type index
+possible_keys NULL
+key PRIMARY
+key_len 8
+ref NULL
+rows 3
+Extra Using index
+DROP TABLE t1;
+#
End of 5.1 tests
diff --git a/mysql-test/suite/innodb/t/innodb_mysql.test b/mysql-test/suite/innodb/t/innodb_mysql.test
index d633cb2222e..ae03bebfbe3 100644
--- a/mysql-test/suite/innodb/t/innodb_mysql.test
+++ b/mysql-test/suite/innodb/t/innodb_mysql.test
@@ -768,9 +768,14 @@ START TRANSACTION;
SELECT * FROM t1 LOCK IN SHARE MODE;
connection con1;
+let $conn_id= `SELECT CONNECTION_ID()`;
--send SELECT * FROM t1 FOR UPDATE
connection con2;
+let $wait_timeout= 2;
+let $wait_condition= SELECT 1 FROM INFORMATION_SCHEMA.PROCESSLIST
+WHERE ID=$conn_id AND STATE='Sending data';
+--source include/wait_condition.inc
--echo # should not crash
--error ER_LOCK_DEADLOCK
SELECT * FROM t1 GROUP BY (SELECT a FROM t2 LIMIT 1 FOR UPDATE) + t1.a;
@@ -781,5 +786,30 @@ disconnect con2;
DROP TABLE t1,t2;
+--echo #
+--echo # Bug#55656: mysqldump can be slower after bug #39653 fix
+--echo #
+
+CREATE TABLE t1 (a INT , b INT, c INT, d INT,
+ KEY (b), PRIMARY KEY (a,b)) ENGINE=INNODB;
+INSERT INTO t1 VALUES (1,1,1,1), (2,2,2,2), (3,3,3,3);
+--query_vertical EXPLAIN SELECT COUNT(*) FROM t1
+
+DROP INDEX b ON t1;
+CREATE INDEX b ON t1(a,b);
+--query_vertical EXPLAIN SELECT COUNT(*) FROM t1
+
+DROP INDEX b ON t1;
+CREATE INDEX b ON t1(a,b,c);
+--query_vertical EXPLAIN SELECT COUNT(*) FROM t1
+
+DROP INDEX b ON t1;
+CREATE INDEX b ON t1(a,b,c,d);
+--query_vertical EXPLAIN SELECT COUNT(*) FROM t1
+
+DROP TABLE t1;
+
+--echo #
+
--echo End of 5.1 tests
diff --git a/sql/log.cc b/sql/log.cc
index 3f41bf1c929..156c293e3aa 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -5063,70 +5063,93 @@ void sql_perror(const char *message)
}
+#ifdef __WIN__
+extern "C" my_bool reopen_fstreams(const char *filename,
+ FILE *outstream, FILE *errstream)
+{
+ int handle_fd;
+ int stream_fd;
+ HANDLE osfh;
+
+ DBUG_ASSERT(filename && (outstream || errstream));
+
+ if ((osfh= CreateFile(filename, GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE |
+ FILE_SHARE_DELETE, NULL,
+ OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL,
+ NULL)) == INVALID_HANDLE_VALUE)
+ return TRUE;
+
+ if ((handle_fd= _open_osfhandle((intptr_t)osfh,
+ _O_APPEND | _O_TEXT)) == -1)
+ {
+ CloseHandle(osfh);
+ return TRUE;
+ }
+
+ if (outstream)
+ {
+ stream_fd= _fileno(outstream);
+ if (_dup2(handle_fd, stream_fd) < 0)
+ {
+ CloseHandle(osfh);
+ return TRUE;
+ }
+ }
+
+ if (errstream)
+ {
+ stream_fd= _fileno(errstream);
+ if (_dup2(handle_fd, stream_fd) < 0)
+ {
+ CloseHandle(osfh);
+ return TRUE;
+ }
+ }
+
+ _close(handle_fd);
+ return FALSE;
+}
+#else
+extern "C" my_bool reopen_fstreams(const char *filename,
+ FILE *outstream, FILE *errstream)
+{
+ if (outstream && !freopen(filename, "a+", outstream))
+ return TRUE;
+
+ if (errstream && !freopen(filename, "a+", errstream))
+ return TRUE;
+
+ return FALSE;
+}
+#endif
+
+
/*
Unfortunately, there seems to be no good way
to restore the original streams upon failure.
*/
static bool redirect_std_streams(const char *file)
{
- if (freopen(file, "a+", stdout) && freopen(file, "a+", stderr))
- {
- setbuf(stderr, NULL);
- return FALSE;
- }
+ if (reopen_fstreams(file, stdout, stderr))
+ return TRUE;
- return TRUE;
+ setbuf(stderr, NULL);
+ return FALSE;
}
bool flush_error_log()
{
- bool result=0;
+ bool result= 0;
if (opt_error_log)
{
- char err_renamed[FN_REFLEN], *end;
- end= strmake(err_renamed,log_error_file,FN_REFLEN-5);
- strmov(end, "-old");
VOID(pthread_mutex_lock(&LOCK_error_log));
-#ifdef __WIN__
- char err_temp[FN_REFLEN+5];
- /*
- On Windows is necessary a temporary file for to rename
- the current error file.
- */
- strxmov(err_temp, err_renamed,"-tmp",NullS);
- (void) my_delete(err_temp, MYF(0));
- if (freopen(err_temp,"a+",stdout))
- {
- int fd;
- size_t bytes;
- uchar buf[IO_SIZE];
-
- freopen(err_temp,"a+",stderr);
- setbuf(stderr, NULL);
- (void) my_delete(err_renamed, MYF(0));
- my_rename(log_error_file,err_renamed,MYF(0));
- redirect_std_streams(log_error_file);
-
- if ((fd = my_open(err_temp, O_RDONLY, MYF(0))) >= 0)
- {
- while ((bytes= my_read(fd, buf, IO_SIZE, MYF(0))) &&
- bytes != MY_FILE_ERROR)
- my_fwrite(stderr, buf, bytes, MYF(0));
- my_close(fd, MYF(0));
- }
- (void) my_delete(err_temp, MYF(0));
- }
- else
- result= 1;
-#else
- my_rename(log_error_file,err_renamed,MYF(0));
- if (redirect_std_streams(log_error_file))
- result= 1;
-#endif
+ if (redirect_std_streams(log_error_file))
+ result= 1;
VOID(pthread_mutex_unlock(&LOCK_error_log));
}
- return result;
+ return result;
}
void MYSQL_BIN_LOG::signal_update()
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 08407d52e09..d9c4c7fc3f5 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -199,6 +199,9 @@ typedef fp_except fp_except_t;
# endif
#endif
+extern "C" my_bool reopen_fstreams(const char *filename,
+ FILE *outstream, FILE *errstream);
+
inline void setup_fpu()
{
#if defined(__FreeBSD__) && defined(HAVE_IEEEFP_H)
@@ -3821,13 +3824,15 @@ static int init_server_components()
opt_error_log= 1; // Too long file name
else
{
+ my_bool res;
#ifndef EMBEDDED_LIBRARY
- if (freopen(log_error_file, "a+", stdout))
+ res= reopen_fstreams(log_error_file, stdout, stderr);
+#else
+ res= reopen_fstreams(log_error_file, NULL, stderr);
#endif
- {
- if (freopen(log_error_file, "a+", stderr))
- setbuf(stderr, NULL);
- }
+
+ if (!res)
+ setbuf(stderr, NULL);
}
}
@@ -4475,8 +4480,8 @@ we force server id to 2, but this MySQL server will not act as a slave.");
#ifdef __WIN__
if (!opt_console)
{
- freopen(log_error_file,"a+",stdout);
- freopen(log_error_file,"a+",stderr);
+ if (reopen_fstreams(log_error_file, stdout, stderr))
+ unireg_abort(1);
setbuf(stderr, NULL);
FreeConsole(); // Remove window
}
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 7ee1762295f..4a32ca34790 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -13017,6 +13017,34 @@ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx,
}
+/**
+ Find shortest key suitable for full table scan.
+
+ @param table Table to scan
+ @param usable_keys Allowed keys
+
+ @note
+ As far as
+ 1) clustered primary key entry data set is a set of all record
+ fields (key fields and not key fields) and
+ 2) secondary index entry data is a union of its key fields and
+ primary key fields (at least InnoDB and its derivatives don't
+ duplicate primary key fields there, even if the primary and
+ the secondary keys have a common subset of key fields),
+ then secondary index entry data is always a subset of primary key entry.
+ Unfortunately, key_info[nr].key_length doesn't show the length
+ of key/pointer pair but a sum of key field lengths only, thus
+ we can't estimate index IO volume comparing only this key_length
+ value of secondary keys and clustered PK.
+ So, try secondary keys first, and choose PK only if there are no
+ usable secondary covering keys or found best secondary key include
+ all table fields (i.e. same as PK):
+
+ @return
+ MAX_KEY no suitable key found
+ key index otherwise
+*/
+
uint find_shortest_key(TABLE *table, const key_map *usable_keys)
{
uint best= MAX_KEY;
@@ -13029,23 +13057,6 @@ uint find_shortest_key(TABLE *table, const key_map *usable_keys)
uint min_length= (uint) ~0;
for (uint nr=0; nr < table->s->keys ; nr++)
{
- /*
- As far as
- 1) clustered primary key entry data set is a set of all record
- fields (key fields and not key fields) and
- 2) secondary index entry data is a union of its key fields and
- primary key fields (at least InnoDB and its derivatives don't
- duplicate primary key fields there, even if the primary and
- the secondary keys have a common subset of key fields),
- then secondary index entry data is always a subset of primary key
- entry, and the PK is always longer.
- Unfortunately, key_info[nr].key_length doesn't show the length
- of key/pointer pair but a sum of key field lengths only, thus
- we can't estimate index IO volume comparing only this key_length
- value of seconday keys and clustered PK.
- So, try secondary keys first, and choose PK only if there are no
- usable secondary covering keys:
- */
if (nr == usable_clustered_pk)
continue;
if (usable_keys->is_set(nr))
@@ -13058,7 +13069,20 @@ uint find_shortest_key(TABLE *table, const key_map *usable_keys)
}
}
}
- return best != MAX_KEY ? best : usable_clustered_pk;
+ if (usable_clustered_pk != MAX_KEY)
+ {
+ /*
+ If the primary key is clustered and found shorter key covers all table
+ fields then primary key scan normally would be faster because amount of
+ data to scan is the same but PK is clustered.
+ It's safe to compare key parts with table fields since duplicate key
+ parts aren't allowed.
+ */
+ if (best == MAX_KEY ||
+ table->key_info[best].key_parts >= table->s->fields)
+ best= usable_clustered_pk;
+ }
+ return best;
}
/**