Commit a0826252 authored by unknown's avatar unknown

5.0 -> 5.1 merge


configure.in:
  Auto merged
mysql-test/lib/mtr_timer.pl:
  Auto merged
mysql-test/r/information_schema.result:
  Auto merged
mysql-test/r/information_schema_db.result:
  Auto merged
mysql-test/r/query_cache_notembedded.result:
  Auto merged
mysql-test/t/information_schema.test:
  Auto merged
mysql-test/t/query_cache_notembedded.test:
  Auto merged
scripts/make_binary_distribution.sh:
  Auto merged
sql/sql_acl.cc:
  Auto merged
sql/sql_parse.cc:
  Auto merged
sql/sql_show.cc:
  Auto merged
sql/sql_yacc.yy:
  Auto merged
storage/ndb/src/kernel/blocks/backup/Backup.cpp:
  Auto merged
sql/ha_innodb.cc:
  manual merge
sql/sql_insert.cc:
  manual merge
parents 573ee9ca e10ec04a
...@@ -294,6 +294,13 @@ sub1 sub1 ...@@ -294,6 +294,13 @@ sub1 sub1
select count(*) from information_schema.ROUTINES; select count(*) from information_schema.ROUTINES;
count(*) count(*)
2 2
create view v1 as select routine_schema, routine_name from information_schema.routines
order by routine_schema, routine_name;
select * from v1;
routine_schema routine_name
test sel2
test sub1
drop view v1;
select ROUTINE_NAME, ROUTINE_DEFINITION from information_schema.ROUTINES; select ROUTINE_NAME, ROUTINE_DEFINITION from information_schema.ROUTINES;
ROUTINE_NAME ROUTINE_DEFINITION ROUTINE_NAME ROUTINE_DEFINITION
show create function sub1; show create function sub1;
......
...@@ -33,4 +33,18 @@ create database `inf%`; ...@@ -33,4 +33,18 @@ create database `inf%`;
use `inf%`; use `inf%`;
show tables; show tables;
Tables_in_inf% Tables_in_inf%
grant all privileges on `inf%`.* to 'mysqltest_1'@'localhost';
create table t1 (f1 int);
create function func1(curr_int int) returns int
begin
declare ret_val int;
select max(f1) from t1 into ret_val;
return ret_val;
end|
create view v1 as select f1 from t1 where f1 = func1(f1);
select * from information_schema.tables;
drop user mysqltest_1@localhost;
drop view v1;
drop function func1;
drop table t1;
drop database `inf%`; drop database `inf%`;
...@@ -314,4 +314,34 @@ drop procedure f2; ...@@ -314,4 +314,34 @@ drop procedure f2;
drop procedure f3; drop procedure f3;
drop procedure f4; drop procedure f4;
drop table t1; drop table t1;
reset query cache;
drop function if exists f1;
create table t1 (id int);
create function f1 ()
returns int
begin
declare i_var int;
set i_var = sleep(3);
insert into t1 values(3);
set i_var = sleep(3);
return 0;
end;|
select f1();
select sleep(4);
sleep(4)
0
select * from t1;
id
3
f1()
0
select * from t1;
id
3
reset query cache;
select * from t1;
id
3
drop table t1;
drop function f1;
set GLOBAL query_cache_size=0; set GLOBAL query_cache_size=0;
...@@ -146,6 +146,11 @@ select a.ROUTINE_NAME, b.name from information_schema.ROUTINES a, ...@@ -146,6 +146,11 @@ select a.ROUTINE_NAME, b.name from information_schema.ROUTINES a,
mysql.proc b where a.ROUTINE_NAME = convert(b.name using utf8) order by 1; mysql.proc b where a.ROUTINE_NAME = convert(b.name using utf8) order by 1;
select count(*) from information_schema.ROUTINES; select count(*) from information_schema.ROUTINES;
create view v1 as select routine_schema, routine_name from information_schema.routines
order by routine_schema, routine_name;
select * from v1;
drop view v1;
connect (user1,localhost,mysqltest_1,,); connect (user1,localhost,mysqltest_1,,);
connection user1; connection user1;
select ROUTINE_NAME, ROUTINE_DEFINITION from information_schema.ROUTINES; select ROUTINE_NAME, ROUTINE_DEFINITION from information_schema.ROUTINES;
......
...@@ -8,4 +8,35 @@ show tables from INFORMATION_SCHEMA like 'T%'; ...@@ -8,4 +8,35 @@ show tables from INFORMATION_SCHEMA like 'T%';
create database `inf%`; create database `inf%`;
use `inf%`; use `inf%`;
show tables; show tables;
#
# Bug#18113 SELECT * FROM information_schema.xxx crashes server
# Crash happened when one selected data from one of INFORMATION_SCHEMA
# tables and in order to build its contents server had to open view which
# used stored function and table or view on which one had not global or
# database-level privileges (e.g. had only table-level or had no
# privileges at all).
#
grant all privileges on `inf%`.* to 'mysqltest_1'@'localhost';
create table t1 (f1 int);
delimiter |;
create function func1(curr_int int) returns int
begin
declare ret_val int;
select max(f1) from t1 into ret_val;
return ret_val;
end|
delimiter ;|
create view v1 as select f1 from t1 where f1 = func1(f1);
connect (user1,localhost,mysqltest_1,,);
connection user1;
--disable_result_log
select * from information_schema.tables;
--enable_result_log
connection default;
drop user mysqltest_1@localhost;
drop view v1;
drop function func1;
drop table t1;
drop database `inf%`; drop database `inf%`;
...@@ -180,5 +180,45 @@ drop procedure f3; ...@@ -180,5 +180,45 @@ drop procedure f3;
drop procedure f4; drop procedure f4;
drop table t1; drop table t1;
#
# bug#14767: INSERT in SF + concurrent SELECT with query cache
#
reset query cache;
--disable_warnings
drop function if exists f1;
--enable_warnings
create table t1 (id int);
delimiter |;
create function f1 ()
returns int
begin
declare i_var int;
set i_var = sleep(3);
insert into t1 values(3);
set i_var = sleep(3);
return 0;
end;|
delimiter ;|
connect (con1,localhost,root,,);
connect (con2,localhost,root,,);
connection con1;
send select f1();
connection con2;
select sleep(4);
select * from t1;
connection con1;
reap;
connection con2;
# This gives wrong result i.e. 't' table seems to be empty
select * from t1;
reset query cache;
select * from t1;
drop table t1;
drop function f1;
disconnect con1;
disconnect con2;
connection default;
set GLOBAL query_cache_size=0; set GLOBAL query_cache_size=0;
...@@ -534,16 +534,23 @@ convert_error_code_to_mysql( ...@@ -534,16 +534,23 @@ convert_error_code_to_mysql(
} else if (error == (int) DB_CORRUPTION) { } else if (error == (int) DB_CORRUPTION) {
return(HA_ERR_CRASHED); return(HA_ERR_CRASHED);
} else if (error == (int) DB_NO_SAVEPOINT) { } else if (error == (int) DB_NO_SAVEPOINT) {
return(HA_ERR_NO_SAVEPOINT); return(HA_ERR_NO_SAVEPOINT);
} else if (error == (int) DB_LOCK_TABLE_FULL) { } else if (error == (int) DB_LOCK_TABLE_FULL) {
/* Since we rolled back the whole transaction, we must
tell it also to MySQL so that MySQL knows to empty the
cached binlog for this transaction */
return(HA_ERR_LOCK_TABLE_FULL); if (thd) {
} else { ha_rollback(thd);
return(-1); // Unknown error }
}
return(HA_ERR_LOCK_TABLE_FULL);
} else {
return(-1); // Unknown error
}
} }
/***************************************************************** /*****************************************************************
...@@ -6950,25 +6957,25 @@ ha_innobase::store_lock( ...@@ -6950,25 +6957,25 @@ ha_innobase::store_lock(
} }
/* If we are not doing a LOCK TABLE, DISCARD/IMPORT /* If we are not doing a LOCK TABLE, DISCARD/IMPORT
TABLESPACE or TRUNCATE TABLE then allow multiple TABLESPACE or TRUNCATE TABLE then allow multiple
writers. Note that ALTER TABLE uses a TL_WRITE_ALLOW_READ writers. Note that ALTER TABLE uses a TL_WRITE_ALLOW_READ
< TL_WRITE_CONCURRENT_INSERT. < TL_WRITE_CONCURRENT_INSERT.
We especially allow multiple writers if MySQL is at the We especially allow multiple writers if MySQL is at the
start of a stored procedure call (SQLCOM_CALL) start of a stored procedure call (SQLCOM_CALL)
(MySQL does have thd->in_lock_tables TRUE there). */ (MySQL does have thd->in_lock_tables TRUE there). */
if ((lock_type >= TL_WRITE_CONCURRENT_INSERT if ((lock_type >= TL_WRITE_CONCURRENT_INSERT
&& lock_type <= TL_WRITE) && lock_type <= TL_WRITE)
&& (!thd->in_lock_tables && !(thd->in_lock_tables
|| thd->lex->sql_command == SQLCOM_CALL) && thd->lex->sql_command == SQLCOM_LOCK_TABLES)
&& !thd->tablespace_op && !thd->tablespace_op
&& thd->lex->sql_command != SQLCOM_TRUNCATE && thd->lex->sql_command != SQLCOM_TRUNCATE
&& thd->lex->sql_command != SQLCOM_OPTIMIZE && thd->lex->sql_command != SQLCOM_OPTIMIZE
&& thd->lex->sql_command != SQLCOM_CREATE_TABLE) { && thd->lex->sql_command != SQLCOM_CREATE_TABLE) {
lock_type = TL_WRITE_ALLOW_WRITE; lock_type = TL_WRITE_ALLOW_WRITE;
} }
/* In queries of type INSERT INTO t1 SELECT ... FROM t2 ... /* In queries of type INSERT INTO t1 SELECT ... FROM t2 ...
MySQL would use the lock TL_READ_NO_INSERT on t2, and that MySQL would use the lock TL_READ_NO_INSERT on t2, and that
......
...@@ -3668,6 +3668,13 @@ my_bool grant_reload(THD *thd) ...@@ -3668,6 +3668,13 @@ my_bool grant_reload(THD *thd)
RETURN RETURN
0 ok 0 ok
1 Error: User did not have the requested privileges 1 Error: User did not have the requested privileges
NOTE
This functions assumes that either number of tables to be inspected
by it is limited explicitly (i.e. is is not UINT_MAX) or table list
used and thd->lex->query_tables_own_last value correspond to each
other (the latter should be either 0 or point to next_global member
of one of elements of this table list).
****************************************************************************/ ****************************************************************************/
bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
......
...@@ -272,6 +272,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, ...@@ -272,6 +272,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
bool log_on= (thd->options & OPTION_BIN_LOG) || bool log_on= (thd->options & OPTION_BIN_LOG) ||
(!(thd->security_ctx->master_access & SUPER_ACL)); (!(thd->security_ctx->master_access & SUPER_ACL));
bool transactional_table, joins_freed= FALSE; bool transactional_table, joins_freed= FALSE;
bool changed;
uint value_count; uint value_count;
ulong counter = 1; ulong counter = 1;
ulonglong id; ulonglong id;
...@@ -558,35 +559,33 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, ...@@ -558,35 +559,33 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
else if (table->next_number_field && info.copied) else if (table->next_number_field && info.copied)
id=table->next_number_field->val_int(); // Return auto_increment value id=table->next_number_field->val_int(); // Return auto_increment value
/*
Invalidate the table in the query cache if something changed.
For the transactional algorithm to work the invalidation must be
before binlog writing and ha_autocommit_or_rollback
*/
if (info.copied || info.deleted || info.updated)
{
query_cache_invalidate3(thd, table_list, 1);
}
transactional_table= table->file->has_transactions(); transactional_table= table->file->has_transactions();
if ((info.copied || info.deleted || info.updated) && if ((changed= (info.copied || info.deleted || info.updated)))
(error <= 0 || !transactional_table))
{ {
if (mysql_bin_log.is_open()) /*
Invalidate the table in the query cache if something changed.
For the transactional algorithm to work the invalidation must be
before binlog writing and ha_autocommit_or_rollback
*/
query_cache_invalidate3(thd, table_list, 1);
if (error <= 0 || !transactional_table)
{ {
if (error <= 0) if (mysql_bin_log.is_open())
thd->clear_error();
if (thd->binlog_query(THD::ROW_QUERY_TYPE,
thd->query, thd->query_length,
transactional_table, FALSE) &&
transactional_table)
{ {
error=1; if (error <= 0)
thd->clear_error();
if (thd->binlog_query(THD::ROW_QUERY_TYPE,
thd->query, thd->query_length,
transactional_table, FALSE) &&
transactional_table)
{
error=1;
}
} }
if (!transactional_table)
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
} }
if (!transactional_table)
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
} }
if (transactional_table) if (transactional_table)
error=ha_autocommit_or_rollback(thd,error); error=ha_autocommit_or_rollback(thd,error);
...@@ -594,6 +593,16 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, ...@@ -594,6 +593,16 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
if (thd->lock) if (thd->lock)
{ {
mysql_unlock_tables(thd, thd->lock); mysql_unlock_tables(thd, thd->lock);
/*
Invalidate the table in the query cache if something changed
after unlocking when changes become fisible.
TODO: this is workaround. right way will be move invalidating in
the unlock procedure.
*/
if (lock_type == TL_WRITE_CONCURRENT_INSERT && changed)
{
query_cache_invalidate3(thd, table_list, 1);
}
thd->lock=0; thd->lock=0;
} }
} }
......
...@@ -3351,6 +3351,19 @@ mysql_execute_command(THD *thd) ...@@ -3351,6 +3351,19 @@ mysql_execute_command(THD *thd)
select_lex->context.table_list= select_lex->context.table_list=
select_lex->context.first_name_resolution_table= second_table; select_lex->context.first_name_resolution_table= second_table;
res= handle_select(thd, lex, result, OPTION_SETUP_TABLES_DONE); res= handle_select(thd, lex, result, OPTION_SETUP_TABLES_DONE);
/*
Invalidate the table in the query cache if something changed
after unlocking when changes become visible.
TODO: this is workaround. right way will be move invalidating in
the unlock procedure.
*/
if (first_table->lock_type == TL_WRITE_CONCURRENT_INSERT &&
thd->lock)
{
mysql_unlock_tables(thd, thd->lock);
query_cache_invalidate3(thd, first_table, 1);
thd->lock=0;
}
delete result; delete result;
} }
/* revert changes for SP */ /* revert changes for SP */
......
...@@ -476,7 +476,7 @@ mysql_find_files(THD *thd,List<char> *files, const char *db,const char *path, ...@@ -476,7 +476,7 @@ mysql_find_files(THD *thd,List<char> *files, const char *db,const char *path,
table_list.table_name= file->name; table_list.table_name= file->name;
table_list.table_name_length= strlen(file->name); table_list.table_name_length= strlen(file->name);
table_list.grant.privilege=col_access; table_list.grant.privilege=col_access;
if (check_grant(thd, TABLE_ACLS, &table_list, 1, UINT_MAX, 1)) if (check_grant(thd, TABLE_ACLS, &table_list, 1, 1, 1))
continue; continue;
} }
#endif #endif
...@@ -4664,7 +4664,8 @@ bool get_schema_tables_result(JOIN *join) ...@@ -4664,7 +4664,8 @@ bool get_schema_tables_result(JOIN *join)
TABLE_LIST *table_list= tab->table->pos_in_table_list; TABLE_LIST *table_list= tab->table->pos_in_table_list;
if (table_list->schema_table && thd->fill_derived_tables()) if (table_list->schema_table && thd->fill_derived_tables())
{ {
bool is_subselect= (&lex->unit != lex->current_select->master_unit()); bool is_subselect= (&lex->unit != lex->current_select->master_unit() &&
lex->current_select->master_unit()->item);
/* /*
The schema table is already processed and The schema table is already processed and
the statement is not a subselect. the statement is not a subselect.
......
...@@ -7821,7 +7821,19 @@ replace: ...@@ -7821,7 +7821,19 @@ replace:
; ;
insert_lock_option: insert_lock_option:
/* empty */ { $$= TL_WRITE_CONCURRENT_INSERT; } /* empty */
{
#ifdef HAVE_QUERY_CACHE
/*
If it is SP we do not allow insert optimisation whan result of
insert visible only after the table unlocking but everyone can
read table.
*/
$$= (Lex->sphead ? TL_WRITE :TL_WRITE_CONCURRENT_INSERT);
#else
$$= TL_WRITE_CONCURRENT_INSERT;
#endif
}
| LOW_PRIORITY { $$= TL_WRITE_LOW_PRIORITY; } | LOW_PRIORITY { $$= TL_WRITE_LOW_PRIORITY; }
| DELAYED_SYM { $$= TL_WRITE_DELAYED; } | DELAYED_SYM { $$= TL_WRITE_DELAYED; }
| HIGH_PRIORITY { $$= TL_WRITE; } | HIGH_PRIORITY { $$= TL_WRITE; }
...@@ -8740,7 +8752,16 @@ opt_local: ...@@ -8740,7 +8752,16 @@ opt_local:
load_data_lock: load_data_lock:
/* empty */ { $$= YYTHD->update_lock_default; } /* empty */ { $$= YYTHD->update_lock_default; }
| CONCURRENT { $$= TL_WRITE_CONCURRENT_INSERT ; } | CONCURRENT
{
#ifdef HAVE_QUERY_CACHE
/*
Ignore this option in SP to avoid problem with query cache
*/
if (Lex->sphead != 0)
#endif
$$= TL_WRITE_CONCURRENT_INSERT;
}
| LOW_PRIORITY { $$= TL_WRITE_LOW_PRIORITY; }; | LOW_PRIORITY { $$= TL_WRITE_LOW_PRIORITY; };
......
...@@ -560,14 +560,20 @@ int vio_close_shared_memory(Vio * vio) ...@@ -560,14 +560,20 @@ int vio_close_shared_memory(Vio * vio)
Close all handlers. UnmapViewOfFile and CloseHandle return non-zero Close all handlers. UnmapViewOfFile and CloseHandle return non-zero
result if they are success. result if they are success.
*/ */
r= UnmapViewOfFile(vio->handle_map) || CloseHandle(vio->event_server_wrote) || if (UnmapViewOfFile(vio->handle_map) == 0)
CloseHandle(vio->event_server_read) || CloseHandle(vio->event_client_wrote) || DBUG_PRINT("vio_error", ("UnmapViewOfFile() failed"));
CloseHandle(vio->event_client_read) || CloseHandle(vio->handle_file_map); if (CloseHandle(vio->event_server_wrote) == 0)
if (!r) DBUG_PRINT("vio_error", ("CloseHandle(vio->esw) failed"));
{ if (CloseHandle(vio->event_server_read) == 0)
DBUG_PRINT("vio_error", ("close() failed, error: %d",r)); DBUG_PRINT("vio_error", ("CloseHandle(vio->esr) failed"));
/* FIXME: error handling (not critical for MySQL) */ if (CloseHandle(vio->event_client_wrote) == 0)
} DBUG_PRINT("vio_error", ("CloseHandle(vio->ecw) failed"));
if (CloseHandle(vio->event_client_read) == 0)
DBUG_PRINT("vio_error", ("CloseHandle(vio->ecr) failed"));
if (CloseHandle(vio->handle_file_map) == 0)
DBUG_PRINT("vio_error", ("CloseHandle(vio->hfm) failed"));
if (CloseHandle(vio->event_conn_closed) == 0)
DBUG_PRINT("vio_error", ("CloseHandle(vio->ecc) failed"));
} }
vio->type= VIO_CLOSED; vio->type= VIO_CLOSED;
vio->sd= -1; vio->sd= -1;
......
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