Manual merge of mysql-5.1-bugteam to mysql-trunk-merge.
Conflicts: Text conflict in mysql-test/r/grant.result Text conflict in mysql-test/t/grant.test Text conflict in mysys/mf_loadpath.c Text conflict in sql/slave.cc Text conflict in sql/sql_priv.h
This commit is contained in:
commit
ad43230e3b
@ -1437,6 +1437,22 @@ SHOW GRANTS FOR mysqltest_1;
|
|||||||
Grants for mysqltest_1@%
|
Grants for mysqltest_1@%
|
||||||
GRANT ALL PRIVILEGES ON *.* TO 'mysqltest_1'@'%'
|
GRANT ALL PRIVILEGES ON *.* TO 'mysqltest_1'@'%'
|
||||||
DROP USER mysqltest_1;
|
DROP USER mysqltest_1;
|
||||||
|
CREATE DATABASE db1;
|
||||||
|
CREATE DATABASE db2;
|
||||||
|
GRANT SELECT ON db1.* to 'testbug'@localhost;
|
||||||
|
USE db2;
|
||||||
|
CREATE TABLE t1 (a INT);
|
||||||
|
USE test;
|
||||||
|
SELECT * FROM `../db2/tb2`;
|
||||||
|
ERROR 42S02: Table 'db1.../db2/tb2' doesn't exist
|
||||||
|
SELECT * FROM `../db2`.tb2;
|
||||||
|
ERROR 42000: SELECT command denied to user 'testbug'@'localhost' for table 'tb2'
|
||||||
|
SELECT * FROM `#mysql50#/../db2/tb2`;
|
||||||
|
ERROR 42S02: Table 'db1.#mysql50#/../db2/tb2' doesn't exist
|
||||||
|
DROP USER 'testbug'@localhost;
|
||||||
|
DROP TABLE db2.t1;
|
||||||
|
DROP DATABASE db1;
|
||||||
|
DROP DATABASE db2;
|
||||||
#########################################################################
|
#########################################################################
|
||||||
#
|
#
|
||||||
# Bug#38347: ALTER ROUTINE privilege allows SHOW CREATE TABLE.
|
# Bug#38347: ALTER ROUTINE privilege allows SHOW CREATE TABLE.
|
||||||
|
@ -2383,6 +2383,36 @@ SELECT SECOND(c)-@bug47453 FROM t1 JOIN t2 ON d=a;
|
|||||||
SECOND(c)-@bug47453
|
SECOND(c)-@bug47453
|
||||||
0
|
0
|
||||||
DROP TABLE t1, t2;
|
DROP TABLE t1, t2;
|
||||||
|
#
|
||||||
|
# Bug #53334: wrong result for outer join with impossible ON condition
|
||||||
|
# (see the same test case for MyISAM in join.test)
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (id INT PRIMARY KEY);
|
||||||
|
CREATE TABLE t2 (id INT);
|
||||||
|
INSERT INTO t1 VALUES (75);
|
||||||
|
INSERT INTO t1 VALUES (79);
|
||||||
|
INSERT INTO t1 VALUES (78);
|
||||||
|
INSERT INTO t1 VALUES (77);
|
||||||
|
REPLACE INTO t1 VALUES (76);
|
||||||
|
REPLACE INTO t1 VALUES (76);
|
||||||
|
INSERT INTO t1 VALUES (104);
|
||||||
|
INSERT INTO t1 VALUES (103);
|
||||||
|
INSERT INTO t1 VALUES (102);
|
||||||
|
INSERT INTO t1 VALUES (101);
|
||||||
|
INSERT INTO t1 VALUES (105);
|
||||||
|
INSERT INTO t1 VALUES (106);
|
||||||
|
INSERT INTO t1 VALUES (107);
|
||||||
|
INSERT INTO t2 VALUES (107),(75),(1000);
|
||||||
|
SELECT t1.id,t2.id FROM t2 LEFT JOIN t1 ON t1.id>=74 AND t1.id<=0
|
||||||
|
WHERE t2.id=75 AND t1.id IS NULL;
|
||||||
|
id id
|
||||||
|
NULL 75
|
||||||
|
EXPLAIN SELECT t1.id,t2.id FROM t2 LEFT JOIN t1 ON t1.id>=74 AND t1.id<=0
|
||||||
|
WHERE t2.id=75 AND t1.id IS NULL;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 const PRIMARY NULL NULL NULL 1 Impossible ON condition
|
||||||
|
1 SIMPLE t2 ALL NULL NULL NULL NULL 3 Using where
|
||||||
|
DROP TABLE t1,t2;
|
||||||
End of 5.1 tests
|
End of 5.1 tests
|
||||||
#
|
#
|
||||||
# Test for bug #39932 "create table fails if column for FK is in different
|
# Test for bug #39932 "create table fails if column for FK is in different
|
||||||
|
@ -1312,4 +1312,34 @@ WHERE (COALESCE(t1.f1, t2.f1), f3) IN ((1, 3), (2, 2));
|
|||||||
f1 f2 f3 f1 f2
|
f1 f2 f3 f1 f2
|
||||||
1 NULL 3 NULL NULL
|
1 NULL 3 NULL NULL
|
||||||
DROP TABLE t1, t2;
|
DROP TABLE t1, t2;
|
||||||
|
#
|
||||||
|
# Bug#52357: Assertion failed: join->best_read in greedy_search
|
||||||
|
# optimizer_search_depth=0
|
||||||
|
#
|
||||||
|
CREATE TABLE t1( a INT );
|
||||||
|
INSERT INTO t1 VALUES (1),(2);
|
||||||
|
SET optimizer_search_depth = 0;
|
||||||
|
# Should not core dump on query preparation
|
||||||
|
EXPLAIN
|
||||||
|
SELECT 1
|
||||||
|
FROM t1 tt3 LEFT OUTER JOIN t1 tt4 ON 1
|
||||||
|
LEFT OUTER JOIN t1 tt5 ON 1
|
||||||
|
LEFT OUTER JOIN t1 tt6 ON 1
|
||||||
|
LEFT OUTER JOIN t1 tt7 ON 1
|
||||||
|
LEFT OUTER JOIN t1 tt8 ON 1
|
||||||
|
RIGHT OUTER JOIN t1 tt2 ON 1
|
||||||
|
RIGHT OUTER JOIN t1 tt1 ON 1
|
||||||
|
STRAIGHT_JOIN t1 tt9 ON 1;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE tt1 ALL NULL NULL NULL NULL 2
|
||||||
|
1 SIMPLE tt2 ALL NULL NULL NULL NULL 2
|
||||||
|
1 SIMPLE tt3 ALL NULL NULL NULL NULL 2
|
||||||
|
1 SIMPLE tt4 ALL NULL NULL NULL NULL 2
|
||||||
|
1 SIMPLE tt5 ALL NULL NULL NULL NULL 2
|
||||||
|
1 SIMPLE tt6 ALL NULL NULL NULL NULL 2
|
||||||
|
1 SIMPLE tt7 ALL NULL NULL NULL NULL 2
|
||||||
|
1 SIMPLE tt8 ALL NULL NULL NULL NULL 2
|
||||||
|
1 SIMPLE tt9 ALL NULL NULL NULL NULL 2 Using join buffer
|
||||||
|
SET optimizer_search_depth = DEFAULT;
|
||||||
|
DROP TABLE t1;
|
||||||
End of 5.1 tests
|
End of 5.1 tests
|
||||||
|
@ -4561,5 +4561,20 @@ a b c
|
|||||||
SET NAMES default;
|
SET NAMES default;
|
||||||
DROP TABLE t1, t2;
|
DROP TABLE t1, t2;
|
||||||
#
|
#
|
||||||
|
# Bug #53088: mysqldump with -T & --default-character-set set
|
||||||
|
# truncates text/blob to 766 chars
|
||||||
|
#
|
||||||
|
# Also see outfile_loaddata.test
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (a BLOB) CHARSET latin1;
|
||||||
|
CREATE TABLE t2 LIKE t1;
|
||||||
|
INSERT INTO t1 VALUES (REPEAT('.', 800));
|
||||||
|
LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/t1.txt' INTO TABLE t2 CHARACTER SET latin1;
|
||||||
|
# should be 800
|
||||||
|
SELECT LENGTH(a) FROM t2;
|
||||||
|
LENGTH(a)
|
||||||
|
800
|
||||||
|
DROP TABLE t1, t2;
|
||||||
|
#
|
||||||
# End of 5.1 tests
|
# End of 5.1 tests
|
||||||
#
|
#
|
||||||
|
@ -239,4 +239,24 @@ a b c
|
|||||||
2 NULL NULL
|
2 NULL NULL
|
||||||
SET NAMES default;
|
SET NAMES default;
|
||||||
DROP TABLE t1, t2;
|
DROP TABLE t1, t2;
|
||||||
|
#
|
||||||
|
# Bug #53088: mysqldump with -T & --default-character-set set
|
||||||
|
# truncates text/blob to 766 chars
|
||||||
|
#
|
||||||
|
# Also see mysqldump.test
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (a BLOB) CHARSET latin1;
|
||||||
|
CREATE TABLE t2 LIKE t1;
|
||||||
|
INSERT INTO t1 VALUES (REPEAT('.', 800));
|
||||||
|
SELECT * INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/bug53088.txt' CHARACTER SET latin1 FROM t1;
|
||||||
|
# should be greater than 800
|
||||||
|
SELECT LENGTH(LOAD_FILE('MYSQLTEST_VARDIR/tmp/bug53088.txt'));
|
||||||
|
LENGTH(LOAD_FILE('MYSQLTEST_VARDIR/tmp/bug53088.txt'))
|
||||||
|
801
|
||||||
|
LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/bug53088.txt' INTO TABLE t2;
|
||||||
|
# should be 800
|
||||||
|
SELECT LENGTH(a) FROM t2;
|
||||||
|
LENGTH(a)
|
||||||
|
800
|
||||||
|
DROP TABLE t1, t2;
|
||||||
# End of 5.1 tests.
|
# End of 5.1 tests.
|
||||||
|
@ -2142,8 +2142,6 @@ CREATE TRIGGER trg1 BEFORE INSERT ON t2 FOR EACH ROW INSERT/*!INTO*/t1 VALUES (1
|
|||||||
# Used to crash
|
# Used to crash
|
||||||
SHOW TRIGGERS IN db1;
|
SHOW TRIGGERS IN db1;
|
||||||
Trigger Event Table Statement Timing Created sql_mode Definer character_set_client collation_connection Database Collation
|
Trigger Event Table Statement Timing Created sql_mode Definer character_set_client collation_connection Database Collation
|
||||||
Warnings:
|
|
||||||
Warning 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'VALUES (1)' at line 1
|
|
||||||
INSERT INTO t2 VALUES (1);
|
INSERT INTO t2 VALUES (1);
|
||||||
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'VALUES (1)' at line 1
|
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'VALUES (1)' at line 1
|
||||||
SELECT * FROM t1;
|
SELECT * FROM t1;
|
||||||
|
@ -50,22 +50,22 @@ The following suites are included:
|
|||||||
|
|
||||||
Known Issues
|
Known Issues
|
||||||
------------
|
------------
|
||||||
1) The 'funcs' and 'iuds' suites currently runs only against MySQL 5.1 server.
|
1) The folowing tests in the 'iuds' suite:
|
||||||
Running them against MySQL 5.5 will generate errors.
|
|
||||||
|
|
||||||
2) The folowing tests in the 'iuds' suite:
|
|
||||||
- delete_decimal
|
- delete_decimal
|
||||||
- insert_decimal
|
- insert_decimal
|
||||||
- update_decimal
|
- update_decimal
|
||||||
will return a 'Warning 1264 - Out of range value...' warning if run in a 32-bit environment.
|
will return a 'Warning 1264 - Out of range value...' warning if run in a 32-bit environment.
|
||||||
Add the '--force' option to prevent the test run from aborting.
|
Add the '--force' option to prevent the test run from aborting.
|
||||||
|
|
||||||
3) The following tests in the 'funcs' suite will fail when run against the innodb_plugin:
|
2) The following tests in the 'funcs' suite will fail when run against the innodb_plugin:
|
||||||
- crash_manycolumns_string (bug 50495)
|
- crash_manycolumns_string (bug 50495)
|
||||||
- ix_unique_lob (bug 52056, masked by an 'Out of memory error' on some 32-bit platforms)
|
- ix_unique_lob (bug 52056, masked by an 'Out of memory error' on some 32-bit platforms)
|
||||||
- ix_unique_string_length (bug 52056, masked by an 'Out of memory error' on some 32-bit platforms)
|
- ix_unique_string_length (bug 52056, masked by an 'Out of memory error' on some 32-bit platforms)
|
||||||
Add the '--force' option to prevent the test run from aborting.
|
Add the '--force' option to prevent the test run from aborting.
|
||||||
|
|
||||||
4) Some of the rpl_xxx tests in the 'funcs' suite require a secific binlog_forat setting and will be
|
3) Some of the rpl_xxx tests in the 'funcs' suite require a secific binlog_forat setting and will be
|
||||||
skipped otherwise.
|
skipped otherwise.
|
||||||
|
|
||||||
|
4) Some of the rpl_xxx tests in the 'funcs' suite will report a 'Statement unsafe for replication' warning
|
||||||
|
when run againsr a server configured to use statement based replication.
|
||||||
|
|
||||||
|
@ -1554,6 +1554,30 @@ connection default;
|
|||||||
disconnect conn1;
|
disconnect conn1;
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug #53371: COM_FIELD_LIST can be abused to bypass table level grants.
|
||||||
|
#
|
||||||
|
|
||||||
|
CREATE DATABASE db1;
|
||||||
|
CREATE DATABASE db2;
|
||||||
|
GRANT SELECT ON db1.* to 'testbug'@localhost;
|
||||||
|
USE db2;
|
||||||
|
CREATE TABLE t1 (a INT);
|
||||||
|
USE test;
|
||||||
|
connect (con1,localhost,testbug,,db1);
|
||||||
|
--error ER_NO_SUCH_TABLE
|
||||||
|
SELECT * FROM `../db2/tb2`;
|
||||||
|
--error ER_TABLEACCESS_DENIED_ERROR
|
||||||
|
SELECT * FROM `../db2`.tb2;
|
||||||
|
--error ER_NO_SUCH_TABLE
|
||||||
|
SELECT * FROM `#mysql50#/../db2/tb2`;
|
||||||
|
connection default;
|
||||||
|
disconnect con1;
|
||||||
|
DROP USER 'testbug'@localhost;
|
||||||
|
DROP TABLE db2.t1;
|
||||||
|
DROP DATABASE db1;
|
||||||
|
DROP DATABASE db2;
|
||||||
|
|
||||||
# Wait till we reached the initial number of concurrent sessions
|
# Wait till we reached the initial number of concurrent sessions
|
||||||
--source include/wait_until_count_sessions.inc
|
--source include/wait_until_count_sessions.inc
|
||||||
|
|
||||||
|
@ -618,6 +618,36 @@ SELECT SECOND(c)-@bug47453 FROM t1 JOIN t2 ON d=a;
|
|||||||
|
|
||||||
DROP TABLE t1, t2;
|
DROP TABLE t1, t2;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Bug #53334: wrong result for outer join with impossible ON condition
|
||||||
|
--echo # (see the same test case for MyISAM in join.test)
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
CREATE TABLE t1 (id INT PRIMARY KEY);
|
||||||
|
CREATE TABLE t2 (id INT);
|
||||||
|
|
||||||
|
INSERT INTO t1 VALUES (75);
|
||||||
|
INSERT INTO t1 VALUES (79);
|
||||||
|
INSERT INTO t1 VALUES (78);
|
||||||
|
INSERT INTO t1 VALUES (77);
|
||||||
|
REPLACE INTO t1 VALUES (76);
|
||||||
|
REPLACE INTO t1 VALUES (76);
|
||||||
|
INSERT INTO t1 VALUES (104);
|
||||||
|
INSERT INTO t1 VALUES (103);
|
||||||
|
INSERT INTO t1 VALUES (102);
|
||||||
|
INSERT INTO t1 VALUES (101);
|
||||||
|
INSERT INTO t1 VALUES (105);
|
||||||
|
INSERT INTO t1 VALUES (106);
|
||||||
|
INSERT INTO t1 VALUES (107);
|
||||||
|
|
||||||
|
INSERT INTO t2 VALUES (107),(75),(1000);
|
||||||
|
|
||||||
|
SELECT t1.id,t2.id FROM t2 LEFT JOIN t1 ON t1.id>=74 AND t1.id<=0
|
||||||
|
WHERE t2.id=75 AND t1.id IS NULL;
|
||||||
|
EXPLAIN SELECT t1.id,t2.id FROM t2 LEFT JOIN t1 ON t1.id>=74 AND t1.id<=0
|
||||||
|
WHERE t2.id=75 AND t1.id IS NULL;
|
||||||
|
|
||||||
|
DROP TABLE t1,t2;
|
||||||
|
|
||||||
--echo End of 5.1 tests
|
--echo End of 5.1 tests
|
||||||
|
|
||||||
|
@ -913,4 +913,27 @@ WHERE (COALESCE(t1.f1, t2.f1), f3) IN ((1, 3), (2, 2));
|
|||||||
|
|
||||||
DROP TABLE t1, t2;
|
DROP TABLE t1, t2;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Bug#52357: Assertion failed: join->best_read in greedy_search
|
||||||
|
--echo # optimizer_search_depth=0
|
||||||
|
--echo #
|
||||||
|
CREATE TABLE t1( a INT );
|
||||||
|
|
||||||
|
INSERT INTO t1 VALUES (1),(2);
|
||||||
|
SET optimizer_search_depth = 0;
|
||||||
|
|
||||||
|
--echo # Should not core dump on query preparation
|
||||||
|
EXPLAIN
|
||||||
|
SELECT 1
|
||||||
|
FROM t1 tt3 LEFT OUTER JOIN t1 tt4 ON 1
|
||||||
|
LEFT OUTER JOIN t1 tt5 ON 1
|
||||||
|
LEFT OUTER JOIN t1 tt6 ON 1
|
||||||
|
LEFT OUTER JOIN t1 tt7 ON 1
|
||||||
|
LEFT OUTER JOIN t1 tt8 ON 1
|
||||||
|
RIGHT OUTER JOIN t1 tt2 ON 1
|
||||||
|
RIGHT OUTER JOIN t1 tt1 ON 1
|
||||||
|
STRAIGHT_JOIN t1 tt9 ON 1;
|
||||||
|
|
||||||
|
SET optimizer_search_depth = DEFAULT;
|
||||||
|
DROP TABLE t1;
|
||||||
--echo End of 5.1 tests
|
--echo End of 5.1 tests
|
||||||
|
@ -2136,6 +2136,35 @@ SELECT * FROM t1 UNION SELECT * FROM t2 ORDER BY a, b, c;
|
|||||||
|
|
||||||
SET NAMES default;
|
SET NAMES default;
|
||||||
|
|
||||||
|
DROP TABLE t1, t2;
|
||||||
|
###########################################################################
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Bug #53088: mysqldump with -T & --default-character-set set
|
||||||
|
--echo # truncates text/blob to 766 chars
|
||||||
|
--echo #
|
||||||
|
--echo # Also see outfile_loaddata.test
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
CREATE TABLE t1 (a BLOB) CHARSET latin1;
|
||||||
|
CREATE TABLE t2 LIKE t1;
|
||||||
|
|
||||||
|
let $table= t1;
|
||||||
|
let $dir= $MYSQLTEST_VARDIR/tmp;
|
||||||
|
let $file= $dir/$table.txt;
|
||||||
|
let $length= 800;
|
||||||
|
|
||||||
|
--eval INSERT INTO t1 VALUES (REPEAT('.', $length))
|
||||||
|
|
||||||
|
--exec $MYSQL_DUMP --character-sets-dir=$CHARSETSDIR --default-character-set=latin1 --tab=$dir/ test $table
|
||||||
|
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
||||||
|
|
||||||
|
--eval LOAD DATA INFILE '$file' INTO TABLE t2 CHARACTER SET latin1
|
||||||
|
--remove_file $file
|
||||||
|
|
||||||
|
--echo # should be $length
|
||||||
|
SELECT LENGTH(a) FROM t2;
|
||||||
|
|
||||||
DROP TABLE t1, t2;
|
DROP TABLE t1, t2;
|
||||||
|
|
||||||
###########################################################################
|
###########################################################################
|
||||||
|
@ -251,6 +251,40 @@ SELECT * FROM t1 UNION SELECT * FROM t2 ORDER BY a, b, c;
|
|||||||
SET NAMES default;
|
SET NAMES default;
|
||||||
|
|
||||||
DROP TABLE t1, t2;
|
DROP TABLE t1, t2;
|
||||||
|
###########################################################################
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Bug #53088: mysqldump with -T & --default-character-set set
|
||||||
|
--echo # truncates text/blob to 766 chars
|
||||||
|
--echo #
|
||||||
|
--echo # Also see mysqldump.test
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
CREATE TABLE t1 (a BLOB) CHARSET latin1;
|
||||||
|
CREATE TABLE t2 LIKE t1;
|
||||||
|
|
||||||
|
let $file= '$MYSQLTEST_VARDIR/tmp/bug53088.txt';
|
||||||
|
let $length= 800;
|
||||||
|
|
||||||
|
--eval INSERT INTO t1 VALUES (REPEAT('.', $length))
|
||||||
|
|
||||||
|
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
||||||
|
--eval SELECT * INTO OUTFILE $file CHARACTER SET latin1 FROM t1
|
||||||
|
|
||||||
|
--echo # should be greater than $length
|
||||||
|
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
||||||
|
--eval SELECT LENGTH(LOAD_FILE($file))
|
||||||
|
|
||||||
|
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
||||||
|
--eval LOAD DATA INFILE $file INTO TABLE t2
|
||||||
|
|
||||||
|
--remove_file $MYSQLTEST_VARDIR/tmp/bug53088.txt
|
||||||
|
|
||||||
|
--echo # should be $length
|
||||||
|
SELECT LENGTH(a) FROM t2;
|
||||||
|
|
||||||
|
DROP TABLE t1, t2;
|
||||||
|
|
||||||
|
|
||||||
###########################################################################
|
###########################################################################
|
||||||
--echo # End of 5.1 tests.
|
--echo # End of 5.1 tests.
|
||||||
|
@ -34,7 +34,7 @@ char * my_load_path(char * to, const char *path,
|
|||||||
|
|
||||||
if ((path[0] == FN_HOMELIB && path[1] == FN_LIBCHAR) ||
|
if ((path[0] == FN_HOMELIB && path[1] == FN_LIBCHAR) ||
|
||||||
test_if_hard_path(path))
|
test_if_hard_path(path))
|
||||||
(void) strmov(buff,path);
|
(void) strnmov(buff, path, FN_REFLEN);
|
||||||
else if ((is_cur=(path[0] == FN_CURLIB && path[1] == FN_LIBCHAR)) ||
|
else if ((is_cur=(path[0] == FN_CURLIB && path[1] == FN_LIBCHAR)) ||
|
||||||
(is_prefix(path,FN_PARENTDIR)) ||
|
(is_prefix(path,FN_PARENTDIR)) ||
|
||||||
! own_path_prefix)
|
! own_path_prefix)
|
||||||
@ -42,13 +42,14 @@ char * my_load_path(char * to, const char *path,
|
|||||||
if (is_cur)
|
if (is_cur)
|
||||||
is_cur=2; /* Remove current dir */
|
is_cur=2; /* Remove current dir */
|
||||||
if (! my_getwd(buff,(uint) (FN_REFLEN-strlen(path)+is_cur),MYF(0)))
|
if (! my_getwd(buff,(uint) (FN_REFLEN-strlen(path)+is_cur),MYF(0)))
|
||||||
(void) strcat(buff,path+is_cur);
|
(void) strncat(buff, path+is_cur, FN_REFLEN);
|
||||||
else
|
else
|
||||||
(void) strmov(buff,path); /* Return org file name */
|
(void) strnmov(buff, path, FN_REFLEN); /* Return org file name */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
(void) strxmov(buff,own_path_prefix,path,NullS);
|
(void) strxnmov(buff, FN_REFLEN, own_path_prefix, path, NullS);
|
||||||
strmov(to,buff);
|
strnmov(to, buff, FN_REFLEN);
|
||||||
|
to[FN_REFLEN-1]= '\0';
|
||||||
DBUG_PRINT("exit",("to: %s",to));
|
DBUG_PRINT("exit",("to: %s",to));
|
||||||
DBUG_RETURN(to);
|
DBUG_RETURN(to);
|
||||||
} /* my_load_path */
|
} /* my_load_path */
|
||||||
|
@ -50,11 +50,16 @@ int my_getwd(char * buf, size_t size, myf MyFlags)
|
|||||||
DBUG_PRINT("my",("buf: 0x%lx size: %u MyFlags %d",
|
DBUG_PRINT("my",("buf: 0x%lx size: %u MyFlags %d",
|
||||||
(long) buf, (uint) size, MyFlags));
|
(long) buf, (uint) size, MyFlags));
|
||||||
|
|
||||||
|
if (size < 1)
|
||||||
|
return(-1);
|
||||||
|
|
||||||
if (curr_dir[0]) /* Current pos is saved here */
|
if (curr_dir[0]) /* Current pos is saved here */
|
||||||
(void) strmake(buf,&curr_dir[0],size-1);
|
(void) strmake(buf,&curr_dir[0],size-1);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#if defined(HAVE_GETCWD)
|
#if defined(HAVE_GETCWD)
|
||||||
|
if (size < 2)
|
||||||
|
return(-1);
|
||||||
if (!getcwd(buf,(uint) (size-2)) && MyFlags & MY_WME)
|
if (!getcwd(buf,(uint) (size-2)) && MyFlags & MY_WME)
|
||||||
{
|
{
|
||||||
my_errno=errno;
|
my_errno=errno;
|
||||||
@ -68,6 +73,8 @@ int my_getwd(char * buf, size_t size, myf MyFlags)
|
|||||||
strmake(buf,pathname,size-1);
|
strmake(buf,pathname,size-1);
|
||||||
}
|
}
|
||||||
#elif defined(VMS)
|
#elif defined(VMS)
|
||||||
|
if (size < 2)
|
||||||
|
return(-1);
|
||||||
if (!getcwd(buf,size-2,1) && MyFlags & MY_WME)
|
if (!getcwd(buf,size-2,1) && MyFlags & MY_WME)
|
||||||
{
|
{
|
||||||
my_errno=errno;
|
my_errno=errno;
|
||||||
|
12
sql/item.cc
12
sql/item.cc
@ -5640,13 +5640,25 @@ inline uint char_val(char X)
|
|||||||
X-'a'+10);
|
X-'a'+10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Item_hex_string::Item_hex_string()
|
||||||
|
{
|
||||||
|
hex_string_init("", 0);
|
||||||
|
}
|
||||||
|
|
||||||
Item_hex_string::Item_hex_string(const char *str, uint str_length)
|
Item_hex_string::Item_hex_string(const char *str, uint str_length)
|
||||||
|
{
|
||||||
|
hex_string_init(str, str_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Item_hex_string::hex_string_init(const char *str, uint str_length)
|
||||||
{
|
{
|
||||||
max_length=(str_length+1)/2;
|
max_length=(str_length+1)/2;
|
||||||
char *ptr=(char*) sql_alloc(max_length+1);
|
char *ptr=(char*) sql_alloc(max_length+1);
|
||||||
if (!ptr)
|
if (!ptr)
|
||||||
|
{
|
||||||
|
str_value.set("", 0, &my_charset_bin);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
str_value.set(ptr,max_length,&my_charset_bin);
|
str_value.set(ptr,max_length,&my_charset_bin);
|
||||||
char *end=ptr+max_length;
|
char *end=ptr+max_length;
|
||||||
if (max_length*2 != str_length)
|
if (max_length*2 != str_length)
|
||||||
|
@ -2302,7 +2302,7 @@ public:
|
|||||||
class Item_hex_string: public Item_basic_constant
|
class Item_hex_string: public Item_basic_constant
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Item_hex_string() {}
|
Item_hex_string();
|
||||||
Item_hex_string(const char *str,uint str_length);
|
Item_hex_string(const char *str,uint str_length);
|
||||||
enum Type type() const { return VARBIN_ITEM; }
|
enum Type type() const { return VARBIN_ITEM; }
|
||||||
double val_real()
|
double val_real()
|
||||||
@ -2322,6 +2322,8 @@ public:
|
|||||||
bool eq(const Item *item, bool binary_cmp) const;
|
bool eq(const Item *item, bool binary_cmp) const;
|
||||||
virtual Item *safe_charset_converter(CHARSET_INFO *tocs);
|
virtual Item *safe_charset_converter(CHARSET_INFO *tocs);
|
||||||
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
|
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
|
||||||
|
private:
|
||||||
|
void hex_string_init(const char *str, uint str_length);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -7731,6 +7731,9 @@ bool is_secure_file_path(char *path)
|
|||||||
if (!opt_secure_file_priv)
|
if (!opt_secure_file_priv)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
|
if (strlen(path) >= FN_REFLEN)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
if (my_realpath(buff1, path, 0))
|
if (my_realpath(buff1, path, 0))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -7816,6 +7819,8 @@ static int fix_paths(void)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (strlen(opt_secure_file_priv) >= FN_REFLEN)
|
||||||
|
opt_secure_file_priv[FN_REFLEN-1]= '\0';
|
||||||
if (my_realpath(buff, opt_secure_file_priv, 0))
|
if (my_realpath(buff, opt_secure_file_priv, 0))
|
||||||
{
|
{
|
||||||
sql_print_warning("Failed to normalize the argument for --secure-file-priv.");
|
sql_print_warning("Failed to normalize the argument for --secure-file-priv.");
|
||||||
|
@ -1191,7 +1191,7 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type,
|
|||||||
part_elem->engine_type= default_engine_type;
|
part_elem->engine_type= default_engine_type;
|
||||||
}
|
}
|
||||||
if (check_table_name(part_elem->partition_name,
|
if (check_table_name(part_elem->partition_name,
|
||||||
strlen(part_elem->partition_name)))
|
strlen(part_elem->partition_name), FALSE))
|
||||||
{
|
{
|
||||||
my_error(ER_WRONG_PARTITION_NAME, MYF(0));
|
my_error(ER_WRONG_PARTITION_NAME, MYF(0));
|
||||||
goto end;
|
goto end;
|
||||||
@ -1209,7 +1209,7 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type,
|
|||||||
{
|
{
|
||||||
sub_elem= sub_it++;
|
sub_elem= sub_it++;
|
||||||
if (check_table_name(sub_elem->partition_name,
|
if (check_table_name(sub_elem->partition_name,
|
||||||
strlen(sub_elem->partition_name)))
|
strlen(sub_elem->partition_name), FALSE))
|
||||||
{
|
{
|
||||||
my_error(ER_WRONG_PARTITION_NAME, MYF(0));
|
my_error(ER_WRONG_PARTITION_NAME, MYF(0));
|
||||||
goto end;
|
goto end;
|
||||||
|
31
sql/slave.cc
31
sql/slave.cc
@ -3124,6 +3124,11 @@ pthread_handler_t handle_slave_sql(void *arg)
|
|||||||
{
|
{
|
||||||
THD *thd; /* needs to be first for thread_stack */
|
THD *thd; /* needs to be first for thread_stack */
|
||||||
char llbuff[22],llbuff1[22];
|
char llbuff[22],llbuff1[22];
|
||||||
|
char saved_log_name[FN_REFLEN];
|
||||||
|
char saved_master_log_name[FN_REFLEN];
|
||||||
|
my_off_t saved_log_pos;
|
||||||
|
my_off_t saved_master_log_pos;
|
||||||
|
my_off_t saved_skip= 0;
|
||||||
|
|
||||||
Relay_log_info* rli = &((Master_info*)arg)->rli;
|
Relay_log_info* rli = &((Master_info*)arg)->rli;
|
||||||
const char *errmsg;
|
const char *errmsg;
|
||||||
@ -3269,6 +3274,17 @@ log '%s' at position %s, relay log '%s' position: %s", RPL_LOG_NAME,
|
|||||||
do not want to wait for next event in this case.
|
do not want to wait for next event in this case.
|
||||||
*/
|
*/
|
||||||
mysql_mutex_lock(&rli->data_lock);
|
mysql_mutex_lock(&rli->data_lock);
|
||||||
|
if (rli->slave_skip_counter)
|
||||||
|
{
|
||||||
|
char *pos;
|
||||||
|
pos= strmake(saved_log_name, rli->group_relay_log_name, FN_REFLEN - 1);
|
||||||
|
pos= '\0';
|
||||||
|
pos= strmake(saved_master_log_name, rli->group_master_log_name, FN_REFLEN - 1);
|
||||||
|
pos= '\0';
|
||||||
|
saved_log_pos= rli->group_relay_log_pos;
|
||||||
|
saved_master_log_pos= rli->group_master_log_pos;
|
||||||
|
saved_skip= rli->slave_skip_counter;
|
||||||
|
}
|
||||||
if (rli->until_condition != Relay_log_info::UNTIL_NONE &&
|
if (rli->until_condition != Relay_log_info::UNTIL_NONE &&
|
||||||
rli->is_until_satisfied(thd, NULL))
|
rli->is_until_satisfied(thd, NULL))
|
||||||
{
|
{
|
||||||
@ -3287,6 +3303,21 @@ log '%s' at position %s, relay log '%s' position: %s", RPL_LOG_NAME,
|
|||||||
thd_proc_info(thd, "Reading event from the relay log");
|
thd_proc_info(thd, "Reading event from the relay log");
|
||||||
DBUG_ASSERT(rli->sql_thd == thd);
|
DBUG_ASSERT(rli->sql_thd == thd);
|
||||||
THD_CHECK_SENTRY(thd);
|
THD_CHECK_SENTRY(thd);
|
||||||
|
|
||||||
|
if (saved_skip && rli->slave_skip_counter == 0)
|
||||||
|
{
|
||||||
|
sql_print_information("'SQL_SLAVE_SKIP_COUNTER=%ld' executed at "
|
||||||
|
"relay_log_file='%s', relay_log_pos='%ld', master_log_name='%s', "
|
||||||
|
"master_log_pos='%ld' and new position at "
|
||||||
|
"relay_log_file='%s', relay_log_pos='%ld', master_log_name='%s', "
|
||||||
|
"master_log_pos='%ld' ",
|
||||||
|
(ulong) saved_skip, saved_log_name, (ulong) saved_log_pos,
|
||||||
|
saved_master_log_name, (ulong) saved_master_log_pos,
|
||||||
|
rli->group_relay_log_name, (ulong) rli->group_relay_log_pos,
|
||||||
|
rli->group_master_log_name, (ulong) rli->group_master_log_pos);
|
||||||
|
saved_skip= 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (exec_relay_log_event(thd,rli))
|
if (exec_relay_log_event(thd,rli))
|
||||||
{
|
{
|
||||||
DBUG_PRINT("info", ("exec_relay_log_event() failed"));
|
DBUG_PRINT("info", ("exec_relay_log_event() failed"));
|
||||||
|
@ -2086,9 +2086,21 @@ bool select_export::send_data(List<Item> &items)
|
|||||||
const char *from_end_pos;
|
const char *from_end_pos;
|
||||||
const char *error_pos;
|
const char *error_pos;
|
||||||
uint32 bytes;
|
uint32 bytes;
|
||||||
bytes= well_formed_copy_nchars(write_cs, cvt_buff, sizeof(cvt_buff),
|
uint64 estimated_bytes=
|
||||||
|
((uint64) res->length() / res->charset()->mbminlen + 1) *
|
||||||
|
write_cs->mbmaxlen + 1;
|
||||||
|
set_if_smaller(estimated_bytes, UINT_MAX32);
|
||||||
|
if (cvt_str.realloc((uint32) estimated_bytes))
|
||||||
|
{
|
||||||
|
my_error(ER_OUTOFMEMORY, MYF(0), (uint32) estimated_bytes);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes= well_formed_copy_nchars(write_cs, (char *) cvt_str.ptr(),
|
||||||
|
cvt_str.alloced_length(),
|
||||||
res->charset(), res->ptr(), res->length(),
|
res->charset(), res->ptr(), res->length(),
|
||||||
sizeof(cvt_buff),
|
UINT_MAX32, // copy all input chars,
|
||||||
|
// i.e. ignore nchars parameter
|
||||||
&well_formed_error_pos,
|
&well_formed_error_pos,
|
||||||
&cannot_convert_error_pos,
|
&cannot_convert_error_pos,
|
||||||
&from_end_pos);
|
&from_end_pos);
|
||||||
@ -2106,6 +2118,15 @@ bool select_export::send_data(List<Item> &items)
|
|||||||
"string", printable_buff,
|
"string", printable_buff,
|
||||||
item->name, row_count);
|
item->name, row_count);
|
||||||
}
|
}
|
||||||
|
else if (from_end_pos < res->ptr() + res->length())
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
result is longer than UINT_MAX32 and doesn't fit into String
|
||||||
|
*/
|
||||||
|
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||||
|
WARN_DATA_TRUNCATED, ER(WARN_DATA_TRUNCATED),
|
||||||
|
item->full_name(), row_count);
|
||||||
|
}
|
||||||
cvt_str.length(bytes);
|
cvt_str.length(bytes);
|
||||||
res= &cvt_str;
|
res= &cvt_str;
|
||||||
}
|
}
|
||||||
|
@ -1170,6 +1170,13 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
|||||||
}
|
}
|
||||||
thd->convert_string(&conv_name, system_charset_info,
|
thd->convert_string(&conv_name, system_charset_info,
|
||||||
packet, arg_length, thd->charset());
|
packet, arg_length, thd->charset());
|
||||||
|
if (check_table_name(conv_name.str, conv_name.length, FALSE))
|
||||||
|
{
|
||||||
|
/* this is OK due to convert_string() null-terminating the string */
|
||||||
|
my_error(ER_WRONG_TABLE_NAME, MYF(0), conv_name.str);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
table_list.alias= table_list.table_name= conv_name.str;
|
table_list.alias= table_list.table_name= conv_name.str;
|
||||||
packet= arg_end + 1;
|
packet= arg_end + 1;
|
||||||
|
|
||||||
@ -6063,7 +6070,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
|
|||||||
DBUG_RETURN(0); // End of memory
|
DBUG_RETURN(0); // End of memory
|
||||||
alias_str= alias ? alias->str : table->table.str;
|
alias_str= alias ? alias->str : table->table.str;
|
||||||
if (!test(table_options & TL_OPTION_ALIAS) &&
|
if (!test(table_options & TL_OPTION_ALIAS) &&
|
||||||
check_table_name(table->table.str, table->table.length))
|
check_table_name(table->table.str, table->table.length, FALSE))
|
||||||
{
|
{
|
||||||
my_error(ER_WRONG_TABLE_NAME, MYF(0), table->table.str);
|
my_error(ER_WRONG_TABLE_NAME, MYF(0), table->table.str);
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
|
@ -1347,6 +1347,10 @@ bool change_master(THD* thd, Master_info* mi)
|
|||||||
const char* errmsg= 0;
|
const char* errmsg= 0;
|
||||||
bool need_relay_log_purge= 1;
|
bool need_relay_log_purge= 1;
|
||||||
bool ret= FALSE;
|
bool ret= FALSE;
|
||||||
|
char saved_host[HOSTNAME_LENGTH + 1];
|
||||||
|
uint saved_port;
|
||||||
|
char saved_log_name[FN_REFLEN];
|
||||||
|
my_off_t saved_log_pos;
|
||||||
DBUG_ENTER("change_master");
|
DBUG_ENTER("change_master");
|
||||||
|
|
||||||
lock_slave_threads(mi);
|
lock_slave_threads(mi);
|
||||||
@ -1388,6 +1392,17 @@ bool change_master(THD* thd, Master_info* mi)
|
|||||||
could possibly modify the data structures from running
|
could possibly modify the data structures from running
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Before processing the command, save the previous state.
|
||||||
|
*/
|
||||||
|
char *pos;
|
||||||
|
pos= strmake(saved_host, mi->host, HOSTNAME_LENGTH);
|
||||||
|
pos= '\0';
|
||||||
|
saved_port= mi->port;
|
||||||
|
pos= strmake(saved_log_name, mi->master_log_name, FN_REFLEN - 1);
|
||||||
|
pos= '\0';
|
||||||
|
saved_log_pos= mi->master_log_pos;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
If the user specified host or port without binlog or position,
|
If the user specified host or port without binlog or position,
|
||||||
reset binlog's name to FIRST and position to 4.
|
reset binlog's name to FIRST and position to 4.
|
||||||
@ -1586,6 +1601,15 @@ bool change_master(THD* thd, Master_info* mi)
|
|||||||
/* Clear the errors, for a clean start */
|
/* Clear the errors, for a clean start */
|
||||||
mi->rli.clear_error();
|
mi->rli.clear_error();
|
||||||
mi->rli.clear_until_condition();
|
mi->rli.clear_until_condition();
|
||||||
|
|
||||||
|
sql_print_information("'CHANGE MASTER TO executed'. "
|
||||||
|
"Previous state master_host='%s', master_port='%u', master_log_file='%s', "
|
||||||
|
"master_log_pos='%ld'. "
|
||||||
|
"New state master_host='%s', master_port='%u', master_log_file='%s', "
|
||||||
|
"master_log_pos='%ld'.", saved_host, saved_port, saved_log_name,
|
||||||
|
(ulong) saved_log_pos, mi->host, mi->port, mi->master_log_name,
|
||||||
|
(ulong) mi->master_log_pos);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
If we don't write new coordinates to disk now, then old will remain in
|
If we don't write new coordinates to disk now, then old will remain in
|
||||||
relay-log.info until START SLAVE is issued; but if mysqld is shutdown
|
relay-log.info until START SLAVE is issued; but if mysqld is shutdown
|
||||||
|
@ -3005,8 +3005,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables_arg, COND *conds,
|
|||||||
s->quick=select->quick;
|
s->quick=select->quick;
|
||||||
s->needed_reg=select->needed_reg;
|
s->needed_reg=select->needed_reg;
|
||||||
select->quick=0;
|
select->quick=0;
|
||||||
if (records == 0 && s->table->reginfo.impossible_range &&
|
if (records == 0 && s->table->reginfo.impossible_range)
|
||||||
(s->table->file->ha_table_flags() & HA_STATS_RECORDS_IS_EXACT))
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Impossible WHERE or ON expression
|
Impossible WHERE or ON expression
|
||||||
@ -9209,6 +9208,46 @@ static bool check_interleaving_with_nj(JOIN_TAB *next_tab)
|
|||||||
/**
|
/**
|
||||||
Nested joins perspective: Remove the last table from the join order.
|
Nested joins perspective: Remove the last table from the join order.
|
||||||
|
|
||||||
|
The algorithm is the reciprocal of check_interleaving_with_nj(), hence
|
||||||
|
parent join nest nodes are updated only when the last table in its child
|
||||||
|
node is removed. The ASCII graphic below will clarify.
|
||||||
|
|
||||||
|
%A table nesting such as <tt> t1 x [ ( t2 x t3 ) x ( t4 x t5 ) ] </tt>is
|
||||||
|
represented by the below join nest tree.
|
||||||
|
|
||||||
|
@verbatim
|
||||||
|
NJ1
|
||||||
|
_/ / \
|
||||||
|
_/ / NJ2
|
||||||
|
_/ / / \
|
||||||
|
/ / / \
|
||||||
|
t1 x [ (t2 x t3) x (t4 x t5) ]
|
||||||
|
@endverbatim
|
||||||
|
|
||||||
|
At the point in time when check_interleaving_with_nj() adds the table t5 to
|
||||||
|
the query execution plan, QEP, it also directs the node named NJ2 to mark
|
||||||
|
the table as covered. NJ2 does so by incrementing its @c counter
|
||||||
|
member. Since all of NJ2's tables are now covered by the QEP, the algorithm
|
||||||
|
proceeds up the tree to NJ1, incrementing its counter as well. All join
|
||||||
|
nests are now completely covered by the QEP.
|
||||||
|
|
||||||
|
restore_prev_nj_state() does the above in reverse. As seen above, the node
|
||||||
|
NJ1 contains the nodes t2, t3, and NJ2. Its counter being equal to 3 means
|
||||||
|
that the plan covers t2, t3, and NJ2, @e and that the sub-plan (t4 x t5)
|
||||||
|
completely covers NJ2. The removal of t5 from the partial plan will first
|
||||||
|
decrement NJ2's counter to 1. It will then detect that NJ2 went from being
|
||||||
|
completely to partially covered, and hence the algorithm must continue
|
||||||
|
upwards to NJ1 and decrement its counter to 2. %A subsequent removal of t4
|
||||||
|
will however not influence NJ1 since it did not un-cover the last table in
|
||||||
|
NJ2.
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
restore_prev_nj_state()
|
||||||
|
last join table to remove, it is assumed to be the last in current
|
||||||
|
partial join order.
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
|
||||||
Remove the last table from the partial join order and update the nested
|
Remove the last table from the partial join order and update the nested
|
||||||
joins counters and join->cur_embedding_map. It is ok to call this
|
joins counters and join->cur_embedding_map. It is ok to call this
|
||||||
function for the first table in join order (for which
|
function for the first table in join order (for which
|
||||||
@ -9222,19 +9261,20 @@ static void restore_prev_nj_state(JOIN_TAB *last)
|
|||||||
{
|
{
|
||||||
TABLE_LIST *last_emb= last->table->pos_in_table_list->embedding;
|
TABLE_LIST *last_emb= last->table->pos_in_table_list->embedding;
|
||||||
JOIN *join= last->join;
|
JOIN *join= last->join;
|
||||||
while (last_emb)
|
for (;last_emb != NULL; last_emb= last_emb->embedding)
|
||||||
{
|
{
|
||||||
if (!(--last_emb->nested_join->counter))
|
NESTED_JOIN *nest= last_emb->nested_join;
|
||||||
join->cur_embedding_map&= ~last_emb->nested_join->nj_map;
|
DBUG_ASSERT(nest->counter > 0);
|
||||||
else if (last_emb->nested_join->join_list.elements-1 ==
|
|
||||||
last_emb->nested_join->counter)
|
bool was_fully_covered= nest->is_fully_covered();
|
||||||
{
|
|
||||||
join->cur_embedding_map|= last_emb->nested_join->nj_map;
|
if (--nest->counter == 0)
|
||||||
|
join->cur_embedding_map&= ~nest->nj_map;
|
||||||
|
|
||||||
|
if (!was_fully_covered)
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
else
|
join->cur_embedding_map|= nest->nj_map;
|
||||||
break;
|
|
||||||
last_emb= last_emb->embedding;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -469,7 +469,21 @@ uint tablename_to_filename(const char *from, char *to, uint to_length)
|
|||||||
DBUG_PRINT("enter", ("from '%s'", from));
|
DBUG_PRINT("enter", ("from '%s'", from));
|
||||||
|
|
||||||
if ((length= check_n_cut_mysql50_prefix(from, to, to_length)))
|
if ((length= check_n_cut_mysql50_prefix(from, to, to_length)))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Check if the name supplied is a valid mysql 5.0 name and
|
||||||
|
make the name a zero length string if it's not.
|
||||||
|
Note that just returning zero length is not enough :
|
||||||
|
a lot of places don't check the return value and expect
|
||||||
|
a zero terminated string.
|
||||||
|
*/
|
||||||
|
if (check_table_name(to, length, TRUE))
|
||||||
|
{
|
||||||
|
to[0]= 0;
|
||||||
|
length= 0;
|
||||||
|
}
|
||||||
DBUG_RETURN(length);
|
DBUG_RETURN(length);
|
||||||
|
}
|
||||||
length= strconvert(system_charset_info, from,
|
length= strconvert(system_charset_info, from,
|
||||||
&my_charset_filename, to, to_length, &errors);
|
&my_charset_filename, to, to_length, &errors);
|
||||||
if (check_if_legal_tablename(to) &&
|
if (check_if_legal_tablename(to) &&
|
||||||
|
@ -6670,7 +6670,7 @@ alter_list_item:
|
|||||||
{
|
{
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
}
|
}
|
||||||
if (check_table_name($3->table.str,$3->table.length) ||
|
if (check_table_name($3->table.str,$3->table.length, FALSE) ||
|
||||||
($3->db.str && check_db_name(&$3->db)))
|
($3->db.str && check_db_name(&$3->db)))
|
||||||
{
|
{
|
||||||
my_error(ER_WRONG_TABLE_NAME, MYF(0), $3->table.str);
|
my_error(ER_WRONG_TABLE_NAME, MYF(0), $3->table.str);
|
||||||
|
29
sql/table.cc
29
sql/table.cc
@ -500,6 +500,26 @@ inline bool is_system_table_name(const char *name, uint length)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Check if a string contains path elements
|
||||||
|
*/
|
||||||
|
|
||||||
|
static inline bool has_disabled_path_chars(const char *str)
|
||||||
|
{
|
||||||
|
for (; *str; str++)
|
||||||
|
switch (*str)
|
||||||
|
{
|
||||||
|
case FN_EXTCHAR:
|
||||||
|
case '/':
|
||||||
|
case '\\':
|
||||||
|
case '~':
|
||||||
|
case '@':
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Read table definition from a binary / text based .frm file
|
Read table definition from a binary / text based .frm file
|
||||||
|
|
||||||
@ -556,7 +576,8 @@ int open_table_def(THD *thd, TABLE_SHARE *share, uint db_flags)
|
|||||||
This kind of tables must have been opened only by the
|
This kind of tables must have been opened only by the
|
||||||
mysql_file_open() above.
|
mysql_file_open() above.
|
||||||
*/
|
*/
|
||||||
if (strchr(share->table_name.str, '@') ||
|
if (has_disabled_path_chars(share->table_name.str) ||
|
||||||
|
has_disabled_path_chars(share->db.str) ||
|
||||||
!strncmp(share->db.str, MYSQL50_TABLE_NAME_PREFIX,
|
!strncmp(share->db.str, MYSQL50_TABLE_NAME_PREFIX,
|
||||||
MYSQL50_TABLE_NAME_PREFIX_LENGTH) ||
|
MYSQL50_TABLE_NAME_PREFIX_LENGTH) ||
|
||||||
!strncmp(share->table_name.str, MYSQL50_TABLE_NAME_PREFIX,
|
!strncmp(share->table_name.str, MYSQL50_TABLE_NAME_PREFIX,
|
||||||
@ -2769,7 +2790,6 @@ bool check_db_name(LEX_STRING *org_name)
|
|||||||
(name_length > NAME_CHAR_LEN)); /* purecov: inspected */
|
(name_length > NAME_CHAR_LEN)); /* purecov: inspected */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Allow anything as a table name, as long as it doesn't contain an
|
Allow anything as a table name, as long as it doesn't contain an
|
||||||
' ' at the end
|
' ' at the end
|
||||||
@ -2777,7 +2797,7 @@ bool check_db_name(LEX_STRING *org_name)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
bool check_table_name(const char *name, uint length)
|
bool check_table_name(const char *name, uint length, bool check_for_path_chars)
|
||||||
{
|
{
|
||||||
uint name_length= 0; // name length in symbols
|
uint name_length= 0; // name length in symbols
|
||||||
const char *end= name+length;
|
const char *end= name+length;
|
||||||
@ -2804,6 +2824,9 @@ bool check_table_name(const char *name, uint length)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (check_for_path_chars &&
|
||||||
|
(*name == '/' || *name == '\\' || *name == '~' || *name == FN_EXTCHAR))
|
||||||
|
return 1;
|
||||||
#endif
|
#endif
|
||||||
name++;
|
name++;
|
||||||
name_length++;
|
name_length++;
|
||||||
|
17
sql/table.h
17
sql/table.h
@ -1894,7 +1894,11 @@ typedef struct st_nested_join
|
|||||||
List<TABLE_LIST> join_list; /* list of elements in the nested join */
|
List<TABLE_LIST> join_list; /* list of elements in the nested join */
|
||||||
table_map used_tables; /* bitmap of tables in the nested join */
|
table_map used_tables; /* bitmap of tables in the nested join */
|
||||||
table_map not_null_tables; /* tables that rejects nulls */
|
table_map not_null_tables; /* tables that rejects nulls */
|
||||||
struct st_join_table *first_nested;/* the first nested table in the plan */
|
/**
|
||||||
|
Used for pointing out the first table in the plan being covered by this
|
||||||
|
join nest. It is used exclusively within make_outerjoin_info().
|
||||||
|
*/
|
||||||
|
struct st_join_table *first_nested;
|
||||||
/*
|
/*
|
||||||
Used to count tables in the nested join in 2 isolated places:
|
Used to count tables in the nested join in 2 isolated places:
|
||||||
1. In make_outerjoin_info().
|
1. In make_outerjoin_info().
|
||||||
@ -1904,6 +1908,15 @@ typedef struct st_nested_join
|
|||||||
*/
|
*/
|
||||||
uint counter;
|
uint counter;
|
||||||
nested_join_map nj_map; /* Bit used to identify this nested join*/
|
nested_join_map nj_map; /* Bit used to identify this nested join*/
|
||||||
|
/**
|
||||||
|
True if this join nest node is completely covered by the query execution
|
||||||
|
plan. This means two things.
|
||||||
|
|
||||||
|
1. All tables on its @c join_list are covered by the plan.
|
||||||
|
|
||||||
|
2. All child join nest nodes are fully covered.
|
||||||
|
*/
|
||||||
|
bool is_fully_covered() const { return join_list.elements == counter; }
|
||||||
} NESTED_JOIN;
|
} NESTED_JOIN;
|
||||||
|
|
||||||
|
|
||||||
@ -2007,7 +2020,7 @@ void update_create_info_from_table(HA_CREATE_INFO *info, TABLE *form);
|
|||||||
bool check_and_convert_db_name(LEX_STRING *db, bool preserve_lettercase);
|
bool check_and_convert_db_name(LEX_STRING *db, bool preserve_lettercase);
|
||||||
bool check_db_name(LEX_STRING *db);
|
bool check_db_name(LEX_STRING *db);
|
||||||
bool check_column_name(const char *name);
|
bool check_column_name(const char *name);
|
||||||
bool check_table_name(const char *name, uint length);
|
bool check_table_name(const char *name, uint length, bool check_for_path_chars);
|
||||||
int rename_file_ext(const char * from,const char * to,const char * ext);
|
int rename_file_ext(const char * from,const char * to,const char * ext);
|
||||||
char *get_field(MEM_ROOT *mem, Field *field);
|
char *get_field(MEM_ROOT *mem, Field *field);
|
||||||
bool get_field(MEM_ROOT *mem, Field *field, class String *res);
|
bool get_field(MEM_ROOT *mem, Field *field, class String *res);
|
||||||
|
@ -18935,6 +18935,50 @@ static void test_bug44495()
|
|||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_bug53371()
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
MYSQL_RES *result;
|
||||||
|
|
||||||
|
myheader("test_bug53371");
|
||||||
|
|
||||||
|
rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
|
||||||
|
myquery(rc);
|
||||||
|
rc= mysql_query(mysql, "DROP DATABASE IF EXISTS bug53371");
|
||||||
|
myquery(rc);
|
||||||
|
rc= mysql_query(mysql, "DROP USER 'testbug'@localhost");
|
||||||
|
|
||||||
|
rc= mysql_query(mysql, "CREATE TABLE t1 (a INT)");
|
||||||
|
myquery(rc);
|
||||||
|
rc= mysql_query(mysql, "CREATE DATABASE bug53371");
|
||||||
|
myquery(rc);
|
||||||
|
rc= mysql_query(mysql, "GRANT SELECT ON bug53371.* to 'testbug'@localhost");
|
||||||
|
myquery(rc);
|
||||||
|
|
||||||
|
rc= mysql_change_user(mysql, "testbug", NULL, "bug53371");
|
||||||
|
myquery(rc);
|
||||||
|
|
||||||
|
rc= mysql_query(mysql, "SHOW COLUMNS FROM client_test_db.t1");
|
||||||
|
DIE_UNLESS(rc);
|
||||||
|
DIE_UNLESS(mysql_errno(mysql) == 1142);
|
||||||
|
|
||||||
|
result= mysql_list_fields(mysql, "../client_test_db/t1", NULL);
|
||||||
|
DIE_IF(result);
|
||||||
|
|
||||||
|
result= mysql_list_fields(mysql, "#mysql50#/../client_test_db/t1", NULL);
|
||||||
|
DIE_IF(result);
|
||||||
|
|
||||||
|
rc= mysql_change_user(mysql, opt_user, opt_password, current_db);
|
||||||
|
myquery(rc);
|
||||||
|
rc= mysql_query(mysql, "DROP TABLE t1");
|
||||||
|
myquery(rc);
|
||||||
|
rc= mysql_query(mysql, "DROP DATABASE bug53371");
|
||||||
|
myquery(rc);
|
||||||
|
rc= mysql_query(mysql, "DROP USER 'testbug'@localhost");
|
||||||
|
myquery(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Bug#49972: Crash in prepared statements.
|
Bug#49972: Crash in prepared statements.
|
||||||
|
|
||||||
@ -19353,6 +19397,7 @@ static struct my_tests_st my_tests[]= {
|
|||||||
{ "test_bug30472", test_bug30472 },
|
{ "test_bug30472", test_bug30472 },
|
||||||
{ "test_bug20023", test_bug20023 },
|
{ "test_bug20023", test_bug20023 },
|
||||||
{ "test_bug45010", test_bug45010 },
|
{ "test_bug45010", test_bug45010 },
|
||||||
|
{ "test_bug53371", test_bug53371 },
|
||||||
{ "test_bug31418", test_bug31418 },
|
{ "test_bug31418", test_bug31418 },
|
||||||
{ "test_bug31669", test_bug31669 },
|
{ "test_bug31669", test_bug31669 },
|
||||||
{ "test_bug28386", test_bug28386 },
|
{ "test_bug28386", test_bug28386 },
|
||||||
|
Loading…
x
Reference in New Issue
Block a user