diff --git a/mysql-test/r/skip_grants.result b/mysql-test/r/skip_grants.result index 6714fa9d217..58ced16acac 100644 --- a/mysql-test/r/skip_grants.result +++ b/mysql-test/r/skip_grants.result @@ -1,30 +1,60 @@ -drop table if exists t1,v1; -drop view if exists t1,v1; -drop procedure if exists f1; use test; -create procedure f1() select 1; -drop procedure f1; -create table t1 (a int); -create definer='user'@'host' sql security definer view v1 as select * from t1; -drop view v1; -drop table t1; -drop function if exists f1; -Warnings: -Note 1305 FUNCTION f1 does not exist DROP VIEW IF EXISTS v1; DROP VIEW IF EXISTS v2; +DROP VIEW IF EXISTS v3; DROP TABLE IF EXISTS t1; +DROP PROCEDURE IF EXISTS p1; +DROP PROCEDURE IF EXISTS p2; +DROP PROCEDURE IF EXISTS p3; +DROP FUNCTION IF EXISTS f1; +DROP FUNCTION IF EXISTS f2; +DROP FUNCTION IF EXISTS f3; CREATE TABLE t1(c INT); CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW SET @a = 1; CREATE VIEW v1 AS SELECT * FROM t1; +CREATE PROCEDURE p1() +SELECT 1; +CREATE FUNCTION f1() RETURNS INT +RETURN 1; CREATE DEFINER=a@b TRIGGER ti_ai AFTER INSERT ON t1 FOR EACH ROW SET @b = 1; CREATE DEFINER=a@b VIEW v2 AS SELECT * FROM t1; +CREATE DEFINER=a@b PROCEDURE p2() +SELECT 2; +CREATE DEFINER=a@b FUNCTION f2() RETURNS INT +RETURN 2; +CREATE DEFINER=a@'' TRIGGER ti_bu BEFORE UPDATE ON t1 +FOR EACH ROW +SET @c = 1; +CREATE DEFINER=a@'' VIEW v3 AS SELECT * FROM t1; +CREATE DEFINER=a@'' PROCEDURE p3() +SELECT 3; +CREATE DEFINER=a@'' FUNCTION f3() RETURNS INT +RETURN 3; +SHOW CREATE VIEW v3; +View Create View +v3 CREATE ALGORITHM=UNDEFINED DEFINER=`a`@`` SQL SECURITY DEFINER VIEW `v3` AS select `t1`.`c` AS `c` from `t1` +SHOW CREATE PROCEDURE p3; +Procedure sql_mode Create Procedure +p3 CREATE DEFINER=`a`@`` PROCEDURE `p3`() +SELECT 3 +SHOW CREATE FUNCTION f3; +Function sql_mode Create Function +f3 CREATE DEFINER=`a`@`` FUNCTION `f3`() RETURNS int(11) +RETURN 3 DROP TRIGGER t1_bi; DROP TRIGGER ti_ai; +DROP TRIGGER ti_bu; DROP VIEW v1; DROP VIEW v2; +DROP VIEW v3; DROP TABLE t1; +DROP PROCEDURE p1; +DROP PROCEDURE p2; +DROP PROCEDURE p3; +DROP FUNCTION f1; +DROP FUNCTION f2; +DROP FUNCTION f3; diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 6521a2b67b7..f31facf6196 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -4796,4 +4796,20 @@ i 0 drop table t3| drop procedure bug16887| +create table t3 (f1 int, f2 varchar(3), primary key(f1)) engine=innodb| +insert into t3 values (1,'aaa'),(2,'bbb'),(3,'ccc')| +CREATE FUNCTION bug13575 ( p1 integer ) +returns varchar(3) +BEGIN +DECLARE v1 VARCHAR(10) DEFAULT null; +SELECT f2 INTO v1 FROM t3 WHERE f1 = p1; +RETURN v1; +END| +select distinct f1, bug13575(f1) from t3 order by f1| +f1 bug13575(f1) +1 aaa +2 bbb +3 ccc +drop function bug13575; +drop table t3| drop table t1,t2; diff --git a/mysql-test/t/skip_grants.test b/mysql-test/t/skip_grants.test index 93e052d8c71..6dda97fcf8a 100644 --- a/mysql-test/t/skip_grants.test +++ b/mysql-test/t/skip_grants.test @@ -1,37 +1,18 @@ # This tests not performed with embedded server -- source include/not_embedded.inc ---disable_warnings -drop table if exists t1,v1; -drop view if exists t1,v1; -drop procedure if exists f1; ---enable_warnings use test; -# -# Test that we can create and drop procedure without warnings -# see bug#9993 -# -create procedure f1() select 1; -drop procedure f1; - -# -# BUG#13504: creation view with DEFINER clause if --skip-grant-tables -# -create table t1 (a int); -create definer='user'@'host' sql security definer view v1 as select * from t1; -drop view v1; -drop table t1; - -# BUG#17595: DROP FUNCTION IF EXISTS f1 crashes server -drop function if exists f1; - # # BUG#16777: Can not create trigger nor view w/o definer if --skip-grant-tables # specified # -# Also, a test that we can create VIEW if privileges check switched off has -# been moved here. +# Also, the following test cases have been moved here: +# - test that we can create VIEW if privileges check switched off has been +# moved here; +# - test that we can create and drop procedure without warnings (BUG#9993); +# - BUG#17595: "DROP FUNCTION IF EXISTS" crashes server; +# - BUG#13504: creation view with DEFINER clause if --skip-grant-tables # # Prepare. @@ -40,33 +21,90 @@ drop function if exists f1; DROP VIEW IF EXISTS v1; DROP VIEW IF EXISTS v2; +DROP VIEW IF EXISTS v3; DROP TABLE IF EXISTS t1; +DROP PROCEDURE IF EXISTS p1; +DROP PROCEDURE IF EXISTS p2; +DROP PROCEDURE IF EXISTS p3; + +DROP FUNCTION IF EXISTS f1; +DROP FUNCTION IF EXISTS f2; +DROP FUNCTION IF EXISTS f3; + --enable_warnings # Test case. CREATE TABLE t1(c INT); +# - try to create with implicit definer (definer would be ''@''); + CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW SET @a = 1; CREATE VIEW v1 AS SELECT * FROM t1; +CREATE PROCEDURE p1() + SELECT 1; + +CREATE FUNCTION f1() RETURNS INT + RETURN 1; + +# - try to create with explicit definer; + CREATE DEFINER=a@b TRIGGER ti_ai AFTER INSERT ON t1 FOR EACH ROW SET @b = 1; CREATE DEFINER=a@b VIEW v2 AS SELECT * FROM t1; +CREATE DEFINER=a@b PROCEDURE p2() + SELECT 2; + +CREATE DEFINER=a@b FUNCTION f2() RETURNS INT + RETURN 2; + +# - try to create with explicit definer with empty host; + +CREATE DEFINER=a@'' TRIGGER ti_bu BEFORE UPDATE ON t1 + FOR EACH ROW + SET @c = 1; + +CREATE DEFINER=a@'' VIEW v3 AS SELECT * FROM t1; + +CREATE DEFINER=a@'' PROCEDURE p3() + SELECT 3; + +CREATE DEFINER=a@'' FUNCTION f3() RETURNS INT + RETURN 3; + +# - check that empty host name is treated correctly; + +SHOW CREATE VIEW v3; + +SHOW CREATE PROCEDURE p3; + +SHOW CREATE FUNCTION f3; + # Cleanup. DROP TRIGGER t1_bi; DROP TRIGGER ti_ai; +DROP TRIGGER ti_bu; DROP VIEW v1; DROP VIEW v2; +DROP VIEW v3; DROP TABLE t1; + +DROP PROCEDURE p1; +DROP PROCEDURE p2; +DROP PROCEDURE p3; + +DROP FUNCTION f1; +DROP FUNCTION f2; +DROP FUNCTION f3; diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 0fbf17761b3..b025b2969b9 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -5635,6 +5635,22 @@ call bug16887()| drop table t3| drop procedure bug16887| +# +# Bug#13575 SP funcs in select with distinct/group and order by can +# produce bad data +# +create table t3 (f1 int, f2 varchar(3), primary key(f1)) engine=innodb| +insert into t3 values (1,'aaa'),(2,'bbb'),(3,'ccc')| +CREATE FUNCTION bug13575 ( p1 integer ) +returns varchar(3) +BEGIN +DECLARE v1 VARCHAR(10) DEFAULT null; +SELECT f2 INTO v1 FROM t3 WHERE f1 = p1; +RETURN v1; +END| +select distinct f1, bug13575(f1) from t3 order by f1| +drop function bug13575; +drop table t3| # # BUG#NNNN: New bug synopsis diff --git a/mysql-test/t/view_grant.test b/mysql-test/t/view_grant.test index 504c4892808..8335c1de20a 100644 --- a/mysql-test/t/view_grant.test +++ b/mysql-test/t/view_grant.test @@ -718,5 +718,3 @@ show create view v1; show create view v2; drop view v1; drop view v2; - - diff --git a/sql/item_func.h b/sql/item_func.h index d8fa45fb9c0..ccbbbab1df4 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -1421,9 +1421,21 @@ public: String *val_str(String *str) { + String buf; + char buff[20]; + buf.set(buff, 20, str->charset()); + buf.length(0); if (execute(&result_field)) return NULL; - return result_field->val_str(str); + /* + result_field will set buf pointing to internal buffer + of the resul_field. Due to this it will change any time + when SP is executed. In order to prevent occasional + corruption of returned value, we make here a copy. + */ + result_field->val_str(&buf); + str->copy(buf); + return str; } virtual bool change_context_processor(byte *cntx) diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 43b7c494246..9310b65e44a 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -766,6 +766,18 @@ static const char *require_quotes(const char *name, uint name_length) } +/* + Quote the given identifier if needed and append it to the target string. + If the given identifier is empty, it will be quoted. + + SYNOPSIS + append_identifier() + thd thread handler + packet target string + name the identifier to be appended + name_length length of the appending identifier +*/ + void append_identifier(THD *thd, String *packet, const char *name, uint length) { @@ -819,8 +831,11 @@ append_identifier(THD *thd, String *packet, const char *name, uint length) length length of name IMPLEMENTATION - If name is a keyword or includes a special character, then force - quoting. + Force quoting in the following cases: + - name is empty (for one, it is possible when we use this function for + quoting user and host names for DEFINER clause); + - name is a keyword; + - name includes a special character; Otherwise identifier is quoted only if the option OPTION_QUOTE_SHOW_CREATE is set.