489 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
		
		
			
		
	
	
			489 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
|  | # func_rollback.test | ||
|  | # | ||
|  | # Test variations inspired by  | ||
|  | # Bug#12713 Error in a stored function called from a SELECT doesn't cause | ||
|  | #           ROLLBACK of statement | ||
|  | # Essential of the bug: | ||
|  | # - A SELECT using a FUNCTION processes a table. | ||
|  | # - The SELECT affects more than row. | ||
|  | # - The FUNCTION modifies a table. | ||
|  | # - When processing the non first matching row, the function fails. | ||
|  | #   But the modification caused by the function when the SELECT processed the | ||
|  | #   first matching row is not reverted. | ||
|  | #    | ||
|  | # Goal of this test:  Attempts to catch a situation where | ||
|  | # - a statement A involving the execution of one or more functions is run | ||
|  | # - the function/functions themself contain one or more statements | ||
|  | #   modifying a table | ||
|  | # - one of the modifying statements within one of the functions fails | ||
|  | # - the table remains at least partially modified | ||
|  | # | ||
|  | # = There is no automatic ROLLBACK of changes caused by the failing | ||
|  | #     statement A. | ||
|  | # = Statement A is not atomic. | ||
|  | # | ||
|  | # Notes: | ||
|  | # - The table to be modified must use a transactional storage engine. | ||
|  | #   For example MyISAM cannot avoid the situation above. | ||
|  | # - Some comments assume that the rows of the table t1_select are processed | ||
|  | #   in the order of insertion. That means | ||
|  | #      SELECT f1,f2 FROM t1_select | ||
|  | #   should have the same result set and row order like | ||
|  | #   SELECT f1,f2 FROM t1_select ORDER BY f1; | ||
|  | # - The manual says that we get in non strict sql mode a warning around INSERT: | ||
|  | #   Inserting NULL into a column that has been declared NOT NULL. | ||
|  | #   For multiple-row INSERT statements or INSERT INTO ... SELECT statements, | ||
|  | #   the column is set to the implicit default value for the column data type. | ||
|  | # | ||
|  | # Created: | ||
|  | # 2008-04-09 mleich | ||
|  | # | ||
|  | 
 | ||
|  | let $fixed_bug_35877 = 0; | ||
|  | 
 | ||
|  | let $from_select = SELECT 1 AS f1,1 AS f2 UNION ALL SELECT 1,NULL; | ||
|  | 
 | ||
|  | --source include/have_innodb.inc | ||
|  | let $engine = InnoDB; | ||
|  | 
 | ||
|  | --disable_warnings | ||
|  | DROP TABLE IF EXISTS t1_select; | ||
|  | DROP TABLE IF EXISTS t1_aux; | ||
|  | DROP TABLE IF EXISTS t1_not_null; | ||
|  | DROP VIEW IF EXISTS v1_not_null; | ||
|  | DROP VIEW IF EXISTS v1_func; | ||
|  | DROP TABLE IF EXISTS t1_fail; | ||
|  | DROP FUNCTION IF EXISTS f1_simple_insert; | ||
|  | DROP FUNCTION IF EXISTS f1_two_inserts; | ||
|  | DROP FUNCTION IF EXISTS f1_insert_select; | ||
|  | --enable_warnings | ||
|  | 
 | ||
|  | SET SESSION AUTOCOMMIT=0; | ||
|  | SET SESSION sql_mode = ''; | ||
|  | 
 | ||
|  | CREATE TABLE t1_select (f1 BIGINT, f2 BIGINT) ENGINE = MEMORY; | ||
|  | INSERT INTO t1_select(f1,f2) VALUES (1,-1),(2,NULL),(3,0),(4,1),(5,2); | ||
|  | SELECT * FROM t1_select; | ||
|  | 
 | ||
|  | --replace_result $engine <transactional_engine> | ||
|  | eval | ||
|  | CREATE TABLE t1_not_null (f1 BIGINT, f2 BIGINT NOT NULL) | ||
|  | ENGINE = $engine; | ||
|  | SELECT * FROM t1_not_null; | ||
|  | 
 | ||
|  | --replace_result $engine <transactional_engine> | ||
|  | eval | ||
|  | CREATE TABLE t1_aux (f1 BIGINT, f2 BIGINT) | ||
|  | ENGINE = $engine; | ||
|  | SELECT * FROM t1_aux; | ||
|  | COMMIT; | ||
|  | 
 | ||
|  | # FUNCTION with "simple" INSERT | ||
|  | delimiter //; | ||
|  | CREATE FUNCTION f1_simple_insert(my_f1 INTEGER) RETURNS INTEGER | ||
|  | BEGIN | ||
|  |    INSERT INTO t1_not_null SET f1 = 10, f2 = my_f1; | ||
|  |    RETURN 1; | ||
|  | END// | ||
|  | delimiter ;// | ||
|  | 
 | ||
|  | --echo | ||
|  | --echo # One f1_simple_insert execution per row, no NOT NULL violation | ||
|  | SELECT f1_simple_insert(1); | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | ROLLBACK; | ||
|  | SELECT * FROM t1_not_null; | ||
|  | # | ||
|  | SELECT f1_simple_insert(1) FROM t1_select; | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | ROLLBACK; | ||
|  | SELECT * FROM t1_not_null; | ||
|  | 
 | ||
|  | --echo | ||
|  | --echo # One f1_simple_insert execution per row, NOT NULL violation when the | ||
|  | --echo # SELECT processes the first row. | ||
|  | --error ER_BAD_NULL_ERROR | ||
|  | SELECT f1_simple_insert(NULL); | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | ROLLBACK; | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | # | ||
|  | --error ER_BAD_NULL_ERROR | ||
|  | SELECT f1_simple_insert(NULL) FROM t1_select; | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | ROLLBACK; | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | # | ||
|  | --error ER_BAD_NULL_ERROR | ||
|  | eval SELECT 1 FROM ($from_select) AS t1 WHERE f1_simple_insert(NULL) = 1; | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | ROLLBACK; | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | 
 | ||
|  | --echo | ||
|  | --echo # One f1_simple_insert execution per row, NOT NULL violation when the | ||
|  | --echo # SELECT processes the non first row | ||
|  | --error ER_BAD_NULL_ERROR | ||
|  | eval SELECT f1_simple_insert(f2) FROM ($from_select) AS t1; | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | ROLLBACK; | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | # | ||
|  | --error ER_BAD_NULL_ERROR | ||
|  | SELECT f1_simple_insert(f2) FROM t1_select; | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | ROLLBACK; | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | 
 | ||
|  | --echo | ||
|  | --echo # Two f1_simple_insert executions per row, NOT NULL violation when the | ||
|  | --echo # SELECT processes the first row. | ||
|  | --error ER_BAD_NULL_ERROR | ||
|  | SELECT f1_simple_insert(1),f1_simple_insert(NULL); | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | ROLLBACK; | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | # | ||
|  | --error ER_BAD_NULL_ERROR | ||
|  | SELECT f1_simple_insert(NULL),f1_simple_insert(1); | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | ROLLBACK; | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | 
 | ||
|  | --echo | ||
|  | --echo # Two f1_simple_insert executions per row, NOT NULL violation when the | ||
|  | --echo # SELECT processes the non first row | ||
|  | --error ER_BAD_NULL_ERROR | ||
|  | eval SELECT f1_simple_insert(f1),f1_simple_insert(f2) FROM ($from_select) AS t1; | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | ROLLBACK; | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | # | ||
|  | --error ER_BAD_NULL_ERROR | ||
|  | eval SELECT f1_simple_insert(f2),f1_simple_insert(f1) FROM ($from_select) AS t1; | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | ROLLBACK; | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | # | ||
|  | --error ER_BAD_NULL_ERROR | ||
|  | SELECT f1_simple_insert(f1),f1_simple_insert(f2) FROM t1_select; | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | ROLLBACK; | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | # | ||
|  | --error ER_BAD_NULL_ERROR | ||
|  | SELECT f1_simple_insert(f2),f1_simple_insert(f1) FROM t1_select; | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | ROLLBACK; | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | # | ||
|  | --error ER_BAD_NULL_ERROR | ||
|  | eval SELECT 1 FROM ($from_select) AS t1 | ||
|  | WHERE 1 = f1_simple_insert(f2) AND 1 = f1_simple_insert(f1); | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | ROLLBACK; | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | 
 | ||
|  | --echo | ||
|  | --echo # Nested functions, the inner fails | ||
|  | --error ER_BAD_NULL_ERROR | ||
|  | SELECT f1_simple_insert(f1_simple_insert(NULL)) FROM t1_select; | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | ROLLBACK; | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | --echo | ||
|  | --echo # Nested functions, the outer fails | ||
|  | --error ER_BAD_NULL_ERROR | ||
|  | SELECT f1_simple_insert(f1_simple_insert(1) + NULL) FROM t1_select; | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | ROLLBACK; | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | DROP FUNCTION f1_simple_insert; | ||
|  | 
 | ||
|  | # FUNCTION with INSERT ... SELECT | ||
|  | delimiter //; | ||
|  | let $f1_insert_select = | ||
|  | CREATE FUNCTION f1_insert_select(my_f1 INTEGER) RETURNS INTEGER | ||
|  | BEGIN | ||
|  |    INSERT INTO t1_not_null SELECT * FROM t1_select WHERE f1 = my_f1; | ||
|  |    RETURN 1; | ||
|  | END// | ||
|  | delimiter ;// | ||
|  | eval $f1_insert_select; | ||
|  | # | ||
|  | --echo | ||
|  | --echo # f1_insert_select(2), tries to INSERT SELECT one row containing NULL | ||
|  | --echo # The fact that | ||
|  | --echo # - SELECT f1_insert_select(2);     gives any result set    and | ||
|  | --echo # - t1_not_null gets a row inserted | ||
|  | --echo # is covered by the manual. | ||
|  | # Non strict sqlmode + INSERT SELECT --> NULL adjusted to default | ||
|  | SELECT f1_insert_select(2); | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | ROLLBACK; | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | DROP FUNCTION f1_insert_select; | ||
|  | # | ||
|  | SET SESSION sql_mode = 'traditional'; | ||
|  | eval $f1_insert_select; | ||
|  | --error ER_BAD_NULL_ERROR | ||
|  | SELECT f1_insert_select(2); | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | ROLLBACK; | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | DROP FUNCTION f1_insert_select; | ||
|  | SET SESSION sql_mode = ''; | ||
|  | 
 | ||
|  | # FUNCTION with two simple INSERTs | ||
|  | --echo | ||
|  | --echo # Function tries to | ||
|  | --echo #    1. INSERT statement: Insert one row with NULL -> NOT NULL violation | ||
|  | --echo #    2. INSERT statement: Insert one row without NULL | ||
|  | # I guess the execution of the function becomes aborted just when the | ||
|  | # error happens. | ||
|  | delimiter //; | ||
|  | CREATE FUNCTION f1_two_inserts() RETURNS INTEGER | ||
|  | BEGIN | ||
|  |    INSERT INTO t1_not_null SET f1 = 10, f2 = NULL; | ||
|  |    INSERT INTO t1_not_null SET f1 = 10, f2 = 10; | ||
|  |    RETURN 1; | ||
|  | END// | ||
|  | delimiter ;// | ||
|  | --error ER_BAD_NULL_ERROR | ||
|  | SELECT f1_two_inserts(); | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | ROLLBACK; | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | DROP FUNCTION f1_two_inserts; | ||
|  | # | ||
|  | --echo | ||
|  | --echo # Function tries to | ||
|  | --echo #    1. INSERT statement: Insert one row without NULL | ||
|  | --echo #    2. INSERT statement: Insert one row with NULL -> NOT NULL violation | ||
|  | delimiter //; | ||
|  | CREATE FUNCTION f1_two_inserts() RETURNS INTEGER | ||
|  | BEGIN | ||
|  |    INSERT INTO t1_not_null SET f1 = 10, f2 = 10; | ||
|  |    INSERT INTO t1_not_null SET f1 = 10, f2 = NULL; | ||
|  |    RETURN 1; | ||
|  | END// | ||
|  | delimiter ;// | ||
|  | --error ER_BAD_NULL_ERROR | ||
|  | SELECT f1_two_inserts(); | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | ROLLBACK; | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | 
 | ||
|  | --echo | ||
|  | --echo # Function tries to | ||
|  | --echo #    INSERT statement: Insert two rows | ||
|  | --echo #                      first row without NULL | ||
|  | --echo #                      second row with NULL -> NOT NULL violation | ||
|  | --echo #       -> NOT NULL violation | ||
|  | delimiter //; | ||
|  | let $f1_insert_with_two_rows = | ||
|  | CREATE FUNCTION f1_insert_with_two_rows() RETURNS INTEGER | ||
|  | BEGIN | ||
|  |    INSERT INTO t1_not_null(f1,f2) VALUES (10,10),(10,NULL); | ||
|  |    RETURN 1; | ||
|  | END// | ||
|  | delimiter ;// | ||
|  | eval $f1_insert_with_two_rows; | ||
|  | --echo # The fact that | ||
|  | --echo # - SELECT f1_insert_with_two_rows();     gives any result set    and | ||
|  | --echo # - t1_not_null gets a row inserted | ||
|  | --echo # is covered by the manual. | ||
|  | # Non strict sqlmode + multiple-row INSERT --> NULL adjusted to default | ||
|  | SELECT f1_insert_with_two_rows(); | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | ROLLBACK; | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | DROP FUNCTION f1_insert_with_two_rows; | ||
|  | # | ||
|  | SET SESSION sql_mode = 'traditional'; | ||
|  | eval $f1_insert_with_two_rows; | ||
|  | --error ER_BAD_NULL_ERROR | ||
|  | SELECT f1_insert_with_two_rows(); | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | ROLLBACK; | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | SET SESSION sql_mode = ''; | ||
|  | 
 | ||
|  | --echo | ||
|  | --echo # FUNCTION in Correlated Subquery | ||
|  | --error ER_BAD_NULL_ERROR | ||
|  | SELECT 1 FROM t1_select t1 | ||
|  | WHERE 1 = (SELECT f1_insert_with_two_rows() FROM t1_select t2 | ||
|  |            WHERE t2.f1 = t1.f1); | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | ROLLBACK; | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | 
 | ||
|  | --echo | ||
|  | --echo # FUNCTION in JOIN | ||
|  | --error ER_BAD_NULL_ERROR | ||
|  | SELECT 1 FROM t1_select t1, t1_select t2 | ||
|  | WHERE t1.f1 = t2.f1 AND t2.f1 = f1_insert_with_two_rows(); | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | ROLLBACK; | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | # | ||
|  | --error ER_BAD_NULL_ERROR | ||
|  | SELECT STRAIGHT_JOIN * FROM t1_select t2 RIGHT JOIN t1_select t1 | ||
|  | ON t1.f1 = t1.f1 WHERE 1 = f1_insert_with_two_rows(); | ||
|  | 
 | ||
|  | DROP FUNCTION f1_insert_with_two_rows; | ||
|  | 
 | ||
|  | --echo | ||
|  | --echo # FUNCTION in UNION | ||
|  | --error ER_BAD_NULL_ERROR | ||
|  | SELECT 1 | ||
|  | UNION ALL | ||
|  | SELECT f1_two_inserts(); | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | ROLLBACK; | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | 
 | ||
|  | --echo | ||
|  | --echo # FUNCTION in INSERT | ||
|  | --error ER_BAD_NULL_ERROR | ||
|  | INSERT INTO t1_aux SET f1 = 1, f2 = f1_two_inserts(); | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | ROLLBACK; | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | # | ||
|  | --error ER_BAD_NULL_ERROR | ||
|  | INSERT INTO t1_aux SELECT 1, f1_two_inserts(); | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | ROLLBACK; | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | SELECT * FROM t1_aux ORDER BY f1,f2; | ||
|  | # | ||
|  | --error ER_BAD_NULL_ERROR | ||
|  | INSERT INTO t1_aux VALUES(1,f1_two_inserts()); | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | SELECT * FROM t1_aux ORDER BY f1,f2; | ||
|  | 
 | ||
|  | --echo | ||
|  | --echo # FUNCTION in DELETE | ||
|  | INSERT INTO t1_aux VALUES (1,1); | ||
|  | COMMIT; | ||
|  | --error ER_BAD_NULL_ERROR | ||
|  | DELETE FROM t1_aux WHERE f1 = f1_two_inserts(); | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | ROLLBACK; | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | SELECT * FROM t1_aux ORDER BY f1,f2; | ||
|  | 
 | ||
|  | --echo | ||
|  | --echo # FUNCTION in UPDATE SET | ||
|  | # FUNCTION in SET | ||
|  | --error ER_BAD_NULL_ERROR | ||
|  | UPDATE t1_aux SET f2 = f1_two_inserts() + 1; | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | ROLLBACK; | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | SELECT * FROM t1_aux ORDER BY f1,f2; | ||
|  | # | ||
|  | if ($fixed_bug_35877) | ||
|  | { | ||
|  | --echo | ||
|  | --echo # FUNCTION in UPDATE WHERE | ||
|  | # Bug#35877 Update .. WHERE with function, constraint violation, crash | ||
|  | UPDATE t1_aux SET f2 = 2 WHERE f1 = f1_two_inserts(); | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | ROLLBACK; | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | SELECT * FROM t1_aux ORDER BY f1,f2; | ||
|  | } | ||
|  | 
 | ||
|  | --echo | ||
|  | --echo # FUNCTION in VIEW definition | ||
|  | CREATE VIEW v1_func AS SELECT f1_two_inserts() FROM t1_select; | ||
|  | --error ER_BAD_NULL_ERROR | ||
|  | SELECT * FROM v1_func; | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | ROLLBACK; | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | DROP VIEW v1_func; | ||
|  | 
 | ||
|  | --echo | ||
|  | --echo # FUNCTION in CREATE TABLE ... AS SELECT | ||
|  | --error ER_BAD_NULL_ERROR | ||
|  | CREATE TABLE t1_fail AS SELECT f1_two_inserts() FROM t1_select; | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | # | ||
|  | --error ER_BAD_NULL_ERROR | ||
|  | CREATE TABLE t1_fail AS SELECT * FROM t1_select WHERE 1 = f1_two_inserts(); | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | # | ||
|  | 
 | ||
|  | --echo | ||
|  | --echo # FUNCTION in ORDER BY | ||
|  | --error ER_BAD_NULL_ERROR | ||
|  | SELECT * FROM t1_select ORDER BY f1,f1_two_inserts(); | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | 
 | ||
|  | --echo | ||
|  | --echo # FUNCTION in aggregate function | ||
|  | --error ER_BAD_NULL_ERROR | ||
|  | SELECT AVG(f1_two_inserts()) FROM t1_select; | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | 
 | ||
|  | --echo | ||
|  | --echo # FUNCTION in HAVING | ||
|  | --error ER_BAD_NULL_ERROR | ||
|  | SELECT 1 FROM t1_select HAVING AVG(f1) = f1_two_inserts() + 2; | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | DROP FUNCTION f1_two_inserts; | ||
|  | 
 | ||
|  | --echo | ||
|  | --echo # FUNCTION modifies Updatable VIEW | ||
|  | CREATE VIEW v1_not_null AS SELECT f1,f2 FROM t1_not_null WITH CHECK OPTION; | ||
|  | delimiter //; | ||
|  | CREATE FUNCTION f1_two_inserts_v1() RETURNS INTEGER | ||
|  | BEGIN | ||
|  |    INSERT INTO v1_not_null SET f1 = 10, f2 = 10; | ||
|  |    INSERT INTO v1_not_null SET f1 = 10, f2 = NULL; | ||
|  |    RETURN 1; | ||
|  | END// | ||
|  | delimiter ;// | ||
|  | --error ER_BAD_NULL_ERROR | ||
|  | SELECT f1_two_inserts_v1(); | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | ROLLBACK; | ||
|  | SELECT * FROM t1_not_null ORDER BY f1,f2; | ||
|  | DROP FUNCTION f1_two_inserts_v1; | ||
|  | DROP VIEW v1_not_null; | ||
|  | 
 | ||
|  | --echo | ||
|  | --echo # FUNCTION causes FOREIGN KEY constraint violation | ||
|  | eval | ||
|  | CREATE TABLE t1_parent (f1 BIGINT, f2 BIGINT, PRIMARY KEY(f1)) | ||
|  | ENGINE = $engine; | ||
|  | INSERT INTO t1_parent VALUES (1,1); | ||
|  | eval | ||
|  | CREATE TABLE t1_child (f1 BIGINT, f2 BIGINT, PRIMARY KEY(f1), | ||
|  | FOREIGN KEY (f1) REFERENCES t1_parent(f1)) | ||
|  | ENGINE = $engine; | ||
|  | --error ER_NO_REFERENCED_ROW_2 | ||
|  | delimiter //; | ||
|  | CREATE FUNCTION f1_two_inserts() RETURNS INTEGER | ||
|  | BEGIN | ||
|  |    INSERT INTO t1_child SET f1 = 1, f2 = 1; | ||
|  |    INSERT INTO t1_child SET f1 = 2, f2 = 2; | ||
|  |    RETURN 1; | ||
|  | END// | ||
|  | delimiter ;// | ||
|  | --error ER_NO_REFERENCED_ROW_2 | ||
|  | SELECT f1_two_inserts(); | ||
|  | SELECT * FROM t1_child; | ||
|  | DROP TABLE t1_child; | ||
|  | DROP TABLE t1_parent; | ||
|  | DROP FUNCTION f1_two_inserts; | ||
|  | 
 | ||
|  | # Cleanup | ||
|  | DROP TABLE t1_select; | ||
|  | DROP TABLE t1_aux; | ||
|  | DROP TABLE t1_not_null; |