← Back to team overview

maria-developers team mailing list archive

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

 

Hi, Oleksandr!

On Oct 21, Oleksandr Byelkin wrote:
> >
> > * 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);
> Done. I think that to test other & current engine is enough because we 
> test variable not engines and using 2 engine which always present makes 
> the test simpler.

The point was to test plugin locking. When you change a default engine,
old engine plugin is unlocked, new engine plugin is locked.

In the debug mode there's a code to assert that locks and unlocks are
correctly paired.

It doesn't matter what two engines you use, so your tests are ok.

> >> +'#------------------ 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
> Yes, probably mistake of test creator (cut'n'paste?)
> > 2. what does it actually test? you don't verify whether
> >     new values had any effect.
> I have no idea how to check the effect, but maybe it is testing crash...

I think it's just one of those useless tests that doesn't test anything.
There were many of them in the original patch.

> >> +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.
> fixed. It was problem that sql_set_variables was not working correctly 
> is you enter it with already happened error.

But the test was good, I hope you kept it.

> >> +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?
> I have no idea what is verified here (crash, syntax, or just test suite 
> was strange from the beginning?)

Again, one of many useless tests in the original patch, I suppose.

> >> 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.
> For some variables (like timestamp) default value is not a certain value 
> but a special state (timestamp in such state returns current time 
> instead of fixed value).

> >> +      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?
> because default value is not just a value for some variables, but 
> special state.

And here's the review:

> diff --git a/mysql-test/r/events_bugs.result b/mysql-test/r/events_bugs.result
> index e359921..95fc690 100644
> --- a/mysql-test/r/events_bugs.result
> +++ b/mysql-test/r/events_bugs.result
> @@ -218,13 +218,13 @@ drop event events_test.mysqltest_user1;
>  drop user mysqltest_user1@localhost;
>  drop database mysqltest_db1;
>  create event e_53 on schedule at (select s1 from ttx) do drop table t;
> -ERROR 42000: This version of MariaDB doesn't yet support 'Usage of subqueries or stored function calls as part of this statement'
> +ERROR HY000: CREATE/ALTER EVENT does not support subqueries or stored functions.

SQLSTATE 42000 looks fine, please change your error message to use it

>  create event e_53 on schedule every (select s1 from ttx) second do drop table t;
> -ERROR 42000: This version of MariaDB doesn't yet support 'Usage of subqueries or stored function calls as part of this statement'
> +ERROR HY000: CREATE/ALTER EVENT does not support subqueries or stored functions.
>  create event e_53 on schedule every 5 second starts (select s1 from ttx) do drop table t;
> -ERROR 42000: This version of MariaDB doesn't yet support 'Usage of subqueries or stored function calls as part of this statement'
> +ERROR HY000: CREATE/ALTER EVENT does not support subqueries or stored functions.
>  create event e_53 on schedule every 5 second ends (select s1 from ttx) do drop table t;
> -ERROR 42000: This version of MariaDB doesn't yet support 'Usage of subqueries or stored function calls as part of this statement'
> +ERROR HY000: CREATE/ALTER EVENT does not support subqueries or stored functions.
>  drop event if exists e_16;
>  drop procedure if exists p_16;
>  create event e_16 on schedule every 1 second do set @a=5;
> diff --git a/mysql-test/t/set_statement.test b/mysql-test/t/set_statement.test
> index 3ea9235..9a2e577 100644
> --- a/mysql-test/t/set_statement.test
> +++ b/mysql-test/t/set_statement.test
> @@ -661,10 +610,92 @@ SELECT @@sql_mode;
>  --echo ''
>  SET STATEMENT sql_mode='ansi' FOR PREPARE stmt FROM 'SELECT "t1".* FROM t1';
>  execute stmt;
> +ALTER TABLE t1 ADD COLUMN v3 int;
> +# repreparation with other mode cause an error
> +--error ER_PARSE_ERROR
> +execute stmt;
> +ALTER TABLE t1 drop COLUMN v3;
>  deallocate prepare stmt;
>  --echo ''
>  --echo '# Post-STATEMENT
>  SELECT @@sql_mode;
> +--echo check the same behaviour in normal set
> +SET sql_mode='ansi';
> +PREPARE stmt FROM 'SELECT "t1".* FROM t1';
> +SET sql_mode=default;
> +execute stmt;
> +ALTER TABLE t1 ADD COLUMN v3 int;
> +# repreparation with other mode cause an error
> +--error ER_PARSE_ERROR
> +execute stmt;
> +ALTER TABLE t1 drop COLUMN v3;
> +deallocate prepare stmt;
> +# the above test about SP
> +SELECT @@sql_mode;
> +SET sql_mode='ansi';
> +SELECT @@sql_mode;
> +DELIMITER |;
> +              CREATE PROCEDURE p6() BEGIN
> +              SELECT @@sql_mode;
> +              SELECT "t1".* FROM t1;
> +              END|
> +DELIMITER ;|
> +SET sql_mode=default;
> +call p6;
> +ALTER TABLE t1 ADD COLUMN v3 int;
> +--echo # no reparsing for now

You can still force re-parsing by somehow flushing the
SP cache. E.g. you can start a new connection and run the SP there, try
that, please.

> +call p6;
> +ALTER TABLE t1 drop COLUMN v3;
> +drop procedure p6;
> +
> +
> +SELECT @@sql_mode;
> +DELIMITER |;
> +--echo # SET and the statement parsed as one unit before the SET takes effect
> +--error ER_PARSE_ERROR
> +SET STATEMENT sql_mode='ansi' FOR
> +              CREATE PROCEDURE p6() BEGIN
> +              SELECT @@sql_mode;
> +              SELECT "t1".* FROM t1;
> +              END|
> +DELIMITER ;|
> +#call p1;
> +#ALTER TABLE t1 ADD COLUMN v3 int;
> +#--echo # no reparsing for now
> +#call p1;
> +#ALTER TABLE t1 drop COLUMN v3;
> +#drop procedure p1;
> +
> +
> +# the above test about compaund statement

compOund, not compAund

> +SELECT @@sql_mode;
> +SET sql_mode='ansi';
> +SELECT @@sql_mode;
> +DELIMITER |;
> +BEGIN NOT ATOMIC
> +              SELECT @@sql_mode;
> +              SELECT "t1".* FROM t1;
> +END|
> +DELIMITER ;|
> +SET sql_mode=default;
> +
> +
> +SELECT @@sql_mode;
> +DELIMITER |;
> +--echo # SET and the statement parsed as one unit before the SET takes effect
> +--error ER_PARSE_ERROR
> +SET STATEMENT sql_mode='ansi' FOR
> +BEGIN NOT ATOMIC
> +              SELECT @@sql_mode;
> +              SELECT "t1".* FROM t1;
> +END|
> +SET STATEMENT sql_mode='ansi' FOR
> +BEGIN NOT ATOMIC
> +              SELECT @@sql_mode;
> +              SELECT * FROM t1;
> +              SELECT @@sql_mode;
> +END|
> +DELIMITER ;|
>  --echo ''
>  --echo ''
>  --echo '#------------------Test 17-----------------------#'
> diff --git a/sql/set_var.cc b/sql/set_var.cc
> index 20e3040..1dad360 100644
> --- a/sql/set_var.cc
> +++ b/sql/set_var.cc
> @@ -687,7 +688,7 @@ int sql_set_variables(THD *thd, List<set_var_base> *var_list, bool free)
>      if ((error= var->check(thd)))
>        goto err;
>    }
> -  if (!(error= MY_TEST(thd->is_error())))
> +  if (was_error || !(error= MY_TEST(thd->is_error())))

ok, this is that bug with restoring values after an error...

>    {
>      it.rewind();
>      while ((var= it++))
> diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt
> index 4072af4..e3f0de7 100644
> --- a/sql/share/errmsg-utf8.txt
> +++ b/sql/share/errmsg-utf8.txt
> @@ -7110,5 +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"
> +ER_SUBQUERIES_NOT_SUPPORTED

Here use SQLSTATE 42000

> +        eng "%s does not support subqueries or stored functions."
> diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
> index eff0e08..0fa3b15 100644
> --- a/sql/sql_parse.cc
> +++ b/sql/sql_parse.cc
> @@ -2648,6 +2648,11 @@ static bool do_execute_sp(THD *thd, sp_head *sp)
>      {
>        DBUG_ASSERT(var->is_system());
>        set_var *o= NULL, *v= (set_var*)var;
> +      if (v->value->walk(&Item::is_sp_processor, FALSE, NULL))
> +      {
> +        my_error(ER_SUBQUERIES_NOT_SUPPORTED, MYF(0), "SET STATEMENT");
> +        goto error;
> +      }

couldn't you rather check lex->table_or_sp_used() in the parser
(like events or KILL are doing) instead of walking the item tree?

>        if (v->var->is_default())
>            o= new set_var(v->type, v->var, &v->base, NULL);
>        else
> @@ -2727,6 +2732,11 @@ static bool do_execute_sp(THD *thd, sp_head *sp)
>          my_error(ER_WRONG_ARGUMENTS, MYF(0), "SET");
>        goto error;
>      }
> +    if (lex->sql_command == SQLCOM_COMPOUND)
> +    {
> +      /* mode might be changed by SET STATEMENT */
> +      lex->sphead->m_sql_mode= thd->variables.sql_mode;
> +    }

In fact, it might be that you don't need that and you can remove my fix for
MDEV-6609 and simply put this assignment into 'case SQLCOM_COMPOUND:'

>    }
>  
>    /*

Regards,
Sergei


Follow ups

References