diff options
author | unknown <serg@sergbook.mysql.com> | 2007-03-24 17:16:53 +0200 |
---|---|---|
committer | unknown <serg@sergbook.mysql.com> | 2007-03-24 17:16:53 +0200 |
commit | 99d1dee47301ba8313dd6fadeaabedcf60c38d27 (patch) | |
tree | b9c03afd33f12eacdee1a66fbe3bd8f2a850b5dd | |
parent | aa42093553ad7b066b96ca3e49facc02b6b8981e (diff) | |
parent | 79bfd0b958f4bade19e0f49ae379b6502cc145fe (diff) | |
download | mariadb-git-99d1dee47301ba8313dd6fadeaabedcf60c38d27.tar.gz |
Merge bk-internal.mysql.com:/home/bk/mysql-5.0-marvel
into sergbook.mysql.com:/usr/home/serg/Abk/mysql-5.0
mysql-test/r/sp.result:
Auto merged
mysql-test/t/sp.test:
Auto merged
sql/ha_ndbcluster.cc:
Auto merged
sql/handler.cc:
Auto merged
sql/mysql_priv.h:
Auto merged
sql/sp_head.cc:
Auto merged
sql/sql_base.cc:
Auto merged
sql/sql_class.h:
Auto merged
sql/sql_insert.cc:
Auto merged
sql/sql_table.cc:
Auto merged
sql/sql_view.cc:
Auto merged
-rw-r--r-- | client/client_priv.h | 2 | ||||
-rw-r--r-- | client/mysqldump.c | 24 | ||||
-rw-r--r-- | mysql-test/r/information_schema_db.result | 71 | ||||
-rw-r--r-- | mysql-test/r/sp.result | 25 | ||||
-rw-r--r-- | mysql-test/r/sp_trans.result | 31 | ||||
-rw-r--r-- | mysql-test/t/information_schema_db.test | 55 | ||||
-rw-r--r-- | mysql-test/t/sp.test | 24 | ||||
-rw-r--r-- | mysql-test/t/sp_trans.test | 31 | ||||
-rw-r--r-- | sql/ha_ndbcluster.cc | 3 | ||||
-rw-r--r-- | sql/handler.cc | 2 | ||||
-rw-r--r-- | sql/item_func.h | 4 | ||||
-rw-r--r-- | sql/log.cc | 4 | ||||
-rw-r--r-- | sql/mysql_priv.h | 3 | ||||
-rw-r--r-- | sql/set_var.cc | 5 | ||||
-rw-r--r-- | sql/sp_head.cc | 6 | ||||
-rw-r--r-- | sql/sql_base.cc | 27 | ||||
-rw-r--r-- | sql/sql_class.h | 8 | ||||
-rw-r--r-- | sql/sql_delete.cc | 4 | ||||
-rw-r--r-- | sql/sql_insert.cc | 18 | ||||
-rw-r--r-- | sql/sql_load.cc | 16 | ||||
-rw-r--r-- | sql/sql_parse.cc | 36 | ||||
-rw-r--r-- | sql/sql_table.cc | 2 | ||||
-rw-r--r-- | sql/sql_update.cc | 48 | ||||
-rw-r--r-- | sql/sql_view.cc | 7 | ||||
-rw-r--r-- | sql/table.cc | 5 |
25 files changed, 374 insertions, 87 deletions
diff --git a/client/client_priv.h b/client/client_priv.h index 7748dc612d6..418bf86f2c8 100644 --- a/client/client_priv.h +++ b/client/client_priv.h @@ -51,5 +51,5 @@ enum options_client OPT_TRIGGERS, OPT_IGNORE_TABLE,OPT_INSERT_IGNORE,OPT_SHOW_WARNINGS,OPT_DROP_DATABASE, OPT_TZ_UTC, OPT_AUTO_CLOSE, OPT_SSL_VERIFY_SERVER_CERT, - OPT_DEBUG_INFO + OPT_DEBUG_INFO, OPT_ERROR_LOG_FILE }; diff --git a/client/mysqldump.c b/client/mysqldump.c index 94ab9dac5ac..0d7c0c3a0bf 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -105,7 +105,8 @@ static char *opt_password=0,*current_user=0, *lines_terminated=0, *enclosed=0, *opt_enclosed=0, *escaped=0, *where=0, *order_by=0, *opt_compatible_mode_str= 0, - *err_ptr= 0; + *err_ptr= 0, + *log_error_file= NULL; static char **defaults_argv= 0; static char compatible_mode_normal_str[255]; static ulong opt_compatible_mode= 0; @@ -116,7 +117,9 @@ static my_string opt_mysql_unix_port=0; static int first_error=0; static DYNAMIC_STRING extended_row; #include <sslopt-vars.h> -FILE *md_result_file= 0; +FILE *md_result_file= 0; +FILE *stderror_file=0; + #ifdef HAVE_SMEM static char *shared_memory_base_name=0; #endif @@ -293,6 +296,9 @@ static struct my_option my_long_options[] = 0, 0, 0, 0, 0, 0}, {"lock-tables", 'l', "Lock all tables for read.", (gptr*) &lock_tables, (gptr*) &lock_tables, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, + {"log-error", OPT_ERROR_LOG_FILE, "Append warnings and errors to given file.", + (gptr*) &log_error_file, (gptr*) &log_error_file, 0, GET_STR, + REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"master-data", OPT_MASTER_DATA, "This causes the binary log position and filename to be appended to the " "output. If equal to 1, will print it as a CHANGE MASTER command; if equal" @@ -3694,6 +3700,16 @@ int main(int argc, char **argv) free_resources(0); exit(exit_code); } + + if (log_error_file) + { + if(!(stderror_file= freopen(log_error_file, "a+", stderr))) + { + free_resources(0); + exit(EX_MYSQLERR); + } + } + if (connect_to_db(current_host, current_user, opt_password)) { free_resources(0); @@ -3746,5 +3762,9 @@ err: if (!path) write_footer(md_result_file); free_resources(); + + if (stderror_file) + fclose(stderror_file); + return(first_error); } /* main */ diff --git a/mysql-test/r/information_schema_db.result b/mysql-test/r/information_schema_db.result index 47efe1d17ad..2d330dda333 100644 --- a/mysql-test/r/information_schema_db.result +++ b/mysql-test/r/information_schema_db.result @@ -106,16 +106,82 @@ use testdb_1; create table t1 (f1 char(4)); create view v1 as select f1 from t1; grant insert on v1 to testdb_2@localhost; +create view v5 as select f1 from t1; +grant show view on v5 to testdb_2@localhost; +create definer=`no_such_user`@`no_such_host` view v6 as select f1 from t1; +ERROR 42000: Access denied; you need the SUPER privilege for this operation +use testdb_1; +create view v6 as select f1 from t1; +grant show view on v6 to testdb_2@localhost; +create table t2 (f1 char(4)); +create definer=`no_such_user`@`no_such_host` view v7 as select * from t2; +Warnings: +Note 1449 There is no 'no_such_user'@'no_such_host' registered +show fields from testdb_1.v6; +Field Type Null Key Default Extra +f1 char(4) YES NULL +show create view testdb_1.v6; +View Create View +v6 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v6` AS select `t1`.`f1` AS `f1` from `t1` +show create view testdb_1.v7; +View Create View +v7 CREATE ALGORITHM=UNDEFINED DEFINER=`no_such_user`@`no_such_host` SQL SECURITY DEFINER VIEW `v7` AS select `testdb_1`.`t2`.`f1` AS `f1` from `t2` +Warnings: +Warning 1356 View 'testdb_1.v7' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +show fields from testdb_1.v7; +Field Type Null Key Default Extra +f1 null YES NULL +Warnings: +Note 1449 There is no 'no_such_user'@'no_such_host' registered create table t3 (f1 char(4), f2 char(4)); create view v3 as select f1,f2 from t3; grant insert(f1), insert(f2) on v3 to testdb_2@localhost; create view v2 as select f1 from testdb_1.v1; create view v4 as select f1,f2 from testdb_1.v3; +show fields from testdb_1.v5; +Field Type Null Key Default Extra +f1 char(4) YES NULL +show create view testdb_1.v5; +View Create View +v5 CREATE ALGORITHM=UNDEFINED DEFINER=`testdb_1`@`localhost` SQL SECURITY DEFINER VIEW `testdb_1`.`v5` AS select `testdb_1`.`t1`.`f1` AS `f1` from `testdb_1`.`t1` +show fields from testdb_1.v6; +Field Type Null Key Default Extra +f1 char(4) YES NULL +show create view testdb_1.v6; +View Create View +v6 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `testdb_1`.`v6` AS select `testdb_1`.`t1`.`f1` AS `f1` from `testdb_1`.`t1` +show fields from testdb_1.v7; +Field Type Null Key Default Extra +f1 null YES NULL +Warnings: +Note 1449 There is no 'no_such_user'@'no_such_host' registered +show create view testdb_1.v7; +View Create View +v7 CREATE ALGORITHM=UNDEFINED DEFINER=`no_such_user`@`no_such_host` SQL SECURITY DEFINER VIEW `v7` AS select `testdb_1`.`t2`.`f1` AS `f1` from `t2` +Warnings: +Warning 1356 View 'testdb_1.v7' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them revoke insert(f1) on v3 from testdb_2@localhost; +revoke show view on v5 from testdb_2@localhost; +use testdb_1; +revoke show view on v6 from testdb_2@localhost; +show fields from testdb_1.v5; +ERROR 42000: SELECT command denied to user 'testdb_2'@'localhost' for table 'v5' +show create view testdb_1.v5; +ERROR 42000: SELECT command denied to user 'testdb_2'@'localhost' for table 'v5' +show fields from testdb_1.v6; +ERROR 42000: SELECT command denied to user 'testdb_2'@'localhost' for table 'v6' +show create view testdb_1.v6; +ERROR 42000: SELECT command denied to user 'testdb_2'@'localhost' for table 'v6' +show fields from testdb_1.v7; +ERROR 42000: SELECT command denied to user 'testdb_2'@'localhost' for table 'v7' +show create view testdb_1.v7; +ERROR 42000: SELECT command denied to user 'testdb_2'@'localhost' for table 'v7' show create view v4; ERROR HY000: EXPLAIN/SHOW can not be issued; lacking privileges for underlying table show fields from v4; -ERROR HY000: EXPLAIN/SHOW can not be issued; lacking privileges for underlying table +Field Type Null Key Default Extra +f1 null YES NULL +f2 char(4) YES NULL show fields from v2; Field Type Null Key Default Extra f1 char(4) YES NULL @@ -140,7 +206,8 @@ where a.table_name = 'testdb_1.v1'; view_definition select * from v2; ERROR HY000: View 'test.v2' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them -drop view testdb_1.v1,v2, testdb_1.v3, v4; +use test; +drop view testdb_1.v1, v2, testdb_1.v3, v4; drop database testdb_1; drop user testdb_1@localhost; drop user testdb_2@localhost; diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index cf3cf07630a..ddd2369d36d 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -5970,3 +5970,28 @@ SUM(f2) bug25373(f1) DROP FUNCTION bug25373| DROP TABLE t3| drop table t1,t2; +CREATE TABLE t1 (a int auto_increment primary key) engine=MyISAM; +CREATE TABLE t2 (a int auto_increment primary key, b int) engine=innodb; +set @a=0; +CREATE function bug27354() RETURNS int deterministic +begin +insert into t1 values (null); +set @a=@a+1; +return @a; +end| +update t2 set b=1 where a=bug27354(); +select count(t_1.a),count(t_2.a) from t1 as t_1, t2 as t_2 /* must be 0,0 */; +count(t_1.a) count(t_2.a) +0 0 +insert into t2 values (1,1),(2,2),(3,3); +update t2 set b=-b where a=bug27354(); +select * from t2 /* must return 1,-1 ... */; +a b +1 -1 +2 -2 +3 -3 +select count(*) from t1 /* must be 3 */; +count(*) +3 +drop table t1,t2; +drop function bug27354; diff --git a/mysql-test/r/sp_trans.result b/mysql-test/r/sp_trans.result index 564e31c9e32..57c73bea86e 100644 --- a/mysql-test/r/sp_trans.result +++ b/mysql-test/r/sp_trans.result @@ -530,3 +530,34 @@ count(*) drop table t3, t4| drop procedure bug14210| set @@session.max_heap_table_size=default| +drop function if exists bug23333| +drop table if exists t1,t2| +CREATE TABLE t1 (a int NOT NULL auto_increment primary key) ENGINE=MyISAM| +CREATE TABLE t2 (a int NOT NULL auto_increment, b int, PRIMARY KEY (a)) ENGINE=InnoDB| +reset master| +insert into t2 values (1,1)| +create function bug23333() +RETURNS int(11) +DETERMINISTIC +begin +insert into t1 values (null); +select count(*) from t1 into @a; +return @a; +end| +insert into t2 values (bug23333(),1)| +ERROR 23000: Duplicate entry '1' for key 1 +show binlog events from 98 /* must show the insert */| +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query 1 # use `test`; insert into t2 values (1,1) +master-bin.000001 # Xid 1 # COMMIT /* xid=1165 */ +master-bin.000001 # Query 1 # use `test`; CREATE DEFINER=`root`@`localhost` function bug23333() +RETURNS int(11) +DETERMINISTIC +begin +insert into t1 values (null); +select count(*) from t1 into @a; +return @a; +end +select count(*),@a from t1 /* must be 1,1 */| +count(*) @a +1 1 diff --git a/mysql-test/t/information_schema_db.test b/mysql-test/t/information_schema_db.test index e15e50e8766..666f331c7b9 100644 --- a/mysql-test/t/information_schema_db.test +++ b/mysql-test/t/information_schema_db.test @@ -121,6 +121,28 @@ create table t1 (f1 char(4)); create view v1 as select f1 from t1; grant insert on v1 to testdb_2@localhost; +create view v5 as select f1 from t1; +grant show view on v5 to testdb_2@localhost; + +--error 1227 +create definer=`no_such_user`@`no_such_host` view v6 as select f1 from t1; + +connection default; +use testdb_1; +create view v6 as select f1 from t1; +grant show view on v6 to testdb_2@localhost; + +create table t2 (f1 char(4)); +create definer=`no_such_user`@`no_such_host` view v7 as select * from t2; + +show fields from testdb_1.v6; +show create view testdb_1.v6; + +show create view testdb_1.v7; +show fields from testdb_1.v7; + +connection testdb_1; + create table t3 (f1 char(4), f2 char(4)); create view v3 as select f1,f2 from t3; grant insert(f1), insert(f2) on v3 to testdb_2@localhost; @@ -129,13 +151,41 @@ connect (testdb_2,localhost,testdb_2,,test); create view v2 as select f1 from testdb_1.v1; create view v4 as select f1,f2 from testdb_1.v3; +show fields from testdb_1.v5; +show create view testdb_1.v5; + +show fields from testdb_1.v6; +show create view testdb_1.v6; + connection testdb_1; +show fields from testdb_1.v7; +show create view testdb_1.v7; + revoke insert(f1) on v3 from testdb_2@localhost; +revoke show view on v5 from testdb_2@localhost; +connection default; +use testdb_1; +revoke show view on v6 from testdb_2@localhost; connection testdb_2; +--error 1142 +show fields from testdb_1.v5; +--error 1142 +show create view testdb_1.v5; + +--error 1142 +show fields from testdb_1.v6; +--error 1142 +show create view testdb_1.v6; + +--error 1142 +show fields from testdb_1.v7; +--error 1142 +show create view testdb_1.v7; + --error 1345 show create view v4; ---error 1345 +#--error 1345 show fields from v4; show fields from v2; @@ -155,7 +205,8 @@ where a.table_name = 'testdb_1.v1'; select * from v2; connection default; -drop view testdb_1.v1,v2, testdb_1.v3, v4; +use test; +drop view testdb_1.v1, v2, testdb_1.v3, v4; drop database testdb_1; drop user testdb_1@localhost; drop user testdb_2@localhost; diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 5c67319cefc..fd158408fb6 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -6946,3 +6946,27 @@ DROP TABLE t3| # practical, or create table t3, t4 etc temporarily (and drop them). delimiter ;| drop table t1,t2; + +CREATE TABLE t1 (a int auto_increment primary key) engine=MyISAM; +CREATE TABLE t2 (a int auto_increment primary key, b int) engine=innodb; +set @a=0; + +delimiter |; +CREATE function bug27354() RETURNS int deterministic +begin +insert into t1 values (null); +set @a=@a+1; +return @a; +end| + +delimiter ;| +update t2 set b=1 where a=bug27354(); +select count(t_1.a),count(t_2.a) from t1 as t_1, t2 as t_2 /* must be 0,0 */; +insert into t2 values (1,1),(2,2),(3,3); +update t2 set b=-b where a=bug27354(); +select * from t2 /* must return 1,-1 ... */; +select count(*) from t1 /* must be 3 */; + + +drop table t1,t2; +drop function bug27354; diff --git a/mysql-test/t/sp_trans.test b/mysql-test/t/sp_trans.test index 1ea32316f1e..f2ed39c093e 100644 --- a/mysql-test/t/sp_trans.test +++ b/mysql-test/t/sp_trans.test @@ -554,6 +554,37 @@ set @@session.max_heap_table_size=default| # +# Bug #13270 INSERT,UPDATE,etc that calls func with side-effect does not binlog +# Bug #23333 stored function + non-transac table + transac table = +# breaks stmt-based binlog +# Bug #27395 OPTION_STATUS_NO_TRANS_UPDATE is not preserved at the end of SF() +# +--disable_warnings +drop function if exists bug23333| +drop table if exists t1,t2| +--enable_warnings + CREATE TABLE t1 (a int NOT NULL auto_increment primary key) ENGINE=MyISAM| + CREATE TABLE t2 (a int NOT NULL auto_increment, b int, PRIMARY KEY (a)) ENGINE=InnoDB| + +reset master| +insert into t2 values (1,1)| + +create function bug23333() +RETURNS int(11) +DETERMINISTIC +begin + insert into t1 values (null); + select count(*) from t1 into @a; + return @a; +end| + +--error ER_DUP_ENTRY +insert into t2 values (bug23333(),1)| +--replace_column 2 # 5 # +show binlog events from 98 /* must show the insert */| +select count(*),@a from t1 /* must be 1,1 */| + +# # BUG#NNNN: New bug synopsis # #--disable_warnings diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index d2a242a6b01..6d593dce9dc 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -3636,8 +3636,7 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type) { m_transaction_on= FALSE; /* Would be simpler if has_transactions() didn't always say "yes" */ - thd->options|= OPTION_STATUS_NO_TRANS_UPDATE; - thd->no_trans_update= TRUE; + thd->no_trans_update.all= thd->no_trans_update.stmt= TRUE; } else if (!thd->transaction.on) m_transaction_on= FALSE; diff --git a/sql/handler.cc b/sql/handler.cc index 524f47209dc..302c1773a9f 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -830,7 +830,7 @@ int ha_rollback_trans(THD *thd, bool all) the error log; but we don't want users to wonder why they have this message in the error log, so we don't send it. */ - if (is_real_trans && (thd->options & OPTION_STATUS_NO_TRANS_UPDATE) && + if (is_real_trans && thd->no_trans_update.all && !thd->slave_thread) push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARNING_NOT_COMPLETE_ROLLBACK, diff --git a/sql/item_func.h b/sql/item_func.h index 68591f9c6f5..24f30994b22 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -1411,7 +1411,7 @@ private: bool execute(Field **flp); bool execute_impl(THD *thd, Field *return_value_fld); Field *sp_result_field(void) const; - + public: Item_func_sp(Name_resolution_context *context_arg, sp_name *name); @@ -1422,6 +1422,8 @@ public: virtual ~Item_func_sp() {} + table_map used_tables() const { return RAND_TABLE_BIT; } + void cleanup(); const char *func_name() const; diff --git a/sql/log.cc b/sql/log.cc index 7d0bef5ca2c..a0068dce1c5 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -162,7 +162,7 @@ static int binlog_rollback(THD *thd, bool all) table. Such cases should be rare (updating a non-transactional table inside a transaction...) */ - if (unlikely(thd->options & OPTION_STATUS_NO_TRANS_UPDATE)) + if (unlikely(thd->no_trans_update.all)) { Query_log_event qev(thd, STRING_WITH_LEN("ROLLBACK"), TRUE, FALSE); qev.error_code= 0; // see comment in MYSQL_LOG::write(THD, IO_CACHE) @@ -217,7 +217,7 @@ static int binlog_savepoint_rollback(THD *thd, void *sv) non-transactional table. Otherwise, truncate the binlog cache starting from the SAVEPOINT command. */ - if (unlikely(thd->options & OPTION_STATUS_NO_TRANS_UPDATE)) + if (unlikely(thd->no_trans_update.all)) { Query_log_event qinfo(thd, thd->query, thd->query_length, TRUE, FALSE); DBUG_RETURN(mysql_bin_log.write(&qinfo)); diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index de567eacbeb..4d08b381a2e 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -347,9 +347,6 @@ MY_LOCALE *my_locale_by_number(uint number); in the user query has requested */ #define SELECT_ALL (ULL(1) << 24) // SELECT, user, parser -/* Set if we are updating a non-transaction safe table */ -#define OPTION_STATUS_NO_TRANS_UPDATE (ULL(1) << 25) // THD, intern - /* The following can be set when importing tables in a 'wrong order' to suppress foreign key checks */ #define OPTION_NO_FOREIGN_KEY_CHECKS (ULL(1) << 26) // THD, user, binlog diff --git a/sql/set_var.cc b/sql/set_var.cc index 46c2a775d8a..ca5b6471bec 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -2873,14 +2873,15 @@ static bool set_option_autocommit(THD *thd, set_var *var) if ((org_options & OPTION_NOT_AUTOCOMMIT)) { /* We changed to auto_commit mode */ - thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE); + thd->options&= ~(ulong) OPTION_BEGIN; + thd->no_trans_update.all= FALSE; thd->server_status|= SERVER_STATUS_AUTOCOMMIT; if (ha_commit(thd)) return 1; } else { - thd->options&= ~(ulong) (OPTION_STATUS_NO_TRANS_UPDATE); + thd->no_trans_update.all= FALSE; thd->server_status&= ~SERVER_STATUS_AUTOCOMMIT; } } diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 1f44fa6639c..9d7fc55ff70 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -337,13 +337,13 @@ sp_eval_expr(THD *thd, Field *result_field, Item **expr_item_ptr) enum_check_fields save_count_cuted_fields= thd->count_cuted_fields; bool save_abort_on_warning= thd->abort_on_warning; - bool save_no_trans_update= thd->no_trans_update; + bool save_no_trans_update_stmt= thd->no_trans_update.stmt; thd->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL; thd->abort_on_warning= thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES); - thd->no_trans_update= 0; + thd->no_trans_update.stmt= FALSE; /* Save the value in the field. Convert the value if needed. */ @@ -351,7 +351,7 @@ sp_eval_expr(THD *thd, Field *result_field, Item **expr_item_ptr) thd->count_cuted_fields= save_count_cuted_fields; thd->abort_on_warning= save_abort_on_warning; - thd->no_trans_update= save_no_trans_update; + thd->no_trans_update.stmt= save_no_trans_update_stmt; if (thd->net.report_error) { diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 4a09a442c0d..ad6f8ec7cdd 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -3573,14 +3573,35 @@ find_field_in_tables(THD *thd, Item_ident *item, { Field *cur_field= find_field_in_table_ref(thd, cur_table, name, length, item->name, db, table_name, ref, - check_privileges, allow_rowid, + check_privileges, + allow_rowid, &(item->cached_field_index), register_tree_change, &actual_table); if (cur_field) { if (cur_field == WRONG_GRANT) - return (Field*) 0; + { + if (thd->lex->sql_command != SQLCOM_SHOW_FIELDS) + return (Field*) 0; + + thd->clear_error(); + cur_field= find_field_in_table_ref(thd, cur_table, name, length, + item->name, db, table_name, ref, + false, + allow_rowid, + &(item->cached_field_index), + register_tree_change, + &actual_table); + if (cur_field) + { + Field *nf=new Field_null(NULL,0,Field::NONE, + cur_field->field_name, + cur_field->table, + &my_charset_bin); + cur_field= nf; + } + } /* Store the original table of the field, which may be different from @@ -3603,7 +3624,7 @@ find_field_in_tables(THD *thd, Item_ident *item, report_error == IGNORE_EXCEPT_NON_UNIQUE) my_error(ER_NON_UNIQ_ERROR, MYF(0), table_name ? item->full_name() : name, thd->where); - return (Field*) 0; + return (Field*) 0; } found= cur_field; } diff --git a/sql/sql_class.h b/sql/sql_class.h index 048da718dfd..560058f1a94 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1440,7 +1440,11 @@ public: bool charset_is_system_charset, charset_is_collation_connection; bool charset_is_character_set_filesystem; bool enable_slow_log; /* enable slow log for current statement */ - bool no_trans_update, abort_on_warning; + struct { + bool all:1; + bool stmt:1; + } no_trans_update; + bool abort_on_warning; bool got_warning; /* Set on call to push_warning() */ bool no_warnings_for_error; /* no warnings on call to my_error() */ /* set during loop of derived table processing */ @@ -1667,7 +1671,7 @@ public: inline bool really_abort_on_warning() { return (abort_on_warning && - (!no_trans_update || + (!no_trans_update.stmt || (variables.sql_mode & MODE_STRICT_ALL_TABLES))); } void set_status_var_init(); diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index fe89f0f28f0..8cf07f328bf 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -311,7 +311,7 @@ cleanup: error=1; } if (!transactional_table) - thd->options|=OPTION_STATUS_NO_TRANS_UPDATE; + thd->no_trans_update.all= TRUE; } free_underlaid_joins(thd, select_lex); if (transactional_table) @@ -791,7 +791,7 @@ bool multi_delete::send_eof() local_error=1; // Log write failed: roll back the SQL statement } if (!transactional_tables) - thd->options|=OPTION_STATUS_NO_TRANS_UPDATE; + thd->no_trans_update.all= TRUE; } /* Commit or rollback the current SQL statement */ if (transactional_tables) diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 3c8f9fd5fc2..df8c224f765 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -584,7 +584,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, if (lock_type != TL_WRITE_DELAYED && !thd->prelocked_mode) table->file->start_bulk_insert(values_list.elements); - thd->no_trans_update= 0; + thd->no_trans_update.stmt= FALSE; thd->abort_on_warning= (!ignore && (thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES))); @@ -731,7 +731,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, error=1; } if (!transactional_table) - thd->options|=OPTION_STATUS_NO_TRANS_UPDATE; + thd->no_trans_update.all= TRUE; } } if (transactional_table) @@ -1129,7 +1129,7 @@ static int last_uniq_key(TABLE *table,uint keynr) then both on update triggers will work instead. Similarly both on delete triggers will be invoked if we will delete conflicting records. - Sets thd->no_trans_update if table which is updated didn't have + Sets thd->no_trans_update.stmt to TRUE if table which is updated didn't have transactions. RETURN VALUE @@ -1295,7 +1295,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) goto err; info->deleted++; if (!table->file->has_transactions()) - thd->no_trans_update= 1; + thd->no_trans_update.stmt= TRUE; if (table->triggers && table->triggers->process_triggers(thd, TRG_EVENT_DELETE, TRG_ACTION_AFTER, TRUE)) @@ -1327,7 +1327,7 @@ ok_or_after_trg_err: if (key) my_safe_afree(key,table->s->max_unique_length,MAX_KEY_LENGTH); if (!table->file->has_transactions()) - thd->no_trans_update= 1; + thd->no_trans_update.stmt= TRUE; DBUG_RETURN(trg_error); err: @@ -2520,7 +2520,7 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u) table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE); table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS); } - thd->no_trans_update= 0; + thd->no_trans_update.stmt= FALSE; thd->abort_on_warning= (!info.ignore && (thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES | @@ -2678,7 +2678,7 @@ void select_insert::send_error(uint errcode,const char *err) mysql_bin_log.write(&qinfo); } if (!table->s->tmp_table) - thd->options|=OPTION_STATUS_NO_TRANS_UPDATE; + thd->no_trans_update.all= TRUE; } if (info.copied || info.deleted || info.updated) { @@ -2707,7 +2707,7 @@ bool select_insert::send_eof() { query_cache_invalidate3(thd, table, 1); if (!(table->file->has_transactions() || table->s->tmp_table)) - thd->options|=OPTION_STATUS_NO_TRANS_UPDATE; + thd->no_trans_update.all= TRUE; } if (last_insert_id) @@ -2933,7 +2933,7 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u) } if (!thd->prelocked_mode) table->file->start_bulk_insert((ha_rows) 0); - thd->no_trans_update= 0; + thd->no_trans_update.stmt= FALSE; thd->abort_on_warning= (!info.ignore && (thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES | diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 3f67a0c3f5d..8848c2c5e5b 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -377,7 +377,7 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, table->file->start_bulk_insert((ha_rows) 0); table->copy_blobs=1; - thd->no_trans_update= 0; + thd->no_trans_update.stmt= FALSE; thd->abort_on_warning= (!ignore && (thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES | @@ -467,7 +467,7 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, (ulong) (info.records - info.copied), (ulong) thd->cuted_fields); if (!transactional_table) - thd->options|=OPTION_STATUS_NO_TRANS_UPDATE; + thd->no_trans_update.all= TRUE; #ifndef EMBEDDED_LIBRARY if (mysql_bin_log.is_open()) { @@ -531,7 +531,7 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, Item_field *sql_field; TABLE *table= table_list->table; ulonglong id; - bool no_trans_update; + bool no_trans_update_stmt; DBUG_ENTER("read_fixed_length"); id= 0; @@ -559,7 +559,7 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, #ifdef HAVE_purify read_info.row_end[0]=0; #endif - no_trans_update= !table->file->has_transactions(); + no_trans_update_stmt= !table->file->has_transactions(); restore_record(table, s->default_values); /* @@ -627,7 +627,7 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, if (write_record(thd, table, &info)) DBUG_RETURN(1); - thd->no_trans_update= no_trans_update; + thd->no_trans_update.stmt= no_trans_update_stmt; /* If auto_increment values are used, save the first one for @@ -670,12 +670,12 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, TABLE *table= table_list->table; uint enclosed_length; ulonglong id; - bool no_trans_update; + bool no_trans_update_stmt; DBUG_ENTER("read_sep_field"); enclosed_length=enclosed.length(); id= 0; - no_trans_update= !table->file->has_transactions(); + no_trans_update_stmt= !table->file->has_transactions(); for (;;it.rewind()) { @@ -817,7 +817,7 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, We don't need to reset auto-increment field since we are restoring its default value at the beginning of each loop iteration. */ - thd->no_trans_update= no_trans_update; + thd->no_trans_update.stmt= no_trans_update_stmt; if (read_info.next_line()) // Skip to next line break; if (read_info.line_cuted) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 1b8bfd38fc4..486942a8bb9 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -147,7 +147,8 @@ static bool end_active_trans(THD *thd) thd->server_status&= ~SERVER_STATUS_IN_TRANS; if (ha_commit(thd)) error=1; - thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE); + thd->options&= ~(ulong) OPTION_BEGIN; + thd->no_trans_update.all= FALSE; } DBUG_RETURN(error); } @@ -171,8 +172,8 @@ static bool begin_trans(THD *thd) else { LEX *lex= thd->lex; - thd->options= ((thd->options & (ulong) ~(OPTION_STATUS_NO_TRANS_UPDATE)) | - OPTION_BEGIN); + thd->no_trans_update.all= FALSE; + thd->options|= (ulong) OPTION_BEGIN; thd->server_status|= SERVER_STATUS_IN_TRANS; if (lex->start_transaction_opt & MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT) error= ha_start_consistent_snapshot(thd); @@ -1463,7 +1464,8 @@ int end_trans(THD *thd, enum enum_mysql_completiontype completion) */ thd->server_status&= ~SERVER_STATUS_IN_TRANS; res= ha_commit(thd); - thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE); + thd->options&= ~(ulong) OPTION_BEGIN; + thd->no_trans_update.all= FALSE; break; case COMMIT_RELEASE: do_release= 1; /* fall through */ @@ -1480,7 +1482,8 @@ int end_trans(THD *thd, enum enum_mysql_completiontype completion) thd->server_status&= ~SERVER_STATUS_IN_TRANS; if (ha_rollback(thd)) res= -1; - thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE); + thd->options&= ~(ulong) OPTION_BEGIN; + thd->no_trans_update.all= FALSE; if (!res && (completion == ROLLBACK_AND_CHAIN)) res= begin_trans(thd); break; @@ -2933,7 +2936,7 @@ mysql_execute_command(THD *thd) else { /* So that CREATE TEMPORARY TABLE gets to binlog at commit/rollback */ - thd->options|= OPTION_STATUS_NO_TRANS_UPDATE; + thd->no_trans_update.all= TRUE; } DBUG_ASSERT(first_table == all_tables && first_table != 0); bool link_to_local; @@ -3707,10 +3710,10 @@ end_with_restore_list: we silently add IF EXISTS if TEMPORARY was used. */ if (thd->slave_thread) - lex->drop_if_exists= 1; + lex->drop_if_exists= 1; /* So that DROP TEMPORARY TABLE gets to binlog at commit/rollback */ - thd->options|= OPTION_STATUS_NO_TRANS_UPDATE; + thd->no_trans_update.all= TRUE; } /* DDL and binlog write order protected by LOCK_open */ res= mysql_rm_table(thd, first_table, lex->drop_if_exists, @@ -4296,7 +4299,7 @@ end_with_restore_list: res= TRUE; // cannot happen else { - if ((thd->options & OPTION_STATUS_NO_TRANS_UPDATE) && + if (thd->no_trans_update.all && !thd->slave_thread) push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARNING_NOT_COMPLETE_ROLLBACK, @@ -4939,8 +4942,8 @@ create_sp_error: thd->transaction.xid_state.xa_state=XA_ACTIVE; thd->transaction.xid_state.xid.set(thd->lex->xid); xid_cache_insert(&thd->transaction.xid_state); - thd->options= ((thd->options & (ulong) ~(OPTION_STATUS_NO_TRANS_UPDATE)) | - OPTION_BEGIN); + thd->no_trans_update.all= FALSE; + thd->options|= (ulong) OPTION_BEGIN; thd->server_status|= SERVER_STATUS_IN_TRANS; send_ok(thd); break; @@ -5033,7 +5036,8 @@ create_sp_error: xa_state_names[thd->transaction.xid_state.xa_state]); break; } - thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE); + thd->options&= ~(ulong) OPTION_BEGIN; + thd->no_trans_update.all= FALSE; thd->server_status&= ~SERVER_STATUS_IN_TRANS; xid_cache_delete(&thd->transaction.xid_state); thd->transaction.xid_state.xa_state=XA_NOTR; @@ -5063,7 +5067,8 @@ create_sp_error: my_error(ER_XAER_RMERR, MYF(0)); else send_ok(thd); - thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE); + thd->options&= ~(ulong) OPTION_BEGIN; + thd->no_trans_update.all= FALSE; thd->server_status&= ~SERVER_STATUS_IN_TRANS; xid_cache_delete(&thd->transaction.xid_state); thd->transaction.xid_state.xa_state=XA_NOTR; @@ -5159,7 +5164,10 @@ bool check_single_table_access(THD *thd, ulong privilege, goto deny; /* Show only 1 table for check_grant */ - if (grant_option && check_grant(thd, privilege, all_tables, 0, 1, 0)) + if (grant_option && + !(all_tables->belong_to_view && + (thd->lex->sql_command == SQLCOM_SHOW_FIELDS)) && + check_grant(thd, privilege, all_tables, 0, 1, 0)) goto deny; thd->security_ctx= backup_ctx; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index c75aff7fab6..289bb21bb98 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -3968,7 +3968,7 @@ copy_data_between_tables(TABLE *from,TABLE *to, alter_table_manage_keys(to, from->file->indexes_are_disabled(), keys_onoff); /* We can abort alter table for any table type */ - thd->no_trans_update= 0; + thd->no_trans_update.stmt= FALSE; thd->abort_on_warning= !ignore && test(thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES)); diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 27d38114885..860d00b5bdd 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -429,7 +429,7 @@ int mysql_update(THD *thd, query_id=thd->query_id; transactional_table= table->file->has_transactions(); - thd->no_trans_update= 0; + thd->no_trans_update.stmt= FALSE; thd->abort_on_warning= test(!ignore && (thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES | @@ -452,7 +452,7 @@ int mysql_update(THD *thd, if (fill_record_n_invoke_before_triggers(thd, fields, values, 0, table->triggers, TRG_EVENT_UPDATE)) - break; /* purecov: inspected */ + break; /* purecov: inspected */ found++; @@ -470,12 +470,12 @@ int mysql_update(THD *thd, break; } } - if (!(error=table->file->update_row((byte*) table->record[1], - (byte*) table->record[0]))) - { - updated++; - thd->no_trans_update= !transactional_table; - + if (!(error=table->file->update_row((byte*) table->record[1], + (byte*) table->record[0]))) + { + updated++; + thd->no_trans_update.stmt= !transactional_table; + if (table->triggers && table->triggers->process_triggers(thd, TRG_EVENT_UPDATE, TRG_ACTION_AFTER, TRUE)) @@ -483,25 +483,25 @@ int mysql_update(THD *thd, error= 1; break; } - } - else if (!ignore || error != HA_ERR_FOUND_DUPP_KEY) - { + } + else if (!ignore || error != HA_ERR_FOUND_DUPP_KEY) + { /* If (ignore && error == HA_ERR_FOUND_DUPP_KEY) we don't have to do anything; otherwise... */ if (error != HA_ERR_FOUND_DUPP_KEY) thd->fatal_error(); /* Other handler errors are fatal */ - table->file->print_error(error,MYF(0)); - error= 1; - break; - } + table->file->print_error(error,MYF(0)); + error= 1; + break; + } } - + if (!--limit && using_limit) { - error= -1; // Simulate end of file - break; + error= -1; // Simulate end of file + break; } } else @@ -546,7 +546,7 @@ int mysql_update(THD *thd, error=1; // Rollback update } if (!transactional_table) - thd->options|=OPTION_STATUS_NO_TRANS_UPDATE; + thd->no_trans_update.all= TRUE; } free_underlaid_joins(thd, select_lex); if (transactional_table) @@ -910,7 +910,7 @@ bool mysql_multi_update(THD *thd, handle_duplicates, ignore))) DBUG_RETURN(TRUE); - thd->no_trans_update= 0; + thd->no_trans_update.stmt= FALSE; thd->abort_on_warning= test(thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES)); @@ -1224,7 +1224,7 @@ multi_update::~multi_update() delete [] copy_field; thd->count_cuted_fields= CHECK_FIELD_IGNORE; // Restore this setting if (!trans_safe) - thd->options|=OPTION_STATUS_NO_TRANS_UPDATE; + thd->no_trans_update.all= TRUE; } @@ -1311,7 +1311,7 @@ bool multi_update::send_data(List<Item> ¬_used_values) else { if (!table->file->has_transactions()) - thd->no_trans_update= 1; + thd->no_trans_update.stmt= TRUE; if (table->triggers && table->triggers->process_triggers(thd, TRG_EVENT_UPDATE, TRG_ACTION_AFTER, TRUE)) @@ -1541,10 +1541,10 @@ bool multi_update::send_eof() Query_log_event qinfo(thd, thd->query, thd->query_length, transactional_tables, FALSE); if (mysql_bin_log.write(&qinfo) && trans_safe) - local_error= 1; // Rollback update + local_error= 1; // Rollback update } if (!transactional_tables) - thd->options|=OPTION_STATUS_NO_TRANS_UPDATE; + thd->no_trans_update.all= TRUE; } if (transactional_tables) diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 533e847682d..14d9aeb4df5 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -1018,6 +1018,11 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table, CHARSET_INFO *save_cs= thd->variables.character_set_client; thd->variables.character_set_client= system_charset_info; res= MYSQLparse((void *)thd); + + if ((old_lex->sql_command == SQLCOM_SHOW_FIELDS) || + (old_lex->sql_command == SQLCOM_SHOW_CREATE)) + lex->sql_command= old_lex->sql_command; + thd->variables.character_set_client= save_cs; thd->variables.sql_mode= save_mode; } @@ -1043,7 +1048,7 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table, } } else if (!table->prelocking_placeholder && - old_lex->sql_command == SQLCOM_SHOW_CREATE && + (old_lex->sql_command == SQLCOM_SHOW_CREATE) && !table->belong_to_view) { if (check_table_access(thd, SHOW_VIEW_ACL, table, 0)) diff --git a/sql/table.cc b/sql/table.cc index 960534bf7d4..6d13514e782 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -2085,7 +2085,7 @@ void st_table_list::hide_view_error(THD *thd) thd->net.last_errno == ER_NO_SUCH_TABLE) { TABLE_LIST *top= top_table(); - thd->clear_error(); + thd->clear_error(); my_error(ER_VIEW_INVALID, MYF(0), top->view_db.str, top->view_name.str); } else if (thd->net.last_errno == ER_NO_DEFAULT_FOR_FIELD) @@ -2441,7 +2441,8 @@ bool st_table_list::prepare_view_securety_context(THD *thd) definer.host.str, thd->db)) { - if (thd->lex->sql_command == SQLCOM_SHOW_CREATE) + if ((thd->lex->sql_command == SQLCOM_SHOW_CREATE) || + (thd->lex->sql_command == SQLCOM_SHOW_FIELDS)) { push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_NO_SUCH_USER, |