From 3764875ca6fa16865f865ba9a643ac394c21217e Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 13 Sep 2005 16:07:38 +0500 Subject: [PATCH 1/7] Bug#9683 INFORMATION_SCH: Creation of temporary table allowed in Information_schema DB Bug#9846 Inappropriate error displayed while dropping table from 'INFORMATION_SCHEMA' Bug#10734 Grant of privileges other than 'select' and 'create view' should fail on schema Bug#10708 SP's can use INFORMATION_SCHEMA as ROUTINE_SCHEMA cumulative fix for bugs above(after review, 2nd version) added privilege check for information schema db & tables --- mysql-test/r/information_schema.result | 24 ++++- mysql-test/t/information_schema.test | 38 ++++++- sql/mysql_priv.h | 4 +- sql/repl_failsafe.cc | 2 +- sql/sql_acl.cc | 10 +- sql/sql_parse.cc | 132 +++++++++++++++++-------- sql/sql_prepare.cc | 2 +- sql/sql_repl.cc | 4 +- sql/sql_show.cc | 13 +-- sql/sql_update.cc | 3 +- sql/sql_view.cc | 6 +- 11 files changed, 172 insertions(+), 66 deletions(-) diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index 9a7a0b48f47..e2812283901 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -594,7 +594,7 @@ TABLE_CONSTRAINTS TABLE_PRIVILEGES TRIGGERS create database information_schema; -ERROR HY000: Can't create database 'information_schema'; database exists +ERROR 42000: Access denied for user 'root'@'localhost' to database 'information_schema' use information_schema; show full tables like "T%"; Tables_in_information_schema (T%) Table_type @@ -990,3 +990,25 @@ Field Type Null Key Default Extra c int(11) YES NULL drop view v1; drop table t1; +alter database information_schema; +ERROR 42000: Access denied for user 'root'@'localhost' to database 'information_schema' +drop database information_schema; +ERROR 42000: Access denied for user 'root'@'localhost' to database 'information_schema' +drop table information_schema.tables; +ERROR 42000: Access denied for user 'root'@'localhost' to database 'information_schema' +alter table information_schema.tables; +ERROR 42000: Access denied for user 'root'@'localhost' to database 'information_schema' +use information_schema; +create temporary table schemata(f1 char(10)); +ERROR 42000: Access denied for user 'root'@'localhost' to database 'information_schema' +CREATE PROCEDURE p1 () +BEGIN +SELECT 'foo' FROM DUAL; +END | +ERROR 42000: Access denied for user 'root'@'localhost' to database 'information_schema' +select ROUTINE_NAME from routines; +ROUTINE_NAME +grant all on information_schema.* to 'user1'@'localhost'; +ERROR 42000: Access denied for user 'root'@'localhost' to database 'information_schema' +grant select on information_schema.* to 'user1'@'localhost'; +ERROR 42000: Access denied for user 'root'@'localhost' to database 'information_schema' diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test index aa1b632f919..51cca0a3db1 100644 --- a/mysql-test/t/information_schema.test +++ b/mysql-test/t/information_schema.test @@ -338,7 +338,7 @@ from information_schema.tables where table_schema='information_schema' limit 2; show tables from information_schema like "T%"; ---error 1007 +--error 1044 create database information_schema; use information_schema; show full tables like "T%"; @@ -678,3 +678,39 @@ show fields from test.v1; connection default; drop view v1; drop table t1; + +# +# Bug #9846 Inappropriate error displayed while dropping table from 'INFORMATION_SCHEMA' +# +--error 1044 +alter database information_schema; +--error 1044 +drop database information_schema; +--error 1044 +drop table information_schema.tables; +--error 1044 +alter table information_schema.tables; +# +# Bug #9683 INFORMATION_SCH: Creation of temporary table allowed in Information_schema DB +# +use information_schema; +--error 1044 +create temporary table schemata(f1 char(10)); +# +# Bug #10708 SP's can use INFORMATION_SCHEMA as ROUTINE_SCHEMA +# +delimiter |; +--error 1044 +CREATE PROCEDURE p1 () +BEGIN + SELECT 'foo' FROM DUAL; +END | +delimiter ;| +select ROUTINE_NAME from routines; +# +# Bug #10734 Grant of privileges other than 'select' and 'create view' should fail on schema +# +--error 1044 +grant all on information_schema.* to 'user1'@'localhost'; +--error 1044 +grant select on information_schema.* to 'user1'@'localhost'; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 0bddf92e6aa..31e721d6052 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -621,7 +621,7 @@ void close_connection(THD *thd, uint errcode, bool lock); bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, bool *write_to_binlog); bool check_access(THD *thd, ulong access, const char *db, ulong *save_priv, - bool no_grant, bool no_errors); + bool no_grant, bool no_errors, bool schema_db); bool check_table_access(THD *thd, ulong want_access, TABLE_LIST *tables, bool no_errors); bool check_global_access(THD *thd, ulong want_access); @@ -848,6 +848,8 @@ int fill_schema_schema_privileges(THD *thd, TABLE_LIST *tables, COND *cond); int fill_schema_table_privileges(THD *thd, TABLE_LIST *tables, COND *cond); int fill_schema_column_privileges(THD *thd, TABLE_LIST *tables, COND *cond); bool get_schema_tables_result(JOIN *join); +#define is_schema_db(X) \ + !my_strcasecmp(system_charset_info, information_schema_name.str, (X)) /* sql_prepare.cc */ diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc index 0b6e44c0272..59e29d1d80c 100644 --- a/sql/repl_failsafe.cc +++ b/sql/repl_failsafe.cc @@ -162,7 +162,7 @@ int register_slave(THD* thd, uchar* packet, uint packet_length) SLAVE_INFO *si; uchar *p= packet, *p_end= packet + packet_length; - if (check_access(thd, REPL_SLAVE_ACL, any_db,0,0,0)) + if (check_access(thd, REPL_SLAVE_ACL, any_db,0,0,0,0)) return 1; if (!(si = (SLAVE_INFO*)my_malloc(sizeof(SLAVE_INFO), MYF(MY_WME)))) goto err2; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 4127129576b..1314d92e89a 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1337,7 +1337,7 @@ bool check_change_password(THD *thd, const char *host, const char *user, (strcmp(thd->user,user) || my_strcasecmp(system_charset_info, host, thd->priv_host))) { - if (check_access(thd, UPDATE_ACL, "mysql",0,1,0)) + if (check_access(thd, UPDATE_ACL, "mysql",0,1,0,0)) return(1); } if (!thd->slave_thread && !thd->user[0]) @@ -5532,7 +5532,7 @@ int fill_schema_user_privileges(THD *thd, TABLE_LIST *tables, COND *cond) ulong want_access; char buff[100]; TABLE *table= tables->table; - bool no_global_access= check_access(thd, SELECT_ACL, "mysql",0,1,1); + bool no_global_access= check_access(thd, SELECT_ACL, "mysql",0,1,1,0); char *curr_host= thd->priv_host ? thd->priv_host : (char *) "%"; DBUG_ENTER("fill_schema_user_privileges"); @@ -5585,7 +5585,7 @@ int fill_schema_schema_privileges(THD *thd, TABLE_LIST *tables, COND *cond) ulong want_access; char buff[100]; TABLE *table= tables->table; - bool no_global_access= check_access(thd, SELECT_ACL, "mysql",0,1,1); + bool no_global_access= check_access(thd, SELECT_ACL, "mysql",0,1,1,0); char *curr_host= thd->priv_host ? thd->priv_host : (char *) "%"; DBUG_ENTER("fill_schema_schema_privileges"); @@ -5640,7 +5640,7 @@ int fill_schema_table_privileges(THD *thd, TABLE_LIST *tables, COND *cond) uint index; char buff[100]; TABLE *table= tables->table; - bool no_global_access= check_access(thd, SELECT_ACL, "mysql",0,1,1); + bool no_global_access= check_access(thd, SELECT_ACL, "mysql",0,1,1,0); char *curr_host= thd->priv_host ? thd->priv_host : (char *) "%"; DBUG_ENTER("fill_schema_table_privileges"); @@ -5702,7 +5702,7 @@ int fill_schema_column_privileges(THD *thd, TABLE_LIST *tables, COND *cond) uint index; char buff[100]; TABLE *table= tables->table; - bool no_global_access= check_access(thd, SELECT_ACL, "mysql",0,1,1); + bool no_global_access= check_access(thd, SELECT_ACL, "mysql",0,1,1,0); char *curr_host= thd->priv_host ? thd->priv_host : (char *) "%"; DBUG_ENTER("fill_schema_table_privileges"); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 514b1acd2b4..3cf51454277 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1776,7 +1776,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, remove_escape(table_list.table_name); // This can't have wildcards if (check_access(thd,SELECT_ACL,table_list.db,&table_list.grant.privilege, - 0, 0)) + 0, 0, test(table_list.schema_table))) break; if (grant_option && check_grant(thd, SELECT_ACL, &table_list, 2, UINT_MAX, 0)) @@ -1817,7 +1817,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, my_error(ER_WRONG_DB_NAME, MYF(0), db ? db : "NULL"); break; } - if (check_access(thd,CREATE_ACL,db,0,1,0)) + if (check_access(thd,CREATE_ACL,db,0,1,0,is_schema_db(db))) break; mysql_log.write(thd,command,packet); bzero(&create_info, sizeof(create_info)); @@ -1836,7 +1836,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, my_error(ER_WRONG_DB_NAME, MYF(0), db ? db : "NULL"); break; } - if (check_access(thd,DROP_ACL,db,0,1,0)) + if (check_access(thd,DROP_ACL,db,0,1,0,is_schema_db(db))) break; if (thd->locked_tables || thd->active_transaction()) { @@ -2134,7 +2134,8 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident, my_error(ER_WRONG_DB_NAME, MYF(0), db); DBUG_RETURN(1); } - if (check_access(thd,SELECT_ACL,db,&thd->col_access,0,0)) + if (check_access(thd, SELECT_ACL, db, &thd->col_access, 0, 0, + is_schema_db(db))) DBUG_RETURN(1); /* purecov: inspected */ if (!thd->col_access && check_grant_db(thd,db)) { @@ -2173,7 +2174,8 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident, remove_escape(db); // Fix escaped '_' remove_escape(table_list->table_name); if (check_access(thd,SELECT_ACL | EXTRA_ACL,db, - &table_list->grant.privilege, 0, 0)) + &table_list->grant.privilege, 0, 0, + test(table_list->schema_table))) DBUG_RETURN(1); /* purecov: inspected */ if (grant_option && check_grant(thd, SELECT_ACL, table_list, 2, UINT_MAX, 0)) @@ -2430,7 +2432,7 @@ mysql_execute_command(THD *thd) else res= check_access(thd, lex->exchange ? SELECT_ACL | FILE_ACL : SELECT_ACL, - any_db, 0, 0, 0); + any_db, 0, 0, 0, 0); if (res) goto error; @@ -2612,7 +2614,8 @@ mysql_execute_command(THD *thd) DBUG_ASSERT(first_table == all_tables && first_table != 0); if (check_db_used(thd, all_tables) || check_access(thd, INDEX_ACL, first_table->db, - &first_table->grant.privilege, 0, 0)) + &first_table->grant.privilege, 0, 0, + test(first_table->schema_table))) goto error; res= mysql_assign_to_keycache(thd, first_table, &lex->ident); break; @@ -2622,7 +2625,8 @@ mysql_execute_command(THD *thd) DBUG_ASSERT(first_table == all_tables && first_table != 0); if (check_db_used(thd, all_tables) || check_access(thd, INDEX_ACL, first_table->db, - &first_table->grant.privilege, 0, 0)) + &first_table->grant.privilege, 0, 0, + test(first_table->schema_table))) goto error; res = mysql_preload_keys(thd, first_table); break; @@ -2688,7 +2692,8 @@ mysql_execute_command(THD *thd) if (!first_table->db) first_table->db= thd->db; if (check_access(thd, CREATE_ACL, first_table->db, - &first_table->grant.privilege, 0, 0)) + &first_table->grant.privilege, 0, 0, + test(first_table->schema_table))) goto error; /* purecov: inspected */ if (grant_option) { @@ -2953,8 +2958,10 @@ end_with_restore_list: select_lex->db= first_table->db; } if (check_access(thd, ALTER_ACL, first_table->db, - &first_table->grant.privilege, 0, 0) || - check_access(thd,INSERT_ACL | CREATE_ACL,select_lex->db,&priv,0,0)|| + &first_table->grant.privilege, 0, 0, + test(first_table->schema_table)) || + check_access(thd,INSERT_ACL | CREATE_ACL,select_lex->db,&priv,0,0, + is_schema_db(select_lex->db))|| check_merge_table_access(thd, first_table->db, (TABLE_LIST *) lex->create_info.merge_list.first)) @@ -3004,9 +3011,10 @@ end_with_restore_list: for (table= first_table; table; table= table->next_local->next_local) { if (check_access(thd, ALTER_ACL | DROP_ACL, table->db, - &table->grant.privilege,0,0) || + &table->grant.privilege,0,0, test(table->schema_table)) || check_access(thd, INSERT_ACL | CREATE_ACL, table->next_local->db, - &table->next_local->grant.privilege, 0, 0)) + &table->next_local->grant.privilege, 0, 0, + test(table->next_local->schema_table))) goto error; if (grant_option) { @@ -3058,7 +3066,8 @@ end_with_restore_list: if (check_db_used(thd, all_tables) || check_access(thd, SELECT_ACL | EXTRA_ACL, first_table->db, - &first_table->grant.privilege, 0, 0)) + &first_table->grant.privilege, 0, 0, + test(first_table->schema_table))) goto error; if (grant_option && check_grant(thd, SELECT_ACL, all_tables, 2, UINT_MAX, 0)) goto error; @@ -3390,7 +3399,7 @@ end_with_restore_list: goto error; #else { - if (grant_option && check_access(thd, FILE_ACL, any_db,0,0,0)) + if (grant_option && check_access(thd, FILE_ACL, any_db,0,0,0,0)) goto error; res= mysqld_show_logs(thd); break; @@ -3519,7 +3528,7 @@ end_with_restore_list: break; } #endif - if (check_access(thd,CREATE_ACL,lex->name,0,1,0)) + if (check_access(thd,CREATE_ACL,lex->name,0,1,0,is_schema_db(lex->name))) break; res= mysql_create_db(thd,(lower_case_table_names == 2 ? alias : lex->name), &lex->create_info, 0); @@ -3553,7 +3562,7 @@ end_with_restore_list: break; } #endif - if (check_access(thd,DROP_ACL,lex->name,0,1,0)) + if (check_access(thd,DROP_ACL,lex->name,0,1,0,is_schema_db(lex->name))) break; if (thd->locked_tables || thd->active_transaction()) { @@ -3593,7 +3602,7 @@ end_with_restore_list: break; } #endif - if (check_access(thd, ALTER_ACL, db, 0, 1, 0)) + if (check_access(thd, ALTER_ACL, db, 0, 1, 0, is_schema_db(db))) break; if (thd->locked_tables || thd->active_transaction()) { @@ -3611,14 +3620,14 @@ end_with_restore_list: my_error(ER_WRONG_DB_NAME, MYF(0), lex->name); break; } - if (check_access(thd,SELECT_ACL,lex->name,0,1,0)) + if (check_access(thd,SELECT_ACL,lex->name,0,1,0,is_schema_db(lex->name))) break; res=mysqld_show_create_db(thd,lex->name,&lex->create_info); break; } case SQLCOM_CREATE_FUNCTION: // UDF function { - if (check_access(thd,INSERT_ACL,"mysql",0,1,0)) + if (check_access(thd,INSERT_ACL,"mysql",0,1,0,0)) break; #ifdef HAVE_DLOPEN if (sp_find_function(thd, lex->spname)) @@ -3637,7 +3646,7 @@ end_with_restore_list: #ifndef NO_EMBEDDED_ACCESS_CHECKS case SQLCOM_CREATE_USER: { - if (check_access(thd, INSERT_ACL, "mysql", 0, 1, 1) && + if (check_access(thd, INSERT_ACL, "mysql", 0, 1, 1, 0) && check_global_access(thd,CREATE_USER_ACL)) break; if (!(res= mysql_create_user(thd, lex->users_list))) @@ -3653,7 +3662,7 @@ end_with_restore_list: } case SQLCOM_DROP_USER: { - if (check_access(thd, DELETE_ACL, "mysql", 0, 1, 1) && + if (check_access(thd, DELETE_ACL, "mysql", 0, 1, 1, 0) && check_global_access(thd,CREATE_USER_ACL)) break; if (!(res= mysql_drop_user(thd, lex->users_list))) @@ -3669,7 +3678,7 @@ end_with_restore_list: } case SQLCOM_RENAME_USER: { - if (check_access(thd, UPDATE_ACL, "mysql", 0, 1, 1) && + if (check_access(thd, UPDATE_ACL, "mysql", 0, 1, 1, 0) && check_global_access(thd,CREATE_USER_ACL)) break; if (!(res= mysql_rename_user(thd, lex->users_list))) @@ -3685,7 +3694,7 @@ end_with_restore_list: } case SQLCOM_REVOKE_ALL: { - if (check_access(thd, UPDATE_ACL, "mysql", 0, 1, 1) && + if (check_access(thd, UPDATE_ACL, "mysql", 0, 1, 1, 0) && check_global_access(thd,CREATE_USER_ACL)) break; if (!(res = mysql_revoke_all(thd, lex->users_list))) @@ -3705,7 +3714,9 @@ end_with_restore_list: if (check_access(thd, lex->grant | lex->grant_tot_col | GRANT_ACL, first_table ? first_table->db : select_lex->db, first_table ? &first_table->grant.privilege : 0, - first_table ? 0 : 1, 0)) + first_table ? 0 : 1, 0, + first_table ? (bool) first_table->schema_table : + select_lex->db ? is_schema_db(select_lex->db) : 0)) goto error; if (thd->user) // If not replication @@ -3730,7 +3741,7 @@ end_with_restore_list: { // TODO: use check_change_password() if (check_acl_user(user, &counter) && user->password.str && - check_access(thd, UPDATE_ACL,"mysql",0,1,1)) + check_access(thd, UPDATE_ACL,"mysql",0,1,1,0)) { my_message(ER_PASSWORD_NOT_ALLOWED, ER(ER_PASSWORD_NOT_ALLOWED), MYF(0)); @@ -3855,7 +3866,7 @@ end_with_restore_list: case SQLCOM_SHOW_GRANTS: if ((thd->priv_user && !strcmp(thd->priv_user,lex->grant_user->user.str)) || - !check_access(thd, SELECT_ACL, "mysql",0,1,0)) + !check_access(thd, SELECT_ACL, "mysql",0,1,0,0)) { res = mysql_show_grants(thd,lex->grant_user); } @@ -4010,7 +4021,8 @@ end_with_restore_list: DBUG_ASSERT(lex->sphead != 0); - if (check_access(thd, CREATE_PROC_ACL, lex->sphead->m_db.str, 0, 0, 0)) + if (check_access(thd, CREATE_PROC_ACL, lex->sphead->m_db.str, 0, 0, 0, + is_schema_db(lex->sphead->m_db.str))) { delete lex->sphead; lex->sphead= 0; @@ -4354,7 +4366,7 @@ end_with_restore_list: lex->spname->m_name.length); if (udf) { - if (check_access(thd, DELETE_ACL, "mysql", 0, 1, 0)) + if (check_access(thd, DELETE_ACL, "mysql", 0, 1, 0, 0)) goto error; if (!(res = mysql_drop_function(thd, &lex->spname->m_name))) { @@ -4719,7 +4731,8 @@ cleanup: bool check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *all_tables) { if (check_access(thd, privilege, all_tables->db, - &all_tables->grant.privilege, 0, 0)) + &all_tables->grant.privilege, 0, 0, + test(all_tables->schema_table))) return 1; /* Show only 1 table for check_grant */ @@ -4758,13 +4771,14 @@ bool check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *all_tables) bool check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, - bool dont_check_global_grants, bool no_errors) + bool dont_check_global_grants, bool no_errors, bool schema_db) { #ifndef NO_EMBEDDED_ACCESS_CHECKS ulong db_access; bool db_is_pattern= test(want_access & GRANT_ACL); #endif ulong dummy; + const char *db_name; DBUG_ENTER("check_access"); DBUG_PRINT("enter",("db: %s want_access: %lu master_access: %lu", db ? db : "", want_access, thd->master_access)); @@ -4782,6 +4796,23 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, DBUG_RETURN(TRUE); /* purecov: tested */ } + db_name= db ? db : thd->db; + if (schema_db) + { + if (want_access & ~(SELECT_ACL | EXTRA_ACL)) + { + if (!no_errors) + my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), + thd->priv_user, thd->priv_host, db_name); + DBUG_RETURN(TRUE); + } + else + { + *save_priv= SELECT_ACL; + DBUG_RETURN(FALSE); + } + } + #ifdef NO_EMBEDDED_ACCESS_CHECKS DBUG_RETURN(0); #else @@ -4894,6 +4925,15 @@ check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables, TABLE_LIST *org_tables=tables; for (; tables; tables= tables->next_global) { + if (tables->schema_table && + (want_access & ~(SELECT_ACL | EXTRA_ACL))) + { + if (!no_errors) + my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), + thd->priv_user, thd->priv_host, + information_schema_name.str); + return TRUE; + } if (tables->derived || tables->schema_table || tables->belong_to_view || (tables->table && (int)tables->table->s->tmp_table) || my_tz_check_n_skip_implicit_tables(&tables, @@ -4909,14 +4949,14 @@ check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables, else { if (check_access(thd,want_access,tables->db,&tables->grant.privilege, - 0, no_errors)) + 0, no_errors, test(tables->schema_table))) return TRUE; // Access denied found_access=tables->grant.privilege; found=1; } } else if (check_access(thd,want_access,tables->db,&tables->grant.privilege, - 0, no_errors)) + 0, no_errors, test(tables->schema_table))) return TRUE; } if (grant_option) @@ -4939,7 +4979,7 @@ check_routine_access(THD *thd, ulong want_access,char *db, char *name, if ((thd->master_access & want_access) == want_access && !thd->db) tables->grant.privilege= want_access; else if (check_access(thd,want_access,db,&tables->grant.privilege, - 0, no_errors)) + 0, no_errors, test(tables->schema_table))) return TRUE; #ifndef NO_EMBEDDED_ACCESS_CHECKS @@ -4971,7 +5011,11 @@ bool check_some_routine_access(THD *thd, const char *db, const char *name, ulong save_priv; if (thd->master_access & SHOW_PROC_ACLS) return FALSE; - if (!check_access(thd, SHOW_PROC_ACLS, db, &save_priv, 0, 1) || + /* + There are no routines in information_schema db. So we can safely + pass zero to last paramter of check_access function + */ + if (!check_access(thd, SHOW_PROC_ACLS, db, &save_priv, 0, 1, 0) || (save_priv & SHOW_PROC_ACLS)) return FALSE; return check_routine_level_acl(thd, db, name, is_proc); @@ -5003,7 +5047,8 @@ bool check_some_access(THD *thd, ulong want_access, TABLE_LIST *table) if (access & want_access) { if (!check_access(thd, access, table->db, - &table->grant.privilege, 0, 1) && + &table->grant.privilege, 0, 1, + test(table->schema_table)) && !grant_option || !check_grant(thd, access, table, 0, 1, 1)) DBUG_RETURN(0); } @@ -6808,7 +6853,8 @@ static bool check_multi_update_lock(THD *thd) { TABLE_LIST *save= table->next_local; table->next_local= 0; - if ((check_access(thd, UPDATE_ACL, table->db, &table->grant.privilege,0,1) || + if ((check_access(thd, UPDATE_ACL, table->db, & + table->grant.privilege,0,1, test(table->schema_table)) || (grant_option && check_grant(thd, UPDATE_ACL, table,0,1,1))) && check_one_table_access(thd, SELECT_ACL, table)) goto error; @@ -6976,11 +7022,13 @@ bool multi_update_precheck(THD *thd, TABLE_LIST *tables) if (table->derived) table->grant.privilege= SELECT_ACL; else if ((check_access(thd, UPDATE_ACL, table->db, - &table->grant.privilege, 0, 1) || + &table->grant.privilege, 0, 1, + test(table->schema_table)) || grant_option && check_grant(thd, UPDATE_ACL, table, 0, 1, 1)) && (check_access(thd, SELECT_ACL, table->db, - &table->grant.privilege, 0, 0) || + &table->grant.privilege, 0, 0, + test(table->schema_table)) || grant_option && check_grant(thd, SELECT_ACL, table, 0, 1, 0))) DBUG_RETURN(TRUE); @@ -6999,7 +7047,8 @@ bool multi_update_precheck(THD *thd, TABLE_LIST *tables) !table->table_in_first_from_clause) { if (check_access(thd, SELECT_ACL, table->db, - &table->grant.privilege, 0, 0) || + &table->grant.privilege, 0, 0, + test(table->schema_table)) || grant_option && check_grant(thd, SELECT_ACL, table, 0, 1, 0)) DBUG_RETURN(TRUE); } @@ -7216,7 +7265,8 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables, CREATE_TMP_ACL : CREATE_ACL); lex->create_info.alias= create_table->alias; if (check_access(thd, want_priv, create_table->db, - &create_table->grant.privilege, 0, 0) || + &create_table->grant.privilege, 0, 0, + test(create_table->schema_table)) || check_merge_table_access(thd, create_table->db, (TABLE_LIST *) lex->create_info.merge_list.first)) diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 879ea626494..531af6dc2ac 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1226,7 +1226,7 @@ static int mysql_test_select(Prepared_statement *stmt, if (check_table_access(thd, privilege, tables,0)) goto error; } - else if (check_access(thd, privilege, any_db,0,0,0)) + else if (check_access(thd, privilege, any_db,0,0,0,0)) goto error; #endif diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 32a8378d41d..98f47d13eee 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -769,7 +769,7 @@ int start_slave(THD* thd , MASTER_INFO* mi, bool net_report) int thread_mask; DBUG_ENTER("start_slave"); - if (check_access(thd, SUPER_ACL, any_db,0,0,0)) + if (check_access(thd, SUPER_ACL, any_db,0,0,0,0)) DBUG_RETURN(1); lock_slave_threads(mi); // this allows us to cleanly read slave_running // Get a mask of _stopped_ threads @@ -894,7 +894,7 @@ int stop_slave(THD* thd, MASTER_INFO* mi, bool net_report ) if (!thd) thd = current_thd; - if (check_access(thd, SUPER_ACL, any_db,0,0,0)) + if (check_access(thd, SUPER_ACL, any_db,0,0,0,0)) return 1; thd->proc_info = "Killing slave"; int thread_mask; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 51330a6109b..cd38465516d 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -2025,8 +2025,8 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) (base_name= select_lex->db) && !bases.elements)) { #ifndef NO_EMBEDDED_ACCESS_CHECKS - if (with_i_schema || // don't check the rights if information schema db - !check_access(thd,SELECT_ACL, base_name, &thd->col_access,0,1) || + if (!check_access(thd,SELECT_ACL, base_name, + &thd->col_access, 0, 1, with_i_schema) || thd->master_access & (DB_ACLS | SHOW_DB_ACL) || acl_get(thd->host, thd->ip, thd->priv_user, base_name,0) || (grant_option && !check_grant_db(thd, base_name))) @@ -2448,7 +2448,7 @@ static int get_schema_column_record(THD *thd, struct st_table_list *tables, #ifndef NO_EMBEDDED_ACCESS_CHECKS uint col_access; check_access(thd,SELECT_ACL | EXTRA_ACL, base_name, - &tables->grant.privilege, 0, 0); + &tables->grant.privilege, 0, 0, test(tables->schema_table)); col_access= get_column_grant(thd, &tables->grant, base_name, file_name, field->field_name) & COL_ACLS; @@ -2464,12 +2464,7 @@ static int get_schema_column_record(THD *thd, struct st_table_list *tables, end=strmov(end,grant_types.type_names[bitnr]); } } - if (tables->schema_table) // any user has 'select' privilege on all - // I_S table columns - table->field[17]->store(grant_types.type_names[0], - strlen(grant_types.type_names[0]), cs); - else - table->field[17]->store(tmp+1,end == tmp ? 0 : (uint) (end-tmp-1), cs); + table->field[17]->store(tmp+1,end == tmp ? 0 : (uint) (end-tmp-1), cs); #endif table->field[1]->store(base_name, base_name_length, cs); diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 42c06d478be..e02bebfaded 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -720,7 +720,8 @@ bool mysql_multi_update_prepare(THD *thd) { uint want_privilege= tl->updating ? UPDATE_ACL : SELECT_ACL; if (check_access(thd, want_privilege, - tl->db, &tl->grant.privilege, 0, 0) || + tl->db, &tl->grant.privilege, 0, 0, + test(tl->schema_table)) || (grant_option && check_grant(thd, want_privilege, tl, 0, 1, 0))) DBUG_RETURN(TRUE); } diff --git a/sql/sql_view.cc b/sql/sql_view.cc index eb5d64e0fe0..e2daa4e3069 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -224,11 +224,11 @@ bool mysql_create_view(THD *thd, table (i.e. user will not get some privileges by view creation) */ if ((check_access(thd, CREATE_VIEW_ACL, view->db, &view->grant.privilege, - 0, 0) || + 0, 0, is_schema_db(view->db)) || grant_option && check_grant(thd, CREATE_VIEW_ACL, view, 0, 1, 0)) || (mode != VIEW_CREATE_NEW && (check_access(thd, DROP_ACL, view->db, &view->grant.privilege, - 0, 0) || + 0, 0, is_schema_db(view->db)) || grant_option && check_grant(thd, DROP_ACL, view, 0, 1, 0)))) { res= TRUE; @@ -280,7 +280,7 @@ bool mysql_create_view(THD *thd, if (!tbl->table_in_first_from_clause) { if (check_access(thd, SELECT_ACL, tbl->db, - &tbl->grant.privilege, 0, 0) || + &tbl->grant.privilege, 0, 0, test(tbl->schema_table)) || grant_option && check_grant(thd, SELECT_ACL, tbl, 0, 1, 0)) { res= TRUE; From 065a93773ede926d80a8f2dc772e43878304bce3 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 13 Sep 2005 17:16:12 +0200 Subject: [PATCH 2/7] Fixed BUG#12712: SET AUTOCOMMIT should fail within SP/functions/triggers Second version after review. Allow 'set autocommit' in procedures, but not functions or triggers. Can return error in run-time (when a function calls a procedure). mysql-test/r/sp-error.result: New test case for BUG#12712. mysql-test/t/sp-error.test: New test case for BUG#12712. sql/set_var.cc: Made sys_autocommit external, to allow testing in sql_yacc.yy. sql/set_var.h: Made sys_autocommit external, to allow testing in sql_yacc.yy. sql/share/errmsg.txt: New error message for disallowing the setting of autocommit in stored functions and triggers. sql/sp_head.h: New flag: has 'set autocommit', and testing for this in is_not_allowed_in_function(). sql/sql_yacc.yy: Disallow setting AUTOCOMMIT in stored function and triggers. --- mysql-test/r/sp-error.result | 47 +++++++++++++++++++++++++++++ mysql-test/t/sp-error.test | 58 ++++++++++++++++++++++++++++++++++++ sql/set_var.cc | 8 ++--- sql/set_var.h | 1 + sql/share/errmsg.txt | 2 ++ sql/sp_head.h | 5 +++- sql/sql_yacc.yy | 9 ++++++ 7 files changed, 125 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index 09d829e9d12..17a2050437f 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -786,3 +786,50 @@ END| ERROR 0A000: HANDLER is not allowed in stored procedures SELECT bug12995()| ERROR 42000: FUNCTION test.bug12995 does not exist +drop procedure if exists bug12712; +drop function if exists bug12712; +create procedure bug12712() +set session autocommit = 0; +select @@autocommit; +@@autocommit +1 +set @au = @@autocommit; +call bug12712(); +select @@autocommit; +@@autocommit +0 +set session autocommit = @au; +create function bug12712() +returns int +begin +call bug12712(); +return 0; +end| +set @x = bug12712()| +ERROR HY000: Not allowed to set autocommit from a stored function or trigger +drop procedure bug12712| +drop function bug12712| +create function bug12712() +returns int +begin +set session autocommit = 0; +return 0; +end| +ERROR HY000: Not allowed to set autocommit from a stored function or trigger +create function bug12712() +returns int +begin +set @@autocommit = 0; +return 0; +end| +ERROR HY000: Not allowed to set autocommit from a stored function or trigger +create function bug12712() +returns int +begin +set local autocommit = 0; +return 0; +end| +ERROR HY000: Not allowed to set autocommit from a stored function or trigger +create trigger bug12712 +before insert on t1 for each row set session autocommit = 0; +ERROR HY000: Not allowed to set autocommit from a stored function or trigger diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index 9f91c32c104..40f59f3f124 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -1130,6 +1130,64 @@ END| SELECT bug12995()| delimiter ;| + +# +# BUG#12712: SET AUTOCOMMIT should fail within SP/functions/triggers +# +--disable_warnings +drop procedure if exists bug12712; +drop function if exists bug12712; +--enable_warnings +# Can... +create procedure bug12712() + set session autocommit = 0; + +select @@autocommit; +set @au = @@autocommit; +call bug12712(); +select @@autocommit; +set session autocommit = @au; + +delimiter |; +create function bug12712() + returns int +begin + call bug12712(); + return 0; +end| + +# Can't... +--error ER_SP_CANT_SET_AUTOCOMMIT +set @x = bug12712()| +drop procedure bug12712| +drop function bug12712| +--error ER_SP_CANT_SET_AUTOCOMMIT +create function bug12712() + returns int +begin + set session autocommit = 0; + return 0; +end| +--error ER_SP_CANT_SET_AUTOCOMMIT +create function bug12712() + returns int +begin + set @@autocommit = 0; + return 0; +end| +--error ER_SP_CANT_SET_AUTOCOMMIT +create function bug12712() + returns int +begin + set local autocommit = 0; + return 0; +end| +delimiter ;| +--error ER_SP_CANT_SET_AUTOCOMMIT +create trigger bug12712 + before insert on t1 for each row set session autocommit = 0; + + # # BUG#NNNN: New bug synopsis # diff --git a/sql/set_var.cc b/sql/set_var.cc index 774062dedf2..ff997158941 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -447,10 +447,10 @@ sys_var_thd_date_time_format sys_datetime_format("datetime_format", /* Variables that are bits in THD */ -static sys_var_thd_bit sys_autocommit("autocommit", 0, - set_option_autocommit, - OPTION_NOT_AUTOCOMMIT, - 1); +sys_var_thd_bit sys_autocommit("autocommit", 0, + set_option_autocommit, + OPTION_NOT_AUTOCOMMIT, + 1); static sys_var_thd_bit sys_big_tables("big_tables", 0, set_option_bit, OPTION_BIG_TABLES); diff --git a/sql/set_var.h b/sql/set_var.h index 40ff4c8583f..854409c159e 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -905,6 +905,7 @@ extern sys_var_const_str sys_charset_system; extern sys_var_str sys_init_connect; extern sys_var_str sys_init_slave; extern sys_var_thd_time_zone sys_time_zone; +extern sys_var_thd_bit sys_autocommit; CHARSET_INFO *get_old_charset_by_name(const char *old_name); gptr find_named(I_List *list, const char *name, uint length, NAMED_LIST **found); diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 5f1f7035af9..57e70c6acb6 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5403,3 +5403,5 @@ ER_VIEW_PREVENT_UPDATE eng "The definition of table '%-.64s' prevents operation %s on table '%-.64s'." ER_PS_NO_RECURSION eng "The prepared statement contains a stored routine call that refers to that same statement. It's not allowed to execute a prepared statement in such a recursive manner" +ER_SP_CANT_SET_AUTOCOMMIT + eng "Not allowed to set autocommit from a stored function or trigger" diff --git a/sql/sp_head.h b/sql/sp_head.h index 271119ff2fb..7c9cf364b17 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -114,7 +114,8 @@ public: IN_HANDLER= 4, // Is set if the parser is in a handler body MULTI_RESULTS= 8, // Is set if a procedure with SELECT(s) CONTAINS_DYNAMIC_SQL= 16, // Is set if a procedure with PREPARE/EXECUTE - IS_INVOKED= 32 // Is set if this sp_head is being used. + IS_INVOKED= 32, // Is set if this sp_head is being used + HAS_SET_AUTOCOMMIT_STMT = 64 // Is set if a procedure with 'set autocommit' }; int m_type; // TYPE_ENUM_FUNCTION or TYPE_ENUM_PROCEDURE @@ -282,6 +283,8 @@ public: my_error(ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0), "Dynamic SQL"); else if (m_flags & MULTI_RESULTS) my_error(ER_SP_NO_RETSET, MYF(0), where); + else if (m_flags & HAS_SET_AUTOCOMMIT_STMT) + my_error(ER_SP_CANT_SET_AUTOCOMMIT, MYF(0)); return test(m_flags & (CONTAINS_DYNAMIC_SQL|MULTI_RESULTS)); } private: diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 104f9ca8445..a8810f5de94 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -8004,6 +8004,15 @@ internal_variable_name: if (tmp == &sys_time_zone && lex->add_time_zone_tables_to_query_tables(YYTHD)) YYABORT; + else + if (spc && tmp == &sys_autocommit) + { + /* + We don't allow setting AUTOCOMMIT from a stored function + or trigger. + */ + lex->sphead->m_flags|= sp_head::HAS_SET_AUTOCOMMIT_STMT; + } } else { From 685173664a1c970318775cb05dfa4a72b8cd4e45 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 14 Sep 2005 07:25:32 +0400 Subject: [PATCH 3/7] fix for Bug #12979 Stored procedures: crash if inout decimal parameter mysql-test/r/sp.result: fix result mysql-test/r/type_newdecimal.result: fix result mysql-test/t/sp.test: add a test for the bug mysql-test/t/type_newdecimal.test: add a test for the bug sql/item_func.cc: call correct method of the item --- mysql-test/r/sp.result | 16 ++++++++++++++++ mysql-test/r/type_newdecimal.result | 3 +++ mysql-test/t/sp.test | 29 +++++++++++++++++++++++++++++ mysql-test/t/type_newdecimal.test | 7 +++++++ sql/item_func.cc | 2 +- 5 files changed, 56 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 0559b45168b..9ad9f9175db 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -3331,4 +3331,20 @@ set @x=y; end| call bug13124()| drop procedure bug13124| +drop procedure if exists bug12979_1| +create procedure bug12979_1(inout d decimal(5)) set d = d / 2| +set @bug12979_user_var = NULL| +call bug12979_1(@bug12979_user_var)| +drop procedure bug12979_1| +drop procedure if exists bug12979_2| +create procedure bug12979_2() +begin +declare internal_var decimal(5); +set internal_var= internal_var / 2; +select internal_var; +end| +call bug12979_2()| +internal_var +NULL +drop procedure bug12979_2| drop table t1,t2; diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result index f06e290a49b..d821339a229 100644 --- a/mysql-test/r/type_newdecimal.result +++ b/mysql-test/r/type_newdecimal.result @@ -1016,3 +1016,6 @@ v tdec v tdec 9 0 drop procedure wg2; +select cast(@non_existing_user_var/2 as DECIMAL); +cast(@non_existing_user_var/2 as DECIMAL) +NULL diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index a1e2bf8aa32..d44b6ac7e98 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -4177,6 +4177,35 @@ end| call bug13124()| drop procedure bug13124| +# +# Bug #12979 Stored procedures: crash if inout decimal parameter +# + +# check NULL inout parameters processing + +--disable_warnings +drop procedure if exists bug12979_1| +--enable_warnings +create procedure bug12979_1(inout d decimal(5)) set d = d / 2| +set @bug12979_user_var = NULL| +call bug12979_1(@bug12979_user_var)| +drop procedure bug12979_1| + +# check NULL local variables processing + +--disable_warnings +drop procedure if exists bug12979_2| +--enable_warnings +create procedure bug12979_2() +begin +declare internal_var decimal(5); +set internal_var= internal_var / 2; +select internal_var; +end| +call bug12979_2()| +drop procedure bug12979_2| + + # # BUG#NNNN: New bug synopsis # diff --git a/mysql-test/t/type_newdecimal.test b/mysql-test/t/type_newdecimal.test index 55e0618a3e5..3f04aa931d2 100644 --- a/mysql-test/t/type_newdecimal.test +++ b/mysql-test/t/type_newdecimal.test @@ -1037,3 +1037,10 @@ call wg2()// delimiter ;// drop procedure wg2; + +# +# Bug #12979 Stored procedures: crash if inout decimal parameter +# (not a SP bug in fact) +# + +select cast(@non_existing_user_var/2 as DECIMAL); diff --git a/sql/item_func.cc b/sql/item_func.cc index b47d7d19fbd..518fb011e0f 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -765,7 +765,7 @@ my_decimal *Item_func_numhybrid::val_decimal(my_decimal *decimal_value) } case REAL_RESULT: { - double result= (double)int_op(); + double result= (double)real_op(); double2my_decimal(E_DEC_FATAL_ERROR, result, decimal_value); break; } From 77a7ba13dbb805ef085f5a09530053225938f107 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 14 Sep 2005 12:10:07 +0500 Subject: [PATCH 4/7] formatting typo fix --- sql/sql_parse.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 3cf51454277..4bc9f478cd1 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -6853,11 +6853,11 @@ static bool check_multi_update_lock(THD *thd) { TABLE_LIST *save= table->next_local; table->next_local= 0; - if ((check_access(thd, UPDATE_ACL, table->db, & - table->grant.privilege,0,1, test(table->schema_table)) || - (grant_option && check_grant(thd, UPDATE_ACL, table,0,1,1))) && + if ((check_access(thd, UPDATE_ACL, table->db, + &table->grant.privilege,0,1, test(table->schema_table)) || + (grant_option && check_grant(thd, UPDATE_ACL, table,0,1,1))) && check_one_table_access(thd, SELECT_ACL, table)) - goto error; + goto error; table->next_local= save; } From 8c86f8e4bfb7627051f8f231daf8bfa87c4e468a Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 14 Sep 2005 10:54:02 +0200 Subject: [PATCH 5/7] Post-review fix for BUG#12712: SET AUTOCOMMIT should fail within SP/functions/triggers mysql-test/r/sp.result: Added missing drop table. mysql-test/t/sp.test: Added missing drop table. sql/sp_head.h: Post-review fix for autocommit check in SPs and triggers. sql/sql_yacc.yy: Post-review fix for autocommit check in SPs and triggers. --- mysql-test/r/sp.result | 1 + mysql-test/t/sp.test | 1 + sql/sp_head.h | 3 ++- sql/sql_yacc.yy | 17 ++++++++--------- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 0559b45168b..e4259eae6bf 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -3323,6 +3323,7 @@ drop function bug12379| drop procedure bug12379_1| drop procedure bug12379_2| drop procedure bug12379_3| +drop table t3| drop procedure if exists bug13124| create procedure bug13124() begin diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index a1e2bf8aa32..1e78a38c040 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -4161,6 +4161,7 @@ drop function bug12379| drop procedure bug12379_1| drop procedure bug12379_2| drop procedure bug12379_3| +drop table t3| # # Bug #13124 Stored Procedure using SELECT INTO crashes server diff --git a/sql/sp_head.h b/sql/sp_head.h index 7c9cf364b17..9888fe74149 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -285,7 +285,8 @@ public: my_error(ER_SP_NO_RETSET, MYF(0), where); else if (m_flags & HAS_SET_AUTOCOMMIT_STMT) my_error(ER_SP_CANT_SET_AUTOCOMMIT, MYF(0)); - return test(m_flags & (CONTAINS_DYNAMIC_SQL|MULTI_RESULTS)); + return test(m_flags & + (CONTAINS_DYNAMIC_SQL|MULTI_RESULTS|HAS_SET_AUTOCOMMIT_STMT)); } private: diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index c163db3c393..3253e1065ff 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -8005,15 +8005,14 @@ internal_variable_name: if (tmp == &sys_time_zone && lex->add_time_zone_tables_to_query_tables(YYTHD)) YYABORT; - else - if (spc && tmp == &sys_autocommit) - { - /* - We don't allow setting AUTOCOMMIT from a stored function - or trigger. - */ - lex->sphead->m_flags|= sp_head::HAS_SET_AUTOCOMMIT_STMT; - } + else if (spc && tmp == &sys_autocommit) + { + /* + We don't allow setting AUTOCOMMIT from a stored function + or trigger. + */ + lex->sphead->m_flags|= sp_head::HAS_SET_AUTOCOMMIT_STMT; + } } else { From e7d7e0e92f34d3a68d16b802f76e97076dbb6088 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 14 Sep 2005 11:41:36 +0200 Subject: [PATCH 6/7] Bug #13152 bit fields and fileds that follow become corrupted when dumped from NDB tables --- mysql-test/r/ndb_bitfield.result | 58 ++++++++++++++++++++++++++++++++ mysql-test/t/ndb_bitfield.test | 52 ++++++++++++++++++++++++++++ sql/table.cc | 2 ++ 3 files changed, 112 insertions(+) diff --git a/mysql-test/r/ndb_bitfield.result b/mysql-test/r/ndb_bitfield.result index 66ec593e195..e2326459a8c 100644 --- a/mysql-test/r/ndb_bitfield.result +++ b/mysql-test/r/ndb_bitfield.result @@ -140,6 +140,64 @@ b+0 499 drop table t1; create table t1 ( +dummyKey INTEGER NOT NULL, +a001 TINYINT, +a010 TINYINT, +a012 TINYINT, +a015 TINYINT, +a016 TINYINT, +a017 TINYINT, +a019 TINYINT, +a029 TINYINT, +a030 TINYINT, +a031 TINYINT, +a032 TINYINT, +a042 TINYINT, +a043 TINYINT, +a044 TINYINT, +a3001 TINYINT, +a3002 TINYINT, +a3003 TINYINT, +a3004 TINYINT, +a3005 TINYINT, +a3021 TINYINT, +a3022 TINYINT, +a BIT(6), +b BIT(6), +c BIT(6), +d TINYINT, +e TINYINT, +f TINYINT, +g TINYINT, +h TINYINT, +i TINYINT, +j TINYINT, +k TINYINT, +l TINYINT, +m TINYINT, +n TINYINT, +o TINYINT, +a034 TINYINT, +PRIMARY KEY USING HASH (dummyKey) ) engine=ndb; +INSERT INTO `t1` VALUES +(1,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'000001',b'111111',b'111110',4,5,5,5,5,5,5,5,5,5,3,2,1), +(2,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'000010',b'000000',b'111101',4,5,5,5,5,5,5,5,5,5,3,2,1), +(3,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'000100',b'001111',b'111011',4,5,5,5,5,5,5,5,5,5,3,2,1), +(4,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'001000',b'110000',b'110111',4,5,5,5,5,5,5,5,5,5,3,2,1), +(5,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'010000',b'100001',b'101111',4,5,5,5,5,5,5,5,5,5,3,2,1), +(6,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'100000',b'010010',b'011111',4,5,5,5,5,5,5,5,5,5,3,2,1), +(7,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'000000',b'001100',b'111111',4,5,5,5,5,5,5,5,5,5,3,2,1), +(8,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'111111',b'000000',b'000000',4,5,5,5,5,5,5,5,5,5,3,2,1); +INSERT INTO `t1` VALUES (1,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'','?','>',4,5,5,5,5,5,5,5,5,5,3,2,1); +INSERT INTO `t1` VALUES (2,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'','\0','=',4,5,5,5,5,5,5,5,5,5,3,2,1); +INSERT INTO `t1` VALUES (3,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'','',';',4,5,5,5,5,5,5,5,5,5,3,2,1); +INSERT INTO `t1` VALUES (4,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'','0','7',4,5,5,5,5,5,5,5,5,5,3,2,1); +INSERT INTO `t1` VALUES (5,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'','!','/',4,5,5,5,5,5,5,5,5,5,3,2,1); +INSERT INTO `t1` VALUES (6,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,' ','','',4,5,5,5,5,5,5,5,5,5,3,2,1); +INSERT INTO `t1` VALUES (7,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'\0',' ','?',4,5,5,5,5,5,5,5,5,5,3,2,1); +INSERT INTO `t1` VALUES (8,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'?','\0','\0',4,5,5,5,5,5,5,5,5,5,3,2,1); +drop table t1; +create table t1 ( pk1 bit(9) not null primary key, b int ) engine=ndbcluster; diff --git a/mysql-test/t/ndb_bitfield.test b/mysql-test/t/ndb_bitfield.test index efacd8f7c06..6b805c2f1cd 100644 --- a/mysql-test/t/ndb_bitfield.test +++ b/mysql-test/t/ndb_bitfield.test @@ -47,6 +47,58 @@ select a+0 from t1 order by a; select b+0 from t1 order by b; drop table t1; +create table t1 ( + dummyKey INTEGER NOT NULL, + a001 TINYINT, + a010 TINYINT, + a012 TINYINT, + a015 TINYINT, + a016 TINYINT, + a017 TINYINT, + a019 TINYINT, + a029 TINYINT, + a030 TINYINT, + a031 TINYINT, + a032 TINYINT, + a042 TINYINT, + a043 TINYINT, + a044 TINYINT, + a3001 TINYINT, + a3002 TINYINT, + a3003 TINYINT, + a3004 TINYINT, + a3005 TINYINT, + a3021 TINYINT, + a3022 TINYINT, + a BIT(6), + b BIT(6), + c BIT(6), + d TINYINT, + e TINYINT, + f TINYINT, + g TINYINT, + h TINYINT, + i TINYINT, + j TINYINT, + k TINYINT, + l TINYINT, + m TINYINT, + n TINYINT, + o TINYINT, + a034 TINYINT, +PRIMARY KEY USING HASH (dummyKey) ) engine=ndb; +INSERT INTO `t1` VALUES +(1,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'000001',b'111111',b'111110',4,5,5,5,5,5,5,5,5,5,3,2,1), +(2,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'000010',b'000000',b'111101',4,5,5,5,5,5,5,5,5,5,3,2,1), +(3,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'000100',b'001111',b'111011',4,5,5,5,5,5,5,5,5,5,3,2,1), +(4,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'001000',b'110000',b'110111',4,5,5,5,5,5,5,5,5,5,3,2,1), +(5,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'010000',b'100001',b'101111',4,5,5,5,5,5,5,5,5,5,3,2,1), +(6,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'100000',b'010010',b'011111',4,5,5,5,5,5,5,5,5,5,3,2,1), +(7,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'000000',b'001100',b'111111',4,5,5,5,5,5,5,5,5,5,3,2,1), +(8,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'111111',b'000000',b'000000',4,5,5,5,5,5,5,5,5,5,3,2,1); +--exec $MYSQL_DUMP --compact --order-by-primary --skip-extended-insert --no-create-info test t1 +drop table t1; + --error 1005 create table t1 ( pk1 bit(9) not null primary key, diff --git a/sql/table.cc b/sql/table.cc index 6ac5e07daf1..52521755b69 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -287,6 +287,8 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat, keynames=(char*) key_part; strpos+= (strmov(keynames, (char *) strpos) - keynames)+1; + share->null_bytes == (null_pos-(uchar*)outparam->null_flags + (null_bit_pos + 7) / 8); + share->reclength = uint2korr((head+16)); if (*(head+26) == 1) share->system= 1; /* one-record-database */ From e2b72d815f7a66412000fd22bca898fb0406dfdb Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 14 Sep 2005 13:24:41 +0200 Subject: [PATCH 7/7] (corrected typo in prev patch) Bug #13152 bit fields and fileds that follow become corrupted when dumped from NDB --- sql/table.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/table.cc b/sql/table.cc index 52521755b69..be89081af8c 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -287,7 +287,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat, keynames=(char*) key_part; strpos+= (strmov(keynames, (char *) strpos) - keynames)+1; - share->null_bytes == (null_pos-(uchar*)outparam->null_flags + (null_bit_pos + 7) / 8); + share->null_bytes= (null_pos-(uchar*)outparam->null_flags + (null_bit_pos + 7) / 8); share->reclength = uint2korr((head+16)); if (*(head+26) == 1)