Commit d06e324e authored by Jonathan Perkin's avatar Jonathan Perkin

Merge from mysql-5.5.9-release

parents 1e921bb2 e1d5d26d
......@@ -5,7 +5,7 @@ For the avoidance of doubt, this particular copy of the software
is released under the version 2 of the GNU General Public License.
MySQL is brought to you by the MySQL team at Oracle.
Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
License information can be found in the COPYING file.
......
......@@ -24,6 +24,11 @@ sys_vars.max_sp_recursion_depth_func @solaris # Bug#47791 2010-01-20 alik Severa
sys_vars.plugin_dir_basic # Bug#52223 2010-11-24 alik Test "plugin_dir_basic" does not support RPM build (test) directory structure
sys_vars.slow_query_log_func @solaris # Bug#54819 2010-06-26 alik sys_vars.slow_query_log_func fails sporadically on Solaris 10
sys_vars.wait_timeout_func # Bug#41255 2010-04-26 alik wait_timeout_func fails
sys_vars.sys_vars # Bug #59148 2011-01-10 joro 'INSTALL PLUGIN rpl_semi_sync_master' fails in release build with debug binaries
sys_vars.rpl_semi_sync_master_enabled_basic # Bug #59148 2011-01-10 joro 'INSTALL PLUGIN rpl_semi_sync_master' fails in release build with debug binaries
sys_vars.rpl_semi_sync_master_timeout_basic # Bug #59148 2011-01-10 joro 'INSTALL PLUGIN rpl_semi_sync_master' fails in release build with debug binaries
sys_vars.rpl_semi_sync_master_trace_level_basic # Bug #59148 2011-01-10 joro 'INSTALL PLUGIN rpl_semi_sync_master' fails in release build with debug binaries
sys_vars.rpl_semi_sync_master_wait_no_slave_basic # Bug #59148 2011-01-10 joro 'INSTALL PLUGIN rpl_semi_sync_master' fails in release build with debug binaries
# BUG #59055 : All ndb tests should be removed from the repository
# Leaving the sys_vars tests for now. sys_vars.all_vars.test fails on removing ndb tests
......
......@@ -2168,6 +2168,16 @@ sub environment_setup {
$ENV{'MYSQL_LIBDIR'}= "$basedir/lib";
$ENV{'MYSQL_SHAREDIR'}= $path_language;
$ENV{'MYSQL_CHARSETSDIR'}= $path_charsetsdir;
if (IS_WINDOWS)
{
$ENV{'SECURE_LOAD_PATH'}= $glob_mysql_test_dir."\\std_data";
}
else
{
$ENV{'SECURE_LOAD_PATH'}= $glob_mysql_test_dir."/std_data";
}
# ----------------------------------------------------
# Setup env for NDB
......
......@@ -1378,6 +1378,80 @@ CURRENT_USER()
root@localhost
SET PASSWORD FOR CURRENT_USER() = PASSWORD("admin");
SET PASSWORD FOR CURRENT_USER() = PASSWORD("");
# Bug#57952
DROP DATABASE IF EXISTS mysqltest1;
DROP DATABASE IF EXISTS mysqltest2;
CREATE DATABASE mysqltest1;
CREATE DATABASE mysqltest2;
use mysqltest1;
CREATE TABLE t1(a INT, b INT);
INSERT INTO t1 VALUES (1, 1);
CREATE TABLE t2(a INT);
INSERT INTO t2 VALUES (2);
CREATE TABLE mysqltest2.t3(a INT);
INSERT INTO mysqltest2.t3 VALUES (4);
CREATE USER testuser@localhost;
GRANT CREATE ROUTINE, EXECUTE ON mysqltest1.* TO testuser@localhost;
GRANT SELECT(b) ON t1 TO testuser@localhost;
GRANT SELECT ON t2 TO testuser@localhost;
GRANT SELECT ON mysqltest2.* TO testuser@localhost;
# Connection: bug57952_con1 (testuser@localhost, db: mysqltest1)
PREPARE s1 FROM 'SELECT b FROM t1';
PREPARE s2 FROM 'SELECT a FROM t2';
PREPARE s3 FROM 'SHOW TABLES FROM mysqltest2';
CREATE PROCEDURE p1() SELECT b FROM t1;
CREATE PROCEDURE p2() SELECT a FROM t2;
CREATE PROCEDURE p3() SHOW TABLES FROM mysqltest2;
CALL p1;
b
1
CALL p2;
a
2
CALL p3;
Tables_in_mysqltest2
t3
# Connection: default
REVOKE SELECT ON t1 FROM testuser@localhost;
GRANT SELECT(a) ON t1 TO testuser@localhost;
REVOKE SELECT ON t2 FROM testuser@localhost;
REVOKE SELECT ON mysqltest2.* FROM testuser@localhost;
# Connection: bug57952_con1 (testuser@localhost, db: mysqltest1)
# - Check column-level privileges...
EXECUTE s1;
ERROR 42000: SELECT command denied to user 'testuser'@'localhost' for column 'b' in table 't1'
SELECT b FROM t1;
ERROR 42000: SELECT command denied to user 'testuser'@'localhost' for column 'b' in table 't1'
EXECUTE s1;
ERROR 42000: SELECT command denied to user 'testuser'@'localhost' for column 'b' in table 't1'
CALL p1;
ERROR 42000: SELECT command denied to user 'testuser'@'localhost' for column 'b' in table 't1'
# - Check table-level privileges...
SELECT a FROM t2;
ERROR 42000: SELECT command denied to user 'testuser'@'localhost' for table 't2'
EXECUTE s2;
ERROR 42000: SELECT command denied to user 'testuser'@'localhost' for table 't2'
CALL p2;
ERROR 42000: SELECT command denied to user 'testuser'@'localhost' for table 't2'
# - Check database-level privileges...
SHOW TABLES FROM mysqltest2;
ERROR 42000: Access denied for user 'testuser'@'localhost' to database 'mysqltest2'
EXECUTE s3;
ERROR 42000: Access denied for user 'testuser'@'localhost' to database 'mysqltest2'
CALL p3;
ERROR 42000: Access denied for user 'testuser'@'localhost' to database 'mysqltest2'
# Connection: default
DROP DATABASE mysqltest1;
DROP DATABASE mysqltest2;
DROP USER testuser@localhost;
use test;
End of 5.0 tests
set names utf8;
grant select on test.* to юзер_юзер@localhost;
......
......@@ -341,4 +341,18 @@ ta_y s tb_y s
2001 2001 2001 2001
DROP TABLE t1;
#
# Bug #59211: Select Returns Different Value for min(year) Function
#
CREATE TABLE t1(c1 YEAR(4));
INSERT INTO t1 VALUES (1901),(2155),(0000);
SELECT * FROM t1;
c1
1901
2155
0000
SELECT COUNT(*) AS total_rows, MIN(c1) AS min_value, MAX(c1) FROM t1;
total_rows min_value MAX(c1)
3 0 2155
DROP TABLE t1;
#
End of 5.1 tests
......@@ -448,6 +448,12 @@ DROP TABLE t1;
select @v:=@v:=sum(1) from dual;
@v:=@v:=sum(1)
1
CREATE TABLE t1(a DECIMAL(31,21));
INSERT INTO t1 VALUES (0);
SELECT (@v:=a) <> (@v:=1) FROM t1;
(@v:=a) <> (@v:=1)
1
DROP TABLE t1;
End of 5.1 tests
DROP TABLE IF EXISTS t1;
CREATE TABLE t1(f1 INT AUTO_INCREMENT, PRIMARY KEY(f1));
......
......@@ -2418,7 +2418,7 @@ INSERT INTO t1 SELECT * FROM t2 LIMIT 1;
DROP TABLE t1,t2;
"Should NOT have any warning message issued in the following func7() and trig"
CREATE TABLE t1 (a INT);
CREATE TABLE t2 (a CHAR(40));
CREATE TABLE t2 (a TEXT);
CREATE TABLE trigger_table (a CHAR(7));
CREATE FUNCTION func7()
RETURNS INT
......
......@@ -481,7 +481,7 @@ DROP TABLE t1,t2;
--echo "Should NOT have any warning message issued in the following func7() and trig"
CREATE TABLE t1 (a INT);
CREATE TABLE t2 (a CHAR(40));
CREATE TABLE t2 (a TEXT);
CREATE TABLE trigger_table (a CHAR(7));
DELIMITER |;
CREATE FUNCTION func7()
......
DROP TABLE IF EXISTS t1_56228;
Warnings:
Note 1051 Unknown table 't1_56228'
DROP TABLE IF EXISTS t2_56228;
Warnings:
Note 1051 Unknown table 't2_56228'
DROP FUNCTION IF EXISTS bug56228;
Warnings:
Note 1305 FUNCTION test.bug56228 does not exist
CREATE TEMPORARY TABLE t1_56228(
c1 iNT AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB;
CREATE TEMPORARY TABLE t2_56228(
c1 iNT AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB;
CREATE FUNCTION bug56228() RETURNS INT DETERMINISTIC
BEGIN
INSERT INTO t1_56228 VALUES(NULL);
INSERT INTO t2_56228 VALUES(NULL);
INSERT INTO t1_56228 VALUES(NULL);
INSERT INTO t2_56228 VALUES(NULL);
DROP TEMPORARY TABLE t1_56228;
RETURN 42;
END //
SELECT bug56228();
bug56228()
42
DROP FUNCTION bug56228;
DROP TEMPORARY TABLE t2_56228;
DROP TEMPORARY TABLE IF EXISTS t1_56228;
Warnings:
Note 1051 Unknown table 't1_56228'
-- source include/have_innodb.inc
##
# Bug #56228: dropping tables from within an active statement crashes server
#
DROP TABLE IF EXISTS t1_56228;
DROP TABLE IF EXISTS t2_56228;
DROP FUNCTION IF EXISTS bug56228;
CREATE TEMPORARY TABLE t1_56228(
c1 iNT AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB;
CREATE TEMPORARY TABLE t2_56228(
c1 iNT AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB;
DELIMITER //;
CREATE FUNCTION bug56228() RETURNS INT DETERMINISTIC
BEGIN
INSERT INTO t1_56228 VALUES(NULL);
INSERT INTO t2_56228 VALUES(NULL);
INSERT INTO t1_56228 VALUES(NULL);
INSERT INTO t2_56228 VALUES(NULL);
DROP TEMPORARY TABLE t1_56228;
RETURN 42;
END //
DELIMITER ;//
SELECT bug56228();
DROP FUNCTION bug56228;
DROP TEMPORARY TABLE t2_56228;
DROP TEMPORARY TABLE IF EXISTS t1_56228;
......@@ -74,6 +74,21 @@ LOAD/*!99999 special comments that do not expand */DATA/*!99999 code from the fu
SET sql_mode='PIPES_AS_CONCAT,ANSI_QUOTES,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER';
LOAD DATA LOCAL INFILE 'MYSQLD_DATADIR/bug43746.sql' INTO TABLE t1;
[slave]
Bug #59267:
"LOAD DATA LOCAL INFILE not executed on slave with SBR"
[master]
SELECT * INTO OUTFILE 'MYSQLD_DATADIR/bug59267.sql' FROM t1;
TRUNCATE TABLE t1;
LOAD DATA LOCAL INFILE 'MYSQLD_DATADIR/bug59267.sql' INTO TABLE t1;
SELECT 'Master', COUNT(*) FROM t1;
Master COUNT(*)
Master 44
[slave]
SELECT 'Slave', COUNT(*) FROM t1;
Slave COUNT(*)
Slave 44
[master]
DROP TABLE t1;
SET SESSION sql_mode=@old_mode;
......
......@@ -151,12 +151,34 @@ eval LOAD DATA LOCAL INFILE '$MYSQLD_DATADIR/bug43746.sql' INTO TABLE t1;
--echo [slave]
sync_slave_with_master;
# cleanup
--echo
--echo Bug #59267:
--echo "LOAD DATA LOCAL INFILE not executed on slave with SBR"
--echo
--remove_file $MYSQLD_DATADIR/bug43746.sql
--echo [master]
connection master;
--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR
eval SELECT * INTO OUTFILE '$MYSQLD_DATADIR/bug59267.sql' FROM t1;
TRUNCATE TABLE t1;
--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR
eval LOAD DATA LOCAL INFILE '$MYSQLD_DATADIR/bug59267.sql' INTO TABLE t1;
SELECT 'Master', COUNT(*) FROM t1;
--echo [slave]
--sync_slave_with_master
SELECT 'Slave', COUNT(*) FROM t1;
# cleanup
--echo [master]
connection master;
--remove_file $MYSQLD_DATADIR/bug43746.sql
--remove_file $MYSQLD_DATADIR/bug59267.sql
DROP TABLE t1;
SET SESSION sql_mode=@old_mode;
......
CREATE TABLE t1 (c1 INT);
LOAD DATA INFILE "t1.MYI" into table t1;
ERROR HY000: The MySQL server is running with the --secure-file-priv option so it cannot execute this statement
LOAD DATA INFILE "/test" into table t1;
ERROR HY000: The MySQL server is running with the --secure-file-priv option so it cannot execute this statement
DROP TABLE t1;
#
# Bug58747 breaks secure_file_priv+not secure yet+still accesses other folders
#
CREATE TABLE t1 (c1 INT);
#
# Before the patch this statement failed with
# Linux:
# -> errno 13: 'Can't get stat of '
# Windows:
# -> Warning 1366 Incorrect integer value: '■■☺' for
# -> column 'c1' at row 1
# Now it should consistently fail with ER_OPTION_PREVENTS_STATEMENT
# on all platforms.
--error ER_OPTION_PREVENTS_STATEMENT
LOAD DATA INFILE "t1.MYI" into table t1;
#
# The following test makes the assuption that /test isn't a valid path in any
# operating system running the test suite.
--error ER_OPTION_PREVENTS_STATEMENT
LOAD DATA INFILE "/test" into table t1;
DROP TABLE t1;
......@@ -1295,6 +1295,107 @@ SELECT CURRENT_USER();
SET PASSWORD FOR CURRENT_USER() = PASSWORD("admin");
SET PASSWORD FOR CURRENT_USER() = PASSWORD("");
#
# Bug#57952: privilege change is not taken into account by EXECUTE.
#
--echo
--echo # Bug#57952
--echo
--disable_warnings
DROP DATABASE IF EXISTS mysqltest1;
DROP DATABASE IF EXISTS mysqltest2;
--enable_warnings
CREATE DATABASE mysqltest1;
CREATE DATABASE mysqltest2;
use mysqltest1;
CREATE TABLE t1(a INT, b INT);
INSERT INTO t1 VALUES (1, 1);
CREATE TABLE t2(a INT);
INSERT INTO t2 VALUES (2);
CREATE TABLE mysqltest2.t3(a INT);
INSERT INTO mysqltest2.t3 VALUES (4);
CREATE USER testuser@localhost;
GRANT CREATE ROUTINE, EXECUTE ON mysqltest1.* TO testuser@localhost;
GRANT SELECT(b) ON t1 TO testuser@localhost;
GRANT SELECT ON t2 TO testuser@localhost;
GRANT SELECT ON mysqltest2.* TO testuser@localhost;
--echo
--echo # Connection: bug57952_con1 (testuser@localhost, db: mysqltest1)
--connect (bug57952_con1,localhost,testuser,,mysqltest1)
PREPARE s1 FROM 'SELECT b FROM t1';
PREPARE s2 FROM 'SELECT a FROM t2';
PREPARE s3 FROM 'SHOW TABLES FROM mysqltest2';
CREATE PROCEDURE p1() SELECT b FROM t1;
CREATE PROCEDURE p2() SELECT a FROM t2;
CREATE PROCEDURE p3() SHOW TABLES FROM mysqltest2;
CALL p1;
CALL p2;
CALL p3;
--echo
--echo # Connection: default
--connection default
REVOKE SELECT ON t1 FROM testuser@localhost;
GRANT SELECT(a) ON t1 TO testuser@localhost;
REVOKE SELECT ON t2 FROM testuser@localhost;
REVOKE SELECT ON mysqltest2.* FROM testuser@localhost;
--echo
--echo # Connection: bug57952_con1 (testuser@localhost, db: mysqltest1)
--connection bug57952_con1
--echo # - Check column-level privileges...
--error ER_COLUMNACCESS_DENIED_ERROR
EXECUTE s1;
--error ER_COLUMNACCESS_DENIED_ERROR
SELECT b FROM t1;
--error ER_COLUMNACCESS_DENIED_ERROR
EXECUTE s1;
--error ER_COLUMNACCESS_DENIED_ERROR
CALL p1;
--echo # - Check table-level privileges...
--error ER_TABLEACCESS_DENIED_ERROR
SELECT a FROM t2;
--error ER_TABLEACCESS_DENIED_ERROR
EXECUTE s2;
--error ER_TABLEACCESS_DENIED_ERROR
CALL p2;
--echo # - Check database-level privileges...
--error ER_DBACCESS_DENIED_ERROR
SHOW TABLES FROM mysqltest2;
--error ER_DBACCESS_DENIED_ERROR
EXECUTE s3;
--error ER_DBACCESS_DENIED_ERROR
CALL p3;
--echo
--echo # Connection: default
--connection default
--disconnect bug57952_con1
DROP DATABASE mysqltest1;
DROP DATABASE mysqltest2;
DROP USER testuser@localhost;
use test;
--echo
--echo End of 5.0 tests
#
......
......@@ -149,6 +149,16 @@ SELECT ta.y AS ta_y, ta.s, tb.y AS tb_y, tb.s FROM t1 ta, t1 tb HAVING ta_y = tb
DROP TABLE t1;
--echo #
--echo # Bug #59211: Select Returns Different Value for min(year) Function
--echo #
CREATE TABLE t1(c1 YEAR(4));
INSERT INTO t1 VALUES (1901),(2155),(0000);
SELECT * FROM t1;
SELECT COUNT(*) AS total_rows, MIN(c1) AS min_value, MAX(c1) FROM t1;
DROP TABLE t1;
--echo #
--echo End of 5.1 tests
......@@ -351,6 +351,18 @@ DROP TABLE t1;
select @v:=@v:=sum(1) from dual;
#
# Bug #57187: more user variable fun with multiple assignments and
# comparison in query
#
CREATE TABLE t1(a DECIMAL(31,21));
INSERT INTO t1 VALUES (0);
SELECT (@v:=a) <> (@v:=1) FROM t1;
DROP TABLE t1;
--echo End of 5.1 tests
#
......
......@@ -3203,11 +3203,10 @@ class Item_cache: public Item_basic_constant
protected:
Item *example;
table_map used_table_map;
/*
Field that this object will get value from. This is set/used by
/**
Field that this object will get value from. This is used by
index-based subquery engines to detect and remove the equality injected
by IN->EXISTS transformation.
For all other uses of Item_cache, cached_field doesn't matter.
*/
Field *cached_field;
enum enum_field_types cached_field_type;
......@@ -3275,6 +3274,14 @@ public:
{
return (value_cached || cache_value()) && !null_value;
}
/**
If this item caches a field value, return pointer to underlying field.
@return Pointer to field, or NULL if this is not a cache for a field value.
*/
Field* field() { return cached_field; }
virtual void store(Item *item);
virtual bool cache_value()= 0;
bool basic_const_item() const
......
......@@ -1208,9 +1208,12 @@ get_year_value(THD *thd, Item ***item_arg, Item **cache_arg,
value of 2000.
*/
Item *real_item= item->real_item();
if (!(real_item->type() == Item::FIELD_ITEM &&
((Item_field *)real_item)->field->type() == MYSQL_TYPE_YEAR &&
((Item_field *)real_item)->field->field_length == 4))
Field *field= NULL;
if (real_item->type() == Item::FIELD_ITEM)
field= ((Item_field *)real_item)->field;
else if (real_item->type() == Item::CACHE_ITEM)
field= ((Item_cache *)real_item)->field();
if (!(field && field->type() == MYSQL_TYPE_YEAR && field->field_length == 4))
{
if (value < 70)
value+= 100;
......
......@@ -4478,7 +4478,7 @@ my_decimal *user_var_entry::val_decimal(my_bool *null_value, my_decimal *val)
int2my_decimal(E_DEC_FATAL_ERROR, *(longlong*) value, 0, val);
break;
case DECIMAL_RESULT:
val= (my_decimal *)value;
my_decimal2decimal((my_decimal *) value, val);
break;
case STRING_RESULT:
str2my_decimal(E_DEC_FATAL_ERROR, value, length, collation.collation, val);
......
......@@ -6155,6 +6155,8 @@ find_field_in_natural_join(THD *thd, TABLE_LIST *table_ref, const char *name,
/*
Find field by name in a base table or a view with temp table algorithm.
The caller is expected to check column-level privileges.
SYNOPSIS
find_field_in_table()
thd thread handler
......@@ -6262,6 +6264,8 @@ find_field_in_table(THD *thd, TABLE *table, const char *name, uint length,
This procedure detects the type of the table reference 'table_list'
and calls the corresponding search routine.
The routine checks column-level privieleges for the found field.
RETURN
0 field is not found
view_ref_found found value in VIEW (real result is in *ref)
......@@ -6537,8 +6541,16 @@ find_field_in_tables(THD *thd, Item_ident *item,
when table_ref->field_translation != NULL.
*/
if (table_ref->table && !table_ref->view)
{
found= find_field_in_table(thd, table_ref->table, name, length,
TRUE, &(item->cached_field_index));
#ifndef NO_EMBEDDED_ACCESS_CHECKS
/* Check if there are sufficient access rights to the found field. */
if (found && check_privileges &&
check_column_grant_in_table_ref(thd, table_ref, name, length))
found= WRONG_GRANT;
#endif
}
else
found= find_field_in_table_ref(thd, table_ref, name, length, item->name,
NULL, NULL, ref, check_privileges,
......
......@@ -363,58 +363,59 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
(void) fn_format(name, ex->file_name, mysql_real_data_home, "",
MY_RELATIVE_PATH | MY_UNPACK_FILENAME |
MY_RETURN_REAL_PATH);
#if !defined(__WIN__)
MY_STAT stat_info;
if (!mysql_file_stat(key_file_load, name, &stat_info, MYF(MY_WME)))
DBUG_RETURN(TRUE);
// if we are not in slave thread, the file must be:
if (!thd->slave_thread &&
!((stat_info.st_mode & S_IROTH) == S_IROTH && // readable by others
(stat_info.st_mode & S_IFLNK) != S_IFLNK && // and not a symlink
((stat_info.st_mode & S_IFREG) == S_IFREG ||
(stat_info.st_mode & S_IFIFO) == S_IFIFO)))
{
my_error(ER_TEXTFILE_NOT_READABLE, MYF(0), name);
DBUG_RETURN(TRUE);
}
if ((stat_info.st_mode & S_IFIFO) == S_IFIFO)
is_fifo = 1;
#endif
}
if (thd->slave_thread)
{
if (thd->slave_thread)
{
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
if (strncmp(active_mi->rli.slave_patternload_file, name,
active_mi->rli.slave_patternload_file_size))
{
/*
LOAD DATA INFILE in the slave SQL Thread can only read from
--slave-load-tmpdir". This should never happen. Please, report a bug.
*/
sql_print_error("LOAD DATA INFILE in the slave SQL Thread can only read from --slave-load-tmpdir. " \
"Please, report a bug.");
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--slave-load-tmpdir");
DBUG_RETURN(TRUE);
}
#else
if (strncmp(active_mi->rli.slave_patternload_file, name,
active_mi->rli.slave_patternload_file_size))
{
/*
This is impossible and should never happen.
LOAD DATA INFILE in the slave SQL Thread can only read from
--slave-load-tmpdir". This should never happen. Please, report a bug.
*/
DBUG_ASSERT(FALSE);
#endif
}
else if (!is_secure_file_path(name))
{
/* Read only allowed from within dir specified by secure_file_priv */
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
sql_print_error("LOAD DATA INFILE in the slave SQL Thread can only read from --slave-load-tmpdir. " \
"Please, report a bug.");
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--slave-load-tmpdir");
DBUG_RETURN(TRUE);
}
#else
/*
This is impossible and should never happen.
*/
DBUG_ASSERT(FALSE);
#endif
}
else if (!is_secure_file_path(name))
{
/* Read only allowed from within dir specified by secure_file_priv */
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
DBUG_RETURN(TRUE);
}
#if !defined(__WIN__) && ! defined(__NETWARE__)
MY_STAT stat_info;
if (!my_stat(name,&stat_info,MYF(MY_WME)))
DBUG_RETURN(TRUE);
// if we are not in slave thread, the file must be:
if (!thd->slave_thread &&
!((stat_info.st_mode & S_IROTH) == S_IROTH && // readable by others
(stat_info.st_mode & S_IFLNK) != S_IFLNK && // and not a symlink
((stat_info.st_mode & S_IFREG) == S_IFREG ||
(stat_info.st_mode & S_IFIFO) == S_IFIFO)))
{
my_error(ER_TEXTFILE_NOT_READABLE, MYF(0), name);
DBUG_RETURN(TRUE);
}
if ((stat_info.st_mode & S_IFIFO) == S_IFIFO)
is_fifo = 1;
#endif
if ((file= mysql_file_open(key_file_load,
name, O_RDONLY, MYF(MY_WME))) < 0)
DBUG_RETURN(TRUE);
}
......
......@@ -949,7 +949,7 @@ dict_table_rename_in_cache(
dict_foreign_t* foreign;
dict_index_t* index;
ulint fold;
char old_name[MAX_TABLE_NAME_LEN + 1];
char old_name[MAX_FULL_NAME_LEN + 1];
ut_ad(table);
ut_ad(mutex_own(&(dict_sys->mutex)));
......@@ -961,7 +961,7 @@ dict_table_rename_in_cache(
ut_print_timestamp(stderr);
fprintf(stderr, "InnoDB: too long table name: '%s', "
"max length is %d\n", table->name,
MAX_TABLE_NAME_LEN);
MAX_FULL_NAME_LEN);
ut_error;
}
......@@ -1011,11 +1011,11 @@ dict_table_rename_in_cache(
ut_fold_string(old_name), table);
if (strlen(new_name) > strlen(table->name)) {
/* We allocate MAX_TABLE_NAME_LEN+1 bytes here to avoid
/* We allocate MAX_FULL_NAME_LEN + 1 bytes here to avoid
memory fragmentation, we assume a repeated calls of
ut_realloc() with the same size do not cause fragmentation */
ut_a(strlen(new_name) <= MAX_TABLE_NAME_LEN);
table->name = ut_realloc(table->name, MAX_TABLE_NAME_LEN + 1);
ut_a(strlen(new_name) <= MAX_FULL_NAME_LEN);
table->name = ut_realloc(table->name, MAX_FULL_NAME_LEN + 1);
}
memcpy(table->name, new_name, strlen(new_name) + 1);
......
......@@ -6236,6 +6236,17 @@ create_table_def(
DBUG_RETURN(HA_ERR_GENERIC);
}
/* MySQL does the name length check. But we do additional check
on the name length here */
if (strlen(table_name) > MAX_FULL_NAME_LEN) {
push_warning_printf(
(THD*) trx->mysql_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_TABLE_NAME,
"InnoDB: Table Name or Database Name is too long");
DBUG_RETURN(ER_TABLE_NAME);
}
n_cols = form->s->fields;
/* We pass 0 as the space id, and determine at a lower level the space
......
......@@ -767,16 +767,7 @@ fill_innodb_locks_from_cache(
for (i = 0; i < rows_num; i++) {
i_s_locks_row_t* row;
/* note that the decoded database or table name is
never expected to be longer than NAME_LEN;
NAME_LEN for database name
2 for surrounding quotes around database name
NAME_LEN for table name
2 for surrounding quotes around table name
1 for the separating dot (.)
9 for the #mysql50# prefix */
char buf[2 * NAME_LEN + 14];
char buf[MAX_FULL_NAME_LEN + 1];
const char* bufend;
char lock_trx_id[TRX_ID_MAX_LEN + 1];
......
......@@ -308,6 +308,18 @@ number does not include a terminating '\0'. InnoDB probably can handle
longer names internally */
#define MAX_TABLE_NAME_LEN 192
/* The maximum length of a database name. Like MAX_TABLE_NAME_LEN this is
the MySQL's NAME_LEN, see check_and_convert_db_name(). */
#define MAX_DATABASE_NAME_LEN MAX_TABLE_NAME_LEN
/* MAX_FULL_NAME_LEN defines the full name path including the
database name and table name. In addition, 14 bytes is added for:
2 for surrounding quotes around table name
1 for the separating dot (.)
9 for the #mysql50# prefix */
#define MAX_FULL_NAME_LEN \
(MAX_TABLE_NAME_LEN + MAX_DATABASE_NAME_LEN + 14)
/*
UNIVERSAL TYPE DEFINITIONS
==========================
......
......@@ -93,6 +93,25 @@ ib_vector_get(
ib_vector_t* vec, /*!< in: vector */
ulint n); /*!< in: element index to get */
/****************************************************************//**
Get last element. The vector must not be empty.
@return last element */
UNIV_INLINE
void*
ib_vector_get_last(
/*===============*/
ib_vector_t* vec); /*!< in: vector */
/****************************************************************//**
Set the n'th element. */
UNIV_INLINE
void
ib_vector_set(
/*==========*/
ib_vector_t* vec, /*!< in/out: vector */
ulint n, /*!< in: element index to set */
void* elem); /*!< in: data element */
/****************************************************************//**
Remove the last element from the vector. */
UNIV_INLINE
......
......@@ -50,6 +50,35 @@ ib_vector_get(
return(vec->data[n]);
}
/****************************************************************//**
Get last element. The vector must not be empty.
@return last element */
UNIV_INLINE
void*
ib_vector_get_last(
/*===============*/
ib_vector_t* vec) /*!< in: vector */
{
ut_a(vec->used > 0);
return(vec->data[vec->used - 1]);
}
/****************************************************************//**
Set the n'th element. */
UNIV_INLINE
void
ib_vector_set(
/*==========*/
ib_vector_t* vec, /*!< in/out: vector */
ulint n, /*!< in: element index to set */
void* elem) /*!< in: data element */
{
ut_a(n < vec->used);
vec->data[n] = elem;
}
/****************************************************************//**
Remove the last element from the vector.
@return last vector element */
......
......@@ -3621,6 +3621,80 @@ lock_table_create(
return(lock);
}
/*************************************************************//**
Pops autoinc lock requests from the transaction's autoinc_locks. We
handle the case where there are gaps in the array and they need to
be popped off the stack. */
UNIV_INLINE
void
lock_table_pop_autoinc_locks(
/*=========================*/
trx_t* trx) /*!< in/out: transaction that owns the AUTOINC locks */
{
ut_ad(mutex_own(&kernel_mutex));
ut_ad(!ib_vector_is_empty(trx->autoinc_locks));
/* Skip any gaps, gaps are NULL lock entries in the
trx->autoinc_locks vector. */
do {
ib_vector_pop(trx->autoinc_locks);
if (ib_vector_is_empty(trx->autoinc_locks)) {
return;
}
} while (ib_vector_get_last(trx->autoinc_locks) == NULL);
}
/*************************************************************//**
Removes an autoinc lock request from the transaction's autoinc_locks. */
UNIV_INLINE
void
lock_table_remove_autoinc_lock(
/*===========================*/
lock_t* lock, /*!< in: table lock */
trx_t* trx) /*!< in/out: transaction that owns the lock */
{
lock_t* autoinc_lock;
lint i = ib_vector_size(trx->autoinc_locks) - 1;
ut_ad(mutex_own(&kernel_mutex));
ut_ad(lock_get_mode(lock) == LOCK_AUTO_INC);
ut_ad(lock_get_type_low(lock) & LOCK_TABLE);
ut_ad(!ib_vector_is_empty(trx->autoinc_locks));
/* With stored functions and procedures the user may drop
a table within the same "statement". This special case has
to be handled by deleting only those AUTOINC locks that were
held by the table being dropped. */
autoinc_lock = ib_vector_get(trx->autoinc_locks, i);
/* This is the default fast case. */
if (autoinc_lock == lock) {
lock_table_pop_autoinc_locks(trx);
} else {
/* The last element should never be NULL */
ut_a(autoinc_lock != NULL);
/* Handle freeing the locks from within the stack. */
while (--i >= 0) {
autoinc_lock = ib_vector_get(trx->autoinc_locks, i);
if (UNIV_LIKELY(autoinc_lock == lock)) {
ib_vector_set(trx->autoinc_locks, i, NULL);
return;
}
}
/* Must find the autoinc lock. */
ut_error;
}
}
/*************************************************************//**
Removes a table lock request from the queue and the trx list of locks;
this is a low-level function which does NOT check if waiting requests
......@@ -3660,10 +3734,8 @@ lock_table_remove_low(
if (!lock_get_wait(lock)
&& !ib_vector_is_empty(trx->autoinc_locks)) {
lock_t* autoinc_lock;
autoinc_lock = ib_vector_pop(trx->autoinc_locks);
ut_a(autoinc_lock == lock);
lock_table_remove_autoinc_lock(lock, trx);
}
ut_a(table->n_waiting_or_granted_auto_inc_locks > 0);
......
......@@ -2388,7 +2388,7 @@ row_merge_rename_tables(
{
ulint err = DB_ERROR;
pars_info_t* info;
char old_name[MAX_TABLE_NAME_LEN + 1];
char old_name[MAX_FULL_NAME_LEN + 1];
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
ut_ad(old_table != new_table);
......@@ -2403,7 +2403,7 @@ row_merge_rename_tables(
ut_print_timestamp(stderr);
fprintf(stderr, "InnoDB: too long table name: '%s', "
"max length is %d\n", old_table->name,
MAX_TABLE_NAME_LEN);
MAX_FULL_NAME_LEN);
ut_error;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment