Commit 15017480 authored by unknown's avatar unknown

Merge bk-internal.mysql.com:/home/bk/mysql-4.0

into mysql.com:/home/dlenev/src/mysql-4.0-bg7297

parents 1ffd688a 4ba981e5
...@@ -4,7 +4,7 @@ dnl Process this file with autoconf to produce a configure script. ...@@ -4,7 +4,7 @@ dnl Process this file with autoconf to produce a configure script.
AC_INIT(sql/mysqld.cc) AC_INIT(sql/mysqld.cc)
AC_CANONICAL_SYSTEM AC_CANONICAL_SYSTEM
# The Docs Makefile.am parses this line! # The Docs Makefile.am parses this line!
AM_INIT_AUTOMAKE(mysql, 4.0.23) AM_INIT_AUTOMAKE(mysql, 4.0.24)
AM_CONFIG_HEADER(config.h) AM_CONFIG_HEADER(config.h)
PROTOCOL_VERSION=10 PROTOCOL_VERSION=10
......
...@@ -1195,6 +1195,7 @@ os_file_pread( ...@@ -1195,6 +1195,7 @@ os_file_pread(
return(n_bytes); return(n_bytes);
#else #else
{ {
off_t ret_offset;
ssize_t ret; ssize_t ret;
ulint i; ulint i;
...@@ -1203,12 +1204,12 @@ os_file_pread( ...@@ -1203,12 +1204,12 @@ os_file_pread(
os_mutex_enter(os_file_seek_mutexes[i]); os_mutex_enter(os_file_seek_mutexes[i]);
ret = lseek(file, offs, 0); ret_offset = lseek(file, offs, SEEK_SET);
if (ret < 0) { if (ret_offset < 0) {
os_mutex_exit(os_file_seek_mutexes[i]); os_mutex_exit(os_file_seek_mutexes[i]);
return(ret); return(-1);
} }
ret = read(file, buf, (ssize_t)n); ret = read(file, buf, (ssize_t)n);
...@@ -1281,6 +1282,7 @@ os_file_pwrite( ...@@ -1281,6 +1282,7 @@ os_file_pwrite(
return(ret); return(ret);
#else #else
{ {
off_t ret_offset;
ulint i; ulint i;
/* Protect the seek / write operation with a mutex */ /* Protect the seek / write operation with a mutex */
...@@ -1288,12 +1290,12 @@ os_file_pwrite( ...@@ -1288,12 +1290,12 @@ os_file_pwrite(
os_mutex_enter(os_file_seek_mutexes[i]); os_mutex_enter(os_file_seek_mutexes[i]);
ret = lseek(file, offs, 0); ret_offset = lseek(file, offs, SEEK_SET);
if (ret < 0) { if (ret_offset < 0) {
os_mutex_exit(os_file_seek_mutexes[i]); os_mutex_exit(os_file_seek_mutexes[i]);
return(ret); return(-1);
} }
ret = write(file, buf, (ssize_t)n); ret = write(file, buf, (ssize_t)n);
......
...@@ -1373,8 +1373,34 @@ row_ins_check_foreign_constraints( ...@@ -1373,8 +1373,34 @@ row_ins_check_foreign_constraints(
row_mysql_freeze_data_dictionary(trx); row_mysql_freeze_data_dictionary(trx);
} }
if (foreign->referenced_table) {
mutex_enter(&(dict_sys->mutex));
(foreign->referenced_table
->n_foreign_key_checks_running)++;
mutex_exit(&(dict_sys->mutex));
}
/* NOTE that if the thread ends up waiting for a lock
we will release dict_operation_lock temporarily!
But the counter on the table protects the referenced
table from being dropped while the check is running. */
err = row_ins_check_foreign_constraint(TRUE, foreign, err = row_ins_check_foreign_constraint(TRUE, foreign,
table, entry, thr); table, entry, thr);
if (foreign->referenced_table) {
mutex_enter(&(dict_sys->mutex));
ut_a(foreign->referenced_table
->n_foreign_key_checks_running > 0);
(foreign->referenced_table
->n_foreign_key_checks_running)--;
mutex_exit(&(dict_sys->mutex));
}
if (got_s_lock) { if (got_s_lock) {
row_mysql_unfreeze_data_dictionary(trx); row_mysql_unfreeze_data_dictionary(trx);
} }
......
...@@ -1761,20 +1761,19 @@ row_drop_table_for_mysql_in_background( ...@@ -1761,20 +1761,19 @@ row_drop_table_for_mysql_in_background(
trx = trx_allocate_for_background(); trx = trx_allocate_for_background();
/* If the original transaction was dropping a table referenced by
foreign keys, we must set the following to be able to drop the
table: */
trx->check_foreigns = FALSE;
/* fputs("InnoDB: Error: Dropping table ", stderr); /* fputs("InnoDB: Error: Dropping table ", stderr);
ut_print_name(stderr, name); ut_print_name(stderr, name);
fputs(" in background drop list\n", stderr); */ fputs(" in background drop list\n", stderr); */
/* Drop the table in InnoDB */ /* Try to drop the table in InnoDB */
error = row_drop_table_for_mysql(name, trx, FALSE); error = row_drop_table_for_mysql(name, trx, FALSE);
if (error != DB_SUCCESS) {
ut_print_timestamp(stderr);
fputs(" InnoDB: Error: Dropping table ", stderr);
ut_print_name(stderr, name);
fputs(" in background drop list failed\n", stderr);
}
/* Flush the log to reduce probability that the .frm files and /* Flush the log to reduce probability that the .frm files and
the InnoDB data dictionary get out-of-sync if the user runs the InnoDB data dictionary get out-of-sync if the user runs
...@@ -1786,7 +1785,7 @@ row_drop_table_for_mysql_in_background( ...@@ -1786,7 +1785,7 @@ row_drop_table_for_mysql_in_background(
trx_free_for_background(trx); trx_free_for_background(trx);
return(DB_SUCCESS); return(error);
} }
/************************************************************************* /*************************************************************************
...@@ -1820,6 +1819,7 @@ row_drop_tables_for_mysql_in_background(void) ...@@ -1820,6 +1819,7 @@ row_drop_tables_for_mysql_in_background(void)
mutex_exit(&kernel_mutex); mutex_exit(&kernel_mutex);
if (drop == NULL) { if (drop == NULL) {
/* All tables dropped */
return(n_tables + n_tables_dropped); return(n_tables + n_tables_dropped);
} }
...@@ -1834,16 +1834,16 @@ row_drop_tables_for_mysql_in_background(void) ...@@ -1834,16 +1834,16 @@ row_drop_tables_for_mysql_in_background(void)
goto already_dropped; goto already_dropped;
} }
if (table->n_mysql_handles_opened > 0 if (DB_SUCCESS != row_drop_table_for_mysql_in_background(
|| table->n_foreign_key_checks_running > 0) { drop->table_name)) {
/* If the DROP fails for some table, we return, and let the
main thread retry later */
return(n_tables + n_tables_dropped); return(n_tables + n_tables_dropped);
} }
n_tables_dropped++; n_tables_dropped++;
row_drop_table_for_mysql_in_background(drop->table_name);
already_dropped: already_dropped:
mutex_enter(&kernel_mutex); mutex_enter(&kernel_mutex);
...@@ -1887,21 +1887,21 @@ row_get_background_drop_list_len_low(void) ...@@ -1887,21 +1887,21 @@ row_get_background_drop_list_len_low(void)
} }
/************************************************************************* /*************************************************************************
Adds a table to the list of tables which the master thread drops in If a table is not yet in the drop list, adds the table to the list of tables
background. We need this on Unix because in ALTER TABLE MySQL may call which the master thread drops in background. We need this on Unix because in
drop table even if the table has running queries on it. */ ALTER TABLE MySQL may call drop table even if the table has running queries on
it. Also, if there are running foreign key checks on the table, we drop the
table lazily. */
static static
void ibool
row_add_table_to_background_drop_list( row_add_table_to_background_drop_list(
/*==================================*/ /*==================================*/
/* out: TRUE if the table was not yet in the
drop list, and was added there */
dict_table_t* table) /* in: table */ dict_table_t* table) /* in: table */
{ {
row_mysql_drop_t* drop; row_mysql_drop_t* drop;
drop = mem_alloc(sizeof(row_mysql_drop_t));
drop->table_name = mem_strdup(table->name);
mutex_enter(&kernel_mutex); mutex_enter(&kernel_mutex);
if (!row_mysql_drop_list_inited) { if (!row_mysql_drop_list_inited) {
...@@ -1909,6 +1909,25 @@ row_add_table_to_background_drop_list( ...@@ -1909,6 +1909,25 @@ row_add_table_to_background_drop_list(
UT_LIST_INIT(row_mysql_drop_list); UT_LIST_INIT(row_mysql_drop_list);
row_mysql_drop_list_inited = TRUE; row_mysql_drop_list_inited = TRUE;
} }
/* Look if the table already is in the drop list */
drop = UT_LIST_GET_FIRST(row_mysql_drop_list);
while (drop != NULL) {
if (strcmp(drop->table_name, table->name) == 0) {
/* Already in the list */
mutex_exit(&kernel_mutex);
return(FALSE);
}
drop = UT_LIST_GET_NEXT(row_mysql_drop_list, drop);
}
drop = mem_alloc(sizeof(row_mysql_drop_t));
drop->table_name = mem_strdup(table->name);
UT_LIST_ADD_LAST(row_mysql_drop_list, row_mysql_drop_list, drop); UT_LIST_ADD_LAST(row_mysql_drop_list, row_mysql_drop_list, drop);
...@@ -1917,6 +1936,8 @@ row_add_table_to_background_drop_list( ...@@ -1917,6 +1936,8 @@ row_add_table_to_background_drop_list(
fputs(" to background drop list\n", stderr); */ fputs(" to background drop list\n", stderr); */
mutex_exit(&kernel_mutex); mutex_exit(&kernel_mutex);
return(TRUE);
} }
/************************************************************************* /*************************************************************************
...@@ -2151,36 +2172,53 @@ row_drop_table_for_mysql( ...@@ -2151,36 +2172,53 @@ row_drop_table_for_mysql(
} }
if (table->n_mysql_handles_opened > 0) { if (table->n_mysql_handles_opened > 0) {
ibool added;
ut_print_timestamp(stderr); added = row_add_table_to_background_drop_list(table);
fputs(" InnoDB: Warning: MySQL is trying to drop table ",
stderr);
ut_print_name(stderr, table->name);
fputs("\n"
"InnoDB: though there are still open handles to it.\n"
"InnoDB: Adding the table to the background drop queue.\n",
stderr);
row_add_table_to_background_drop_list(table); if (added) {
ut_print_timestamp(stderr);
fputs(" InnoDB: Warning: MySQL is trying to drop table ", stderr);
ut_print_name(stderr, table->name);
fputs("\n"
"InnoDB: though there are still open handles to it.\n"
"InnoDB: Adding the table to the background drop queue.\n",
stderr);
/* We return DB_SUCCESS to MySQL though the drop will
happen lazily later */
err = DB_SUCCESS; err = DB_SUCCESS;
} else {
/* The table is already in the background drop list */
err = DB_ERROR;
}
goto funct_exit; goto funct_exit;
} }
if (table->n_foreign_key_checks_running > 0) { if (table->n_foreign_key_checks_running > 0) {
ibool added;
added = row_add_table_to_background_drop_list(table);
ut_print_timestamp(stderr); if (added) {
fputs(" InnoDB: You are trying to drop table ", stderr); ut_print_timestamp(stderr);
fputs(" InnoDB: You are trying to drop table ", stderr);
ut_print_name(stderr, table->name); ut_print_name(stderr, table->name);
fputs("\n" fputs("\n"
"InnoDB: though there is a foreign key check running on it.\n" "InnoDB: though there is a foreign key check running on it.\n"
"InnoDB: Adding the table to the background drop queue.\n", "InnoDB: Adding the table to the background drop queue.\n",
stderr); stderr);
row_add_table_to_background_drop_list(table); /* We return DB_SUCCESS to MySQL though the drop will
happen lazily later */
err = DB_SUCCESS; err = DB_SUCCESS;
} else {
/* The table is already in the background drop list */
err = DB_ERROR;
}
goto funct_exit; goto funct_exit;
} }
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
# Sligtly updated by Monty # Sligtly updated by Monty
# Cleaned up again by Matt # Cleaned up again by Matt
# Fixed by Sergei # Fixed by Sergei
# List of failed cases (--force) backported from 4.1 by Joerg
# :-) # :-)
#++ #++
...@@ -202,6 +203,7 @@ MYSQL_MANAGER_LOG=$MYSQL_TEST_DIR/var/log/manager.log ...@@ -202,6 +203,7 @@ MYSQL_MANAGER_LOG=$MYSQL_TEST_DIR/var/log/manager.log
MYSQL_MANAGER_USER=root MYSQL_MANAGER_USER=root
NO_SLAVE=0 NO_SLAVE=0
USER_TEST= USER_TEST=
FAILED_CASES=
EXTRA_MASTER_OPT="" EXTRA_MASTER_OPT=""
EXTRA_MYSQL_TEST_OPT="" EXTRA_MYSQL_TEST_OPT=""
...@@ -1333,7 +1335,7 @@ run_testcase () ...@@ -1333,7 +1335,7 @@ run_testcase ()
show_failed_diff $result_file show_failed_diff $result_file
$ECHO $ECHO
if [ x$FORCE != x1 ] ; then if [ x$FORCE != x1 ] ; then
$ECHO "Aborting. To continue, re-run with '--force'." $ECHO "Aborting: $tname failed. To continue, re-run with '--force'."
$ECHO $ECHO
if [ -z "$DO_GDB" ] && [ -z "$USE_RUNNING_SERVER" ] && [ -z "$DO_DDD" ] if [ -z "$DO_GDB" ] && [ -z "$USE_RUNNING_SERVER" ] && [ -z "$DO_DDD" ]
then then
...@@ -1342,7 +1344,7 @@ run_testcase () ...@@ -1342,7 +1344,7 @@ run_testcase ()
fi fi
exit 1 exit 1
fi fi
FAILED_CASES="$FAILED_CASES $tname"
if [ -z "$DO_GDB" ] && [ -z "$USE_RUNNING_SERVER" ] && [ -z "$DO_DDD" ] if [ -z "$DO_GDB" ] && [ -z "$USE_RUNNING_SERVER" ] && [ -z "$DO_DDD" ]
then then
mysql_restart mysql_restart
...@@ -1485,4 +1487,10 @@ $ECHO ...@@ -1485,4 +1487,10 @@ $ECHO
[ "$DO_GCOV" ] && gcov_collect # collect coverage information [ "$DO_GCOV" ] && gcov_collect # collect coverage information
[ "$DO_GPROF" ] && gprof_collect # collect coverage information [ "$DO_GPROF" ] && gprof_collect # collect coverage information
exit 0 if [ $TOT_FAIL -ne 0 ]; then
$ECHO "mysql-test-run: *** Failing the test(s):$FAILED_CASES"
$ECHO
exit 1
else
exit 0
fi
...@@ -291,3 +291,9 @@ trim(trailing 'foo' from 'foo') ...@@ -291,3 +291,9 @@ trim(trailing 'foo' from 'foo')
select trim(leading 'foo' from 'foo'); select trim(leading 'foo' from 'foo');
trim(leading 'foo' from 'foo') trim(leading 'foo' from 'foo')
select quote(ltrim(concat(' ', 'a')));
quote(ltrim(concat(' ', 'a')))
'a'
select quote(trim(concat(' ', 'a')));
quote(trim(concat(' ', 'a')))
'a'
...@@ -36,6 +36,28 @@ Grants for mysqltest_1@localhost ...@@ -36,6 +36,28 @@ Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' REQUIRE ISSUER 'MySQL AB' SUBJECT 'testsubject' CIPHER 'EDH-RSA-DES-CBC3-SHA' GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' REQUIRE ISSUER 'MySQL AB' SUBJECT 'testsubject' CIPHER 'EDH-RSA-DES-CBC3-SHA'
delete from mysql.user where user='mysqltest_1'; delete from mysql.user where user='mysqltest_1';
flush privileges; flush privileges;
delete from mysql.user where user='mysqltest_1';
flush privileges;
grant usage on *.* to mysqltest_1@localhost with max_queries_per_hour 10;
select * from mysql.user where user="mysqltest_1";
Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections
localhost mysqltest_1 N N N N N N N N N N N N N N N N N N N N N 10 0 0
show grants for mysqltest_1@localhost;
Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' WITH MAX_QUERIES_PER_HOUR 10
grant usage on *.* to mysqltest_1@localhost with max_updates_per_hour 20 max_connections_per_hour 30;
select * from mysql.user where user="mysqltest_1";
Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections
localhost mysqltest_1 N N N N N N N N N N N N N N N N N N N N N 10 20 30
show grants for mysqltest_1@localhost;
Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' WITH MAX_QUERIES_PER_HOUR 10 MAX_UPDATES_PER_HOUR 20 MAX_CONNECTIONS_PER_HOUR 30
flush privileges;
show grants for mysqltest_1@localhost;
Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' WITH MAX_QUERIES_PER_HOUR 10 MAX_UPDATES_PER_HOUR 20 MAX_CONNECTIONS_PER_HOUR 30
delete from mysql.user where user='mysqltest_1';
flush privileges;
grant CREATE TEMPORARY TABLES, LOCK TABLES on mysqltest.* to mysqltest_1@localhost; grant CREATE TEMPORARY TABLES, LOCK TABLES on mysqltest.* to mysqltest_1@localhost;
show grants for mysqltest_1@localhost; show grants for mysqltest_1@localhost;
Grants for mysqltest_1@localhost Grants for mysqltest_1@localhost
...@@ -156,3 +178,67 @@ select host,db,user,select_priv,insert_priv from mysql.db where db="db6123"; ...@@ -156,3 +178,67 @@ select host,db,user,select_priv,insert_priv from mysql.db where db="db6123";
host db user select_priv insert_priv host db user select_priv insert_priv
delete from mysql.user where user='test6123'; delete from mysql.user where user='test6123';
drop database db6123; drop database db6123;
create database mysqltest_1;
create database mysqltest_2;
create table mysqltest_1.t1 select 1 a, 2 q;
create table mysqltest_1.t2 select 1 b, 2 r;
create table mysqltest_2.t1 select 1 c, 2 s;
create table mysqltest_2.t2 select 1 d, 2 t;
grant update (a) on mysqltest_1.t1 to mysqltest_3@localhost;
grant select (b) on mysqltest_1.t2 to mysqltest_3@localhost;
grant select (c) on mysqltest_2.t1 to mysqltest_3@localhost;
grant update (d) on mysqltest_2.t2 to mysqltest_3@localhost;
show grants for mysqltest_3@localhost;
Grants for mysqltest_3@localhost
GRANT USAGE ON *.* TO 'mysqltest_3'@'localhost'
GRANT SELECT (b) ON `mysqltest_1`.`t2` TO 'mysqltest_3'@'localhost'
GRANT SELECT (c) ON `mysqltest_2`.`t1` TO 'mysqltest_3'@'localhost'
GRANT UPDATE (a) ON `mysqltest_1`.`t1` TO 'mysqltest_3'@'localhost'
GRANT UPDATE (d) ON `mysqltest_2`.`t2` TO 'mysqltest_3'@'localhost'
update mysqltest_1.t1, mysqltest_1.t2 set q=10 where b=1;
UPDATE command denied to user: 'mysqltest_3@localhost' for column 'q' in table 't1'
update mysqltest_1.t1, mysqltest_2.t2 set d=20 where d=1;
select command denied to user: 'mysqltest_3@localhost' for table 't1'
update mysqltest_2.t1, mysqltest_1.t2 set c=20 where b=1;
UPDATE command denied to user: 'mysqltest_3@localhost' for column 'c' in table 't1'
update mysqltest_2.t1, mysqltest_2.t2 set d=10 where s=2;
SELECT command denied to user: 'mysqltest_3@localhost' for column 's' in table 't1'
update mysqltest_1.t1, mysqltest_2.t2 set a=10,d=10;
update mysqltest_1.t1, mysqltest_2.t1 set a=20 where c=20;
select t1.*,t2.* from mysqltest_1.t1,mysqltest_1.t2;
a q b r
10 2 1 2
select t1.*,t2.* from mysqltest_2.t1,mysqltest_2.t2;
c s d t
1 2 10 2
revoke all on mysqltest_1.t1 from mysqltest_3@localhost;
revoke all on mysqltest_1.t2 from mysqltest_3@localhost;
revoke all on mysqltest_2.t1 from mysqltest_3@localhost;
revoke all on mysqltest_2.t2 from mysqltest_3@localhost;
grant all on mysqltest_2.* to mysqltest_3@localhost;
grant select on *.* to mysqltest_3@localhost;
flush privileges;
use mysqltest_1;
update mysqltest_2.t1, mysqltest_2.t2 set c=500,d=600;
update mysqltest_1.t1, mysqltest_1.t2 set a=100,b=200;
UPDATE command denied to user: 'mysqltest_3@localhost' for column 'a' in table 't1'
use mysqltest_2;
update mysqltest_1.t1, mysqltest_1.t2 set a=100,b=200;
Access denied for user: 'mysqltest_3@localhost' to database 'mysqltest_1'
update mysqltest_2.t1, mysqltest_1.t2 set c=100,b=200;
Access denied for user: 'mysqltest_3@localhost' to database 'mysqltest_1'
update mysqltest_1.t1, mysqltest_2.t2 set a=100,d=200;
Access denied for user: 'mysqltest_3@localhost' to database 'mysqltest_1'
select t1.*,t2.* from mysqltest_1.t1,mysqltest_1.t2;
a q b r
10 2 1 2
select t1.*,t2.* from mysqltest_2.t1,mysqltest_2.t2;
c s d t
500 2 600 2
delete from mysql.user where user='mysqltest_3';
delete from mysql.db where user="mysqltest_3";
delete from mysql.tables_priv where user="mysqltest_3";
delete from mysql.columns_priv where user="mysqltest_3";
flush privileges;
drop database mysqltest_1;
drop database mysqltest_2;
...@@ -203,3 +203,9 @@ colC colA colD colE colF ...@@ -203,3 +203,9 @@ colC colA colD colE colF
3 4433 10005 492 500 3 4433 10005 492 500
DROP TABLE t1; DROP TABLE t1;
DROP TABLE t2; DROP TABLE t2;
create table t1 (c1 int, c2 char(6), c3 int);
create table t2 (c1 int, c2 char(6));
insert into t1 values (1, "t1c2-1", 10), (2, "t1c2-2", 20);
update t1 left join t2 on t1.c1 = t2.c1 set t2.c2 = "t2c2-1";
update t1 left join t2 on t1.c1 = t2.c1 set t2.c2 = "t2c2-1" where t1.c3 = 10;
drop table t1, t2;
...@@ -185,3 +185,11 @@ drop table t1; ...@@ -185,3 +185,11 @@ drop table t1;
select trim(trailing 'foo' from 'foo'); select trim(trailing 'foo' from 'foo');
select trim(leading 'foo' from 'foo'); select trim(leading 'foo' from 'foo');
#
# crashing bug with QUOTE() and LTRIM() or TRIM() fixed
# Bug #7495
#
select quote(ltrim(concat(' ', 'a')));
select quote(trim(concat(' ', 'a')));
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
drop table if exists t1; drop table if exists t1;
--enable_warnings --enable_warnings
connect (master,localhost,root,,);
connection master;
# #
# Test that SSL options works properly # Test that SSL options works properly
# #
...@@ -25,6 +27,23 @@ show grants for mysqltest_1@localhost; ...@@ -25,6 +27,23 @@ show grants for mysqltest_1@localhost;
delete from mysql.user where user='mysqltest_1'; delete from mysql.user where user='mysqltest_1';
flush privileges; flush privileges;
#
# Test of GRANTS specifying user limits
#
delete from mysql.user where user='mysqltest_1';
flush privileges;
grant usage on *.* to mysqltest_1@localhost with max_queries_per_hour 10;
select * from mysql.user where user="mysqltest_1";
show grants for mysqltest_1@localhost;
grant usage on *.* to mysqltest_1@localhost with max_updates_per_hour 20 max_connections_per_hour 30;
select * from mysql.user where user="mysqltest_1";
show grants for mysqltest_1@localhost;
# This is just to double check that one won't ignore results of selects
flush privileges;
show grants for mysqltest_1@localhost;
delete from mysql.user where user='mysqltest_1';
flush privileges;
# #
# Test that the new db privileges are stored/retrieved correctly # Test that the new db privileges are stored/retrieved correctly
# #
...@@ -114,3 +133,73 @@ grant usage on db6123.* to test6123 identified by 'magic123'; ...@@ -114,3 +133,73 @@ grant usage on db6123.* to test6123 identified by 'magic123';
select host,db,user,select_priv,insert_priv from mysql.db where db="db6123"; select host,db,user,select_priv,insert_priv from mysql.db where db="db6123";
delete from mysql.user where user='test6123'; delete from mysql.user where user='test6123';
drop database db6123; drop database db6123;
#
# Bug#7391: Cross-database multi-table UPDATE security problem
#
create database mysqltest_1;
create database mysqltest_2;
create table mysqltest_1.t1 select 1 a, 2 q;
create table mysqltest_1.t2 select 1 b, 2 r;
create table mysqltest_2.t1 select 1 c, 2 s;
create table mysqltest_2.t2 select 1 d, 2 t;
#test the column privileges
grant update (a) on mysqltest_1.t1 to mysqltest_3@localhost;
grant select (b) on mysqltest_1.t2 to mysqltest_3@localhost;
grant select (c) on mysqltest_2.t1 to mysqltest_3@localhost;
grant update (d) on mysqltest_2.t2 to mysqltest_3@localhost;
connect (conn1,localhost,mysqltest_3,,);
connection conn1;
show grants for mysqltest_3@localhost;
--error 1143
update mysqltest_1.t1, mysqltest_1.t2 set q=10 where b=1;
--error 1142
update mysqltest_1.t1, mysqltest_2.t2 set d=20 where d=1;
--error 1143
update mysqltest_2.t1, mysqltest_1.t2 set c=20 where b=1;
--error 1143
update mysqltest_2.t1, mysqltest_2.t2 set d=10 where s=2;
#the following two should work
update mysqltest_1.t1, mysqltest_2.t2 set a=10,d=10;
update mysqltest_1.t1, mysqltest_2.t1 set a=20 where c=20;
connection master;
select t1.*,t2.* from mysqltest_1.t1,mysqltest_1.t2;
select t1.*,t2.* from mysqltest_2.t1,mysqltest_2.t2;
revoke all on mysqltest_1.t1 from mysqltest_3@localhost;
revoke all on mysqltest_1.t2 from mysqltest_3@localhost;
revoke all on mysqltest_2.t1 from mysqltest_3@localhost;
revoke all on mysqltest_2.t2 from mysqltest_3@localhost;
#test the db/table level privileges
grant all on mysqltest_2.* to mysqltest_3@localhost;
grant select on *.* to mysqltest_3@localhost;
flush privileges;
disconnect conn1;
connect (conn2,localhost,mysqltest_3,,);
connection conn2;
use mysqltest_1;
update mysqltest_2.t1, mysqltest_2.t2 set c=500,d=600;
# the following failed before, should fail now.
--error 1143
update mysqltest_1.t1, mysqltest_1.t2 set a=100,b=200;
use mysqltest_2;
#the following used to succeed, it must fail now.
--error 1044
update mysqltest_1.t1, mysqltest_1.t2 set a=100,b=200;
--error 1044
update mysqltest_2.t1, mysqltest_1.t2 set c=100,b=200;
--error 1044
update mysqltest_1.t1, mysqltest_2.t2 set a=100,d=200;
#lets see the result
connection master;
select t1.*,t2.* from mysqltest_1.t1,mysqltest_1.t2;
select t1.*,t2.* from mysqltest_2.t1,mysqltest_2.t2;
delete from mysql.user where user='mysqltest_3';
delete from mysql.db where user="mysqltest_3";
delete from mysql.tables_priv where user="mysqltest_3";
delete from mysql.columns_priv where user="mysqltest_3";
flush privileges;
drop database mysqltest_1;
drop database mysqltest_2;
...@@ -155,3 +155,12 @@ SELECT * FROM t2; ...@@ -155,3 +155,12 @@ SELECT * FROM t2;
DROP TABLE t1; DROP TABLE t1;
DROP TABLE t2; DROP TABLE t2;
#
# Bug #6054
#
create table t1 (c1 int, c2 char(6), c3 int);
create table t2 (c1 int, c2 char(6));
insert into t1 values (1, "t1c2-1", 10), (2, "t1c2-2", 20);
update t1 left join t2 on t1.c1 = t2.c1 set t2.c2 = "t2c2-1";
update t1 left join t2 on t1.c1 = t2.c1 set t2.c2 = "t2c2-1" where t1.c3 = 10;
drop table t1, t2;
...@@ -4702,7 +4702,8 @@ ha_innobase::external_lock( ...@@ -4702,7 +4702,8 @@ ha_innobase::external_lock(
if (prebuilt->select_lock_type != LOCK_NONE) { if (prebuilt->select_lock_type != LOCK_NONE) {
if (thd->in_lock_tables && if (thd->in_lock_tables &&
thd->variables.innodb_table_locks) { thd->variables.innodb_table_locks &&
(thd->options & OPTION_NOT_AUTOCOMMIT)) {
ulint error; ulint error;
error = row_lock_table_for_mysql(prebuilt); error = row_lock_table_for_mysql(prebuilt);
......
...@@ -2185,16 +2185,16 @@ String *Item_func_quote::val_str(String *str) ...@@ -2185,16 +2185,16 @@ String *Item_func_quote::val_str(String *str)
/* /*
We have to use realloc() instead of alloc() as we want to keep the We have to use realloc() instead of alloc() as we want to keep the
old result in str old result in arg
*/ */
if (str->realloc(new_length)) if (arg->realloc(new_length))
goto null; goto null;
/* /*
As 'arg' and 'str' may be the same string, we must replace characters As 'arg' and 'str' may be the same string, we must replace characters
from the end to the beginning from the end to the beginning
*/ */
to= (char*) str->ptr() + new_length - 1; to= (char*) arg->ptr() + new_length - 1;
*to--= '\''; *to--= '\'';
for (start= (char*) arg->ptr(),end= start + arg_length; end-- != start; to--) for (start= (char*) arg->ptr(),end= start + arg_length; end-- != start; to--)
{ {
...@@ -2222,9 +2222,9 @@ String *Item_func_quote::val_str(String *str) ...@@ -2222,9 +2222,9 @@ String *Item_func_quote::val_str(String *str)
} }
} }
*to= '\''; *to= '\'';
str->length(new_length); arg->length(new_length);
null_value= 0; null_value= 0;
return str; return arg;
null: null:
null_value= 1; null_value= 1;
......
...@@ -107,15 +107,6 @@ extern "C" { // Because of SCO 3.2V4.2 ...@@ -107,15 +107,6 @@ extern "C" { // Because of SCO 3.2V4.2
int allow_severity = LOG_INFO; int allow_severity = LOG_INFO;
int deny_severity = LOG_WARNING; int deny_severity = LOG_WARNING;
#ifdef __STDC__
#define my_fromhost(A) fromhost(A)
#define my_hosts_access(A) hosts_access(A)
#define my_eval_client(A) eval_client(A)
#else
#define my_fromhost(A) fromhost()
#define my_hosts_access(A) hosts_access()
#define my_eval_client(A) eval_client()
#endif
#endif /* HAVE_LIBWRAP */ #endif /* HAVE_LIBWRAP */
#ifdef HAVE_SYS_MMAN_H #ifdef HAVE_SYS_MMAN_H
...@@ -3240,8 +3231,8 @@ extern "C" pthread_handler_decl(handle_connections_sockets, ...@@ -3240,8 +3231,8 @@ extern "C" pthread_handler_decl(handle_connections_sockets,
struct request_info req; struct request_info req;
signal(SIGCHLD, SIG_DFL); signal(SIGCHLD, SIG_DFL);
request_init(&req, RQ_DAEMON, libwrapName, RQ_FILE, new_sock, NULL); request_init(&req, RQ_DAEMON, libwrapName, RQ_FILE, new_sock, NULL);
my_fromhost(&req); fromhost(&req);
if (!my_hosts_access(&req)) if (!hosts_access(&req))
{ {
/* /*
This may be stupid but refuse() includes an exit(0) This may be stupid but refuse() includes an exit(0)
...@@ -3249,7 +3240,7 @@ extern "C" pthread_handler_decl(handle_connections_sockets, ...@@ -3249,7 +3240,7 @@ extern "C" pthread_handler_decl(handle_connections_sockets,
clean_exit() - same stupid thing ... clean_exit() - same stupid thing ...
*/ */
syslog(deny_severity, "refused connect from %s", syslog(deny_severity, "refused connect from %s",
my_eval_client(&req)); eval_client(&req));
/* /*
C++ sucks (the gibberish in front just translates the supplied C++ sucks (the gibberish in front just translates the supplied
......
...@@ -1403,6 +1403,7 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo, ...@@ -1403,6 +1403,7 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
Field **tmp_field; Field **tmp_field;
ulong priv; ulong priv;
uint next_field;
for (tmp_field= table->field+3, priv = SELECT_ACL; for (tmp_field= table->field+3, priv = SELECT_ACL;
*tmp_field && (*tmp_field)->real_type() == FIELD_TYPE_ENUM && *tmp_field && (*tmp_field)->real_type() == FIELD_TYPE_ENUM &&
((Field_enum*) (*tmp_field))->typelib->count == 2 ; ((Field_enum*) (*tmp_field))->typelib->count == 2 ;
...@@ -1411,56 +1412,59 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo, ...@@ -1411,56 +1412,59 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
if (priv & rights) // set requested privileges if (priv & rights) // set requested privileges
(*tmp_field)->store(&what,1); (*tmp_field)->store(&what,1);
} }
rights=get_access(table,3,0); rights= get_access(table, 3, &next_field);
DBUG_PRINT("info",("table->fields: %d",table->fields)); DBUG_PRINT("info",("table->fields: %d",table->fields));
if (table->fields >= 31) /* From 4.0.0 we have more fields */ if (table->fields >= 31) /* From 4.0.0 we have more fields */
{ {
/* We write down SSL related ACL stuff */ /* We write down SSL related ACL stuff */
switch (thd->lex.ssl_type) { switch (thd->lex.ssl_type) {
case SSL_TYPE_ANY: case SSL_TYPE_ANY:
table->field[24]->store("ANY",3); table->field[next_field]->store("ANY", 3);
table->field[25]->store("",0); table->field[next_field+1]->store("", 0);
table->field[26]->store("",0); table->field[next_field+2]->store("", 0);
table->field[27]->store("",0); table->field[next_field+3]->store("", 0);
break; break;
case SSL_TYPE_X509: case SSL_TYPE_X509:
table->field[24]->store("X509",4); table->field[next_field]->store("X509", 4);
table->field[25]->store("",0); table->field[next_field+1]->store("", 0);
table->field[26]->store("",0); table->field[next_field+2]->store("", 0);
table->field[27]->store("",0); table->field[next_field+3]->store("", 0);
break; break;
case SSL_TYPE_SPECIFIED: case SSL_TYPE_SPECIFIED:
table->field[24]->store("SPECIFIED",9); table->field[next_field]->store("SPECIFIED", 9);
table->field[25]->store("",0); table->field[next_field+1]->store("", 0);
table->field[26]->store("",0); table->field[next_field+2]->store("", 0);
table->field[27]->store("",0); table->field[next_field+3]->store("", 0);
if (thd->lex.ssl_cipher) if (thd->lex.ssl_cipher)
table->field[25]->store(thd->lex.ssl_cipher, table->field[next_field+1]->store(thd->lex.ssl_cipher,
strlen(thd->lex.ssl_cipher)); strlen(thd->lex.ssl_cipher));
if (thd->lex.x509_issuer) if (thd->lex.x509_issuer)
table->field[26]->store(thd->lex.x509_issuer, table->field[next_field+2]->store(thd->lex.x509_issuer,
strlen(thd->lex.x509_issuer)); strlen(thd->lex.x509_issuer));
if (thd->lex.x509_subject) if (thd->lex.x509_subject)
table->field[27]->store(thd->lex.x509_subject, table->field[next_field+3]->store(thd->lex.x509_subject,
strlen(thd->lex.x509_subject)); strlen(thd->lex.x509_subject));
break; break;
case SSL_TYPE_NOT_SPECIFIED: case SSL_TYPE_NOT_SPECIFIED:
break; break;
case SSL_TYPE_NONE: case SSL_TYPE_NONE:
table->field[24]->store("",0); table->field[next_field]->store("", 0);
table->field[25]->store("",0); table->field[next_field+1]->store("", 0);
table->field[26]->store("",0); table->field[next_field+2]->store("", 0);
table->field[27]->store("",0); table->field[next_field+3]->store("", 0);
break; break;
} }
/* Skip over SSL related fields to first user limits related field */
next_field+= 4;
USER_RESOURCES mqh = thd->lex.mqh; USER_RESOURCES mqh = thd->lex.mqh;
if (mqh.bits & 1) if (mqh.bits & 1)
table->field[28]->store((longlong) mqh.questions); table->field[next_field]->store((longlong) mqh.questions);
if (mqh.bits & 2) if (mqh.bits & 2)
table->field[29]->store((longlong) mqh.updates); table->field[next_field+1]->store((longlong) mqh.updates);
if (mqh.bits & 4) if (mqh.bits & 4)
table->field[30]->store((longlong) mqh.connections); table->field[next_field+2]->store((longlong) mqh.connections);
mqh_used = mqh_used || mqh.questions || mqh.updates || mqh.connections; mqh_used = mqh_used || mqh.questions || mqh.updates || mqh.connections;
} }
if (old_row_exists) if (old_row_exists)
......
...@@ -4951,10 +4951,7 @@ join_read_system(JOIN_TAB *tab) ...@@ -4951,10 +4951,7 @@ join_read_system(JOIN_TAB *tab)
table->file->print_error(error,MYF(0)); table->file->print_error(error,MYF(0));
return 1; return 1;
} }
if (tab->on_expr) mark_as_null_row(tab->table);
mark_as_null_row(tab->table);
else
table->null_row=1; // Why do this for inner join?
empty_record(table); // Make empty record empty_record(table); // Make empty record
return -1; return -1;
} }
...@@ -4984,10 +4981,7 @@ join_read_const(JOIN_TAB *tab) ...@@ -4984,10 +4981,7 @@ join_read_const(JOIN_TAB *tab)
} }
if (error) if (error)
{ {
if (tab->on_expr) mark_as_null_row(tab->table);
mark_as_null_row(tab->table);
else
table->null_row=1;
empty_record(table); empty_record(table);
if (error != HA_ERR_KEY_NOT_FOUND) if (error != HA_ERR_KEY_NOT_FOUND)
{ {
......
...@@ -465,21 +465,34 @@ int mysql_multi_update(THD *thd, ...@@ -465,21 +465,34 @@ int mysql_multi_update(THD *thd,
*/ */
for (tl= table_list ; tl ; tl=tl->next) for (tl= table_list ; tl ; tl=tl->next)
{ {
TABLE_LIST *save= tl->next;
TABLE *table= tl->table; TABLE *table= tl->table;
uint wants;
tl->next= 0;
if (update_map & table->map) if (update_map & table->map)
{ {
DBUG_PRINT("info",("setting table `%s` for update", tl->alias)); DBUG_PRINT("info",("setting table `%s` for update", tl->alias));
tl->lock_type= thd->lex.lock_option; tl->lock_type= thd->lex.lock_option;
tl->updating= 1; tl->updating= 1;
wants= UPDATE_ACL;
} }
else else
{ {
DBUG_PRINT("info",("setting table `%s` for read-only", tl->alias)); DBUG_PRINT("info",("setting table `%s` for read-only", tl->alias));
tl->lock_type= TL_READ; tl->lock_type= TL_READ;
tl->updating= 0; tl->updating= 0;
wants= SELECT_ACL;
} }
if (!using_lock_tables) if (!using_lock_tables)
tl->table->reginfo.lock_type= tl->lock_type; tl->table->reginfo.lock_type= tl->lock_type;
if (check_access(thd, wants, tl->db, &tl->grant.privilege, 0, 0) ||
(grant_option && check_grant(thd, wants, tl, 0, 0)))
{
tl->next= save;
DBUG_RETURN(0);
}
tl->next= save;
} }
/* Relock the tables with the correct modes */ /* Relock the tables with the correct modes */
......
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