Merge lp://qastaging/~vlad-lesin/percona-server/5.6-per_query_variables_settings into lp://qastaging/percona-server/5.6
- 5.6-per_query_variables_settings
- Merge into 5.6
Status: | Merged |
---|---|
Approved by: | Alexey Kopytov |
Approved revision: | no longer in the source branch. |
Merged at revision: | 477 |
Proposed branch: | lp://qastaging/~vlad-lesin/percona-server/5.6-per_query_variables_settings |
Merge into: | lp://qastaging/percona-server/5.6 |
Diff against target: |
2284 lines (+2107/-18) 13 files modified
Percona-Server/mysql-test/r/percona_statement_set.result (+862/-0) Percona-Server/mysql-test/suite/rpl/include/percona_rpl_set_statement_variable_test.inc (+31/-0) Percona-Server/mysql-test/suite/rpl/r/percona_rpl_stm_per_query_variables_settings.result (+143/-0) Percona-Server/mysql-test/suite/rpl/t/percona_rpl_stm_per_query_variables_settings.test (+57/-0) Percona-Server/mysql-test/t/percona_statement_set.test (+830/-0) Percona-Server/sql/lex.h (+1/-0) Percona-Server/sql/set_var.h (+3/-0) Percona-Server/sql/sql_lex.cc (+1/-0) Percona-Server/sql/sql_lex.h (+2/-1) Percona-Server/sql/sql_parse.cc (+47/-0) Percona-Server/sql/sql_plugin.cc (+66/-0) Percona-Server/sql/sql_plugin.h (+9/-0) Percona-Server/sql/sql_yacc.yy (+55/-17) |
To merge this branch: | bzr merge lp://qastaging/~vlad-lesin/percona-server/5.6-per_query_variables_settings |
Related bugs: | |
Related blueprints: |
Per query variable statement
(Medium)
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Alexey Kopytov (community) | Approve | ||
Laurynas Biveinis (community) | Needs Fixing | ||
Review via email:
|
Commit message
Description of the change
This is implementation of this https:/
Jenkins: http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Laurynas Biveinis (laurynas-biveinis) wrote : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Vlad Lesin (vlad-lesin) wrote : | # |
> - How does it replicate? Would a test be needed for that?
> https:/
There are the following types of variables:
1) variables that are NOT replicated correctly when using STATEMENT mode;
2) variables thar ARE replicated correctly when using STATEMENT mode;
3) sql_mode which is replicated correctly exept NO_DIR_IN_CREATE value;
4) variables that are not replicated at all:
default_
1)
But as we can set variables in a statements itself and that statements are written to binlog in STATEMENT mode and old values of variables are restored just after statement execution it works correctly.
2)
That variables are saved in Query_log_event on master for each event and restored on slave in Query_log_
3)
The NO_DIR_IN_CREATE mode is reset just before event applying on slave in Query_log_
4)
The same is for 3.
> - Please add tests for invalid syntax
Done.
> - Please add tests for global-only variable use attempts
Done
> - Since it is supported only for variables with certain show type,
> please test that variables with unsupported show types are
> rejected correctly.
Done.
> - set_stmt_reset_vars shouldn't assume that the update back to the
> original value might possibly fail. I.e. it can fail, but that
> should be a fatal assertion in a debug build. Thus instead of
> if (!var->check(thd))
> error|= var->update(thd);
> I'd do something like
> DBUG_ASSERT(
> error|= var->update(thd);
> DBUG_ASSERT(
Done.
> - Please add CREATE TABLE STATEMENT(a INT) test to a testcase
Done.
> - Lines 2063--2067: one_shot is removed as of 5.6.1.
But thd->one_shot and lex->one_shot are still in the code. And it's resonable to take them into account while they are still there.
> - Lines 2093--2094: can this free list swap cause that something
> non related to the per-statement vars might get freed late as
> well? If that's not the case, then a
> DBUG_ASSERT(
> loop call woul...
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Vlad Lesin (vlad-lesin) wrote : | # |
Rebased to new code.
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Alexey Kopytov (akopytov) wrote : | # |
It looks like tests have not been committed after rebasing.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Alexey Kopytov (akopytov) wrote : | # |
- the following assertion
+ if (lex->sql_command == SQLCOM_EXECUTE || lex->sql_command == SQLCOM_PREPARE)
+ {
+ DBUG_ASSERT(
+ thd->free_list= stmt_free_list;
+ }
would fail in the following case:
SET global_
because if an error occurs in one of the set_stmt_
we bail out before saving and resetting thd->free_list.
- the following code will not be resetting variables to their previous
values in release builds (i.e. var->update() will not be called at
all):
+ while ((var = it++))
+ {
+ DBUG_ASSERT(
+ DBUG_ASSERT(
+ }
- variable length array in set_stmt_
You actually don't even need another buffer for the var name, and
another LEX_STRING variable. what's wrong with using a pointer to
var->var->name directly?
- switch() in set_stmt_
options. What about SHOW_BOOL, SHOW_DOUBLE, SHOW_SIGNED_LONG, etc.?
- please remove all changes related to ONE_SHOT
- the following code should be wrapped into #ifndef DBUG_OFF:
+ if(thd-
+ DBUG_ASSERT(
- in general, I would implement it all differently. Just replace
thd->variables with its deep copy before statement execution, then
destroy it after statement execution and assign the original pointer
to thd->variables. This way you don't have to mess with option
types, Item instances, thd->free_list, etc. I guess the patch would
be 50% smaller and more robust against future changes.
- replication. No system variables are replicated except a small
subset which is listed in the manual. But variables from that subset
are written to the binlog event header. Which means a slave should
ignore _all_ statement variables and we don't need
filter_
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Vlad Lesin (vlad-lesin) wrote : | # |
> - the following assertion
>
> + if (lex->sql_command == SQLCOM_EXECUTE || lex->sql_command ==
> SQLCOM_PREPARE)
> + {
> + DBUG_ASSERT(
> + thd->free_list= stmt_free_list;
> + }
>
> would fail in the following case:
>
> SET global_
>
> because if an error occurs in one of the set_stmt_
> we bail out before saving and resetting thd->free_list.
>
> - the following code will not be resetting variables to their previous
> values in release builds (i.e. var->update() will not be called at
> all):
>
> + while ((var = it++))
> + {
> + DBUG_ASSERT(
> + DBUG_ASSERT(
> + }
>
> - variable length array in set_stmt_
> You actually don't even need another buffer for the var name, and
> another LEX_STRING variable. what's wrong with using a pointer to
> var->var->name directly?
>
> - switch() in set_stmt_
> options. What about SHOW_BOOL, SHOW_DOUBLE, SHOW_SIGNED_LONG, etc.?
>
The above comments do not make sense because the feature is implemented in another way now.
> - please remove all changes related to ONE_SHOT
>
Done.
> - the following code should be wrapped into #ifndef DBUG_OFF:
>
> + if(thd-
> + DBUG_ASSERT(
>
Done.
> - in general, I would implement it all differently. Just replace
> thd->variables with its deep copy before statement execution, then
> destroy it after statement execution and assign the original pointer
> to thd->variables. This way you don't have to mess with option
> types, Item instances, thd->free_list, etc. I guess the patch would
> be 50% smaller and more robust against future changes.
Done.
> - replication. No system variables are replicated except a small
> subset which is listed in the manual. But variables from that subset
> are written to the binlog event header. Which means a slave should
> ignore _all_ statement variables and we don't need
> filter_
Done.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Vlad Lesin (vlad-lesin) wrote : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Alexey Kopytov (akopytov) wrote : | # |
Debug builds fail.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Vlad Lesin (vlad-lesin) wrote : | # |
> Debug builds fail.
Fixed.
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Alexey Kopytov (akopytov) wrote : | # |
- the comment for LEX::set_statement says:
“The number of recursive SET STATEMENT ... FOR ... statements“
but the variable has the ‘bool’ type?
- but it got me wondering what happens with recursive SET STATEMENT
statements, and indeed they don’t work as one would expect,
i.e. only the innermost SET STATEMENT has an effect, and the outer
ones seem to be ignored. This doesn’t look like a serious limitation
and I’m fine with documenting it, but are there are real reasons for
this behavior? It looks like making in work correctly is a matter of
not calling lex->var_
- the patch introduces a new Bison warning:
“...sql/
action: <NONE> != <>”
because it doesn’t define an action after “set_stmt_
- do you really need set_var:
place in the code. It returns a value, but the only place where it is
called doesn’t care about its return value. What gives?
- the following change leads to server allocating 816 bytes on stack
for all queries, even those not using per-query variables.
---
@@ -2419,6 +2419,8 @@ mysql_execute_
/* have table map for update for multi-update statement (BUG#37051) */
bool have_table_
#endif
+ struct system_variables per_query_
+
DBUG_
DBUG_
---
let’s allocate it on heap instead?
- I guess changes in sql_prepare.cc are no longer required and can be
reverted?
- please rename rpl_* files to percona_rpl_*
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Vlad Lesin (vlad-lesin) wrote : | # |
On 09/22/2013 05:06 PM, Alexey Kopytov wrote:
> Review: Needs Fixing
>
> - the comment for LEX::set_statement says:
> “The number of recursive SET STATEMENT ... FOR ... statements“
>
> but the variable has the ‘bool’ type?
Yes, I forgot to change this comment, initially this variable was ulint.
But bool is enough even for recursive use. Fixed.
> - but it got me wondering what happens with recursive SET STATEMENT
> statements, and indeed they don’t work as one would expect,
> i.e. only the innermost SET STATEMENT has an effect, and the outer
> ones seem to be ignored. This doesn’t look like a serious limitation
> and I’m fine with documenting it, but are there are real reasons for
> this behavior? It looks like making in work correctly is a matter of
> not calling lex->var_
Fixed, new test case #21 in mysql-test/
added.
But this implementation has disadvantage. In the case of "SET STATEMENT
... FOR SET SESSION ..." query lex->var_list will be cleared when SET
SESSION is parsed, so all variables settings in SET STATEMENT section
will be cleared. The solution could be in using separate list for
statement variables. But in this case all variables which was set in
"SET SESSION" part will be reset to pre-statement state as
thd->variables will be completely restored after statement execution.
> - the patch introduces a new Bison warning:
>
> “...sql/
> action: <NONE> != <>”
>
> because it doesn’t define an action after “set_stmt_
Fixed.
> - do you really need set_var:
> place in the code. It returns a value, but the only place where it is
> called doesn’t care about its return value. What gives?
Return type is changed to "void". But this function is still necessary
because sys_var::on_update is protected.
> - the following change leads to server allocating 816 bytes on stack
> for all queries, even those not using per-query variables.
>
> ---
> @@ -2419,6 +2419,8 @@ mysql_execute_
> /* have table map for update for multi-update statement (BUG#37051) */
> bool have_table_
> #endif
> + struct system_variables per_query_
> +
> DBUG_ENTER(
> DBUG_ASSERT(
> ---
>
> let’s allocate it on heap instead?
Done.
> - I guess changes in sql_prepare.cc are no longer required and can be
> reverted?
No, they are still required because objects of "Item" class are
allocated during parsing and thd->free_list contains list of those objects.
> - please rename rpl_* files to percona_rpl_*
Done.
Here is new testing
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Alexey Kopytov (akopytov) wrote : | # |
Hi Vlad,
On Mon, 23 Sep 2013 10:27:28 +0400, Vlad Lesin wrote:
>> - I guess changes in sql_prepare.cc are no longer required and can be
>> reverted?
> No, they are still required because objects of "Item" class are
> allocated during parsing and thd->free_list contains list of those objects.
>
OK, I see it now. Shouldn't we instead of adjusting the assertion in
sql_prepare.cc just reset thd->free_list after calling
sql_set_variables() in mysql_execute_
the previous implementation, but is possible now, right?
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Alexey Kopytov (akopytov) wrote : | # |
Vlad,
Conflicts, please rebase on trunk.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Vlad Lesin (vlad-lesin) wrote : | # |
> Conflicts, please rebase on trunk.
Rebased.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Vlad Lesin (vlad-lesin) wrote : | # |
> Hi Vlad,
>
> On Mon, 23 Sep 2013 10:27:28 +0400, Vlad Lesin wrote:
>
> >> - I guess changes in sql_prepare.cc are no longer required and can be
> >> reverted?
> > No, they are still required because objects of "Item" class are
> > allocated during parsing and thd->free_list contains list of those objects.
> >
>
> OK, I see it now. Shouldn't we instead of adjusting the assertion in
> sql_prepare.cc just reset thd->free_list after calling
> sql_set_variables() in mysql_execute_
> the previous implementation, but is possible now, right?
Resetting thd->free_list after each sql_set_variables() call does not work right because thd->free_list can contain "Item" class instances not only from SET STATEMENT parsing. If fixes in sql_prepare.cc are not desirable thd->free_list can be released in SQLCOM_EXECUTE command handler in mysql_execute_
The following note was ignored but I consider it is very important and it should be discussed:
---
But this implementation has disadvantage. In the case of "SET STATEMENT
... FOR SET SESSION ..." query lex->var_list will be cleared when SET
SESSION is parsed, so all variables settings in SET STATEMENT section
will be cleared. The solution could be in using separate list for
statement variables. But in this case all variables which was set in
"SET SESSION" part will be reset to pre-statement state as
thd->variables will be completely restored after statement execution.
---
My suggestions:
1) Forbid using "SET" as a statement after "FOR" keyword. But the problem will not go because SET SESSION can be used in SP or prepared query.
2) Use separate list of parsed variables for SET and SET STATEMENT ... FOR ... statements
3) Check if SET STATEMENT ... FOR ... was parsed in SQLCOM_SET_OPTION handler in mysql_execute_
Here is new code testing results:
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Alexey Kopytov (akopytov) wrote : | # |
Hi Vlad,
On Fri, 27 Sep 2013 21:29:46 -0000, Vlad Lesin wrote:>> Hi Vlad,
>>
>> On Mon, 23 Sep 2013 10:27:28 +0400, Vlad Lesin wrote:
>>
>>>> - I guess changes in sql_prepare.cc are no longer required and can be
>>>> reverted?
>>> No, they are still required because objects of "Item" class are
>>> allocated during parsing and thd->free_list contains list of those objects.
>>>
>>
>> OK, I see it now. Shouldn't we instead of adjusting the assertion in
>> sql_prepare.cc just reset thd->free_list after calling
>> sql_set_variables() in mysql_execute_
>> the previous implementation, but is possible now, right?
>
> Resetting thd->free_list after each sql_set_variables() call does not work right because thd->free_list can contain "Item" class instances not only from SET STATEMENT parsing. If fixes in sql_prepare.cc are not desirable thd->free_list can be released in SQLCOM_EXECUTE command handler in mysql_execute_
>
Right, but I think the current way is more correct than adjusting the assertion in Prepared_
> The following note was ignored but I consider it is very important and it should be discussed:
> ---
> But this implementation has disadvantage. In the case of "SET STATEMENT
> ... FOR SET SESSION ..." query lex->var_list will be cleared when SET
> SESSION is parsed, so all variables settings in SET STATEMENT section
> will be cleared. The solution could be in using separate list for
> statement variables. But in this case all variables which was set in
> "SET SESSION" part will be reset to pre-statement state as
> thd->variables will be completely restored after statement execution.
> ---
>
I don't think SET STATEMENT ... FOR SET SESSSION ... is a "very important" case. I'm fine with documenting it as a known limitation and figuring out a way to fix it, if and when someone gets unhappy about it.
Approved.
- How does it replicate? Would a test be needed for that? /dev.mysql. com/doc/ refman/ 5.6/en/ replication- features- variables. html ASSERT( var->check( thd)); ASSERT( !error) ; ASSERT( !thd->free_ list) before the set_stmt_ get_reset_ vars assignment_ lex() call warnings; idiom in the testcase. get_reset_ vars header comment: s/will retrieve/retrieves
https:/
- Please add tests for invalid syntax
- Please add tests for global-only variable use attempts
- Since it is supported only for variables with certain show type,
please test that variables with unsupported show types are
rejected correctly.
- set_stmt_reset_vars shouldn't assume that the update back to the
original value might possibly fail. I.e. it can fail, but that
should be a fatal assertion in a debug build. Thus instead of
if (!var->check(thd))
error|= var->update(thd);
I'd do something like
DBUG_
error|= var->update(thd);
DBUG_
- Please add CREATE TABLE STATEMENT(a INT) test to a testcase
- Lines 2063--2067: one_shot is removed as of 5.6.1.
- Lines 2093--2094: can this free list swap cause that something
non related to the per-statement vars might get freed late as
well? If that's not the case, then a
DBUG_
loop call would document this. But if it is the case, then care
must be taken to remove only per-statement var Item instances
from the thd->free_list.
- Lines 2106--2112 and 2127--2135: please factor out to a common
function.
- Should lines 2240--2244 be sp_create_
instead?
- Spurious line 2260.
Minor comments:
- Please use the disable_warnings; DROP TABLE IF EXISTS;
enable_
- The test depends on t1 being MyISAM. Please either spell it out
by ENGINE=MyISAM, either look into future-proofing the test by
using an InnoDB table instead (that would require adjusting Test
4 accordingly).
- Testcase comments: s/check/check that/g where appropriate.
- set_stmt_
- body comment: s/ans/and
- Diff line 2022: s/Variables list/Variable list
- Diff line 2086: s/fot/for