← Back to team overview

maria-developers team mailing list archive

Re: [Commits] 28fcccc: MDEV-5231: Per query variables from Percona Server (rewritten)

 

Hi, Sanja!

On Oct 13, sanja@xxxxxxxxxxx wrote:
> revision-id: 28fccccad32fa8a47dc572b968613e18ff51b634
> parent(s): fec5ab5a56cb9a45c621207620cc85079cddf537
> committer: Oleksandr Byelkin
> branch nick: work-maria-10.1-sysvar2
> timestamp: 2014-10-13 22:35:40 +0200
> message:
> 
> MDEV-5231: Per query variables from Percona Server (rewritten)

This looks a lot better that the previous patch. Thanks!
See my comments below.

Some parts of the patch are not used (left-overs from the old
implementation?). Some others, I think, are not needed.

And some of the old tests don't make much sense, your new tests made
them redundant and useless.

A couple of comments after reading my previous review:

* please add a test for any sysvar with non-trivial implementations of
  sys_var::session_update(), that is, for a sysvar where old approach
  doesn't work. Unless, of course, your timestamp tests are exactly that :)

* add tests with @@default_engine. For example:

  SET @@default_engine=MyISAM;
  SET STATEMENT @@default_engine=MEMORY CREATE TABLE t1 (a int);
  SHOW CREATE TABLE t1; -- verify the engine
  SET STATEMENT @@default_engine=MyISAM CREATE TABLE t2 (a int);

etc.

See other comments below:

> diff --git a/mysql-test/r/set_statement.result b/mysql-test/r/set_statement.result
> new file mode 100644
> index 0000000..fed937e
> --- /dev/null
> +++ b/mysql-test/r/set_statement.result
> @@ -0,0 +1,941 @@
> +'# SET STATEMENT ..... FOR ....  TEST'
> +DROP TABLE IF EXISTS t1;
> +DROP FUNCTION IF EXISTS myProc;
> +DROP PROCEDURE IF EXISTS p1;
> +DROP PROCEDURE IF EXISTS p2;
> +DROP PROCEDURE IF EXISTS p3;
> +DROP PROCEDURE IF EXISTS p4;
> +DROP PROCEDURE IF EXISTS p5;
> +DROP TABLE IF EXISTS STATEMENT;
> +'# Setup database'
> +CREATE TABLE t1 (v1 INT, v2 INT);
> +INSERT INTO t1 VALUES (1,2);
> +INSERT INTO t1 VALUES (3,4);
> +''
> +'#------------------ STATEMENT Test 1 -----------------------#'
> +'# Initialize variables to known setting'
> +SET SESSION sort_buffer_size=100000;
> +''
> +'# Pre-STATEMENT variable value'
> +SHOW SESSION VARIABLES LIKE 'sort_buffer_size';
> +Variable_name	Value
> +sort_buffer_size	100000
> +SET STATEMENT sort_buffer_size=150000 FOR SELECT *,@@sort_buffer_size FROM t1;
> +v1	v2	@@sort_buffer_size
> +1	2	150000
> +3	4	150000
> +''
> +'# Post-STATEMENT variable value'
> +SHOW SESSION VARIABLES LIKE 'sort_buffer_size';
> +Variable_name	Value
> +sort_buffer_size	100000
> +''
> +'#------------------ STATEMENT Test 2 -----------------------#'
> +'# Initialize variables to known setting'
> +SET SESSION binlog_format=mixed;
> +SET SESSION sort_buffer_size=100000;
> +'# Pre-STATEMENT variable value'
> +SHOW SESSION VARIABLES LIKE 'sort_buffer_size';
> +Variable_name	Value
> +sort_buffer_size	100000
> +SHOW SESSION VARIABLES LIKE 'binlog_format';
> +Variable_name	Value
> +binlog_format	MIXED
> +SET STATEMENT sort_buffer_size=150000, binlog_format=row
> +FOR SELECT *,@@sort_buffer_size,@@binlog_format FROM t1;
> +v1	v2	@@sort_buffer_size	@@binlog_format
> +1	2	150000	ROW
> +3	4	150000	ROW
> +'# Post-STATEMENT variable value'
> +SHOW SESSION VARIABLES LIKE 'sort_buffer_size';
> +Variable_name	Value
> +sort_buffer_size	100000
> +SHOW SESSION VARIABLES LIKE 'binlog_format';
> +Variable_name	Value
> +binlog_format	MIXED
> +''
> +'#------------------ STATEMENT Test 3 -----------------------#'
> +'# set initial variable value, make prepared statement
> +SET SESSION binlog_format=row;
> +PREPARE stmt1 FROM 'SET STATEMENT binlog_format=row FOR SELECT *,@@binlog_format FROM t1';
> +''
> +'# Change variable setting'
> +SET SESSION binlog_format=mixed;
> +''
> +'# Pre-STATEMENT variable value'
> +''
> +SHOW SESSION VARIABLES LIKE 'binlog_format';
> +Variable_name	Value
> +binlog_format	MIXED
> +''
> +EXECUTE stmt1;
> +v1	v2	@@binlog_format
> +1	2	ROW
> +3	4	ROW
> +''
> +'# Post-STATEMENT variable value'
> +SHOW SESSION VARIABLES LIKE 'binlog_format';
> +Variable_name	Value
> +binlog_format	MIXED
> +''
> +DEALLOCATE PREPARE stmt1;
> +'#------------------ STATEMENT Test 4 -----------------------#'
> +'# set initial variable value, make prepared statement
> +SET SESSION myisam_sort_buffer_size=500000, myisam_repair_threads=1;
> +''
> +'# Pre-STATEMENT variable value'
> +SHOW SESSION VARIABLES LIKE 'myisam_sort_buffer_size';
> +Variable_name	Value
> +myisam_sort_buffer_size	500000
> +SHOW SESSION VARIABLES LIKE 'myisam_repair_threads';
> +Variable_name	Value
> +myisam_repair_threads	1
> +''
> +SET STATEMENT myisam_sort_buffer_size=800000,
> +myisam_repair_threads=2 FOR OPTIMIZE TABLE t1;

1. this is not "make prepared statement" as the comment says
2. what does it actually test? you don't verify whether
   new values had any effect.

> +Table	Op	Msg_type	Msg_text
> +test.t1	optimize	status	OK
> +''
> +'# Post-STATEMENT variable value'
> +SHOW SESSION VARIABLES LIKE 'myisam_sort_buffer_size';
> +Variable_name	Value
> +myisam_sort_buffer_size	500000
> +SHOW SESSION VARIABLES LIKE 'myisam_repair_threads';
> +Variable_name	Value
> +myisam_repair_threads	1
> +''
> +'#------------------ STATEMENT Test 5 -----------------------#'
> +'# Initialize variables to known setting'
> +SET SESSION sort_buffer_size=100000;
> +''
> +'# Pre-STATEMENT variable value'
> +SHOW SESSION VARIABLES LIKE 'sort_buffer_size';
> +Variable_name	Value
> +sort_buffer_size	100000
> +''
> +SET STATEMENT sort_buffer_size=150000 FOR SELECT * FROM t2;
> +ERROR 42S02: Table 'test.t2' doesn't exist
> +''
> +'# Post-STATEMENT variable value'
> +SHOW SESSION VARIABLES LIKE 'sort_buffer_size';
> +Variable_name	Value
> +sort_buffer_size	150000

Looks wrong. The value is not restored in case of an error.

> +''
> +'#------------------ STATEMENT Test 6 -----------------------#'
> +'# Initialize variables to known setting'
> +SET SESSION  keep_files_on_create=ON;
> +''
> +'# Pre-STATEMENT variable value'
> +SHOW SESSION VARIABLES LIKE 'keep_files_on_create';
> +Variable_name	Value
> +keep_files_on_create	ON
> +''
> +SET STATEMENT keep_files_on_create=OFF FOR SELECT *,@@keep_files_on_create FROM t1;
> +v1	v2	@@keep_files_on_create
> +1	2	0
> +3	4	0

How is this test different from other tests above?

> +''
> +'# Post-STATEMENT variable value'
> +SHOW SESSION VARIABLES LIKE 'keep_files_on_create';
> +Variable_name	Value
> +keep_files_on_create	ON
> +''
> +'#------------------ STATEMENT Test 7 -----------------------#'
> +'# Initialize variables to known setting'
> +SET SESSION  max_join_size=2222220000000;
> +''
> +'# Pre-STATEMENT variable value'
> +SHOW SESSION VARIABLES LIKE 'max_join_size';
> +Variable_name	Value
> +max_join_size	2222220000000
> +''
> +SET STATEMENT max_join_size=1000000000000 FOR SELECT *,@@max_join_size FROM t1;
> +v1	v2	@@max_join_size
> +1	2	1000000000000
> +3	4	1000000000000

Same question - how is this test different from other tests above?

> +''
> +'# Post-STATEMENT variable value'
> +SHOW SESSION VARIABLES LIKE 'max_join_size';
> +Variable_name	Value
> +max_join_size	2222220000000
> +''
> +'#------------------Test 8-----------------------#'
> +'# Initialize test variables'
> +SET SESSION myisam_sort_buffer_size=500000,
> +myisam_repair_threads=1,
> +sort_buffer_size = 200000,
> +max_join_size=2222220000000,
> +keep_files_on_create=ON;
> +''
> +'#  LONG    '
> +SHOW SESSION VARIABLES LIKE 'sort_buffer_size';
> +Variable_name	Value
> +sort_buffer_size	200000
> +SET STATEMENT sort_buffer_size = 100000
> +FOR SHOW SESSION VARIABLES LIKE 'sort_buffer_size';
> +Variable_name	Value
> +sort_buffer_size	100000
> +SHOW SESSION VARIABLES LIKE 'sort_buffer_size';
> +Variable_name	Value
> +sort_buffer_size	200000
> +''
> +'# MY_BOOL     '
> +SHOW SESSION VARIABLES LIKE 'keep_files_on_create';
> +Variable_name	Value
> +keep_files_on_create	ON
> +SET STATEMENT keep_files_on_create=OFF
> +FOR SHOW SESSION VARIABLES LIKE 'keep_files_on_create';
> +Variable_name	Value
> +keep_files_on_create	OFF
> +SHOW SESSION VARIABLES LIKE 'keep_files_on_create';
> +Variable_name	Value
> +keep_files_on_create	ON
> +''
> +'# INT/LONG    '
> +SHOW SESSION VARIABLES LIKE 'myisam_repair_threads';
> +Variable_name	Value
> +myisam_repair_threads	1
> +SET STATEMENT myisam_repair_threads=2
> +FOR SHOW SESSION VARIABLES LIKE 'myisam_repair_threads';
> +Variable_name	Value
> +myisam_repair_threads	2
> +SHOW SESSION VARIABLES LIKE 'myisam_repair_threads';
> +Variable_name	Value
> +myisam_repair_threads	1
> +''
> +'# ULONGLONG     '
> +SHOW SESSION VARIABLES LIKE 'max_join_size';
> +Variable_name	Value
> +max_join_size	2222220000000
> +SET STATEMENT max_join_size=2000000000000
> +FOR SHOW SESSION VARIABLES LIKE 'max_join_size';
> +Variable_name	Value
> +max_join_size	2000000000000
> +SHOW SESSION VARIABLES LIKE 'max_join_size';
> +Variable_name	Value
> +max_join_size	2222220000000
> +''
> +'#------------------Test 9-----------------------#'
> +'# set initial variable values
> +SET SESSION myisam_sort_buffer_size=500000,
> +myisam_repair_threads=1,
> +sort_buffer_size=100000,
> +binlog_format=mixed,
> +keep_files_on_create=ON,
> +max_join_size=2222220000000;
> +''
> +''
> +'# Pre-STATEMENT variable value
> +SELECT @@myisam_sort_buffer_size,
> +@@myisam_repair_threads,
> +@@sort_buffer_size,
> +@@binlog_format,
> +@@keep_files_on_create,
> +@@max_join_size;
> +@@myisam_sort_buffer_size	@@myisam_repair_threads	@@sort_buffer_size	@@binlog_format	@@keep_files_on_create	@@max_join_size
> +500000	1	100000	MIXED	1	2222220000000
> +''
> +''
> +CREATE FUNCTION myProc (cost DECIMAL(10,2))
> +RETURNS DECIMAL(10,2)
> +SQL SECURITY DEFINER
> +tax: BEGIN
> +DECLARE order_tax DECIMAL(10,2);
> +SET order_tax = cost * .05;
> +RETURN order_tax;
> +END|
> +''
> +'# During Execution values
> +SET STATEMENT myisam_sort_buffer_size=400000,
> +myisam_repair_threads=2,
> +sort_buffer_size=200000,
> +binlog_format=row,
> +keep_files_on_create=OFF,
> +max_join_size=4444440000000 FOR
> +SELECT myProc(123.45);
> +myProc(123.45)
> +6.17

How does this verify that SET STATEMENT had any effect?

> +''
> +'# Post-STATEMENT No 1 variable value Pre-STATEMENT for No 2'
> +SELECT @@myisam_sort_buffer_size,
> +@@myisam_repair_threads,
> +@@sort_buffer_size,
> +@@binlog_format,
> +@@keep_files_on_create,
> +@@max_join_size;
> +@@myisam_sort_buffer_size	@@myisam_repair_threads	@@sort_buffer_size	@@binlog_format	@@keep_files_on_create	@@max_join_size
> +500000	1	100000	MIXED	1	2222220000000
> +''
> +SET STATEMENT myisam_sort_buffer_size=400000,
> +myisam_repair_threads=2,
> +sort_buffer_size=200000,
> +binlog_format=row,
> +keep_files_on_create=OFF,
> +max_join_size=4444440000000 FOR
> +DROP FUNCTION myProc;

How does this verify that SET STATEMENT had any effect?

> +''
> +'# Post-STATEMENT No 2 variable value
> +SELECT @@myisam_sort_buffer_size,
> +@@myisam_repair_threads,
> +@@sort_buffer_size,
> +@@binlog_format,
> +@@keep_files_on_create,
> +@@max_join_size;
> +@@myisam_sort_buffer_size	@@myisam_repair_threads	@@sort_buffer_size	@@binlog_format	@@keep_files_on_create	@@max_join_size
> +500000	1	100000	MIXED	1	2222220000000
> +''
> +'#------------------Test 10-----------------------#'
> +'# set initial variable values
> +SET SESSION myisam_sort_buffer_size=500000,
> +myisam_repair_threads=1,
> +sort_buffer_size=100000,
> +binlog_format=mixed,
> +keep_files_on_create=ON,
> +max_join_size=2222220000000;
> +''
> +'# Pre-STATEMENT variable value
> +SELECT @@myisam_sort_buffer_size,
> +@@myisam_repair_threads,
> +@@sort_buffer_size,
> +@@binlog_format,
> +@@keep_files_on_create,
> +@@max_join_size;
> +@@myisam_sort_buffer_size	@@myisam_repair_threads	@@sort_buffer_size	@@binlog_format	@@keep_files_on_create	@@max_join_size
> +500000	1	100000	MIXED	1	2222220000000
> +''
> +''
> +SET STATEMENT myisam_sort_buffer_size=400000,
> +myisam_repair_threads=2,
> +sort_buffer_size=200000,
> +binlog_format=row,
> +keep_files_on_create=OFF,
> +max_join_size=4444440000000 FOR
> +PREPARE stmt2
> +FROM 'SELECT * FROM t1';
> +''
> +'Test No 1 Post Value & Test 2 Pre values'
> +SELECT @@myisam_sort_buffer_size,
> +@@myisam_repair_threads,
> +@@sort_buffer_size,
> +@@binlog_format,
> +@@keep_files_on_create,
> +@@max_join_size;
> +@@myisam_sort_buffer_size	@@myisam_repair_threads	@@sort_buffer_size	@@binlog_format	@@keep_files_on_create	@@max_join_size
> +500000	1	100000	MIXED	1	2222220000000
> +''
> +''
> +SET STATEMENT myisam_sort_buffer_size=400000,
> +myisam_repair_threads=2,
> +sort_buffer_size=200000,
> +binlog_format=row,
> +keep_files_on_create=OFF,
> +max_join_size=4444440000000 FOR
> +EXECUTE stmt2;
> +v1	v2
> +1	2
> +3	4

How does this verify that SET STATEMENT had any effect?

Add @@binlog_format and @@sort_buffer_size to the SELECT
and use different values for @@sort_buffer_size in
SET STATEMENT for PREPARE and EXECUTE.

Ok, I see that you do it below. Then how is this test useful?

> +''
> +'# Post-STATEMENT No 2
> +SELECT @@myisam_sort_buffer_size,
> +@@myisam_repair_threads,
> +@@sort_buffer_size,
> +@@binlog_format,
> +@@keep_files_on_create,
> +@@max_join_size;
> +@@myisam_sort_buffer_size	@@myisam_repair_threads	@@sort_buffer_size	@@binlog_format	@@keep_files_on_create	@@max_join_size
> +500000	1	100000	MIXED	1	2222220000000
> +''
> +DEALLOCATE PREPARE stmt2;
> +''
> +'#------------------Test 11-----------------------#'
> +'# set initial variable values
> +SET SESSION myisam_sort_buffer_size=500000,
> +myisam_repair_threads=1,
> +sort_buffer_size=100000,
> +binlog_format=mixed,
> +keep_files_on_create=ON,
> +max_join_size=2222220000000;
> +''
> +''
> +'# Pre-STATEMENT variable value
> +SELECT @@myisam_sort_buffer_size,
> +@@myisam_repair_threads,
> +@@sort_buffer_size,
> +@@binlog_format,
> +@@keep_files_on_create,
> +@@max_join_size;
> +@@myisam_sort_buffer_size	@@myisam_repair_threads	@@sort_buffer_size	@@binlog_format	@@keep_files_on_create	@@max_join_size
> +500000	1	100000	MIXED	1	2222220000000
> +''
> +''
> +SET STATEMENT myisam_sort_buffer_size=400000,
> +myisam_repair_threads=2,
> +sort_buffer_size=200000,
> +keep_files_on_create=OFF,
> +max_join_size=4444440000000 FOR
> +PREPARE stmt1 FROM
> +'SET STATEMENT binlog_format=row FOR SELECT *,@@binlog_format FROM t1';

please also add @@sort_buffer_size to this SELECT

> +''
> +'Test No 1 Post Value & Test 2 Pre values'
> +SELECT @@myisam_sort_buffer_size,
> +@@myisam_repair_threads,
> +@@sort_buffer_size,
> +@@binlog_format,
> +@@keep_files_on_create,
> +@@max_join_size;
> +@@myisam_sort_buffer_size	@@myisam_repair_threads	@@sort_buffer_size	@@binlog_format	@@keep_files_on_create	@@max_join_size
> +500000	1	100000	MIXED	1	2222220000000
> +''
> +''
> +SET STATEMENT myisam_sort_buffer_size=400000,
> +myisam_repair_threads=2,
> +sort_buffer_size=200000,
> +keep_files_on_create=OFF,
> +max_join_size=4444440000000 FOR
> +EXECUTE stmt1;
> +v1	v2	@@binlog_format
> +1	2	ROW
> +3	4	ROW
> +''
> +'# Post-STATEMENT No 2
> +SELECT @@myisam_sort_buffer_size,
> +@@myisam_repair_threads,
> +@@sort_buffer_size,
> +@@binlog_format,
> +@@keep_files_on_create,
> +@@max_join_size;
> +@@myisam_sort_buffer_size	@@myisam_repair_threads	@@sort_buffer_size	@@binlog_format	@@keep_files_on_create	@@max_join_size
> +500000	1	100000	MIXED	1	2222220000000
> +''
> +''
> +'#------------------Test 12-----------------------#'
> +'# set initial variable values
> +SET SESSION myisam_sort_buffer_size=500000,
> +myisam_repair_threads=1,
> +sort_buffer_size=100000,
> +binlog_format=mixed,
> +keep_files_on_create=ON,
> +max_join_size=2222220000000;
> +''
> +''
> +'# Pre-STATEMENT variable value
> +SELECT @@myisam_sort_buffer_size,
> +@@myisam_repair_threads,
> +@@sort_buffer_size,
> +@@binlog_format,
> +@@keep_files_on_create,
> +@@max_join_size;
> +@@myisam_sort_buffer_size	@@myisam_repair_threads	@@sort_buffer_size	@@binlog_format	@@keep_files_on_create	@@max_join_size
> +500000	1	100000	MIXED	1	2222220000000
> +''
> +''
> +SET STATEMENT myisam_sort_buffer_size=400000,
> +myisam_repair_threads=2,
> +sort_buffer_size=200000,
> +binlog_format=row,
> +keep_files_on_create=OFF,
> +max_join_size=4444440000000 FOR
> +CREATE PROCEDURE p1() BEGIN
> +SELECT @@myisam_sort_buffer_size,
> +@@myisam_repair_threads,
> +@@sort_buffer_size,
> +@@binlog_format,
> +@@keep_files_on_create,
> +@@max_join_size;
> +END|
> +''
> +'Test No 1 Post Value & Test 2 Pre values'
> +SELECT @@myisam_sort_buffer_size,
> +@@myisam_repair_threads,
> +@@sort_buffer_size,
> +@@binlog_format,
> +@@keep_files_on_create,
> +@@max_join_size;
> +@@myisam_sort_buffer_size	@@myisam_repair_threads	@@sort_buffer_size	@@binlog_format	@@keep_files_on_create	@@max_join_size
> +500000	1	100000	MIXED	1	2222220000000
> +''
> +''
> +SET STATEMENT myisam_sort_buffer_size=400000,
> +myisam_repair_threads=2,
> +sort_buffer_size=200000,
> +binlog_format=row,
> +keep_files_on_create=OFF,
> +max_join_size=4444440000000 FOR

Use different values here, not same as in the previous SET STATEMENT

> +CALL p1();
> +@@myisam_sort_buffer_size	@@myisam_repair_threads	@@sort_buffer_size	@@binlog_format	@@keep_files_on_create	@@max_join_size
> +400000	2	200000	ROW	0	4444440000000
> +''
> +'# Post-STATEMENT No 2
> +SELECT @@myisam_sort_buffer_size,
> +@@myisam_repair_threads,
> +@@sort_buffer_size,
> +@@binlog_format,
> +@@keep_files_on_create,
> +@@max_join_size;
> +@@myisam_sort_buffer_size	@@myisam_repair_threads	@@sort_buffer_size	@@binlog_format	@@keep_files_on_create	@@max_join_size
> +500000	1	100000	MIXED	1	2222220000000
> +''
> +''
> +'#------------------Test 13-----------------------#'
> +'# set initial variable values
> +SET SESSION myisam_sort_buffer_size=500000,
> +myisam_repair_threads=1,
> +sort_buffer_size=100000,
> +binlog_format=mixed,
> +keep_files_on_create=ON,
> +max_join_size=2222220000000;
> +''
> +''
> +CREATE PROCEDURE p2() BEGIN
> +SET STATEMENT myisam_sort_buffer_size=400000,
> +myisam_repair_threads=3,
> +sort_buffer_size=300000,
> +binlog_format=mixed,
> +keep_files_on_create=OFF,
> +max_join_size=3333330000000 FOR
> +CALL p1();
> +END|
> +''
> +'# Pre-STATEMENT variable value
> +SELECT @@myisam_sort_buffer_size,
> +@@myisam_repair_threads,
> +@@sort_buffer_size,
> +@@binlog_format,
> +@@keep_files_on_create,
> +@@max_join_size;
> +@@myisam_sort_buffer_size	@@myisam_repair_threads	@@sort_buffer_size	@@binlog_format	@@keep_files_on_create	@@max_join_size
> +500000	1	100000	MIXED	1	2222220000000
> +''
> +''
> +SET STATEMENT myisam_sort_buffer_size=400000,
> +myisam_repair_threads=2,
> +sort_buffer_size=200000,
> +binlog_format=row,
> +keep_files_on_create=OFF,
> +max_join_size=4444440000000 FOR
> +CALL p2();
> +@@myisam_sort_buffer_size	@@myisam_repair_threads	@@sort_buffer_size	@@binlog_format	@@keep_files_on_create	@@max_join_size
> +400000	3	300000	MIXED	0	3333330000000
> +''
> +'# Post-STATEMENT
> +SELECT @@myisam_sort_buffer_size,
> +@@myisam_repair_threads,
> +@@sort_buffer_size,
> +@@binlog_format,
> +@@keep_files_on_create,
> +@@max_join_size;
> +@@myisam_sort_buffer_size	@@myisam_repair_threads	@@sort_buffer_size	@@binlog_format	@@keep_files_on_create	@@max_join_size
> +500000	1	100000	MIXED	1	2222220000000
> +''
> +''
> +'#------------------Test 14-----------------------#'
> +'# set initial variable values
> +SET SESSION myisam_sort_buffer_size=500000,
> +myisam_repair_threads=1,
> +sort_buffer_size=100000,
> +binlog_format=mixed,
> +keep_files_on_create=ON,
> +max_join_size=2222220000000;
> +''
> +''
> +CREATE PROCEDURE p3() BEGIN
> +SELECT @@myisam_sort_buffer_size,
> +@@myisam_repair_threads,
> +@@sort_buffer_size,
> +@@binlog_format,
> +@@keep_files_on_create,
> +@@max_join_size;
> +SET STATEMENT myisam_sort_buffer_size=320000,
> +myisam_repair_threads=2,
> +sort_buffer_size=220022,
> +binlog_format=row,
> +keep_files_on_create=ON,
> +max_join_size=2222220000000 FOR
> +CALL p2();
> +END|
> +''
> +'# Pre-STATEMENT variable value
> +SELECT @@myisam_sort_buffer_size,
> +@@myisam_repair_threads,
> +@@sort_buffer_size,
> +@@binlog_format,
> +@@keep_files_on_create,
> +@@max_join_size;
> +@@myisam_sort_buffer_size	@@myisam_repair_threads	@@sort_buffer_size	@@binlog_format	@@keep_files_on_create	@@max_join_size
> +500000	1	100000	MIXED	1	2222220000000
> +''
> +''
> +SET STATEMENT myisam_sort_buffer_size=400000,
> +myisam_repair_threads=2,
> +sort_buffer_size=200000,
> +binlog_format=row,
> +keep_files_on_create=OFF,
> +max_join_size=4444440000000 FOR
> +CALL p3();
> +@@myisam_sort_buffer_size	@@myisam_repair_threads	@@sort_buffer_size	@@binlog_format	@@keep_files_on_create	@@max_join_size
> +400000	2	200000	ROW	0	4444440000000
> +@@myisam_sort_buffer_size	@@myisam_repair_threads	@@sort_buffer_size	@@binlog_format	@@keep_files_on_create	@@max_join_size
> +400000	3	300000	MIXED	0	3333330000000
> +''
> +'# Post-STATEMENT
> +SELECT @@myisam_sort_buffer_size,
> +@@myisam_repair_threads,
> +@@sort_buffer_size,
> +@@binlog_format,
> +@@keep_files_on_create,
> +@@max_join_size;
> +@@myisam_sort_buffer_size	@@myisam_repair_threads	@@sort_buffer_size	@@binlog_format	@@keep_files_on_create	@@max_join_size
> +500000	1	100000	MIXED	1	2222220000000
> +''
> +''
> +''
> +''
> +'#------------------Test 15-----------------------#'
> +'# set initial variable values
> +SET SESSION myisam_sort_buffer_size=500000,
> +myisam_repair_threads=1,
> +sort_buffer_size=100000,
> +binlog_format=mixed,
> +keep_files_on_create=ON,
> +max_join_size=2222220000000;
> +''
> +''
> +CREATE PROCEDURE p4() BEGIN
> +SELECT @@myisam_sort_buffer_size,
> +@@myisam_repair_threads,
> +@@sort_buffer_size,
> +@@binlog_format,
> +@@keep_files_on_create,
> +@@max_join_size;
> +SET STATEMENT myisam_sort_buffer_size=320000,
> +myisam_repair_threads=2,
> +sort_buffer_size=220022,
> +binlog_format=row,
> +keep_files_on_create=ON,
> +max_join_size=2222220000000 FOR
> +SELECT @@myisam_sort_buffer_size,
> +@@myisam_repair_threads,
> +@@sort_buffer_size,
> +@@binlog_format,
> +@@keep_files_on_create,
> +@@max_join_size;
> +SET STATEMENT myisam_sort_buffer_size=320000,
> +myisam_repair_threads=2,
> +sort_buffer_size=220022,
> +binlog_format=row,
> +keep_files_on_create=ON,
> +max_join_size=2222220000000 FOR
> +SELECT @@myisam_sort_buffer_size,
> +@@myisam_repair_threads,
> +@@sort_buffer_size,
> +@@binlog_format,
> +@@keep_files_on_create,
> +@@max_join_size;
> +SET STATEMENT myisam_sort_buffer_size=320000,
> +myisam_repair_threads=2,
> +sort_buffer_size=220022,
> +binlog_format=row,
> +keep_files_on_create=ON,
> +max_join_size=2222220000000 FOR
> +SELECT @@myisam_sort_buffer_size,
> +@@myisam_repair_threads,
> +@@sort_buffer_size,
> +@@binlog_format,
> +@@keep_files_on_create,
> +@@max_join_size;
> +END|
> +''
> +'# Pre-STATEMENT variable value
> +SELECT @@myisam_sort_buffer_size,
> +@@myisam_repair_threads,
> +@@sort_buffer_size,
> +@@binlog_format,
> +@@keep_files_on_create,
> +@@max_join_size;
> +@@myisam_sort_buffer_size	@@myisam_repair_threads	@@sort_buffer_size	@@binlog_format	@@keep_files_on_create	@@max_join_size
> +500000	1	100000	MIXED	1	2222220000000
> +''
> +''
> +SET STATEMENT myisam_sort_buffer_size=400000,
> +myisam_repair_threads=2,
> +sort_buffer_size=200000,
> +binlog_format=row,
> +keep_files_on_create=OFF,
> +max_join_size=4444440000000 FOR
> +CALL p4();
> +@@myisam_sort_buffer_size	@@myisam_repair_threads	@@sort_buffer_size	@@binlog_format	@@keep_files_on_create	@@max_join_size
> +400000	2	200000	ROW	0	4444440000000
> +@@myisam_sort_buffer_size	@@myisam_repair_threads	@@sort_buffer_size	@@binlog_format	@@keep_files_on_create	@@max_join_size
> +320000	2	220022	ROW	1	2222220000000
> +@@myisam_sort_buffer_size	@@myisam_repair_threads	@@sort_buffer_size	@@binlog_format	@@keep_files_on_create	@@max_join_size
> +320000	2	220022	ROW	1	2222220000000
> +@@myisam_sort_buffer_size	@@myisam_repair_threads	@@sort_buffer_size	@@binlog_format	@@keep_files_on_create	@@max_join_size
> +320000	2	220022	ROW	1	2222220000000
> +''
> +'# Post-STATEMENT
> +SELECT @@myisam_sort_buffer_size,
> +@@myisam_repair_threads,
> +@@sort_buffer_size,
> +@@binlog_format,
> +@@keep_files_on_create,
> +@@max_join_size;
> +@@myisam_sort_buffer_size	@@myisam_repair_threads	@@sort_buffer_size	@@binlog_format	@@keep_files_on_create	@@max_join_size
> +500000	1	100000	MIXED	1	2222220000000
> +''
> +''
> +'#------------------Test 16-----------------------#'
> +''
> +'# Pre-STATEMENT variable value
> +SELECT @@sql_mode;
> +@@sql_mode
> +
> +''
> +''
> +SET STATEMENT sql_mode='ansi' FOR PREPARE stmt FROM 'SELECT "t1".* FROM t1';
> +execute stmt;
> +v1	v2
> +1	2
> +3	4

Ok, that's getting interesting. Now before deallocating, try to trigger
automatic reprepare. e.g. ALTER TABLE t1 ADD COLUMN v3 int;
and then execute it again.

also do the same with SP. I mean, set statement sql_mode=ansi create procedure
this procedure uses ansi quotes. verify that the correct sql mode (ansi)
is recorded in mysql.proc table.

> +deallocate prepare stmt;
> +''
> +'# Post-STATEMENT
> +SELECT @@sql_mode;
> +@@sql_mode
> +
> +''
> +''
> +'#------------------Test 17-----------------------#'
> +'# set initial variable values
> +SET SESSION myisam_sort_buffer_size=500000,
> +myisam_repair_threads=1,
> +sort_buffer_size=100000,
> +binlog_format=mixed,
> +keep_files_on_create=ON,
> +max_join_size=2222220000000;
> +''
> +'# Pre-STATEMENT variable value
> +SELECT @@myisam_sort_buffer_size,
> +@@myisam_repair_threads,
> +@@sort_buffer_size,
> +@@binlog_format,
> +@@keep_files_on_create,
> +@@max_join_size;
> +@@myisam_sort_buffer_size	@@myisam_repair_threads	@@sort_buffer_size	@@binlog_format	@@keep_files_on_create	@@max_join_size
> +500000	1	100000	MIXED	1	2222220000000
> +''
> +''
> +SET STATEMENT myisam_sort_buffer_size=320000,
> +myisam_repair_threads=2,
> +sort_buffer_size=220022,
> +binlog_format=row,
> +keep_files_on_create=ON,
> +max_join_size=2222220000000
> +FOR SET SESSION
> +myisam_sort_buffer_size=260000,
> +myisam_repair_threads=3,
> +sort_buffer_size=230013,
> +binlog_format=row,
> +keep_files_on_create=ON,
> +max_join_size=2323230000000;

Add a couple of other variables to SET SESSION. The point - have some
variables in SET SESSION that are *not* present in SET STATEMENT.
Verify that their values were correctly set.

Ok, I see that you do it below. Then how is this test useful?

> +''
> +'# Post-STATEMENT
> +SELECT @@myisam_sort_buffer_size,
> +@@myisam_repair_threads,
> +@@sort_buffer_size,
> +@@binlog_format,
> +@@keep_files_on_create,
> +@@max_join_size;
> +@@myisam_sort_buffer_size	@@myisam_repair_threads	@@sort_buffer_size	@@binlog_format	@@keep_files_on_create	@@max_join_size
> +500000	1	100000	MIXED	1	2222220000000
> +''
> +''
> +'#------------------Test 18-----------------------#'
> +'# set initial variable values
> +SET SESSION myisam_sort_buffer_size=500000,
> +myisam_repair_threads=1,
> +sort_buffer_size=100000,
> +binlog_format=mixed,
> +keep_files_on_create=ON,
> +max_join_size=2222220000000;
> +''
> +'# Pre-STATEMENT variable value
> +SELECT @@myisam_sort_buffer_size,
> +@@myisam_repair_threads,
> +@@sort_buffer_size,
> +@@binlog_format,
> +@@keep_files_on_create,
> +@@max_join_size;
> +@@myisam_sort_buffer_size	@@myisam_repair_threads	@@sort_buffer_size	@@binlog_format	@@keep_files_on_create	@@max_join_size
> +500000	1	100000	MIXED	1	2222220000000
> +''
> +''
> +CREATE PROCEDURE p5() BEGIN
> +SELECT @@myisam_sort_buffer_size,
> +@@myisam_repair_threads,
> +@@sort_buffer_size,
> +@@binlog_format,
> +@@keep_files_on_create,
> +@@max_join_size;
> +SET SESSION
> +myisam_sort_buffer_size=260000,
> +myisam_repair_threads=3,
> +sort_buffer_size=230013,
> +binlog_format=row,
> +keep_files_on_create=ON,
> +max_join_size=2323230000000;
> +SELECT @@myisam_sort_buffer_size,
> +@@myisam_repair_threads,
> +@@sort_buffer_size,
> +@@binlog_format,
> +@@keep_files_on_create,
> +@@max_join_size;
> +END|

How is this test different from other tests above?

> +''
> +''
> +SET STATEMENT myisam_sort_buffer_size=400000,
> +myisam_repair_threads=2,
> +sort_buffer_size=200000,
> +binlog_format=row,
> +keep_files_on_create=OFF,
> +max_join_size=4444440000000 FOR
> +CALL p5();
> +@@myisam_sort_buffer_size	@@myisam_repair_threads	@@sort_buffer_size	@@binlog_format	@@keep_files_on_create	@@max_join_size
> +400000	2	200000	ROW	0	4444440000000
> +@@myisam_sort_buffer_size	@@myisam_repair_threads	@@sort_buffer_size	@@binlog_format	@@keep_files_on_create	@@max_join_size
> +260000	3	230013	ROW	1	2323230000000
> +''
> +'# Post-STATEMENT
> +SELECT @@myisam_sort_buffer_size,
> +@@myisam_repair_threads,
> +@@sort_buffer_size,
> +@@binlog_format,
> +@@keep_files_on_create,
> +@@max_join_size;
> +@@myisam_sort_buffer_size	@@myisam_repair_threads	@@sort_buffer_size	@@binlog_format	@@keep_files_on_create	@@max_join_size
> +500000	1	100000	MIXED	1	2222220000000
> +''
> +''
> +'#------------------Test 19-----------------------#'
> +SET STATEMENT max_error_count=100 FOR;
> +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1
> +SET STATEMENT max_error_count=100 INSERT t1 VALUES (1,2);
> +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'INSERT t1 VALUES (1,2)' at line 1
> +SET STATEMENT FOR INSERT INTO t1 VALUES (1,2);
> +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'FOR INSERT INTO t1 VALUES (1,2)' at line 1
> +SET max_error_count=100 FOR INSERT INTO t1 VALUES (1,2);
> +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'FOR INSERT INTO t1 VALUES (1,2)' at line 1
> +SET max_error_count=100 FOR INSERT INTO t1 VALUES (1,2);

Same erroneous statement tested twice?

> +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'FOR INSERT INTO t1 VALUES (1,2)' at line 1
> +SET STATEMENT GLOBAL max_error_count=100 FOR INSERT INTO t1 VALUES (1,2);
> +ERROR HY000: Unknown system variable 'GLOBAL'
> +SET STATEMENT @@global.max_error_count=100 FOR INSERT INTO t1 VALUES (1,2);
> +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '@@global.max_error_count=100 FOR INSERT INTO t1 VALUES (1,2)' at line 1
> +''
> +''
> +'#------------------Test 20-----------------------#'
> +SET STATEMENT connect_timeout=100 FOR INSERT INTO t1 VALUES (1,2);
> +ERROR HY000: Variable 'connect_timeout' is a GLOBAL variable and should be set with SET GLOBAL
> +''
> +''
> +'#------------------Test 21-----------------------#'
> +SELECT @@myisam_sort_buffer_size, @@sort_buffer_size;
> +@@myisam_sort_buffer_size	@@sort_buffer_size
> +500000	100000
> +SET STATEMENT myisam_sort_buffer_size = 700000, sort_buffer_size = 3000000
> +FOR SET STATEMENT myisam_sort_buffer_size=200000
> +FOR SELECT @@myisam_sort_buffer_size, @@sort_buffer_size;
> +@@myisam_sort_buffer_size	@@sort_buffer_size
> +200000	100000
> +SELECT @@myisam_sort_buffer_size, @@sort_buffer_size;
> +@@myisam_sort_buffer_size	@@sort_buffer_size
> +500000	100000
> +''
> +''
> +'#------------------Test 22-----------------------#'
> +CREATE TABLE STATEMENT(a INT);
> +DROP TABLE STATEMENT;
> +''
> +'# Cleanup'
> +DROP TABLE t1;
> +DROP PROCEDURE p1;
> +DROP PROCEDURE p2;
> +DROP PROCEDURE p3;
> +DROP PROCEDURE p4;
> +DROP PROCEDURE p5;
> +CREATE TABLE t1 (v1 INT, v2 INT);
> +PREPARE stmt
> +FROM 'SELECT * FROM t1';
> +SET STATEMENT myisam_sort_buffer_size=400000,
> +myisam_repair_threads=(select max(v1) from t1),
> +sort_buffer_size=200000,
> +binlog_format=row,
> +keep_files_on_create=OFF,
> +max_join_size=4444440000000 FOR
> +EXECUTE stmt;
> +ERROR HY000: SET STATEMENT does not support using tables in the assignment variables expressions

Why do you need a prepared statement to test that error?

> +deallocate prepare stmt;
> +drop table t1;
> +set session binlog_format=mixed;
> +PREPARE stmt1 FROM 'SELECT @@binlog_format';
> +execute stmt1;
> +@@binlog_format
> +MIXED
> +set statement binlog_format=row for execute stmt1;
> +@@binlog_format
> +ROW
> +execute stmt1;
> +@@binlog_format
> +MIXED
> +deallocate prepare stmt1;
> +set statement binlog_format=row for PREPARE stmt1 FROM 'SELECT @@binlog_format';
> +execute stmt1;
> +@@binlog_format
> +MIXED
> +execute stmt1;
> +@@binlog_format
> +MIXED
> +deallocate prepare stmt1;
> +PREPARE stmt1 FROM 'set statement binlog_format=row for SELECT @@binlog_format';
> +execute stmt1;
> +@@binlog_format
> +ROW
> +execute stmt1;
> +@@binlog_format
> +ROW
> +deallocate prepare stmt1;
> +set session binlog_format=default;
> +set session binlog_format=mixed;
> +SET STATEMENT sort_buffer_size=150000 FOR set session binlog_format=row;
> +SELECT @@binlog_format;
> +@@binlog_format
> +ROW

those are good tests, and they make many of the tests above unnecessary

> +#Correctly set timestamp
> +set session timestamp=4646464;
> +select @@timestamp != 4646464;
> +@@timestamp != 4646464
> +0
> +select @@timestamp != 4646464;
> +@@timestamp != 4646464
> +0
> +#Correctly returned normal behaviour
> +set session timestamp=default;
> +select @@timestamp != 4646464;
> +@@timestamp != 4646464
> +1
> +select @@timestamp != 4646464;
> +@@timestamp != 4646464
> +1
> +#here timestamp should be set only for the statement then restored default
> +set statement timestamp=4646464 for select @@timestamp;
> +@@timestamp
> +4646464.000000
> +set @save_tm=@@timestamp;
> +select @@timestamp != 4646464;
> +@@timestamp != 4646464
> +1
> +select @@timestamp != 4646464;
> +@@timestamp != 4646464
> +1
> +select @@timestamp != @save_tm;
> +@@timestamp != @save_tm
> +1
> diff --git a/sql/set_var.cc b/sql/set_var.cc
> index bae6511..20e3040 100644
> --- a/sql/set_var.cc
> +++ b/sql/set_var.cc
> @@ -147,7 +147,7 @@ void sys_var_end()
>    flags(flags_arg), show_val_type(show_val_type_arg),
>    guard(lock), offset(off), on_check(on_check_func), on_update(on_update_func),
>    deprecation_substitute(substitute),
> -  is_os_charset(FALSE)
> +  is_os_charset(FALSE), default_val(TRUE)

I've asked below why is that needed.

>  {
>    /*
>      There is a limitation in handle_options() related to short options:
> @@ -695,7 +695,8 @@ int sql_set_variables(THD *thd, List<set_var_base> *var_list)
>    }
>  
>  err:
> -  free_underlaid_joins(thd, &thd->lex->select_lex);
> +  if (free)
> +    free_underlaid_joins(thd, &thd->lex->select_lex);

Ok, so in normal SET you want to free_underlaid_joins,
and in SET STATEMENT you don't. Right?

>    DBUG_RETURN(error);
>  }
>  
> diff --git a/sql/item_func.cc b/sql/item_func.cc
> index 2b89aa0..651e0b1 100644
> --- a/sql/item_func.cc
> +++ b/sql/item_func.cc
> @@ -5556,7 +5556,7 @@ longlong Item_func_get_user_var::val_int()
>      tmp_var_list.push_back(new set_var_user(new Item_func_set_user_var(name,
>                                                                         new Item_null())));
>      /* Create the variable */
> -    if (sql_set_variables(thd, &tmp_var_list))
> +    if (sql_set_variables(thd, &tmp_var_list, true))

Make if 'false', not 'true' here. It doesn't make any practical difference
(there are no joins, the variable is set to Item_null, explicitly),
but makes the logic a bit clearer (standalone SET statement = free joins,
a SET that is part of another statement = don't free joins).

Alternatively (and better) approach would be to remove sql_set_variables()
here and use the same code that Item_func_set_user_var does.

And then sql_set_variables() will be only used in SET variants, where
a sysvar can be used. Here sysvars aren't possible, so sql_set_variables() is
misleading.

>      {
>        thd->lex= sav_lex;
>        goto err;
> diff --git a/sql/set_var.h b/sql/set_var.h
> index e48f394..9ee914b 100644
> --- a/sql/set_var.h
> +++ b/sql/set_var.h
> @@ -118,6 +119,9 @@ class sys_var
>    */
>    bool set_default(THD *thd, set_var *var);
>    bool update(THD *thd, set_var *var);
> +  void stmt_update(THD *thd) {
> +    on_update && on_update(this, thd, OPT_SESSION);
> +  }

Doesn't seem to be used anywhere in the patch

>  
>    String *val_str_nolock(String *str, THD *thd, const uchar *value);
>    longlong val_int(bool *is_null, THD *thd, enum_var_type type, const LEX_STRING *base);
> diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt
> index 233bb83..4072af4 100644
> --- a/sql/share/errmsg-utf8.txt
> +++ b/sql/share/errmsg-utf8.txt
> @@ -7110,3 +7110,5 @@ ER_SLAVE_SKIP_NOT_IN_GTID
>  	eng "When using GTID, @@sql_slave_skip_counter can not be used. Instead, setting @@gtid_slave_pos explicitly can be used to skip to after a given GTID position."
>  ER_STATEMENT_TIMEOUT 70100
>          eng "Query execution was interrupted (max_statement_time exceeded)"
> +ER_SET_STATEMENT_TABLES_IS_NOT_SUPPORTED
> +        eng "SET STATEMENT does not support using tables in the assignment variables expressions"

Better write it as

ER_SUBQUERIES_NOT_SUPPORTED
    eng "%s does not support subqueries or stored functions."

and use it for SET STATEMENT:

  my_error(ER_SUBQUERIES_NOT_SUPPORTED, MYF(0), "SET STATEMENT");

and also use it for KILL:

- my_error(ER_NOT_SUPPORTED_YET, MYF(0), "Usage of subqueries or stored "
-          "function calls as part of this statement");
+ my_error(ER_SUBQUERIES_NOT_SUPPORTED, MYF(0), "KILL");

> diff --git a/sql/sql_class.h b/sql/sql_class.h
> index d7bbfc3..0f6b39e 100644
> --- a/sql/sql_class.h
> +++ b/sql/sql_class.h
> @@ -3711,6 +3711,10 @@ class THD :public Statement,
>    void rgi_unlock_temporary_tables();
>    bool rgi_have_temporary_tables();
>  public:
> +  inline MEM_ROOT *get_execution_mem_root()
> +  {
> +    return &main_mem_root;
> +  }

Doesn't seem to be used anywhere in this patch

>    /*
>      Flag, mutex and condition for a thread to wait for a signal from another
>      thread.
> diff --git a/sql/sql_lex.h b/sql/sql_lex.h
> index 5e9c7b9..03861d1 100644
> --- a/sql/sql_lex.h
> +++ b/sql/sql_lex.h
> @@ -2379,6 +2381,8 @@ struct LEX: public Query_tables_list
>      required a local context, the parser pops the top-most context.
>    */
>    List<Name_resolution_context> context_stack;
> +  /* true if SET STATEMENT ... FOR ... statement is use, false otherwise */
> +  bool set_statement;

This doesn't seem to be needed, I've checked all places where
set_statement is used below.

>  
>    SQL_I_List<ORDER> proc_list;
>    SQL_I_List<TABLE_LIST> auxiliary_table_list, save_list;
> diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
> index d8906b2..eff0e08 100644
> --- a/sql/sql_parse.cc
> +++ b/sql/sql_parse.cc
> @@ -2637,6 +2637,98 @@ static bool do_execute_sp(THD *thd, sp_head *sp)
>    thd->get_binlog_format(&orig_binlog_format,
>                           &orig_current_stmt_binlog_format);
>  
> +  if (lex->set_statement && !lex->stmt_var_list.is_empty())

Why do you check lex->set_statement? I'd think that

  if (!lex->stmt_var_list.is_empty())

is quite enough.

> +  {
> +    DBUG_PRINT("info", ("SET STATEMENT %d vars", lex->stmt_var_list.elements));
> +
> +    lex->old_var_list.empty();
> +    List_iterator_fast<set_var_base> it(lex->stmt_var_list);
> +    set_var_base *var;
> +    while ((var=it++))
> +    {
> +      DBUG_ASSERT(var->is_system());
> +      set_var *o= NULL, *v= (set_var*)var;
> +      if (v->var->is_default())
> +          o= new set_var(v->type, v->var, &v->base, NULL);

Why do you treat default values differently?

> +      else
> +      {
> +        switch (v->var->option.var_type)
> +        {
> +        case GET_BOOL:
> +        case GET_INT:
> +        case GET_LONG:
> +        case GET_LL:
> +          {
> +            bool null_value;
> +            longlong val= v->var->val_int(&null_value, thd, v->type, &v->base);
> +            o= new set_var(v->type, v->var, &v->base,
> +                           (null_value ?
> +                            (Item *)new Item_null() :
> +                            (Item *)new Item_int(val)));
> +          }
> +          break;
> +        case GET_UINT:
> +        case GET_ULONG:
> +        case GET_ULL:
> +          {
> +            bool null_value;
> +            ulonglong val= v->var->val_int(&null_value, thd, v->type, &v->base);
> +            o= new set_var(v->type, v->var, &v->base,
> +                           (null_value ?
> +                            (Item *)new Item_null() :
> +                            (Item *)new Item_uint(val)));
> +          }
> +          break;
> +        case GET_DOUBLE:
> +          {
> +            bool null_value;
> +            double val= v->var->val_real(&null_value, thd, v->type, &v->base);
> +            o= new set_var(v->type, v->var, &v->base,
> +                           (null_value ?
> +                            (Item *)new Item_null() :
> +                            (Item *)new Item_float(val, 1)));
> +          }
> +          break;
> +        default:
> +        case GET_NO_ARG:
> +        case GET_DISABLED:
> +          DBUG_ASSERT(0);
> +        case 0:
> +        case GET_FLAGSET:
> +        case GET_ASK_ADDR:
> +        case GET_TYPE_MASK:
> +        case GET_ENUM:
> +        case GET_SET:
> +        case GET_STR:
> +        case GET_STR_ALLOC:
> +          {
> +            char buff[STRING_BUFFER_USUAL_SIZE];
> +            String tmp(buff, sizeof(buff), v->var->charset(thd)),*val;
> +            val= v->var->val_str(&tmp, thd, v->type, &v->base);
> +            if (val)
> +            {
> +              Item_string *str= new Item_string(v->var->charset(thd));
> +              str->set_str_with_copy(val->ptr(), val->length());
> +              o= new set_var(v->type, v->var, &v->base, str);
> +            }
> +            else
> +              o= new set_var(v->type, v->var, &v->base, new Item_null());
> +          }
> +          break;
> +        }
> +      }
> +      DBUG_ASSERT(o);
> +      lex->old_var_list.push_back(o);
> +    }
> +    if (thd->is_error() ||
> +        (res= sql_set_variables(thd, &lex->stmt_var_list, false)))
> +    {
> +      if (!thd->is_error())
> +        my_error(ER_WRONG_ARGUMENTS, MYF(0), "SET");
> +      goto error;
> +    }
> +  }
> +
>    /*
>      Force statement logging for DDL commands to allow us to update
>      privilege, system or statistic tables directly without the updates
> @@ -2812,6 +2904,12 @@ static bool do_execute_sp(THD *thd, sp_head *sp)
>    }
>    case SQLCOM_EXECUTE:
>    {
> +    /*
> +      Clean up free_list here from Items used in setting statement variables
> +      to present clear item list to Prepared_statement::execute_loop which
> +      need it empty because switch arena (and so item list) on statement arena.
> +    */
> +    //free_items(thd->free_list); thd->free_list= NULL;

Eh? Forgot to remove it?

>      mysql_sql_stmt_execute(thd);
>      break;
>    }
> diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc
> index 9ae3d79..4b54989 100644
> --- a/sql/sql_plugin.cc
> +++ b/sql/sql_plugin.cc
> @@ -4078,3 +4078,48 @@ static void restore_ptr_backup(uint n, st_ptr_backup *backup)
>      (backup++)->restore();
>  }
>  
> +
> +/**
> +  Create deep copy of system_variables instance.
> +*/
> +struct system_variables *
> +copy_system_variables(const struct system_variables *src)

Doesn't seem to be used anywhere in the patch

> +{
> +  struct system_variables *dst;
> +
> +  DBUG_ASSERT(src);
> +
> +  dst= (struct system_variables *)
> +    sql_alloc(sizeof(struct system_variables));
> +  if (!dst)
> +    return NULL;
> +  *dst= *src;
> +
> +  if (dst->dynamic_variables_ptr)
> +  {
> +    if (!(dst->dynamic_variables_ptr=
> +          (char *)my_malloc(dst->dynamic_variables_size, MYF(MY_WME | MY_FAE))))
> +      return NULL;
> +    memcpy(dst->dynamic_variables_ptr,
> +           src->dynamic_variables_ptr,
> +           src->dynamic_variables_size);
> +  }
> +
> +  mysql_mutex_lock(&LOCK_plugin);
> +  dst->table_plugin=
> +    intern_plugin_lock(NULL, src->table_plugin);
> +  mysql_mutex_unlock(&LOCK_plugin);
> +
> +  return dst;
> +}
> +
> +void free_system_variables(struct system_variables *v)

Doesn't seem to be used anywhere in the patch

> +{
> +  DBUG_ASSERT(v);
> +
> +  mysql_mutex_lock(&LOCK_plugin);
> +  intern_plugin_unlock(NULL, v->table_plugin);
> +  mysql_mutex_unlock(&LOCK_plugin);
> +
> +  my_free(v->dynamic_variables_ptr);
> +}
> diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
> index e7fcdfb..d140597 100644
> --- a/sql/sql_yacc.yy
> +++ b/sql/sql_yacc.yy
> @@ -14416,8 +14420,52 @@ set:
>            }
>            start_option_value_list
>            {}
> +        | SET STATEMENT_SYM
> +          {
> +            LEX *lex= Lex;
> +            mysql_init_select(lex);
> +            lex->sql_command= SQLCOM_SET_OPTION;
> +	    /* Don't clear var_list in the case of recursive statement */

What's "recursive set statement"? SET STATEMENT a=1 FOR SET STATEMENT ?
I'd simply return a syntax error here. Like

   MYSQL_YYABORT_UNLESS(lex->stmt_var_list.is_empty());

> +	    if (!lex->set_statement)
> +            {
> +              lex->var_list.empty();
> +              lex->stmt_var_list.empty();

Why here, and not in lex_start() ?

> +            }
> +            lex->autocommit= 0;
> +            lex->set_statement= true;
> +            sp_head *sp= lex->sphead;
> +            if (sp && !sp->is_invoked())
> +            {
> +              sp->m_param_begin= ((yychar == YYEMPTY) ?  YYLIP->get_ptr() : YYLIP->get_tok_start());
> +              sp->m_param_end= ((yychar == YYEMPTY) ?  YYLIP->get_ptr() : YYLIP->get_tok_end());

what's that?

> +            }
> +          }
> +          set_stmt_option_value_following_option_type_list
> +          {
> +            LEX *lex= Lex;
> +            if (lex->query_tables)
> +            {
> +              my_error(ER_SET_STATEMENT_TABLES_IS_NOT_SUPPORTED, MYF(0));

why? what about stored functions that use tables internally?

> +              MYSQL_YYABORT;
> +            }
> +            //if (lex->set_statement && lex->stmt_var_list.is_empty())
> +            {
> +              lex->stmt_var_list= lex->var_list;
> +              lex->var_list.empty();
> +            }
> +          }
> +          FOR_SYM statement 
> +	  {}
>          ;
>  
> +set_stmt_option_value_following_option_type_list:
> +       /*
> +         Only system variables can be used here. If this condition is changed
> +         please check careful code under lex->option_type == OPT_STATEMENT
> +         condition on wrong type casts.
> +       */
> +          option_value_following_option_type
> +        | set_stmt_option_value_following_option_type_list ',' option_value_following_option_type
>  
>  // Start of option value list
>  start_option_value_list:
> @@ -14522,6 +14570,14 @@ option_value_following_option_type:
>            {
>              LEX *lex= Lex;
>  
> +            /*
> +              Ignore SET STATEMENT variables list on slaves because system
> +              variables are not replicated except certain variables set the
> +              values of whose are written to binlog event header and nothing
> +              additional is required to set them.
> +            */
> +            if (!(thd->slave_thread && lex->set_statement))
> +            {

Hmm, okay. Alternatively, you can simply make sure that set statement
is not written into binlog. Or don't execute assignments in the slave thread.

>              if ($1.var && $1.var != trg_new_row_fake_var)
>              {
>                /* It is a system variable. */

Regards,
Sergei


Follow ups