Manual merge from the mysql-5.1-bugteam.

This commit is contained in:
Alexey Kopytov 2009-11-24 11:19:06 +03:00
commit a460914482
28 changed files with 761 additions and 219 deletions

View File

@ -198,10 +198,6 @@ test-bt-fast:
-cd mysql-test ; MTR_BUILD_THREAD=auto \ -cd mysql-test ; MTR_BUILD_THREAD=auto \
@PERL@ ./mysql-test-run.pl --force --comment=stress --suite=stress $(EXP) @PERL@ ./mysql-test-run.pl --force --comment=stress --suite=stress $(EXP)
test-bt-fast:
-cd mysql-test ; MTR_BUILD_THREAD=auto \
@PERL@ ./mysql-test-run.pl --force --comment=ps --ps-protocol --report-features
test-bt-debug: test-bt-debug:
-cd mysql-test ; MTR_BUILD_THREAD=auto \ -cd mysql-test ; MTR_BUILD_THREAD=auto \
@PERL@ ./mysql-test-run.pl --comment=debug --force --timer \ @PERL@ ./mysql-test-run.pl --comment=debug --force --timer \

View File

@ -601,15 +601,15 @@ dnl ---------------------------------------------------------------------------
dnl MYSQL_NEEDS_MYSYS_NEW dnl MYSQL_NEEDS_MYSYS_NEW
AC_DEFUN([MYSQL_NEEDS_MYSYS_NEW], AC_DEFUN([MYSQL_NEEDS_MYSYS_NEW],
[AC_CACHE_CHECK([needs mysys_new helpers], mysql_use_mysys_new, [AC_CACHE_CHECK([needs mysys_new helpers], mysql_cv_use_mysys_new,
[ [
AC_LANG_PUSH(C++) AC_LANG_PUSH(C++)
AC_TRY_LINK([], [ AC_TRY_LINK([], [
class A { public: int b; }; A *a=new A; a->b=10; delete a; class A { public: int b; }; A *a=new A; a->b=10; delete a;
], mysql_use_mysys_new=no, mysql_use_mysys_new=yes) ], mysql_cv_use_mysys_new=no, mysql_cv_use_mysys_new=yes)
AC_LANG_POP(C++) AC_LANG_POP(C++)
]) ])
if test "$mysql_use_mysys_new" = "yes" if test "$mysql_cv_use_mysys_new" = "yes"
then then
AC_DEFINE([USE_MYSYS_NEW], [1], [Needs to use mysys_new helpers]) AC_DEFINE([USE_MYSYS_NEW], [1], [Needs to use mysys_new helpers])
fi fi

View File

@ -13,6 +13,12 @@ AC_CANONICAL_SYSTEM
AM_INIT_AUTOMAKE(mysql, 5.5.0-beta) AM_INIT_AUTOMAKE(mysql, 5.5.0-beta)
AM_CONFIG_HEADER([include/config.h:config.h.in]) AM_CONFIG_HEADER([include/config.h:config.h.in])
# Request support for automake silent-rules if available.
# Default to verbose output. One can use the configure-time
# option --enable-silent-rules or make V=1 to activate
# silent rules.
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([no])])
PROTOCOL_VERSION=10 PROTOCOL_VERSION=10
DOT_FRM_VERSION=6 DOT_FRM_VERSION=6
# See the libtool docs for information on how to do shared lib versions. # See the libtool docs for information on how to do shared lib versions.

View File

@ -185,6 +185,14 @@ INSERT INTO global_suppressions VALUES
("Master server does not support or not configured semi-sync replication, fallback to asynchronous"), ("Master server does not support or not configured semi-sync replication, fallback to asynchronous"),
(": The MySQL server is running with the --secure-backup-file-priv option so it cannot execute this statement"), (": The MySQL server is running with the --secure-backup-file-priv option so it cannot execute this statement"),
("Slave: Unknown table 't1' Error_code: 1051"), ("Slave: Unknown table 't1' Error_code: 1051"),
/*
Transient network failures that cause warnings on reconnect.
BUG#47743 and BUG#47983.
*/
("Slave I/O: Get master SERVER_ID failed with error:.*"),
("Slave I/O: Get master clock failed with error:.*"),
("Slave I/O: Get master COLLATION_SERVER failed with error:.*"),
("Slave I/O: Get master TIME_ZONE failed with error:.*"),
("THE_LAST_SUPPRESSION")|| ("THE_LAST_SUPPRESSION")||

View File

@ -551,3 +551,42 @@ EXECUTE s;
MATCH (col) AGAINST('findme') MATCH (col) AGAINST('findme')
DEALLOCATE PREPARE s; DEALLOCATE PREPARE s;
DROP TABLE t1; DROP TABLE t1;
#
# Bug #47930: MATCH IN BOOLEAN MODE returns too many results
# inside subquery
#
CREATE TABLE t1 (a int);
INSERT INTO t1 VALUES (1), (2);
CREATE TABLE t2 (a int, b2 char(10), FULLTEXT KEY b2 (b2));
INSERT INTO t2 VALUES (1,'Scargill');
CREATE TABLE t3 (a int, b int);
INSERT INTO t3 VALUES (1,1), (2,1);
# t2 should use full text index
EXPLAIN
SELECT count(*) FROM t1 WHERE
not exists(
SELECT 1 FROM t2, t3
WHERE t3.a=t1.a AND MATCH(b2) AGAINST('scargill' IN BOOLEAN MODE)
);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
2 DEPENDENT SUBQUERY t2 fulltext b2 b2 0 1 Using where
2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 2 Using where
# should return 0
SELECT count(*) FROM t1 WHERE
not exists(
SELECT 1 FROM t2, t3
WHERE t3.a=t1.a AND MATCH(b2) AGAINST('scargill' IN BOOLEAN MODE)
);
count(*)
0
# should return 0
SELECT count(*) FROM t1 WHERE
not exists(
SELECT 1 FROM t2 IGNORE INDEX (b2), t3
WHERE t3.a=t1.a AND MATCH(b2) AGAINST('scargill' IN BOOLEAN MODE)
);
count(*)
0
DROP TABLE t1,t2,t3;
End of 5.1 tests

View File

@ -2251,4 +2251,26 @@ c >= '2009-10-09 00:00:00.001' AND c <= '2009-10-09 00:00:00.00';
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
DROP TABLE t1; DROP TABLE t1;
#
# Bug #46175: NULL read_view and consistent read assertion
#
CREATE TABLE t1(a CHAR(13),KEY(a)) ENGINE=innodb;
CREATE TABLE t2(b DATETIME,KEY(b)) ENGINE=innodb;
INSERT INTO t1 VALUES (),();
INSERT INTO t2 VALUES (),();
CREATE OR REPLACE VIEW v1 AS SELECT 1 FROM t2
WHERE b =(SELECT a FROM t1 LIMIT 1);
CREATE PROCEDURE p1(num INT)
BEGIN
DECLARE i INT DEFAULT 0;
REPEAT
SHOW CREATE VIEW v1;
SET i:=i+1;
UNTIL i>num END REPEAT;
END|
# Should not crash
# Should not crash
DROP PROCEDURE p1;
DROP VIEW v1;
DROP TABLE t1,t2;
End of 5.1 tests End of 5.1 tests

View File

@ -753,4 +753,16 @@ b
100 100
NULL NULL
DROP TABLE t1, t2; DROP TABLE t1, t2;
#
# Bug #48475: DISTINCT is ignored with GROUP BY WITH ROLLUP
# and only const tables
CREATE TABLE t1 (a INT);
CREATE TABLE t2 (b INT);
INSERT INTO t1 VALUES (1);
INSERT INTO t2 VALUES (1);
SELECT DISTINCT b FROM t1, t2 GROUP BY a, b WITH ROLLUP;
b
1
NULL
DROP TABLE t1, t2;
End of 5.0 tests End of 5.0 tests

View File

@ -1444,6 +1444,27 @@ FROM t3;
2 2
NULL NULL
DROP TABLE t1, t2, t3; DROP TABLE t1, t2, t3;
#
# Bug #42760: Select doesn't return desired results when we have null
# values
#
CREATE TABLE t1 (
a INT,
c INT,
UNIQUE KEY a_c (a,c),
KEY (a));
INSERT INTO t1 VALUES (1, 10), (2, NULL);
# Must use ref-or-null on the a_c index
EXPLAIN
SELECT 1 AS col FROM t1 WHERE a=2 AND (c=10 OR c IS NULL) ORDER BY c;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref_or_null a_c,a a_c 10 const,const 1 Using where
# Must return 1 row
SELECT 1 AS col FROM t1 WHERE a=2 AND (c=10 OR c IS NULL) ORDER BY c;
col
1
DROP TABLE t1;
End of 5.0 tests
CREATE TABLE t2 (a varchar(32), b int(11), c float, d double, CREATE TABLE t2 (a varchar(32), b int(11), c float, d double,
UNIQUE KEY a (a,b,c), KEY b (b), KEY c (c)); UNIQUE KEY a (a,b,c), KEY b (b), KEY c (c));
CREATE TABLE t1 (a varchar(32), b char(3), UNIQUE KEY a (a,b), KEY b (b)); CREATE TABLE t1 (a varchar(32), b char(3), UNIQUE KEY a (a,b), KEY b (b));

View File

@ -4427,6 +4427,20 @@ ROW(a,a) <=> ROW((SELECT 1 FROM t1 WHERE 1=2),(SELECT 1 FROM t1))
INTO @var0; INTO @var0;
ERROR 21000: Subquery returns more than 1 row ERROR 21000: Subquery returns more than 1 row
DROP TABLE t1; DROP TABLE t1;
#
# Bug #48458: simple query tries to allocate enormous amount of
# memory
#
CREATE TABLE t1(a INT NOT NULL, b YEAR);
INSERT INTO t1 VALUES ();
Warnings:
Warning 1364 Field 'a' doesn't have a default value
CREATE TABLE t2(c INT);
# Should not err out because of out-of-memory
SELECT 1 FROM t2 JOIN t1 ON 1=1
WHERE a != '1' AND NOT a >= b OR NOT ROW(b,a )<> ROW(a,a);
1
DROP TABLE t1,t2;
End of 5.0 tests End of 5.0 tests
create table t1(a INT, KEY (a)); create table t1(a INT, KEY (a));
INSERT INTO t1 VALUES (1),(2),(3),(4),(5); INSERT INTO t1 VALUES (1),(2),(3),(4),(5);

View File

@ -484,3 +484,44 @@ PREPARE s FROM
EXECUTE s; EXECUTE s;
DEALLOCATE PREPARE s; DEALLOCATE PREPARE s;
DROP TABLE t1; DROP TABLE t1;
--echo #
--echo # Bug #47930: MATCH IN BOOLEAN MODE returns too many results
--echo # inside subquery
--echo #
CREATE TABLE t1 (a int);
INSERT INTO t1 VALUES (1), (2);
CREATE TABLE t2 (a int, b2 char(10), FULLTEXT KEY b2 (b2));
INSERT INTO t2 VALUES (1,'Scargill');
CREATE TABLE t3 (a int, b int);
INSERT INTO t3 VALUES (1,1), (2,1);
--echo # t2 should use full text index
EXPLAIN
SELECT count(*) FROM t1 WHERE
not exists(
SELECT 1 FROM t2, t3
WHERE t3.a=t1.a AND MATCH(b2) AGAINST('scargill' IN BOOLEAN MODE)
);
--echo # should return 0
SELECT count(*) FROM t1 WHERE
not exists(
SELECT 1 FROM t2, t3
WHERE t3.a=t1.a AND MATCH(b2) AGAINST('scargill' IN BOOLEAN MODE)
);
--echo # should return 0
SELECT count(*) FROM t1 WHERE
not exists(
SELECT 1 FROM t2 IGNORE INDEX (b2), t3
WHERE t3.a=t1.a AND MATCH(b2) AGAINST('scargill' IN BOOLEAN MODE)
);
DROP TABLE t1,t2,t3;
--echo End of 5.1 tests

View File

@ -489,5 +489,51 @@ EXPLAIN SELECT * FROM t1 WHERE a = 'TEST' AND
c >= '2009-10-09 00:00:00.001' AND c <= '2009-10-09 00:00:00.00'; c >= '2009-10-09 00:00:00.001' AND c <= '2009-10-09 00:00:00.00';
DROP TABLE t1; DROP TABLE t1;
--echo #
--echo # Bug #46175: NULL read_view and consistent read assertion
--echo #
CREATE TABLE t1(a CHAR(13),KEY(a)) ENGINE=innodb;
CREATE TABLE t2(b DATETIME,KEY(b)) ENGINE=innodb;
INSERT INTO t1 VALUES (),();
INSERT INTO t2 VALUES (),();
CREATE OR REPLACE VIEW v1 AS SELECT 1 FROM t2
WHERE b =(SELECT a FROM t1 LIMIT 1);
--disable_query_log
--disable_result_log
CONNECT (con1, localhost, root,,);
--enable_query_log
--enable_result_log
CONNECTION default;
DELIMITER |;
CREATE PROCEDURE p1(num INT)
BEGIN
DECLARE i INT DEFAULT 0;
REPEAT
SHOW CREATE VIEW v1;
SET i:=i+1;
UNTIL i>num END REPEAT;
END|
DELIMITER ;|
--echo # Should not crash
--disable_query_log
--disable_result_log
--send CALL p1(1000)
CONNECTION con1;
--echo # Should not crash
CALL p1(1000);
CONNECTION default;
--reap
--enable_query_log
--enable_result_log
DISCONNECT con1;
DROP PROCEDURE p1;
DROP VIEW v1;
DROP TABLE t1,t2;
--echo End of 5.1 tests --echo End of 5.1 tests

View File

@ -390,4 +390,17 @@ SELECT DISTINCT b FROM t1, t2 GROUP BY a, b WITH ROLLUP;
DROP TABLE t1, t2; DROP TABLE t1, t2;
--echo #
--echo # Bug #48475: DISTINCT is ignored with GROUP BY WITH ROLLUP
--echo # and only const tables
CREATE TABLE t1 (a INT);
CREATE TABLE t2 (b INT);
INSERT INTO t1 VALUES (1);
INSERT INTO t2 VALUES (1);
SELECT DISTINCT b FROM t1, t2 GROUP BY a, b WITH ROLLUP;
DROP TABLE t1, t2;
--echo End of 5.0 tests --echo End of 5.0 tests

View File

@ -867,6 +867,31 @@ SELECT
DROP TABLE t1, t2, t3; DROP TABLE t1, t2, t3;
--echo #
--echo # Bug #42760: Select doesn't return desired results when we have null
--echo # values
--echo #
CREATE TABLE t1 (
a INT,
c INT,
UNIQUE KEY a_c (a,c),
KEY (a));
INSERT INTO t1 VALUES (1, 10), (2, NULL);
--echo # Must use ref-or-null on the a_c index
EXPLAIN
SELECT 1 AS col FROM t1 WHERE a=2 AND (c=10 OR c IS NULL) ORDER BY c;
--echo # Must return 1 row
SELECT 1 AS col FROM t1 WHERE a=2 AND (c=10 OR c IS NULL) ORDER BY c;
DROP TABLE t1;
--echo End of 5.0 tests
# #
# Bug #35206: select query result different if the key is indexed or not # Bug #35206: select query result different if the key is indexed or not
# #

View File

@ -3772,6 +3772,19 @@ INTO @var0;
DROP TABLE t1; DROP TABLE t1;
--echo #
--echo # Bug #48458: simple query tries to allocate enormous amount of
--echo # memory
--echo #
CREATE TABLE t1(a INT NOT NULL, b YEAR);
INSERT INTO t1 VALUES ();
CREATE TABLE t2(c INT);
--echo # Should not err out because of out-of-memory
SELECT 1 FROM t2 JOIN t1 ON 1=1
WHERE a != '1' AND NOT a >= b OR NOT ROW(b,a )<> ROW(a,a);
DROP TABLE t1,t2;
--echo End of 5.0 tests --echo End of 5.0 tests

View File

@ -413,17 +413,17 @@ invalid value '%s'",
else if (optp->arg_type == OPT_ARG && else if (optp->arg_type == OPT_ARG &&
(((optp->var_type & GET_TYPE_MASK) == GET_BOOL) || (((optp->var_type & GET_TYPE_MASK) == GET_BOOL) ||
(optp->var_type & GET_TYPE_MASK) == GET_ENUM)) (optp->var_type & GET_TYPE_MASK) == GET_ENUM))
{ {
if (optend == disabled_my_option) if (optend == disabled_my_option)
*((my_bool*) value)= (my_bool) 0; init_one_value(optp, value, 0);
else else
{ {
if (!optend) /* No argument -> enable option */ if (!optend) /* No argument -> enable option */
*((my_bool*) value)= (my_bool) 1; init_one_value(optp, value, 1);
else else
argument= optend; argument= optend;
} }
} }
else if (optp->arg_type == REQUIRED_ARG && !optend) else if (optp->arg_type == REQUIRED_ARG && !optend)
{ {
/* Check if there are more arguments after this one */ /* Check if there are more arguments after this one */

View File

@ -17,17 +17,42 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
use Fcntl; use Fcntl;
use File::Spec;
use if $^O eq 'MSWin32', 'Term::ReadKey' => qw/ReadMode/;
use strict; use strict;
my $config = ".my.cnf.$$"; my $config = ".my.cnf.$$";
my $command = ".mysql.$$"; my $command = ".mysql.$$";
my $hadpass = 0; my $hadpass = 0;
my $mysql; # How to call the mysql client
# FIXME
# trap "interrupt" 2
my $rootpass = ""; my $rootpass = "";
$SIG{QUIT} = $SIG{INT} = sub {
print "\nAborting!\n\n";
echo_on();
cleanup();
exit 1;
};
END {
# Remove temporary files, even if exiting via die(), etc.
cleanup();
}
sub read_without_echo {
my ($prompt) = @_;
print $prompt;
echo_off();
my $answer = <STDIN>;
echo_on();
print "\n";
chomp($answer);
return $answer;
}
sub echo_on { sub echo_on {
if ($^O eq 'MSWin32') { if ($^O eq 'MSWin32') {
ReadMode('normal'); ReadMode('normal');
@ -55,6 +80,25 @@ sub write_file {
} }
sub prepare { sub prepare {
# Locate the mysql client; look in current directory first, then
# in path
our $SAVEERR; # Suppress Perl warning message
open SAVEERR, ">& STDERR";
close STDERR;
for my $m (File::Spec->catfile('bin', 'mysql'), 'mysql') {
# mysql --version should always work
qx($m --no-defaults --version);
next unless $? == 0;
$mysql = $m;
last;
}
open STDERR, ">& SAVEERR";
die "Can't find a 'mysql' client in PATH or ./bin\n"
unless $mysql;
# Create safe files to avoid leaking info to other users
foreach my $file ( $config, $command ) { foreach my $file ( $config, $command ) {
next if -f $file; # Already exists next if -f $file; # Already exists
local *FILE; local *FILE;
@ -64,30 +108,50 @@ sub prepare {
} }
} }
# Simple escape mechanism (\-escape any ' and \), suitable for two contexts:
# - single-quoted SQL strings
# - single-quoted option values on the right hand side of = in my.cnf
#
# These two contexts don't handle escapes identically. SQL strings allow
# quoting any character (\C => C, for any C), but my.cnf parsing allows
# quoting only \, ' or ". For example, password='a\b' quotes a 3-character
# string in my.cnf, but a 2-character string in SQL.
#
# This simple escape works correctly in both places.
sub basic_single_escape {
my ($str) = @_;
# Inside a character class, \ is not special; this escapes both \ and '
$str =~ s/([\'])/\\$1/g;
return $str;
}
sub do_query { sub do_query {
my $query = shift; my $query = shift;
write_file($command, $query); write_file($command, $query);
system("mysql --defaults-file=$config < $command"); my $rv = system("$mysql --defaults-file=$config < $command");
return $?; # system() returns -1 if exec fails (e.g., command not found, etc.); die
# in this case because nothing is going to work
die "Failed to execute mysql client '$mysql'\n" if $rv == -1;
# Return true if query executed OK, or false if there was some problem
# (for example, SQL error or wrong password)
return ($rv == 0 ? 1 : undef);
} }
sub make_config { sub make_config {
my $password = shift; my $password = shift;
my $esc_pass = basic_single_escape($rootpass);
write_file($config, write_file($config,
"# mysql_secure_installation config file", "# mysql_secure_installation config file",
"[mysql]", "[mysql]",
"user=root", "user=root",
"password=$rootpass"); "password='$esc_pass'");
} }
sub get_root_password { sub get_root_password {
my $status = 1; my $attempts = 3;
while ( $status == 1 ) { for (;;) {
echo_off(); my $password = read_without_echo("Enter current password for root (enter for none): ");
print "Enter current password for root (enter for none): ";
my $password = <STDIN>;
echo_on();
if ( $password ) { if ( $password ) {
$hadpass = 1; $hadpass = 1;
} else { } else {
@ -95,64 +159,56 @@ sub get_root_password {
} }
$rootpass = $password; $rootpass = $password;
make_config($rootpass); make_config($rootpass);
do_query(""); last if do_query("");
$status = $?;
die "Unable to connect to the server as root user, giving up.\n"
if --$attempts == 0;
} }
print "OK, successfully used password, moving on...\n\n"; print "OK, successfully used password, moving on...\n\n";
} }
sub set_root_password { sub set_root_password {
echo_off(); my $password1;
print "New password: "; for (;;) {
my $password1 = <STDIN>; $password1 = read_without_echo("New password: ");
print "\nRe-enter new password: ";
my $password2 = <STDIN>;
print "\n";
echo_on();
if ( $password1 eq $password2 ) { if ( !$password1 ) {
print "Sorry, passwords do not match.\n\n"; print "Sorry, you can't use an empty password here.\n\n";
return 1; next;
}
if ( !$password1 ) {
print "Sorry, you can't use an empty password here.\n\n";
return 1;
}
do_query("UPDATE mysql.user SET Password=PASSWORD('$password1') WHERE User='root';");
if ( $? == 0 ) {
print "Password updated successfully!\n";
print "Reloading privilege tables..\n";
if ( !reload_privilege_tables() ) {
exit 1;
} }
print "\n";
$rootpass = $password1; my $password2 = read_without_echo("Re-enter new password: ");
make_config($rootpass);
} else { if ( $password1 ne $password2 ) {
print "Password update failed!\n"; print "Sorry, passwords do not match.\n\n";
exit 1; next;
}
last;
} }
return 0; my $esc_pass = basic_single_escape($password1);
do_query("UPDATE mysql.user SET Password=PASSWORD('$esc_pass') WHERE User='root';")
or die "Password update failed!\n";
print "Password updated successfully!\n";
print "Reloading privilege tables..\n";
reload_privilege_tables()
or die "Can not continue.\n";
print "\n";
$rootpass = $password1;
make_config($rootpass);
} }
sub remove_anonymous_users { sub remove_anonymous_users {
do_query("DELETE FROM mysql.user WHERE User='';"); do_query("DELETE FROM mysql.user WHERE User='';")
if ( $? == 0 ) { or die print " ... Failed!\n";
print " ... Success!\n"; print " ... Success!\n";
} else {
print " ... Failed!\n";
exit 1;
}
return 0;
} }
sub remove_remote_root { sub remove_remote_root {
do_query("DELETE FROM mysql.user WHERE User='root' AND Host!='localhost';"); if (do_query("DELETE FROM mysql.user WHERE User='root' AND Host!='localhost';")) {
if ( $? == 0 ) {
print " ... Success!\n"; print " ... Success!\n";
} else { } else {
print " ... Failed!\n"; print " ... Failed!\n";
@ -161,44 +217,31 @@ sub remove_remote_root {
sub remove_test_database { sub remove_test_database {
print " - Dropping test database...\n"; print " - Dropping test database...\n";
do_query("DROP DATABASE test;"); if (do_query("DROP DATABASE test;")) {
if ( $? == 0 ) {
print " ... Success!\n"; print " ... Success!\n";
} else { } else {
print " ... Failed! Not critical, keep moving...\n"; print " ... Failed! Not critical, keep moving...\n";
} }
print " - Removing privileges on test database...\n"; print " - Removing privileges on test database...\n";
do_query("DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%'"); if (do_query("DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%'")) {
if ( $? == 0 ) {
print " ... Success!\n"; print " ... Success!\n";
} else { } else {
print " ... Failed! Not critical, keep moving...\n"; print " ... Failed! Not critical, keep moving...\n";
} }
return 0;
} }
sub reload_privilege_tables { sub reload_privilege_tables {
do_query("FLUSH PRIVILEGES;"); if (do_query("FLUSH PRIVILEGES;")) {
if ( $? == 0 ) {
print " ... Success!\n"; print " ... Success!\n";
return 0; return 1;
} else { } else {
print " ... Failed!\n"; print " ... Failed!\n";
return 1; return undef;
} }
} }
sub interrupt {
print "\nAborting!\n\n";
cleanup();
echo_on();
exit 1;
}
sub cleanup { sub cleanup {
print "Cleaning up...\n";
unlink($config,$command); unlink($config,$command);
} }
@ -242,11 +285,7 @@ my $reply = <STDIN>;
if ( $reply =~ /n/i ) { if ( $reply =~ /n/i ) {
print " ... skipping.\n"; print " ... skipping.\n";
} else { } else {
my $status = 1; set_root_password();
while ( $status == 1 ) {
set_root_password();
$status = $?;
}
} }
print "\n"; print "\n";
@ -334,8 +373,6 @@ if ( $reply =~ /n/i ) {
} }
print "\n"; print "\n";
cleanup();
print <<HERE; print <<HERE;

View File

@ -38,16 +38,39 @@ prepare() {
} }
do_query() { do_query() {
echo $1 >$command echo "$1" >$command
#sed 's,^,> ,' < $command # Debugging
mysql --defaults-file=$config <$command mysql --defaults-file=$config <$command
return $? return $?
} }
# Simple escape mechanism (\-escape any ' and \), suitable for two contexts:
# - single-quoted SQL strings
# - single-quoted option values on the right hand side of = in my.cnf
#
# These two contexts don't handle escapes identically. SQL strings allow
# quoting any character (\C => C, for any C), but my.cnf parsing allows
# quoting only \, ' or ". For example, password='a\b' quotes a 3-character
# string in my.cnf, but a 2-character string in SQL.
#
# This simple escape works correctly in both places.
basic_single_escape () {
# The quoting on this sed command is a bit complex. Single-quoted strings
# don't allow *any* escape mechanism, so they cannot contain a single
# quote. The string sed gets (as argv[1]) is: s/\(['\]\)/\\\1/g
#
# Inside a character class, \ and ' are not special, so the ['\] character
# class is balanced and contains two characters.
echo "$1" | sed 's/\(['"'"'\]\)/\\\1/g'
}
make_config() { make_config() {
echo "# mysql_secure_installation config file" >$config echo "# mysql_secure_installation config file" >$config
echo "[mysql]" >>$config echo "[mysql]" >>$config
echo "user=root" >>$config echo "user=root" >>$config
echo "password=$rootpass" >>$config esc_pass=`basic_single_escape "$rootpass"`
echo "password='$esc_pass'" >>$config
#sed 's,^,> ,' < $config # Debugging
} }
get_root_password() { get_root_password() {
@ -94,13 +117,12 @@ set_root_password() {
return 1 return 1
fi fi
do_query "UPDATE mysql.user SET Password=PASSWORD('$password1') WHERE User='root';" esc_pass=`basic_single_escape "$password1"`
do_query "UPDATE mysql.user SET Password=PASSWORD('$esc_pass') WHERE User='root';"
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
echo "Password updated successfully!" echo "Password updated successfully!"
echo "Reloading privilege tables.." echo "Reloading privilege tables.."
if ! reload_privilege_tables; then reload_privilege_tables || exit 1
exit 1
fi
echo echo
rootpass=$password1 rootpass=$password1
make_config make_config

View File

@ -6940,7 +6940,22 @@ int stored_field_cmp_to_item(THD *thd, Field *field, Item *item)
Item_cache* Item_cache::get_cache(const Item *item) Item_cache* Item_cache::get_cache(const Item *item)
{ {
switch (item->result_type()) { return get_cache(item, item->result_type());
}
/**
Get a cache item of given type.
@param item value to be cached
@param type required type of cache
@return cache item
*/
Item_cache* Item_cache::get_cache(const Item *item, const Item_result type)
{
switch (type) {
case INT_RESULT: case INT_RESULT:
return new Item_cache_int(); return new Item_cache_int();
case REAL_RESULT: case REAL_RESULT:
@ -6958,6 +6973,12 @@ Item_cache* Item_cache::get_cache(const Item *item)
} }
} }
void Item_cache::store(Item *item)
{
if (item)
example= item;
value_cached= FALSE;
}
void Item_cache::print(String *str, enum_query_type query_type) void Item_cache::print(String *str, enum_query_type query_type)
{ {
@ -6969,17 +6990,19 @@ void Item_cache::print(String *str, enum_query_type query_type)
str->append(')'); str->append(')');
} }
void Item_cache_int::cache_value()
void Item_cache_int::store(Item *item)
{ {
value= item->val_int_result(); value_cached= TRUE;
null_value= item->null_value; value= example->val_int_result();
unsigned_flag= item->unsigned_flag; null_value= example->null_value;
unsigned_flag= example->unsigned_flag;
} }
void Item_cache_int::store(Item *item, longlong val_arg) void Item_cache_int::store(Item *item, longlong val_arg)
{ {
/* An explicit values is given, save it. */
value_cached= TRUE;
value= val_arg; value= val_arg;
null_value= item->null_value; null_value= item->null_value;
unsigned_flag= item->unsigned_flag; unsigned_flag= item->unsigned_flag;
@ -6989,6 +7012,8 @@ void Item_cache_int::store(Item *item, longlong val_arg)
String *Item_cache_int::val_str(String *str) String *Item_cache_int::val_str(String *str)
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
if (!value_cached)
cache_value();
str->set(value, default_charset()); str->set(value, default_charset());
return str; return str;
} }
@ -6997,21 +7022,49 @@ String *Item_cache_int::val_str(String *str)
my_decimal *Item_cache_int::val_decimal(my_decimal *decimal_val) my_decimal *Item_cache_int::val_decimal(my_decimal *decimal_val)
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
if (!value_cached)
cache_value();
int2my_decimal(E_DEC_FATAL_ERROR, value, unsigned_flag, decimal_val); int2my_decimal(E_DEC_FATAL_ERROR, value, unsigned_flag, decimal_val);
return decimal_val; return decimal_val;
} }
double Item_cache_int::val_real()
void Item_cache_real::store(Item *item)
{ {
value= item->val_result(); DBUG_ASSERT(fixed == 1);
null_value= item->null_value; if (!value_cached)
cache_value();
return (double) value;
} }
longlong Item_cache_int::val_int()
{
DBUG_ASSERT(fixed == 1);
if (!value_cached)
cache_value();
return value;
}
void Item_cache_real::cache_value()
{
value_cached= TRUE;
value= example->val_result();
null_value= example->null_value;
}
double Item_cache_real::val_real()
{
DBUG_ASSERT(fixed == 1);
if (!value_cached)
cache_value();
return value;
}
longlong Item_cache_real::val_int() longlong Item_cache_real::val_int()
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
if (!value_cached)
cache_value();
return (longlong) rint(value); return (longlong) rint(value);
} }
@ -7019,6 +7072,8 @@ longlong Item_cache_real::val_int()
String* Item_cache_real::val_str(String *str) String* Item_cache_real::val_str(String *str)
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
if (!value_cached)
cache_value();
str->set_real(value, decimals, default_charset()); str->set_real(value, decimals, default_charset());
return str; return str;
} }
@ -7027,15 +7082,18 @@ String* Item_cache_real::val_str(String *str)
my_decimal *Item_cache_real::val_decimal(my_decimal *decimal_val) my_decimal *Item_cache_real::val_decimal(my_decimal *decimal_val)
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
if (!value_cached)
cache_value();
double2my_decimal(E_DEC_FATAL_ERROR, value, decimal_val); double2my_decimal(E_DEC_FATAL_ERROR, value, decimal_val);
return decimal_val; return decimal_val;
} }
void Item_cache_decimal::store(Item *item) void Item_cache_decimal::cache_value()
{ {
my_decimal *val= item->val_decimal_result(&decimal_value); value_cached= TRUE;
if (!(null_value= item->null_value) && val != &decimal_value) my_decimal *val= example->val_decimal_result(&decimal_value);
if (!(null_value= example->null_value) && val != &decimal_value)
my_decimal2decimal(val, &decimal_value); my_decimal2decimal(val, &decimal_value);
} }
@ -7043,6 +7101,8 @@ double Item_cache_decimal::val_real()
{ {
DBUG_ASSERT(fixed); DBUG_ASSERT(fixed);
double res; double res;
if (!value_cached)
cache_value();
my_decimal2double(E_DEC_FATAL_ERROR, &decimal_value, &res); my_decimal2double(E_DEC_FATAL_ERROR, &decimal_value, &res);
return res; return res;
} }
@ -7051,6 +7111,8 @@ longlong Item_cache_decimal::val_int()
{ {
DBUG_ASSERT(fixed); DBUG_ASSERT(fixed);
longlong res; longlong res;
if (!value_cached)
cache_value();
my_decimal2int(E_DEC_FATAL_ERROR, &decimal_value, unsigned_flag, &res); my_decimal2int(E_DEC_FATAL_ERROR, &decimal_value, unsigned_flag, &res);
return res; return res;
} }
@ -7058,6 +7120,8 @@ longlong Item_cache_decimal::val_int()
String* Item_cache_decimal::val_str(String *str) String* Item_cache_decimal::val_str(String *str)
{ {
DBUG_ASSERT(fixed); DBUG_ASSERT(fixed);
if (!value_cached)
cache_value();
my_decimal_round(E_DEC_FATAL_ERROR, &decimal_value, decimals, FALSE, my_decimal_round(E_DEC_FATAL_ERROR, &decimal_value, decimals, FALSE,
&decimal_value); &decimal_value);
my_decimal2string(E_DEC_FATAL_ERROR, &decimal_value, 0, 0, 0, str); my_decimal2string(E_DEC_FATAL_ERROR, &decimal_value, 0, 0, 0, str);
@ -7067,15 +7131,18 @@ String* Item_cache_decimal::val_str(String *str)
my_decimal *Item_cache_decimal::val_decimal(my_decimal *val) my_decimal *Item_cache_decimal::val_decimal(my_decimal *val)
{ {
DBUG_ASSERT(fixed); DBUG_ASSERT(fixed);
if (!value_cached)
cache_value();
return &decimal_value; return &decimal_value;
} }
void Item_cache_str::store(Item *item) void Item_cache_str::cache_value()
{ {
value_buff.set(buffer, sizeof(buffer), item->collation.collation); value_cached= TRUE;
value= item->str_result(&value_buff); value_buff.set(buffer, sizeof(buffer), example->collation.collation);
if ((null_value= item->null_value)) value= example->str_result(&value_buff);
if ((null_value= example->null_value))
value= 0; value= 0;
else if (value != &value_buff) else if (value != &value_buff)
{ {
@ -7097,6 +7164,8 @@ double Item_cache_str::val_real()
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
int err_not_used; int err_not_used;
char *end_not_used; char *end_not_used;
if (!value_cached)
cache_value();
if (value) if (value)
return my_strntod(value->charset(), (char*) value->ptr(), return my_strntod(value->charset(), (char*) value->ptr(),
value->length(), &end_not_used, &err_not_used); value->length(), &end_not_used, &err_not_used);
@ -7108,6 +7177,8 @@ longlong Item_cache_str::val_int()
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
int err; int err;
if (!value_cached)
cache_value();
if (value) if (value)
return my_strntoll(value->charset(), value->ptr(), return my_strntoll(value->charset(), value->ptr(),
value->length(), 10, (char**) 0, &err); value->length(), 10, (char**) 0, &err);
@ -7115,9 +7186,21 @@ longlong Item_cache_str::val_int()
return (longlong)0; return (longlong)0;
} }
String* Item_cache_str::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
if (!value_cached)
cache_value();
return value;
}
my_decimal *Item_cache_str::val_decimal(my_decimal *decimal_val) my_decimal *Item_cache_str::val_decimal(my_decimal *decimal_val)
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
if (!value_cached)
cache_value();
if (value) if (value)
string2my_decimal(E_DEC_FATAL_ERROR, value, decimal_val); string2my_decimal(E_DEC_FATAL_ERROR, value, decimal_val);
else else
@ -7128,6 +7211,8 @@ my_decimal *Item_cache_str::val_decimal(my_decimal *decimal_val)
int Item_cache_str::save_in_field(Field *field, bool no_conversions) int Item_cache_str::save_in_field(Field *field, bool no_conversions)
{ {
if (!value_cached)
cache_value();
int res= Item_cache::save_in_field(field, no_conversions); int res= Item_cache::save_in_field(field, no_conversions);
return (is_varbinary && field->type() == MYSQL_TYPE_STRING && return (is_varbinary && field->type() == MYSQL_TYPE_STRING &&
value->length() < field->field_length) ? 1 : res; value->length() < field->field_length) ? 1 : res;
@ -7162,11 +7247,19 @@ bool Item_cache_row::setup(Item * item)
void Item_cache_row::store(Item * item) void Item_cache_row::store(Item * item)
{ {
for (uint i= 0; i < item_count; i++)
values[i]->store(item->element_index(i));
}
void Item_cache_row::cache_value()
{
value_cached= TRUE;
null_value= 0; null_value= 0;
item->bring_value(); example->bring_value();
for (uint i= 0; i < item_count; i++) for (uint i= 0; i < item_count; i++)
{ {
values[i]->store(item->element_index(i)); values[i]->cache_value();
null_value|= values[i]->null_value; null_value|= values[i]->null_value;
} }
} }

View File

@ -1024,7 +1024,11 @@ class sp_head;
class Item_basic_constant :public Item class Item_basic_constant :public Item
{ {
table_map used_table_map;
public: public:
Item_basic_constant(): Item(), used_table_map(0) {};
void set_used_tables(table_map map) { used_table_map= map; }
table_map used_tables() const { return used_table_map; }
/* to prevent drop fixed flag (no need parent cleanup call) */ /* to prevent drop fixed flag (no need parent cleanup call) */
void cleanup() void cleanup()
{ {
@ -2889,15 +2893,25 @@ protected:
*/ */
Field *cached_field; Field *cached_field;
enum enum_field_types cached_field_type; enum enum_field_types cached_field_type;
/*
TRUE <=> cache holds value of the last stored item (i.e actual value).
store() stores item to be cached and sets this flag to FALSE.
On the first call of val_xxx function if this flag is set to FALSE the
cache_value() will be called to actually cache value of saved item.
cache_value() will set this flag to TRUE.
*/
bool value_cached;
public: public:
Item_cache(): Item_cache():
example(0), used_table_map(0), cached_field(0), cached_field_type(MYSQL_TYPE_STRING) example(0), used_table_map(0), cached_field(0), cached_field_type(MYSQL_TYPE_STRING),
value_cached(0)
{ {
fixed= 1; fixed= 1;
null_value= 1; null_value= 1;
} }
Item_cache(enum_field_types field_type_arg): Item_cache(enum_field_types field_type_arg):
example(0), used_table_map(0), cached_field(0), cached_field_type(field_type_arg) example(0), used_table_map(0), cached_field(0), cached_field_type(field_type_arg),
value_cached(0)
{ {
fixed= 1; fixed= 1;
null_value= 1; null_value= 1;
@ -2917,10 +2931,10 @@ public:
cached_field= ((Item_field *)item)->field; cached_field= ((Item_field *)item)->field;
return 0; return 0;
}; };
virtual void store(Item *)= 0;
enum Type type() const { return CACHE_ITEM; } enum Type type() const { return CACHE_ITEM; }
enum_field_types field_type() const { return cached_field_type; } enum_field_types field_type() const { return cached_field_type; }
static Item_cache* get_cache(const Item *item); static Item_cache* get_cache(const Item *item);
static Item_cache* get_cache(const Item* item, const Item_result type);
table_map used_tables() const { return used_table_map; } table_map used_tables() const { return used_table_map; }
virtual void keep_array() {} virtual void keep_array() {}
virtual void print(String *str, enum_query_type query_type); virtual void print(String *str, enum_query_type query_type);
@ -2932,6 +2946,8 @@ public:
{ {
return this == item; return this == item;
} }
virtual void store(Item *item);
virtual void cache_value()= 0;
}; };
@ -2940,18 +2956,19 @@ class Item_cache_int: public Item_cache
protected: protected:
longlong value; longlong value;
public: public:
Item_cache_int(): Item_cache(), value(0) {} Item_cache_int(): Item_cache(),
value(0) {}
Item_cache_int(enum_field_types field_type_arg): Item_cache_int(enum_field_types field_type_arg):
Item_cache(field_type_arg), value(0) {} Item_cache(field_type_arg), value(0) {}
void store(Item *item);
void store(Item *item, longlong val_arg); void store(Item *item, longlong val_arg);
double val_real() { DBUG_ASSERT(fixed == 1); return (double) value; } double val_real();
longlong val_int() { DBUG_ASSERT(fixed == 1); return value; } longlong val_int();
String* val_str(String *str); String* val_str(String *str);
my_decimal *val_decimal(my_decimal *); my_decimal *val_decimal(my_decimal *);
enum Item_result result_type() const { return INT_RESULT; } enum Item_result result_type() const { return INT_RESULT; }
bool result_as_longlong() { return TRUE; } bool result_as_longlong() { return TRUE; }
void cache_value();
}; };
@ -2959,14 +2976,15 @@ class Item_cache_real: public Item_cache
{ {
double value; double value;
public: public:
Item_cache_real(): Item_cache(), value(0) {} Item_cache_real(): Item_cache(),
value(0) {}
void store(Item *item); double val_real();
double val_real() { DBUG_ASSERT(fixed == 1); return value; }
longlong val_int(); longlong val_int();
String* val_str(String *str); String* val_str(String *str);
my_decimal *val_decimal(my_decimal *); my_decimal *val_decimal(my_decimal *);
enum Item_result result_type() const { return REAL_RESULT; } enum Item_result result_type() const { return REAL_RESULT; }
void cache_value();
}; };
@ -2977,12 +2995,12 @@ protected:
public: public:
Item_cache_decimal(): Item_cache() {} Item_cache_decimal(): Item_cache() {}
void store(Item *item);
double val_real(); double val_real();
longlong val_int(); longlong val_int();
String* val_str(String *str); String* val_str(String *str);
my_decimal *val_decimal(my_decimal *); my_decimal *val_decimal(my_decimal *);
enum Item_result result_type() const { return DECIMAL_RESULT; } enum Item_result result_type() const { return DECIMAL_RESULT; }
void cache_value();
}; };
@ -3000,14 +3018,14 @@ public:
MYSQL_TYPE_VARCHAR && MYSQL_TYPE_VARCHAR &&
!((const Item_field *) item)->field->has_charset()) !((const Item_field *) item)->field->has_charset())
{} {}
void store(Item *item);
double val_real(); double val_real();
longlong val_int(); longlong val_int();
String* val_str(String *) { DBUG_ASSERT(fixed == 1); return value; } String* val_str(String *);
my_decimal *val_decimal(my_decimal *); my_decimal *val_decimal(my_decimal *);
enum Item_result result_type() const { return STRING_RESULT; } enum Item_result result_type() const { return STRING_RESULT; }
CHARSET_INFO *charset() const { return value->charset(); }; CHARSET_INFO *charset() const { return value->charset(); };
int save_in_field(Field *field, bool no_conversions); int save_in_field(Field *field, bool no_conversions);
void cache_value();
}; };
class Item_cache_row: public Item_cache class Item_cache_row: public Item_cache
@ -3017,7 +3035,8 @@ class Item_cache_row: public Item_cache
bool save_array; bool save_array;
public: public:
Item_cache_row() Item_cache_row()
:Item_cache(), values(0), item_count(2), save_array(0) {} :Item_cache(), values(0), item_count(2),
save_array(0) {}
/* /*
'allocate' used only in row transformer, to preallocate space for row 'allocate' used only in row transformer, to preallocate space for row
@ -3075,6 +3094,7 @@ public:
values= 0; values= 0;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
void cache_value();
}; };

View File

@ -785,15 +785,21 @@ Arg_comparator::can_compare_as_dates(Item *a, Item *b, ulonglong *const_value)
if (cmp_type != CMP_DATE_DFLT) if (cmp_type != CMP_DATE_DFLT)
{ {
THD *thd= current_thd;
/* /*
Do not cache GET_USER_VAR() function as its const_item() may return TRUE Do not cache GET_USER_VAR() function as its const_item() may return TRUE
for the current thread but it still may change during the execution. for the current thread but it still may change during the execution.
Don't use cache while in the context analysis mode only (i.e. for
EXPLAIN/CREATE VIEW and similar queries). Cache is useless in such
cases and can cause problems. For example evaluating subqueries can
confuse storage engines since in context analysis mode tables
aren't locked.
*/ */
if (cmp_type != CMP_DATE_WITH_DATE && str_arg->const_item() && if (!thd->is_context_analysis_only() &&
cmp_type != CMP_DATE_WITH_DATE && str_arg->const_item() &&
(str_arg->type() != Item::FUNC_ITEM || (str_arg->type() != Item::FUNC_ITEM ||
((Item_func*)str_arg)->functype() != Item_func::GUSERVAR_FUNC)) ((Item_func*)str_arg)->functype() != Item_func::GUSERVAR_FUNC))
{ {
THD *thd= current_thd;
ulonglong value; ulonglong value;
bool error; bool error;
String tmp, *str_val= 0; String tmp, *str_val= 0;
@ -881,13 +887,13 @@ int Arg_comparator::set_cmp_func(Item_bool_func2 *owner_arg,
{ {
enum enum_date_cmp_type cmp_type; enum enum_date_cmp_type cmp_type;
ulonglong const_value= (ulonglong)-1; ulonglong const_value= (ulonglong)-1;
thd= current_thd;
owner= owner_arg;
a= a1; a= a1;
b= a2; b= a2;
if ((cmp_type= can_compare_as_dates(*a, *b, &const_value))) if ((cmp_type= can_compare_as_dates(*a, *b, &const_value)))
{ {
thd= current_thd;
owner= owner_arg;
a_type= (*a)->field_type(); a_type= (*a)->field_type();
b_type= (*b)->field_type(); b_type= (*b)->field_type();
a_cache= 0; a_cache= 0;
@ -895,6 +901,10 @@ int Arg_comparator::set_cmp_func(Item_bool_func2 *owner_arg,
if (const_value != (ulonglong)-1) if (const_value != (ulonglong)-1)
{ {
/*
cache_converted_constant can't be used here because it can't
correctly convert a DATETIME value from string to int representation.
*/
Item_cache_int *cache= new Item_cache_int(); Item_cache_int *cache= new Item_cache_int();
/* Mark the cache as non-const to prevent re-caching. */ /* Mark the cache as non-const to prevent re-caching. */
cache->set_used_tables(1); cache->set_used_tables(1);
@ -920,8 +930,6 @@ int Arg_comparator::set_cmp_func(Item_bool_func2 *owner_arg,
(*b)->field_type() == MYSQL_TYPE_TIME) (*b)->field_type() == MYSQL_TYPE_TIME)
{ {
/* Compare TIME values as integers. */ /* Compare TIME values as integers. */
thd= current_thd;
owner= owner_arg;
a_cache= 0; a_cache= 0;
b_cache= 0; b_cache= 0;
is_nulls_eq= test(owner && owner->functype() == Item_func::EQUAL_FUNC); is_nulls_eq= test(owner && owner->functype() == Item_func::EQUAL_FUNC);
@ -940,10 +948,46 @@ int Arg_comparator::set_cmp_func(Item_bool_func2 *owner_arg,
return 1; return 1;
} }
a= cache_converted_constant(thd, a, &a_cache, type);
b= cache_converted_constant(thd, b, &b_cache, type);
return set_compare_func(owner_arg, type); return set_compare_func(owner_arg, type);
} }
/**
Convert and cache a constant.
@param value [in] An item to cache
@param cache_item [out] Placeholder for the cache item
@param type [in] Comparison type
@details
When given item is a constant and its type differs from comparison type
then cache its value to avoid type conversion of this constant on each
evaluation. In this case the value is cached and the reference to the cache
is returned.
Original value is returned otherwise.
@return cache item or original value.
*/
Item** Arg_comparator::cache_converted_constant(THD *thd, Item **value,
Item **cache_item,
Item_result type)
{
/* Don't need cache if doing context analysis only. */
if (!thd->is_context_analysis_only() &&
(*value)->const_item() && type != (*value)->result_type())
{
Item_cache *cache= Item_cache::get_cache(*value, type);
cache->store(*value);
*cache_item= cache;
return cache_item;
}
return value;
}
void Arg_comparator::set_datetime_cmp_func(Item **a1, Item **b1) void Arg_comparator::set_datetime_cmp_func(Item **a1, Item **b1)
{ {
thd= current_thd; thd= current_thd;
@ -1582,6 +1626,7 @@ longlong Item_in_optimizer::val_int()
bool tmp; bool tmp;
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
cache->store(args[0]); cache->store(args[0]);
cache->cache_value();
if (cache->null_value) if (cache->null_value)
{ {

View File

@ -94,6 +94,8 @@ public:
ulonglong *const_val_arg); ulonglong *const_val_arg);
void set_datetime_cmp_func(Item **a1, Item **b1); void set_datetime_cmp_func(Item **a1, Item **b1);
Item** cache_converted_constant(THD *thd, Item **value, Item **cache,
Item_result type);
static arg_cmp_func comparator_matrix [5][2]; static arg_cmp_func comparator_matrix [5][2];
friend class Item_func; friend class Item_func;

View File

@ -480,6 +480,7 @@ Item_singlerow_subselect::select_transformer(JOIN *join)
void Item_singlerow_subselect::store(uint i, Item *item) void Item_singlerow_subselect::store(uint i, Item *item)
{ {
row[i]->store(item); row[i]->store(item);
row[i]->cache_value();
} }
enum Item_result Item_singlerow_subselect::result_type() const enum Item_result Item_singlerow_subselect::result_type() const
@ -1831,6 +1832,7 @@ void subselect_engine::set_row(List<Item> &item_list, Item_cache **row)
if (!(row[i]= Item_cache::get_cache(sel_item))) if (!(row[i]= Item_cache::get_cache(sel_item)))
return; return;
row[i]->setup(sel_item); row[i]->setup(sel_item);
row[i]->store(sel_item);
} }
if (item_list.elements > 1) if (item_list.elements > 1)
res_type= ROW_RESULT; res_type= ROW_RESULT;

View File

@ -941,14 +941,16 @@ static Item *create_comparator(MY_XPATH *xpath,
in a loop through all of the nodes in the node set. in a loop through all of the nodes in the node set.
*/ */
Item *fake= new Item_string("", 0, xpath->cs); Item_string *fake= new Item_string("", 0, xpath->cs);
/* Don't cache fake because its value will be changed during comparison.*/
fake->set_used_tables(RAND_TABLE_BIT);
Item_nodeset_func *nodeset; Item_nodeset_func *nodeset;
Item *scalar, *comp; Item *scalar, *comp;
if (a->type() == Item::XPATH_NODESET) if (a->type() == Item::XPATH_NODESET)
{ {
nodeset= (Item_nodeset_func*) a; nodeset= (Item_nodeset_func*) a;
scalar= b; scalar= b;
comp= eq_func(oper, fake, scalar); comp= eq_func(oper, (Item*)fake, scalar);
} }
else else
{ {

View File

@ -3966,6 +3966,27 @@ server.");
if (opt_bin_log) if (opt_bin_log)
{ {
/* Reports an error and aborts, if the --log-bin's path
is a directory.*/
if (opt_bin_logname &&
opt_bin_logname[strlen(opt_bin_logname) - 1] == FN_LIBCHAR)
{
sql_print_error("Path '%s' is a directory name, please specify \
a file name for --log-bin option", opt_bin_logname);
unireg_abort(1);
}
/* Reports an error and aborts, if the --log-bin-index's path
is a directory.*/
if (opt_binlog_index_name &&
opt_binlog_index_name[strlen(opt_binlog_index_name) - 1]
== FN_LIBCHAR)
{
sql_print_error("Path '%s' is a directory name, please specify \
a file name for --log-bin-index option", opt_binlog_index_name);
unireg_abort(1);
}
char buf[FN_REFLEN]; char buf[FN_REFLEN];
const char *ln; const char *ln;
ln= mysql_bin_log.generate_name(opt_bin_logname, "-bin", 1, buf); ln= mysql_bin_log.generate_name(opt_bin_logname, "-bin", 1, buf);
@ -8736,14 +8757,8 @@ static int fix_paths(void)
pos[0]= FN_LIBCHAR; pos[0]= FN_LIBCHAR;
pos[1]= 0; pos[1]= 0;
} }
convert_dirname(mysql_real_data_home,mysql_real_data_home,NullS);
my_realpath(mysql_unpacked_real_data_home, mysql_real_data_home, MYF(0));
mysql_unpacked_real_data_home_len= strlen(mysql_unpacked_real_data_home);
if (mysql_unpacked_real_data_home[mysql_unpacked_real_data_home_len-1] == FN_LIBCHAR)
--mysql_unpacked_real_data_home_len;
convert_dirname(language,language,NullS); convert_dirname(language,language,NullS);
convert_dirname(mysql_real_data_home,mysql_real_data_home,NullS);
(void) my_load_path(mysql_home,mysql_home,""); // Resolve current dir (void) my_load_path(mysql_home,mysql_home,""); // Resolve current dir
(void) my_load_path(mysql_real_data_home,mysql_real_data_home,mysql_home); (void) my_load_path(mysql_real_data_home,mysql_real_data_home,mysql_home);
(void) my_load_path(pidfile_name,pidfile_name,mysql_real_data_home); (void) my_load_path(pidfile_name,pidfile_name,mysql_real_data_home);
@ -8751,6 +8766,12 @@ static int fix_paths(void)
get_relative_path(PLUGINDIR), mysql_home); get_relative_path(PLUGINDIR), mysql_home);
opt_plugin_dir_ptr= opt_plugin_dir; opt_plugin_dir_ptr= opt_plugin_dir;
my_realpath(mysql_unpacked_real_data_home, mysql_real_data_home, MYF(0));
mysql_unpacked_real_data_home_len=
(int) strlen(mysql_unpacked_real_data_home);
if (mysql_unpacked_real_data_home[mysql_unpacked_real_data_home_len-1] == FN_LIBCHAR)
--mysql_unpacked_real_data_home_len;
char *sharedir=get_relative_path(SHAREDIR); char *sharedir=get_relative_path(SHAREDIR);
if (test_if_hard_path(sharedir)) if (test_if_hard_path(sharedir))
strmake(buff,sharedir,sizeof(buff)-1); /* purecov: tested */ strmake(buff,sharedir,sizeof(buff)-1); /* purecov: tested */

View File

@ -132,6 +132,29 @@ int init_relay_log_info(Relay_log_info* rli,
rli->relay_log.max_size (and mysql_bin_log.max_size). rli->relay_log.max_size (and mysql_bin_log.max_size).
*/ */
{ {
/* Reports an error and returns, if the --relay-log's path
is a directory.*/
if (opt_relay_logname &&
opt_relay_logname[strlen(opt_relay_logname) - 1] == FN_LIBCHAR)
{
pthread_mutex_unlock(&rli->data_lock);
sql_print_error("Path '%s' is a directory name, please specify \
a file name for --relay-log option", opt_relay_logname);
DBUG_RETURN(1);
}
/* Reports an error and returns, if the --relay-log-index's path
is a directory.*/
if (opt_relaylog_index_name &&
opt_relaylog_index_name[strlen(opt_relaylog_index_name) - 1]
== FN_LIBCHAR)
{
pthread_mutex_unlock(&rli->data_lock);
sql_print_error("Path '%s' is a directory name, please specify \
a file name for --relay-log-index option", opt_relaylog_index_name);
DBUG_RETURN(1);
}
char buf[FN_REFLEN]; char buf[FN_REFLEN];
const char *ln; const char *ln;
static bool name_warning_sent= 0; static bool name_warning_sent= 0;

View File

@ -617,7 +617,7 @@ sp_rcontext::set_case_expr(THD *thd, int case_expr_id, Item **case_expr_item_ptr
} }
m_case_expr_holders[case_expr_id]->store(case_expr_item); m_case_expr_holders[case_expr_id]->store(case_expr_item);
m_case_expr_holders[case_expr_id]->cache_value();
return FALSE; return FALSE;
} }

View File

@ -985,14 +985,20 @@ JOIN::optimize()
DBUG_RETURN(1); DBUG_RETURN(1);
} }
if (select_lex->olap == ROLLUP_TYPE && rollup_process_const_fields()) if (rollup.state != ROLLUP::STATE_NONE)
{ {
DBUG_PRINT("error", ("Error: rollup_process_fields() failed")); if (rollup_process_const_fields())
DBUG_RETURN(1); {
DBUG_PRINT("error", ("Error: rollup_process_fields() failed"));
DBUG_RETURN(1);
}
}
else
{
/* Remove distinct if only const tables */
select_distinct= select_distinct && (const_tables != tables);
} }
/* Remove distinct if only const tables */
select_distinct= select_distinct && (const_tables != tables);
thd_proc_info(thd, "preparing"); thd_proc_info(thd, "preparing");
if (result->initialize_tables(this)) if (result->initialize_tables(this))
{ {
@ -1291,11 +1297,14 @@ JOIN::optimize()
- We are using an ORDER BY or GROUP BY on fields not in the first table - We are using an ORDER BY or GROUP BY on fields not in the first table
- We are using different ORDER BY and GROUP BY orders - We are using different ORDER BY and GROUP BY orders
- The user wants us to buffer the result. - The user wants us to buffer the result.
When the WITH ROLLUP modifier is present, we cannot skip temporary table
creation for the DISTINCT clause just because there are only const tables.
*/ */
need_tmp= (const_tables != tables && need_tmp= ((const_tables != tables &&
((select_distinct || !simple_order || !simple_group) || ((select_distinct || !simple_order || !simple_group) ||
(group_list && order) || (group_list && order) ||
test(select_options & OPTION_BUFFER_RESULT))); test(select_options & OPTION_BUFFER_RESULT))) ||
rollup.state != ROLLUP::STATE_NONE && select_distinct);
// No cache for MATCH // No cache for MATCH
make_join_readinfo(this, make_join_readinfo(this,
@ -6481,6 +6490,56 @@ void rr_unlock_row(st_join_table *tab)
/**
Pick the appropriate access method functions
Sets the functions for the selected table access method
@param tab Table reference to put access method
*/
static void
pick_table_access_method(JOIN_TAB *tab)
{
switch (tab->type)
{
case JT_REF:
tab->read_first_record= join_read_always_key;
tab->read_record.read_record= join_read_next_same;
break;
case JT_REF_OR_NULL:
tab->read_first_record= join_read_always_key_or_null;
tab->read_record.read_record= join_read_next_same_or_null;
break;
case JT_CONST:
tab->read_first_record= join_read_const;
tab->read_record.read_record= join_no_more_records;
break;
case JT_EQ_REF:
tab->read_first_record= join_read_key;
tab->read_record.read_record= join_no_more_records;
break;
case JT_FT:
tab->read_first_record= join_ft_read_first;
tab->read_record.read_record= join_ft_read_next;
break;
case JT_SYSTEM:
tab->read_first_record= join_read_system;
tab->read_record.read_record= join_no_more_records;
break;
/* keep gcc happy */
default:
break;
}
}
static void static void
make_join_readinfo(JOIN *join, ulonglong options) make_join_readinfo(JOIN *join, ulonglong options)
{ {
@ -6515,45 +6574,15 @@ make_join_readinfo(JOIN *join, ulonglong options)
tab->sorted= sorted; tab->sorted= sorted;
sorted= 0; // only first must be sorted sorted= 0; // only first must be sorted
table->status=STATUS_NO_RECORD;
pick_table_access_method (tab);
switch (tab->type) { switch (tab->type) {
case JT_SYSTEM: // Only happens with left join
table->status=STATUS_NO_RECORD;
tab->read_first_record= join_read_system;
tab->read_record.read_record= join_no_more_records;
break;
case JT_CONST: // Only happens with left join
table->status=STATUS_NO_RECORD;
tab->read_first_record= join_read_const;
tab->read_record.read_record= join_no_more_records;
if (table->covering_keys.is_set(tab->ref.key) &&
!table->no_keyread)
{
table->key_read=1;
table->file->extra(HA_EXTRA_KEYREAD);
}
break;
case JT_EQ_REF: case JT_EQ_REF:
table->status=STATUS_NO_RECORD;
if (tab->select)
{
delete tab->select->quick;
tab->select->quick=0;
}
delete tab->quick;
tab->quick=0;
tab->read_first_record= join_read_key;
tab->read_record.unlock_row= join_read_key_unlock_row; tab->read_record.unlock_row= join_read_key_unlock_row;
tab->read_record.read_record= join_no_more_records; /* fall through */
if (table->covering_keys.is_set(tab->ref.key) &&
!table->no_keyread)
{
table->key_read=1;
table->file->extra(HA_EXTRA_KEYREAD);
}
break;
case JT_REF_OR_NULL: case JT_REF_OR_NULL:
case JT_REF: case JT_REF:
table->status=STATUS_NO_RECORD;
if (tab->select) if (tab->select)
{ {
delete tab->select->quick; delete tab->select->quick;
@ -6561,34 +6590,20 @@ make_join_readinfo(JOIN *join, ulonglong options)
} }
delete tab->quick; delete tab->quick;
tab->quick=0; tab->quick=0;
/* fall through */
case JT_CONST: // Only happens with left join
if (table->covering_keys.is_set(tab->ref.key) && if (table->covering_keys.is_set(tab->ref.key) &&
!table->no_keyread) !table->no_keyread)
{ {
table->key_read=1; table->key_read=1;
table->file->extra(HA_EXTRA_KEYREAD); table->file->extra(HA_EXTRA_KEYREAD);
} }
if (tab->type == JT_REF)
{
tab->read_first_record= join_read_always_key;
tab->read_record.read_record= join_read_next_same;
}
else
{
tab->read_first_record= join_read_always_key_or_null;
tab->read_record.read_record= join_read_next_same_or_null;
}
break;
case JT_FT:
table->status=STATUS_NO_RECORD;
tab->read_first_record= join_ft_read_first;
tab->read_record.read_record= join_ft_read_next;
break; break;
case JT_ALL: case JT_ALL:
/* /*
If previous table use cache If previous table use cache
If the incoming data set is already sorted don't use cache. If the incoming data set is already sorted don't use cache.
*/ */
table->status=STATUS_NO_RECORD;
if (i != join->const_tables && !(options & SELECT_NO_JOIN_CACHE) && if (i != join->const_tables && !(options & SELECT_NO_JOIN_CACHE) &&
tab->use_quick != 2 && !tab->first_inner && !ordered_set) tab->use_quick != 2 && !tab->first_inner && !ordered_set)
{ {
@ -6668,6 +6683,9 @@ make_join_readinfo(JOIN *join, ulonglong options)
} }
} }
break; break;
case JT_FT:
case JT_SYSTEM:
break;
default: default:
DBUG_PRINT("error",("Table type %d found",tab->type)); /* purecov: deadcode */ DBUG_PRINT("error",("Table type %d found",tab->type)); /* purecov: deadcode */
break; /* purecov: deadcode */ break; /* purecov: deadcode */
@ -7819,12 +7837,12 @@ static COND *build_equal_items_for_cond(THD *thd, COND *cond,
{ {
item_equal->fix_length_and_dec(); item_equal->fix_length_and_dec();
item_equal->update_used_tables(); item_equal->update_used_tables();
set_if_bigger(thd->lex->current_select->max_equal_elems,
item_equal->members());
return item_equal;
} }
else
item_equal= (Item_equal *) eq_list.pop(); return eq_list.pop();
set_if_bigger(thd->lex->current_select->max_equal_elems,
item_equal->members());
return item_equal;
} }
else else
{ {
@ -13189,6 +13207,8 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
if (create_ref_for_key(tab->join, tab, keyuse, if (create_ref_for_key(tab->join, tab, keyuse,
tab->join->const_table_map)) tab->join->const_table_map))
DBUG_RETURN(0); DBUG_RETURN(0);
pick_table_access_method(tab);
} }
else else
{ {

View File

@ -475,8 +475,7 @@ static void _ftb_init_index_search(FT_INFO *ftb)
int i; int i;
FTB_WORD *ftbw; FTB_WORD *ftbw;
if ((ftb->state != READY && ftb->state !=INDEX_DONE) || if (ftb->state == UNINITIALIZED || ftb->keynr == NO_SUCH_KEY)
ftb->keynr == NO_SUCH_KEY)
return; return;
ftb->state=INDEX_SEARCH; ftb->state=INDEX_SEARCH;