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:
Alexey Kopytov 2010-05-09 02:03:35 +04:00
commit 5ef2bdea81
28 changed files with 532 additions and 38 deletions

View file

@ -1437,6 +1437,22 @@ SHOW GRANTS FOR mysqltest_1;
Grants for mysqltest_1@%
GRANT ALL PRIVILEGES ON *.* TO '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.

View file

@ -2383,6 +2383,36 @@ SELECT SECOND(c)-@bug47453 FROM t1 JOIN t2 ON d=a;
SECOND(c)-@bug47453
0
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
#
# Test for bug #39932 "create table fails if column for FK is in different

View file

@ -1312,4 +1312,34 @@ WHERE (COALESCE(t1.f1, t2.f1), f3) IN ((1, 3), (2, 2));
f1 f2 f3 f1 f2
1 NULL 3 NULL NULL
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

View file

@ -4561,5 +4561,20 @@ a b c
SET NAMES default;
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
#

View file

@ -239,4 +239,24 @@ a b c
2 NULL NULL
SET NAMES default;
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.

View file

@ -2142,8 +2142,6 @@ CREATE TRIGGER trg1 BEFORE INSERT ON t2 FOR EACH ROW INSERT/*!INTO*/t1 VALUES (1
# Used to crash
SHOW TRIGGERS IN db1;
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);
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;

View file

@ -50,22 +50,22 @@ The following suites are included:
Known Issues
------------
1) The 'funcs' and 'iuds' suites currently runs only against MySQL 5.1 server.
Running them against MySQL 5.5 will generate errors.
2) The folowing tests in the 'iuds' suite:
1) The folowing tests in the 'iuds' suite:
- delete_decimal
- insert_decimal
- update_decimal
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.
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)
- 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)
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.
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.

View file

@ -1554,6 +1554,30 @@ connection default;
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
--source include/wait_until_count_sessions.inc

View file

@ -618,6 +618,36 @@ SELECT SECOND(c)-@bug47453 FROM t1 JOIN t2 ON d=a;
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

View file

@ -913,4 +913,27 @@ WHERE (COALESCE(t1.f1, t2.f1), f3) IN ((1, 3), (2, 2));
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

View file

@ -2136,6 +2136,35 @@ SELECT * FROM t1 UNION SELECT * FROM t2 ORDER BY a, b, c;
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;
###########################################################################

View file

@ -251,6 +251,40 @@ SELECT * FROM t1 UNION SELECT * FROM t2 ORDER BY a, b, c;
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 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.

View file

@ -34,7 +34,7 @@ char * my_load_path(char * to, const char *path,
if ((path[0] == FN_HOMELIB && path[1] == FN_LIBCHAR) ||
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)) ||
(is_prefix(path,FN_PARENTDIR)) ||
! own_path_prefix)
@ -42,13 +42,14 @@ char * my_load_path(char * to, const char *path,
if (is_cur)
is_cur=2; /* Remove current dir */
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
(void) strmov(buff,path); /* Return org file name */
(void) strnmov(buff, path, FN_REFLEN); /* Return org file name */
}
else
(void) strxmov(buff,own_path_prefix,path,NullS);
strmov(to,buff);
(void) strxnmov(buff, FN_REFLEN, own_path_prefix, path, NullS);
strnmov(to, buff, FN_REFLEN);
to[FN_REFLEN-1]= '\0';
DBUG_PRINT("exit",("to: %s",to));
DBUG_RETURN(to);
} /* my_load_path */

View file

@ -50,11 +50,16 @@ int my_getwd(char * buf, size_t size, myf MyFlags)
DBUG_PRINT("my",("buf: 0x%lx size: %u MyFlags %d",
(long) buf, (uint) size, MyFlags));
if (size < 1)
return(-1);
if (curr_dir[0]) /* Current pos is saved here */
(void) strmake(buf,&curr_dir[0],size-1);
else
{
#if defined(HAVE_GETCWD)
if (size < 2)
return(-1);
if (!getcwd(buf,(uint) (size-2)) && MyFlags & MY_WME)
{
my_errno=errno;
@ -68,6 +73,8 @@ int my_getwd(char * buf, size_t size, myf MyFlags)
strmake(buf,pathname,size-1);
}
#elif defined(VMS)
if (size < 2)
return(-1);
if (!getcwd(buf,size-2,1) && MyFlags & MY_WME)
{
my_errno=errno;

View file

@ -5640,13 +5640,25 @@ inline uint char_val(char X)
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)
{
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;
char *ptr=(char*) sql_alloc(max_length+1);
if (!ptr)
{
str_value.set("", 0, &my_charset_bin);
return;
}
str_value.set(ptr,max_length,&my_charset_bin);
char *end=ptr+max_length;
if (max_length*2 != str_length)

View file

@ -2302,7 +2302,7 @@ public:
class Item_hex_string: public Item_basic_constant
{
public:
Item_hex_string() {}
Item_hex_string();
Item_hex_string(const char *str,uint str_length);
enum Type type() const { return VARBIN_ITEM; }
double val_real()
@ -2322,6 +2322,8 @@ public:
bool eq(const Item *item, bool binary_cmp) const;
virtual Item *safe_charset_converter(CHARSET_INFO *tocs);
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
private:
void hex_string_init(const char *str, uint str_length);
};

View file

@ -7731,6 +7731,9 @@ bool is_secure_file_path(char *path)
if (!opt_secure_file_priv)
return TRUE;
if (strlen(path) >= FN_REFLEN)
return FALSE;
if (my_realpath(buff1, path, 0))
{
/*
@ -7816,6 +7819,8 @@ static int fix_paths(void)
}
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))
{
sql_print_warning("Failed to normalize the argument for --secure-file-priv.");

View file

@ -1191,7 +1191,7 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type,
part_elem->engine_type= default_engine_type;
}
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));
goto end;
@ -1209,7 +1209,7 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type,
{
sub_elem= sub_it++;
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));
goto end;

View file

@ -3124,6 +3124,11 @@ pthread_handler_t handle_slave_sql(void *arg)
{
THD *thd; /* needs to be first for thread_stack */
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;
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.
*/
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 &&
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");
DBUG_ASSERT(rli->sql_thd == 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))
{
DBUG_PRINT("info", ("exec_relay_log_event() failed"));

View file

@ -2086,9 +2086,21 @@ bool select_export::send_data(List<Item> &items)
const char *from_end_pos;
const char *error_pos;
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(),
sizeof(cvt_buff),
UINT_MAX32, // copy all input chars,
// i.e. ignore nchars parameter
&well_formed_error_pos,
&cannot_convert_error_pos,
&from_end_pos);
@ -2106,6 +2118,15 @@ bool select_export::send_data(List<Item> &items)
"string", printable_buff,
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);
res= &cvt_str;
}

View file

@ -1170,6 +1170,13 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
}
thd->convert_string(&conv_name, system_charset_info,
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;
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
alias_str= alias ? alias->str : table->table.str;
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);
DBUG_RETURN(0);

View file

@ -1347,6 +1347,10 @@ bool change_master(THD* thd, Master_info* mi)
const char* errmsg= 0;
bool need_relay_log_purge= 1;
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");
lock_slave_threads(mi);
@ -1388,6 +1392,17 @@ bool change_master(THD* thd, Master_info* mi)
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,
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 */
mi->rli.clear_error();
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
relay-log.info until START SLAVE is issued; but if mysqld is shutdown

View file

@ -3005,8 +3005,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables_arg, COND *conds,
s->quick=select->quick;
s->needed_reg=select->needed_reg;
select->quick=0;
if (records == 0 && s->table->reginfo.impossible_range &&
(s->table->file->ha_table_flags() & HA_STATS_RECORDS_IS_EXACT))
if (records == 0 && s->table->reginfo.impossible_range)
{
/*
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.
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
joins counters and join->cur_embedding_map. It is ok to call this
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;
JOIN *join= last->join;
while (last_emb)
for (;last_emb != NULL; last_emb= last_emb->embedding)
{
if (!(--last_emb->nested_join->counter))
join->cur_embedding_map&= ~last_emb->nested_join->nj_map;
else if (last_emb->nested_join->join_list.elements-1 ==
last_emb->nested_join->counter)
{
join->cur_embedding_map|= last_emb->nested_join->nj_map;
NESTED_JOIN *nest= last_emb->nested_join;
DBUG_ASSERT(nest->counter > 0);
bool was_fully_covered= nest->is_fully_covered();
if (--nest->counter == 0)
join->cur_embedding_map&= ~nest->nj_map;
if (!was_fully_covered)
break;
}
else
break;
last_emb= last_emb->embedding;
join->cur_embedding_map|= nest->nj_map;
}
}

View file

@ -469,7 +469,21 @@ uint tablename_to_filename(const char *from, char *to, uint to_length)
DBUG_PRINT("enter", ("from '%s'", from));
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);
}
length= strconvert(system_charset_info, from,
&my_charset_filename, to, to_length, &errors);
if (check_if_legal_tablename(to) &&

View file

@ -6670,7 +6670,7 @@ alter_list_item:
{
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)))
{
my_error(ER_WRONG_TABLE_NAME, MYF(0), $3->table.str);

View file

@ -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
@ -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
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,
MYSQL50_TABLE_NAME_PREFIX_LENGTH) ||
!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 */
}
/*
Allow anything as a table name, as long as it doesn't contain an
' ' 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
const char *end= name+length;
@ -2804,6 +2824,9 @@ bool check_table_name(const char *name, uint length)
continue;
}
}
if (check_for_path_chars &&
(*name == '/' || *name == '\\' || *name == '~' || *name == FN_EXTCHAR))
return 1;
#endif
name++;
name_length++;

View file

@ -1894,7 +1894,11 @@ typedef struct st_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 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:
1. In make_outerjoin_info().
@ -1904,6 +1908,15 @@ typedef struct st_nested_join
*/
uint counter;
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;
@ -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_db_name(LEX_STRING *db);
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);
char *get_field(MEM_ROOT *mem, Field *field);
bool get_field(MEM_ROOT *mem, Field *field, class String *res);

View file

@ -18935,6 +18935,50 @@ static void test_bug44495()
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.
@ -19353,6 +19397,7 @@ static struct my_tests_st my_tests[]= {
{ "test_bug30472", test_bug30472 },
{ "test_bug20023", test_bug20023 },
{ "test_bug45010", test_bug45010 },
{ "test_bug53371", test_bug53371 },
{ "test_bug31418", test_bug31418 },
{ "test_bug31669", test_bug31669 },
{ "test_bug28386", test_bug28386 },